Shell Shockers | All in One

This script gathers most of my mods into 1 place

이 스크립트를 설치하려면 Tampermonkey, Greasemonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey와 같은 확장 프로그램을 설치해야 합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Userscripts와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 유저 스크립트 관리자 확장 프로그램이 필요합니다.

(이미 유저 스크립트 관리자가 설치되어 있습니다. 설치를 진행합니다!)

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

(이미 유저 스타일 관리자가 설치되어 있습니다. 설치를 진행합니다!)

// ==UserScript==
// @name        Shell Shockers | All in One
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_deleteValue
// @grant        GM_listValues
// @grant        GM_info
// @grant        GM_setClipboard
// @grant        GM_openInTab
//
// @grant        GM.setValue
// @grant        GM.getValue
// @grant        GM.deleteValue
// @grant        GM.listValues
// @grant        GM.info
// @grant        GM.setClipboard
// @grant        GM.openInTab

// @grant        none
// @run-at       document-start
// @require      https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js
// @require     https://cdn.jsdelivr.net/npm/[email protected]/dist/tweakpane.min.js
// @require      https://cdn.jsdelivr.net/npm/@tweakpane/[email protected]/dist/tweakpane-plugin-essentials.min.js
// @require      https://cdnjs.cloudflare.com/ajax/libs/jszip/3.7.1/jszip.min.js
//
// @license MIT
// @namespace https://greatest.deepsurf.us/users/1361048

// @version     3.8
// @author      wish?
// @description This script gathers most of my mods into 1 place

// @match        *://*.shellshock.io/*
// @match        *://*.shell.onlypuppy7.online/*
// @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        *://*.risenegg.com/*
// @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/*
// @match        *://*.shellshockers.best/*
// @match        *://*.eggboy.me/*
// @match        *://*.shellshock.guru/*
// ==/UserScript==
(function () {
	let noPointerPause;
	const clientKeysURL = `https://raw.githubusercontent.com/StateFarmNetwork/client-keys/refs/heads/main/statefarm_`;
	let ss;
	let F = [];
	let H = {};
	let playerArr = [];
	let functionNames = [];
	let keyRetrieved = false;

	const tp = {
		mainCH: {
			color: "#fff",
			length: 0.8,
			width: 0.3,
			opacity: 0.7,
			border: "#000000",
			rotate: 0,
		},
		middleDot: {
			opacity: 1,
			color: "#000",
			border: "#000",
			size: 0.2,
			round: false,
			shape: "Dot",
			length: 0.2,
			width: 0.2,
		},
		FPS: {
			hide: false,
			min: 20,
			max: 200,
			random: false,
		},
		ping: {
			min: 20,
			max: 200,
			random: false,
		},
		sounds: {
			crackshot: "default",
			"egg-k": "default",
			scrambler: "default",
			"free-ranger": "default",
			rpegg: "default",
			whipper: "default",
			"tri-hard": "default",
			pistol: "default",
		},
		meleeSounds: {
			melee: "default",
		},
		extra: {
			disableScopeLines: false,
		},
		paneSettings: {
			width: 300,
			tabout: "`",
			hidePanel: "h",
			refreshSounds: "g",
		},
	};

	const startUp = function () {
		console.log("startup");
		injectScript();
		console.log("after startup");
	};

	function getRandom(arr) {
		if (Array.isArray(arr)) return arr[Math.floor(Math.random() * arr.length)]
		else return arr;
	}

	let originalReplace = String.prototype.replace;
	let originalReplaceAll = String.prototype.replaceAll;

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

	const log = function (...args) {
		let condition;
		try {
			condition = false;
		} catch (error) {
			condition = GM_getValue(storageKey + "DisableLogs");
		}
		if (!condition) {
			console.log(...args);
		}
	};

	const fetchTextContent = function (url) {
		try {
			var xhr = new XMLHttpRequest();
			xhr.open("GET", url, false);
			xhr.send();
			if (xhr.status === 200) {
				return xhr.responseText;
			} else {
				console.error("Error fetching " + url);
				return null;
			}
		} catch (err) {
			return null;
		}
	};
	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 getScrambled = () =>
		Array.from({ length: 10 }, () =>
			String.fromCharCode(97 + Math.floor(Math.random() * 26)),
		).join("");
	const createAnonFunction = function (name, func) {
		const funcName = getScrambled();
		window[funcName] = func;
		window[funcName] = function () {
			try {
				return func.apply(this, arguments);
			} catch (error) {
				log("Error in anonymous function:", error);
			}
		};

		F[name] = window[funcName];
		functionNames[name] = funcName;
	};

	function loadExistingSettings(name, target, callback) {
		const stuff = localStorage.getItem(name);

		if (stuff) {
			const parsed = JSON.parse(stuff);

			Object.assign(target, parsed);
			if (typeof callback === "function") callback();
		}
	}

	function updateSounds() {
		const players = window.players;
		if (!players) return;
		const H = window.H;

		const WEAPON_SOUND_MAP = {
			gun_m24: "crackshot",
			gun_eggk47: "egg-k",
			gun_dozenGauge: "scrambler",
			gun_csg1: "free-ranger",
			gun_rpegg: "rpegg",
			gun_smg: "whipper",
			gun_aug: "tri-hard",
			gun_cluck9mm: "pistol",
		};

		for (const player of players) {
			if (!player?.hasOwnProperty("ws")) continue;
			H.actor = findKeyWithProperty(player, H.mesh);

			for (const wp of player.weapons) {
				let weaponObj = wp[H.actor];
				let myWeaponName = wp[H.actor][H.extra.weapon];

				weaponObj.defaultSound ??= weaponObj.fireSound;

				const soundKey = WEAPON_SOUND_MAP[myWeaponName];
				if (soundKey) {
					const sound = tp.sounds[soundKey];
					weaponObj.fireSound =
						sound === "fire" ? weaponObj.defaultSound : `${myWeaponName}_${sound}`;
				}
			}

			player.meleeWeapon[H.actor].defaultSound ??= player.meleeWeapon[H.actor].swingSounds;

			// MELEE (MELEE default sound: [melee_whisk_a])
			// check if the sound saved in tp is the default sound
			// player.meleeWeapon[H.actor].swingSounds =
			// 	tp.meleeSounds["melee"][0] === "melee_whisk_a"
			// 		? player.meleeWeapon[H.actor].defaultSound
			// 		: tp.meleeSounds["melee"];

			// if (Array.isArray(tp.meleeSounds["melee"])) {
			// 	// its an array, meaning its not the default sound
			// 	player.meleeWeapon[H.actor].swingSounds = [tp.meleeSounds["melee"][Math.floor(Math.random() * tp.meleeSounds["melee"].length)]]
			// } else {
			// 	// Only the default option is a string, the rest are all in an array
			// 	player.meleeWeapon[H.actor].swingSounds = player.meleeWeapon[H.actor].defaultSound;
			// }

			const meleeSound = tp.meleeSounds["melee"];
			const meleeArray = meleeSound.split(",");

			if (meleeArray[0] == "melee_whisk_a") {
				player.meleeWeapon[H.actor].swingSounds = player.meleeWeapon[H.actor].defaultSound;
			} else {
				player.meleeWeapon[H.actor].swingSounds = meleeArray;
			}
		}
	}

	const injectScript = function () {
		createAnonFunction("adBlocker", function (input) {
			try {
				if (input == 10 && false) {
					return 1;
				} else if (true) {
					if (typeof input == "boolean") {
						return true;
					} else if (input == 10) {
						return 5;
					} else if (input == "adsBlocked") {
						return false;
					}
				}
				return input;
			} catch (error) {
				return true;
			}
		});

		createAnonFunction("FakePing", function (original) {
			if (tp.ping.random) {
				const randomPing =
					Math.floor(Math.random() * (tp.ping.max - tp.ping.min + 1)) + tp.ping.min;
				return randomPing;
			} else {
				return Date.now() - original;
			}
		});
		createAnonFunction("FakeFps", function (original) {
			if (tp.FPS.hide) return "";
			if (tp.FPS.random) {
				const randomPing =
					Math.floor(Math.random() * (tp.FPS.max - tp.FPS.min + 1)) + tp.FPS.min;
				return randomPing;
			} else {
				return original;
			}
		});

		createAnonFunction("disableScopeLines", function () {
			return tp.extra.disableScopeLines ? "0" : "536870912";
		});

		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;
				node.innerHTML = applyScript(node.innerHTML);
			}
			return _apc.call(this, node);
		};

		const proto = window.HTMLScriptElement.prototype;
		const existing = Object.getOwnPropertyDescriptor(proto, "textContent");

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

		Object.defineProperty(proto, "textContent", {
			get: function () {
				// if (this === window.document.currentScript) {
				//     prompt("[Hook] document.currentScript.textContent accessed");
				//     debugger; // <-- triggers breakpoint
				// };
				let textContent = original.get.call(this);
				if (textContent && textContent.startsWith("(()=>{")) {
					return shellshock_og;
				} else {
					return textContent;
				}
			},
			set: original.set,
			configurable: true,
			enumerable: true,
		});

		const applyScript = function (js) {
			let match;
			let clientKeys;
			console.log(js);

			let originalJS = fetchTextContent("/js/shellshock.js");

			const getVardata = function () {
				return fetchTextContent(clientKeysURL + "latest.json?v=" + Date.now());
			};

			// console.log(hash);
			let onlineClientKeys = getVardata();

			try {
				clientKeys = JSON.parse(onlineClientKeys);
			} catch (e) {
				console.error(e);
			}

			let H = clientKeys.vars;
			let C = clientKeys.commCodes?.codes;

			const patterns = {
				scope: /,this\.(..)\.position\.z=2/,
				ping: /(case [A-Za-z$_]+\.[A-Za-z$_]+\:[A-Za-z$_]+\=)Date\.now\(\)-([A-Za-z$_]+),/,
				fps: /(document\.getElementById\("FPS"\)\.innerText=)(.*?)}/,
				spec: /received"\),(.*?)=.*?\.unPackInt8U\(\)/,
				weapon: /this\.([a-zA-Z0-9_$]+)\=\"gun\_/,
			};

			const scopeVar = patterns.scope.exec(js)[1];
			const fpsVar = patterns.fps.exec(js);
			const specVar = patterns.spec.exec(js);
			H.extra = {
				scope: scopeVar,
				fps: fpsVar,
				spec: specVar,
				ping: patterns.ping.exec(js),
				weapon: patterns.weapon.exec(js)[1],
			};
			window.H = H;

			let injectionString = "";

			try {
				//SERVERSYNC
				match = new RegExp(`function serverSync\\(\\)\\{(.*?)\\)\\}`).exec(js);
				log("SERVERSYNC:", match);
				H.SERVERSYNC = match
					? match[1].replace(/[a-zA-Z$_\.\[\]]+shots/, 0) + ")"
					: "function(){log('no serversync womp womp')}";
				//PAUSE
				match = new RegExp(
					`,setTimeout\\(\\(\\(\\)=>\\{([=A-z0-9\\(\\),\\{ \\.;!\\|\\?:\\}]+send\\([a-zA-Z$_]+\\))`,
				).exec(js);
				log("PAUSE:", match);
				H.PAUSE = match
					? `function(){${match[1]}}`
					: "function(){log('no pause womp womp')}";

				const variableNameRegex = /^[a-zA-Z0-9_$\[\]"\\\.,]*$/;
				console.log(H);
				for (let name in H) {
					let deobf = H[name];
					if (name == "SERVERSYNC" || name == "PAUSE" || variableNameRegex.test(deobf)) {
						//serversync should only be defined just before...
						injectionString = `${injectionString}${name}:  (() => { let variable = "value_undefined"; try { eval("variable = ${deobf};"); } catch (error) { return "value_undefined"; }; return variable; })(),`;
					} else {
					}
				}
				console.log(injectionString);

				log(
					"%cSTATEFARM INJECTION STAGE 1: GATHER VARS",
					"color: yellow; font-weight: bold; font-size: 1.2em; text-decoration: underline;",
				);

				const modifyJS = function (find, replace) {
					let oldJS = js;
					try {
						js = js.originalReplaceAll(find, replace);
					} catch (err) {
						console.log(
							"%cReplacement failed! Likely a required var was not found. Attempted to replace " +
								find +
								" with: " +
								replace,
							"color: red; font-weight: bold; font-size: 0.6em; text-decoration: italic;",
						);
					}
					if (oldJS !== js) {
						console.log(
							"%cReplacement successful! Injected code: replaced: " +
								find +
								" with: " +
								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;",
						);
					}
				};

				const f = function (varName) {
					return varName.replace("$", "\\$");
				};
				const FUNCTIONPARAM = new RegExp(
					"function " + f(H._connectFail) + "\\(([a-zA-Z$_]+)\\)",
				).exec(js)[1];
				const v = `[a-zA-Z_$][a-zA-Z0-9_$]*`;
				const regex = (strings, ...values) =>
					new RegExp(
						strings.raw.reduce((acc, str, i) => acc + str + (values[i] ?? ""), ""),
						"g",
					);

				// ad-blocker
				modifyJS(
					"adsBlocked=" + FUNCTIONPARAM,
					"adsBlocked=" + functionNames.adBlocker + '("adsBlocked")',
				);
				modifyJS('"user-has-adblock"', functionNames.adBlocker + '("user-has-adblock")');
				modifyJS("layed=!1", "layed=window." + functionNames.adBlocker + "(!1)");
				modifyJS("showAdBlockerVideo", "hideAdBlockerVideo"); //hello eggs bullshit
				match = js.match(/return ([A-Za-z0-9_$]+)\.productBlockAds\}/);
				H.USERDATA = match[1];
				modifyJS(
					H.USERDATA + ".playerAccount.isUpgraded()",
					functionNames.adBlocker + "(" + f(H.USERDATA) + ".playerAccount.isUpgraded())",
				);

				// chat filter
				match = js.match(/this\.lastControlTeam=255\,.*?function ([A-z]+)\((.)\)/);
				H.isBadWord = match[1];
				H._insideFilterFunction = match[2];
				modifyJS(
					`!${f(H.isBadWord)}(${f(H._insideFilterFunction)})`,
					`((!${f(H.isBadWord)}(${f(H._insideFilterFunction)}))||true)`,
				);
				let [_, elm, str] = js.match(/\)\),([a-zA-Z$_]+)\.innerHTML=([a-zA-Z$_]+),/);
				modifyJS(
					_,
					_ +
						`${f(
							H.isBadWord,
						)}(${str})&&true&&!arguments[3]&&(${elm}.style.color="red"),`,
				);

				// remove mouse down console logs
				const r = /,?console\.log\(\`Mouse button .*?\`\),?/gm;
				const matches = js.match(r);

				if (matches) {
					for (const m of matches) {
						modifyJS(m, "");
					}
				}

				// FPS & PING
				modifyJS(
					H.extra.ping[0],
					`${H.extra.ping[1]}window.${functionNames.FakePing}(${H.extra.ping[2]}),`,
				);
				modifyJS(
					H.extra.fps[0],
					`${H.extra.fps[1]}window.${functionNames.FakeFps}(${H.extra.fps[2]})}`,
				);

				//SCOPE LINES
				modifyJS(
					`this.${H.extra.scope}.applyFog=!1,this.${H.extra.scope}.layerMask=536870912,`,
					`this.${H.extra.scope}.applyFog=!1,this.${H.extra.scope}.layerMask=window.${functionNames.disableScopeLines}(),`,
				);

				// GET PLAYERS
				match = js.match(/(([a-zA-Z_$][a-zA-Z0-9_$])\[this\.playerIdx\])/);
				modifyJS(`${match[2]}=[]`, `${match[2]}=[],window.players=${match[2]}`);

				log(H, "last");
				return js;
			} catch (e) {
				console.log(e);
			}
		};
	};
	// injectScript();
	startUp();

	function waitForElement(selector) {
		return new Promise((resolve) => {
			const intervalId = setInterval(() => {
				const element = document.getElementById(selector);
				console.log("looking for", selector);
				if (element) {
					console.dir(`found: ${element}`);
					clearInterval(intervalId);
					resolve(element);
				}
			}, 100);
		});
	}

	const changeMainCH = (obj) => {
		const previousStyle = document.getElementById("custom-mainCH");
		const containerCH = document.getElementById("crosshairContainer");
		containerCH.style.transform = `rotate(${obj.rotate}deg)`;

		if (previousStyle) {
			previousStyle.remove();
		}
		// Create a new stylesheet
		const style = document.createElement("style");
		style.id = "custom-mainCH";
		style.innerHTML = `
			.crosshair {
				position: absolute;
				transform-origin: 50% top;
				top: 50%;
				border: solid 0.05em ${obj.border};
				height: ${obj.length}em;
				opacity: ${obj.opacity};
				transform: rotate(${obj.angle || 0}deg);
			}
			.crosshair.normal {
				left: calc(50% - ${obj.width / 2}em);
				background: ${obj.color};
				width: ${obj.width}em;
			}
			.crosshair.powerful {
				left: calc(50% - ${obj.width / 2}em);
				background: red;
				width: ${obj.width}em;
			}
			.shotReticle.fill.normal {
				border-color: ${obj.color};
				border-left: solid transparent;
				border-right: solid transparent;
				border-width: 0.18em;
				padding: 0.18em;
			}
		`;

		document.body.appendChild(style);
	};

	const changeMiddleDot = (obj) => {
		const previousStyle = document.getElementById("custom-middleDot");
		if (previousStyle) previousStyle.remove();

		const dot = document.getElementById("reticleDot");

		dot.innerHTML = "";

		const style = document.createElement("style");
		style.id = "custom-middleDot";

		if (obj.shape === "plus") {
			style.innerHTML = `
				#reticleDot {
					position: absolute;
					top: 50%;
					left: 50%;
					transform: translate(-50%, -50%);
					width: 0;
					height: 0;
					background: none !important;
					border: none !important;
					opacity: ${obj.opacity};
				}
				#reticleDot .bar {
					position: absolute;
					background-color: ${obj.color};
					border: solid 0.05em ${obj.border}
				}
				#reticleDot .bar.horizontal {
					top: 50%;
					left: 50%;
					width: ${obj.width}px;
					height: ${obj.length}px;
					transform: translate(-50%, -50%) rotate(90deg);
				}
				#reticleDot .bar.vertical {
					left: 50%;
					top: 50%;
					width: ${obj.width}px;
					height: ${obj.length}px;
					transform: translate(-50%, -50%);
				}
			`;
			dot.innerHTML = `
				<div class="bar horizontal"></div>
				<div class="bar vertical"></div>
			`;
		} else {
			style.innerHTML = `
				#reticleDot {
					display: block;
					position: absolute;
					transform: translate(-50%, -50%);
					top: 50%;
					left: 50%;
					background-color: ${obj.color};
					border: solid 0.05em ${obj.border};
					width: ${obj.size}em;
					height: ${obj.size}em;
					opacity: ${obj.opacity};
					${obj.round ? "border-radius: 100%;" : ""}
				}
			`;
		}

		document.body.appendChild(style);
	};

	const makeDraggable = function (element, notMenu) {
		if (element) {
			let offsetX, offsetY;
			element.addEventListener("mousedown", function (e) {
				const dragElement = function (e) {
					const x = ((e.clientX - offsetX) / window.innerWidth) * 100;
					const y = ((e.clientY - offsetY) / window.innerHeight) * 100;
					const maxX = 100 - (element.offsetWidth / window.innerWidth) * 100;
					const maxY = 100 - (element.offsetHeight / window.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
				}
			});
		}
	};

	const playSound = (name) => {
		try {
			window.BAWK.play(name);
		} catch (e) {}
	};

	waitForElement("crosshairContainer").then((e) => {
		const Tweakpane = window.Tweakpane;
		const pane = new Tweakpane.Pane({
			title: "WISH",
			expanded: true,
		});
		const paneEl = document.querySelector("div.tp-dfwv");
		paneEl.style.zIndex = 1000;
		paneEl.style.width = `300px`;

		function createFolders(NFolder) {
			let test = pane.addFolder({
				title: NFolder,
				expanded: false,
			});
			return test;
		}

		function createInput(folder, obj, property, options, callback) {
			const x = folder.addInput(obj, property, options).on("change", callback);
			return x;
		}

		function addInputWithValidation(folder, obj, property, label) {
			const df = structuredClone(obj[property]);
			folder.addInput(obj, property, { label: label }).on("change", (value) => {
				if (value.value.length > 1) {
					value.value = df;
					obj[property] = df;
					console.log(obj[property]);
					value.target.controller_.binding.value.rawValue_ = df;
					window.alert("Please enter a single key");
				} else {
					const store = value.value.replace(/"/g, "");
					localStorage.setItem(`tp-${property}`, store);
				}
			});
		}

		makeDraggable(document.querySelector(".tp-dfwv"));

		const folderMainCH = createFolders("Crosshair");
		const folderMiddleDot = createFolders("Middle Dot");
		const folderFPSSettings = createFolders("FPS Settings");
		const folderPingSettings = createFolders("Ping Settings");
		const folderSoundsSettings = createFolders("Sounds Settings");
		const folderExtraSettings = createFolders("Extra Settings");
		const folderPaneSettings = createFolders("Panel Settings");

		loadExistingSettings("tp-mainCH", tp.mainCH, () => changeMainCH(tp.mainCH));
		loadExistingSettings("tp-middleDot", tp.middleDot, () => changeMiddleDot(tp.middleDot));
		loadExistingSettings("tp-paneSettings", tp.paneSettings, () => {
			const paneEl = document.querySelector("div.tp-dfwv");
			paneEl.style.width = `${tp.paneSettings.width}px`;
		});
		loadExistingSettings("tp-FPS", tp.FPS);
		loadExistingSettings("tp-ping", tp.ping);
		// loadExistingSettings("tp-sounds", tp.sounds);
		loadExistingSettings("tp-extra", tp.extra);

		const savedSounds = JSON.parse(localStorage.getItem("tp-sounds"));
		tp.sounds = savedSounds?.sounds ?? tp.sounds;
		tp.meleeSounds = savedSounds?.meleeSounds ?? tp.meleeSounds;

		createInput(folderMainCH, tp.mainCH, "color", { label: "Color" }, () => {});
		createInput(folderMainCH, tp.mainCH, "border", { label: "Border Color" }, () => {});
		createInput(
			folderMainCH,
			tp.mainCH,
			"length",
			{ label: "Length", min: 0, max: 10, step: 0.1 },
			() => {},
		);
		createInput(
			folderMainCH,
			tp.mainCH,
			"width",
			{ label: "Width", min: 0.1, max: 10, step: 0.1 },
			() => {},
		);
		createInput(
			folderMainCH,
			tp.mainCH,
			"opacity",
			{ label: "Opacity", min: 0, max: 1, step: 0.01 },
			() => {},
		);
		createInput(
			folderMainCH,
			tp.mainCH,
			"rotate",
			{ label: "Rotate", min: 0, max: 360, step: 1.0 },
			() => {},
		);

		folderMainCH.on("change", (data) => {
			localStorage.setItem("tp-mainCH", JSON.stringify(tp.mainCH));
			changeMainCH(tp.mainCH);
		});

		const resetCHBtn = folderMainCH.addButton({
			title: "Reset",
			label: "Crosshair",
		});

		resetCHBtn.on("click", () => {
			const cur = {
				mainCH: {
					color: "#fff",
					length: 0.8,
					width: 0.3,
					opacity: 0.7,
					border: "#000000",
					rotate: 0,
				},
				middleDot: {
					opacity: 1,
					color: "#ffffff",
					border: "#000",
					size: 0.3,
					round: false,
					shape: "Dot",
					length: 0.2,
					width: 0.2,
				},
			};
			changeMainCH(cur.mainCH);
			changeMiddleDot(cur.middleDot);
		});

		createInput(folderMiddleDot, tp.middleDot, "color", { label: "Color" }, () => {});
		createInput(folderMiddleDot, tp.middleDot, "border", { label: "Border Color" }, () => {});
		const mdSize = createInput(
			folderMiddleDot,
			tp.middleDot,
			"size",
			{ label: "Size", min: 0, max: 5, step: 0.1 },
			() => {},
		);
		const mdRound = createInput(
			folderMiddleDot,
			tp.middleDot,
			"round",
			{ label: "Round" },
			() => {},
		);
		createInput(
			folderMiddleDot,
			tp.middleDot,
			"opacity",
			{ label: "Opacity", min: 0, max: 1, step: 0.01 },
			() => {},
		);
		createInput(
			folderMiddleDot,
			tp.middleDot,
			"shape",
			{
				view: "list",
				label: "Shape",
				options: [
					{ text: "Dot", value: "dot" },
					{ text: "Plus", value: "plus" },
				],
			},
			() => {},
		);
		const mdLength = createInput(
			folderMiddleDot,
			tp.middleDot,
			"length",
			{ label: "Length", min: 0, max: 100, step: 1 },
			() => {},
		);
		const mdWidth = createInput(
			folderMiddleDot,
			tp.middleDot,
			"width",
			{ label: "Width", min: 0, max: 5, step: 0.1 },
			() => {},
		);

		// to disable it when the script is first launched
		if (tp.middleDot.shape === "dot") {
			mdLength.disabled = true;
			mdWidth.disabled = true;
		} else {
			mdSize.disabled = true;
			mdRound.disabled = true;
		}

		folderMiddleDot.on("change", (data) => {
			localStorage.setItem("tp-middleDot", JSON.stringify(tp.middleDot));
			changeMiddleDot(tp.middleDot);
			// console.log(tp.middleDot);
			if (tp.middleDot.shape === "dot") {
				mdLength.disabled = true;
				mdWidth.disabled = true;
				mdSize.disabled = false;
				mdRound.disabled = false;
			} else {
				mdLength.disabled = false;
				mdWidth.disabled = false;
				mdSize.disabled = true;
				mdRound.disabled = true;
			}
		});

		createInput(folderFPSSettings, tp.FPS, "hide", { label: "Hide FPS" }, () => {});
		createInput(folderFPSSettings, tp.FPS, "random", { label: "Randomise FPS" }, () => {});
		createInput(
			folderFPSSettings,
			tp.FPS,
			"min",
			{ label: "Min FPS", view: "slider", min: 1, max: 999, step: 1 },
			() => {},
		);
		createInput(
			folderFPSSettings,
			tp.FPS,
			"max",
			{ label: "Max FPS", view: "slider", min: 1, max: 999, step: 1 },
			() => {},
		);

		folderFPSSettings.on("change", (data) => {
			localStorage.setItem("tp-FPS", JSON.stringify(tp.FPS));
		});

		createInput(
			folderPingSettings,
			tp.ping,
			"min",
			{ label: "Min Ping", view: "slider", min: 1, max: 999, step: 1 },
			() => {},
		);
		createInput(
			folderPingSettings,
			tp.ping,
			"max",
			{ label: "Max Ping", view: "slider", min: 1, max: 999, step: 1 },
			() => {},
		);
		createInput(folderPingSettings, tp.ping, "random", { label: "Randomise Ping" }, () => {});

		folderPingSettings.on("change", (data) => {
			localStorage.setItem("tp-ping", JSON.stringify(tp.ping));
		});

		createInput(
			folderSoundsSettings,
			tp.sounds,
			"crackshot",
			{
				label: "Crackshot",
				options: {
					Default: "fire",
					"8bit": "fire_m24_8bit",
					BadEgg: "Badegg_fire",
					Chess: "Chess_fire",
					Cyborg: "Cyborg_fire",
					Frostfall: "Frostfall_fire",
					Fusion: "Fusion_fire",
					Infernal: "Infernal_fire",
					Irish: "irish_fire",
					Polaroid: "Polaroid_fire",
					Quack: "Quackshot_fire",
					Retro: "Retro_fire",
					"Silenced": "",
					Scavenger: "Scavenger_fire",
					Techno: "Techno_fire",
					Valkyrie: "Valkyrie_fire",
				},
			},
			(data) => {
				playSound(`gun_m24_${data.value}`);
			},
		);

		createInput(
			folderSoundsSettings,
			tp.sounds,
			"egg-k",
			{
				label: "Egg-K",
				options: {
					Default: "fire",
					Alien: "Alien_fire",
					Chocolate: "Chocolate_fire",
					Fusion: "Fusion_fire",
					Infernal: "Infernal_fire",
					"Infernal-2": "Infernal2_fire",
					Retro: "Retro_fire",
					"Silenced": "",
					Steambot: "Steambot_fire",
					Techno: "Techno_fire",
					Valkyrie: "Valkyrie_fire",
				},
			},
			(data) => {
				playSound(`gun_eggk47_${data.value}`);
			},
		);

		createInput(
			folderSoundsSettings,
			tp.sounds,
			"scrambler",
			{
				label: "Scrambler",
				options: {
					Default: "fire",
					Basketball: "Basketball_fire",
					Clouds: "Clouds_fire",
					Cutesy: "Cutesy_fire",
					Fantasy: "Fantasy_fire",
					Fusion: "Fusion_fire",
					Infernal: "Infernal_fire",
					Irish: "Irish_fire",
					Octopus: "Octopus_fire",
					Retro: "Retro_fire",
					"Silenced": "",
					Steambot: "Steambot_fire",
					Techno: "Techno_fire",
					Valkyrie: "Valkyrie_fire",
				},
			},
			(data) => {
				playSound(`gun_dozenGauge_${data.value}`);
			},
		);

		createInput(
			folderSoundsSettings,
			tp.sounds,
			"free-ranger",
			{
				label: "Free-Ranger",
				options: {
					Default: "fire",
					Fusion: "Fusion_fire",
					Infernal: "Infernal_fire",
					Retro: "Retro_fire",
					RubberChicken: "RubberChicken_fire",
					Shellpreme: "Shellpreme_fire",
					"Silenced": "",
					"Space-Egg": "spaceEgg_fire",
					Steambot: "Steambot_fire",
					Techno: "Techno_fire",
					Valkyrie: "Valkyrie_fire",
				},
			},
			(data) => {
				playSound(`gun_csg1_${data.value}`);
			},
		);

		createInput(
			folderSoundsSettings,
			tp.sounds,
			"rpegg",
			{
				label: "Rpegg",
				options: {
					Default: "fire",
					BFG: "BFG_fire",
					Bouzouki: "Bouzouki_fire",
					Christmas: "Christmas_fire",
					Fusion: "Fusion_fire",
					Infernal: "Infernal_fire",
					Retro: "Retro_fire",
					"Silenced": "",
					Skeleton: "Skeleton_fire",
					Techno: "Techno_fire",
					Valkyrie: "Valkyrie_fire",
				},
			},
			(data) => {
				playSound(`gun_rpegg_${data.value}`);
			},
		);

		createInput(
			folderSoundsSettings,
			tp.sounds,
			"whipper",
			{
				label: "Whipper",
				options: {
					Default: "fire",
					Fusion: "Fusion_fire",
					Infernal: "Infernal_fire",
					Pumpkin: "Pumpkin_fire",
					Retro: "Retro_fire",
					"Silenced": "",
					"Special-Turkey": "SpecialTurkey_fire",
					Techno: "Techno_fire",
					Valkyrie: "Valkyrie_fire",
				},
			},
			(data) => {
				playSound(`gun_smg_${data.value}`);
			},
		);

		createInput(
			folderSoundsSettings,
			tp.sounds,
			"tri-hard",
			{
				label: "Tri-Hard",
				options: {
					Default: "fire",
					Cupid: "Cupid_fire",
					Fusion: "Fusion_fire",
					Infernal: "Infernal_fire",
					Pumpkinpie: "Pumpkinpie_fire",
					Retro: "Retro_fire",
					"Silenced": "",
					Techno: "Techno_fire",
					Valkyrie: "Valkyrie_fire",
				},
			},
			(data) => {
				playSound(`gun_aug_${data.value}`);
			},
		);

		createInput(
			folderSoundsSettings,
			tp.meleeSounds,
			"melee",
			{
				label: "Melee",
				options: {
					Default: "melee_whisk_a",
					Carver: "melee_carver",
					"Boxing Glove": "melee_boxingGlove_a,melee_boxingGlove_b",
					Cup: "melee_cup_a,melee_cup_b",
					Eggpan: "melee_eggpan",
					Elf: "melee_elf_a,melee_elf_b",
					Fish: "melee_gfish_a,melee_gfish_b",
					Harrison: "melee_harrison",
					Infernal: "melee_infernal",
					Keytar: "melee_keytar",
					Mayan: "melee_mayan",
					Nutcracker: "melee_nutcracker",
					Pickleball: "melee_pickleball",
					Plunger: "melee_plunger",
					"Proper-Fish (idk)": "melee_properfish_a,melee_properfish_b",
					"Red Saber": "melee_redSaber",
					Retro: "melee_retro",
					Rock: "melee_rock",
					"Silenced": "",
					Steambot: "melee_steambot",
					Techno: "melee_techno",
					Valkyrie: "melee_valkyrie",
					Zombie: "melee_zombie",
				},
			},
			(data) => {
				// console.log(data.value)
				playSound(`${getRandom(data.value.split(","))}`);
			},
		);

		createInput(
			folderSoundsSettings,
			tp.sounds,
			"pistol",
			{
				label: "Pistol",
				options: {
					Default: "fire",
					Camera: "Camera_fire",
					Clouds: "Clouds_fire",
					"Cubic-Castle": "CubicCastles_fire",
					Fusion: "Fusion_fire",
					Infernal: "Infernal_fire",
					Megaphone: "Megaphone_fire",
					Retro: "Retro_fire",
					"Silenced": "",
					"Space-Egg": "spaceEgg_fire",
					Steambot: "Steambot_fire",
					Techno: "Techno_fire",
					Valkyrie: "Valkyrie_fire",
				},
			},
			(data) => {
				playSound(`gun_cluck9mm_${data.value}`);
			},
		);

		folderSoundsSettings.on("change", (value) => {
			localStorage.setItem("tp-sounds", JSON.stringify({sounds: tp.sounds, meleeSounds: tp.meleeSounds}));
			updateSounds();
		});

		createInput(
			folderExtraSettings,
			tp.extra,
			"disableScopeLines",
			{ label: "Hide Scope Lines" },
			() => {},
		);

		folderExtraSettings.on("change", (data) => {
			localStorage.setItem("tp-extra", JSON.stringify(tp.extra));
		});

		addInputWithValidation(folderPaneSettings, tp.paneSettings, "hidePanel", "Hide Panel");
		addInputWithValidation(folderPaneSettings, tp.paneSettings, "tabout", "Tabout");
		addInputWithValidation(
			folderPaneSettings,
			tp.paneSettings,
			"refreshSounds",
			"Refresh Sounds",
		);
		createInput(
			folderPaneSettings,
			tp.paneSettings,
			"width",
			{ label: "Panel Width", min: 300, max: 1000, step: 1 },
			() => {},
		);
		folderPaneSettings.on("change", (data) => {
			setTimeout(() => {
				const paneEl = document.querySelector("div.tp-dfwv");
				paneEl.style.width = `${tp.paneSettings.width}px`;
				localStorage.setItem("tp-paneSettings", JSON.stringify(tp.paneSettings));
			}, 1000);
		});

		// ADD OTHER STYLES
		const style = document.createElement("style");
		style.innerHTML = `
			#chickenBadge {
				display: none !important;
			}
		`;
		document.body.appendChild(style);

		document.querySelector(".btn-respawn").addEventListener("click", (e) => {
			updateSounds();
		});
	});

	let oldPointerLock;
	let disable = () => {
		if (document.onpointerlockchange == null) return;
		oldPointerLock = document.onpointerlockchange;
		document.onpointerlockchange = null;
		document.exitPointerLock();
	};

	let enable = () => {
		if (document.onpointerlockchange) return;
		canvas.requestPointerLock();
		document.onpointerlockchange = oldPointerLock;
	};

	let handle = (event) => {
		let isPaused = vueApp?.game?.isPaused;
		let chatOpened = document.activeElement.id == "chatIn";
		if (chatOpened || isPaused) return; // hopefully this also helps prevent people from spamming it
		let inGame = extern?.inGame; // uncertain if this is needed?
		if (!inGame) return;
		document.onpointerlockchange == null ? enable() : disable(); // toggle :blobshrug:
	};
	document.addEventListener("keydown", (event) => {
		let chatOpened = document.activeElement.id == "chatIn";
		if (chatOpened) return;

		if (event.key === tp.paneSettings.hidePanel) {
			const element = document.querySelector(".tp-dfwv");
			element.style.display = element.style.display === "none" ? "block" : "none";
		} else if (event.key === tp.paneSettings.tabout) {
			handle(event);
		} else if (event.key === tp.paneSettings.refreshSounds) {
			updateSounds();
		}
	});
})();