Universal Speed Hack

A powerful Universal Speed Hack supporting setTimeout,setInterval,requestAnimationFrame,Date.now(), and performance.now()

Terá de instalar uma extensão como Tampermonkey, Greasemonkey ou Violentmonkey para instalar este script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

Terá de instalar uma extensão como Tampermonkey ou Violentmonkey para instalar este script.

Terá de instalar uma extensão como Tampermonkey ou Userscripts para instalar este script.

Terá de instalar uma extensão como Tampermonkey para instalar este script.

Terá de instalar uma extensão de gestão de scripts de utilizador para instalar este script.

(Já tenho um gestor de scripts de utilizador, deixe-me instalá-lo!)

Terá de instalar uma extensão como Stylus para instalar este estilo.

Terá de instalar uma extensão como Stylus para instalar este estilo.

Terá de instalar uma extensão como Stylus para instalar este estilo.

Terá de instalar uma extensão de gestão de estilos de utilizador para instalar este estilo.

Terá de instalar uma extensão de gestão de estilos de utilizador para instalar este estilo.

Terá de instalar uma extensão de gestão de estilos de utilizador para instalar este estilo.

(Já tenho um gestor de estilos de utilizador, deixe-me instalá-lo!)

// ==UserScript==
// @name         Universal Speed Hack
// @namespace    http://tampermonkey.net/
// @version      1
// @description  A powerful Universal Speed Hack supporting setTimeout,setInterval,requestAnimationFrame,Date.now(), and performance.now()
// @author       OpenSource (https://www.youtube.com/@OpenSource-w4j)
// @match        *://*/*
// @run-at       document-start
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    function enableSpeedHackEngine() {
        if (window.__universal_sh_engine_active) return;
        window.__universal_sh_engine_active = true;

        let globalSpeed = 1.0;
        let speedhackActive = false;

        window.__sh_setSpeed = (val) => { globalSpeed = val; };
        window.__sh_setActive = (act) => { speedhackActive = act; };

        const realPerfNow = performance.now.bind(performance);
        const origRAF = window.requestAnimationFrame.bind(window);

        let lastTime = realPerfNow();
        let simTime = lastTime;

        performance.now = function() {
            if (!speedhackActive || globalSpeed === 1.0) return realPerfNow();
            const now = realPerfNow();
            simTime += (now - lastTime) * globalSpeed;
            lastTime = now;
            return simTime;
        };

        window.requestAnimationFrame = function(cb) {
            return origRAF(function(timestamp) {
                lastTime = timestamp;
                if (!speedhackActive || globalSpeed === 1.0) return cb(timestamp);
                return cb(simTime);
            });
        };

        const origSetInterval = window.setInterval;
        const origSetTimeout = window.setTimeout;

        window.setInterval = function(callback, delay, ...args) {
            if (speedhackActive && globalSpeed > 0) {
                delay = delay / globalSpeed;
            }
            return origSetInterval(callback, delay, ...args);
        };

        window.setTimeout = function(callback, delay, ...args) {
            if (speedhackActive && globalSpeed > 0) {
                delay = delay / globalSpeed;
            }
            return origSetTimeout(callback, delay, ...args);
        };

        const realDateNow = Date.now.bind(Date);
        let simDateNow = realDateNow();
        let lastDateCheck = realDateNow();

        Date.now = function() {
            if (!speedhackActive || globalSpeed === 1.0) return realDateNow();
            const now = realDateNow();
            simDateNow += (now - lastDateCheck) * globalSpeed;
            lastDateCheck = now;
            return Math.floor(simDateNow);
        };
    }

    enableSpeedHackEngine();

    function initWhenCanvasReady() {
        if (document.getElementById('universal-speed-hack-host')) return;

        const checkInterval = setInterval(() => {
            const gameCanvas = document.querySelector('canvas');
            if (gameCanvas && (gameCanvas.width > 100 || gameCanvas.height > 100 || gameCanvas.style.display !== 'none')) {
                clearInterval(checkInterval);
                createGUI();
            }
        }, 300);
    }

    function createGUI() {
        if (document.getElementById('universal-speed-hack-host')) return;

        let globalSpeed = 1.0;
        let speedhackActive = false;
        let toggleKey = 'h';

        const host = document.createElement('div');
        host.id = 'universal-speed-hack-host';
        host.style.cssText = 'position: fixed; top: 0; left: 0; z-index: 2147483647; pointer-events: none;';
        const shadow = host.attachShadow({ mode: 'open' });

        const container = document.createElement('div');
        container.id = 'universal-speed-hack-gui';
        container.style.cssText = `
            position: fixed;
            top: 15px;
            right: 15px;
            pointer-events: auto;
            background: #141414;
            color: #e0e0e0;
            padding: 12px;
            border-radius: 8px;
            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
            font-size: 12px;
            box-shadow: 0 8px 24px rgba(0,0,0,0.6);
            user-select: none;
            display: flex;
            flex-direction: column;
            gap: 10px;
            width: 200px;
            border: 1px solid #2a2a2a;
        `;
        shadow.appendChild(container);

        const header = document.createElement('div');
        header.style.cssText = 'font-weight: 600; display: flex; justify-content: space-between; align-items: center; border-bottom: 1px solid #262626; padding-bottom: 6px; cursor: move; color: #fff; letter-spacing: 0.3px;';
        header.innerHTML = '<span>Universal Speed Hack</span> <span style="cursor:pointer; color:#777; font-size:14px;" id="sh-min">−</span>';
        container.appendChild(header);

        const body = document.createElement('div');
        body.id = 'sh-content';
        body.style.cssText = 'display: flex; flex-direction: column; gap: 8px;';
        container.appendChild(body);

        const toggleBtn = document.createElement('button');
        toggleBtn.innerText = 'OFF';
        toggleBtn.style.cssText = `
            background: #2a2a2a;
            color: #ef4444;
            border: 1px solid #3f3f46;
            padding: 6px;
            border-radius: 5px;
            cursor: pointer;
            font-weight: 700;
            font-size: 11px;
            transition: all 0.2s;
        `;

        function updateToggleUI() {
            toggleBtn.style.background = speedhackActive ? '#166534' : '#2a2a2a';
            toggleBtn.style.color = speedhackActive ? '#4ade80' : '#ef4444';
            toggleBtn.style.borderColor = speedhackActive ? '#22c55e' : '#3f3f46';
            toggleBtn.innerText = speedhackActive ? 'ACTIVE' : 'OFF';
            if (window.__sh_setActive) window.__sh_setActive(speedhackActive);
        }

        toggleBtn.onclick = () => {
            speedhackActive = !speedhackActive;
            updateToggleUI();
        };
        body.appendChild(toggleBtn);

        const controlWrap = document.createElement('div');
        controlWrap.style.cssText = 'display: flex; flex-direction: column; gap: 6px; background: #1a1a1a; padding: 8px; border-radius: 6px; border: 1px solid #222;';

        const labelRow = document.createElement('div');
        labelRow.style.cssText = 'display: flex; justify-content: space-between; color: #a1a1aa; font-size: 11px; align-items: center;';
        labelRow.innerHTML = `<span>Speed</span>`;

        const inputControls = document.createElement('div');
        inputControls.style.cssText = 'display: flex; align-items: center; gap: 4px;';

        const minusBtn = document.createElement('button');
        minusBtn.innerText = '-';
        minusBtn.style.cssText = 'background: #222; color: #38bdf8; border: 1px solid #333; width: 22px; height: 22px; border-radius: 3px; cursor: pointer; font-weight: bold; font-size: 12px;';

        const numberInput = document.createElement('input');
        numberInput.type = 'text';
        numberInput.value = '1';
        numberInput.style.cssText = `
            width: 40px;
            background: #111;
            color: #38bdf8;
            border: 1px solid #333;
            text-align: center;
            font-family: monospace;
            font-size: 11px;
            border-radius: 4px;
            height: 20px;
            outline: none;
        `;

        const plusBtn = document.createElement('button');
        plusBtn.innerText = '+';
        plusBtn.style.cssText = 'background: #222; color: #38bdf8; border: 1px solid #333; width: 22px; height: 22px; border-radius: 3px; cursor: pointer; font-weight: bold; font-size: 12px;';

        function applySpeed(val) {
            let num = parseFloat(val);
            if (isNaN(num) || num < 1) num = 1;
            if (num > 9999) num = 9999;
            globalSpeed = num;
            numberInput.value = num;
            sliderInput.value = num > sliderInput.max ? sliderInput.max : num;
            if (window.__sh_setSpeed) window.__sh_setSpeed(globalSpeed);
        }

        // CONTINUOUS HOLD-TO-INCREMENT LOGIC (PC & MOBILE TOUCH)
        let holdInterval = null;
        let holdTimeout = null;

        function startHold(stepValue) {
            stopHold();
            applySpeed(globalSpeed + stepValue);

            holdTimeout = setTimeout(() => {
                holdInterval = setInterval(() => {
                    applySpeed(globalSpeed + stepValue);
                }, 75);
            }, 400);
        }

        function stopHold() {
            if (holdTimeout) { clearTimeout(holdTimeout); holdTimeout = null; }
            if (holdInterval) { clearInterval(holdInterval); holdInterval = null; }
        }

        minusBtn.addEventListener('mousedown', (e) => { e.preventDefault(); startHold(-1); });
        minusBtn.addEventListener('mouseup', stopHold);
        minusBtn.addEventListener('mouseleave', stopHold);
        minusBtn.addEventListener('touchstart', (e) => { e.preventDefault(); startHold(-1); }, {passive: false});
        minusBtn.addEventListener('touchend', stopHold);

        plusBtn.addEventListener('mousedown', (e) => { e.preventDefault(); startHold(1); });
        plusBtn.addEventListener('mouseup', stopHold);
        plusBtn.addEventListener('mouseleave', stopHold);
        plusBtn.addEventListener('touchstart', (e) => { e.preventDefault(); startHold(1); }, {passive: false});
        plusBtn.addEventListener('touchend', stopHold);

        numberInput.addEventListener('input', (e) => {
            let clean = e.target.value.replace(/[^0-9.]/g, '');
            if (clean !== '') applySpeed(clean);
        });

        numberInput.addEventListener('keydown', (e) => {
            e.stopPropagation();
            if (e.key === 'Enter') {
                e.preventDefault();
                numberInput.blur();
            }
        });

        inputControls.appendChild(minusBtn);
        inputControls.appendChild(numberInput);
        inputControls.appendChild(plusBtn);
        labelRow.appendChild(inputControls);
        controlWrap.appendChild(labelRow);

        const sliderInput = document.createElement('input');
        sliderInput.type = 'range';
        sliderInput.min = '1';
        sliderInput.max = '9999';
        sliderInput.step = '1';
        sliderInput.value = '1';
        sliderInput.style.cssText = 'width: 100%; cursor: pointer; accent-color: #38bdf8;';

        sliderInput.oninput = (e) => {
            applySpeed(e.target.value);
        };

        controlWrap.appendChild(sliderInput);
        body.appendChild(controlWrap);

        const footer = document.createElement('div');
        footer.style.cssText = 'font-size: 8px; color: #52525b; text-align: center; border-top: 1px solid #262626; padding-top: 4px;';
        footer.innerHTML = '<a href="https://www.youtube.com/@OpenSource-w4j" target="_blank" style="color: #38bdf8; text-decoration: none;">Made by OpenSource</a>';
        container.appendChild(footer);

        let minimized = false;
        header.querySelector('#sh-min').onclick = () => {
            minimized = !minimized;
            body.style.display = minimized ? 'none' : 'flex';
            header.querySelector('#sh-min').innerText = minimized ? '+' : '−';
        };

        window.addEventListener('keydown', (e) => {
            if (shadow.activeElement === numberInput) return;
            if (e.key.toLowerCase() === toggleKey) {
                container.style.display = container.style.display === 'none' ? 'flex' : 'none';
            }
        });

        // PC Drag-and-Drop
        let isDragging = false;
        let startX, startY, initialX, initialY;

        header.onmousedown = (e) => {
            if (e.target.id === 'sh-min') return;
            isDragging = true;
            startX = e.clientX;
            startY = e.clientY;
            initialX = container.offsetLeft;
            initialY = container.offsetTop;
            document.addEventListener('mousemove', onMouseMove);
            document.addEventListener('mouseup', onMouseUp);
        };

        function onMouseMove(e) {
            if (!isDragging) return;
            container.style.left = (initialX + (e.clientX - startX)) + 'px';
            container.style.top = (initialY + (e.clientY - startY)) + 'px';
            container.style.right = 'auto';
        }

        function onMouseUp() {
            isDragging = false;
            document.removeEventListener('mousemove', onMouseMove);
            document.removeEventListener('mouseup', onMouseUp);
        }

        // Mobile Touch Support for Dragging
        header.ontouchstart = (e) => {
            if (e.target.id === 'sh-min') return;
            const touch = e.touches[0];
            isDragging = true;
            startX = touch.clientX;
            startY = touch.clientY;
            initialX = container.offsetLeft;
            initialY = container.offsetTop;
            document.addEventListener('touchmove', onTouchMove);
            document.addEventListener('touchend', onTouchEnd);
        };

        function onTouchMove(e) {
            if (!isDragging) return;
            const touch = e.touches[0];
            container.style.left = (initialX + (touch.clientX - startX)) + 'px';
            container.style.top = (initialY + (touch.clientY - startY)) + 'px';
            container.style.right = 'auto';
        }

        function onTouchEnd() {
            isDragging = false;
            document.removeEventListener('touchmove', onTouchMove);
            document.removeEventListener('touchend', onTouchEnd);
        }

        if (document.body) {
            document.body.appendChild(host);
            showNotification(shadow);
        } else {
            window.addEventListener('DOMContentLoaded', () => {
                document.body.appendChild(host);
                showNotification(shadow);
            });
        }
    }

    function showNotification(shadowRoot) {
        const notif = document.createElement('div');
        notif.style.cssText = `
            position: fixed;
            bottom: 20px;
            left: 50%;
            transform: translateX(-50%);
            z-index: 2147483647;
            background: #18181b;
            color: #f4f4f5;
            padding: 8px 16px;
            border-radius: 6px;
            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
            font-size: 11px;
            box-shadow: 0 4px 12px rgba(0,0,0,0.5);
            border: 1px solid #27272a;
            transition: opacity 0.5s ease;
            opacity: 1;
            pointer-events: auto;
            letter-spacing: 0.3px;
        `;
        notif.innerHTML = '<a href="https://www.youtube.com/@OpenSource-w4j" target="_blank" style="color: #38bdf8; text-decoration: none;">Made by OpenSource</a>';
        shadowRoot.appendChild(notif);

        // Disappears automatically after 2 seconds
        setTimeout(() => {
            notif.style.opacity = '0';
            setTimeout(() => notif.remove(), 500);
        }, 2000);
    }

    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', initWhenCanvasReady);
    } else {
        initWhenCanvasReady();
    }
})();