Shell Shockers | Crosshair

9/16/2024, 8:34:24 PM

  1. // ==UserScript==
  2. // @name Shell Shockers | Crosshair
  3. // @namespace Violentmonkey Scripts
  4. // @grant none
  5. // @version 5.0
  6. // @author https://greasyfork.org/en/users/1361048-wish
  7. // @description 9/16/2024, 8:34:24 PM
  8. // @require https://unpkg.com/guify@0.12.0/lib/guify.min.js
  9. // @license MIT; https://opensource.org/licenses/MIT
  10.  
  11. // @match *://eggshooter.best/*
  12. // @match *://*.shellshock.io/*
  13. // @match *://*.shell.onlypuppy7.online/*
  14. // @match *://*.algebra.best/*
  15. // @match *://*.algebra.vip/*
  16. // @match *://*.biologyclass.club/*
  17. // @match *://*.deadlyegg.com/*
  18. // @match *://*.deathegg.world/*
  19. // @match *://*.eggboy.club/*
  20. // @match *://*.eggboy.xyz/*
  21. // @match *://*.eggcombat.com/*
  22. // @match *://*.egg.dance/*
  23. // @match *://*.eggfacts.fun/*
  24. // @match *://*.egghead.institute/*
  25. // @match *://*.eggisthenewblack.com/*
  26. // @match *://*.eggsarecool.com/*
  27. // @match *://*.geometry.best/*
  28. // @match *://*.geometry.monster/*
  29. // @match *://*.geometry.pw/*
  30. // @match *://*.geometry.report/*
  31. // @match *://*.hardboiled.life/*
  32. // @match *://*.hardshell.life/*
  33. // @match *://*.humanorganising.org/*
  34. // @match *://*.mathactivity.xyz/*
  35. // @match *://*.mathactivity.club/*
  36. // @match *://*.mathdrills.info/*
  37. // @match *://*.mathdrills.life/*
  38. // @match *://*.mathfun.rocks/*
  39. // @match *://*.mathgames.world/*
  40. // @match *://*.math.international/*
  41. // @match *://*.mathlete.fun/*
  42. // @match *://*.mathlete.pro/*
  43. // @match *://*.overeasy.club/*
  44. // @match *://*.risenegg.com/*
  45. // @match *://*.scrambled.tech/*
  46. // @match *://*.scrambled.today/*
  47. // @match *://*.scrambled.us/*
  48. // @match *://*.scrambled.world/*
  49. // @match *://*.shellshockers.club/*
  50. // @match *://*.shellshockers.life/*
  51. // @match *://*.shellshockers.site/*
  52. // @match *://*.shellshockers.us/*
  53. // @match *://*.shellshockers.world/*
  54. // @match *://*.shellshockers.xyz/*
  55. // @match *://*.shellsocks.com/*
  56. // @match *://*.softboiled.club/*
  57. // @match *://*.urbanegger.com/*
  58. // @match *://*.violentegg.club/*
  59. // @match *://*.violentegg.fun/*
  60. // @match *://*.yolk.best/*
  61. // @match *://*.yolk.life/*
  62. // @match *://*.yolk.rocks/*
  63. // @match *://*.yolk.tech/*
  64. // @match *://*.yolk.quest/*
  65. // @match *://*.yolk.today/*
  66. // @match *://*.zygote.cafe/*
  67. // @match *://*.shellshockers.best/*
  68. // @match *://*.eggboy.me/*
  69.  
  70. // @require https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js
  71. // @require https://cdn.jsdelivr.net/npm/tweakpane@3.1.10/dist/tweakpane.min.js
  72. // @require https://cdn.jsdelivr.net/npm/@tweakpane/plugin-essentials@0.1.8/dist/tweakpane-plugin-essentials.min.js
  73. // @require https://cdnjs.cloudflare.com/ajax/libs/jszip/3.7.1/jszip.min.js
  74. //
  75. // @run-at document-end
  76.  
  77. // ==/UserScript==
  78. (function () {
  79. function waitForElement(selector) {
  80. return new Promise((resolve) => {
  81. const intervalId = setInterval(() => {
  82. const element = document.getElementById(selector);
  83. console.log("looking for", selector);
  84. if (element) {
  85. console.dir(`found: ${element}`);
  86. clearInterval(intervalId);
  87. resolve(element);
  88. }
  89. }, 100);
  90. });
  91. }
  92. waitForElement("crosshairContainer").then((e) => {
  93. const tp = {
  94. mainCH: {
  95. color: "#fff",
  96. length: 0.8,
  97. width: 0.3,
  98. opacity: 0.7,
  99. border: "#000000",
  100. rotate: 0,
  101. },
  102. middleDot: {
  103. opacity: 1,
  104. color: "#000",
  105. border: "#000",
  106. size: 0.3,
  107. round: false,
  108. shape: "Dot",
  109. length: 0.5,
  110. width: 0.5,
  111. },
  112. paneSettings: {
  113. width: 300,
  114. tabout: "`",
  115. hidePanel: "h",
  116. },
  117. };
  118.  
  119. function createFolders(NFolder) {
  120. let test = pane.addFolder({
  121. title: NFolder,
  122. expanded: false,
  123. });
  124. return test;
  125. }
  126.  
  127. function createInput(folder, obj, property, options, callback) {
  128. const x = folder.addInput(obj, property, options).on("change", callback);
  129. return x;
  130. }
  131.  
  132. const makeDraggable = function (element, notMenu) {
  133. if (element) {
  134. let offsetX, offsetY;
  135. element.addEventListener("mousedown", function (e) {
  136. const dragElement = function (e) {
  137. const x = ((e.clientX - offsetX) / unsafeWindow.innerWidth) * 100;
  138. const y = ((e.clientY - offsetY) / unsafeWindow.innerHeight) * 100;
  139. const maxX = 100 - (element.offsetWidth / unsafeWindow.innerWidth) * 100;
  140. const maxY = 100 - (element.offsetHeight / unsafeWindow.innerHeight) * 100;
  141. element.style.left = `${Math.max(0, Math.min(x, maxX))}%`;
  142. element.style.top = `${Math.max(0, Math.min(y, maxY))}%`;
  143. };
  144. if (notMenu || e.target.classList.contains("tp-rotv_t")) {
  145. offsetX = e.clientX - element.getBoundingClientRect().left;
  146. offsetY = e.clientY - element.getBoundingClientRect().top;
  147. document.addEventListener("mousemove", dragElement);
  148. document.addEventListener("mouseup", function () {
  149. document.removeEventListener("mousemove", dragElement);
  150. });
  151. e.preventDefault(); // Prevent text selection during drag
  152. }
  153. });
  154. }
  155. };
  156.  
  157. function loadExistingSettings(name, target, callback) {
  158. const stuff = localStorage.getItem(name);
  159.  
  160. if (stuff) {
  161. const parsed = JSON.parse(stuff);
  162.  
  163. Object.assign(target, parsed);
  164. if (typeof callback === "function") callback();
  165. }
  166. }
  167.  
  168. function addInputWithValidation(folder, obj, property, label) {
  169. const df = structuredClone(obj[property]);
  170. folder.addInput(obj, property, { label: label }).on("change", (value) => {
  171. if (value.value.length > 1) {
  172. value.value = df;
  173. obj[property] = df;
  174. console.log(obj[property]);
  175. value.target.controller_.binding.value.rawValue_ = df;
  176. unsafeWindow.alert("Please enter a single key");
  177. } else {
  178. const store = value.value.replace(/"/g, "");
  179. localStorage.setItem(`tp-${property}`, store);
  180. }
  181. });
  182. }
  183.  
  184. const changeMainCH = (obj) => {
  185. const previousStyle = document.getElementById("custom-mainCH");
  186. const containerCH = document.getElementById("crosshairContainer");
  187. containerCH.style.transform = `rotate(${obj.rotate}deg)`;
  188.  
  189. if (previousStyle) {
  190. previousStyle.remove();
  191. }
  192. // Create a new stylesheet
  193. const style = document.createElement("style");
  194. style.id = "custom-mainCH";
  195. style.innerHTML = `
  196. .crosshair {
  197. position: absolute;
  198. transform-origin: 50% top;
  199. top: 50%;
  200. border: solid 0.05em ${obj.border};
  201. height: ${obj.length}em;
  202. opacity: ${obj.opacity};
  203. transform: rotate(${obj.angle || 0}deg);
  204. }
  205. .crosshair.normal {
  206. left: calc(50% - ${obj.width / 2}em);
  207. background: ${obj.color};
  208. width: ${obj.width}em;
  209. }
  210. .crosshair.powerful {
  211. left: calc(50% - ${obj.width / 2}em);
  212. background: red;
  213. width: ${obj.width}em;
  214. }
  215. .shotReticle.fill.normal {
  216. border-color: ${obj.color};
  217. border-left: solid transparent;
  218. border-right: solid transparent;
  219. border-width: 0.18em;
  220. padding: 0.18em;
  221. }
  222. `;
  223.  
  224. document.body.appendChild(style);
  225. };
  226.  
  227. const changeMiddleDot = (obj) => {
  228. const previousStyle = document.getElementById("custom-middleDot");
  229. if (previousStyle) previousStyle.remove();
  230.  
  231. const dot = document.getElementById("reticleDot");
  232.  
  233. dot.innerHTML = "";
  234.  
  235. const style = document.createElement("style");
  236. style.id = "custom-middleDot";
  237.  
  238. if (obj.shape === "plus") {
  239. style.innerHTML = `
  240. #reticleDot {
  241. position: absolute;
  242. top: 50%;
  243. left: 50%;
  244. transform: translate(-50%, -50%);
  245. width: 0;
  246. height: 0;
  247. background: none !important;
  248. border: none !important;
  249. opacity: ${obj.opacity};
  250. }
  251. #reticleDot .bar {
  252. position: absolute;
  253. background-color: ${obj.color};
  254. border: solid 0.05em ${obj.border}
  255. }
  256. #reticleDot .bar.horizontal {
  257. top: 50%;
  258. left: 50%;
  259. width: ${obj.width}px;
  260. height: ${obj.length}px;
  261. transform: translate(-50%, -50%) rotate(90deg);
  262. }
  263. #reticleDot .bar.vertical {
  264. left: 50%;
  265. top: 50%;
  266. width: ${obj.width}px;
  267. height: ${obj.length}px;
  268. transform: translate(-50%, -50%);
  269. }
  270. `;
  271. dot.innerHTML = `
  272. <div class="bar horizontal"></div>
  273. <div class="bar vertical"></div>
  274. `;
  275. } else {
  276. style.innerHTML = `
  277. #reticleDot {
  278. display: block;
  279. position: absolute;
  280. transform: translate(-50%, -50%);
  281. top: 50%;
  282. left: 50%;
  283. background-color: ${obj.color};
  284. border: solid 0.05em ${obj.border};
  285. width: ${obj.size}em;
  286. height: ${obj.size}em;
  287. opacity: ${obj.opacity};
  288. ${obj.round ? "border-radius: 100%;" : ""}
  289. }
  290. `;
  291. }
  292.  
  293. document.body.appendChild(style);
  294. };
  295.  
  296. const Tweakpane = window.Tweakpane;
  297. const pane = new Tweakpane.Pane({
  298. title: "WISH",
  299. expanded: true,
  300. });
  301. const paneEl = document.querySelector("div.tp-dfwv");
  302. paneEl.style.zIndex = 1000;
  303. paneEl.style.width = `300px`;
  304. makeDraggable(document.querySelector(".tp-dfwv"));
  305.  
  306. const folderMainCH = createFolders("Crosshair");
  307. const folderMiddleDot = createFolders("Middle Dot");
  308. const folderPaneSettings = createFolders("Panel Settings");
  309.  
  310. loadExistingSettings("tp-mainCH", tp.mainCH, () => changeMainCH(tp.mainCH));
  311. loadExistingSettings("tp-middleDot", tp.middleDot, () => changeMiddleDot(tp.middleDot));
  312. loadExistingSettings("tp-paneSettings", tp.paneSettings, () => {
  313. const paneEl = document.querySelector("div.tp-dfwv");
  314. paneEl.style.width = `${tp.paneSettings.width}px`;
  315. });
  316.  
  317. createInput(folderMainCH, tp.mainCH, "color", { label: "Color" }, () => {});
  318. createInput(folderMainCH, tp.mainCH, "border", { label: "Border Color" }, () => {});
  319. createInput(folderMainCH, tp.mainCH, "length", { label: "Length", min: 0, max: 10, step: 0.1 }, () => {});
  320. createInput(folderMainCH, tp.mainCH, "width", { label: "Width", min: 0, max: 10, step: 0.1 }, () => {});
  321. createInput(folderMainCH, tp.mainCH, "opacity", { label: "Opacity", min: 0, max: 1, step: 0.01 }, () => {});
  322. createInput(folderMainCH, tp.mainCH, "rotate", { label: "Rotate", min: 0, max: 360, step: 1.0 }, () => {});
  323.  
  324. folderMainCH.on("change", (data) => {
  325. localStorage.setItem("tp-mainCH", JSON.stringify(tp.mainCH));
  326. changeMainCH(tp.mainCH);
  327. });
  328.  
  329. createInput(folderMiddleDot, tp.middleDot, "color", { label: "Color" }, () => {});
  330. createInput(folderMiddleDot, tp.middleDot, "border", { label: "Border Color" }, () => {});
  331. const s = createInput(folderMiddleDot, tp.middleDot, "size", { label: "Size", min: 0, max: 5, step: 0.1 }, () => {});
  332. const r = createInput(folderMiddleDot, tp.middleDot, "round", { label: "Round" }, () => {});
  333. createInput(folderMiddleDot, tp.middleDot, "opacity", { label: "Opacity", min: 0, max: 1, step: 0.01 }, () => {});
  334. createInput(
  335. folderMiddleDot,
  336. tp.middleDot,
  337. "shape",
  338. {
  339. view: "list",
  340. label: "Shape",
  341. options: [
  342. { text: "Dot", value: "dot" },
  343. { text: "Plus", value: "plus" },
  344. ],
  345. },
  346. () => {}
  347. );
  348. const i = createInput(folderMiddleDot, tp.middleDot, "length", { label: "Length", min: 0, max: 100, step: 1 }, () => {});
  349. const x = createInput(folderMiddleDot, tp.middleDot, "width", { label: "Width", min: 0, max: 5, step: 0.1 }, () => {});
  350.  
  351. if (tp.middleDot.shape === "dot") {
  352. i.disabled = true;
  353. x.disabled = true;
  354. } else {
  355. s.disabled = true;
  356. r.disabled = true;
  357. }
  358.  
  359. folderMiddleDot.on("change", (data) => {
  360. localStorage.setItem("tp-middleDot", JSON.stringify(tp.middleDot));
  361. changeMiddleDot(tp.middleDot);
  362. // console.log(tp.middleDot);
  363. if (tp.middleDot.shape === "dot") {
  364. i.disabled = true;
  365. x.disabled = true;
  366. s.disabled = false;
  367. r.disabled = false;
  368. } else {
  369. i.disabled = false;
  370. x.disabled = false;
  371. s.disabled = true;
  372. r.disabled = true;
  373. }
  374. });
  375.  
  376. addInputWithValidation(folderPaneSettings, tp.paneSettings, "hidePanel", "Hide Panel");
  377. addInputWithValidation(folderPaneSettings, tp.paneSettings, "tabout", "Tabout");
  378. createInput(folderPaneSettings, tp.paneSettings, "width", { label: "Panel Width", min: 300, max: 1000, step: 1 }, () => {});
  379. folderPaneSettings.on("change", (data) => {
  380. setTimeout(() => {
  381. const paneEl = document.querySelector("div.tp-dfwv");
  382. paneEl.style.width = `${tp.paneSettings.width}px`;
  383. localStorage.setItem("tp-paneSettings", JSON.stringify(tp.paneSettings));
  384. }, 1000);
  385. });
  386.  
  387. let oldPointerLock;
  388. let disable = () => {
  389. if (document.onpointerlockchange == null) return;
  390. oldPointerLock = document.onpointerlockchange;
  391. document.onpointerlockchange = null;
  392. document.exitPointerLock();
  393. };
  394.  
  395. let enable = () => {
  396. if (document.onpointerlockchange) return;
  397. canvas.requestPointerLock();
  398. document.onpointerlockchange = oldPointerLock;
  399. };
  400.  
  401. let handle = (event) => {
  402. let isPaused = vueApp?.game?.isPaused;
  403. let chatOpened = document.activeElement.id == "chatIn";
  404. if (chatOpened || isPaused) return; // hopefully this also helps prevent people from spamming it
  405. let inGame = extern?.inGame; // uncertain if this is needed?
  406. if (!inGame) return;
  407. document.onpointerlockchange == null ? enable() : disable(); // toggle :blobshrug:
  408. };
  409.  
  410. document.addEventListener("keydown", (event) => {
  411. if (event.key === tp.paneSettings.hidePanel) {
  412. let chatOpened = document.activeElement.id == "chatIn";
  413. if (chatOpened) return;
  414. const element = document.querySelector(".tp-dfwv");
  415. element.style.display = element.style.display === "none" ? "block" : "none";
  416. }
  417.  
  418. if (event.key === tp.paneSettings.tabout) {
  419. handle(event);
  420. }
  421. });
  422. });
  423. })();