Blubbled's UI Mod v2

Adds some QoL features, such as always showing kill count, green health bar, etc

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         Blubbled's UI Mod v2
// @namespace    http://tampermonkey.net/
// @version      2
// @description  Adds some QoL features, such as always showing kill count, green health bar, etc
// @author       Blubbled
// @match        https://suroi.io/*
// @grant        none
// @license MIT
// ==/UserScript==



(function() {

    'use strict';

    function periodicallyShowKillCounter() {
        showKillCounter();
        setTimeout(periodicallyShowKillCounter, 100);
    }

    function showKillCounter() {
        var killCounter = document.getElementById('kill-counter');
        if (killCounter) {
            killCounter.style.display = 'flex';
            killCounter.style.alignItems = 'center';
            var skullIcon = killCounter.querySelector('img');
            if (skullIcon) {
                skullIcon.style.marginRight = '5px';
            }
            var counterText = killCounter.querySelector('.counter-text');
            if (counterText) {
                counterText.style.minWidth = '30px';
            }
        }
    }
    var actionTimer;
    var countdownElement;

    function startActionTimer() {
        var countdownValue = 4;
        countdownElement = document.createElement('div');
        countdownElement.id = 'action-countdown';
        countdownElement.textContent = countdownValue;
        countdownElement.style.position = 'fixed';
        countdownElement.style.top = '50%';
        countdownElement.style.left = '50%';
        countdownElement.style.transform = 'translate(-50%, -170%)';
        countdownElement.style.fontSize = '24px';
        countdownElement.style.fontWeight = 'bold';
        countdownElement.style.color = 'white';
        countdownElement.style.zIndex = '9999'; 
        document.body.appendChild(countdownElement);

        actionTimer = setInterval(function() {
            countdownValue -= 0.1;
            countdownElement.textContent = countdownValue.toFixed(1);
            if (countdownValue <= 0) {
                clearInterval(actionTimer);
                actionTimer = null;

                countdownElement.parentNode.removeChild(countdownElement);
            }
        }, 100);
    }




    //function handleMouseDown(event) {
    //    console.log('Mouse down event detected');
//
//        if (event.button === 0){
 //           var weaponSlot = document.getElementById('weapon-slot-4');
  //          if (weaponSlot.classList.contains('active')) {
   //             console.log('Starting action timer');
  //              startActionTimer();
   //         }
    //    }
   // }


   // function handleMouseUp(event) {
   //     console.log('Mouse up event detected');

    //    if (event.button === 0) {

    //        if (actionTimer) {
    //            console.log('Clearing action timer');
    //            clearInterval(actionTimer);
    //            actionTimer = null;

     //           if (countdownElement) {
     //               countdownElement.parentNode.removeChild(countdownElement);
     //               countdownElement = null;
     //           }
     //   }
  //  }

  //  window.addEventListener('mousedown', handleMouseDown);
    //window.addEventListener('mouseup', handleMouseUp);


    function addAdditionalUI() {
        var additionalText = document.createElement('h1');
        additionalText.textContent = "Technical UI pack by Blubbled ";
        var joinLink = document.createElement('a');
        joinLink.textContent = "[JOIN ZESK]";
        joinLink.href = "https://discord.gg/msNbP9Nt2r";
        joinLink.style.color = 'blue';
        joinLink.style.textDecoration = 'underline';
        joinLink.style.marginLeft = '5px';
        additionalText.appendChild(joinLink);
        additionalText.style.position = 'fixed';
        additionalText.style.top = '10px';
        additionalText.style.right = '10px';
        additionalText.style.color = '#ffffff';
        additionalText.style.zIndex = '9999';
        additionalText.style.display = 'none';
        document.body.appendChild(additionalText);

        var masterVolumeSlider = document.getElementById('slider-master-volume');
        var sfxVolumeSlider = document.getElementById('slider-sfx-volume');
        var musicVolumeSlider = document.getElementById('slider-music-volume');
        var uiScaleSlider = document.getElementById('slider-ui-scale');
        var minimapTransparencySlider = document.getElementById('slider-minimap-transparency');
        var bigMapTransparencySlider = document.getElementById('slider-big-map-transparency');

        if (masterVolumeSlider && sfxVolumeSlider && musicVolumeSlider && uiScaleSlider && minimapTransparencySlider && bigMapTransparencySlider) {
            masterVolumeSlider.step = 0.01;
            sfxVolumeSlider.step = 0.01;
            musicVolumeSlider.step = 0.01;
            uiScaleSlider.step = 0.01;
            minimapTransparencySlider.step = 0.01;
            bigMapTransparencySlider.step = 0.01;
        }
    }

    function replaceWithHeader() {
        var customHeader = document.createElement('h1');
        customHeader.textContent = "Technical UI pack by Blubbled ";
        var joinLink = document.createElement('a');
        joinLink.textContent = "[JOIN ZESK]";
        joinLink.href = "https://discord.gg/msNbP9Nt2r";
        joinLink.style.color = 'blue';
        joinLink.style.textDecoration = 'underline';
        joinLink.style.marginLeft = '5px';
        customHeader.appendChild(joinLink);
        customHeader.style.position = 'fixed';
        customHeader.style.top = '10px';
        customHeader.style.right = '10px';
        customHeader.style.color = '#ffffff';
        customHeader.style.zIndex = '9999';
        var elementToReplace = document.querySelector('a[href="./changelog/"][target="_blank"][rel="noopener noreferrer"]');
        if (elementToReplace) {
            elementToReplace.parentNode.replaceChild(customHeader, elementToReplace);
        }
    }






    var settingsTabsContainer = document.getElementById('settings-tabs-container');
    var modSettingsTabButton = document.createElement('button');
    modSettingsTabButton.className = 'tab';
    modSettingsTabButton.id = 'tab-mod-settings';
    modSettingsTabButton.innerHTML = '<i class="fa-solid fa-gear"></i>Mod Settings';
    settingsTabsContainer.querySelector('#settings-tab-bar').appendChild(modSettingsTabButton);

    var modSettingsTabContent = document.createElement('div');
    modSettingsTabContent.className = 'tab-content';
    modSettingsTabContent.id = 'tab-mod-settings-content';
    modSettingsTabContent.style.display = 'none';

    var modSettingsContent = document.createElement('div');




    modSettingsTabContent.appendChild(modSettingsContent);
    settingsTabsContainer.querySelector('#settings-tabs').appendChild(modSettingsTabContent);



//player info
    function togglePlayerInfo(enabled) {
        if (enabled) {
            var healthBarPercentageCopy = document.createElement('span');
            healthBarPercentageCopy.id = 'health-bar-percentage-copy';
            healthBarPercentageCopy.classList.add('unselectable');
            healthBarPercentageCopy.style.position = 'fixed';
            healthBarPercentageCopy.style.top = '50%';
            healthBarPercentageCopy.style.left = '46.2%';
            healthBarPercentageCopy.style.transform = 'translate(-50%, -50%)';
            healthBarPercentageCopy.style.fontSize = '20px';
            healthBarPercentageCopy.style.fontWeight = 'bold';

            function updateHealthBarPercentageCopy() {
                var healthBarPercentageValue = document.getElementById('health-bar-percentage').textContent;
                var healthBarColor = document.getElementById('health-bar').style.backgroundColor;

                healthBarPercentageCopy.textContent = healthBarPercentageValue + "➕";
                healthBarPercentageCopy.style.color = healthBarColor;
            }

            healthBarPercentageCopy.style.webkitTouchCallout = 'none'; /* iOS Safari */
            healthBarPercentageCopy.style.webkitUserSelect = 'none'; /* Safari */
            healthBarPercentageCopy.style.userSelect = 'none'; /* Standard syntax */

            updateHealthBarPercentageCopy();
            document.body.appendChild(healthBarPercentageCopy);

            var observer1 = new MutationObserver(updateHealthBarPercentageCopy);
            var targetNode1 = document.getElementById('health-bar-percentage');
            observer1.observe(targetNode1, { childList: true, subtree: true });

            var adrenalineBarPercentageCopy = document.createElement('span');
            adrenalineBarPercentageCopy.id = 'adrenaline-bar-percentage-copy';
            adrenalineBarPercentageCopy.classList.add('unselectable');
            adrenalineBarPercentageCopy.style.position = 'fixed';
            adrenalineBarPercentageCopy.style.top = '50%';
            adrenalineBarPercentageCopy.style.right = '46.2%';
            adrenalineBarPercentageCopy.style.transform = 'translate(50%, -50%)';
            adrenalineBarPercentageCopy.style.fontSize = '20px';
            adrenalineBarPercentageCopy.style.fontWeight = 'bold';

            function updateAdrenalineBarPercentageCopy() {
                var adrenalineBarPercentageValue = document.getElementById('adrenaline-bar-percentage').textContent;
                var adrenalineBarColor = document.getElementById('adrenaline-bar').style.backgroundColor;

                adrenalineBarPercentageCopy.textContent = adrenalineBarPercentageValue + "⚡";
                adrenalineBarPercentageCopy.style.color = adrenalineBarColor;
            }

            adrenalineBarPercentageCopy.style.webkitTouchCallout = 'none'; /* iOS Safari */
            adrenalineBarPercentageCopy.style.webkitUserSelect = 'none'; /* Safari */
            adrenalineBarPercentageCopy.style.userSelect = 'none'; /* Standard syntax */

            updateAdrenalineBarPercentageCopy();
            document.body.appendChild(adrenalineBarPercentageCopy);

            var observer2 = new MutationObserver(updateAdrenalineBarPercentageCopy);
            var targetNode2 = document.getElementById('adrenaline-bar-percentage');
            observer2.observe(targetNode2, { childList: true, subtree: true });
        } else {
          
            var healthBarPercentageCopy = document.getElementById('health-bar-percentage-copy');
            if (healthBarPercentageCopy) {
                healthBarPercentageCopy.parentNode.removeChild(healthBarPercentageCopy);
            }

            var adrenalineBarPercentageCopy = document.getElementById('adrenaline-bar-percentage-copy');
            if (adrenalineBarPercentageCopy) {
                adrenalineBarPercentageCopy.parentNode.removeChild(adrenalineBarPercentageCopy);
            }
        }
    }


    
    function createTextDistanceSlider() {
        var slider = document.createElement('input');
        slider.type = 'range';
        slider.min = '-100'; 
        slider.max = '100';
        slider.value = '0'; 
        slider.id = 'textDistanceSlider';
        slider.style.position = 'fixed';
        slider.style.top = '26.2%'; 
        slider.style.left = 'auto'; 
        slider.style.right = '28.5%'; 
        slider.style.transform = 'translate(50%, -50%)';
        slider.style.width = '180px';
      
        slider.addEventListener('input', function() {
            var distance = this.value;
         
            var healthBarPercentageCopy = document.getElementById('health-bar-percentage-copy');
            var adrenalineBarPercentageCopy = document.getElementById('adrenaline-bar-percentage-copy');
            if (healthBarPercentageCopy && adrenalineBarPercentageCopy) {
                healthBarPercentageCopy.style.left = (46.2 + parseInt(distance)) + '%';
                adrenalineBarPercentageCopy.style.right = (46.2 + parseInt(distance)) + '%';
            }
        });

        return slider;
    }

    var modSettingsContent = document.getElementById('tab-mod-settings-content');
    if (modSettingsContent) {
        var slider = createTextDistanceSlider();
        modSettingsContent.appendChild(slider);
    }


//text colors
    function createToggleCustomTextColorSetting() {
        var toggleSetting = document.createElement('div');
        toggleSetting.className = 'modal-item';
        toggleSetting.style.marginBottom = '10px';
        toggleSetting.innerHTML = `
            <input type="checkbox" id="toggle-custom-text-color" ${localStorage.getItem('customTextColorEnabled') === 'true' ? 'checked' : ''}>
            <label for="text-color-picker" style="font-weight: bold; margin-left: 0px;">Text Color</label>
            <input type="color" id="text-color-picker" value="${localStorage.getItem('textColor') || '#ffffff'}" style="margin-left: -100px;">

        `;
        toggleSetting.querySelector('#toggle-custom-text-color').addEventListener('change', function() {
            updateCustomTextColorSetting(this.checked);
        });
        toggleSetting.querySelector('#text-color-picker').addEventListener('input', function() {
            updateTextColorSetting(this.value);
        });
        return toggleSetting;
    }

    function updateCustomTextColorSetting(enabled) {
        localStorage.setItem('customTextColorEnabled', enabled);
        if (enabled) {
            applyCustomTextColor();
        } else {
            disableCustomTextColor();
        }
    }

    function applyCustomTextColor() {
        var customTextColor = localStorage.getItem('textColor') || '#ffffff';
        applyTextColor(customTextColor);
    }

    function disableCustomTextColor() {
        var countElements = document.querySelectorAll('.item-count, #fps-counter, #coordinates-hud, #ping-counter');
        countElements.forEach(function(element) {
            element.style.color = ''; 
        });
    }

    function updateTextColorSetting(color) {
        localStorage.setItem('textColor', color);
        if (localStorage.getItem('customTextColorEnabled') === 'true') {
            applyCustomTextColor();
        }
    }

    function applyTextColor(color) {
        var countElements = document.querySelectorAll('.item-count');
        countElements.forEach(function(element) {
            element.style.color = color;
        });

        var fpsElement = document.getElementById('fps-counter');
        var coordsElement = document.getElementById('coordinates-hud');
        var pingElement = document.getElementById('ping-counter');

        if (fpsElement) {
            fpsElement.style.color = color;
        }

        if (coordsElement) {
            coordsElement.style.color = color;
        }

        if (pingElement) {
            pingElement.style.color = color;
        }
    }

    modSettingsContent.appendChild(createToggleCustomTextColorSetting());
    if (localStorage.getItem('customTextColorEnabled') === 'true') {
        applyCustomTextColor();
    }


    var playerInfoEnabled = localStorage.getItem('playerInfoEnabled') === 'true';
 
    togglePlayerInfo(playerInfoEnabled);

 
    function updatePlayerInfoSetting(enabled) {
        localStorage.setItem('playerInfoEnabled', enabled);
     
        togglePlayerInfo(enabled);
    }


    function createPlayerInfoSetting() {
        var playerInfoSetting = document.createElement('div');
        playerInfoSetting.className = 'modal-item checkbox-setting';
        playerInfoSetting.style.marginBottom = '10px';
        playerInfoSetting.innerHTML = `
        <label>
            <span class="setting-title" style="margin-right: 10px;">Info on Player</span>
            <input type="checkbox" id="toggle-player-info" ${playerInfoEnabled ? 'checked' : ''} style="margin-left: auto; margin-right: -0px; ">
        </label>
    `;
        playerInfoSetting.querySelector('#toggle-player-info').addEventListener('change', function() {
            updatePlayerInfoSetting(this.checked);
        });
        return playerInfoSetting;
    }

    modSettingsContent.appendChild(createPlayerInfoSetting());

//uncap fps
    function toggleUncappedFPS(enabled) {
        if (enabled) {
            window.requestAnimationFrame = function(callback) {
                return setTimeout(callback, 1);
            };
        } else {
            window.requestAnimationFrame = function(callback) {
                return setTimeout(callback, 1000 / 60);
            };
        }
    }


    var uncappedFPSEnabled = localStorage.getItem('uncappedFPSEnabled') === 'true';
    toggleUncappedFPS(uncappedFPSEnabled);


    function updateUncappedFPSSetting(enabled) {
        localStorage.setItem('uncappedFPSEnabled', enabled);
        toggleUncappedFPS(enabled);
    }


    function createUncappedFPSSetting() {
        var uncappedFPSSetting = document.createElement('div');
        uncappedFPSSetting.className = 'modal-item checkbox-setting';
        uncappedFPSSetting.style.marginBottom = '10px';
        uncappedFPSSetting.innerHTML = `
            <label>
                <span class="setting-title" style="margin-right: 10px;">Uncapped FPS</span>
                <input type="checkbox" id="toggle-uncapped-fps" ${uncappedFPSEnabled ? 'checked' : ''} style="margin-left: auto; margin-right: -0px; ">
            </label>
        `;
        uncappedFPSSetting.querySelector('#toggle-uncapped-fps').addEventListener('change', function() {
            updateUncappedFPSSetting(this.checked);
        });
        return uncappedFPSSetting;
    }

    var gunSwitchDelayMap = {
        "AK-47": 400,
        "ARX-160": 400,
        "AUG": 400,
        "ACR": 400,
        "M3K": 700,
        "Model 37": 900,
        "HP18": 400,
        "Flues": 250,
        "Vepr-12": 650,
        "Mosin-Nagant": 900,
        "Tango 51": 900,
        "CZ-600": 600,
        "Barrett M95": 900,
        "M1895": 250,
        "G19": 250,
        "Radio": 250,
        "CZ-75A": 250,
        "SAF-200": 300,
        "M16A4": 400,
        "Micro Uzi": 300,
        "Vector": 300,
        "PP-19": 300,
        "MP40": 300,
        "MCX Spear": 400,
        "Lewis Gun": 400,
        "Stoner 63": 400,
        "MG5": 400,
        "Negev": 400,
        "MG36": 400,
        "M1 Garand": 400,
        "VSS": 400,
        "SR-25": 400,
        "Mini-14": 400,
        "Model 89": 400,
        "USAS-12": 400,
        "G17 (scoped)": 250,
        "Death Ray": 500,
        "Destroyer Of Worlds": 100
    };



    function startCountdownAbovePlayer(countdownValue) {
        var countdownElement = document.createElement('div');
        countdownElement.id = 'weapon-switch-countdown';
        countdownElement.textContent = countdownValue.toFixed(1);
        countdownElement.style.position = 'fixed';
        countdownElement.style.top = '45%';
        countdownElement.style.left = '50%';
        countdownElement.style.transform = 'translate(-50%, -170%)';
        countdownElement.style.fontSize = '24px';
        countdownElement.style.fontWeight = 'bold';
        countdownElement.style.color = 'white';
        countdownElement.style.zIndex = '9999';
        document.body.appendChild(countdownElement);

        var countdownTimer = setInterval(function() {
            countdownValue -= 0.1;
            countdownElement.textContent = countdownValue.toFixed(1);
            if (countdownValue <= 0) {
                clearInterval(countdownTimer);
                countdownElement.parentNode.removeChild(countdownElement);
            }
        }, 100);
    }

    var countdownActive1 = false;
    var countdownActive2 = false;
    var countdownInterval1;
    var countdownInterval2;
    var lastDetectionTimestamp = 0;

    function detectActiveWeaponAndStartCountdown() {

        var currentTimestamp = Date.now();

        if (currentTimestamp - lastDetectionTimestamp < 10) {
            return;
        }

        lastDetectionTimestamp = currentTimestamp;

        var weaponSlot1 = document.getElementById('weapon-slot-1');
        var weaponSlot2 = document.getElementById('weapon-slot-2');

        if (weaponSlot1 && weaponSlot1.classList.contains('active')) {
            var itemNameElement = weaponSlot1.querySelector('.item-name');
            if (itemNameElement) {
                var itemName = itemNameElement.textContent.trim();
                var switchDelay = gunSwitchDelayMap[itemName];
                if (switchDelay !== undefined) {
                    if (!countdownActive1) {
                        var countdownValue = switchDelay / 1000;
                        startCountdownAbovePlayer(countdownValue);
                        countdownActive1 = true;
                    } else {
                    }
                } else {
                }
            } else {
            }
        } else {
            countdownActive1 = false;
            clearInterval(countdownInterval1);
        }

        if (weaponSlot2 && weaponSlot2.classList.contains('active')) {
            var itemNameElement = weaponSlot2.querySelector('.item-name');
            if (itemNameElement) {
                var itemName = itemNameElement.textContent.trim();
                var switchDelay = gunSwitchDelayMap[itemName];
                if (switchDelay !== undefined) {
                    if (!countdownActive2) {
                        var countdownValue = switchDelay / 1000;
                        startCountdownAbovePlayer(countdownValue);
                        countdownActive2 = true;
                    } else {
                    }
                } else {
                }
            } else {
            }
        } else {
            countdownActive2 = false;
            clearInterval(countdownInterval2);
        }
    }

    setInterval(detectActiveWeaponAndStartCountdown, 1);

    function toggleSwitchDelay(enabled) {
        if (enabled) {
            document.addEventListener('click', detectActiveWeaponAndStartCountdown);
        } else {

            document.removeEventListener('click', detectActiveWeaponAndStartCountdown);
            var existingCountdownElement = document.getElementById('weapon-switch-countdown');
            if (existingCountdownElement) {
                existingCountdownElement.parentNode.removeChild(existingCountdownElement);
            }
        }
    }

    var switchDelayEnabled = localStorage.getItem('switchDelayEnabled') === 'true';


    toggleSwitchDelay(switchDelayEnabled);


    function updateSwitchDelaySetting(enabled) {
        localStorage.setItem('switchDelayEnabled', enabled);
        toggleSwitchDelay(enabled);
    }


    function createSwitchDelaySetting() {
        var switchDelaySetting = document.createElement('div');
        switchDelaySetting.className = 'modal-item checkbox-setting';
        switchDelaySetting.style.marginBottom = '10px';
        switchDelaySetting.innerHTML = `
    <label>
        <span class="setting-title" style="margin-right: 10px;">Enable switchDelay</span>
        <input type="checkbox" id="toggle-switch-delay" ${switchDelayEnabled ? 'checked' : ''} style="margin-left: auto; margin-right: -0px; ">
    </label>
`;
        switchDelaySetting.querySelector('#toggle-switch-delay').addEventListener('change', function() {
            updateSwitchDelaySetting(this.checked);
        });
        return switchDelaySetting;
    }

    var modSettingsContent = document.getElementById('tab-mod-settings-content');
    if (modSettingsContent) {
        modSettingsContent.appendChild(createSwitchDelaySetting());
    }



    modSettingsContent.appendChild(createUncappedFPSSetting());

    showKillCounter();
    addAdditionalUI();

    createUncappedFPSSetting()





    periodicallyShowKillCounter();
    document.addEventListener('DOMContentLoaded', addAdditionalUI);
    window.addEventListener('popstate', showKillCounter);
    replaceWithHeader();
})();