Greasy Fork

Greasy Fork is available in English.

Shell Shockers Basic Aimbot + ESP: LibertyMutualV1

UPDATED FOR 0.50.0! Fed up of a popular script injecting ads into your game? Need a simple script to modify or use? FOSS ESP, Tracers and Aimbot. Hold right mouse button to aimlock.

// ==UserScript==
// @name         Shell Shockers Basic Aimbot + ESP: LibertyMutualV1
// @namespace    https://github.com/onlypuppy7/LibertyMutualShellShockers/
// @license      GPL-3.0
// @version      1.4.1
// @author       onlypuppy7
// @description  UPDATED FOR 0.50.0! Fed up of a popular script injecting ads into your game? Need a simple script to modify or use? FOSS ESP, Tracers and Aimbot. Hold right mouse button to aimlock.
// @match        https://shellshock.io/*
// @grant        none
// @run-at       document-start
// @icon         https://github.com/onlypuppy7/LibertyMutualShellShockers/blob/main/scripticon.jpg?raw=true
// @require      https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js
// @require      https://cdn.jsdelivr.net/npm/[email protected]/babylon.min.js
// ==/UserScript==

//Usage: Hold right mouse button to aimlock
//This script is more of a template than a functioning tool. If you're modifying this, you can add a GUI to start!

(function () {
    //intercept log
    const oldConsoleLog = console.log;
    const log = function(...args) {
        const argsNew = [
            "%c%s",
            `color: white; font-weight: bold; background:rgb(212, 212, 0); padding: 2px 6px; border-radius: 5px; margin-right: 5px;`,
            `LM`,
            ...args
        ];
        oldConsoleLog.apply(console, argsNew);
    };
    //create random number betwee 1 and 999
    const randomInt = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;
    let randomDebugKey = `debug${randomInt(9,999)}`;
    log("LM started??", randomDebugKey);

    // crackedshell is a script executor for chromebooks
    let crackedShell = typeof $WEBSOCKET !== 'undefined';

    let originalReplace = String.prototype.replace;

    String.prototype.originalReplace = function() {
        return originalReplace.apply(this, arguments);
    };

    const enableESP=true; //turn to false for off
    const enableTracers=true; //turn to false for off

    //Credit for script injection code: AI. ChatGPT prompt: "tampermonkey script. how can i make it grab a javascript file as it's loaded. if it detects the javascript file, make it apply modifications to it via regex? using XMLHttpRequest"
    //Credit for idea to use XMLHttpRequest: A3+++
    const useXHRMethod = false;

    if (useXHRMethod) {
        const originalXHROpen = XMLHttpRequest.prototype.open;
        const originalXHRGetResponse = Object.getOwnPropertyDescriptor(XMLHttpRequest.prototype, 'response');
        let shellshockjs
        XMLHttpRequest.prototype.open = function(...args) {
            const url = args[1];
            if (url && url.includes("js/shellshock.js")) {
                shellshockjs = this;
            };
            originalXHROpen.apply(this, args);
        };
        Object.defineProperty(XMLHttpRequest.prototype, 'response', {
            get: function() {
                if (this===shellshockjs) {
                    return applyLibertyMutual(originalXHRGetResponse.get.call(this));
                };
                return originalXHRGetResponse.get.call(this);
            }
        });
    };

    let _apc = HTMLElement.prototype.appendChild;
    let shellshock_og = null;

    HTMLElement.prototype.appendChild = function(node) {
        if (node.tagName === 'SCRIPT' && node.innerHTML && node.innerHTML.startsWith('(()=>{')) {
            shellshock_og = node.innerHTML;
            log("shellshock_og set");
            node.innerHTML = applyLibertyMutual(node.innerHTML);
        };
        return _apc.call(this, node);
    };
    
    const proto = unsafeWindow.HTMLScriptElement.prototype;
    const existing = Object.getOwnPropertyDescriptor(proto, "textContent");

    const original = existing || Object.getOwnPropertyDescriptor(unsafeWindow.Node.prototype, "textContent");

    Object.defineProperty(proto, "textContent", {
        get: function () {
            let textContent = original.get.call(this);
            if (textContent && textContent.startsWith('(()=>{')) {
                log("returning shellshock_og");
                return shellshock_og;
            } else {
                return textContent;
            };
        },
        set: original.set,
        configurable: true,
        enumerable: true
    });

    //Credit for event listener code: AI. ChatGPT prompt: "tampermonkey script. how can i intercept the addEventListener function and log the type of event, listener, and options?"
    const originalAddEventListener = EventTarget.prototype.addEventListener;
    // const eventCache = [];
    // unsafeWindow.__eventListenerCache = eventCache;

    EventTarget.prototype.addEventListener = function (type, listener, options) {
        try {
            const target = this;
            const tag = target.tagName || target.constructor.name;

            // eventCache.push({ target: tag, type, listener, options });

            // log(`Listener added: [${tag}] type=${type}, listener=${listener.name || 'anonymous'}, options=${JSON.stringify(options)}`);

            if (type == "pointermove" && listener.name == "real") {
                yawpitch.listener = listener;
                log("Gotcha. REAL pointermove listener detected.");
                
                const originalListener = listener;
                listener = function(event) {
                    yawpitch.listenerHook(event, originalListener);
                };
            };
        } catch (e) {
            console.warn('Event hook error:', e);
        };

        return originalAddEventListener.call(this, type, listener, options);
    };

    const yawpitch = {
        magicValue: 0.0025, // multiplier for mouse movement
        listener: null,
        movementsToApply: {
            x: 0,
            y: 0,
            reset: () => {
                yawpitch.movementsToApply.x = 0;
                yawpitch.movementsToApply.y = 0;
            },
        },
        listenerHook: (event, originalListener) => {
            //this is a mess of many failed ideas and i could clean this, but i feel it might be useful in the future

            // const deltaX = yawpitch.movementsToApply.x;
            // const deltaY = yawpitch.movementsToApply.y;

            // const proxyEvent = new Proxy(event, {
            //     get(target, prop) {
            //         if (prop === 'movementX') return target.movementX + deltaX;
            //         if (prop === 'movementY') return target.movementY + deltaY;
            //         if (prop === 'isTrusted') return true;
            //         return Reflect.get(target, prop);
            //     },
            // });

            console.log("YawPitch listener hook called with event:", event);
            originalListener.call(this, event);

            //uncomment for thing
            // const proxyEvent = {
            //     movementX: event.movementX + yawpitch.movementsToApply.x,
            //     movementY: event.movementY + yawpitch.movementsToApply.y,
            //     isTrusted: true,
            // };

            // // log("x:", proxyEvent.movementX, "y:", proxyEvent.movementY, "mX:", yawpitch.movementsToApply.x, "mY:", yawpitch.movementsToApply.y);
            // yawpitch.movementsToApply.reset();
    
            // // console.log("YawPitch listener hook called with event:", event);

            // originalListener.call(this, { 
            //     movementX: proxyEvent.movementX,
            //     movementY: proxyEvent.movementY,
            //     isTrusted: true
            // });
        },
        // fakeMovePointer: (force = false) => {
        //     if (!force && !(yawpitch.movementsToApply.x || yawpitch.movementsToApply.y)) {
        //         return;
        //     };
        //     const event = new PointerEvent('pointermove');
        //     yawpitch.listenerHook(event, yawpitch.listener);
        // },
        movePointer: (movementX = 0, movementY = 0) => {
            yawpitch.setMouseParams();

            movementX = Math.ceil(movementX);
            movementY = Math.ceil(movementY);

            yawpitch.listener({ //direct call will bypass the hook
                movementX,
                movementY,
                x: 1,
                isTrusted: true,
            });

            yawpitch.getAndSetYawPitch();
        },
        getAndSetYawPitch: (viaWasm = true) => {
            if (viaWasm) {
                const result = unsafeWindow.get_yaw_pitch();
                ss.MYPLAYER[H.yaw] = result.yaw;
                ss.MYPLAYER[H.pitch] = result.pitch;
                ss.MYPLAYER[H.coords] = result.coords;
                return result;
            } else {
                return {
                    yaw: ss.MYPLAYER[H.yaw],
                    pitch: ss.MYPLAYER[H.pitch],
                    coords: ss.MYPLAYER[H.coords]
                };
            };
        },
        setMouseParams: (mouseSpeed = 50, mouseInvert = 0, scopeFov = 0.9, scope = false, uniqueId = ss.MYPLAYER[H.uniqueId]) => {
            unsafeWindow.set_mouse_params(
                mouseSpeed,
                mouseInvert, 
                scopeFov, //ss.MYPLAYER[H.weapon][H.actor].scopeFov
                scope, //ss.MYPLAYER.scope
                uniqueId
            );
        },
        changeByMovement: (x = 0, y = 0) => {
            yawpitch.setMouseParams();

            log("Changing yaw and pitch by movement:", x, y);

            yawpitch.movePointer(x, y);

            // yawpitch.movementsToApply.x = x;
            // yawpitch.movementsToApply.y = y;
            // yawpitch.fakeMovePointer();
        },
        changeByYawPitchDiff: (yaw = 0, pitch = 0) => {
            yawpitch.changeByMovement(
                yaw   / yawpitch.magicValue,
                pitch / yawpitch.magicValue
            );
        },
        radianAngleDiff: (angle1 = 0, angle2 = 0) => {
            const fullCircle = 2 * Math.PI;
            // Normalize angles to be within [0, 2π]
            angle1 = (angle1 % fullCircle + fullCircle) % fullCircle;
            angle2 = (angle2 % fullCircle + fullCircle) % fullCircle;
            // Find the absolute angular difference
            let diff = Math.abs(angle1 - angle2);
            // Ensure the difference is within [0, π)
            diff = Math.min(diff, fullCircle - diff);
            // Determine the sign of the difference correctly
            if ((angle1 - angle2 + fullCircle) % fullCircle > Math.PI) {
                return -diff;
            } else {
                return diff;
            };
        },
        setToYawPitch: (yaw = 0, pitch = 0) => {
            const yawDiff = yawpitch.radianAngleDiff(ss.MYPLAYER[H.yaw], yaw);
            const pitchDiff = yawpitch.radianAngleDiff(ss.MYPLAYER[H.pitch], pitch);

            // log("Setting yaw and pitch:", yaw, pitch, "Diffs:", yawDiff, pitchDiff);

            yawpitch.changeByYawPitchDiff(yawDiff, pitchDiff);
        },
        getCoordsForYawPitch: (yaw = 0, pitch = 0) => { //useful for silent
            const starting = yawpitch.getAndSetYawPitch(false);
            yawpitch.setToYawPitch(yaw, pitch);
            const atDesired = yawpitch.getAndSetYawPitch(false);
            yawpitch.setToYawPitch(starting.yaw, starting.pitch);

            //for testing
            // const ending = yawpitch.getAndSetYawPitch(false);
            // console.log("Starting:", starting, "At desired:", atDesired, "Ending:", ending);

            return atDesired;
        },
    };

    //VAR STUFF
    let F=[];
    let H={};
    let functionNames=[];
    let ESPArray=[];
    let RMB=false;

    //Credit: AI. ChatGPT prompt: "make javascript tampermonkey code that sets a variable RMB to true while right mouse button is being held"
    document.addEventListener('mousedown', function(event) {
        if (event.button === 2) {
            RMB = true;
        };
    }, true);

    document.addEventListener('mouseup', function(event) {
        if (event.button === 2) {
            RMB = false;
        };
    }, true);

    //scrambled... geddit????
    const getScrambled=function(){return Array.from({length: 10}, () => String.fromCharCode(97 + Math.floor(Math.random() * 26))).join('')}
    const createAnonFunction=function(name,func){
        const funcName=getScrambled();
        window[funcName]=func;
        F[name]=window[funcName];
        functionNames[name]=funcName
    };
    const findKeyWithProperty = function(obj, propertyToFind) {
        for (const key in obj) {
            if (obj.hasOwnProperty(key)) {
                if (key === propertyToFind) {
                    return [key];
                } else if (
                    typeof obj[key] === 'object' &&
                    obj[key] !== null &&
                    obj[key].hasOwnProperty(propertyToFind)
                ) {
                    return key;
                };
            };
        };
        // Property not found
        return null;
    };
    const fetchTextContent = function(url) {
        var xhr = new XMLHttpRequest();
        xhr.open('GET', url, false); // Make the request synchronous
        xhr.send();
        if (xhr.status === 200) {
            return xhr.responseText;
        } else {
            console.error("Error fetching text content. Status:", xhr.status);
            return null;
        };
    };

    const applyLibertyMutual = function(js) {
        // support crackedshell's harsh rewriting system
        // more info @ https://github.com/VillainsRule/CrackedShell
        let clientKeyJS = js;
        // if (crackedShell) clientKeyJS = fetchTextContent('/js/shellshock.og.js');

        // let hash = CryptoJS.SHA256(clientKeyJS).toString(CryptoJS.enc.Hex);
        let clientKeys;
        onlineClientKeys = fetchTextContent("https://raw.githubusercontent.com/StateFarmNetwork/client-keys/main/libertymutual_latest.json"); //credit: me :D
        // onlineClientKeys = fetchTextContent("https://raw.githubusercontent.com/StateFarmNetwork/client-keys/main/libertymutual_"+hash+".json"); //credit: me :D

        if (onlineClientKeys == "value_undefined" || onlineClientKeys == null) {
            let userInput = prompt('Valid keys could not be retrieved online. Enter keys if you have them. Join the StateFarm Network Discord server to generate keys! https://discord.gg/HYJG3jXVJF', '');
            if (userInput !== null && userInput !== '') {
                alert('Aight, let\'s try this. If it is invalid, it will just crash.');
                clientKeys = JSON.parse(userInput);
            } else {
                alert('You did not enter anything, this is gonna crash lmao.');
            };
        } else {
            clientKeys = JSON.parse(onlineClientKeys);
        };

        H = clientKeys.vars;

        let injectionString="";
        
        const modifyJS = function(find,replace) {
            let oldJS = js;
            js = js.originalReplace(find,replace);
            if (oldJS !== js) {
                log("%cReplacement successful! Injected code: "+replace, 'color: green; font-weight: bold; font-size: 0.6em; text-decoration: italic;');
            } else {
                log("%cReplacement failed! Attempted to replace "+find+" with: "+replace, 'color: red; font-weight: bold; font-size: 0.6em; text-decoration: italic;');
            };
        };

        log('%cATTEMPTING TO START LIBERTYMUTUAL', 'color: magenta; font-weight: bold; font-size: 1.5em; text-decoration: underline;');
        const variableNameRegex = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;
        for (let name in H) {
            deobf = H[name];
            if (variableNameRegex.test(deobf)) {
                injectionString = `${injectionString}${name}: (() => { try { return ${deobf}; } catch (error) { return "value_undefined"; } })(),`;
            } else {
                alert("Message from the LibertyMutual Devs: WARNING! The keys inputted contain non-variable characters! There is a possibility that this could run code unintended by the LibertyMutual team, although possibly there is also a mistake. Do NOT proceed with using this, and report to the LibertyMutual developers what is printed in the console.");
                log("REPORT THIS IN THE DISCORD SERVER:", clientKeys);
                const crashplease = "balls";
                crashplease = "balls2";
            };
        };
        log(injectionString);
        log('%cLIBERTYMUTUAL INJECTION: INJECT VAR RETRIEVAL FUNCTION AND MAIN LOOP', 'color: yellow; font-weight: bold; font-size: 1.2em; text-decoration: underline;');
        modifyJS(H.SCENE+'.render',`window["${functionNames.retrieveFunctions}"]({${injectionString}},true)||${H.SCENE}.render`);
        log('%cSuccess! Variable retrieval and main loop hooked.', 'color: green; font-weight: bold;');
        modifyJS(`{if(${H.CULL})`,`{if(true)`);
        log('%cSuccess! Cull inhibition hooked.', 'color: green; font-weight: bold;');
        modifyJS("Not playing in iframe", "LIBERTYMUTUAL ACTIVE!");
        // log(js);
        log(H);
        return js;
    };

    let ss = {}; //skvll this wasnt here so it was global skvll
    createAnonFunction("retrieveFunctions",function(vars) { 
        Object.assign(ss, vars);
        F.LIBERTYMUTUAL();
    });

    const tracersKey = getScrambled();

    const createOrUpdateTracer = (PLAYER, CROSSHAIRS) => {
        const points = [
            PLAYER[H.actor][H.mesh].position.clone(),
            CROSSHAIRS.clone()
        ];
        points[0].y += 0.4;

        if (!PLAYER[tracersKey]) {
            PLAYER[tracersKey] = BABYLON.MeshBuilder.CreateLines(getScrambled(), { points, updatable: true }, ss.SCENE);
            PLAYER[tracersKey].isPickable = false;
            PLAYER[tracersKey].alwaysSelectAsActiveMesh = true;
            PLAYER[tracersKey].doNotSyncBoundingInfo = true;
            PLAYER[tracersKey][H.renderingGroupId] = 1;
            PLAYER[tracersKey].visibility = true;
        } else {
            BABYLON.MeshBuilder.CreateLines(undefined, {
                points,
                instance: PLAYER[tracersKey],
                updatable: true
            });
        };

        PLAYER[tracersKey].visibility = (PLAYER[H.playing] && enableTracers);
        return PLAYER[tracersKey];
    };

    createAnonFunction("LIBERTYMUTUAL",function() {
        // globalSS = ss;
        
        ss.PLAYERS.forEach(PLAYER=>{
            if (PLAYER.hasOwnProperty("ws")) {
                ss.MYPLAYER = PLAYER
            };
        });

        H.actor = findKeyWithProperty(ss.MYPLAYER,H.mesh);

        let TARGETED;
        let CROSSHAIRS=new BABYLON.Vector3();
        CROSSHAIRS.copyFrom(ss.MYPLAYER[H.actor][H.mesh].position);

        // eye level
        CROSSHAIRS.y += 0.4;
        const forwardOffset = -5; 
        const yaw = ss.MYPLAYER[H.yaw];
        const pitch = -ss.MYPLAYER[H.pitch];
        const forwardX = Math.sin(yaw) * Math.cos(pitch);
        const forwardY = Math.sin(pitch);
        const forwardZ = Math.cos(yaw) * Math.cos(pitch);
        CROSSHAIRS.x += forwardX * forwardOffset;
        CROSSHAIRS.y += forwardY * forwardOffset;
        CROSSHAIRS.z += forwardZ * forwardOffset;

        const timecode=Date.now();
        let minValue=99999;
        ss.PLAYERS.forEach(PLAYER=>{
            if (PLAYER) {
                PLAYER.timecode=timecode;
                //Partial credit for enemy player filtering: PacyTense. Also just common sense.
                if ((PLAYER!==ss.MYPLAYER) && ((ss.MYPLAYER.team==0)||(PLAYER.team!==ss.MYPLAYER.team))) {
                    //ESP CODE
                    if ((!PLAYER.generatedESP)) {
                        //Credit for box from lines code: AI. ChatGPT prompt: "how can i create a box out of lines in babylon.js?"
                        //ESP BOXES
                        const boxSize = {width: 0.4, height: 0.65, depth: 0.4};
                        const vertices = [
                            new BABYLON.Vector3(-boxSize.width / 2, 0, -boxSize.depth / 2),
                            new BABYLON.Vector3(boxSize.width / 2, 0, -boxSize.depth / 2),
                            new BABYLON.Vector3(boxSize.width / 2, 0 + boxSize.height, -boxSize.depth / 2),
                            new BABYLON.Vector3(-boxSize.width / 2, 0 + boxSize.height, -boxSize.depth / 2),
                            new BABYLON.Vector3(-boxSize.width / 2, 0, boxSize.depth / 2),
                            new BABYLON.Vector3(boxSize.width / 2, 0, boxSize.depth / 2),
                            new BABYLON.Vector3(boxSize.width / 2, 0 + boxSize.height, boxSize.depth / 2),
                            new BABYLON.Vector3(-boxSize.width / 2, 0 + boxSize.height, boxSize.depth / 2),
                        ];
                        const lines = [];
                        for (let i = 0; i < 4; i++) {
                            lines.push([vertices[i], vertices[(i + 1) % 4]]);
                            lines.push([vertices[i + 4], vertices[(i + 1) % 4 + 4]]);
                            lines.push([vertices[i], vertices[i + 4]]);
                        };
                        const box = BABYLON.MeshBuilder.CreateLineSystem(getScrambled(), { lines }, ss.SCENE);
                        //ChatGPT prompt: "how can i make an object anchored to another object, change its color, and have it render on top of everything else? babylon.js"
                        box.color = new BABYLON.Color3(1, 1, 1);
                        box[H.renderingGroupId] = 1;
                        box.parent=PLAYER[H.actor][H.mesh];
                        
                        PLAYER.box=box;
                        PLAYER.generatedESP=true;
                        ESPArray.push([box,createOrUpdateTracer(PLAYER, CROSSHAIRS),PLAYER]);
                    };
                    
                    createOrUpdateTracer(PLAYER, CROSSHAIRS);

                    PLAYER.box.visibility=enableESP;
                    PLAYER[tracersKey].visibility=(PLAYER[H.playing]&&enableTracers);

                    //AIMBOT CODE
                    //Credit: This section is mostly common sense, and could be made by most decent programmers. It is still worth mentioning PacyTense used a functionally equivalent thing similar to this this before me 4 years ago.
                    const distance=Math.hypot(PLAYER[H.x]-ss.MYPLAYER[H.x], PLAYER[H.y]-ss.MYPLAYER[H.y], PLAYER[H.z]-ss.MYPLAYER[H.z]);

                    if (distance<minValue) {
                        TARGETED=PLAYER;
                        minValue=distance;
                    };
                };
            };
        });
        //im gonna kms why was this in the player loop
        if (RMB && TARGETED && TARGETED[H.playing]) {
            //3D maths
            const directionVector={
                [H.x]: -(TARGETED[H.x]-ss.MYPLAYER[H.x]),
                [H.y]: -(TARGETED[H.y]-ss.MYPLAYER[H.y]-0.05),
                [H.z]: -(TARGETED[H.z]-ss.MYPLAYER[H.z]),
            };
            // console.log("Direction vector:", directionVector, "Yaw:", F.calculateYaw(directionVector), "Pitch:", F.calculatePitch(directionVector));
            yawpitch.setToYawPitch(
                F.calculateYaw(directionVector),
                F.calculatePitch(directionVector)
            );
            // ss.MYPLAYER[H.yaw]=F.calculateYaw(directionVector);
            // ss.MYPLAYER[H.pitch]=F.calculatePitch(directionVector);
        };
        for ( let i=0;i<ESPArray.length;i++) {
            if (ESPArray[i][2] && ESPArray[i][2].timecode==timecode) { //still exists
            } else {
                //Credit for info: AI. ChatGPT prompt: "how can i delete an object in babylon.js?"
                ESPArray[i][0].dispose();
                ESPArray[i][1].dispose();
                ESPArray.splice(i,1);
            };
        };

        if (unsafeWindow[randomDebugKey]) {
            unsafeWindow.globalSS = {
                ss, F, H, functionNames, cross: {
                    CROSSHAIRS, yaw, pitch
                }, BABYLON, TARGETED, ESPArray, RMB, timecode, createOrUpdateTracer, tracersKey, yawpitch
            };
        };

        // log("Main loop executed.");
    });
    createAnonFunction("setPrecision",function (value) { return Math.floor(value * 8192) / 8192 }); //required precision
    createAnonFunction("calculateYaw",function (pos) {
        return F.setPrecision(Math.mod(Math.atan2(pos[H.x],pos[H.z]), Math.PI2));
    });
    createAnonFunction("calculatePitch",function (pos) {
        return F.setPrecision(-Math.atan2(pos[H.y],Math.hypot(pos[H.x],pos[H.z]))%1.5);
    });
})();