您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Some useful mods for Shell Shockers, including infinite history, FOV and more. Bindable too.
当前为
// ==UserScript== // @name ShellFarm - Utilities for Shell Shockers. // @description Some useful mods for Shell Shockers, including infinite history, FOV and more. Bindable too. // @author onlypuppy7 // @namespace https://github.com/onlypuppy7/ShellFarmClientShellShockers/ // @supportURL https://github.com/onlypuppy7/ShellFarmClientShellShockers/issues/ // @license GPL-3.0 // @run-at document-start // @grant GM_info // @icon https://github.com/onlypuppy7/ShellFarmClientShellShockers/blob/main/icon.png?raw=true // @require https://cdn.jsdelivr.net/npm/[email protected]/dist/tweakpane.min.js // version naming: //3.#.#-pre[number] for development versions, increment for every commit (not full release) //3.#.#-release for release //this ensures that each version of the script is counted as different // @version 1.0.4 // @match *://shellshock.io/* // @match *://algebra.best/* // @match *://algebra.vip/* // @match *://biologyclass.club/* // @match *://deadlyegg.com/* // @match *://deathegg.world/* // @match *://eggboy.club/* // @match *://eggboy.xyz/* // @match *://eggcombat.com/* // @match *://egg.dance/* // @match *://eggfacts.fun/* // @match *://egghead.institute/* // @match *://eggisthenewblack.com/* // @match *://eggsarecool.com/* // @match *://geometry.best/* // @match *://geometry.monster/* // @match *://geometry.pw/* // @match *://geometry.report/* // @match *://hardboiled.life/* // @match *://hardshell.life/* // @match *://humanorganising.org/* // @match *://mathactivity.xyz/* // @match *://mathactivity.club/* // @match *://mathdrills.info/* // @match *://mathdrills.life/* // @match *://mathfun.rocks/* // @match *://mathgames.world/* // @match *://math.international/* // @match *://mathlete.fun/* // @match *://mathlete.pro/* // @match *://overeasy.club/* // @match *://scrambled.tech/* // @match *://scrambled.today/* // @match *://scrambled.us/* // @match *://scrambled.world/* // @match *://shellshockers.club/* // @match *://shellshockers.life/* // @match *://shellshockers.site/* // @match *://shellshockers.us/* // @match *://shellshockers.world/* // @match *://shellshockers.xyz/* // @match *://shellsocks.com/* // @match *://softboiled.club/* // @match *://urbanegger.com/* // @match *://violentegg.club/* // @match *://violentegg.fun/* // @match *://yolk.best/* // @match *://yolk.life/* // @match *://yolk.rocks/* // @match *://yolk.tech/* // @match *://yolk.quest/* // @match *://yolk.today/* // @match *://zygote.cafe/* // ==/UserScript== (function () { //script info const name="ShellFarm"; const version=GM_info.script.version; const menuTitle=name + " v" + version; //startup sequence const startUp=function () { mainLoop() injectScript() document.addEventListener("DOMContentLoaded", function () { initMenu(); applyStylesAddElements(); //set font and change menu cass, and other stuff to do with the page const intervalId1 = setInterval(everySecond, 1000); const intervalId2 = setInterval(everyDecisecond, 100); }); }; //INIT WEBSITE LINKS: store them here so they are easy to maintain and update! const discordURL = "https://discord.gg/mPa95HB7Q6"; //INIT VARS unsafeWindow.newGame=false let binding=false; const allModules=[]; const allFolders=[]; const F=[]; const functionNames=[]; const isKeyToggled={}; let onlinePlayersArray=[]; let bindsArray={}; const H={}; // obfuscated shit lol const tp={}; // <-- tp = tweakpane let ss,msgElement,resetModules,noPointerPause,playersInGame,coordElement,gameInfoElement,playerstatsElement,ranOneTime,lastWeaponBox,lastChatItemLength,configMain; let previousDetail; //menu interaction functions const extract = function (variable,shouldUpdate) { if (shouldUpdate) {updateConfig()}; return configMain[variable]; }; const beginBinding = function (value) { if (binding == false) { binding=value; tp[binding+"BindButton"].title="PRESS KEY"; }; }; const change = function (module,newValue) { //its important to note that every module must have a unique name const labels = document.querySelectorAll('.tp-lblv_l'); const moduleButton=module+"Button"; const moduleLabel=tp[moduleButton].label; for (const label of labels) { if (label.textContent.includes(moduleLabel)) { const inputContainer = label.nextElementSibling; const currentValue=extract(module); // check for checkbox const checkbox = inputContainer.querySelector('.tp-ckbv_i'); if (checkbox) { if (newValue==undefined) { newValue=(!currentValue); }; if (newValue!==!(!currentValue)) { checkbox.click(); // Toggle checkbox }; console.log(module,"checkbox",currentValue,newValue); return extract(module,true); }; // check for button const button = inputContainer.querySelector('.tp-btnv_b'); if (button) { button.click(); // Trigger button click console.log(module,"button",currentValue,newValue); return ("NOMSG"); //no change of state, dont show pop up message }; // check for dropdown const dropdown = inputContainer.querySelector('.tp-lstv_s'); if (dropdown) { if (newValue==undefined) { //if youre going to set a list to a certain value, use the int value of the list item newValue=(dropdown.selectedIndex+1) % dropdown.options.length; }; dropdown.selectedIndex = newValue; dropdown.dispatchEvent(new Event('change')); // trigger change event for dropdown console.log(module,"dropdown",currentValue,newValue); return extract(module,true); }; // check for text input const textInput = inputContainer.querySelector('.tp-txtv_i'); if (textInput) { textInput.value = newValue; textInput.dispatchEvent(new Event('change')); // trigger change event for dropdown return extract(module,true); }; }; }; }; const findKeyByValue = function(obj, value) { for (const key in obj) { if (obj[key] === value) { return key; }; }; return null; // Return null if the value is not found }; document.addEventListener('mousedown', function (event) { if (event.button === 2) { isRightButtonDown = true; } else if (event.button === 0) { isLeftButtonDown = true; }; }); document.addEventListener('mouseup', function (event) { if (event.button === 2) { isRightButtonDown = false; } else if (event.button === 0) { isLeftButtonDown = false; }; }); //menu document.addEventListener("keydown", function (event) { event=(event.code.replace("Key","")); isKeyToggled[event]=true; if (event=="Escape") { noPointerPause=false; unsafeWindow.document.onpointerlockchange() }; }); document.addEventListener("keyup", function (event) { event=(event.code.replace("Key","")); isKeyToggled[event]=false; if (document.activeElement&&document.activeElement.tagName==='INPUT' ) { return; } else if (binding!=false) { if (event=="Delete") { event="Set Bind" }; tp[binding+"BindButton"].title=event; bindsArray[binding]=event; localStorage.setItem(binding+"Bind",JSON.stringify(event)); createPopup("Binded "+tp[binding+"Button"].label+" to key: "+event); binding=false; } else { Object.keys(bindsArray).forEach(function (module) { if ((bindsArray[module] == event) && module!="zoom") { let state=change(module) let popupText=state if (state!="NOMSG") { if (state===true||state===false||state===undefined) {state=(state?"ON":"OFF")}; popupText="Set "+module+" to: "+state; } else { switch (module) { case ("hide"): popupText="Toggled ShellFarm Panel"; break; case ("panic"): popupText="Exiting to set URL..."; break; }; }; createPopup(popupText); }; }); }; }); const initTab = function(tab) { tp[tab.storeAs]=tab.location.addTab({ pages: [ {title: 'Modules'}, {title: 'Binds'}, ], }); }; const initFolder = function(folder) { tp[folder.storeAs]=folder.location.addFolder({ title: folder.title, expanded: JSON.parse(localStorage.getItem(folder.storeAs)) !== null ? JSON.parse(localStorage.getItem(folder.storeAs)) : false }); allFolders.push(folder.storeAs); }; const initModule = function (module) { const value={}; value[module.storeAs]=(module.defaultValue !== undefined ? module.defaultValue : false); if (!(module.slider&&module.slider.step)) {module.slider={}}; const config={ label: module.title, options: module.dropdown, min: module.slider.min, max: module.slider.max, step: module.slider.step, title: module.button, }; if (module.button) { tp[(module.storeAs+"Button")]=module.location.addButton({ label: module.title, title: module.button, }).on("click", (value) => { if (module.clickFunction!==undefined) {module.clickFunction(value)}; if (module.botParam!==undefined) {updateBotParams(module.botParam)}; }); } else if (module.monitor) { monitorObjects[module.storeAs]="Text Goes Here"; tp[(module.storeAs+"Button")]=module.location.addMonitor(monitorObjects,module.storeAs,{ label: '', expanded: true, multiline: true, lineCount: module.monitor, }); setInterval(() => { tp[(module.storeAs+"Button")].refresh(); }, 1000); } else { tp[(module.storeAs+"Button")]=module.location.addInput(value,module.storeAs,config ).on("change", (value) => { if (module.changeFunction!==undefined) {module.changeFunction(value)}; if (module.botParam!==undefined) { setTimeout(() => { updateBotParams(module.botParam); }, 500); }; setTimeout(() => { saveConfig(); }, 500); }); }; allModules.push(name.replace("Button","")); if (module.bindLocation) {initBind(module)}; }; const initBind = function (module) { if (resetModules) { localStorage.removeItem(module.storeAs+"Bind") }; const theBind=(JSON.parse(localStorage.getItem(module.storeAs+"Bind")) || module.defaultBind || "Set Bind"); tp[(module.storeAs+"BindButton")]=module.bindLocation.addButton({ label: module.title, title: theBind, }).on("click", (value) => { beginBinding(module.storeAs); }); bindsArray[module.storeAs]=theBind; }; const initMenu = function (reset) { //INIT MENU //init tp.mainPanel resetModules = reset; if (tp.mainPanel) { tp.mainPanel.dispose() }; tp.mainPanel = new Tweakpane.Pane(); tp.mainPanel.title = menuTitle; //RENDER MODULES initFolder({ location: tp.mainPanel, title: "Render", storeAs: "renderFolder",}); initTab({ location: tp.renderFolder, storeAs: "renderTab" }); initModule({ location: tp.renderTab.pages[0], title: "FOV", storeAs: "fov", slider: {min: 0, max: 360, step: 3}, defaultValue: 72,}); initModule({ location: tp.renderTab.pages[0], title: "Zoom FOV", storeAs: "zoom", slider: {min: 0, max: 72, step: 1}, defaultValue: 15, bindLocation: tp.renderTab.pages[1], defaultBind: "C",}); tp.renderTab.pages[0].addSeparator(); initModule({ location: tp.renderTab.pages[0], title: "Egg Size", storeAs: "eggSize", slider: {min: 0, max: 10, step: 0.25}, defaultValue: 1,}); tp.renderTab.pages[0].addSeparator(); initModule({ location: tp.renderTab.pages[0], title: "Set Detail", storeAs: "setDetail", bindLocation: tp.renderTab.pages[1], dropdown: [{text: "Disabled", value: "disabled"}, {text: "Auto Detail", value: "autodetail"}, {text: "No Details", value: "nodetails"}, {text: "Shadows", value: "shadows"}, {text: "High Res", value: "highres"}, {text: "Shadows+High Res", value: "shadowshighres"}], defaultValue: "disabled"}); initModule({ location: tp.renderTab.pages[0], title: "Textures", storeAs: "enableTextures", bindLocation: tp.renderTab.pages[1], defaultValue: true,}); //HUD MODULES initFolder({ location: tp.mainPanel, title: "HUD", storeAs: "hudFolder",}); initTab({ location: tp.hudFolder, storeAs: "hudTab" }); initModule({ location: tp.hudTab.pages[0], title: "Co-ords", storeAs: "showCoordinates", bindLocation: tp.hudTab.pages[1],}); initModule({ location: tp.hudTab.pages[0], title: "HP Display", storeAs: "playerStats", bindLocation: tp.hudTab.pages[1],}); initModule({ location: tp.hudTab.pages[0], title: "GameInfo", storeAs: "gameInfo", bindLocation: tp.hudTab.pages[1],}); //CHAT MODULES initFolder({ location: tp.mainPanel, title: "Chat", storeAs: "chatFolder",}); initTab({ location: tp.chatFolder, storeAs: "chatTab" }); initModule({ location: tp.chatTab.pages[0], title: "InfiniHistory", storeAs: "chatExtend", bindLocation: tp.chatTab.pages[1],}); initModule({ location: tp.chatTab.pages[0], title: "HighlightTxt", storeAs: "chatHighlight", bindLocation: tp.chatTab.pages[1],}); initModule({ location: tp.chatTab.pages[0], title: "Max Ingame", storeAs: "maxChat", slider: {min: 0, max: 30, step: 1}, defaultValue: 5,}); initModule({ location: tp.chatTab.pages[0], title: "ShowFiltered", storeAs: "disableChatFilter", bindLocation: tp.chatTab.pages[1],}); tp.chatTab.pages[0].addSeparator(); initFolder({ location: tp.chatTab.pages[0], title: "Join/Leave Msgs Options", storeAs: "joinLeaveFolder",}); initModule({ location: tp.joinLeaveFolder, title: "Join Msgs", storeAs: "joinMessages", bindLocation: tp.chatTab.pages[1],}); initModule({ location: tp.joinLeaveFolder, title: "Leave Msgs", storeAs: "leaveMessages", bindLocation: tp.chatTab.pages[1],}); //MISC MODULES initFolder({ location: tp.mainPanel, title: "Misc", storeAs: "miscFolder",}); initTab({ location: tp.miscFolder, storeAs: "miscTab" }) initModule({ location: tp.miscTab.pages[0], title: "Unlock Skins", storeAs: "unlockSkins", bindLocation: tp.miscTab.pages[1],}); tp.miscTab.pages[0].addSeparator(); initModule({ location: tp.miscTab.pages[0], title: "Switch Focus", storeAs: "unfocus", bindLocation: tp.miscTab.pages[1], button: "FOCUS/UNFOCUS", defaultBind: "P", clickFunction: function(){ if (document.pointerLockElement !== null) { //currently locked noPointerPause=true; unsafeWindow.document.exitPointerLock(); } else if (noPointerPause) { //already unlocked? noPointerPause=false; canvas.requestPointerLock(); }; },}); //CLIENT MODULES initFolder({ location: tp.mainPanel, title: "Client & About", storeAs: "clientFolder",}); initTab({ location: tp.clientFolder, storeAs: "clientTab" }) initModule({ location: tp.clientTab.pages[0], title: "Hide GUI", storeAs: "hide", bindLocation: tp.clientTab.pages[1], button: "Hide!", clickFunction: function(){tp.mainPanel.hidden=!tp.mainPanel.hidden}, defaultBind:"H",}); initModule({ location: tp.clientTab.pages[0], title: "Pop-ups", storeAs: "popups", bindLocation: tp.clientTab.pages[1], defaultValue: true,}); tp.clientTab.pages[0].addSeparator(); initModule({ location: tp.clientTab.pages[0], title: "Panic", storeAs: "panic", bindLocation: tp.clientTab.pages[1], button: "EXIT!", clickFunction: function(){if (extract("enablePanic")) { unsafeWindow.location.replace(extract("panicURL")) }}, defaultBind:"X",}); initFolder({ location: tp.clientTab.pages[0], title: "Panic Options", storeAs: "panicFolder",}); initModule({ location: tp.panicFolder, title: "Enable", storeAs: "enablePanic", bindLocation: tp.clientTab.pages[1], defaultValue: true,}); initModule({ location: tp.panicFolder, title: "Set URL", storeAs: "panicURL", defaultValue: "https://classroom.google.com/",}); tp.clientTab.pages[0].addSeparator(); initModule({ location: tp.clientTab.pages[0], title: "Discord", storeAs: "discord", button: "Link", clickFunction: function(){unsafeWindow.open(discordURL)},}); tp.clientTab.pages[0].addSeparator(); initModule({ location: tp.clientTab.pages[0], title: "Reset", storeAs: "clear", button: "DELETE", clickFunction: function(){ const userConfirmed=confirm("Are you sure you want to continue? This will clear all stored module states and keybinds."); if (userConfirmed) { initMenu(true); userConfirmed=alert("Reset to defaults."); }; },}); tp.mainPanel.addSeparator(); if ((!localStorage.getItem("ShellFarmConfigMainPanel")) || reset) { saveConfig(); } else { console.log("##############################################") tp.mainPanel.importPreset(JSON.parse(localStorage.getItem("ShellFarmConfigMainPanel"))); }; updateConfig(); makeDraggable(tp.mainPanel.containerElem_); }; //visual functions const createPopup = function (text,type) { console.log("Creating Popup Type:",type,"With Text:",text); try { if (extract("popups")) { const messageContainer = document.getElementById('message-container'); const messages = messageContainer.getElementsByClassName('msg'); if (messages.length > 5) { messageContainer.removeChild(messages[0]); }; const clonedMsgElement = msgElement.cloneNode(true); clonedMsgElement.innerText = text; switch (type) { case ("success"): clonedMsgElement.style.border='2px solid rgba(0, 255, 0, 0.5)'; break; case ("error"): clonedMsgElement.style.border='2px solid rgba(255, 0, 0, 0.5)'; break; }; clonedMsgElement.style.display='none'; const messageOffset=(messages.length+1)*50; clonedMsgElement.style.bottom=messageOffset+"px"; void clonedMsgElement.offsetWidth; clonedMsgElement.style.display=''; messageContainer.appendChild(clonedMsgElement); //reorder such that newest is lowest for (let i=messages.length-1;i>=0;i--) { messages[i].style.bottom=(((messages.length-i)*50)-40)+"px"; }; }; } catch (error) { // Handle the error and display an error message onscreen console.error("An error occurred:", error); alert("Bollocks! If you're getting this message, injection probably failed. To solve this, perform CTRL+F5 - this performs a hard reload. If this does not work, contact the moderators."); } }; const applyStylesAddElements = function (themeToApply = "null") { const head = document.head || document.getElementsByTagName('head').pages[0]; //menu customisation (apply font, button widths, adjust checkbox right slightly, make menu appear on top, add anim to message) const styleElement = document.createElement('style'); styleElement.textContent = ` @font-face { font-family: "Bahnschrift"; src: url("https://db.onlinewebfonts.com/t/0a6ee448d1bd65c56f6cf256a7c6f20a.eot"); src: url("https://db.onlinewebfonts.com/t/0a6ee448d1bd65c56f6cf256a7c6f20a.eot?#iefix")format("embedded-opentype"), url("https://db.onlinewebfonts.com/t/0a6ee448d1bd65c56f6cf256a7c6f20a.woff2")format("woff2"), url("https://db.onlinewebfonts.com/t/0a6ee448d1bd65c56f6cf256a7c6f20a.woff")format("woff"), url("https://db.onlinewebfonts.com/t/0a6ee448d1bd65c56f6cf256a7c6f20a.ttf")format("truetype"), url("https://db.onlinewebfonts.com/t/0a6ee448d1bd65c56f6cf256a7c6f20a.svg#Bahnschrift")format("svg"); } .tp-dfwv, .tp-sglv_i, .tp-rotv_t, .tp-fldv_t, .tp-ckbv_l, .tp-txtv_i, .tp-lblv_l, .tp-tbiv_t, .msg, .coords, .gameinfo, .playerstats, .playerinfo, .automated { font-family: 'Bahnschrift', sans-serif !important; font-size: 16px; z-index: 9999 !important; } .tp-rotv_m, .tp-fldv_m { display: none; } .tp-rotv_t { cursor: move; user-select: none; } .tp-tbiv_t { font-family: 'Bahnschrift'; font-size: 13px; } .tp-lblv_v, .tp-lstv, .tp-btnv_b, .tp-btnv_t { font-family: 'Bahnschrift'; font-size: 12px; } .tp-mllv { font-family: 'Bahnschrift'; font-size: 12px; letter-spacing: -1px; width: 246px; margin-left: -86px !important; } .tp-mllv_i::-webkit-scrollbar-thumb { background-color: #888; /* Adjust the color as needed */ border: 2px solid #555; /* Change the color of the border and adjust the width as needed */ } .tp-mllv_i::-webkit-scrollbar-track { background-color: #000; /* Change the color as needed */ } .tp-lblv_l { font-size: 14px; letter-spacing: -1px; } .tp-btnv { width: 100px; margin-left: 60px !important; } .tp-ckbv_w { margin-left: 4px !important; } .tp-dfwv, .tp-rotv, .tp-rotv_c, .tp-fldv, .tp-fldv_c, .tp-lblv, .tp-lstv, .tp-btnv, .tp-sldv { z-index: 99999 !important; white-space: nowrap !important; } @keyframes msg { from { transform: translate(-120%, 0); opacity: 0; } to { transform: none; opacity: 1; } } `; document.head.appendChild(styleElement); //initiate message div and css and shit msgElement = document.createElement('div'); // create the element directly msgElement.classList.add('msg'); msgElement.setAttribute('style', ` position: absolute; left: 10px; color: #fff; background: rgba(0, 0, 0, 0.7); font-weight: normal; padding: 10px; border-radius: 5px; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2); border: 2px solid rgba(255, 255, 255, 0.5); animation: msg 0.5s forwards, msg 0.5s reverse forwards 3s; z-index: 999999; pointer-events: none; opacity: 0; transition: opacity 0.3s ease-in-out; `); document.body.appendChild(msgElement); msgElement.style.display = 'none'; const messageContainer = document.createElement('div'); //so it can be cloned. i think. messageContainer.id = 'message-container'; document.body.appendChild(messageContainer); //initiate coord div and css and shit coordElement = document.createElement('div'); // create the element directly coordElement.classList.add('coords'); coordElement.setAttribute('style', ` position: fixed; top: -2px; left: -2px; color: #fff; background: rgba(0, 0, 0, 0.6); font-weight: bolder; padding: 2px; border-radius: 5px; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2); border: 2px solid rgba(255, 255, 255, 0.5); z-index: 999999; `); document.body.appendChild(coordElement); coordElement.style.display = 'none'; //initiate game info div and css and shit gameInfoElement = document.createElement('div'); // create the element directly gameInfoElement.classList.add('gameinfo'); gameInfoElement.setAttribute('style', ` position: fixed; bottom: -2px; left: -2px; color: #fff; background: rgba(0, 0, 0, 0.6); font-weight: bolder; padding: 2px; border-radius: 5px; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2); border: 2px solid rgba(255, 255, 255, 0.5); z-index: 999999; `); document.body.appendChild(gameInfoElement); gameInfoElement.style.display = 'none'; //initiate hp div and css and shit playerstatsElement = document.createElement('div'); // create the element directly playerstatsElement.classList.add('playerstats'); playerstatsElement.setAttribute('style', ` position: fixed; top: 20px; left: 280px; color: #fff; background: rgba(0, 0, 0, 0.6); font-weight: bolder; padding: 10px; border-radius: 5px; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2); border: 2px solid rgba(255, 255, 255, 0.5); z-index: 999999; `); document.body.appendChild(playerstatsElement); playerstatsElement.style.display = 'none'; const rootTheme = ` --tp-base-background-color: hsla(198, 100%, 50%, 1.00); --tp-base-shadow-color: hsla(0, 0%, 0%, 0.2); --tp-button-background-color: hsla(0, 0%, 100%, 1.00); --tp-button-background-color-active: hsla(0, 0%, 85%, 1.00); --tp-button-background-color-focus: hsla(0, 0%, 90%, 1.00); --tp-button-background-color-hover: hsla(0, 0%, 95%, 1.00); --tp-button-foreground-color: hsla(230, 20%, 11%, 1.00); --tp-container-background-color: hsla(0, 0%, 0%, 0.20); --tp-container-background-color-active: hsla(0, 0%, 0%, 0.35); --tp-container-background-color-focus: hsla(0, 0%, 0%, 0.30); --tp-container-background-color-hover: hsla(0, 0%, 0%, 0.25); --tp-container-foreground-color: hsla(0, 0%, 100%, 0.90); --tp-groove-foreground-color: hsla(0, 0%, 0%, 0.50); --tp-input-background-color: hsla(0, 0%, 0%, 0.50); --tp-input-background-color-active: hsla(0, 0%, 0%, 0.65); --tp-input-background-color-focus: hsla(0, 0%, 0%, 0.60); --tp-input-background-color-hover: hsla(0, 0%, 0%, 0.55); --tp-input-foreground-color: hsla(0, 0%, 100%, 0.90); --tp-label-foreground-color: hsla(0, 0%, 100%, 0.90); --tp-monitor-background-color: hsla(0, 0%, 0%, 0.50); --tp-monitor-foreground-color: hsla(0, 0%, 100%, 0.50);`; //menu customisation (apply font, button widths, adjust checkbox right slightly, make menu appear on top, add anim to message) const themeElement = document.createElement('style'); themeElement.textContent = ` :root { ${rootTheme} } `; document.head.appendChild(themeElement); }; const makeDraggable = function(element,notMenu) { if (element) { let offsetX, offsetY; element.addEventListener('mousedown', function(e) { const dragElement = function(e) { const x = (e.clientX - offsetX) / unsafeWindow.innerWidth * 100; const y = (e.clientY - offsetY) / unsafeWindow.innerHeight * 100; const maxX = 100 - (element.offsetWidth / unsafeWindow.innerWidth * 100); const maxY = 100 - (element.offsetHeight / unsafeWindow.innerHeight * 100); element.style.left = `${Math.max(0, Math.min(x, maxX))}%`; element.style.top = `${Math.max(0, Math.min(y, maxY))}%`; }; if (notMenu||e.target.classList.contains('tp-rotv_t')) { offsetX = e.clientX - element.getBoundingClientRect().left; offsetY = e.clientY - element.getBoundingClientRect().top; document.addEventListener('mousemove', dragElement); document.addEventListener('mouseup', function() { document.removeEventListener('mousemove', dragElement); }); e.preventDefault(); // Prevent text selection during drag }; }); }; }; //1337 H4X const distancePlayers = function (player,yMultiplier) { yMultiplier=yMultiplier||1; let vector = getDirectionVectorFacingTarget(player); return Math.hypot(vector.x,vector.y*yMultiplier,vector.z); //pythagoras' theorem in 3 dimensions. no one owns maths, zert. }; const setPrecision = function (value) { return Math.round(value * 8192) / 8192 }; //required precision const calculateYaw = function (pos) { return setPrecision(Math.mod(Math.atan2(pos.x,pos.z), Math.PI2)); }; const calculatePitch = function (pos) { return setPrecision(-Math.atan2(pos.y,Math.hypot(pos.x,pos.z))%1.5); }; const getAngularDifference = function (obj1,obj2) { return Math.abs(obj1.yaw-obj2.yaw)+Math.abs(obj1.pitch-obj2.pitch); }; const getDirectionVectorFacingTarget = function (target,vectorPassed,offsetY) { target = vectorPassed ? target : target[H.actor].mesh.position; offsetY=offsetY||0; return { x: target.x - ss.MYPLAYER[H.actor].mesh.position.x, y: target.y - ss.MYPLAYER[H.actor].mesh.position.y+offsetY, z: target.z - ss.MYPLAYER[H.actor].mesh.position.z, }; }; const reverse_string = function (str) { return str.split("").reverse().join("") }; const isPartialMatch = function (array, searchString) { return array.some(item => item !== "" && searchString.toLowerCase().includes(item.toLowerCase())); }; const randomInt = function(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; }; const radianAngleDiff = function (angle1,angle2) { 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; }; }; const getScrambled=function(){return Array.from({length: 10}, () => String.fromCharCode(97 + Math.floor(Math.random() * 26))).join('')} clientID=(getScrambled()+"noID"); const createAnonFunction=function(name,func){ const funcName=getScrambled(); unsafeWindow[funcName]=func; F[name]=unsafeWindow[funcName]; functionNames[name]=funcName }; const processChatItem = function (text,playerName,playerTeam,highlightColor) { let chatItem = document.createElement("div"); let playerNameSpan = document.createElement("span"); let playerInfoContainer = document.createElement("div"); let serverIcon = document.createElement("i"); chatItem.classList.add("chat-item"); playerInfoContainer.style.display = "inline-block"; playerNameSpan.classList.add("chat-player-name", "ss_marginright_xs"); playerNameSpan.textContent = playerName + " "; playerInfoContainer.style.color = ss.TEAMCOLORS.text[playerTeam]; playerInfoContainer.appendChild(serverIcon); playerInfoContainer.appendChild(playerNameSpan); let messageSpan = document.createElement("span"); messageSpan.innerHTML = text; chatItem.style.fontStyle = "italic"; messageSpan.style.backgroundColor = highlightColor; playerInfoContainer.style.backgroundColor = highlightColor; chatItem.appendChild(playerInfoContainer); chatItem.appendChild(messageSpan); document.getElementById("chatOut").appendChild(chatItem); if (document.querySelector(".chat-container")) { document.querySelector(".chat-container").scrollTop = document.querySelector(".chat-container").scrollHeight; }; }; const everySecond = function () { allFolders.forEach(function (name) { localStorage.setItem(name,JSON.stringify(tp[name].expanded)); }); if (unsafeWindow.extern.inGame) { if (extract("gameInfo")) { let gameInfoText=ss.GAMECODE+" | "+playersInGame+"/18 | "+(18-playersInGame)+" slots remaining. | Server: "+unsafeWindow.vueData.currentRegionId+" | Gamemode: "+findKeyByValue(unsafeWindow.extern.GameType,unsafeWindow.vueApp.game.gameType)+" | Map: "+unsafeWindow.vueApp.game.mapName; gameInfoElement.innerText = gameInfoText; void gameInfoElement.offsetWidth; gameInfoElement.style.display = ''; }; }; if ((!document.getElementById("progressBar"))) { if ((extract("setDetail")!==previousDetail)&&(extract("setDetail")!=="disabled")) { unsafeWindow.vueApp.settingsUi.togglers.misc[3].value=false; if (extract("setDetail")=="autodetail") { unsafeWindow.vueApp.settingsUi.togglers.misc[3].value=true; } else if (extract("setDetail")=="nodetails") { unsafeWindow.vueApp.settingsUi.togglers.misc[4].value=false; unsafeWindow.vueApp.settingsUi.togglers.misc[5].value=false; } else if (extract("setDetail")=="shadows") { unsafeWindow.vueApp.settingsUi.togglers.misc[4].value=true; unsafeWindow.vueApp.settingsUi.togglers.misc[5].value=false; } else if (extract("setDetail")=="highres") { unsafeWindow.vueApp.settingsUi.togglers.misc[4].value=false; unsafeWindow.vueApp.settingsUi.togglers.misc[5].value=true; } else if (extract("setDetail")=="shadowshighres") { unsafeWindow.vueApp.settingsUi.togglers.misc[4].value=true; unsafeWindow.vueApp.settingsUi.togglers.misc[5].value=true; }; unsafeWindow.extern.applyUiSettings(unsafeWindow.vueApp.settingsUi); }; previousDetail=extract("setDetail"); }; //block ads or something kek localStorage.timesPlayed = 0; }; const everyDecisecond = function () { updateConfig(); if (unsafeWindow.extern.inGame) { //innertext stuff, fairly resource intensive. disable these for performance if (extract("playerStats")) { let playerStates=""; ss.PLAYERS.forEach(player=>{ if (player && (player!==ss.MYPLAYER) && player[H.playing] && (player.hp>0) && ((!ss.MYPLAYER.team)||( player.team!==ss.MYPLAYER.team))) { playerStates=playerStates+player.name+": "+Math.round(player.hp)+" HP\n"; }; }); if (playerStates=="") {playerStates="No Enemy Players"}; playerstatsElement.innerText = playerStates; void playerstatsElement.offsetWidth; playerstatsElement.style.display = ''; }; if (extract("showCoordinates")) { const fonx = Number((ss.MYPLAYER[H.actor].mesh.position.x).toFixed(3)); const fony = Number((ss.MYPLAYER[H.actor].mesh.position.y).toFixed(3)); const fonz = Number((ss.MYPLAYER[H.actor].mesh.position.z).toFixed(3)); const yaw = Number((ss.MYPLAYER.yaw).toFixed(3)); //could i function this? yea const pitch = Number((ss.MYPLAYER.pitch).toFixed(3)); const personalCoordinate = `XYZ: ${fonx}, ${fony}, ${fonz} Rot: ${yaw}, ${pitch}`; coordElement.innerText = personalCoordinate; void coordElement.offsetWidth; coordElement.style.display = ''; }; }; }; const updateConfig = function () { configMain = tp.mainPanel.exportPreset(); }; const saveConfig = function () { localStorage.setItem("ShellFarmConfigMainPanel",JSON.stringify(tp.mainPanel.exportPreset())); }; const injectScript = function () { //TODO: replace with anon functions unsafeWindow.fixCamera = function () { return isKeyToggled[bindsArray.zoom] && (extract("zoom")*(Math.PI / 180)) || (extract("fov")*(Math.PI/180)) || 1.25; }; unsafeWindow.getChatLimit = function () { return (extract("chatExtend")&&999999)||4; }; unsafeWindow.getDisableChatFilter = function () { return extract("disableChatFilter"); }; unsafeWindow.getSkinHack = function () { return extract("unlockSkins"); }; unsafeWindow.getPointerEscape = function () { return noPointerPause; }; const originalXHROpen = XMLHttpRequest.prototype.open; //wtf??? libertymutual collab?????? 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 applyShellFarm(originalXHRGetResponse.get.call(this)); }; return originalXHRGetResponse.get.call(this); } }); const applyShellFarm = function(js) { console.log('%cATTEMPTING TO START SHELLFARM', 'color: magenta; font-weight: bold; font-size: 1.5em; text-decoration: underline;'); const allFuncName={}; let vars=[]; let injectionString=""; let match; const getVar=function(name,regex){ const varName=eval(new RegExp(regex)+`.exec(js)[1]`); vars[name]=varName; injectionString=injectionString+name+": ("+varName+")||undefined,"; console.log('%cFound var! Saved '+varName+' as '+name, 'color: green; font-weight: bold;'); }; console.log('%cSHELLFARM INJECTION STAGE 1: GATHER VARS', 'color: yellow; font-weight: bold; font-size: 1.2em; text-decoration: underline;'); try { getVar("PLAYERS", '([a-zA-Z]+)\\[[a-zA-Z]+\\]\\.hp=100'); getVar("MYPLAYER", '\\),([a-zA-Z]+)\\.pitch=Math\\.clamp\\('); getVar("TEAMCOLORS", '\\{([a-zA-Z_$]+)\\.themClass\\['); getVar("GAMECODE", '\\{crazyShare:([a-zA-Z]+)\\}'); createPopup("ShellFarm Script injected!","success"); console.log(injectionString,allFuncName); } catch (err) { createPopup("Error! Scipt injection failed! See console.","error") alert( 'Oh bollocks! Looks like the script is out of date. Report this data to the original developers and any errors in the console.\n' + JSON.stringify( allFuncName, undefined, 2 ) ); console.log(err); return js; }; const modifyJS = function(find,replace) { let oldJS = js; js = js.replace(find,replace); if (oldJS !== js) { console.log("%cReplacement successful! Injected code: "+replace, 'color: green; font-weight: bold; font-size: 0.6em; text-decoration: italic;'); } else { console.log("%cReplacement failed! Attempted to replace "+find+" with: "+replace, 'color: red; font-weight: bold; font-size: 0.6em; text-decoration: italic;'); }; }; console.log('%cSHELLFARM INJECTION STAGE 2: INJECT VAR RETRIEVAL FUNCTION AND MAIN LOOP', 'color: yellow; font-weight: bold; font-size: 1.2em; text-decoration: underline;'); //hook for main loop function in render loop match=js.match(/\.engine\.([a-zA-Z]+)\(\(function\(\)\{!/); console.log(match); modifyJS('.engine.'+match[1]+'((function(){',`.engine.${match[1]}((function(){if(window["${functionNames.retrieveFunctions}"]({${injectionString}},true)){return};`); modifyJS('console.log("After Game Ready"),', `console.log("After Game Ready: ShellFarm is also trying to add vars..."),window["${functionNames.retrieveFunctions}"]({${injectionString}}),`); console.log('%cSuccess! Variable retrieval and main loop ss.', 'color: green; font-weight: bold;'); //hook for fov mods modifyJS(/\.fov\s*=\s*1\.25/g, '.fov = window.fixCamera()'); modifyJS(/\.fov\s*\+\s*\(1\.25/g, '.fov + (window.fixCamera()'); //chat mods: disable chat culling const somethingLength=/\.length>4&&([a-zA-Z]+)\[0\]\.remove\(\),/.exec(js)[1]; modifyJS(new RegExp(`\\.length>4&&${somethingLength}\\[0\\]\\.remove\\(\\),`),`.length>window.getChatLimit()&&${somethingLength}[0].remove(),`); //chat mods: disable filter (credit to A3+++ for this finding) const filterFunction=/\|\|([a-zA-Z]+)\([a-zA-Z]+.normalName/.exec(js)[1]; const thingInsideFilterFunction=new RegExp(`!${filterFunction}\\(([a-zA-Z]+)\\)`).exec(js)[1]; modifyJS(`!${filterFunction}(${thingInsideFilterFunction})`,`((!${filterFunction}(${thingInsideFilterFunction}))||window.getDisableChatFilter())`); //chat mods: make filtered text red let [_, elm, str] = js.match(/\)\),([a-zA-Z]+)\.innerHTML=([a-zA-Z]+),/); modifyJS(_, _ + `${filterFunction}(${str})&&!arguments[2]&&(${elm}.style.color="red"),`); //skins match = js.match(/inventory\[[A-z]\].id===[A-z].id\)return!0;return!1/); if (match) modifyJS(match[0], match[0] + `||window.getSkinHack()`); //reset join/leave msgs modifyJS(',console.log("joinGame()',',window.newGame=true,console.log("value changed, also joinGame()'); //get rid of tutorial popup because its a stupid piece of shit modifyJS(',vueApp.onTutorialPopupClick()',''); //pointer escape modifyJS('onpointerlockchange=function(){','onpointerlockchange=function(){if (window.getPointerEscape()) {return};'); modifyJS('console.log("startShellShockers"),', `console.log("SHELLFARM ACTIVE!"),`); console.log(js); H.playing = js.match(/this\.hp=[a-zA-Z]+\.hp,this\.([a-zA-Z]+)=[a-zA-Z]+\.[a-zA-Z]+,this/)[1]; return js; }; }; const findKeyWithProperty = function(obj, propertyToFind) { for (const key in obj) { if (obj[key] === null || obj[key] === undefined) { continue; }; if (!!obj[key] && (typeof(obj[key])=='object' || typeof(obj[key])=='function') && obj[key].hasOwnProperty(propertyToFind)) { return key; }; }; // Property not found return null; }; const mainLoop = function () { const oneTime = function () { H.actor = findKeyWithProperty(ss.MYPLAYER,"mesh"); ranOneTime=true; }; const initVars = function () { if (unsafeWindow.newGame) { onlinePlayersArray=[]; }; username=ss.MYPLAYER?.name; const weaponBox = document.getElementById("weaponBox"); const chatContainer = document.getElementById('chatOut'); const chatItems = chatContainer.getElementsByClassName('chat-item'); if ((weaponBox.style.display!=lastWeaponBox)||(chatItems.length!=lastChatItemLength)) { lastWeaponBox=weaponBox.style.display; lastChatItemLength=chatItems.length; const maxChat = extract("maxChat"); const maxMessages = (weaponBox.style.display === "block" && maxChat) || 9999999; const startIndex = Math.max(0, chatItems.length - maxMessages); for (let i = chatItems.length - 1; i >= 0; i--) { const chatIndex = i - startIndex; const isInRange = chatIndex >= 0 && chatIndex < maxMessages; chatItems[i].style.display = isInRange ? '' : 'none'; }; }; ss.MYPLAYER[H.actor].scene.texturesEnabled=extract("enableTextures"); }; const iterateOverPlayers = function () { const objExists=Date.now(); ss.PLAYERS.forEach(player=>{ if (player && (player!==ss.MYPLAYER) && player[H.playing] && (player.hp>0) && ((!ss.MYPLAYER.team)||( player.team!==ss.MYPLAYER.team))) { if (player[H.actor]) { eggSize=extract("eggSize"); player[H.actor].bodyMesh.scaling = {x:eggSize, y:eggSize, z:eggSize}; }; player.exists=objExists; }; if (player) { if (!player.logged) { player.logged=true; if (extract("debug")) { playerLogger.push(player);console.log("Logged player: "+player.name,player) } if (extract("joinMessages") && (!unsafeWindow.newGame)) { processChatItem("joined.",player.name,player.team,"rgba(0, 255, 0, 0.2)"); }; onlinePlayersArray.push([player,player.name,player.team]); }; player.isOnline=objExists; }; }); playersInGame=onlinePlayersArray.length; for ( let i=0;i<onlinePlayersArray.length;i++) { if (onlinePlayersArray[i][0] && onlinePlayersArray[i][0].isOnline==objExists) { //player still online onlinePlayersArray[i][2]=onlinePlayersArray[i][0].team; } else { if (extract("leaveMessages") && (!unsafeWindow.newGame)) { processChatItem("left.",onlinePlayersArray[i][1],onlinePlayersArray[i][2],"rgba(255, 0, 0, 0.2)"); }; onlinePlayersArray.splice(i,1); }; }; }; unsafeWindow.newGame=false; createAnonFunction("retrieveFunctions",function(vars,doShellFarm) { ss=vars ; if (doShellFarm) {F.SHELLFARM()} }); createAnonFunction("SHELLFARM",function(){ if ( !ranOneTime ) { oneTime() }; initVars(); iterateOverPlayers(); if ( extract("chatHighlight") ) { document.getElementById("chatOut").style.userSelect="text" }; }); }; //start init thingamajigs startUp(); })();