Hammer Senpa.io Mod - UI Tweaks & Enhancements v2.2

UI Enhancements for Senpa.io: Draggable UI, Optimization, FX, Blur, Freeze, and Help Button

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

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

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Hammer Senpa.io Mod - UI Tweaks & Enhancements v2.2
// @namespace    http://tampermonkey.net/
// @version      2.2
// @description  UI Enhancements for Senpa.io: Draggable UI, Optimization, FX, Blur, Freeze, and Help Button
// @author       Hammer
// @match        https://senpa.io/*
// @grant        GM_addStyle
// ==/UserScript==

(function () {
    'use strict';

    // Global variables
    let optimizationEnabled = true;
    let fxOn = true;
    let isFrozen = false;
    let isBlurred = false;
    let isDragging = false;
    let offsetX, offsetY;

    // Default position (bottom-right corner)
    const defaultPosition = { top: 'auto', left: 'auto', bottom: '20px', right: '20px' };

    // Create the small GUI container (button to show/hide the menu)
    const smallGui = document.createElement('div');
    smallGui.id = 'small-gui';
    Object.assign(smallGui.style, {
        position: 'fixed',
        top: '50%',
        left: '50%',
        transform: 'translate(-50%, -50%)',
        width: '70px',
        height: '50px',
        backgroundColor: 'rgba(0, 0, 0, 0.7)',
        color: 'white',
        textAlign: 'center',
        fontSize: '14px',
        borderRadius: '5px',
        cursor: 'pointer',
        zIndex: '9999',
        border: '2px solid red'
    });
    smallGui.innerText = 'Mods';
    document.body.appendChild(smallGui);

    // Create the GUI menu (hidden by default)
    const guiContainer = document.createElement('div');
    guiContainer.id = 'gui-container';
    Object.assign(guiContainer.style, {
        position: 'fixed',
        top: '60%',
        left: '50%',
        transform: 'translateX(-50%)',
        width: '250px',
        backgroundColor: 'rgba(0, 0, 0, 0.8)',
        color: 'white',
        padding: '20px',
        borderRadius: '10px',
        zIndex: '9999',
        display: 'none',
        fontFamily: 'Arial, sans-serif',
        border: '2px solid red'
    });

    // Create the close button for the menu
    const closeButton = document.createElement('button');
    closeButton.innerText = 'X';
    Object.assign(closeButton.style, {
        backgroundColor: '#dc3545',
        color: 'white',
        border: 'none',
        padding: '5px',
        borderRadius: '50%',
        cursor: 'pointer',
        position: 'absolute',
        top: '10px',
        right: '10px'
    });
    closeButton.addEventListener('click', () => {
        guiContainer.style.display = 'none';
    });

    // Create the "made by hammer" text
    const hammerText = document.createElement('div');
    hammerText.innerText = 'made by hammer <3';
    Object.assign(hammerText.style, {
        color: '#fff',
        fontSize: '14px',
        textAlign: 'center',
        marginTop: '20px',
        display: 'none'
    });

    // Function to create toggle buttons
    function createToggleButton(textOn, textOff, initialState, callback) {
        const btn = document.createElement('button');
        btn.innerText = initialState ? textOff : textOn;
        btn.style.backgroundColor = initialState ? '#28a745' : '#dc3545';
        btn.style.color = 'white';
        btn.style.border = 'none';
        btn.style.padding = '10px';
        btn.style.borderRadius = '5px';
        btn.style.cursor = 'pointer';
        btn.style.marginBottom = '10px';
        btn.addEventListener('click', () => {
            const newState = callback();
            btn.innerText = newState ? textOff : textOn;
            btn.style.backgroundColor = newState ? '#28a745' : '#dc3545';
        });
        return btn;
    }

    // Append elements to the GUI container
    guiContainer.appendChild(closeButton);
    guiContainer.appendChild(createToggleButton('Enable FPS Optimization', 'Disable FPS Optimization', optimizationEnabled, () => {
        optimizationEnabled = !optimizationEnabled;
        optimizationEnabled ? enableOptimization() : disableOptimization();
        return optimizationEnabled;
    }));
    guiContainer.appendChild(createToggleButton('Enable FX', 'Disable FX', fxOn, () => {
        fxOn = !fxOn;
        applyVisualEffects();
        return fxOn;
    }));
    guiContainer.appendChild(createToggleButton('Freeze on Death', 'Unfreeze on Death', isFrozen, () => {
        isFrozen = !isFrozen;
        return isFrozen;
    }));
    guiContainer.appendChild(createToggleButton('Enable Background Blur', 'Disable Background Blur', isBlurred, () => {
        isBlurred = !isBlurred;
        const canvas = document.querySelector('canvas');
        if (canvas) {
            canvas.style.filter = isBlurred ? 'blur(3px)' : 'none';
        }
        document.body.style.backdropFilter = isBlurred ? 'blur(2px)' : 'none';
        return isBlurred;
    }));
    guiContainer.appendChild(hammerText);
    document.body.appendChild(guiContainer);

    // Event to toggle the menu visibility
    smallGui.addEventListener('click', () => {
        const isHidden = guiContainer.style.display === 'none';
        guiContainer.style.display = isHidden ? 'block' : 'none';
        hammerText.style.display = isHidden ? 'block' : 'none';
    });

    // Draggable feature for the small GUI
    smallGui.addEventListener('mousedown', (e) => {
        isDragging = true;
        offsetX = e.clientX - parseInt(window.getComputedStyle(smallGui).left);
        offsetY = e.clientY - parseInt(window.getComputedStyle(smallGui).top);
        smallGui.style.cursor = 'grabbing';
    });

    document.addEventListener('mousemove', (e) => {
        if (isDragging) {
            smallGui.style.left = `${e.clientX - offsetX}px`;
            smallGui.style.top = `${e.clientY - offsetY}px`;
        }
    });

    document.addEventListener('mouseup', () => {
        isDragging = false;
        smallGui.style.cursor = 'grab';
        savePosition();
    });

    // Save position of the small GUI box
    function savePosition() {
        localStorage.setItem('gui-position', JSON.stringify({
            left: smallGui.style.left,
            top: smallGui.style.top
        }));
    }

    // Restore position from localStorage or set default
    function restorePosition() {
        const position = JSON.parse(localStorage.getItem('gui-position'));
        if (position) {
            smallGui.style.left = position.left;
            smallGui.style.top = position.top;
        } else {
            smallGui.style.top = defaultPosition.top;
            smallGui.style.left = defaultPosition.left;
            smallGui.style.bottom = defaultPosition.bottom;
            smallGui.style.right = defaultPosition.right;
        }
    }

    // Apply visual effects like brightness, contrast, etc.
    function applyVisualEffects() {
        const canvas = document.querySelector('canvas');
        if (canvas) {
            canvas.style.filter = fxOn ? 'brightness(1.1) contrast(1.2) saturate(1.1)' : 'none';
        }
    }

    // Enable FPS optimization
    function enableOptimization() {
        document.body.style.backgroundImage = 'none';
        document.querySelectorAll('img').forEach(img => img.src = '');
        const style = document.createElement('style');
        style.innerHTML = `
            * {
                animation: none !important;
                transition: none !important;
                box-shadow: none !important;
            }
            canvas {
                image-rendering: optimizeSpeed;
                will-change: transform;
            }
            body, html {
                background: #000 !important;
                overflow: hidden;
                margin: 0;
                padding: 0;
            }
        `;
        document.head.appendChild(style);
        document.querySelectorAll('audio').forEach(audio => audio.pause());
        document.querySelectorAll('.ad, .sidebar, .popup').forEach(ad => ad.remove());
    }

    // Disable FPS optimization
    function disableOptimization() {
        const style = document.createElement('style');
        style.innerHTML = `
            * {
                animation: initial !important;
                transition: initial !important;
            }
        `;
        document.head.appendChild(style);
    }

    // Freeze player on death (optional)
    function freezeOnDeath() {
        if (!isFrozen) return;
        const player = document.querySelector('.player');
        if (!player) return;

        isFrozen = true;
        const preventMovement = e => { e.preventDefault(); e.stopPropagation(); };

        document.addEventListener('keydown', preventMovement);
        document.addEventListener('mousemove', preventMovement);
        document.addEventListener('mousedown', preventMovement);

        setTimeout(() => {
            isFrozen = false;
            document.removeEventListener('keydown', preventMovement);
            document.removeEventListener('mousemove', preventMovement);
            document.removeEventListener('mousedown', preventMovement);
        }, 3000);
    }

    // Observer to reset position after death or when returning to the main menu
    const observer = new MutationObserver(() => {
        const middleAd = document.querySelector('.middle, .middle-panel, .ad-middle');
        if (middleAd) {
            middleAd.remove();
        }

        const inGame = document.querySelector('.player');
        if (inGame) {
            restorePosition();
        }
    });

    observer.observe(document.body, { childList: true, subtree: true });

    // Check for death/game start and adjust UI accordingly
    setInterval(() => {
        const deathState = document.querySelector('.dead');
        if (deathState && isFrozen) {
            freezeOnDeath();
        }
    }, 1000);

    // Apply optimization and visual effects on load
    if (optimizationEnabled) enableOptimization();
    if (fxOn) applyVisualEffects();
})();