Enhanced Visuals: improves your visuals making the experience better!

Adds better Visuals to Sploop.io! Such Item effects, perfect hitbox, shadows, footsteps, weapon range, and more!

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name           Enhanced Visuals: improves your visuals making the experience better!
// @version        v-3.5
// @description    Adds better Visuals to Sploop.io! Such Item effects, perfect hitbox, shadows, footsteps, weapon range, and more!

// @namespace      EHD
// @license        All Rights Reserved
// @author         Cubic Flex [CF]
// @match          *://sploop.io/
// @grant          none
// @icon           https://cdn.glitch.global/499d2ba6-cd57-4e5f-8b56-5557baa5b3a0/EHD%20Visuals.png?v=1709777562902
// ==/UserScript==

/*!
 * Enhanced Visuals [*Free Version] v3.5.1
 * https://discord.gg/aZGuQmrm8z
 *
 * Auto save features
 * Mouse over for tooltips (feature description)
 * Hold click to settings menu
 *
 * More info at:
 * https://io-mods.glitch.me/
 *
 * Made By: Cubic Flex [CF] | 10/11/2024 (mmddyy)
 */

//[=]=> Util functions
class MouseManager {
    constructor() {
        this.x = 0;
        this.y = 0;
        this.resize();
    }

    listeners() {
        window.addEventListener('mousemove', this.move.bind(this));
        window.addEventListener('resize', this.resize.bind(this));
    }

    resize() {
        this.width = window.innerWidth;
        this.height = window.innerHeight;

        this.update();
    }

    move(e) {
        this.x = e.clientX;
        this.y = e.clientY;

        this.update();
    }

    update() {
        this.angle = Math.atan2(this.y - this.height / 2, this.x - this.width / 2);
    }
}

class Img extends Image {
    constructor(src, width = 150, height = 150) {
        super(width, height);

        this.src = src;
    }
}

class Utils {
    static distance(player1, player2) {
        return Math.sqrt(Math.pow(player2.y - player1.y, 2) +
                         Math.pow(player2.x - player1.x, 2));
    }

    static lerp(start, end, amt) {
        return start + (end - start) * amt;
    }

    static try_parse(STRING) {
        try {
            return JSON.parse(STRING);
        } catch {
            return 'Failed to PARSE'
        }
    }

    static ls_get(key) {
        const got = localStorage[key];

        return got ? this.try_parse(got) : false;
    }

    static ls_set(key, value) {
        localStorage[key] = typeof value === 'string' ? value : JSON.stringify(value);
    }
}

class Tooltip {
    static show(id, title) {
        const TIP = document.querySelector('#tooltip-menu');
        const feature = All_features[id];

        TIP.style.opacity = '1';
        TIP.innerHTML = title || feature.info;
        TIP.style.left = Mouse.x + 'px';
        TIP.style.top = Mouse.y + 'px';
    }

    static hide() {
        const TIP = document.querySelector('#tooltip-menu');

        TIP.style.opacity = '0';
    }
}

//[=]=> Variables def.
const server = {
    request_received: 17,
    entity_spawned: 32,
    items_upgrade: 2,
    items_count: 36,
    ping_update: 15,
    create_clan: 24,
    update_clan: 16,
    entity_chat: 30,
    leave_clan: 27,
    update_age: 8,
    item_hit: 29,
    upgrades: 14,
    spawned: 35,
    killed: 28,
    update: 20,
    died: 19
}

const All_features = {
    colored_hp: {
        name: 'Colored HP',
        info: 'Colors your health bar',
        icon: 'palette-fill',
        enabled: true
    },
    display_hp: {
        name: 'Display HP',
        info: 'Shows how many hp you have',
        icon: 'percent',
        enabled: true
    },
    smooth_hp: {
        name: 'Smooth HP',
        info: 'Makes the health bar smoother',
        icon: 'water',
        enabled: true
    },
    healing_effect: {
        name: 'Healing effect',
        info: 'Particles come out when heal',
        icon: 'apple',
        enabled: true
    },
    weapon_range: {
        name: 'Weapon range',
        info: 'Shows weapon range',
        icon: 'opencollective',
        enabled: true
    },
    hitbox: {
        name: 'Hitbox',
        info: 'Shows objects hitbox',
        icon: 'disc',
        enabled: false
    },
    tornado_particles: {
        name: 'Tornado particles',
        info: 'Adds particles to tornadoes',
        icon: 'tornado',
        enabled: true
    },
    footsteps: {
        name: 'Footsteps',
        info: 'Shows footsteps',
        icon: 'meta',
        enabled: true
    },
    hide_ads: {
        name: 'Hide ads',
        info: 'Hide ads from the game menu',
        icon: 'eye-slash-fill',
        enabled: true
    },
    night_mode: {
        name: 'Night mode',
        info: 'Night mode in sploop',
        icon: 'moon-stars-fill',
        enabled: false
    },
    name_changer: {
        name: 'Name changer',
        info: 'Changes the mob names',
        icon: 'marker-tip',
        enabled: false
    }
}

const Features = Utils.ls_get('ehd_features') || {
    colored_hp: true,
    display_hp: true,
    smooth_hp: true,
    healing_effect: true,
    weapon_range: true,
    hitbox: false,
    tornado_particles: true,
    footsteps: true,
    hide_ads: true,
    night_mode: false,
    name_changer: false
}

const Settings = Utils.ls_get('ehd_settings') || {
    colored_hp: {
        mine_health: '#611a80',
        enemy_health: '#ae6999'
    },
    weapon_range: {
        color: '#404040',
        cap: true
    },
    hitbox: {
        color: '#50C878'
    },
    footsteps: {
        land: false
    },
    name_changers: {
        Wolf: 'Dog',
        Dragon: 'Boss',
        Duck: 'Quack'
    }
}

for (const key in All_features) {
    if (All_features.hasOwnProperty(key)) {
        if (!Features.hasOwnProperty(key)) {
            Features[key] = All_features[key].enabled;
        }
    }
}

const Vars = {
    loaded: false,
    entities: [],
    steps: [],
    heals: [],
    health: false,
    images: {
        cookie: new Img('https://sploop.io/img/entity/cookie.png'),
        apple: new Img('https://sploop.io/img/entity/apple.png')
    },
    holds: {}
}

//[=]=> Menu functions
class MenuManager {
    static parseID(id) {
        const value = id.children[1].innerHTML;

        return value.replace(/ /g, '_').toLowerCase();
    }

    static parseSetting(element) {
        const value = element.parentElement.parentElement;
        const feature = value.parentElement.classList[1].replace(/settings\-/g, '');

        return {
            feature,
            id: value.classList[2]
        }
    }

    static removeNC(element) {
        const name = element.parentElement.children[1].children[0];
        const value = name.innerHTML;

        // Cleans the input values, adds it to the settings & close the "dropdown"
        delete Settings.name_changers[value];

        // Then append the replacers again lm4o
        this.appendReplacer()
    }

    static addNC(element) {
        const inputs = element.parentElement.children[1].children;
        const name = inputs[0];
        const replace = inputs[2];

        if (name.value.trim().length < 1) return name.focus();
        if (replace.value.trim().length < 1) return replace.focus();

        // Cleans the input values, adds it to the settings & close the "dropdown"
        Settings.name_changers[name.value] = replace.value;

        document.querySelector('.button-plus').click() //MenuManager.toggleNewNC(this);

        name.value = '';
        replace.value = '';

        // Then append the replacers again lm4o
        this.appendReplacer()
    }

    static appendReplacer() {
        // Appends each name changer
        let string = '';

        for (let name in Settings.name_changers) {
            const change = Settings.name_changers[name];

            string += `
                <div class="name-changer">
                    <i class="text bi bi-trash-fill" onclick="MenuManager.removeNC(this)"></i>

                    <div class="name-changes">
                        <span>${name}</span>
                        <i class="bi bi-arrow-left-right"></i>
                        <span> ${change} </span>
                    </div>
                </div>
            `;
        }

        document.querySelector('#name-changer-wrap').innerHTML = string;
    }

    static changeIcon(element, over, icon, remove) {
        setTimeout(() => {
            element.classList = `bi bi-${icon}`
        }, 1e3 / 60)
    }

    static toggleNewNC(element) {
        // Display / hide
        const edit = document.querySelectorAll('.edit');
        const display = edit[0].style.display === 'flex' ? 'none' : 'flex';
        const icon = edit[0].style.display === 'flex' ? 'bi bi-plus' : 'bi bi-dash';

        edit.forEach(edit => {
            edit.style.display = display;
        });

        // Focus the input
        const input = document.querySelector('.name-changes').children[0];
        input.focus();

        // Change this icon
        element.children[0].classList = icon;
    }

    static searchParent(element, parentClass) {
        function repeat(elem) {
            if (!elem || !elem.parentElement) {
                return null;
            }

            const contains = elem.parentElement.classList.contains(parentClass);

            if (contains) {
                return elem.parentElement;
            } else {
                return repeat(elem.parentElement);
            }
        }

        return repeat(element);
    }

    static enable(element, id, enabled, disabled) {
        const { feature } = this.parseSetting(element);
        const Setting = Settings[feature][id];

        Settings[feature][id] = element.checked;

        if (!enabled) return;

        const parent = this.searchParent(element, 'switch')
        const icon = parent.querySelector('i');

        icon.classList = `bi bi-${element.checked ? enabled : disabled}`
    }

    static changeColor(element) {
        // Remove all balls active class & add it to self
        const balls = element.parentElement.children;

        for (let ballID in balls) {
            const ball = balls[ballID];

            if (ball.classList?.contains('color-ball')) {
                ball.classList.remove('active');
            }
        }

        element.classList.add('active')

        // Now apply the color to the settings
        const { feature, id } = this.parseSetting(element);

        Settings[feature][id] = element.style.backgroundColor;
    }

    static colorPicker(element) {
        // First apply the color to the settings
        const { feature, id } = this.parseSetting(element);

        Settings[feature][id] = element.value;

        // Then change the color in the ball
        const balls = element.parentElement.parentElement.children[0].children;

        for (let ballID in balls) {
            const ball = balls[ballID];

            if (ball.classList?.contains('picker-div')) {
                ball.style.backgroundColor = element.value
                ball.classList.add('active')
            } else if (ball.classList?.contains('color-ball')) {
                ball.classList.remove('active')
            }
        }

        // Make this element active
    }

    static ToggleToolTip(raw_id, hovering) {
        const id = this.parseID(raw_id);

        if (!hovering) {
            Tooltip.hide()
            return;
        }

        Tooltip.show(id);
    }

    static display(menu, toggle, trigger) {
        menu.style.display = toggle ? 'block' : 'none';

        setTimeout(() => {
            trigger || this.s_opacity(menu, toggle, true);
        }, trigger ? 80 : 0);
    }

    static s_opacity(menu, toggle, trigger) {
        menu.style.opacity = toggle ? '1' : '0';

        setTimeout(() => {
            trigger || this.display(menu, toggle, true);
        }, trigger ? 0 : 400);
    }

    static toggleSelector() {
        // frist change the text to select feture
        document.querySelector('.settings-icon').classList = `bi bi-sliders2 settings-icon`;
        document.querySelector('.settings-name').innerHTML = 'Select a feature';

        // THEN open the selector andclose body
        document.querySelector('.settings-selector').style.display = 'flex';
        document.querySelector('.settings-body').style.display = 'none';
    }

    static toggleSettings(raw_id, toggle) {
        const id = toggle && this.parseID(raw_id);
        const menu = document.querySelector('#settings-menu');

        toggle ? this.display(menu, toggle) : this.s_opacity(menu, toggle);

        if (!toggle) return;
        // ok if its opening then: append the name and info to the menu
        const { icon, name } = All_features[id];
        document.querySelector('.settings-icon').classList = `bi bi-${icon} settings-icon`;
        document.querySelector('.settings-name').innerHTML = name;

        // First closes "all feature settings" div then open the settings div
        document.querySelector('.settings-selector').style.display = 'none';
        document.querySelector('.settings-body').style.display = 'block';

        // After open the div card, if it has a card then open the card if not open the error card kk
        const setting_divs = document.querySelectorAll('.setting');
        const error = document.querySelector('.settings-undefined');

        setting_divs.forEach(div => {
            div.style.display = 'none'; // also clsoes all the opened cards
        })

        const setting = document.querySelector(`.settings-${id}`);
        (setting || error).style.display = 'block';
    }

    static ToggleFeature(raw_id, holding) {
        if (holding) {
            Vars.holds[raw_id] = Date.now();
            return;
        }

        // Handle MouseUp
        const date = Date.now() - Vars.holds[raw_id];

        if (date > 200) { // Holding
            this.toggleSettings(raw_id, true)
            return;
        }

        const id = this.parseID(raw_id);

        Features[id] = !Features[id];

        // Add the active class
        const setting = document.querySelector(`.setting-div-${id}`);
        const toggle = Features[id] ? 'add' : 'remove';

        raw_id.classList[toggle]('active')
        setting.classList[toggle]('active')
    }

    static minimize(element) {
        const menu = document.querySelector('#ehd-menu');
        const minimized = menu.style.width === '4.6vw';

        element.style.rotate = !minimized ? '0deg' : '180deg'; // rotate the arrow
        menu.style.width = minimized ? '16vw' : '4.6vw'; // adjust width

        menu.classList[minimized ? 'remove' : 'add']('minimized'); // then just add / remove the minimized class
    }

    static opacity(element) {
        const checked = element.checked;
        const color = checked ? 'rgb(255 255 255 / .25)' : 'transparent';

        document.querySelector('#ehd-menu').style.opacity = checked ? '.6' : '1';
        document.querySelector('#transparency').parentElement.style.backgroundColor = color;
    }
}

//[=]=> Css !
const CSS = document.createElement('style');
      CSS.innerHTML = `
          @import url("https://cdn.jsdelivr.net/npm/[email protected]/font/bootstrap-icons.css");

          :root {
              --main: #242527;
              --softer: #3a3b3d;
              --color: #dedee0;
              --gray: #a6a7a9;

              --light-gray: #3a3b3d;

              --text: url(img/ui/cursor-text.png) 16 0, text;
              --default: url(img/ui/cursor-default.png) 2 0, default;
              --pointer: url(img/ui/cursor-pointer.png) 6 0, pointer;
              --index: 100000000;
          }

          * {
              transition: all 0.4s ease;
              transition-duration: .4s /* lmao=? */
          }

          @keyframes glow {
              0% {
                  box-shadow: 0 0 20px -1.1vw rgba(255, 255, 255, 0.9);
              }

              50% {
                  box-shadow: 0 0 40px -1.1vw rgba(255, 255, 255, 0.9);
              }

              100% {
                  box-shadow: 0 0 20px -1.1vw rgba(255, 255, 255, 0.9);
              }
          }

          @keyframes rotate {
              0% {
                  transform: scale(1) rotateY(0deg)
              }

              50% {
                  transform: scale(1.15) rotateY(180deg)
              }

              100% {
                  transform: scale(1) rotateY(0deg)
              }
          }

          @keyframes rotateDeg {
              0% {
                  rotate: 0deg
              }

              50% {
                  rotate: 360deg
              }

              100% {
                  rotate: 0deg
              }
          }

          .ehd_scrollBar::-webkit-scrollbar,
          .ehd_scrollBar *::-webkit-scrollbar {
              height: 7px;
              width: 7px;
          }

          .ehd_scrollBar::-webkit-scrollbar-track,
          .ehd_scrollBar *::-webkit-scrollbar-track {
              border-radius: 5px;
              background-color: transparent;
          }

          .ehd_scrollBar::-webkit-scrollbar-track:hover,
          .ehd_scrollBar *::-webkit-scrollbar-track:hover {
              background-color: #B8C0C2;
          }

          .ehd_scrollBar::-webkit-scrollbar-track:active,
          .ehd_scrollBar *::-webkit-scrollbar-track:active {
              background-color: #B8C0C2;
          }

          .ehd_scrollBar::-webkit-scrollbar-thumb,
          .ehd_scrollBar *::-webkit-scrollbar-thumb {
              border-radius: 5px;
              background-color: #5E5E5E;
          }

          .ehd_scrollBar::-webkit-scrollbar-thumb:hover,
          .ehd_scrollBar *::-webkit-scrollbar-thumb:hover {
              background-color: #474747;
          }

          .ehd_scrollBar::-webkit-scrollbar-thumb:active,
          .ehd_scrollBar *::-webkit-scrollbar-thumb:active {
              background-color: #7F7F7F;
          }

          #ehd-menu {
              overflow: hidden;
              background-color: var(--main);
              z-index: var(--index);
              position: fixed;
              left: 1.5vw;
              top: 1.5vw;
              width: 16vw;
              height: 32vw;
              border-radius: .7vw;
              display: flex;
              flex-direction: column;
              box-shadow: 0px 0px 6px 0px black
          }

          #ehd-menu.minimized .body {
              overflow: hidden /* idk, why can you scroll while minimized? no sense ig */
          }

          #ehd-menu.minimized .checkbox,
          #ehd-menu.minimized span {
              font-size: 0vw;
              width: 0vw !important
          }

          #ehd-menu.minimized .menu-size {
              margin-left: 2.8vw
          }

          #ehd-menu div {
              width: 100%;
          }

          #ehd-menu .header {
              height: 16%;
              padding: 1vw;
              display: flex;
              flex-direction: row;
              justify-content: flex-start;
              align-items: center;
          }

          #ehd-menu .body {
              padding: 1vw;
              height: 60%;
              overflow: scroll;
              overflow-x: hidden
          }

          #ehd-menu .footer {
              border-top: 1px solid #47484a;
              padding: 1vw;
              height: max-content
          }

          .header img {
              width: 2.8vw;
              margin-right: .8vw;
              border-radius: 0.4vw
          }

          .header span {
              color: var(--color);
          }

          .header-holder {
              display: flex;
              flex-direction: column
          }

          .header-holder span {
              font-weight: 700;
              font-size: .9vw
          }

          .description {
              color: var(--gray) !important;
              font-size: .8vw !important
          }

          .menu-button {
              margin-bottom: .3vw;
              height: max-content;
              padding: 0.7vw;
              display: flex;
              flex-direction: row;
              align-items: center;
              text-align: left;
              color: var(--color);
              border-radius: 0.4vw;
              overflow: hidden
          }

          .menu-button:hover {
              background: rgb(255 255 255 / .05);
          }

          .menu-button.active {
              background: rgb(255 255 255 / .15);
          }

          .menu-button i,
          .menu-button span {
              margin-right: .7vw;
              font-weight: 600;
              font-size: 1.2vw
          }

          .menu-button span {
              font-size: 0.9vw
          }

          .menu-button,
          .menu-button * {
              cursor: var(--pointer);
          }

          .separator {
              display: flex;
              align-items: center;
          }

          .switch {
              display: flex;
              min-width: 2vw;
              justify-content: space-between;
          }

          .switch * {
              cursor: var(--pointer)
          }

          .switch input[type="checkbox"] {
              opacity: 0;
              position: fixed
          }

          .checkbox {
              display: block;
              width: 2.5vw !important;
              height: 1vw;
              border-radius: 20vw;
              background-color: white;
          }

          .switch .checkbox::before {
              content: '';
              display: block;
              width: 0.8vw;
              height: 0.8vw;
              border-radius: 50%;
              margin: .1vw;
              background-color: var(--main);
              transition: margin-left 0.3s ease
          }

          .switch input[type="checkbox"]:checked + .checkbox::before {
              margin-left: 1.15vw
          }

          .menu-size {
              background-color: var(--light-gray);
              position: fixed;
              border-radius: 50%;
              width: 1.7vw !important;
              height: 1.7vw;
              margin-left: 14vw;
              display: flex;
              flex-direction: row;
              align-items: center;
              justify-content: center;
              font-weight: bolder;
              font-size: 1vw;
              cursor: var(--pointer);
              text-shadow: 0px 0px 1px white;
              box-shadow: 0px 0px 2px black;
              rotate: 180deg
          }

          .menu-size i {
              cursor: var(--pointer);
              color: white;
          }

          #tooltip-menu {
              position: fixed;
              top: 100px;
              left: 220px;
              pointer-events: none;
              background-color: #1d1e1f;
              color: white;
              font-family: 'Baloo Paaji';
              font-weight: 300;
              z-index: calc(var(--index) + 10);
              border-radius: 0.4vw;
              height: 2.8vw;
              padding: 0.4vw 1vw;
              box-shadow: 0px 0px 6px var(--main);
          }

          #settings-menu,
          .night-card {
              position: fixed;
              top: 0;
              left: 0;
              width: 100%;
              height: 100%;
              background: radial-gradient(transparent, rgb(0 0 0 / .6));
              pointer-events: none;
              z-index: calc(var(--index) - 1);
          }

          #settings-menu {
              display: none;
              opacity: 0;
              background: none;
              background-color: rgb(0 0 0 / .4);
              z-index: calc(var(--index) + 2);
              pointer-events: all
          }

          #settings-menu .container {
              display: flex;
              flex-direction: column;
              width: 30%;
              height: 60%;
              margin: 10% auto;
              background: var(--main);
              border-radius: .7vw;
              padding: 1.5vw;
              box-shadow: 0px 0px 6px 0px var(--main)
          }

          #main-content {
              width: max-content
          }

          .settings-header {
              display: flex;
              flex-direction: row;
              justify-content: space-between;
              margin-bottom: 0.5vw
          }

          .settings-header * {
              font-size: 2.7vw;
              font-weight: 700;
              color: var(--color);
          }

          .feature-container {
              display: flex;
              flex-direction: column;
              justify-content: center;
          }

          .feature-container * {
              font-size: 1.3vw;
          }

          .settings-button {
              cursor: var(--pointer)
          }

          .settings-button:hover {
              animation: rotateDeg 1.5s ease forwards
          }

          .actual-feature { /* Same as desc but diff font size */
              color: var(--gray) !important;
              font-size: 1vw !important
          }

          .settings-body,
          .settings-selector {
              width: 100%;
              height: 100%;
              background: #1d1d1d;
              padding: 1vw;
              border-radius: 0.4vw;
              overflow: scroll;
              overflow-x: hidden
          }

          .settings-body *,
          .settings-selector * {
              color: var(--color);
              font-weight: 600;
              font-size: 1.175vw;
          }

          .settings-selector {
              flex-direction: row;
              flex-wrap: wrap;
              justify-content: center;
              align-content: flex-start;
          }

          .settings-item {
              width: 4vw;
              height: 4vw;
              background: rgb(255 255 255 / .025);
              display: grid;
              align-items: center;
              justify-content: center;
              border-radius: 1vw;
              cursor: var(--pointer);
              margin: 1vw;
          }

          .settings-item:hover {
              background: rgb(255 255 255 / .25);
              border-radius: .6vw;
          }

          .settings-item.active {
              background: rgb(255 255 255 / .15);
          }

          .settings-item * {
              cursor: var(--pointer);
              font-size: 2vw
          }

          .color-ball {
              width: 1.5vw;
              height: 1.5vw;
              border-radius: 50%;
              margin: 0vw 0.6vw;
              cursor: var(--pointer);
          }

          .color-ball:hover {
              filter: brightness(.7);
              border-radius: 30%
          }

          .color-ball.active::before {
              transition: all 0.4s ease;
              content: '';
              display: flex;
              width: 109%;
              height: 110%;
              border: 0.15vw solid rgb(255 255 255 / 0.25);
              border-radius: 50%;
              margin: -.22vw;
          }

          .color-ball.active:hover::before {
              filter: brightness(.7);
              border-radius: 30%
          }

          .picker-holder input[type="color"] {
              opacity: 0;
              position: fixed
          }

          .picker-color {
              cursor: var(--pointer);
              font-size: 1.5vw;
              margin-left: 1vw
          }

          .picker-text {
              color: var(--gray) !important;
              font-size: 1vw !important;
          }

          .color-picker {
              display: flex;
              justify-content: space-between;
          }

          .settings-hr {
              margin: 1vw 0vw;
              border: .025vw solid var(--main);
          }

          .checkbox-wrapper {
              flex-direction: row;
              justify-content: space-between;
              align-items: center;
          }

          .checkbox-wrapper i {
              margin-right: 1.5vw;
              font-size: 2.3vw;
          }

          .info-holder {
              display: flex;
              flex-direction: column;
          }

          .info-holder * {
              font-size: 1vw
          }

          .dropdown-div {
              display: flex;
              justify-content: space-between
          }

          .dropdown-div i {
              margin-right: .6vw;
              font-size: 1vw !important;
              color: var(--gray) !important;
          }

          .button-plus {
              cursor: var(--pointer);
              background-color: rgb(255 255 255 / .25););
              border-radius: 50%;
              display: flex;
              flex-direction: row;
              justify-content: center;
              align-items: center;
              width: 1.5vw;
              height: 1.5vw;
          }

          .button-plus:hover {
              filter: opacity(0.7)
          }

          .button-plus:active {
              filter: opacity(1.2)
          }

          .button-plus i {
              cursor: var(--pointer);
              margin: 0px !important;
              color: white !important;
              font-size: 1.3vw;
          }

          .name-changer {
              display: flex;
              flex-direction: row;
              justify-content: space-between;
              align-items: center;
              margin-bottom: 1vw
          }

          .name-changer .text {
              font-size: 2.1vw;
              color: var(--gray) !important;
              cursor: var(--pointer);
              margin-right: 1vw
          }

          .name-changes {
              justify-content: space-between;
              display: flex;
              width: 100%;
              background: #161616;
              padding: 0.6vw 1vw;
              border-radius: 0.4vw;
              flex-direction: row;
              justify-content: center;
              text-align: center;
          }

          .name-changes i {
              margin: 0vw 1vw
          }

          .name-changes > :first-child {
              width: 45%;
          }

          .name-changes > :nth-child(2) {
              width: 10%;
          }

          .name-changes > :nth-child(3) {
              width: 45%;
          }

          .name-edit {
              text-align: center;
              outline: none;
              user-select: none;
              background-color: inherit;
              border: 0px;
              cursor: var(--text);
          }

          .edit {
              margin-bottom: 1vw;
              display: none
          }

          .edit .name-changes {
              animation: glow 1s forwards;
              box-shadow: 0 0 20px -1.1vw rgb(255 255 255 / .9)
          }

          .edit span {
              font-size: 0.8vw;
              margin-bottom: 1vw
          }

          .risk {
              margin-right: .5vw;
              color: #E74C3C
          }

          .icon-change:hover {
              animation: rotate 1s infinite
          }

          .icon-change {
              animation: rotate 1s forwards
          }

          .name-changer i:hover {
              filter: opacity(.5)
          }
      `;

//[=]=> Menu append & title
const HUD = document.createElement('div');
      HUD.id = 'ehd-menu';
      HUD.classList = 'ehd_scrollBar';
      HUD.innerHTML = `
        <div class="header">
            <img src="https://cdn.glitch.global/499d2ba6-cd57-4e5f-8b56-5557baa5b3a0/EHD%20Visuals.png" alt="EHD Mod Icon" draggable="false">

            <div class="header-holder">
                <span> EHD [Free Version] </span>
                <span class="description header-info"> Settings </span>
            </div>

            <div class="menu-size" onclick="MenuManager.minimize(this)">
                <i class="bi bi-chevron-right"></i>
            </div>
        </div>

        <div class="body"></div>

        <div class="footer">
            <div class="menu-button" role="button" onclick="window.open('https://discord.gg/aZGuQmrm8z', '_blank')"
                 onmouseover="Tooltip.show(void 0, 'Join our Discord to share your feedback and discover more mods!')"
                 onmouseout="Tooltip.hide()">
                <i class="bi bi-discord"></i>
                <span> Discord </span>
            </div>

            <label class="menu-button switch">
                <div class="separator" id="transparency">
                    <i class="bi bi-transparency"></i>
                    <span> Transparency </span>
                </div>

                <input type="checkbox" onchange="MenuManager.opacity(this)">
                <div class="checkbox"></div>
            </label>
        </div>
      `;

const TIP = document.createElement('div');
      TIP.id = 'tooltip-menu';
      TIP.style = 'opacity: 0';
      TIP.innerHTML = ` Enhanced Visuals `

const NIGHT = document.createElement('div');
      NIGHT.classList = 'night-card';
      NIGHT.style = 'opacity: 0';

const SETTINGS = document.createElement('div');
      SETTINGS.id = 'settings-menu';
      SETTINGS.innerHTML = `
          <div class="container">
              <div class="settings-header">
                  <div class="separator"> <!-- Separate the flex -->
                      <i class="bi bi-sliders2 settings-icon" style="margin-right: 1vw"></i>

                      <div class="feature-container">
                          <span> Settings </span>
                          <span class="actual-feature settings-name"> Tornado particles </span>
                      </div>
                  </div>

                  <div class="separator">
                      <i class="bi bi-arrow-90deg-left settings-button" style="font-size: 1.2vw; color: var(--gray)" onclick="MenuManager.toggleSelector()"></i>
                      <i class="bi bi-x settings-button" onclick="MenuManager.toggleSettings('', false)"></i>
                  </div>
              </div>

              <div class="settings-selector ehd_scrollBar"> </div>

              <div class="settings-body ehd_scrollBar">
                  <div class="setting settings-colored_hp">
                      Health bar color

                      <div class="separator color-picker mine_health" style="margin-top: 0.6vw">
                          <div class="separator">
                              <div class="color-ball" style="background-color: #801a1a" onclick="MenuManager.changeColor(this)"></div>
                              <div class="color-ball" style="background-color: #bacb29" onclick="MenuManager.changeColor(this)"></div>
                              <div class="color-ball" style="background-color: #269a23" onclick="MenuManager.changeColor(this)"></div>
                              <div class="color-ball" style="background-color: #23629a" onclick="MenuManager.changeColor(this)"></div>
                              <div class="color-ball active picker-div" onclick="MenuManager.changeColor(this)" style="background-color: #611a80"></div>
                          </div>

                          <label class="picker-holder separator">
                              <input type="color" value="#611a80" onchange="MenuManager.colorPicker(this)"/>
                              <span class="picker-text"> Color picker </span>
                              <i class="bi bi-brush-fill picker-color"></i>
                          </label>
                      </div>

                      <hr class="settings-hr">

                      Enemy bar color

                      <div class="separator color-picker enemy_health" style="margin-top: 0.6vw">
                          <div class="separator">
                              <div class="color-ball" style="background-color: #801a1a" onclick="MenuManager.changeColor(this)"></div>
                              <div class="color-ball" style="background-color: #bacb29" onclick="MenuManager.changeColor(this)"></div>
                              <div class="color-ball" style="background-color: #269a23" onclick="MenuManager.changeColor(this)"></div>
                              <div class="color-ball" style="background-color: #23629a" onclick="MenuManager.changeColor(this)"></div>
                              <div class="color-ball active picker-div" onclick="MenuManager.changeColor(this)" style="background-color: #ae6999"></div>
                          </div>

                          <label class="picker-holder separator">
                              <input type="color" value="#ae6999" onchange="MenuManager.colorPicker(this)"/>
                              <span class="picker-text"> Color picker </span>
                              <i class="bi bi-brush-fill picker-color"></i>
                          </label>
                      </div>
                  </div>

                  <div class="setting settings-weapon_range">
                      <div class="switch separator checkbox-wrapper">
                          <div class="separator">
                              <i class="bi bi-slash-circle-fill"></i>

                              <div class="info-holder">
                                  <span> Round Cap </span>
                                  <span class="description"> Rounds the line cap to smooth </span>
                              </div>
                          </div>

                          <label class="separator" style="width: 2.1vw">
                              <input type="checkbox" checked onchange="MenuManager.enable(this, 'cap', 'slash-circle-fill', 'slash-square-fill')">
                              <div class="checkbox"></div>
                          </label>
                      </div>

                      <hr class="settings-hr">

                      Draw color

                      <div class="separator color-picker color" style="margin-top: 0.6vw">
                          <div class="separator">
                              <div class="color-ball" style="background-color: #801a1a" onclick="MenuManager.changeColor(this)"></div>
                              <div class="color-ball" style="background-color: #bacb29" onclick="MenuManager.changeColor(this)"></div>
                              <div class="color-ball" style="background-color: #269a23" onclick="MenuManager.changeColor(this)"></div>
                              <div class="color-ball" style="background-color: #23629a" onclick="MenuManager.changeColor(this)"></div>
                              <div class="color-ball active picker-div" onclick="MenuManager.changeColor(this)" style="background-color: #404040"></div>
                          </div>

                          <label class="picker-holder separator">
                              <input type="color" value="#404040" onchange="MenuManager.colorPicker(this)"/>
                              <span class="picker-text"> Color picker </span>
                              <i class="bi bi-brush-fill picker-color"></i>
                          </label>
                      </div>
                  </div>

                  <div class="setting settings-hitbox">
                      Draw color

                      <div class="separator color-picker color" style="margin-top: 0.6vw">
                          <div class="separator">
                              <div class="color-ball" style="background-color: #801a1a" onclick="MenuManager.changeColor(this)"></div>
                              <div class="color-ball" style="background-color: #bacb29" onclick="MenuManager.changeColor(this)"></div>
                              <div class="color-ball" style="background-color: #269a23" onclick="MenuManager.changeColor(this)"></div>
                              <div class="color-ball" style="background-color: #23629a" onclick="MenuManager.changeColor(this)"></div>
                              <div class="color-ball active picker-div" onclick="MenuManager.changeColor(this)" style="background-color: #50C878"></div>
                          </div>

                          <label class="picker-holder separator">
                              <input type="color" value="#50C878" onchange="MenuManager.colorPicker(this)"/>
                              <span class="picker-text"> Color picker </span>
                              <i class="bi bi-brush-fill picker-color"></i>
                          </label>
                      </div>
                  </div>

                  <div class="setting settings-footsteps">
                      <div class="switch separator checkbox-wrapper">
                          <div class="separator">
                              <i class="bi bi-meta"></i>

                              <div class="info-holder">
                                  <span> Land steps </span>
                                  <span class="description"> Draw steps when walking on land </span>
                              </div>
                          </div>

                          <label class="separator" style="width: 2.1vw">
                              <input type="checkbox" checked onchange="MenuManager.enable(this, 'land')">
                              <div class="checkbox"></div>
                          </label>
                      </div>
                  </div>

                  <div class="setting settings-name_changer">
                      <div class="dropdown-div">
                          <div class="separator">
                              <i class="bi bi-pencil-fill"></i>
                              <span> New Name Changer </span>
                          </div>

                          <div class="button-plus" onclick="MenuManager.toggleNewNC(this)">
                              <i class="bi bi-plus"></i>
                          </div>
                      </div>

                      <hr class="settings-hr">

                      <div class="name-changer-holder">
                          <div class="name-changer edit">
                              <i class="bi bi-pencil-square text icon-change"
                                 onclick="MenuManager.addNC(this)"
                                 onmouseover="MenuManager.changeIcon(this, 1, 'bookmark-plus text icon-change')"
                                 onmouseout="MenuManager.changeIcon(this, 0, 'pencil-square text icon-change')">
                              </i>

                              <div class="name-changes">
                                  <input type="text" placeholder="Wolf" class="name-edit"/>
                                  <i class="bi bi-arrows"></i>
                                  <input type="text" placeholder="Dog" class="name-edit"/>
                              </div>
                          </div>

                          <span class="edit">
                              <span class="risk">*</span>
                              <span> NOTE: The name will be replaced ONCE entity is displayed on screen </span>
                          </span>

                          <div id="name-changer-wrap"></div>
                      </div>
                  </div>

                  <div class="setting settings-undefined" style="display: none">
                      <span> No settings available for this feature. </span>
                  </div>
              </div>
          </div>
      `

document.head.appendChild(CSS);
document.body.appendChild(HUD);
document.body.appendChild(TIP);
document.body.appendChild(NIGHT);
document.body.appendChild(SETTINGS);

document.title = 'Sploop.io - EHD';

//[=]=> WebSocket overrider & functions
class PlayerManager {
    constructor() {
        this.alive = false;
        this.clan = [];
        this.age = 0;
        this.old_weapon = 0;
    }

    update() {
        const velocity = !Vars.steps.length && Player.velocity > 18;

        if (velocity) {
            const land = Settings.footsteps.land;

            const platform = Vars.entities.find(entity => entity && entity.type === 9 && Utils.distance(Player, entity) <= 65);
            const bed = Vars.entities.find(entity => entity && entity.type === 15 && Utils.distance(Player, entity) <= 65);

            const { x, y } = Player;
            const color = bed ? '#474747' : platform ? '#69482a' : y < 2485 ? '#b9b5ad' : y < 7485 ? '#51603a' : y < 8000 ? '#beb387' : y < 9000 ? '#1e6774' : '#86613d'

            if (!land && y < 7485) return;

            Vars.steps.push({ x, y, color, size: 10 });
        }
    }
}

class Packets {
    static init(ws) {
        const url = ws.url;

        ws.addEventListener('message', this.message.bind(this));

        Object.assign(this, { ws, url })
    }

    static message(event) {
        const message = event.data;
        const type = typeof message;
        const data = type === 'string' ? JSON.parse(message) : new Uint8Array(message);
        data.type = data[0];

        if (data.type === server.items_upgrade) {
            if (data.byteLength > 1) {
                Player.items = [];

                for (let index = 1; index < data.byteLength; index++) {
                    Player.items.push(data[index])
                };
            }
        }

        if (data.type === server.spawned) {
            const id = data[1],
                  items = data[4],
                  alive = true;

            Object.assign(Player, { id, items, alive });
        }

        if (data.type === server.died) Player.alive = false;

        if (data.type === server.update) {
            Vars.enemy = null;

            for (let index = 1; index < data.length; index += 19) {
                const broke = data[index + 8];

                const type = data[index + 0];
                const sid = data[index + 1];
                const id = data[index + 2] | data[index + 3] << 8;
                const x = data[index + 4] | data[index + 5] << 8;
                const y = data[index + 6] | data[index + 7] << 8;
                const dir = data[index + 9] / 255 * 6.283185307179586 - Math.PI;
                const weapon = data[index + 10];
                const hat = data[index + 11];
                const team = data[index + 12];
                const health = data[index + 13] / 255 * 100;

                if (2 & broke) {
                    Vars.entities[id] = null;
                } else {
                    const entity = Vars.entities[id] || {};
                    Object.assign(entity, { type, sid, id, x, y, weapon, hat, health, team, dir });

                    Vars.entities[id] = entity;

                    if (id === Player.id) {
                        Player.velocity = Math.hypot(y - Player.y, x - Player.x);

                        Player.update();
                        Object.assign(Player, entity);
                    }

                    const clan = (!Player.team || team != Player.team);
                    if (type === 0 && Player.id !== id && clan) {
                        const enemy = Vars.enemy;
                        const newDist = Math.hypot(Player.y - y, Player.x - x);
                        const oldDist = Vars.enemy ? Math.hypot(Player.y - enemy.y, Player.x - enemy.x) : null;

                        if (enemy) {
                            if (newDist < oldDist) {
                                Vars.enemy = entity;
                            }
                        } else {
                            Vars.enemy = entity;
                        }
                    }
                }
            }
        }
    }
}

WebSocket.prototype.send_ = WebSocket.prototype.send;

WebSocket.prototype.send = function(data) {
    const url = Packets.ws?.url !== this.url;
    if (!Packets.ws || url) {
        Packets.init(this);
    }

    this.send_(data);
};

//[=]=> Canvas drawing functions
const particlesArray = []
class Functions {
    static footsteps(canvas, args) {
        Vars.steps.forEach((step, index) => {
            const { x, y, size, color } = step;

            canvas.save()
            canvas.beginPath()

            canvas.globalAlpha = Math.max(0, 1 - step.size / 30)
            canvas.fillStyle = color
            canvas.arc(x, y, size, 0, Math.PI * 2)

            canvas.fill()
            canvas.restore()

            step.size *= 1.05

            if (step.size > 100) {
                Vars.steps.splice(index, 1);
            }
        })
    }

    static heal_effect(canvas, args) {
        const [ x, y, hp ] = args;

        Vars.heals.forEach((healed, index) => {
            const { plus, type, dir, rot, x, y } = healed;
            const speed = .01;

            healed.alpha -= speed * 2;
            healed.plus += speed * rot;

            canvas.save();
            canvas.translate(x, y);
            canvas.rotate(dir + plus);

            canvas.globalAlpha = healed.alpha;
            canvas.drawImage(type, 0, 0, 80, 80);

            canvas.restore();

            if (healed.alpha < .06) {
                Vars.heals.splice(index, 1);
            }
        })
    }

    static health_bar(canvas) {
        const colors = Settings.colored_hp;
        const color = canvas.fillStyle === '#a4cc4f' ? colors.mine_health : colors.enemy_health;

        canvas.fillStyle = color
    }

    static display_hp(canvas, args) {
        const [ x, y, hp ] = args
        const health = Math.round(hp + 5)

        const content = `${health}%`
        const { width } = canvas.measureText(content)
        const text = [content, x + 30 - (health > 99 ? 2 : 0), y + 30]

        canvas.font = '20px Baloo Paaji'
        canvas.fillStyle = 'white'
        canvas.strokeStyle = '#404040';

        canvas.lineWidth = 6.5

        canvas.strokeText(...text)
        canvas.fillText(...text)
    }

    static weaponRange(canvas, range) {
        const width = Math.min(4, canvas.lineWidth);

        canvas.save()
        canvas.beginPath()
        canvas.strokeStyle = Settings.weapon_range.color || '#404040'
        canvas.globalAlpha = .5

        canvas.lineCap = Settings.weapon_range.cap ? 'round' : 'square';

        canvas.rotate(-Math.PI / 2) // left

        canvas.arc(0, 0, range - width, 0, Math.PI)

        canvas.stroke()
        canvas.restore()
    }

    static hitbox(canvas, radius, object, x = 0, y = 0, width = 0, height = 0) {
        canvas.save()
        canvas.beginPath()
        canvas.strokeStyle = Settings.hitbox.color || '#50C878';
        canvas.globalAlpha = object === 'trap' ? 1 : .6

        canvas.arc(x + width / 2, y + height / 2, radius, 0, Math.PI * 2)

        canvas.stroke()
        canvas.restore()
    }

    static particles(canvas) {
        const particleCount = 20
        const arcRadius = 5

        if (particlesArray.length === 0) {
            for (let i = 0; i < particleCount; i++) {
                const x = Math.random() * 440
                const y = Math.random() * 440

                particlesArray.push({
                    x: -220 + x,
                    y: -220 + y,
                    alpha: 1,
                    lifespan: Math.random() * 100 + 50
                })
            }
        }

        for (let i = particlesArray.length - 1; i >= 0; i--) {
            const particle = particlesArray[i]

            particle.alpha -= 1 / particle.lifespan
            if (particle.alpha <= 0) {
                particle.x = -220 + Math.random() * 400
                particle.y = -220 + Math.random() * 400
                particle.alpha = 1
                particle.lifespan = Math.random() * 100 + 50
            }

            // Draw particle
            canvas.beginPath()
            canvas.arc(particle.x, particle.y, arcRadius, 0, Math.PI * 2, false)
            canvas.fillStyle = `rgba(154, 113, 53, ${particle.alpha})`
            canvas.fill()
            canvas.closePath()
        }
    }
}

// [=]=> Ctx override
function getWeaponRange(src) {
    let range = 0

    weapons.forEach(weapon => {
        if (src.search(weapon) > 0) {
            const index = weapons.indexOf(weapon)

            range = ranges[index]
        }
    })

    return range;
}

const weapons = [ 'hammer', 'sword', 'spear', 'axe', 'shield', 'stick', 'katana', 'naginata', 'bat', 'chillrend', 'dagger', 'staff', 'secret', 'scythe' ];
const ranges = [ 80, 135, 160, 90, 55, 100, 140, 165, 115, 140, 80, 140, 115, 160 ]
const item_radius = {
    trap: 40,
    spike: 45,
    hard_spike: 45,
    big_spike: 42,
    boost: 40,
    wall: 45
}

const drawImage = CanvasRenderingContext2D.prototype.drawImage;
CanvasRenderingContext2D.prototype.drawImage = function (image, x, y, width, height) {
    const canvas = this;
    const check = image.src && image.src.search('inv') < 0;

    const isWeapon = check && weapons.some(item => image.src.search(item) > 0);

    if (isWeapon && Features.weapon_range) {
        const range = getWeaponRange(image.src);

        Functions.weaponRange(canvas, range);
    }

    if (!isWeapon && check && Features.hitbox) {
        const object = image.src.split('/')[5].split('.')[0]
        const radius = item_radius[object]

        const holding = image.src.includes('item');
        const args = holding ? [x, y, width, height] : [];

        if (radius) Functions.hitbox(canvas, radius, object, ...args);
    }

    if (!isWeapon && check && image.src.search('tornado') > 0 && Features.tornado_particles) {
        Functions.particles(canvas)
    }

    return drawImage.apply(this, arguments)
};

const strokeText = CanvasRenderingContext2D.prototype.strokeText;
CanvasRenderingContext2D.prototype.strokeText = function (text, x, y, maxWidth) { // name changer
    const name = Settings.name_changers[text]

    if (Features.name_changer && name) {
        arguments[0] = name;
    }

    return strokeText.apply(this, arguments)
}

const fillText = CanvasRenderingContext2D.prototype.fillText;
CanvasRenderingContext2D.prototype.fillText = function (text, x, y, maxWidth) {
    const canvas = this;

    // Healing effect!
    if (canvas.fillStyle === '#8ecc51' && Features.healing_effect) {
        const type = Player?.items?.includes(12) ? Vars.images.cookie : Vars.images.apple;
        const { x, y } = Player;

        const rot = Vars.rot || -1;
        Vars.rot ? delete Vars.rot : (Vars.rot = 1);

        const dir = Mouse.angle + (rot === -1 ? -.9 : 0);

        Vars.heals.push({ type, dir, rot, x, y, plus: 0, alpha: 1 });
    }

    // Name changer
    const name = Settings.name_changers[text]

    if (Features.name_changer && name) {
        arguments[0] = name;
    }

    return fillText.apply(this, arguments)
};

const fillRect = CanvasRenderingContext2D.prototype.fillRect;
CanvasRenderingContext2D.prototype.fillRect = function (x, y, width, height) {
    const canvas = this;
    const isBar = ['#a4cc4f', '#cc5151'].includes(canvas.fillStyle);

    if (canvas.fillStyle === '#a4cc4f') {
        // Makes hp bar smoother
        if (Features.smooth_hp) {
            const old = Vars.health || width;
            const smooth = Utils.lerp(old, width, .1)

            width = smooth

            Vars.health = smooth
        }

        // Heal effect disp ck
        Features.healing_effect && Functions.heal_effect(canvas, arguments);

        // Footsteps disp
        Features.footsteps && Functions.footsteps(canvas, arguments);
    }

    if (isBar) {
        // Change bar colors
        Features.colored_hp && Functions.health_bar(canvas);
        fillRect.apply(canvas, arguments);

        // Then display HP
        Features.display_hp && Functions.display_hp(canvas, arguments);
        return;
    }

    return fillRect.apply(this, arguments)
};

//[=]=> Apply window values
window.Tooltip = Tooltip;
window.MenuManager = MenuManager;
window.Settings = Settings;

const Player = new PlayerManager();
const Mouse = new MouseManager();

window.addEventListener('beforeunload', function () {
    Utils.ls_set('ehd_features', Features);
    Utils.ls_set('ehd_settings', Settings);
});

window.addEventListener('click', function (event) {
    const { target } = event;

    if (target.id === 'settings-menu') MenuManager.toggleSettings('', false);
});

//[=]=> Event listeners, dom load, etc
(function load() {
    if (Vars.loaded) return;
    Vars.loaded = true;

    Mouse.listeners();
    MenuManager.appendReplacer();

    // Appends each button to the menu
    let string = '';

    for (let featureID in Features) {
        const Feature = Features[featureID];
        const { name, icon, info } = All_features[featureID] || {};

        name && (string += `
            <div class="menu-button ${ Feature ? 'active' : '' }" role="button"
                 onmouseover="MenuManager.ToggleToolTip(this, 1)"
                 onmouseout="MenuManager.ToggleToolTip(this, 0)"
                 onmousedown="MenuManager.ToggleFeature(this, 1)"
                 onmouseup="MenuManager.ToggleFeature(this, 0)">
                <i class="bi bi-${icon}"></i>
                <span>${name}</span>
            </div>
        `);
    }

    document.querySelector('.body').innerHTML = string;

    // Appends features but to the setting selector
    string = '';

    for (let featureID in Features) {
        const Feature = Features[featureID];
        const { name, icon } = All_features[featureID] || {};

        name && (string += `
            <div class="settings-item setting-div-${featureID} ${Feature ? 'active' : ''}"
                 onmouseover="MenuManager.ToggleToolTip(this, 1)"
                 onmouseout="MenuManager.ToggleToolTip(this, 0)"
                 onclick="MenuManager.toggleSettings(this, true)">
                <i class="bi bi-${icon}"></i>
                <span style="display: none">${name}</span>
            </div>
        `);
    }

    document.querySelector('.settings-selector').innerHTML = string;

    function update() {
        // Hide ads, sry
        const rightAd = document.querySelector('#game-right-content-main');
        const leftAd = document.querySelector('#game-left-content-main');
        const downAd = document.querySelector('#game-bottom-content');

        const display = Features.hide_ads ? 'none' : 'block';

        rightAd.style.display = display;
        leftAd.style.display = display;
        downAd.style.display = display;

        // Night mode !
        const condition = Features.night_mode && Player.alive;
        const night = document.querySelector('.night-card');

        night.style.opacity = condition ? '1' : '0';

        setTimeout(() => {
            requestAnimationFrame(update);
        }, 1e2);
    }

    requestAnimationFrame(update);
})();

//yb!
//sry for unsemantic html!