Universal Speed Hack

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

이 스크립트를 설치하려면 Tampermonkey, Greasemonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

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

이 스크립트를 설치하려면 Tampermonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Userscripts와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 유저 스크립트 관리자 확장 프로그램이 필요합니다.

(이미 유저 스크립트 관리자가 설치되어 있습니다. 설치를 진행합니다!)

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

(이미 유저 스타일 관리자가 설치되어 있습니다. 설치를 진행합니다!)

// ==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();
    }
})();