Mod Panel for Shell Shockers

Feat. RAINBOW CROSSHAIR, FOG MOD, SKIN MOD, SKY COLOR MOD

// ==UserScript==
// @name         Mod Panel for Shell Shockers 
// @version      0.2
// @author       A3+++
// @description  Feat. RAINBOW CROSSHAIR, FOG MOD, SKIN MOD, SKY COLOR MOD
// @match        *://shellshock.io/*
// @namespace    https://greasyfork.org/users/815159
// @run-at       document-start
// @grant        none
// ==/UserScript==
(function () {
 
    const shellMod = {
        interval: null,
        gui: null,
        storedData: {
            scene: null,
            camera: null,
            reticle: null,
            rainbowCrosshairEnabled: false,
            colorDelta: 0.89,
            colorIdx: 0,
            colors: [[], [], []],
            skyColor: "#FFFFFF",
            skyBoxAlpha: 1,
            useSkyColor: false,
            fogDensity: 0.01,
            fogColor: "#FFFFFF",
        },
        replacements: {
            unlockSkins: {
                regex: /inventory\[[A-z]\].id===[A-z].id\)return!0;return!1/,
                replace: "rep = `${match[0]}||true`"
            },
            camera: {
                regex: /.push\(([A-z]+)\),\w+.maxZ=100/,
                replace: "rep = `${match[0]},window.modHelper.camera=${match[1]}`"
            },
            scene: {
                regex: /([A-z][A-z])\.fogDensity=.01\)/,
                replace: "rep = `${match[0]};window.modHelper.scene=${match[1]}`"
            },
            crosshairs: {
                regex: /document.getElementById\("reticleDot"\)/,
                replace: "rep = `${match[0]};window.modHelper.reticle=this;${atob('ZG9jdW1lbnQudGl0bGU=')}=atob('U2hlbGwgU2hvY2tlcnMgfCBNb2RkZWQgYnkgQTMgfCBieSBCbHVlIFdpemFyZCBEaWdpdGFs');`"
            }
        },
        updateSky: function () {
            if (!this.storedData.scene) return;
            let skyMesh = this.storedData.scene.getMeshByID("skyBox");
            if (skyMesh) {
                if (!skyMesh.oldTexture) skyMesh.oldTexture = skyMesh.material.reflectionTexture;
 
                if (this.storedData.useSkyColor) {
                    skyMesh.material.emissiveColor.set(...this.hexToRgb(this.storedData.skyColor));
                    skyMesh.material.reflectionTexture = null;
                    skyMesh.material.alpha = this.storedData.skyBoxAlpha;
 
                } else {
                    skyMesh.material.emissiveColor.set(...this.hexToRgb("#000000"));
                    skyMesh.material.reflectionTexture = skyMesh.oldTexture;
                    skyMesh.material.alpha = 1;
 
                }
            }
        },
        updateFog: function () {
            if (!this.storedData.scene) return;
 
            this.storedData.scene.fogColor.set(...this.hexToRgb(this.storedData.fogColor));
            this.storedData.scene.fogDensity = this.storedData.fogDensity;
        },
        hexToRgb: function (hex) {
            let result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
            return result ? [parseInt(result[1], 16) / 255, parseInt(result[2], 16) / 255, parseInt(result[3], 16) / 255] : [];
        },
        doHooks: function () {
            window.XMLHttpRequest = class extends window.XMLHttpRequest {
                constructor() {
                    super(...arguments);
                }
                open() {
                    if (arguments[1] && arguments[1].includes("shellshock.js")) this.scriptMatch = true;
 
                    super.open(...arguments);
                }
                get response() {
 
                    if (this.scriptMatch) {
                        let responseText = super.response;
 
 
                        let rep;
                        for (let key of Object.keys(shellMod.replacements)) {
 
                            let replacement = shellMod.replacements[key];
                            let match = responseText.match(replacement.regex);
                            if (match) responseText = responseText.replace(match[0], eval(replacement.replace));
                        }
 
                        return responseText;
                    }
                    return super.response;
                }
            };
 
        },
        createGUI: function () {
            this.gui = new guify({
                title: "<b>Mod Panel</b>",
                theme: "dark",
                align: "left",
                width: 300,
                barMode: "none",
                panelMode: "none",
                opacity: 0.90,
                root: window.container,
                open: true
            });
 
            this.gui.Register([{
                type: "folder",
                label: "Fog Controls",
                open: false
            }, {
                type: "folder",
                label: "Sky Color",
                open: false
            }, {
                type: "folder",
                label: "Rainbow Crosshair",
                open: false
            }]);
 
            this.gui.Register([{
                type: "checkbox",
                label: "Enabled",
                object: this.storedData,
                property: "useSkyColor",
                onChange: () => this.updateSky()
            }, {
                type: "color",
                label: "Sky Color:",
                format: "hexColor",
                object: this.storedData,
                property: "skyColor",
                onChange: () => this.updateSky()
            }, {
                type: "range",
                label: "Alpha:",
                min: 0, max: 1,
                object: this.storedData,
                property: "skyBoxAlpha",
                onChange: () => this.updateSky()
            }], {
                folder: "Sky Color"
            });
 
            this.gui.Register([{
                type: "range",
                label: "Fog Density:",
                min: 0, max: 1,
                object: this.storedData,
                property: "fogDensity",
                onChange: () => this.updateFog()
            }, {
                type: "color",
                label: "Fog Color:",
                format: "hexColor",
                object: this.storedData,
                property: "fogColor",
                onChange: () => this.updateFog()
            }], {
                folder: "Fog Controls"
            });
 
            this.gui.Register([{
                type: "checkbox",
                label: "Enabled:",
                object: this.storedData,
                property: "rainbowCrosshairEnabled",
            }, {
                type: "range",
                label: "Delta:",
                min: 0, max: 2.5,
                object: this.storedData,
                property: "colorDelta",
            }], {
                folder: "Rainbow Crosshair"
            });
 
            this.gui.Register({
                type: "title",
                label: "Created by A3+++"
            }).container.align = "center";
 
            this.gui.panel.menuButton.style.opacity = 0.3;
        },
        loadMod: function () {
            const addScript = function () {
                let script = document.createElement('script');
                script.onload = function () { shellMod.createGUI() };
                script.src = "https://unpkg.com/guify@0.12.0/lib/guify.min.js";
                document.body.appendChild(script);
            }
            document.body ? addScript() : document.addEventListener("DOMContentLoaded", addScript);
 
            this.doHooks();
 
            function HSVtoRGB(h, s, v) {
                var r, g, b, i, f, p, q, t;
                i = Math.floor(h * 6);
                f = h * 6 - i;
                p = v * (1 - s);
                q = v * (1 - f * s);
                t = v * (1 - (1 - f) * s);
                switch (i % 6) {
                    case 0: r = v, g = t, b = p; break;
                    case 1: r = q, g = v, b = p; break;
                    case 2: r = p, g = v, b = t; break;
                    case 3: r = p, g = q, b = v; break;
                    case 4: r = t, g = p, b = v; break;
                    case 5: r = v, g = p, b = q; break;
                }
                return { r: Math.round(r * 255), g: Math.round(g * 255), b: Math.round(b * 255) };
            }
 
            for (let wl = 0; wl < 100; wl++) {
                const { r, g, b } = HSVtoRGB(wl / 100.0 * 0.85, 1.0, 1.0);
 
                this.storedData.colors[0].push(r);
                this.storedData.colors[1].push(g);
                this.storedData.colors[2].push(b);
            }
 
            if (!this.interval) {
                this.interval = setInterval(function () {
                    if (shellMod.storedData.rainbowCrosshairEnabled && typeof extern !== "undefined" && extern.inGame) {
                        for (let i = 0; i < 4; i++) {
 
                            let ch = shellMod.storedData.reticle.crosshairs[i];
                            const idx = Math.mod(Math.floor(shellMod.storedData.colorIdx + 30 * i), 100);
 
                            const rgbString = `rgb(${shellMod.storedData.colors[0][idx]}, ${shellMod.storedData.colors[1][idx]}, ${shellMod.storedData.colors[2][idx]})`;
                            ch.style.backgroundColor = rgbString;
                            ch.style.color = rgbString;
 
                        }
 
                        shellMod.storedData.colorIdx += shellMod.storedData.colorDelta;
                        if (shellMod.storedData.colorIdx >= 100) shellMod.storedData.colorIdx = 0;
                    }
                    if (typeof window?.extern?.account !== "undefined" && typeof vueApp !== "undefined") {
                        if (!vueApp.isUpgraded || !extern.account.isSubscriber) { vueApp.setAccountUpgraded(true, ""); extern.account.isSubscriber = true; }
                    }
                }, 33);
            }
        }
 
    }
 
    window.modHelper = {
        set scene(c) { shellMod.storedData.scene = c },
        set camera(c) { shellMod.storedData.camera = c },
        set reticle(c) { shellMod.storedData.reticle = c }
    }
 
    shellMod.loadMod();
}())