Evades.io FPS Cap Controller

Controls FPS and lessens Delay

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey, Greasemonkey alebo Violentmonkey.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie, ako napríklad Tampermonkey.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey, % alebo Violentmonkey.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey alebo Userscripts.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie, ako napríklad Tampermonkey.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie správcu používateľských skriptov.

(Už mám správcu používateľských skriptov, nechajte ma ho nainštalovať!)

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

(Už mám správcu používateľských štýlov, nechajte ma ho nainštalovať!)

// ==UserScript==
// @name         Evades.io FPS Cap Controller
// @namespace    http://tampermonkey.net/
// @version      1.0
// @description  Controls FPS and lessens Delay
// @author       JimmyJimmy
// @match        *://*.evades.io/*
// @match        *://evades.io/*
// @license      MIT
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    // Configuration
    const DEFAULT_FPS = 60;  // Default FPS cap
    const FPS_PRESETS = [30, 60, 120, 144, 240, 0]; // 0 means uncapped

    // Wait for game to load
    const checkGameLoaded = setInterval(function() {
        if (typeof window.requestAnimationFrame !== 'undefined') {
            clearInterval(checkGameLoaded);
            initFPSController();
        }
    }, 1000);

    function initFPSController() {
        // Variables to control FPS
        let targetFPS = DEFAULT_FPS;
        let fpsCapEnabled = true;
        let lastFrameTime = 0;
        let frameDelay = 1000 / targetFPS;

        // Store the original requestAnimationFrame
        const originalRAF = window.requestAnimationFrame;

        // Create UI for FPS control
        createFPSControlUI();

        // Override requestAnimationFrame
        window.requestAnimationFrame = function(callback) {
            if (!fpsCapEnabled || targetFPS === 0) {
                // If cap is disabled or set to 0 (uncapped), use original RAF
                return originalRAF(callback);
            }

            const currentTime = performance.now();
            const timeUntilNextFrame = Math.max(0, frameDelay - (currentTime - lastFrameTime));

            return setTimeout(function() {
                lastFrameTime = performance.now();
                callback(lastFrameTime);
            }, timeUntilNextFrame);
        };

        // Functions to update FPS settings
        function setFPS(fps) {
            targetFPS = fps;
            frameDelay = targetFPS > 0 ? 1000 / targetFPS : 0;
            updateFPSDisplay();

            // Save to localStorage
            localStorage.setItem('evades_custom_fps', fps);
        }

        function toggleFPSCap() {
            fpsCapEnabled = !fpsCapEnabled;
            updateFPSDisplay();

            // Save to localStorage
            localStorage.setItem('evades_fps_cap_enabled', fpsCapEnabled ? '1' : '0');
        }

        // Load saved settings
        const savedFPS = localStorage.getItem('evades_custom_fps');
        const savedCapEnabled = localStorage.getItem('evades_fps_cap_enabled');

        if (savedFPS) setFPS(parseInt(savedFPS));
        if (savedCapEnabled) fpsCapEnabled = savedCapEnabled === '1';

        // Create UI elements
        function createFPSControlUI() {
            const controlPanel = document.createElement('div');
            controlPanel.id = 'fps-control-panel';
            controlPanel.style.cssText = `
                position: fixed;
                top: 10px;
                right: 10px;
                background-color: rgba(0, 0, 0, 0.7);
                color: white;
                padding: 10px;
                border-radius: 5px;
                z-index: 10000;
                font-family: Arial, sans-serif;
                user-select: none;
                display: flex;
                flex-direction: column;
                gap: 5px;
            `;

            const fpsDisplay = document.createElement('div');
            fpsDisplay.id = 'fps-display';
            controlPanel.appendChild(fpsDisplay);

            const toggleButton = document.createElement('button');
            toggleButton.textContent = 'Toggle FPS Cap';
            toggleButton.onclick = toggleFPSCap;
            toggleButton.style.cssText = `
                padding: 5px;
                margin-top: 5px;
                cursor: pointer;
            `;
            controlPanel.appendChild(toggleButton);

            const customFpsInput = document.createElement('input');
            customFpsInput.type = 'number';
            customFpsInput.min = '1';
            customFpsInput.placeholder = 'Custom FPS';
            customFpsInput.style.cssText = `
                width: 100%;
                padding: 5px;
                margin-top: 5px;
            `;
            customFpsInput.onchange = function() {
                const customFps = parseInt(this.value);
                if (customFps > 0) setFPS(customFps);
            };
            controlPanel.appendChild(customFpsInput);

            const presetContainer = document.createElement('div');
            presetContainer.style.cssText = `
                display: flex;
                flex-wrap: wrap;
                gap: 5px;
                margin-top: 5px;
            `;

            FPS_PRESETS.forEach(fps => {
                const presetButton = document.createElement('button');
                presetButton.textContent = fps === 0 ? 'Uncap' : fps + ' FPS';
                presetButton.onclick = function() { setFPS(fps); };
                presetButton.style.cssText = `
                    flex: 1;
                    min-width: 60px;
                    padding: 3px;
                    cursor: pointer;
                `;
                presetContainer.appendChild(presetButton);
            });

            controlPanel.appendChild(presetContainer);

            // Add minimize button
            const minimizeBtn = document.createElement('button');
            minimizeBtn.textContent = '−';
            minimizeBtn.style.cssText = `
                position: absolute;
                top: 5px;
                right: 5px;
                width: 20px;
                height: 20px;
                padding: 0;
                display: flex;
                align-items: center;
                justify-content: center;
                cursor: pointer;
                background: none;
                border: none;
                color: white;
                font-size: 16px;
            `;

            let minimized = false;
            const contentElements = [fpsDisplay, toggleButton, customFpsInput, presetContainer];

            minimizeBtn.onclick = function() {
                minimized = !minimized;
                minimizeBtn.textContent = minimized ? '+' : '−';

                contentElements.forEach(el => {
                    el.style.display = minimized ? 'none' : '';
                });

                if (minimized) {
                    controlPanel.style.padding = '5px 25px 5px 10px';
                } else {
                    controlPanel.style.padding = '10px';
                }
            };

            controlPanel.appendChild(minimizeBtn);
            document.body.appendChild(controlPanel);

            // Initial update
            updateFPSDisplay();
        }

        function updateFPSDisplay() {
            const display = document.getElementById('fps-display');
            if (display) {
                display.textContent = `FPS Cap: ${fpsCapEnabled ? (targetFPS === 0 ? 'Uncapped' : targetFPS) : 'Disabled'}`;
                display.style.color = fpsCapEnabled ? '#8ff' : '#f88';
            }
        }

        // Add accurate actual FPS counter using game loop detection
        let frameTimestamps = [];
        let actualFps = 0;

        // Create FPS display element
        const fpsCounter = document.createElement('div');
        fpsCounter.id = 'actual-fps-display';
        fpsCounter.style.cssText = `
            position: fixed;
            top: 0px;
            left: 0px;
            background-color: rgba(0, 0, 0, 0.7);
            color: white;
            padding: 0px 0px;
            border-radius: 0px;
            z-index: 10000;
            font-family: Arial, sans-serif;
        `;
        fpsCounter.textContent = `Actual FPS: 0`;
        document.body.appendChild(fpsCounter);

        // Hook into the game's rendering cycle
        const originalDate = Date.now;
        const originalPerformanceNow = performance.now;

        // Create a more accurate frame counter by intercepting game loop timing functions
        function monitorGameFrames() {
            // Track canvas drawing operations
            const originalGetContext = HTMLCanvasElement.prototype.getContext;
            HTMLCanvasElement.prototype.getContext = function() {
                const context = originalGetContext.apply(this, arguments);
                if (arguments[0] === '2d' && context) {
                    const originalDrawImage = context.drawImage;
                    context.drawImage = function() {
                        recordFrame();
                        return originalDrawImage.apply(this, arguments);
                    };

                    const originalFillRect = context.fillRect;
                    context.fillRect = function() {
                        recordFrame();
                        return originalFillRect.apply(this, arguments);
                    };

                    const originalClearRect = context.clearRect;
                    context.clearRect = function() {
                        recordFrame();
                        return originalClearRect.apply(this, arguments);
                    };
                }
                return context;
            };

            // Monitor WebGL rendering too
            const originalRenderingContextClear = WebGLRenderingContext.prototype.clear;
            WebGLRenderingContext.prototype.clear = function() {
                recordFrame();
                return originalRenderingContextClear.apply(this, arguments);
            };

            if (typeof WebGL2RenderingContext !== 'undefined') {
                const originalWebGL2ContextClear = WebGL2RenderingContext.prototype.clear;
                WebGL2RenderingContext.prototype.clear = function() {
                    recordFrame();
                    return originalWebGL2ContextClear.apply(this, arguments);
                };
            }
        }

        // Record frame and calculate FPS
        function recordFrame() {
            const now = originalPerformanceNow.call(performance);
            frameTimestamps.push(now);

            // Keep only frames from the last second
            while (frameTimestamps.length > 0 && now - frameTimestamps[0] > 1000) {
                frameTimestamps.shift();
            }

            // Calculate FPS based on number of frames in the last second
            actualFps = frameTimestamps.length;

            // Update display at most 10 times per second to avoid performance issues
            if (Math.floor(now / 100) !== Math.floor((now - 16) / 100)) {
                fpsCounter.textContent = `Actual FPS: ${actualFps}`;
            }
        }

        // Start monitoring
        monitorGameFrames();

        console.log('[Evades.io FPS Cap Controller] Initialized');
    }
})();