FINAL: Polished minimalist controller with optimized spacing and dark glow.
目前為
// ==UserScript==
// @name Stake Speed Hack 4
// @namespace http://tampermonkey.net/
// @version 3.4
// @description FINAL: Polished minimalist controller with optimized spacing and dark glow.
// @author jayfantz
// @match *://*/*
// @grant none
// @run-at document-start
// ==/UserScript==
(function() {
'use strict';
// ----------------------------------------------------------------------
// CORE STATE AND CONSTANTS
// ----------------------------------------------------------------------
const C = {
deepNavy: '#0f212e',
darkPill: '#1f3341',
darkerButton: '#0c1a25',
midGray: '#55646e',
lightGray: '#909ba1',
actionGreen: '#107721',
// FINAL GLOW FIX: Dark, subtle glow color
shadow: '#263a46'
};
let speedMultiplier = 1.0;
const originalSetTimeout = window.setTimeout;
const originalSetInterval = window.setInterval;
const originalRequestAnimationFrame = window.requestAnimationFrame;
const nativeAddEventListener = document.addEventListener.bind(document);
// UI/Helper Variables
let controller;
let spdEl;
let brand;
const hooks = {
requestAnimationFrame:true, setTimeout:true, setInterval:true,
performanceNow:false, dateNow:false, css:true, gsap:null, pixi:null,
three:null, anime:null, velocity:null
};
// ======================================================================
// HOOKING AND LOGIC FUNCTIONS
// ======================================================================
function applyImmediateHooks() {
if (hooks.setTimeout) {
window.setTimeout = function (fn, t, ...a) {
return originalSetTimeout.call(window, fn, Math.max(0, (t ?? 0) / speedMultiplier), ...a);
};
} else if (window.setTimeout !== originalSetTimeout) {
window.setTimeout = originalSetTimeout;
}
if (hooks.setInterval) {
window.setInterval = function (fn, t, ...a) {
return originalSetInterval.call(window, fn, Math.max(0, (t ?? 0) / speedMultiplier), ...a);
};
} else if (window.setInterval !== originalSetInterval) {
window.setInterval = originalSetInterval;
}
if (hooks.requestAnimationFrame) {
window.requestAnimationFrame = function (cb) {
return originalRequestAnimationFrame.call(window, ts => cb(ts / speedMultiplier));
};
} else if (window.requestAnimationFrame !== originalRequestAnimationFrame) {
window.requestAnimationFrame = originalRequestAnimationFrame;
}
}
applyImmediateHooks();
// --- Speed Setter ---
function setSpeed(v) {
speedMultiplier = Math.max(0.05, v);
applyImmediateHooks();
const spdEl = document.getElementById('speedDisplay');
if (spdEl) {
spdEl.innerHTML = `
<span style="font-size: 1.5em; font-weight: 700; letter-spacing: 0.05em;">
${speedMultiplier.toFixed(2)}
</span>
<span style="margin-left: 4px; font-size: 1.3em; color: ${C.actionGreen}; font-weight: 800;">
x
</span>
`;
}
}
// --- Button Styling Function ---
function applyButtonStyles(btn) {
// Retaining the final known good manual shifts
let yShift = (btn.textContent.trim() === '▼') ? '2px' : '1px';
btn.style.cssText = `
padding: 4px;
color: ${C.actionGreen};
font-size: 28px;
font-weight: bold;
cursor: pointer;
transition: opacity 0.15s;
/* FINAL ALIGNMENT FIXES */
line-height: 1;
transform: translateY(${yShift});
font-family: Arial, sans-serif;
/* Removed circular styling */
background: none;
border: none;
min-width: 30px;
text-align: center;
`;
btn.addEventListener('mouseenter', () => { btn.style.opacity = '0.7'; });
btn.addEventListener('mouseleave', () => { btn.style.opacity = '1'; });
btn.addEventListener('mousedown', () => { btn.style.opacity = '0.5'; });
btn.addEventListener('mouseup', () => { btn.style.opacity = '0.7'; });
}
// --- UI Construction ---
function buildController() {
controller = document.createElement('div');
controller.id = 'speedController';
controller.style.cssText = `
position: fixed; top: 40px; left: 40px;
background: ${C.darkPill};
color: ${C.lightGray};
/* AESTHETIC FIXES */
border: 4px solid ${C.midGray};
box-shadow: 0 0 30px 8px ${C.shadow}, 0 0 10px 2px ${C.deepNavy} inset;
border-radius: 20px;
padding: 4px 8px;
padding-bottom: 50px; /* Space for the footer */
font-family: 'Inter', system-ui, -apple-system, Segoe UI, Arial, sans-serif;
font-size: 16px;
display: flex;
align-items: center; /* Vertical centering of the number/arrows */
gap: 4px; /* TIGHTEST HORIZONTAL GAP */
z-index: 2147483647;
user-select: none;
cursor: grab;
overflow: hidden;
`;
// Initialize display with integrated arrows (using SPANs)
controller.innerHTML = `
<span id="decreaseBtn" class="control-arrow">▼</span>
<span id="speedDisplay" style="min-width:105px; /* FIXED WIDTH FOR 10.00x */ text-align:center; display: flex; align-items: center; justify-content: center; color: ${C.lightGray};">
1.00<span style="margin-left: 14px;">x</span>
</span>
<span id="increaseBtn" class="control-arrow">▲</span>
<div id="footer-badge" style="
position: absolute; bottom: 0; left: 0; right: 0;
height: 48px; /* Increased height for logo spacing */
background: ${C.deepNavy};
border-top: 1px solid ${C.midGray};
display: flex;
align-items: center;
justify-content: center;
padding: 5px 0; /* Space around the logo */
">
</div>
`;
document.body.appendChild(controller);
// Branding Footer
const footer = controller.querySelector('#footer-badge');
brand = document.createElement('img');
brand.src = 'https://raw.githubusercontent.com/cutiejf/StakeWar/refs/heads/main/chad.png';
brand.style.cssText = `
width: 69px;
height: auto;
opacity: 0.9;
pointer-events: none;
filter: drop-shadow(0 0 4px ${C.actionGreen});
`;
footer.appendChild(brand);
// Event Listeners Setup
const decreaseBtn = document.getElementById('decreaseBtn');
const increaseBtn = document.getElementById('increaseBtn');
// Apply button styles
applyButtonStyles(decreaseBtn);
applyButtonStyles(increaseBtn);
// Click handlers
decreaseBtn.addEventListener('click', () => { setSpeed(speedMultiplier - 0.1); });
increaseBtn.addEventListener('click', () => { setSpeed(speedMultiplier + 0.1); });
// Draggable Logic
controller.addEventListener('mousedown', (e) => {
if (e.target.id === 'decreaseBtn' || e.target.id === 'increaseBtn' || e.target === footer) return;
let isDragging = true;
controller.style.cursor = 'grabbing';
let dx = e.clientX - controller.getBoundingClientRect().left;
let dy = e.clientY - controller.getBoundingClientRect().top;
const move = (ev) => {
if (!isDragging) return;
controller.style.left = ev.pageX - dx + 'px';
controller.style.top = ev.pageY - dy + 'px';
};
const up = () => {
isDragging = false;
controller.style.cursor = 'grab';
document.removeEventListener('mousemove', move);
document.removeEventListener('mouseup', up);
};
document.addEventListener('mousemove', move);
document.addEventListener('mouseup', up);
});
setSpeed(speedMultiplier); // Initial display update
}
// ----------------------------------------------------------------------
// MAIN EXECUTION FLOW
// ----------------------------------------------------------------------
document.addEventListener('DOMContentLoaded', buildController, { once: true });
})();