Shell Shockers Aimbot & ESP: StateFarm Client V3 - Bloom, Chat, Botting, Unban & More, shellshock.io

Shell Shockers Aimbot & ESP of the highest level. Best shellshock.io menu in 2025 with NO ADS! Many cheats such as Aimbot, PlayerESP, AmmoESP, Chams, Nametags, Join/Leave alerts, Chat Filter Bypass, AntiAFK, FOV Slider, Zooming, Player Stats, Auto Reload, Auto Unban and many more whilst having unsurpassed customisation options such as binding to any key, easily editable color scheme and themes - all on the fly!

  1. // ==UserScript==
  2. // @name Shell Shockers Aimbot & ESP: StateFarm Client V3 - Bloom, Chat, Botting, Unban & More, shellshock.io
  3. // @description Shell Shockers Aimbot & ESP of the highest level. Best shellshock.io menu in 2025 with NO ADS! Many cheats such as Aimbot, PlayerESP, AmmoESP, Chams, Nametags, Join/Leave alerts, Chat Filter Bypass, AntiAFK, FOV Slider, Zooming, Player Stats, Auto Reload, Auto Unban and many more whilst having unsurpassed customisation options such as binding to any key, easily editable color scheme and themes - all on the fly!
  4. // @author Hydroflame521, enbyte, notfood, 1ust, OakSwingZZZ, Seq and de_Neuublue
  5. // @namespace https://github.com/Hydroflame522/StateFarmClient/
  6. // @supportURL https://github.com/Hydroflame522/StateFarmClient/issues/
  7. // @license GPL-3.0
  8. // @run-at document-start
  9.  
  10. // @grant GM_setValue
  11. // @grant GM_getValue
  12. // @grant GM_deleteValue
  13. // @grant GM_listValues
  14. // @grant GM_info
  15. // @grant GM_setClipboard
  16. // @grant GM_openInTab
  17.  
  18. // @grant GM.setValue
  19. // @grant GM.getValue
  20. // @grant GM.deleteValue
  21. // @grant GM.listValues
  22. // @grant GM.info
  23. // @grant GM.setClipboard
  24. // @grant GM.openInTab
  25.  
  26. // @icon https://raw.githubusercontent.com/Hydroflame522/StateFarmClient/main/icons/StateFarmClientLogo384px.png?v=1
  27.  
  28. // @require https://cdn.jsdelivr.net/npm/tweakpane@3.1.10/dist/tweakpane.min.js
  29.  
  30. // version naming:
  31. //3.#.#-pre[number] for development versions, increment for every commit (not full release) note: please increment it
  32. //3.#.#-release for release (in the unlikely event that happens)
  33. // this ensures that each version of the script is counted as different
  34.  
  35. // @version 3.4.3-pre26
  36.  
  37. // @match *://*.shellshock.io/*
  38. // @match *://*.algebra.best/*
  39. // @match *://*.algebra.monster/*
  40. // @match *://*.algebra.vip/*
  41. // @match *://*.biologyclass.club/*
  42. // @match *://*.combateggs.com/*
  43. // @match *://*.deadlyegg.com/*
  44. // @match *://*.deathegg.life/*
  45. // @match *://*.deathegg.world/*
  46. // @match *://*.eggbattle.com/*
  47. // @match *://*.eggboy.club/*
  48. // @match *://*.eggboy.me/*
  49. // @match *://*.eggboy.xyz/*
  50. // @match *://*.eggcombat.com/*
  51. // @match *://*.egg.dance/*
  52. // @match *://*.eggfacts.fun/*
  53. // @match *://*.egggames.best/*
  54. // @match *://*.egghead.institute/*
  55. // @match *://*.eggisthenewblack.com/*
  56. // @match *://*.eggsarecool.com/*
  57. // @match *://*.eggshock.com/*
  58. // @match *://*.eggshock.me/*
  59. // @match *://*.eggshock.net/*
  60. // @match *://*.eggshooter.best/*
  61. // @match *://*.eggshooter.com/*
  62. // @match *://*.eggwarfare.com/*
  63. // @match *://*.eggwars.io/*
  64. // @match *://*.geometry.best/*
  65. // @match *://*.geometry.monster/*
  66. // @match *://*.geometry.pw/*
  67. // @match *://*.geometry.report/*
  68. // @match *://*.hardboiled.life/*
  69. // @match *://*.hardshell.life/*
  70. // @match *://*.humanorganising.org/*
  71. // @match *://*.mathactivity.club/*
  72. // @match *://*.mathactivity.xyz/*
  73. // @match *://*.mathdrills.info/*
  74. // @match *://*.mathdrills.life/*
  75. // @match *://*.mathfun.rocks/*
  76. // @match *://*.mathgames.world/*
  77. // @match *://*.math.international/*
  78. // @match *://*.mathlete.fun/*
  79. // @match *://*.mathlete.pro/*
  80. // @match *://*.overeasy.club/*
  81. // @match *://*.risenegg.com/*
  82. // @match *://*.scrambled.tech/*
  83. // @match *://*.scrambled.today/*
  84. // @match *://*.scrambled.us/*
  85. // @match *://*.scrambled.world/*
  86. // @match *://*.shellgame.me/*
  87. // @match *://*.shellplay.live/*
  88. // @match *://*.shellshockers.best/*
  89. // @match *://*.shellshockers.ca/*
  90. // @match *://*.shellshockers.club/*
  91. // @match *://*.shellshockers.life/*
  92. // @match *://*.shellshockers.site/*
  93. // @match *://*.shellshockers.today/*
  94. // @match *://*.shellshockers.us/*
  95. // @match *://*.shellshockers.website/*
  96. // @match *://*.shellshockers.wiki/*
  97. // @match *://*.shellshockers.world/*
  98. // @match *://*.shellshockers.xyz/*
  99. // @match *://*.shellshock.guru/*
  100. // @match *://*.shellsocks.com/*
  101. // @match *://*.softboiled.club/*
  102. // @match *://*.urbanegger.com/*
  103. // @match *://*.violentegg.club/*
  104. // @match *://*.violentegg.fun/*
  105. // @match *://*.yolk.best/*
  106. // @match *://*.yolk.life/*
  107. // @match *://*.yolk.monster/*
  108. // @match *://*.yolk.rocks/*
  109. // @match *://*.yolk.tech/*
  110. // @match *://*.yolk.quest/*
  111. // @match *://*.yolk.today/*
  112. // @match *://*.zygote.cafe/*
  113. // @match *://*.getstate.farm/*
  114. // @match *://localhost:5173/*
  115. // @antifeature membership
  116. // ==/UserScript==
  117.  
  118. if (false) {
  119. const consoleMethods = ["log", "warn", "info", "error", "exception", "table", "trace"];
  120. const _innerConsole = console;
  121.  
  122. consoleMethods.forEach(method => {
  123. if (unsafeWindow.console[method]) {
  124. Object.defineProperty(unsafeWindow.console, method, {
  125. configurable: false,
  126. get: (...args) => {
  127. return _innerConsole[method].bind(_innerConsole);
  128. },
  129. set: () => {}
  130. });
  131. }
  132. });
  133. }
  134.  
  135. let _dateNow = unsafeWindow.Date.now;
  136. /*unsafeWindow.Date.now = () => {
  137. try {
  138. throw new Error("skibidi");
  139. } catch (e) {
  140. //console.log(e.stack);
  141. if (e.stack.includes('imports.wbg.__wbg_now')) {
  142. //return 1743774560481;
  143. }
  144. else return _dateNow();
  145. }
  146. };*/
  147.  
  148. let attemptedInjection = false;
  149. // log("StateFarm: running (before function)");
  150.  
  151. (function () {
  152. //onlypuppy7 leaving alert
  153. if (!GM_getValue("onlypuppy7Alert")) {
  154. alert("Notice: onlypuppy7 is no longer maintaining this script. Please report any bugs to Hydroflame521 or 1ust. Thank you for your understanding.");
  155. GM_setValue("onlypuppy7Alert", true);
  156. };
  157.  
  158. if ((location.hostname.includes('getstate.farm') || location.hostname == 'localhost') && typeof unsafeWindow !== 'undefined') {
  159. unsafeWindow.userscript = typeof GM_info !== 'undefined' ? GM_info : false;
  160.  
  161. const bannedKeys = ['LoginDB', 'AccountRecords', 'MostRecentEmail'];
  162.  
  163. if (typeof GM_listValues !== 'undefined' && typeof GM_getValue !== 'undefined') {
  164. let keyArr = GM_listValues();
  165. const allValues = {};
  166. keyArr = keyArr.filter((key) => !bannedKeys.includes(key));
  167. keyArr.forEach((key) => allValues[key] = GM_getValue(key));
  168. unsafeWindow.gm = allValues;
  169. }
  170.  
  171. if (typeof GM_setValue !== 'undefined') unsafeWindow.onmessage = (m) => {
  172. if (m.data.source !== 'getstate.farm') return;
  173.  
  174. if (m.data.type == 'GM.setValue') GM_setValue(m.data.key, m.data.value);
  175. }
  176. return;
  177. }
  178.  
  179. if (typeof isCrackedShell !== 'undefined') alert('CrackedShell v1 is no longer supported. Upgrade to v2.');
  180.  
  181. let crackedShell = typeof $WEBSOCKET !== 'undefined';
  182.  
  183. if (crackedShell) {
  184. GM_getValue = (name) => {
  185. try {
  186. return JSON.parse(localStorage.getItem(name));
  187. } catch {
  188. return localStorage.getItem(name);
  189. };
  190. };
  191. GM_setValue = (name, value) => {
  192. if (typeof value === 'object') localStorage.setItem(name, JSON.stringify(value));
  193. else localStorage.setItem(name, value);
  194. };
  195. GM_listValues = () => Object.keys(localStorage);
  196. GM_deleteValue = (...a) => localStorage.removeItem(...a);
  197. GM_openInTab = (link) => window.open(link, '_blank');
  198. GM_setClipboard = (text, _, callback) => navigator.clipboard.writeText(text).then(() => callback());
  199. unsafeWindow = window;
  200. };
  201.  
  202. const storageKey = "StateFarm_" + (unsafeWindow.document.location.host.replaceAll(".", "")) + "_";
  203. const log = function(...args) {
  204. let condition;
  205. try {
  206. condition = extract("consoleLogs");
  207. } catch (error) {
  208. condition = GM_getValue(storageKey + "DisableLogs");
  209. };
  210. if (!condition) {
  211. console.log(...args);
  212. };
  213. };
  214.  
  215. let originalReplace = String.prototype.replace;
  216. let originalReplaceAll = String.prototype.replaceAll;
  217.  
  218. String.prototype.originalReplace = function () {
  219. return originalReplace.apply(this, arguments);
  220. };
  221. String.prototype.originalReplaceAll = function () {
  222. return originalReplaceAll.apply(this, arguments);
  223. };
  224.  
  225. log("StateFarm: running (after function)");
  226. //script info
  227. const name = "ЅtateFarm Client";
  228. const version = typeof (GM_info) !== 'undefined' ? GM_info.script.version : "3";
  229. const menuTitle = name + " v" + version;
  230.  
  231. //INIT WEBSITE LINKS: store them here so they are easy to maintain and update!
  232. const discordURL = "https://dsc.gg/sfnetwork";
  233. const discordName = "Farmer's Workers' Union";
  234. const greasyforkID = "482982";
  235. const githubID = "Hydroflame522/StateFarmClient";
  236. const youtubeURL = "https://www.youtube.com/@StateFarmClientV3";
  237.  
  238. const greasyforkURL = `https://gf.qytechs.cn/en/scripts/${greasyforkID}`;
  239. const downloadURL = `https://update.gf.qytechs.cn/scripts/${greasyforkID}/user.js`;
  240. const updateURL = `https://update.gf.qytechs.cn/scripts/${greasyforkID}/meta.js`;
  241. const scriptInfoURL = `https://gf.qytechs.cn/scripts/${greasyforkID}.json`;
  242.  
  243. //all of this github stuff assumes youve cloned the repo
  244. const githubURL = `https://github.com/${githubID}`;
  245. const featuresGuideURL = `https://github.com/${githubID}/tree/main?tab=readme-ov-file#-features`;
  246. const bottingGuideURL = `https://github.com/${githubID}/tree/main?tab=readme-ov-file#-botting`;
  247.  
  248. const replacementLogoURL = `https://cdn.jsdelivr.net/gh/${githubID}@main/icons/shell-logo-replacement.png`;
  249. const replacementLogoHalloweenURL = `https://cdn.jsdelivr.net/gh/${githubID}@main/icons/shell-logo-replacement-halloween.png`;
  250. const replacementLogoChristmasURL = `https://cdn.jsdelivr.net/gh/${githubID}@main/icons/shell-logo-replacement-christmas.png`;
  251. const replacementLogoNewYearsURL = `https://cdn.jsdelivr.net/gh/${githubID}@main/icons/shell-logo-replacement-new-years.png`;
  252.  
  253. const replacementFeedURL = `https://raw.githubusercontent.com/${githubID}/main/ingamefeeds/`;
  254. const commitFeedURL = `https://api.github.com/repos/${githubID}/commits?path=StateFarmClient.js`;
  255. const badgeListURL = `https://cdn.jsdelivr.net/gh/${githubID}@main/ingamebadges/`;
  256. const iconURL = `https://cdn.jsdelivr.net/gh/${githubID}@main/icons/StateFarmClientLogo384px.png`;
  257. const itsOverURL = `https://cdn.jsdelivr.net/gh/${githubID}@main/assets/its%20over/ItsOver4Smaller_.png`;
  258. const eggShowURL = `https://cdn.jsdelivr.net/gh/${githubID}@main/assets/show/EggShowSmaller_.png`;
  259. const sfxURL = `https://api.github.com/repos/${githubID}/contents/soundpacks/sfx`;
  260. const skyboxListURL = `https://api.github.com/repos/${githubID}/contents/skyboxes/`;
  261.  
  262. //misc: statefarm external services
  263. const factoryURL = 'https://factory.getstate.farm/api/account?key=';
  264. const clientKeysURL = `https://js.getstate.farm/vardata/`;
  265. const sfChatURL = `https://raw.githack.com/OakSwingZZZ/StateFarmChatFiles/main/index.html`;
  266.  
  267. //misc: non sfc external things
  268. const babylonURL = `https://cdn.jsdelivr.net/npm/babylonjs@{0}/babylon.min.js`;
  269. const violentmonkeyURL = `https://violentmonkey.github.io/get-it/`;
  270.  
  271. //various debug fun things
  272. const __DEBUG__ = {
  273. forceTriggerVarData: false
  274. }
  275.  
  276. //startup sequence
  277. const startUp = function () {
  278. log("StateFarm: detectURLParams()");
  279. detectURLParams();
  280. log("StateFarm: mainLoop()");
  281. mainLoop();
  282. log("StateFarm: injectScript()");
  283. injectScript();
  284. document.addEventListener("DOMContentLoaded", function () {
  285. onContentLoaded();
  286. log("StateFarm: DOMContentLoaded, ran onContentLoaded, fetching sfx");
  287. try {
  288. log("fetching badge list...", badgeListURL + "badges.json");
  289. badgeList = fetchTextContent(badgeListURL + "badges.json");
  290. badgeList = JSON.parse(badgeList);
  291. log(badgeList);
  292. } catch (error) {
  293. log("couldnt fetch badge list :(");
  294. };
  295. try {
  296. log("fetching greasyfork info...", scriptInfoURL);
  297. scriptInfo = fetchTextContent(scriptInfoURL);
  298. scriptInfo = JSON.parse(scriptInfo);
  299. log(scriptInfo);
  300. } catch (error) {
  301. log("couldnt fetch greasyfork info :(");
  302. };
  303.  
  304. let oldVersion = load("version");
  305. save("version", version);
  306.  
  307. if (extract("statefarmUpdates")) {
  308. const maxAttempts = 30;
  309. const interval = 500;
  310. let attempts = 0;
  311.  
  312. const checkForElement = function() {
  313. const existingContainer = document.querySelector('.secondary-aside-wrap');
  314.  
  315. if (existingContainer) {
  316. log('Element found:', existingContainer);
  317. createAndAppendCommitHistoryBox(existingContainer);
  318. } else if (attempts < maxAttempts) {
  319. attempts++;
  320. // log(`Attempt ${attempts}/${maxAttempts} failed. Retrying...`);
  321. setTimeout(checkForElement, interval); //retry after interval
  322. } else {
  323. log('Element not found after maximum attempts');
  324. }
  325. };
  326.  
  327. const createAndAppendCommitHistoryBox = function(existingContainer) {
  328. let commitHistoryBox = document.createElement('div');
  329. commitHistoryBox.className = 'media-tabs-wrapper box_relative border-blue5 roundme_sm bg_blue6 common-box-shadow ss_margintop_sm';
  330.  
  331. let commitHistoryContent = `
  332. <div class="media-tab-container display-grid align-items-center gap-sm bg_blue3">
  333. <h4 class="common-box-shadow text-shadow-black-40 text_white dynamic-text" style="display: flex; align-items: center;">
  334. <div class="dynamic-text" style="width: 10em; font-size: 1em;">
  335. <div class="dynamic-text" style="font-size: 1em;">StateFarm Updates</div>
  336. </div>
  337. <a href="${discordURL}" target="_blank" style="text-decoration: none; margin-left: auto;">
  338. <button class="ss_button btn_blue bevel_blue box_relative pause-screen-ui btn-account-w-icon text-shadow-none text_blue1" style="font-size: 0.75em; display: flex; align-items: center; padding: 0.5em 1em; width: 12em; margin-left: -3em;">
  339. <i class="fab fa-discord" style="font-size: 1.2em; margin-right: 0.5em;"></i>
  340. <span>Join Discord</span>
  341. </button>
  342. </a>
  343. </h4>
  344. </div>
  345. <div class="media-tabs-content f_col">
  346. <div class="tab-content ss_paddingright ss_paddingleft">
  347. <div class="news-container f_col v_scroll" style="height: 20em; overflow-y: auto;">
  348. `;
  349.  
  350. let disablePlayButton = vueApp.disablePlayButton;
  351. vueApp.disablePlayButton = (isDisabled) => {
  352. log('called disablePlayButton, so we are handling the statefarm updates box')
  353.  
  354. if (isDisabled) commitHistoryBox.style.display = 'none';
  355. else commitHistoryBox.style.display = '';
  356.  
  357. return disablePlayButton(isDisabled);
  358. };
  359.  
  360. fetch(commitFeedURL).then(response => {
  361. if (response.ok) return response.json();
  362. else throw new Error('Failed to fetch commit history contents');
  363. }).then(commitHistory => {
  364. log("retrieved: commit history", commitHistory);
  365.  
  366. if (oldVersion !== version) {
  367. commitHistoryContent += `
  368. <a href="${githubURL}" target="_blank" style="text-decoration: none;">
  369. <div class="updated-notice" style="background-color: #28a745; color: #fff; padding: 0.75em; text-align: center; font-weight: bold; margin-bottom: 0.15em; margin-top: 0.25em; border-radius: 10px; border: 2px solid #155724;">
  370. <p style="margin: 0; font-size: 0.95em;">🎉 StateFarm has been updated (v${version})! Check out the latest updates below.</p>
  371. </div>
  372. </a>
  373. `;
  374. };
  375.  
  376. if (scriptInfo && scriptInfo.version && scriptInfo.version !== version && typeof (GM_info) !== 'undefined') {
  377. commitHistoryContent += `
  378. <a href="${downloadURL}" target="_blank" style="text-decoration: none;">
  379. <div class="attention-notice" style="background-color: #ffcc00; color: #000; padding: 0.75em; text-align: center; font-weight: bold; margin-bottom: 0.15em; margin-top: 0.25em; border-radius: 5px; border: 2px solid #ffff00;">
  380. <p style="margin: 0; font-size: 0.95em;">🚨 A new update for StateFarm is available (v${scriptInfo.version})! Click to install it.</p>
  381. </div>
  382. </a>
  383. `;
  384. };
  385.  
  386. commitHistory.forEach(commit => {
  387. const commitDate = new Date(commit.commit.author.date).toLocaleString();
  388. const authorProfileURL = `https://github.com/${commit.author.login}`; //replace with actual url if available
  389. const messageParts = commit.commit.message.split('\n\n', 2); //split by the first occurrence of '\n\n'
  390. const title = messageParts[0]; //title part of the message
  391. const description = messageParts[1] || ''; //description part of the message, defaults to empty string if not present
  392.  
  393. commitHistoryContent += `
  394. <div class="commit-item" style="padding: 0.2em 0.3em; background-color: #95e2fe; border-bottom: 2px solid #0B93BD;">
  395. <div style="display: flex; align-items: flex-start;">
  396. <a href="${authorProfileURL}" target="_blank" style="margin-right: 0.3em; display: flex; align-items: flex-start;">
  397. <img src="${commit.author.avatar_url}" alt="${commit.author.login}" style="width: 24px; height: 24px; border-radius: 50%;">
  398. </a>
  399. <div style="display: flex; flex-direction: column; justify-content: flex-start;">
  400. <a href="${commit.html_url}" target="_blank" style="color: #0E7697; text-decoration: none; font-size: 0.75em; font-weight: bold; line-height: 1.2;">
  401. ${title}
  402. </a>
  403. ${description ? `<p style="color: #0B93BD; font-size: 0.65em; margin: 0; line-height: 1.2;">${description}</p>` : ''}
  404. <span style="color: white; font-size: 0.75em; font-weight: bold;">
  405. by <a href="${authorProfileURL}" target="_blank" style="color: #0E7697; text-decoration: none; font-size: 0.75em;">${commit.author.login}</a> on ${commitDate}
  406. </span>
  407. </div>
  408. </div>
  409. </div>
  410. `;
  411. });
  412.  
  413. commitHistoryContent += `
  414. </div>
  415. </div>
  416. </div>
  417. `;
  418.  
  419. commitHistoryBox.innerHTML = commitHistoryContent;
  420. existingContainer.appendChild(commitHistoryBox);
  421. }).catch(error => {
  422. log('Error:', error);
  423. });
  424. };
  425.  
  426.  
  427. checkForElement();
  428. };
  429.  
  430. (async () => {
  431. try {
  432. var response = await fetch(sfxURL);
  433. if (!response.ok) throw new Error('Failed to fetch folder contents (custom sfx)');
  434.  
  435. var data = await response.json();
  436. data.forEach((file) => {
  437. retrievedSFX.push({ text: file.name.replace(".zip", ""), value: btoa(file.download_url) });
  438. });
  439. //1ust i hated your implementation and this is me showing that i reached my breaking point.
  440. var response = await fetch(skyboxListURL); //when the nice guy loses his temper
  441. if (!response.ok) throw new Error('Failed to fetch folder contents (custom skyboxes)');
  442.  
  443. var data = await response.json();
  444. data.forEach((folder) => {
  445. if (folder.type === "dir") {
  446. let url = folder.url;
  447. //make it into a download url
  448. url = url.replace("//api.github.com/repos/", "//raw.githubusercontent.com/");
  449. url = url.replace("/contents/", "/master/");
  450. url = `${url.split("?")[0]}/`;
  451. loadedSkyboxes.push({
  452. text: folder.name,
  453. value: btoa(url)
  454. });
  455. };
  456. });
  457.  
  458. initMenu(false);
  459. tp.mainPanel.hidden = extract("hideAtStartup");
  460. } catch (error) {
  461. console.error('Error:', error);
  462. initMenu(false);
  463. tp.mainPanel.hidden = extract("hideAtStartup");
  464. };
  465. })();
  466. });
  467.  
  468. };
  469.  
  470. //INIT VARS
  471. const inbuiltPresets = { //Don't delete onlypuppy7's Config
  472. "onlypuppy7's Config": `sfChatNotifications>true<sfChatNotificationSound>true<sfChatAutoStart>true<sfChatInvitations>true<aimbot>true<aimbotTargetMode>0<aimbotVisibilityMode>1<aimbotRightClick>true<silentAimbot>false<aimbSemiSilent>false<noWallTrack>false<prediction>true<antiBloom>true<antiSwitch>false<oneKill>false<aimbotMinAngle>360<antiSneak>1.8<aimbotAntiSnap>0<aimbotAntiSnapRegime>3<maxAimTime>64<autoRefill>true<smartRefill>true<enableAutomatic>true<enableAutoFire>true<autoFireType>3<autoFireAccuracy>0.05<grenadeMax>true<grenadePower>1<playerESP>true<tracers>true<chams>false<trajectories>true<predictionESP>false<nametags>true<nametagInfo>false<nametagInfoInterval>5<aimbotColor>"#0000ff"<aimbotRainbow>false<tracersType>2<tracersColor1Rainbow>true<tracersColor1>"#ff0000"<tracersColor2>"#00ff00"<tracersColor3>"#ffffff"<tracersColor1to2>5<tracersColor2to3>15<predictionESPColor>"#ff0000"<predictionESPColorRainbow>false<ammoESP>true<ammoTracers>false<ammoESPRegime>1<ammoESPColor>"#ffff00"<grenadeESP>true<grenadeTracers>false<grenadeESPRegime>2<grenadeESPColor>"#00ffff"<lookTracers>false<lookTracersRGI1>false<lookTracersColor>"#00ffff"<fov>120<zoom>15<perspective>0<perspectiveY>0.5<perspectiveZ>2<freecam>false<wireframe>false<particleSpeedMultiplier>0.35<eggSize>1<setDetail>0<enableTextures>true<renderDelay>0<revealBloom>true<showLOS>true<showMinAngle>true<highlightLeaderboard>true<showCoordinates>true<radar>false<playerStats>true<playerInfo>true<gameInfo>true<showStreams>true<minimap>false<minimapZoom>5<minimapSize>1<chatExtend>true<chatHighlight>false<maxChat>10<disableChatFilter>true<unfilterNames>true<chatFilterBypass>false<tallChat>false<fakeMessageID>0<fakeMessageText>"dsc.gg/s𝖿network: ЅtateFarm Client v3.4.1-pre154 On Top! "<fakeMessageBold>false<spamChat>false<spamChatDelay>500<spamChatText>"dsc.gg/s𝖿network: ЅtateFarm Client v3.4.1-pre154 On Top! "<mockMode>false<announcer>false<autoEZ>false<cheatAccuse>false<joinMessages>true<leaveMessages>true<publicBroadcast>false<joinLeaveBranding>false<whitelist>"User-1, User-2"<enableWhitelistAimbot>false<enableWhenNoneVisible>false<enableWhitelistTracers>false<whitelistESPType>0<whitelistColor>"#e80aac"<blacklist>"User-1, User-2"<enableBlacklistAimbot>false<enableBlacklistTracers>false<blacklistESPType>0<blacklistColor>"#00ff00"<bunnyhop>true<autoWalk>false<autoStrafe>false<autoJump>false<autoJumpDelay>1<autoWeapon>0<autoGrenade>false<autoJoin>false<joinCode>"CODE"<useCustomName>false<usernameAutoJoin>"ЅtateFarmer"<autoRespawn>false<autoTeam>0<gameBlacklist>false<gameBlacklistCodes>""<leaveEmpty>false<autoLeave>false<autoLeaveDelay>300<autoGamemode>0<autoRegion>0<eggColor>14<autoStamp>0<autoHat>0<skybox>1<randomSkyBox>true<randomSkyBoxInterval>5.9<legacyModels>true<filter>0<gunPosition>true<bobModifierEnabled>true<bobModifier>0.25<bobModifierWhenStill>true<muteGame>false<distanceMult>1.5<customSFX1>3<customSFX2>4<customSFX3>5<replaceLogo>true<titleAnimation>true<themeType>5<partyLightsEnabled>true<partyLightsIntensity>1.87<worldFlattening>1<loginEmailPass>"ssss"<loginDatabaseSelection>1<autoLogin>0<accountGmail>"example (NO @gmail.com)"<accountPass>"password69"<accountRecordsLogging>false<factoryKey>""<autoUnban>true<adBlock>true<spoofVIP>true<noAnnoyances>true<noTrack>true<antiAFK>true<quickRespawn>true<statefarmUpdates>true<replaceFeeds>true<customBadges>true<unlockSkins>false<adminSpoof>false<autoChickenWinner>true<chickenWinnerNotifs>true<customMacro>"log('cool');"<autoMacro>false<silentRoll>false<enableSeizureX>false<amountSeizureX>2<enableSeizureY>false<amountSeizureY>2<vardataFallback>0<vardataType>0<vardataCustom>"{}"<hideAtStartup>false<consoleLogs>false<popups>true<tooltips>true<enablePanic>true<panicURL>"https://classroom.google.com/"<selectedPreset>0<debug>false`,
  473. "OP7 + Server Hopper": `sfChatNotifications>true<sfChatNotificationSound>true<sfChatAutoStart>true<aimbot>true<aimbotTargetMode>0<aimbotVisibilityMode>1<aimbotRightClick>true<silentAimbot>false<aimbSemiSilent>false<noWallTrack>false<prediction>true<antiBloom>true<antiSwitch>true<oneKill>true<aimbotMinAngle>174<aimbotAntiSnap>0.75<antiSneak>1.8<aimbotColor>"#0000ff"<autoRefill>true<smartRefill>true<enableAutoFire>true<autoFireType>3<grenadeMax>true<playerESP>true<tracers>true<chams>false<nametags>true<targets>false<predictionESP>false<tracersType>0<tracersColor1>"#ff0000"<tracersColor2>"#00ff00"<tracersColor3>"#ffffff"<tracersColor1to2>5<tracersColor2to3>15<predictionESPColor>"#ff0000"<ammoESP>true<ammoTracers>false<ammoESPRegime>1<ammoESPColor>"#ffff00"<grenadeESP>true<grenadeTracers>false<grenadeESPRegime>2<grenadeESPColor>"#00ffff"<lookTracers>false<lookTracersRGI1>false<lookTracersColor>"#00ffff"<fov>120<zoom>15<perspective>0<perspectiveAlpha>false<perspectiveY>0.5<perspectiveZ>2<freecam>false<wireframe>false<particleSpeedMultiplier>0.35<eggSize>1<setDetail>0<enableTextures>true<renderDelay>0<revealBloom>true<showLOS>true<showMinAngle>false<highlightLeaderboard>true<showCoordinates>true<radar>false<playerStats>true<playerInfo>true<gameInfo>true<showStreams>true<chatExtend>true<chatHighlight>false<maxChat>10<disableChatFilter>true<unfilterNames>true<chatFilterBypass>false<tallChat>false<antiAFK>false<spamChat>false<fakeMessageID>12<fakeMessageText>"dsc.gg/s𝖿network: ЅtateFarm Client v3.4.1-pre94 On Top! "<fakeMessageBold>false<spamChatDelay>500<spamChatText>"dsc.gg/s𝖿network: ЅtateFarm Client v3.4.1-pre71 On Top! "<mockMode>false<announcer>false<autoEZ>false<cheatAccuse>false<joinMessages>true<leaveMessages>true<publicBroadcast>false<joinLeaveBranding>false<whitelist>"User-1, User-2"<enableWhitelistAimbot>false<enableWhenNoneVisible>false<enableWhitelistTracers>false<whitelistESPType>0<whitelistColor>"#e80aac"<blacklist>"User-1, User-2"<enableBlacklistAimbot>false<enableBlacklistTracers>false<blacklistESPType>0<blacklistColor>"#00ff00"<bunnyhop>true<autoWalk>false<autoStrafe>false<autoJump>false<autoJumpDelay>1<autoWeapon>0<autoGrenade>false<autoJoin>false<joinCode>"CODE"<useCustomName>false<usernameAutoJoin>"ЅtateFarmer"<autoRespawn>false<autoTeam>0<gameBlacklist>false<gameBlacklistCodes>""<leaveEmpty>true<autoLeave>true<autoLeaveDelay>150<autoGamemode>5<autoRegion>8<eggColor>0<autoStamp>0<autoHat>0<skybox>9<legacyModels>true<filter>2<gunPosition>0<muteGame>false<distanceMult>1.5<customSFX1>3<customSFX2>4<customSFX3>1<replaceLogo>true<titleAnimation>true<themeType>5<loginEmailPass>"ssss"<loginDatabaseSelection>1<autoLogin>0<accountGmail>"example (NO @gmail.com)"<accountPass>"password69"<accountRecordsLogging>false<factoryKey>""<adBlock>true<spoofVIP>false<noAnnoyances>true<noTrack>true<quickRespawn>true<statefarmUpdates>true<replaceFeeds>true<customBadges>true<unlockSkins>false<adminSpoof>false<autoUnban>true<autoChickenWinner>true<customMacro>"log('cool');"<autoMacro>false<silentRoll>false<enableSeizureX>false<amountSeizureX>2<enableSeizureY>false<amountSeizureY>2<hideAtStartup>false<consoleLogs>false<popups>true<enablePanic>false<panicURL>"https://classroom.google.com/"<selectedPreset>0<debug>false`,
  474. "OP7 + Server Hopper + Stream Stealth": `sfChatNotifications>true<sfChatNotificationSound>true<sfChatAutoStart>true<aimbot>true<aimbotTargetMode>0<aimbotVisibilityMode>1<aimbotRightClick>true<silentAimbot>true<aimbSemiSilent>false<noWallTrack>false<prediction>true<antiBloom>true<antiSwitch>false<oneKill>false<aimbotMinAngle>174<aimbotAntiSnap>0.75<antiSneak>1.8<aimbotColor>"#0000ff"<autoRefill>true<smartRefill>true<enableAutoFire>true<autoFireType>3<grenadeMax>true<playerESP>false<tracers>false<chams>false<nametags>true<targets>false<predictionESP>false<tracersType>0<tracersColor1>"#ff0000"<tracersColor2>"#00ff00"<tracersColor3>"#ffffff"<tracersColor1to2>5<tracersColor2to3>15<predictionESPColor>"#ff0000"<ammoESP>false<ammoTracers>false<ammoESPRegime>1<ammoESPColor>"#ffff00"<grenadeESP>false<grenadeTracers>false<grenadeESPRegime>2<grenadeESPColor>"#00ffff"<lookTracers>false<lookTracersRGI1>false<lookTracersColor>"#00ffff"<fov>120<zoom>15<perspective>0<perspectiveAlpha>false<perspectiveY>0.5<perspectiveZ>2<freecam>false<wireframe>false<particleSpeedMultiplier>0.35<eggSize>1<setDetail>0<enableTextures>true<renderDelay>0<revealBloom>false<showLOS>false<showMinAngle>false<highlightLeaderboard>true<showCoordinates>false<radar>false<playerStats>false<playerInfo>false<gameInfo>true<showStreams>false<chatExtend>true<chatHighlight>false<maxChat>10<disableChatFilter>true<unfilterNames>true<chatFilterBypass>false<tallChat>false<antiAFK>false<spamChat>false<fakeMessageID>1<fakeMessageText>"dsc.gg/s𝖿network: ЅtateFarm Client v3.4.1-pre95 On Top! "<fakeMessageBold>false<spamChatDelay>500<spamChatText>"dsc.gg/s𝖿network: ЅtateFarm Client v3.4.1-pre95 On Top! "<mockMode>false<announcer>false<autoEZ>false<cheatAccuse>false<joinMessages>true<leaveMessages>true<publicBroadcast>false<joinLeaveBranding>false<whitelist>"User-1, User-2"<enableWhitelistAimbot>false<enableWhenNoneVisible>false<enableWhitelistTracers>false<whitelistESPType>0<whitelistColor>"#e80aac"<blacklist>"User-1, User-2"<enableBlacklistAimbot>false<enableBlacklistTracers>false<blacklistESPType>0<blacklistColor>"#00ff00"<bunnyhop>true<autoWalk>false<autoStrafe>false<autoJump>false<autoJumpDelay>1<autoWeapon>0<autoGrenade>false<autoJoin>false<joinCode>"CODE"<useCustomName>true<usernameAutoJoin>"[sfc] onlypuppy7"<autoRespawn>false<autoTeam>0<gameBlacklist>false<gameBlacklistCodes>""<leaveEmpty>true<autoLeave>true<autoLeaveDelay>150<autoGamemode>5<autoRegion>8<eggColor>0<autoStamp>0<autoHat>0<skybox>9<legacyModels>true<filter>true<gunPosition>true<muteGame>false<distanceMult>1.5<customSFX1>3<customSFX2>4<customSFX3>1<replaceLogo>true<titleAnimation>false<themeType>5<loginEmailPass>"ssss"<loginDatabaseSelection>1<autoLogin>0<accountGmail>"example (NO @gmail.com)"<accountPass>"password69"<accountRecordsLogging>false<factoryKey>""<adBlock>true<spoofVIP>false<noAnnoyances>true<noTrack>true<quickRespawn>true<statefarmUpdates>true<replaceFeeds>true<customBadges>true<unlockSkins>false<adminSpoof>false<autoUnban>true<autoChickenWinner>true<customMacro>"log('cool');"<autoMacro>false<silentRoll>false<enableSeizureX>false<amountSeizureX>2<enableSeizureY>false<amountSeizureY>2<hideAtStartup>false<consoleLogs>false<popups>false<enablePanic>false<panicURL>"https://classroom.google.com/"<selectedPreset>1<debug>false`,
  475. "Doeshotter's Crackshot Config": `sfChatNotifications>false<sfChatNotificationSound>false<sfChatAutoStart>false<sfChatInvitations>true<aimbot>true<aimbotTargetMode>0<aimbotVisibilityMode>2<aimbotRightClick>true<silentAimbot>true<aimbSemiSilent>false<noWallTrack>false<prediction>true<antiBloom>true<antiSwitch>true<oneKill>false<aimbotMinAngle>7<antiSneak>0<aimbotAntiSnap>0<autoRefill>true<smartRefill>true<enableAutomatic>true<enableAutoFire>true<autoFireType>3<autoFireAccuracy>0.15000000000000002<grenadeMax>false<grenadePower>1<playerESP>true<tracers>false<chams>false<trajectories>true<predictionESP>false<nametags>true<nametagInfo>false<nametagInfoInterval>14<aimbotColor>"#ff0000"<aimbotRainbow>false<tracersType>2<tracersColor1Rainbow>true<tracersColor1>"#ff0000"<tracersColor2>"#0000ff"<tracersColor3>"#ffffff"<tracersColor1to2>5<tracersColor2to3>15<predictionESPColor>"#ff0000"<predictionESPColorRainbow>false<ammoESP>false<ammoTracers>false<ammoESPRegime>0<ammoESPColor>"#ffff00"<grenadeESP>false<grenadeTracers>false<grenadeESPRegime>0<grenadeESPColor>"#00ffff"<lookTracers>false<lookTracersRGI1>false<lookTracersColor>"#00ffff"<fov>72<zoom>15<perspective>0<perspectiveAlpha>false<perspectiveY>0.5<perspectiveZ>2<freecam>false<wireframe>false<particleSpeedMultiplier>1<eggSize>1<setDetail>0<enableTextures>true<renderDelay>0<revealBloom>true<showLOS>true<showMinAngle>false<highlightLeaderboard>false<showCoordinates>false<radar>false<playerStats>false<playerInfo>false<gameInfo>false<showStreams>false<minimap>false<minimapZoom>5<minimapSize>1<chatExtend>false<chatHighlight>false<maxChat>5<disableChatFilter>false<unfilterNames>false<chatFilterBypass>false<tallChat>false<fakeMessageID>1<fakeMessageText>"dsc.gg/s𝖿network: ЅtateFarm Client v3.4.1-pre147 On Top! "<fakeMessageBold>false<spamChat>false<spamChatDelay>500<spamChatText>"dsc.gg/s𝖿network: ЅtateFarm Client v3.4.1-pre147 On Top! "<mockMode>false<announcer>false<autoEZ>false<cheatAccuse>false<joinMessages>false<leaveMessages>false<publicBroadcast>false<joinLeaveBranding>false<whitelist>"User-1, User-2"<enableWhitelistAimbot>false<enableWhenNoneVisible>false<enableWhitelistTracers>false<whitelistESPType>0<whitelistColor>"#e80aac"<blacklist>"User-1, User-2"<enableBlacklistAimbot>false<enableBlacklistTracers>false<blacklistESPType>0<blacklistColor>"#00ff00"<bunnyhop>true<autoWalk>false<autoStrafe>false<autoJump>false<autoJumpDelay>1<autoWeapon>0<autoGrenade>false<autoJoin>false<joinCode>"CODE"<useCustomName>false<usernameAutoJoin>"ЅtateFarmer"<autoRespawn>false<autoTeam>0<gameBlacklist>false<gameBlacklistCodes>""<leaveEmpty>false<autoLeave>false<autoLeaveDelay>300<autoGamemode>0<autoRegion>0<eggColor>0<autoStamp>0<autoHat>0<skybox>true<randomSkyBox>false<randomSkyBoxInterval>3<legacyModels>false<filter>true<gunPosition>true<muteGame>false<distanceMult>1<customSFX1>true<customSFX2>true<customSFX3>true<replaceLogo>false<titleAnimation>false<themeType>5<partyLightsEnabled>false<partyLightsIntensity>0.5<loginEmailPass>"ex@gmail.com:passwd"<loginDatabaseSelection>0<autoLogin>0<accountGmail>"example (NO @gmail.com)"<accountPass>"password69"<accountRecordsLogging>false<factoryKey>""<adBlock>false<spoofVIP>false<noAnnoyances>true<noTrack>true<antiAFK>true<quickRespawn>true<statefarmUpdates>true<replaceFeeds>true<customBadges>true<unlockSkins>true<adminSpoof>false<autoUnban>true<autoChickenWinner>false<customMacro>"log('wow ur cool!');"<autoMacro>true<silentRoll>false<enableSeizureX>false<amountSeizureX>2<enableSeizureY>false<amountSeizureY>2<vardataFallback>0<vardataType>0<vardataCustom>"{}"<hideAtStartup>false<consoleLogs>false<popups>true<tooltips>true<enablePanic>false<panicURL>"https://classroom.google.com/"<selectedPreset>0<debug>false`,
  476. // ^^ no idea how to fix blue filter being on, its whatever
  477. // "onlypuppy7's Silent Config": `aimbot>true<aimbotTargetMode>1<aimbotVisibilityMode>1<aimbotRightClick>true<silentAimbot>true<noWallTrack>false<prediction>true<antiBloom>true<antiSwitch>false<oneKill>false<aimbotMinAngle>360<aimbotAntiSnap>0.77<antiSneak>1.8<aimbotColor>"#0000ff"<autoRefill>true<smartRefill>true<enableAutoFire>true<autoFireType>3<grenadeMax>true<playerESP>true<tracers>true<chams>false<nametags>true<targets>true<tracersType>0<tracersColor1>"#ff0000"<tracersColor2>"#00ff00"<tracersColor3>"#ffffff"<tracersColor1to2>5<tracersColor2to3>15<ammoESP>true<ammoTracers>false<ammoESPRegime>1<ammoESPColor>"#ffff00"<grenadeESP>true<grenadeTracers>false<grenadeESPRegime>0<grenadeESPColor>"#00ffff"<fov>120<zoom>15<freecam>false<wireframe>false<eggSize>1<setDetail>0<enableTextures>true<renderDelay>0<revealBloom>true<showLOS>true<showMinAngle>false<highlightLeaderboard>false<showCoordinates>true<radar>false<playerStats>true<playerInfo>true<gameInfo>true<showStreams>true<chatExtend>true<chatHighlight>false<maxChat>10<disableChatFilter>true<chatFilterBypass>false<tallChat>false<antiAFK>true<spamChat>false<spamChatDelay>500<spamChatText>"dsc.gg/s𝖿network: ЅtateFarm Client v3.4.0-pre19 On Top! "<mockMode>false<announcer>false<autoEZ>false<cheatAccuse>false<joinMessages>true<leaveMessages>true<publicBroadcast>false<joinLeaveBranding>false<whitelist>"User-1, User-2"<enableWhitelistAimbot>false<enableWhitelistTracers>false<whitelistESPType>0<whitelistColor>"#e80aac"<blacklist>"User-1, User-2"<enableBlacklistAimbot>false<enableBlacklistTracers>false<blacklistESPType>0<blacklistColor>"#00ff00"<bunnyhop>true<autoWalk>false<autoStrafe>false<autoJump>false<autoJumpDelay>1<autoWeapon>0<autoGrenade>false<autoJoin>false<joinCode>"CODE"<useCustomName>false<usernameAutoJoin>"ЅtateFarmer"<autoRespawn>false<autoTeam>0<gameBlacklist>false<gameBlacklistCodes>""<leaveEmpty>false<autoLeave>false<autoLeaveDelay>300<autoGamemode>0<autoRegion>0<eggColor>0<autoStamp>0<autoHat>0<muteGame>false<distanceMult>1<customSFX>0<adBlock>true<spoofVIP>false<unlockSkins>false<adminSpoof>false<autoUnban>true<silentRoll>false<enableSeizureX>false<amountSeizureX>2<enableSeizureY>false<amountSeizureY>2<popups>true<replaceLogo>true<titleAnimation>true<themeType>5<enablePanic>false<panicURL>"https://classroom.google.com/"<selectedPreset>0<debug>false`,
  478. "Hydroflame521's Config": `aimbot>true<aimbotTargetMode>0<aimbotVisibilityMode>0<aimbotRightClick>true<silentAimbot>false<noWallTrack>true<prediction>true<antiBloom>true<antiSwitch>true<oneKill>true<aimbotMinAngle>30<aimbotAntiSnap>0.77<antiSneak>1.8<aimbotColor>"#0000ff"<autoRefill>true<smartRefill>true<enableAutoFire>true<autoFireType>3<grenadeMax>true<playerESP>true<tracers>true<chams>false<nametags>true<targets>true<tracersType>1<tracersColor1>"#b200ff"<tracersColor2>"#ff0000"<tracersColor3>"#00ff4b"<tracersColor1to2>3<tracersColor2to3>20<ammoESP>true<ammoTracers>false<ammoESPRegime>1<ammoESPColor>"#ffff00"<grenadeESP>true<grenadeTracers>false<grenadeESPRegime>0<grenadeESPColor>"#00ffff"<fov>120<zoom>15<freecam>false<wireframe>false<eggSize>1<setDetail>0<enableTextures>true<renderDelay>0<revealBloom>true<showLOS>true<showMinAngle>false<highlightLeaderboard>false<showCoordinates>true<radar>false<playerStats>true<playerInfo>true<gameInfo>true<showStreams>true<chatExtend>true<chatHighlight>false<maxChat>10<disableChatFilter>true<chatFilterBypass>false<tallChat>false<antiAFK>false<spamChat>false<spamChatDelay>1440<spamChatText>"Live now at twitch.tv/ЅtateFarmNetwork! "<mockMode>false<announcer>false<autoEZ>false<cheatAccuse>false<joinMessages>true<leaveMessages>true<publicBroadcast>false<joinLeaveBranding>false<whitelist>"User-1, User-2"<enableWhitelistAimbot>false<enableWhitelistTracers>false<whitelistESPType>0<whitelistColor>"#e80aac"<blacklist>"User-1, User-2"<enableBlacklistAimbot>false<enableBlacklistTracers>false<blacklistESPType>0<blacklistColor>"#00ff00"<bunnyhop>false<autoWalk>false<autoStrafe>false<autoJump>false<autoJumpDelay>1<autoWeapon>0<autoGrenade>false<autoJoin>false<joinCode>"CODE"<useCustomName>false<usernameAutoJoin>"CaptainShell74"<autoRespawn>false<autoTeam>0<gameBlacklist>false<gameBlacklistCodes>""<leaveEmpty>false<autoLeave>false<autoLeaveDelay>240<autoGamemode>0<autoRegion>0<eggColor>0<autoStamp>0<autoHat>0<muteGame>false<distanceMult>0.59<customSFX>true<adBlock>true<spoofVIP>false<unlockSkins>false<adminSpoof>false<autoUnban>true<silentRoll>false<enableSeizureX>false<amountSeizureX>2<enableSeizureY>false<amountSeizureY>0.04772456526919999<popups>true<replaceLogo>false<titleAnimation>false<themeType>7<enablePanic>false<panicURL>"https://classroom.google.com/"<selectedPreset>0<debug>false`,
  479. // "Server Hopper + Non-Silent": `aimbot>true<aimbotTargetMode>0<aimbotVisibilityMode>0<aimbotRightClick>true<silentAimbot>false<noWallTrack>true<prediction>true<antiBloom>true<antiSwitch>true<oneKill>true<aimbotMinAngle>30<aimbotAntiSnap>0.77<antiSneak>1.8<aimbotColor>"#0000ff"<autoRefill>true<smartRefill>true<enableAutoFire>true<autoFireType>0<grenadeMax>true<playerESP>true<tracers>true<chams>false<nametags>true<targets>true<tracersType>0<tracersColor1>"#ff0000"<tracersColor2>"#00ff00"<tracersColor3>"#ffffff"<tracersColor1to2>5<tracersColor2to3>15<ammoESP>true<ammoTracers>false<ammoESPRegime>1<ammoESPColor>"#ffff00"<grenadeESP>true<grenadeTracers>false<grenadeESPRegime>0<grenadeESPColor>"#00ffff"<fov>120<zoom>15<freecam>false<wireframe>false<eggSize>1<setDetail>0<enableTextures>true<renderDelay>0<revealBloom>true<showLOS>true<showMinAngle>false<highlightLeaderboard>false<showCoordinates>true<radar>false<playerStats>true<playerInfo>true<gameInfo>true<showStreams>true<chatExtend>true<chatHighlight>false<maxChat>10<disableChatFilter>true<chatFilterBypass>false<tallChat>false<antiAFK>true<spamChat>false<spamChatDelay>1440<spamChatText>"Live now at twitch.tv/ЅtateFarmNetwork! "<mockMode>false<announcer>false<autoEZ>false<cheatAccuse>false<joinMessages>true<leaveMessages>true<publicBroadcast>false<joinLeaveBranding>false<whitelist>"User-1, User-2"<enableWhitelistAimbot>false<enableWhitelistTracers>false<whitelistESPType>0<whitelistColor>"#e80aac"<blacklist>"User-1, User-2"<enableBlacklistAimbot>false<enableBlacklistTracers>false<blacklistESPType>0<blacklistColor>"#00ff00"<bunnyhop>true<autoWalk>false<autoStrafe>false<autoJump>false<autoJumpDelay>1<autoWeapon>0<autoGrenade>false<autoJoin>false<joinCode>"CODE"<useCustomName>false<usernameAutoJoin>"CaptainShell74"<autoRespawn>false<autoTeam>0<gameBlacklist>false<gameBlacklistCodes>""<leaveEmpty>false<autoLeave>true<autoLeaveDelay>240<autoGamemode>0<autoRegion>0<eggColor>0<autoStamp>0<autoHat>0<muteGame>false<distanceMult>0.59<customSFX>0<adBlock>true<spoofVIP>false<unlockSkins>false<adminSpoof>false<autoUnban>true<silentRoll>false<enableSeizureX>false<amountSeizureX>2<enableSeizureY>false<amountSeizureY>0.04772456526919999<popups>true<replaceLogo>true<titleAnimation>true<themeType>2<enablePanic>false<panicURL>"https://classroom.google.com/"<selectedPreset>0<debug>false`,
  480. // "Server Hopper + Silent": `aimbot>true<aimbotTargetMode>1<aimbotVisibilityMode>1<aimbotRightClick>true<silentAimbot>true<noWallTrack>false<prediction>true<antiBloom>true<antiSwitch>false<oneKill>false<aimbotMinAngle>360<aimbotAntiSnap>0.77<antiSneak>1.8<aimbotColor>"#0000ff"<autoRefill>true<smartRefill>true<enableAutoFire>true<autoFireType>3<grenadeMax>true<playerESP>true<tracers>true<chams>false<nametags>true<targets>true<tracersType>0<tracersColor1>"#ff0000"<tracersColor2>"#00ff00"<tracersColor3>"#ffffff"<tracersColor1to2>5<tracersColor2to3>15<ammoESP>true<ammoTracers>false<ammoESPRegime>1<ammoESPColor>"#ffff00"<grenadeESP>true<grenadeTracers>false<grenadeESPRegime>0<grenadeESPColor>"#00ffff"<fov>120<zoom>15<freecam>false<wireframe>false<eggSize>1<setDetail>0<enableTextures>true<renderDelay>0<revealBloom>true<showLOS>true<showMinAngle>false<highlightLeaderboard>false<showCoordinates>true<radar>false<playerStats>true<playerInfo>true<gameInfo>true<showStreams>true<chatExtend>true<chatHighlight>false<maxChat>10<disableChatFilter>true<chatFilterBypass>false<tallChat>false<antiAFK>true<spamChat>false<spamChatDelay>1440<spamChatText>"Live now at twitch.tv/ЅtateFarmNetwork! "<mockMode>false<announcer>false<autoEZ>false<cheatAccuse>false<joinMessages>true<leaveMessages>true<publicBroadcast>false<joinLeaveBranding>false<whitelist>"User-1, User-2"<enableWhitelistAimbot>false<enableWhitelistTracers>false<whitelistESPType>0<whitelistColor>"#e80aac"<blacklist>"User-1, User-2"<enableBlacklistAimbot>false<enableBlacklistTracers>false<blacklistESPType>0<blacklistColor>"#00ff00"<bunnyhop>true<autoWalk>false<autoStrafe>false<autoJump>false<autoJumpDelay>1<autoWeapon>0<autoGrenade>false<autoJoin>false<joinCode>"CODE"<useCustomName>false<usernameAutoJoin>"CaptainShell74"<autoRespawn>false<autoTeam>0<gameBlacklist>false<gameBlacklistCodes>""<leaveEmpty>false<autoLeave>true<autoLeaveDelay>240<autoGamemode>0<autoRegion>0<eggColor>0<autoStamp>0<autoHat>0<muteGame>false<distanceMult>0.59<customSFX>true<adBlock>true<spoofVIP>false<unlockSkins>false<adminSpoof>false<autoUnban>true<silentRoll>false<enableSeizureX>false<amountSeizureX>2<enableSeizureY>false<amountSeizureY>0.04772456526919999<popups>true<replaceLogo>true<titleAnimation>true<themeType>2<enablePanic>false<panicURL>"https://classroom.google.com/"<selectedPreset>0<debug>false`,
  481. };
  482. const presetStorageLocation = "StateFarmUserPresets";
  483. let hudElementPositions = {};
  484. let cachedRealData = {};
  485. let blacklistedGameCodes = [];
  486. let sfChatIframe;
  487. let sfChatContainer;
  488. let sfChatUsername;
  489. let presetIgnore = ['sfChatUsername', 'otherSettingYouMightWantNotToBeExported'];
  490. log("Save key:", storageKey);
  491. let binding = false;
  492. let previousFrame = 0;
  493. let framesPassed = 0;
  494. let previousLogin = 0;
  495. let lastSpamMessage = [0, ""];
  496. let startTime = Date.now();
  497. let lastAutoJump = 0;
  498. let lastAntiAFKMessage = 0;
  499. let miniCamera;
  500. let spamMessageCount = 0;
  501. let currentFrameIndex = 0;
  502. let deciSecondsPassed = 0;
  503. let timeJoinedGame = 0;
  504. let lastSentMessage = "";
  505. let spamDelay = 0;
  506. let URLParams = "";
  507. let playerInfoCache = {};
  508. let retrievedSFX = [{ text: "Default", value: "default" }];
  509. let soundsSFC = {};
  510. let targetingComplete = false;
  511. let firstExecution = false;
  512. let username = "";
  513. let autoStrafeValue = [0, 0, "left"];
  514. let TEAMCOLORS = ["#fed838", "#40e0ff", "#ffc0a0"];
  515. let autoLeaveReminder = 9999;
  516. let lastRandomSkyBoxChangeTime = Date.now(); //in milliseconds
  517. const allModules = [];
  518. const allFolders = [];
  519. const F = [];
  520. const createAudioContext = function () { return new (window.AudioContext || window.webkitAudioContext)() };
  521. const audioContexts = {
  522. "BGM": createAudioContext(),
  523. "KOTC": createAudioContext(),
  524. "OTHER1": createAudioContext(),
  525. "OTHER2": createAudioContext(),
  526. "OTHER3": createAudioContext(),
  527. "OTHER4": createAudioContext(),
  528. "OTHER5": createAudioContext(),
  529. "OTHER6": createAudioContext(),
  530. "OTHER7": createAudioContext(),
  531. "OTHER8": createAudioContext(),
  532. "OTHER9": createAudioContext(),
  533. "SOUNDS": createAudioContext(),
  534. };
  535. const loadedSkyboxes = [
  536. { text: 'Default', value: 'default' }
  537. ];
  538. const divertContexts = {
  539. "KOTC": ["kotc_capture", "kotc_capturing_opponents", "kotc_capturing_player", "kotc_contested", "kotc_pointscore", "kotc_roundend", "kotc_zonespawn"],
  540. };
  541. const L = {};
  542. const functionNames = [];
  543. const isKeyToggled = {};
  544. let ESPArray = [];
  545. var trajectory = null;
  546. var trajectoryNade = null;
  547. let onlinePlayersArray = [];
  548. let bindsArray = {};
  549. let currentAimTime = 0;
  550. let nowOld = 0;
  551. // blank variables
  552. let ss = {};
  553. let H = {}; // obfuscated shit lol
  554. let C = {}; // commcodes
  555. const tp = {}; // <-- tp = tweakpane
  556. let msgElement, allowAccess, tooltipElement, vardataOverlay, vardataPopup, closeVardataPopup, botBlacklist, botWhitelist, hash, onlineClientKeys, initialisedCustomSFX, accuracyPercentage, automatedBorder, clientID, partyLight, didStateFarm, menuInitiated, GAMECODE, noPointerPause, sneakyDespawning, resetModules, amountOnline, errorString, playersInGame, loggedGameMap, startUpComplete, isBanned, attemptedAutoUnban, coordElement, performanceElement, gameInfoElement, playerinfoElement, playerstatsElement, firstUseElement, minangleCircle, redCircle, crosshairsPosition, currentlyTargeting, ammo, ranOneTime, lastWeaponBox, lastChatItemLength, configMain, configBots, playerLogger;
  557. let whitelistPlayers, scrambledMsgEl, accountStatus, updateMenu, badgeList, scriptInfo, annoyancesRemoved, oldGa, newGame, previousDetail, previousLegacyModels, previousTitleAnimation, blacklistPlayers, playerLookingAt, forceControlKeys, forceControlKeysCache, playerNearest, enemyLookingAt, enemyNearest, AUTOMATED, ranEverySecond, enemyAimNearest
  558. let cachedCommand = "", cachedCommandTime = Date.now();
  559. let activePath, findNewPath, activeNodeTarget;
  560. let pathfindingTargetOverride = undefined;
  561. let isFirstFrameAttemptingToPathfind = true;
  562. let despawnIfNoPath = false;
  563. let isLeftButtonDown = false;
  564. let isRightButtonDown = false;
  565. let configNotSet = true;
  566. let nameTextures = {};
  567. let tooltips = {};
  568. let amountVisible = 0;
  569. const weaponArray = { //this could be done differently but i cba
  570. eggk47: 0,
  571. scrambler: 1,
  572. freeranger: 2,
  573. rpegg: 3,
  574. whipper: 4,
  575. crackshot: 5,
  576. trihard: 6,
  577. random: 3, // :trol_fancy:
  578. };
  579. // const antiAFKString = "AntiAFK Message. This message is not visible to others. || ";
  580. const filteredList = [ //a selection of filtered words for antiafk. brimslate reports afk messages, so have fun reporting this and trying to explain this to the "eggforcers"
  581. 'date', 'dick', 'fuck', 'fuk', 'suck', 'piss', 'hate', 'nude', 'fux', 'hate', 'pussy',
  582. ]; //filteredList[randomInt(0,filteredList.length-1)]
  583. let proxyList = [
  584. 'shellshock.io', 'algebra.best', 'algebra.vip', 'biologyclass.club', 'combateggs.com', 'deadlyegg.com', 'deathegg.life', 'deathegg.world', 'eggbattle.com', 'eggboy.club', 'eggboy.me', 'eggboy.xyz', 'eggcombat.com', 'egg.dance',
  585. 'eggfacts.fun', 'egghead.institute', 'eggisthenewblack.com', 'eggsarecool.com', 'eggshock.com', 'eggshooter.best', 'eggshooter.com', 'eggwarfare.com', 'geometry.best', 'geometry.monster', 'geometry.pw', 'geometry.report', 'hardboiled.life',
  586. 'hardshell.life', 'humanorganising.org', 'mathactivity.club', 'mathactivity.xyz', 'mathdrills.info', 'mathdrills.life', 'mathfun.rocks', 'mathgames.world', 'math.international',
  587. 'mathlete.fun', 'mathlete.pro', 'overeasy.club', 'risenegg.com', 'scrambled.tech', 'scrambled.today', 'scrambled.us', 'scrambled.world', 'shellshockers.best', 'shellshockers.club', 'shellshockers.life', 'shellshockers.site',
  588. 'shellshockers.today', 'shellshockers.us', 'shellshockers.wiki', 'shellshockers.world', 'shellshockers.xyz', 'shellsocks.com', 'softboiled.club', 'urbanegger.com', 'violentegg.club', 'violentegg.fun', 'yolk.best', 'yolk.life',
  589. 'yolk.rocks', 'yolk.tech', 'yolk.quest', 'yolk.today', 'zygote.cafe'
  590. ];
  591. proxyList = proxyList.filter(item => item !== unsafeWindow.location.hostname);
  592. proxyList = [...proxyList].sort(() => Math.random() - 0.5);
  593. let proxyListIndex = 0;
  594. const monitorObjects = {};
  595. //title animation
  596. const titleAnimationFrames = [
  597. '︻デ═一',
  598. '︻デ═一',
  599. 'デ═一 -',
  600. '═一   -',
  601. '一    -',
  602. '.     -',
  603. '.    -',
  604. '.   -',
  605. '.    -  0',
  606. '.     -0',
  607. '.    \\/',
  608. '.   _-_',
  609. '. ___',
  610. '__',
  611. '.',
  612. 'STATEFARMCLIEN',
  613. 'TATEFARMCLIENT',
  614. 'ATEFARMCLIENTV',
  615. 'TEFARMCLIENTV3',
  616. 'EFARMCLIENTV3 ',
  617. 'FARMCLIENTV3 S',
  618. 'ARMCLIENTV3 ST',
  619. 'RMCLIENTV3 STA',
  620. 'MCLIENTV3 STAT',
  621. 'CLIENTV3 STATE',
  622. 'LIENTV3 STATEF',
  623. 'IENTV3 STATEFA',
  624. 'ENTV3 STATEFAR',
  625. 'NTV3 STATEFARM',
  626. 'TV3 STATEFARMC',
  627. 'V3 STATEFARMCL',
  628. '3 STATEFARMCLI',
  629. 'STATEFARMCLIEN',
  630. 'TATEFARMCLIENT',
  631. 'STATEFARM',
  632. 'CLIENT V3',
  633. 'STATEFARM',
  634. 'CLIENT V3',
  635. 'STATEFARM',
  636. 'CLIENT V3',
  637. 'STATEFARM',
  638. 'CLIENT V3',
  639. ':)',
  640. ';)',
  641. ':)',
  642. '⠝⠓⠗⠅ ஃ ⠟⠑⠙⠟',
  643. '⠑⠑⠟⠟ ஃ ⠙⠛⠟⠕',
  644. '⠛⠟⠍⠑ ஃ ⠅⠑⠍⠃',
  645. '⠅⠟⠇⠝ ஃ ⠟⠕⠗⠕',
  646. '⠝⠓⠗⠅ ஃ ⠟⠑⠙⠟',
  647. '⠑⠑⠟⠟ ஃ ⠙⠛⠟⠕',
  648. '⠛⠟⠍⠑ ஃ ⠅⠑⠍⠃',
  649. '⠅⠟⠇⠝ ஃ ⠟⠕⠗⠕',
  650. '( ͡° ͜ʖ ͡°)',
  651. '( ͠° ͟ʖ ͡°)',
  652. '( ͡° ͟ʖ ͡°)',
  653. '( ͡° ͟ʖ ͠°)一',
  654. '( ͡° ͟ʖ ͠°)═一',
  655. '( ͡° ͟ʖ ͠°)デ═一',
  656. '( ͡° ͟ʖ ͠°)︻デ═一',
  657. ' ͡° ͟ʖ ͠°)︻デ═一',
  658. ' ͟ʖ ͠°)︻デ═一',
  659. ' ͠°)︻デ═一',
  660. ')︻デ═一',
  661. ];
  662.  
  663. const getScrambled = () => Array.from({ length: 10 }, () => String.fromCharCode(97 + Math.floor(Math.random() * 26))).join('');
  664. let skyboxName = getScrambled();
  665.  
  666. //verification system
  667. //you can disable this by setting the variable to false, so please dont worry future ppl using this
  668. //in truth its just to get ppl to join the discord server
  669.  
  670. const verification = {
  671. enabled: true,
  672. verified: true,
  673. currentlyTrial: false,
  674. discordInvite: discordURL,
  675. trialPeriod: 5, //in minutes
  676. trialMessage: "Hello! StateFarm Client requires you to verify in the\nDiscord server to use the full version. You have a trial\nperiod of {0} minutes before you will need to verify.\nIt's all free, so don't worry. No subscriptions!",
  677. trialMessage2: "You have {0} minute(s) left of your SFC trial period.",
  678. trialOverMessage: "The trial period has ended. Please verify to continue to use StateFarm Client.",
  679. mustJoinMessage: "You must verify in the Discord server to continue to use\nthis script.\n\nPlease click the verify button below.",
  680. verificationMessage: "You have been verified! Enjoy the full version of StateFarm Client.",
  681.  
  682. timeUsedStorageKey: "StateFarmVerification_TimeUsed",
  683. verifiedStorageKey: "StateFarmVerification_Verified",
  684.  
  685. getTimeUsed: function () {
  686. if (!verification.timeUsed) verification.timeUsed = GM_getValue(verification.timeUsedStorageKey, 0);
  687. return verification.timeUsed;
  688. },
  689. timeUsed: 0,
  690. checkVerification: function () {
  691. const isVerifiedStorage = GM_getValue(verification.verifiedStorageKey, false);
  692. verification.currentlyTrial = (verification.getTimeUsed() < verification.trialPeriod) && !isVerifiedStorage;
  693. verification.verified = (!verification.enabled) || verification.currentlyTrial || isVerifiedStorage;
  694. // console.warn("isVerifiedStorage", isVerifiedStorage, verification.verified);
  695. return verification.verified;
  696. },
  697. started: false,
  698. beginVerificationCheck: function () {
  699. if (verification.started) return;
  700. verification.started = true;
  701.  
  702. // log("the 'wtf is going on with' logs");
  703. // log(verification.checkVerification());
  704. // log(verification.currentlyTrial);
  705.  
  706. if (verification.checkVerification()) { //allowed to use
  707. if (verification.currentlyTrial) {
  708. createPrompt(verification.trialMessage2.format(verification.trialPeriod - verification.timeUsed), [], 15e3);
  709. verification.interval = setInterval(function () {
  710. verification.timeUsed++;
  711. GM_setValue(verification.timeUsedStorageKey, verification.timeUsed);
  712. log("Time used:", verification.timeUsed);
  713. if (!verification.checkVerification()) {
  714. change("leaveGame");
  715. clearInterval(verification.interval);
  716. createPrompt(verification.trialOverMessage, [], 15e3);
  717. verification.setDisableClient();
  718. };
  719. }, 60000);
  720. };
  721. } else { //not allowed to use
  722. verification.openVerificationPopup();
  723. };
  724. },
  725. setDisableClient: function () {
  726. initMenu();
  727. verification.openVerificationPopup();
  728. },
  729. popupShown: false,
  730. openVerificationPopup: function () {
  731. if (verification.popupShown) return;
  732. verification.popupShown = true;
  733. createVarDataOverlay();
  734. tp.mainPanel.hidden = true;
  735.  
  736. unsafeWindow.BAWK.play("ks_double_eggs_end");
  737.  
  738. //create verificationPopup
  739. let verificationPopup = document.createElement('div');
  740. verificationPopup.style.position = 'fixed';
  741. verificationPopup.style.left = '50%';
  742. verificationPopup.style.top = '50%';
  743. verificationPopup.style.width = '40em';
  744. verificationPopup.style.transform = 'translate(-50%, -50%)';
  745. verificationPopup.style.color = '#fff';
  746. verificationPopup.style.backgroundColor = 'rgba(0, 0, 0, 0.7)';
  747. verificationPopup.style.padding = '15px';
  748. verificationPopup.style.borderRadius = '5px';
  749. verificationPopup.style.boxShadow = '0 2px 10px rgba(0, 0, 0, 0.2)';
  750. verificationPopup.style.border = '2px solid rgba(255, 255, 255, 0.5)';
  751. verificationPopup.style.pointerEvents = 'auto';
  752. verificationPopup.style.opacity = '0';
  753. verificationPopup.style.transition = 'opacity 0.4s ease-in-out';
  754. verificationPopup.style.fontFamily = 'Bahnschrift, sans-serif';
  755. verificationPopup.style.fontSize = '16px';
  756. verificationPopup.style.zIndex = '9999';
  757. verificationPopup.style.whiteSpace = 'pre-wrap';
  758.  
  759. //set verificationPopup content
  760. const title = "Please verify in the StateFarm Discord server";
  761. const message = `You only need to do this once, and it's free.<br>
  762. <strong>Why am I seeing this?</strong>
  763. Due to some recent issues, we have implemented this system to ensure our users are using the genuine StateFarm script.<br>
  764. <strong>How do I verify?</strong>
  765. Verifying is easy.
  766. You can verify by using the command "sf.verify" in the StateFarm Discord bot channel.
  767. <a href="${discordURL}" target="_blank" style="color: #1944ff; text-decoration: underline; font-size: inherit;">Join the ${discordName} Discord server</a> to get your verification code!`;
  768. const image = `<img src='${eggShowURL}' style='width: 20%; height: 20%; margin-right: 15px; vertical-align: middle;'>`;
  769. verificationPopup.innerHTML = `${image}<strong>${title}</strong><br><br>${message}<br>
  770. <label for="verificationInput">Enter Verification Code:</label>
  771. <div style="display: flex; align-items: center;">
  772. <input type="text" id="verificationInput" style="flex: 1; padding: 5px; width: 250px; border: 1px solid rgba(255, 255, 255, 0.5); background-color: rgba(255, 255, 255, 0.1); color: #fff; border-radius: 5px; margin-right: 10px;">
  773. <button id="submitVerificationCode" style="padding: 5px 15px; background-color: rgba(255, 255, 255, 0.1); color: #fff; border: 1px solid rgba(255, 255, 255, 0.5); border-radius: 5px; cursor: pointer; transition: background-color 0.2s;">GO</button>
  774. </div>`;
  775.  
  776. document.body.appendChild(verificationPopup);
  777.  
  778. //add inputs stuff
  779. const input = document.getElementById('verificationInput');
  780. const submitButton = document.getElementById('submitVerificationCode');
  781.  
  782. submitButton.addEventListener('click', () => {
  783. const inputValue = input.value;
  784.  
  785. const error = function () {
  786. createPopup("Inputted verification code isn't valid.", "error");
  787. };
  788.  
  789. try {
  790. if (verification.checkCodeValidity(inputValue)) {
  791. verification.setVerified();
  792. //add success message, timeouts give the storage time to process
  793. createPopup(verification.verificationMessage, "success");
  794. unsafeWindow.BAWK.play("shellstreak_start");
  795. setTimeout(reloadPage, 1500);
  796. // setTimeout(() => alert(verification.verificationMessage), 500);
  797. } else {
  798. error();
  799. };
  800. } catch (e) {
  801. error();
  802. };
  803. });
  804.  
  805. input.addEventListener('keypress', (event) => {
  806. if (event.key === 'Enter') {
  807. submitButton.click();
  808. };
  809. });
  810.  
  811. // log(verificationPopup);
  812.  
  813. //fade anims
  814. setTimeout(() => {
  815. verificationPopup.style.opacity = '1';
  816. }, 10);
  817. },
  818.  
  819. codeExpirationTime: 30 * 60, //in seconds
  820. checkCodeValidity: function (code) {
  821. //if you found this function, well done.
  822. //you can now use the full version of the script without verifying.
  823. //now just let us know in the discord server that you found this and we'll give you a special role.
  824. function fromBase62(str) {
  825. const chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
  826. let num = 0;
  827.  
  828. for (let i = 0; i < str.length; i++) {
  829. num = num * 62 + chars.indexOf(str[i]);
  830. }
  831.  
  832. return num;
  833. };
  834.  
  835. let codeNum = (fromBase62(code) % 100000000000) * 1e3;
  836.  
  837. let isValid = (Date.now() - codeNum) <= (verification.codeExpirationTime * 1e3);
  838.  
  839. return isValid;
  840. },
  841. setVerified: function () {
  842. GM_setValue(verification.verifiedStorageKey, true);
  843. },
  844. };
  845.  
  846. //menu interaction functions
  847. //menu extraction
  848. const extract = function (variable, shouldUpdate) {
  849. try {
  850. if (shouldUpdate) { updateConfig() };
  851. return configMain[variable] || configBots[variable];
  852. } catch (error) {
  853. // variable !== "consoleLogs" && log("Error extracting variable:", variable, error);
  854. return undefined;
  855. };
  856. };
  857. const extractDropdownList = function (variable) {
  858. return tp[variable + "Button"].controller_.binding.value.constraint_.constraints[0].options;
  859. };
  860. const extractAsDropdownInt = function (variable) {
  861. const options = extractDropdownList(variable);
  862. const state = extract(variable);
  863. for (let i = 0; i < options.length; i++) {
  864. if (options[i].value === state) {
  865. return i;
  866. };
  867. };
  868. };
  869.  
  870. const beginBinding = function (value) {
  871. if (binding == false) {
  872. binding = value;
  873. tp[binding + "BindButton"].title = "PRESS KEY";
  874. };
  875. };
  876. //one day i should make this unshit. dom is not the correct way to go about this.
  877. //unfortunately tweakpane is a pain in the ass and has barely anything for actually extracting/changing vars
  878. //a way it could be done is export preset => change value => import preset
  879. //but doesnt account for it being a button... and dropdowns wouldnt switch properly too. laziness. the problem is that this works fine.
  880. //suppose i could always just log the type of module and refer to it later. you can also get the parent object from the tp object, that would save iterating over everything.
  881. const change = function (module, newValue) { //its important to note that every module must have a unique name (the title of the module, NOT the storeAs)
  882. const labels = document.querySelectorAll('.tp-lblv_l');
  883. const moduleButton = module + "Button";
  884. const moduleLabel = tp[moduleButton].label;
  885. for (const label of labels) {
  886. if (label.textContent == moduleLabel) {
  887. const inputContainer = label.nextElementSibling;
  888. const currentValue = extract(module);
  889. // check for checkbox
  890. const checkbox = inputContainer.querySelector('.tp-ckbv_i');
  891. if (checkbox) {
  892. if (newValue == undefined) {
  893. newValue = (!currentValue);
  894. };
  895. if (newValue !== (!!currentValue)) {
  896. checkbox.click(); // Toggle checkbox
  897. };
  898. log(module, "checkbox", currentValue, newValue);
  899. return extract(module, true);
  900. };
  901. // check for button
  902. const button = inputContainer.querySelector('.tp-btnv_b');
  903. if (button) {
  904. button.click(); // Trigger button click
  905. log(module, "button", currentValue, newValue);
  906. return ("NOMSG"); //no change of state, dont show pop up message
  907. };
  908. // check for dropdown
  909. const dropdown = inputContainer.querySelector('.tp-lstv_s');
  910. if (dropdown) {
  911. if (newValue == undefined) { //if youre going to set a list to a certain value, use the int value of the list item
  912. newValue = (dropdown.selectedIndex + 1) % dropdown.options.length;
  913. };
  914. dropdown.selectedIndex = newValue;
  915. dropdown.dispatchEvent(new Event('change')); // trigger change event for dropdown
  916. log(module, "dropdown", currentValue, newValue);
  917. return extract(module, true);
  918. };
  919. // check for text input
  920. const textInput = inputContainer.querySelector('.tp-txtv_i');
  921. if (textInput) {
  922. textInput.value = newValue;
  923. textInput.dispatchEvent(new Event('change')); // trigger change event for dropdown
  924. return extract(module, true);
  925. };
  926. };
  927. };
  928. };
  929. document.addEventListener('mousedown', function (event) {
  930. if (event.button === 2) {
  931. isRightButtonDown = true;
  932. } else if (event.button === 0) {
  933. isLeftButtonDown = true;
  934. };
  935. }, true);
  936. document.addEventListener('mouseup', function (event) {
  937. if (event.button === 2) {
  938. isRightButtonDown = false;
  939. } else if (event.button === 0) {
  940. isLeftButtonDown = false;
  941. };
  942. }, true);
  943. //menu
  944. document.addEventListener("keydown", function (event) {
  945. event = (event.code.originalReplace("Key", ""));
  946. isKeyToggled[event] = true;
  947. if (event == "Escape") {
  948. noPointerPause = false; unsafeWindow.document.onpointerlockchange();
  949. };
  950. });
  951. document.addEventListener("keyup", function (event) {
  952. event = (event.code.originalReplace("Key", ""));
  953. isKeyToggled[event] = false;
  954. if (document.activeElement && document.activeElement.tagName === 'INPUT') {
  955. return;
  956. } else if (binding != false) {
  957. if (event == "Delete") { event = "Set Bind" };
  958. tp[binding + "BindButton"].title = event;
  959. bindsArray[binding] = event;
  960. save(binding + "Bind", event);
  961. createPopup("Bound " + tp[binding + "Button"].label + " to key: " + event);
  962. binding = false;
  963. } else {
  964. Object.keys(bindsArray).forEach(function (module) {
  965. if ((bindsArray[module] == event) && module != "zoom") {
  966. let state = change(module);
  967. let popupText = state;
  968. if (state != "NOMSG") {
  969. if (state === true || state === false || state === undefined) { state = (state ? "ON" : "OFF") };
  970. popupText = "Set " + module + " to: " + state;
  971. if (extract("announcer")) {
  972. sendChatMessage("I just set " + module + " to " + state + "!");
  973. };
  974. } else {
  975. switch (module) {
  976. case ("hide"):
  977. popupText = "Toggled StateFarm Panel"; break;
  978. case ("showBotPanel"):
  979. popupText = "Toggled Bot Panel"; break;
  980. case ("sfChatShowHide"):
  981. popupText = "Toggled SFC Chat"; break;
  982. case ("panic"):
  983. popupText = "Exiting to set URL..."; break;
  984. default:
  985. popupText = module; break;
  986. };
  987. };
  988. createPopup(popupText);
  989. };
  990. });
  991. };
  992. });
  993. const initTabs = function (tab, guideData) {
  994. tp[tab.storeAs] = tab.location.addTab({
  995. pages: [
  996. { title: 'Modules' },
  997. { title: 'Binds' },
  998. { title: 'Guide' },
  999. ],
  1000. });
  1001. if (guideData) {
  1002. const thePages = [];
  1003. guideData.forEach(aPage => {
  1004. thePages.push({ title: aPage.title });
  1005. });
  1006. tp[tab.storeAs + "Guide"] = tp[tab.storeAs].pages[2].addTab({ pages: thePages }); //is there a one liner for this? uhhh probabyl
  1007. //tp[tab.storeAs + "Guide"] = tab.location.addTab({ thePages: guideData.map(page => ({ title: page.title })) });
  1008. for (let i = 0; i < guideData.length; i++) {
  1009. const storeAs = tab.storeAs + "Guide" + i;
  1010. const text = (guideData[i].content || "Not set up correctly lmao");
  1011. initModule({ location: tp[tab.storeAs + "Guide"].pages[i], storeAs: storeAs, monitor: (text.split('\n').length + 0.25), });
  1012. monitorObjects[storeAs] = text;
  1013. const infoElement = tp[storeAs + "Button"].controller_.view.element.children[1].children[0];
  1014. infoElement.style.width = "270px";
  1015. infoElement.style.setProperty("margin-left", "-110px", "important");
  1016. };
  1017. };
  1018. };
  1019. const initFolder = function (folder) {
  1020. tp[folder.storeAs] = folder.location.addFolder({
  1021. title: folder.title,
  1022. expanded: load(folder.storeAs) !== null ? load(folder.storeAs) : false
  1023. });
  1024. allFolders.push(folder.storeAs);
  1025. };
  1026. const initModule = function (module) {
  1027. if (module.requirements) {
  1028.  
  1029. };
  1030.  
  1031. const value = {};
  1032. value[module.storeAs] = (module.defaultValue !== undefined ? module.defaultValue : false);
  1033.  
  1034. if (module.tooltip) tooltips[module.title] = module.tooltip;
  1035.  
  1036. tp[module.storeAs + "TiedModules"] = {
  1037. showConditions: (module.showConditions || false),
  1038. hideConditions: (module.hideConditions || false),
  1039. enableConditions: (module.enableConditions || false),
  1040. //why have disable when there is already enable?
  1041. //enable acts like an AND operator,
  1042. //whereas having conditions for the opposite allows for an OR operation.
  1043. //it is messy, but hey it works lmao?
  1044. disableConditions: (module.disableConditions || false),
  1045. };
  1046.  
  1047. if (!(module.slider && module.slider.step)) { module.slider = {} };
  1048. const config = {
  1049. label: module.title,
  1050. options: module.dropdown,
  1051. min: module.slider.min,
  1052. max: module.slider.max,
  1053. step: module.slider.step,
  1054. title: module.button,
  1055. };
  1056.  
  1057. const tpStoreAs = module.storeAs + "Button";
  1058.  
  1059. if (module.button) {
  1060. tp[tpStoreAs] = module.location.addButton({
  1061. label: module.title,
  1062. title: module.button,
  1063. }).on("click", (value) => {
  1064. try {
  1065. if (module.clickFunction !== undefined) { module.clickFunction(value) };
  1066. } catch (error) {
  1067. log("OooOoOoops, error in click function", module.storeAs, error);
  1068. };
  1069. if (module.botParam !== undefined) { updateBotParams(module.botParam) };
  1070. log("click", module.storeAs, value);
  1071. onOptionChanged(module.storeAs, value);
  1072. });
  1073. } else if (module.monitor) {
  1074. monitorObjects[module.storeAs] = "Text Goes Here";
  1075. tp[tpStoreAs] = module.location.addMonitor(monitorObjects, module.storeAs, {
  1076. label: '',
  1077. expanded: true,
  1078. multiline: true,
  1079. lineCount: module.monitor,
  1080. });
  1081. } else {
  1082. tp[tpStoreAs] = module.location.addInput(value, module.storeAs, config
  1083. ).on("change", (value) => {
  1084. try {
  1085. if (module.changeFunction !== undefined) { module.changeFunction(value) };
  1086. } catch (error) {
  1087. log("OooOoOoops, error in change function", module.storeAs, error);
  1088. };
  1089. setTimeout(() => {
  1090. if (startUpComplete) {
  1091. if ((module.botParam !== undefined)) {
  1092. updateBotParams(module.botParam);
  1093. };
  1094. };
  1095. updateHiddenAndDisabled();
  1096. saveConfig();
  1097. }, 150);
  1098. log("change", module.storeAs, value);
  1099. onOptionChanged(module, value);
  1100. });
  1101. };
  1102. allModules.push(module.storeAs);
  1103. if (module.bindLocation) { initBind(module) };
  1104. };
  1105. const initBind = function (module) {
  1106. if (resetModules) { remove(module.storeAs + "Bind") };
  1107. const theBind = (load(module.storeAs + "Bind") || module.defaultBind || "Set Bind");
  1108. tp[(module.storeAs + "BindButton")] = module.bindLocation.addButton({
  1109. label: module.title,
  1110. title: theBind,
  1111. }).on("click", (value) => {
  1112. beginBinding(module.storeAs);
  1113. });
  1114. bindsArray[module.storeAs] = theBind;
  1115. };
  1116. const initMenu = function (reset) {
  1117. //INIT MENU
  1118. //init tp.mainPanel
  1119.  
  1120. resetModules = reset === true;
  1121. menuInitiated = false;
  1122.  
  1123. const alreadyOpen = tp?.mainPanel !== undefined && !tp.mainPanel.hidden;
  1124.  
  1125. log("alreadyOpen", alreadyOpen);
  1126.  
  1127. if (tp.mainPanel) { tp.mainPanel.dispose() };
  1128. if (tp.botPanel) { tp.botPanel.dispose() };
  1129.  
  1130. tp.mainPanel = new Tweakpane.Pane(); // eslint-disable-line
  1131. tp.mainPanel.hidden = true;
  1132. if (alreadyOpen) tp.mainPanel.hidden = false;
  1133.  
  1134. //VERIFICATION STUFF
  1135. verification.checkVerification();
  1136.  
  1137. allowAccess = true;
  1138.  
  1139. if (verification.currentlyTrial || !verification.verified) {
  1140. initModule({ location: tp.mainPanel, title: "Verification", storeAs: "verificationText", monitor: 5, });
  1141. if (verification.currentlyTrial) {
  1142. monitorObjects["verificationText"] = verification.trialMessage.format(verification.trialPeriod);
  1143. } else {
  1144. monitorObjects["verificationText"] = verification.mustJoinMessage;
  1145. allowAccess = false;
  1146. };
  1147.  
  1148. initModule({ location: tp.mainPanel, title: "Verify", storeAs: "verificationButton", tooltip: "Go to the Discord to verify", button: "Go", clickFunction: verification.openVerificationPopup });
  1149.  
  1150. tp.mainPanel.addSeparator();
  1151.  
  1152. tp.mainPanel.title = menuTitle + " (✘)";
  1153. } else {
  1154. tp.mainPanel.title = menuTitle + " (✔)";
  1155. };
  1156.  
  1157. //SFC CHAT
  1158. initFolder({ location: tp.mainPanel, title: "StateFarm Chat", storeAs: "sfChatFolder", });
  1159. initTabs({ location: tp.sfChatFolder, storeAs: "sfChatTab" }, [
  1160. {
  1161. title: "WIP", content:
  1162. `Sorry! No guide yet!`},
  1163. ]);
  1164. initModule({ location: tp.sfChatTab.pages[0], title: "Username", storeAs: "sfChatUsername", tooltip: "Your username in the chatroom", defaultValue: ("Guest" + (Math.floor(Math.random() * 8999) + 1000)), });
  1165. // initModule({ location: tp.sfChatTab.pages[0], title: "Join Chat", storeAs: "sfChatJoin", button: "Join", bindLocation: tp.sfChatTab.pages[1], clickFunction: function(){
  1166. // if (sfChatIframe != undefined){
  1167. // createPopup("Already Started. Try Showing it.");
  1168. // } else {
  1169. // startStateFarmChat();
  1170. // };
  1171. // },});
  1172. tp.sfChatTab.pages[0].addSeparator();
  1173. initModule({
  1174. location: tp.sfChatTab.pages[0], title: "Show/Hide", storeAs: "sfChatShowHide", tooltip: "Toggle chat panel visibility", button: "Show/Hide", bindLocation: tp.sfChatTab.pages[1], defaultBind: "K", clickFunction: function () {
  1175. if (sfChatContainer != undefined) {
  1176. if (sfChatContainer.style.display == "none") {
  1177. sfChatContainer.style.display = "block";
  1178. } else {
  1179. sfChatContainer.style.display = "none";
  1180. };
  1181. } else {
  1182. startStateFarmChat(); //its just easier this way imo
  1183. };
  1184. },
  1185. });
  1186. tp.sfChatTab.pages[0].addSeparator();
  1187. initModule({ location: tp.sfChatTab.pages[0], title: "Notifications", storeAs: "sfChatNotifications", tooltip: "Shows an in-game notification for every new chat message", bindLocation: tp.sfChatTab.pages[1], });
  1188. initModule({ location: tp.sfChatTab.pages[0], title: "Notification Sound", storeAs: "sfChatNotificationSound", tooltip: "Play a sound for every new message", bindLocation: tp.sfChatTab.pages[1], });
  1189. tp.sfChatTab.pages[0].addSeparator();
  1190. initModule({ location: tp.sfChatTab.pages[0], title: "Auto Start Chat", storeAs: "sfChatAutoStart", tooltip: "Automatically connects to the chatroom on startup", bindLocation: tp.sfChatTab.pages[1], });
  1191. tp.sfChatTab.pages[0].addSeparator();
  1192. initModule({ location: tp.sfChatTab.pages[0], title: "Prompt Invitations", storeAs: "sfChatInvitations", tooltip: "Show invite prompts when someone sends a game code in the chatroom", bindLocation: tp.sfChatTab.pages[1], defaultValue: true, });
  1193. //COMBAT MODULES
  1194. if (allowAccess) {
  1195. initFolder({ location: tp.mainPanel, title: "Combat", storeAs: "combatFolder", });
  1196. initTabs({ location: tp.combatFolder, storeAs: "combatTab" }, [
  1197. {
  1198. title: "Basics", content:
  1199. `This is the combat tab. Here you will find
  1200. options relating to aimbotting, and other
  1201. useful macros. Aimbot is made active by
  1202. turning it on. Using ToggleRM will give you
  1203. more control by allowing you to switch by
  1204. pressing the right mouse button.
  1205. TargetMode also allows a more intuitive
  1206. means of selecting who you will target.
  1207. The most powerful features you can use
  1208. are Predictions and Antibloom. These
  1209. improve the accuracy of the tracking.
  1210. AntiSwitch will make you lock on to a
  1211. target until they die, and if you don't want
  1212. to target anyone else after they die then
  1213. choose 1Kill too. Auto Refill helps you
  1214. stay topped up and choosing the Smart
  1215. mode allows you to refill at the moment
  1216. when you will not have a long
  1217. reload time. GrenadeMAX makes all
  1218. grenades get thrown at max strength.`},
  1219. {
  1220. title: "Visibility", content:
  1221. `There are a couple of options related to
  1222. visibility (Line-of-Sight). First is
  1223. TargetVisible. This tunes the aimbot to
  1224. be more strategic with where it aims.
  1225. NoWallTrack makes it such that if a
  1226. targeted player goes behind a wall, you
  1227. stop aimlocking them. There is also an
  1228. AutoFire mode with this sort of
  1229. functionality.`},
  1230. {
  1231. title: "Advanced", content:
  1232. `If you want to increase stealthiness,
  1233. make use of MinAngle and AntiSnap. The
  1234. first will make it so that you have to
  1235. manually move your reticle within your
  1236. specified radius to lock on. The latter
  1237. smooths snapping, which evades
  1238. detection on botter spotter scripts.
  1239. If you want to be more powerful, opt for
  1240. SilentAim. This modifies your direction
  1241. packets instead of making you lock on.
  1242. However, this can lead to slightly glitchy
  1243. movement. When this is on, MinAngle
  1244. changes to instead narrow down the
  1245. selection of targets rather than acting
  1246. as a guide.
  1247. AntiSneak is a module which, while not
  1248. always showing use, can help you in a
  1249. difficult situation. It automatically
  1250. switches targets to a player that enters
  1251. your specified range, and begins
  1252. shooting with your primary gun, and then
  1253. the pistol. Ideal use case is when you are
  1254. sniping and someone sneaks up on you
  1255. (...hence it is called... AntiSneak).`},
  1256. ]);
  1257. initModule({ location: tp.combatTab.pages[0], title: "Aimbot", storeAs: "aimbot", tooltip: "Locks onto targeted player", bindLocation: tp.combatTab.pages[1], defaultBind: "V", });
  1258. initFolder({ location: tp.combatTab.pages[0], title: "Aimbot Options", storeAs: "aimbotFolder", });
  1259. initModule({ location: tp.aimbotFolder, title: "TargetMode", storeAs: "aimbotTargetMode", tooltip: "Decides the priority for which player aimbot should target", bindLocation: tp.combatTab.pages[1], defaultBind: "T", dropdown: [{ text: "Pointing At", value: "pointingat" }, { text: "Nearest", value: "nearest" }, { text: "Lowest HP", value: "lowestHp" }, { text: "Most Kills", value: "mostKills" }, {text: "Aiming At Me", value: "aimingAt" }], defaultValue: "pointingat", enableConditions: [["aimbot", true]], });
  1260. initModule({ location: tp.aimbotFolder, title: "TargetVisible", storeAs: "aimbotVisibilityMode", tooltip: "A filter, applied after TargetMode helping to pick the aimbot target", bindLocation: tp.combatTab.pages[1], dropdown: [{ text: "Disabled", value: "disabled" }, { text: "Prioritise Visible", value: "prioritise" }, { text: "Only Visible", value: "onlyvisible" }], defaultValue: "disabled", enableConditions: [["aimbot", true]] });
  1261. tp.aimbotFolder.addSeparator();
  1262. initModule({ location: tp.aimbotFolder, title: "ToggleRM", storeAs: "aimbotRightClick", tooltip: "Modifies aimbot to only lock when the right mouse is held", bindLocation: tp.combatTab.pages[1], enableConditions: [["aimbot", true]], });
  1263. initModule({ location: tp.aimbotFolder, title: "SilentAim", storeAs: "silentAimbot", tooltip: "Shoots without moving the camera. ONLY visual, VERY blatant cheating. Refer to the GitHub README for more information", bindLocation: tp.combatTab.pages[1], enableConditions: [["aimbot", true]], });
  1264. initModule({ location: tp.aimbotFolder, title: "SemiSilent", storeAs: "aimbSemiSilent", tooltip: "SilentAimbot behavior, but will move the camera after a shot has been fired", bindLocation: tp.combatTab.pages[1], enableConditions: [["aimbot", true], ["silentAimbot", true]], });
  1265. initModule({ location: tp.aimbotFolder, title: "NoWallTrack", storeAs: "noWallTrack", tooltip: "Aimbot ignores the player if they're behind obstacles", bindLocation: tp.combatTab.pages[1], enableConditions: [["aimbot", true], ["silentAimbot", false]], });
  1266. tp.aimbotFolder.addSeparator();
  1267. initModule({ location: tp.aimbotFolder, title: "Prediction", storeAs: "prediction", tooltip: "Predicts where the player will be when the bullet hits them and ajusts aimbot accordingly", bindLocation: tp.combatTab.pages[1], enableConditions: [["aimbot", true]], defaultValue: true, });
  1268. initModule({ location: tp.aimbotFolder, title: "AntiBloom", storeAs: "antiBloom", tooltip: "Locks onto the predicted bloom point. Good for shooting & moving", bindLocation: tp.combatTab.pages[1], enableConditions: [["aimbot", true]], defaultValue: true, });
  1269. tp.aimbotFolder.addSeparator();
  1270. initModule({ location: tp.aimbotFolder, title: "AntiSwitch", storeAs: "antiSwitch", tooltip: "Prevents the aimbot from changing the target until they die", bindLocation: tp.combatTab.pages[1], enableConditions: [["aimbot", true]], });
  1271. initModule({ location: tp.aimbotFolder, title: "1 Kill", storeAs: "oneKill", tooltip: "Disables aimbot when the targeted player dies", bindLocation: tp.combatTab.pages[1], enableConditions: [["aimbot", true]], });
  1272. tp.aimbotFolder.addSeparator();
  1273. initModule({ location: tp.aimbotFolder, title: "MinAngle", storeAs: "aimbotMinAngle", tooltip: "Prevents you from snapping if the angle between you and the player is greater than this value (in degrees)", slider: { min: 0.05, max: 360, step: 1 }, defaultValue: 360, enableConditions: [["aimbot", true]], });
  1274. initModule({ location: tp.aimbotFolder, title: "AntiSneak", storeAs: "antiSneak", tooltip: "Recommended distance under 2. This automatically kills players in the given range", slider: { min: 0, max: 5, step: 0.2 }, defaultValue: 0, enableConditions: [["aimbot", true]], });
  1275. tp.aimbotFolder.addSeparator();
  1276. initModule({ location: tp.aimbotFolder, title: "AntiSnap", storeAs: "aimbotAntiSnap", tooltip: "This makes snapping smooth at higher values. useful to avoid being spotted", slider: { min: 0, max: 0.99, step: 0.01 }, defaultValue: 0, enableConditions: [["aimbot", true], ["silentAimbot", false]], });
  1277. initFolder({ location: tp.aimbotFolder, title: "AntiSnap Options", storeAs: "antisnapFolder", });
  1278. initModule({ location: tp.antisnapFolder, title: "AntiSnap Regime", storeAs: "aimbotAntiSnapRegime", tooltip: "Changes the method of smoothing\n\nCredit to de_Neuublue for this code", bindLocation: tp.combatTab.pages[1], dropdown: [{ text: "Linear", value: "linear" }, { text: "Slow End", value: "slowEnd" }, { text: "Fast End", value: "fastEnd" }, { text: "Time Based", value: "timeBased" }], defaultValue: "linear", enableConditions: [["aimbot", true], ["silentAimbot", false]], });
  1279. initModule({ location: tp.antisnapFolder, title: "Max Aim Time (ms)", storeAs: "maxAimTime", tooltip: "How long to aim for until you force the locking.", slider: { min: 10, max: 5000, step: 1 }, defaultValue: 700, enableConditions: [["aimbot", true], ["silentAimbot", false]], showConditions: [["aimbotAntiSnapRegime", "timeBased"]], });
  1280.  
  1281. tp.combatTab.pages[0].addSeparator();
  1282. initModule({ location: tp.combatTab.pages[0], title: "Auto Refill", storeAs: "autoRefill", tooltip: "This automatically reloads your gun if there is no more ammo", bindLocation: tp.combatTab.pages[1], });
  1283. initModule({ location: tp.combatTab.pages[0], title: "Smart Refill", storeAs: "smartRefill", tooltip: "This makes your weapon refill at the best moment, which reduces reload time", bindLocation: tp.combatTab.pages[1], showConditions: [["autoRefill", true]], });
  1284. tp.combatTab.pages[0].addSeparator();
  1285. initModule({ location: tp.combatTab.pages[0], title: "Auto Fire", storeAs: "enableAutomatic", tooltip: "Makes every gun act like an automatic one", bindLocation: tp.combatTab.pages[1], });
  1286. initModule({ location: tp.combatTab.pages[0], title: "Triggerbot", storeAs: "enableAutoFire", tooltip: "Automatically shoot the gun", bindLocation: tp.combatTab.pages[1], });
  1287. initModule({ location: tp.combatTab.pages[0], title: "TriggerType", storeAs: "autoFireType", tooltip: "Picks how to shoot the gun", bindLocation: tp.combatTab.pages[1], dropdown: [{ text: "Force Automatic", value: "forceAutomatic" }, { text: "While Visible", value: "whileVisible" }, { text: "While Aimbotting", value: "whileAimbot" }, { text: "Visible and Aimbotting", value: "whileVisAimbot" }, { text: "Always", value: "always" }], defaultValue: "leftMouse", enableConditions: [["enableAutoFire", true]] });
  1288. initModule({ location: tp.combatTab.pages[0], title: "MinAccuracy%", storeAs: "autoFireAccuracy", tooltip: "Minimum spread/accuracy before shooting. Helpful for sniper guns, bad for automatics. Leave at 0 for default.", slider: { min: 0, max: 1, step: 0.05 }, defaultValue: 0, enableConditions: [["enableAutoFire", true]], });
  1289. tp.combatTab.pages[0].addSeparator();
  1290. initModule({ location: tp.combatTab.pages[0], title: "GrenadeMAX", storeAs: "grenadeMax", tooltip: "Sets grenades to be thrown to max power immediately without the need of charging", bindLocation: tp.combatTab.pages[1], });
  1291. initModule({ location: tp.combatTab.pages[0], title: "Nade Power", storeAs: "grenadePower", tooltip: "porcupane hijinks ensue — Today at 6:33 PM• goo/ber grenade power override for how long you hold ot", slider: { min: 0, max: 1, step: 0.05 }, defaultValue: 1, });
  1292. //RENDER MODULES
  1293. initFolder({ location: tp.mainPanel, title: "Render", storeAs: "renderFolder", });
  1294. initTabs({ location: tp.renderFolder, storeAs: "renderTab" }, [
  1295. {
  1296. title: "WIP", content:
  1297. `Sorry! No guide yet!`},
  1298. ]);
  1299. initModule({ location: tp.renderTab.pages[0], title: "PlayerESP", storeAs: "playerESP", tooltip: "Creates boxes around enemy players", bindLocation: tp.renderTab.pages[1], });
  1300. initModule({ location: tp.renderTab.pages[0], title: "Tracers", storeAs: "tracers", tooltip: "Creates lines pointing from the center of the screen to the location of enemy players", bindLocation: tp.renderTab.pages[1], });
  1301. initModule({ location: tp.renderTab.pages[0], title: "Chams", storeAs: "chams", tooltip: "Renders players through walls", bindLocation: tp.renderTab.pages[1], });
  1302. initModule({ location: tp.renderTab.pages[0], title: "Trajectories", storeAs: "trajectories", tooltip: "Shows the path your grenade will take when thrown", bindLocation: tp.renderTab.pages[1], });
  1303. //initModule({ location: tp.renderTab.pages[0], title: "Targets", storeAs: "targets", tooltip: "It's borked rn", bindLocation: tp.renderTab.pages[1], });
  1304. initModule({ location: tp.renderTab.pages[0], title: "PredictionESP", storeAs: "predictionESP", tooltip: "Creates an ESP box at the predicted position of the player", bindLocation: tp.renderTab.pages[1], });
  1305. tp.renderTab.pages[0].addSeparator();
  1306. initModule({ location: tp.renderTab.pages[0], title: "NametagESP", storeAs: "nametags", tooltip: "Enlarges nametags and makes them appear through walls", bindLocation: tp.renderTab.pages[1], });
  1307. initModule({ location: tp.renderTab.pages[0], title: "NametagInfo", storeAs: "nametagInfo", tooltip: "Adds extra info to nametags such as HP and score stats (Warning: Lags)", bindLocation: tp.renderTab.pages[1], });
  1308. initModule({ location: tp.renderTab.pages[0], title: "Info Update Interval", storeAs: "nametagInfoInterval", tooltip: "If the info updater lags you, increase this value to make it update less often.", slider: { min: 1, max: 180, step: 1 }, defaultValue: 180, showConditions: [["nametagInfo", true]], });
  1309. tp.renderTab.pages[0].addSeparator();
  1310. initFolder({ location: tp.renderTab.pages[0], title: "Player ESP/Tracers Options", storeAs: "tracersFolder", });
  1311. initModule({ location: tp.tracersFolder, title: "TargetedColor", storeAs: "aimbotColor", tooltip: "The color used to highlight the ESP line of a targeted player. Useless if PlayerESP is disabled", defaultValue: "#0000ff", showConditions: [["aimbotRainbow", false]] });
  1312. initModule({ location: tp.tracersFolder, title: "Targeted RGB", storeAs: "aimbotRainbow", tooltip: "Adds RGB to the ESP, for fun", defaultValue: true, bindLocation: tp.renderTab.pages[1] });
  1313. tp.aimbotFolder.addSeparator();
  1314. initModule({ location: tp.tracersFolder, title: "Type", storeAs: "tracersType", tooltip: "The mode for how ESP/Tracers are coloured. Different colour options present themselves based on option.\n\nStatic: Just stays as one colour.\nProximity: Fades between three colours based on how close someone is.\nVisibility: Switches between two colours if there is Line of Sight.", bindLocation: tp.renderTab.pages[1], dropdown: [{ text: "Static", value: "static" }, { text: "Proximity", value: "proximity" }, { text: "Visibility", value: "visibility" }], defaultValue: "static", disableConditions: [["tracers", false], ["playerESP", false]], });
  1315. initModule({ location: tp.tracersFolder, title: "RGB Color 1", storeAs: "tracersColor1Rainbow", tooltip: "rainbow. 🌈", defaultValue: false, disableConditions: [["tracers", false], ["playerESP", false]], });
  1316. initModule({ location: tp.tracersFolder, title: "Color 1", storeAs: "tracersColor1", tooltip: "Static: Just stays this colour.\nProximity: Very close colour\nVisibility: Not visible.", defaultValue: "#ff0000", disableConditions: [["tracers", false], ["playerESP", false]], showConditions: [["tracersColor1Rainbow", false]], });
  1317. //TODO: I hate having it like that so maybe a initmodule helper func for color with creates both color opt and rainbow opt. Same with the getColors() btw ~Sq
  1318. //also speed customisation and shit, people love customization.
  1319. //--------
  1320. initModule({ location: tp.tracersFolder, title: "Color 2", storeAs: "tracersColor2", tooltip: "Static: (Unused)\nProximity: Moderately close colour\nVisibility: Visible.", defaultValue: "#00ff00", disableConditions: [["tracers", false], ["playerESP", false]], hideConditions: [["tracersType", "static"]], });
  1321. //initModule({ location: tp.tracersFolder, title: "C2 rainbow", storeAs: "tracersColor2Rainbow", tooltip: "🌈", defaultValue: true, disableConditions: [["tracers", false], ["playerESP", false]], hideConditions: [["tracersType", "static"]], });
  1322. //--------
  1323. initModule({ location: tp.tracersFolder, title: "Color 3", storeAs: "tracersColor3", tooltip: "Static: (Unused)\nProximity: Furthest colour\nVisibility: (Unused)", defaultValue: "#ffffff", disableConditions: [["tracers", false], ["playerESP", false]], showConditions: [["tracersType", "proximity"]], });
  1324. //initModule({ location: tp.tracersFolder, title: "C3 rainbow", storeAs: "tracersColor3Rainbow", tooltip: "🌈", defaultValue: false, disableConditions: [["tracers", false], ["playerESP", false]], showConditions: [["tracersType", "proximity"]], });
  1325. //-------ä
  1326. initModule({ location: tp.tracersFolder, title: "Dist 1->2", storeAs: "tracersColor1to2", tooltip: "Proximity: Distance from which it fades from 1 to 2. Should be the smaller range.", slider: { min: 0, max: 30, step: 0.25 }, defaultValue: 5, showConditions: [["tracersType", "proximity"]], disableConditions: [["tracers", false], ["playerESP", false]], });
  1327. initModule({ location: tp.tracersFolder, title: "Dist 2->3", storeAs: "tracersColor2to3", tooltip: "Proximity: Distance from which it fades from 2 to 3. Should be the larger range.", slider: { min: 0, max: 30, step: 0.25 }, defaultValue: 15, showConditions: [["tracersType", "proximity"]], disableConditions: [["tracers", false], ["playerESP", false]], });
  1328. tp.tracersFolder.addSeparator();
  1329. initModule({ location: tp.tracersFolder, title: "PredictionESPColor", storeAs: "predictionESPColor", tooltip: "Colour to use for the PredictionESP box", defaultValue: "#ff0000", disableConditions: [ ["predictionESP", false]], });
  1330. initModule({ location: tp.tracersFolder, title: "PredictionESPColorRainbow", storeAs: "predictionESPColorRainbow", tooltip: "Color to use for the PredictionESP box rainbow?", defaultValue: false, disableConditions: [ ["predictionESP", false]], });
  1331.  
  1332. tp.renderTab.pages[0].addSeparator();
  1333. initFolder({ location: tp.renderTab.pages[0], title: "Ammo ESP/Tracers Options", storeAs: "tracersAmmoFolder", });
  1334. initFolder({ location: tp.tracersAmmoFolder, title: "Ammo", storeAs: "ammoFolder", });
  1335. initModule({ location: tp.ammoFolder, title: "AESP", storeAs: "ammoESP", tooltip: "Displays where ammo is on the map", bindLocation: tp.renderTab.pages[1], });
  1336. initModule({ location: tp.ammoFolder, title: "ATracers", storeAs: "ammoTracers", tooltip: "No tooltip available", bindLocation: tp.renderTab.pages[1], });
  1337. tp.ammoFolder.addSeparator();
  1338. initModule({ location: tp.ammoFolder, title: "ARegime", storeAs: "ammoESPRegime", tooltip: "No tooltip available", bindLocation: tp.renderTab.pages[1], dropdown: [{ text: "When Depleted", value: "whendepleted" }, { text: "When Low", value: "whenlow" }, { text: "Below Max", value: "belowmax" }, { text: "Always On", value: "alwayson" },], defaultValue: "whendepleted", disableConditions: [["ammoESP", false], ["ammoTracers", false]], });
  1339. initModule({ location: tp.ammoFolder, title: "AColor", storeAs: "ammoESPColor", tooltip: "No tooltip available", defaultValue: "#ffff00", disableConditions: [["ammoESP", false], ["ammoTracers", false]], });
  1340. initFolder({ location: tp.tracersAmmoFolder, title: "Grenades", storeAs: "grenadesFolder", });
  1341. initModule({ location: tp.grenadesFolder, title: "GESP", storeAs: "grenadeESP", tooltip: "Displays where grenade pickupables is on the map", bindLocation: tp.renderTab.pages[1], });
  1342. initModule({ location: tp.grenadesFolder, title: "GTracers", storeAs: "grenadeTracers", tooltip: "No tooltip available", bindLocation: tp.renderTab.pages[1], });
  1343. tp.grenadesFolder.addSeparator();
  1344. initModule({ location: tp.grenadesFolder, title: "GRegime", storeAs: "grenadeESPRegime", tooltip: "No tooltip available", bindLocation: tp.renderTab.pages[1], dropdown: [{ text: "When Depleted", value: "whendepleted" }, { text: "When Low", value: "whenlow" }, { text: "Below Max", value: "belowmax" }, { text: "Always On", value: "alwayson" },], defaultValue: "whendepleted", disableConditions: [["grenadeESP", false], ["grenadeTracers", false]], });
  1345. initModule({ location: tp.grenadesFolder, title: "GColor", storeAs: "grenadeESPColor", tooltip: "No tooltip available", defaultValue: "#00ffff", disableConditions: [["grenadeESP", false], ["grenadeTracers", false]], });
  1346. tp.renderTab.pages[0].addSeparator();
  1347. initModule({ location: tp.renderTab.pages[0], title: "Show Look Dir", storeAs: "lookTracers", tooltip: "Renders the looking direction of each player as a line", bindLocation: tp.renderTab.pages[1], });
  1348. initFolder({ location: tp.renderTab.pages[0], title: "Look Direction Options", storeAs: "lookTracersFolder", });
  1349. initModule({ location: tp.lookTracersFolder, title: "Render Above", storeAs: "lookTracersRGI1", tooltip: "Renders LookTracers above obstacles", bindLocation: tp.renderTab.pages[1], });
  1350. //initModule({ location: tp.lookTracersFolder, title: "length", storeAs: "lookTracersLength", slider: { min: 0, max: 100, step: 0.25 }, defaultValue: 75, });
  1351. initModule({ location: tp.lookTracersFolder, title: "LookTracerColor", storeAs: "lookTracersColor", tooltip: "Color of the LookTracers", defaultValue: "#00ffff", });
  1352. tp.renderTab.pages[0].addSeparator();
  1353. initModule({ location: tp.renderTab.pages[0], title: "FOV", storeAs: "fov", tooltip: "Controls the FOV of the game", slider: { min: 0, max: 360, step: 3 }, defaultValue: 72, });
  1354. initModule({ location: tp.renderTab.pages[0], title: "Zoom FOV", storeAs: "zoom", tooltip: "Controls how zoomed in/out you are. Default keybind is C to zoom", slider: { min: 0, max: 72, step: 1 }, defaultValue: 15, bindLocation: tp.renderTab.pages[1], defaultBind: "C", });
  1355. initModule({ location: tp.renderTab.pages[0], title: "No Mini Egg", storeAs: "noMiniEgg", tooltip: "Makes the screen not squished when under the Mini Egg effect.", bindLocation: tp.renderTab.pages[1] })
  1356. tp.renderTab.pages[0].addSeparator();
  1357. initModule({ location: tp.renderTab.pages[0], title: "Perspective", storeAs: "perspective", tooltip: "Allows you to switch between third and first person. Think Minecraft F5!", bindLocation: tp.renderTab.pages[1], dropdown: [{ text: "1st Person (Default)", value: "firstPerson" }, { text: "3rd Person", value: "thirdPerson" }, { text: "3rd Person (Alt)", value: "thirdPersonAlt" } ], defaultValue: "disabled", defaultBind: "Digit5", });
  1358. initFolder({ location: tp.renderTab.pages[0], title: "Perspective Options", storeAs: "perspectiveFolder", });
  1359. // initModule({ location: tp.perspectiveFolder, title: "Alpha Effect", storeAs: "perspectiveAlpha", tooltip: "Makes players a bit transparent when in third person", bindLocation: tp.renderTab.pages[1], });
  1360. // tp.perspectiveFolder.addSeparator();
  1361. initModule({ location: tp.perspectiveFolder, title: "Y Offset", storeAs: "perspectiveY", tooltip: "Offset of the camera in y-direction (how far behind should it be?)", slider: { min: 0, max: 30, step: 0.25 }, defaultValue: 0.5});
  1362. initModule({ location: tp.perspectiveFolder, title: "Z Offset", storeAs: "perspectiveZ", tooltip: "Offset of the camera in z-direction (how far above should it be?)", slider: { min: 0, max: 30, step: 0.25 }, defaultValue: 2});
  1363. initModule({ location: tp.renderTab.pages[0], title: "CamWIP", storeAs: "freecam", tooltip: "Forever a WIP!!!", bindLocation: tp.renderTab.pages[1], });
  1364. initModule({ location: tp.renderTab.pages[0], title: "Wireframe", storeAs: "wireframe", tooltip: "Outlines map objects to allow you to see directly though walls. Will leave rendering artifacts on the skybox, making the game basically unplayable", bindLocation: tp.renderTab.pages[1], });
  1365. initModule({ location: tp.renderTab.pages[0], title: "Particle Speed", storeAs: "particleSpeedMultiplier", tooltip: "Adjusts speed of particles :D", slider: { min: 0.05, max: 5, step: 0.05 }, defaultValue: 1, });
  1366. initModule({ location: tp.renderTab.pages[0], title: "Egg Size", storeAs: "eggSize", tooltip: "Changes how big eggs are. This does not affect hitboxes and is client-side only", slider: { min: 0, max: 10, step: 0.25 }, defaultValue: 1, });
  1367. tp.renderTab.pages[0].addSeparator();
  1368. initModule({ location: tp.renderTab.pages[0], title: "Set Detail", storeAs: "setDetail", tooltip: "Changes quality of game graphics", 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" });
  1369. initModule({ location: tp.renderTab.pages[0], title: "Textures", storeAs: "enableTextures", tooltip: "Disables some textures. primarily, the sky", bindLocation: tp.renderTab.pages[1], defaultValue: true, });
  1370. initModule({ location: tp.renderTab.pages[0], title: "Render Delay", storeAs: "renderDelay", tooltip: "Basically, this adds extra FPS buffer", slider: { min: 0, max: 30000, step: 10 }, defaultValue: 0, });
  1371. //HUD MODULES
  1372. initFolder({ location: tp.mainPanel, title: "HUD", storeAs: "hudFolder", });
  1373. initTabs({ location: tp.hudFolder, storeAs: "hudTab" }, [
  1374. {
  1375. title: "WIP", content:
  1376. `Sorry! No guide yet!`},
  1377. ]);
  1378. initModule({ location: tp.hudTab.pages[0], title: "Show Bloom", storeAs: "revealBloom", tooltip: "Displays the next shot's bloom as a red dot onscreen", bindLocation: tp.hudTab.pages[1], });
  1379. initModule({ location: tp.hudTab.pages[0], title: "Show LOS", storeAs: "showLOS", tooltip: "Changes the crosshair's color if the player is in an enemy's line of sight", bindLocation: tp.hudTab.pages[1], });
  1380. initModule({ location: tp.hudTab.pages[0], title: "Show MinAngle", storeAs: "showMinAngle", tooltip: "Draws a circle representing the aimbot's minAngle to the hud", bindLocation: tp.hudTab.pages[1], });
  1381. initModule({ showConditions: [["disabledlmao", true]], location: tp.hudTab.pages[0], title: "Leaderboard", storeAs: "highlightLeaderboard", tooltip: "Sie wurden enterbt", bindLocation: tp.hudTab.pages[1], enableConditions: [["aimbot", true]], });
  1382. tp.hudTab.pages[0].addSeparator();
  1383. initModule({ location: tp.hudTab.pages[0], title: "Co-ords", storeAs: "showCoordinates", tooltip: "Displays current position on the map", bindLocation: tp.hudTab.pages[1], });
  1384. initModule({ location: tp.hudTab.pages[0], title: "RadarWIP", storeAs: "radar", tooltip: "Work-in-progress module. You should leave this off if you are not a dev", bindLocation: tp.hudTab.pages[1], });
  1385. initModule({ location: tp.hudTab.pages[0], title: "HP Display", storeAs: "playerStats", tooltip: "Displays the health of your opponents", bindLocation: tp.hudTab.pages[1], });
  1386. initModule({ location: tp.hudTab.pages[0], title: "PlayerInfo", storeAs: "playerInfo", tooltip: "Displays added information about the player you're targeting", bindLocation: tp.hudTab.pages[1], });
  1387. initModule({ location: tp.hudTab.pages[0], title: "GameInfo", storeAs: "gameInfo", tooltip: "Displays extra game information", bindLocation: tp.hudTab.pages[1], });
  1388. initModule({ location: tp.hudTab.pages[0], title: "Performance", storeAs: "performanceInfo", tooltip: "Shows performance information like memory usage", bindLocation: tp.hudTab.pages[1], });
  1389. initModule({ location: tp.hudTab.pages[0], title: "ShowStream", storeAs: "showStreams", tooltip: "Detects & displays ongoing twitch streamers", bindLocation: tp.hudTab.pages[1], });
  1390. tp.hudTab.pages[0].addSeparator();
  1391. initModule({ location: tp.hudTab.pages[0], title: "MiniMap", storeAs: "minimap", tooltip: "Displays a top down view of your game", bindLocation: tp.hudTab.pages[1], });
  1392. initModule({ location: tp.hudTab.pages[0], title: "MiniMap Zoom", storeAs: "minimapZoom", tooltip: "How much the minimap camera should zoom in", slider: { min: 0.1, max: 20, step: 0.1 }, defaultValue: 5, showConditions: [["minimap", true]], });
  1393. initModule({ location: tp.hudTab.pages[0], title: "MiniMap Size", storeAs: "minimapSize", tooltip: "How big the minimap should be on the screen", slider: { min: 0.1, max: 5, step: 0.1 }, defaultValue: 1, showConditions: [["minimap", true]], });
  1394. //CHAT MODULES
  1395. initFolder({ location: tp.mainPanel, title: "Chat", storeAs: "chatFolder", });
  1396. initTabs({ location: tp.chatFolder, storeAs: "chatTab" }, [
  1397. {
  1398. title: "WIP", content:
  1399. `Sorry! No guide yet!`},
  1400. ]);
  1401. initModule({ location: tp.chatTab.pages[0], title: "InfiniHistory", storeAs: "chatExtend", tooltip: "Disables the default limiting of message history", bindLocation: tp.chatTab.pages[1], });
  1402. initModule({ location: tp.chatTab.pages[0], title: "HighlightTxt", storeAs: "chatHighlight", tooltip: "Allows you to highlight text from the chat to copy somewhere else", bindLocation: tp.chatTab.pages[1], });
  1403. // initModule({ location: tp.chatTab.pages[0], title: "RestoreScroll", storeAs: "restoreScroll", tooltip: "Dont fucking add tooltips to modules that HAVE BEEN COMMENTED OUT WTF PUPPY?", bindLocation: tp.chatTab.pages[1], });
  1404. initModule({ location: tp.chatTab.pages[0], title: "Max Ingame", storeAs: "maxChat", tooltip: "The number of messages to show ingame (if unset, infinite history will cause issues)", slider: { min: 0, max: 30, step: 1 }, defaultValue: 5, });
  1405. initModule({ location: tp.chatTab.pages[0], title: "ShowFiltered", storeAs: "disableChatFilter", tooltip: "View messages that are caught by the game filter in red", bindLocation: tp.chatTab.pages[1], });
  1406. initModule({ location: tp.chatTab.pages[0], title: "UnfilterNames", storeAs: "unfilterNames", tooltip: "See filtered people's real names, highlighed in the leaderboard", bindLocation: tp.chatTab.pages[1], });
  1407. tp.chatTab.pages[0].addSeparator();
  1408. initModule({ location: tp.chatTab.pages[0], title: "BypassFilter", storeAs: "chatFilterBypass", tooltip: "Bypass naughty word game message filter!!!!1111 :D", bindLocation: tp.chatTab.pages[1], });
  1409. initModule({ location: tp.chatTab.pages[0], title: "Tall Chat", storeAs: "tallChat", tooltip: "Makes the chat text taller, appends a character to all sent messages", bindLocation: tp.chatTab.pages[1], });
  1410. tp.chatTab.pages[0].addSeparator();
  1411. initFolder({ location: tp.chatTab.pages[0], title: "FakeMessage", storeAs: "fakeMessageFolder", });
  1412. let listOfIDs = [];
  1413. if (unsafeWindow.extern && unsafeWindow.extern.inGame && ss && ss.PLAYERS) {
  1414. ss.PLAYERS.forEach((player) => {
  1415. listOfIDs.push({ text: player.name, value: String(player.id) });
  1416. log({ text: player.name, value: player.id })
  1417. });
  1418. };
  1419. initModule({ location: tp.fakeMessageFolder, title: "Send As", storeAs: "fakeMessageID", tooltip: "Who to send fake message as", bindLocation: tp.chatTab.pages[1], dropdown: [ ...listOfIDs, { text: "MOD", value: "254" }, { text: "SERVER", value: "255" } ], defaultValue: "255" });
  1420. initModule({ location: tp.fakeMessageFolder, title: '(Refresh List)', storeAs: 'fakeMessageRefresh', button: 'REFRESH', tooltip: "Refreshes list", bindLocation: tp.chatTab.pages[1], clickFunction: function () {
  1421. updateMenu = true;
  1422. } });
  1423. initModule({ location: tp.fakeMessageFolder, title: "Content", storeAs: "fakeMessageText", tooltip: "The content of the fake message", defaultValue: "ЅtateFarm Client On Top! ", });
  1424. initModule({ location: tp.fakeMessageFolder, title: "Bold Text", storeAs: "fakeMessageBold", tooltip: "Bold text", bindLocation: tp.chatTab.pages[1], });
  1425. initModule({ location: tp.fakeMessageFolder, title: 'SEND', storeAs: 'fakeMessageSend', button: 'SEND MESSAGE', tooltip: "Allows sending messages as MOD or SERVER (client sided only)", bindLocation: tp.chatTab.pages[1], clickFunction: function () {
  1426. if (ss.addChat && unsafeWindow.extern.inGame) {
  1427. try {
  1428. if (ss.isBadWord(extract("fakeMessageText"))) createPopup("Message would be filtered.", "error");
  1429. ss.addChat(extract("fakeMessageText"), !!extract("fakeMessageBold"), Number(extract("fakeMessageID")));
  1430. } catch (error) {
  1431. log("shit, sending a fake message failed. damn lmao.", error)
  1432. };
  1433. }
  1434. } });
  1435. tp.chatTab.pages[0].addSeparator();
  1436. initModule({ location: tp.chatTab.pages[0], title: "Spammer", storeAs: "spamChat", tooltip: "Automatically send messages", bindLocation: tp.chatTab.pages[1], });
  1437. initFolder({ location: tp.chatTab.pages[0], title: "Spammer Options", storeAs: "spammerFolder", });
  1438. initModule({ location: tp.spammerFolder, title: "Delay (ms)", storeAs: "spamChatDelay", tooltip: "The interval to send messages", slider: { min: 250, max: 60000, step: 10 }, defaultValue: 500, enableConditions: [["spamChat", true]], });
  1439. initModule({ location: tp.spammerFolder, title: "Spam Text", storeAs: "spamChatText", tooltip: "The message to spam", defaultValue: "ЅtateFarm Client On Top! ", });
  1440. tp.chatTab.pages[0].addSeparator();
  1441. initFolder({ location: tp.chatTab.pages[0], title: "Trolling", storeAs: "trollingFolder", });
  1442. initModule({ location: tp.trollingFolder, title: "Mock", storeAs: "mockMode", tooltip: "Rudely mocks people talking in chat", bindLocation: tp.chatTab.pages[1], });
  1443. initModule({ location: tp.trollingFolder, title: "Mock no repeat", storeAs: "mockModeNoRePeat", tooltip: "Makes mock not respond if it doesn't have an answer, instead of copying the message", bindLocation: tp.chatTab.pages[1], });
  1444. initModule({ location: tp.trollingFolder, title: "Announcer", storeAs: "announcer", tooltip: "Announces when you change GUI config", bindLocation: tp.chatTab.pages[1], });
  1445. tp.trollingFolder.addSeparator();
  1446. initModule({ location: tp.trollingFolder, title: "AutoEZ", storeAs: "autoEZ", tooltip: "Gloats on people when you kill them", bindLocation: tp.chatTab.pages[1], });
  1447. initModule({ location: tp.trollingFolder, title: "CheatAccuse", storeAs: "cheatAccuse", tooltip: "Accuses your killer of cheating", bindLocation: tp.chatTab.pages[1], });
  1448. tp.chatTab.pages[0].addSeparator();
  1449. initFolder({ location: tp.chatTab.pages[0], title: "Join/Leave Msgs Options", storeAs: "joinLeaveFolder", });
  1450. initModule({ location: tp.joinLeaveFolder, title: "Join Msgs", storeAs: "joinMessages", tooltip: " Notify you when players join", bindLocation: tp.chatTab.pages[1], });
  1451. initModule({ location: tp.joinLeaveFolder, title: "Leave Msgs", storeAs: "leaveMessages", tooltip: "Notify you when players leave", bindLocation: tp.chatTab.pages[1], });
  1452. tp.joinLeaveFolder.addSeparator();
  1453. initModule({ location: tp.joinLeaveFolder, title: "Send2Chat", storeAs: "publicBroadcast", tooltip: "Decides if these messages are shown to only you or everyone", bindLocation: tp.chatTab.pages[1], disableConditions: [["joinMessages", false], ["leaveMessages", false]], });
  1454. initModule({ location: tp.joinLeaveFolder, title: "[SFC]Added", storeAs: "joinLeaveBranding", tooltip: "If send2chat is enabled, this will add [SFC] to the beginning of the join/leave messages", bindLocation: tp.chatTab.pages[1], disableConditions: [["joinMessages", false], ["leaveMessages", false]], });
  1455. //LISTS MODULES
  1456. initFolder({ location: tp.mainPanel, title: "Lists", storeAs: "listsFolder", });
  1457. initTabs({ location: tp.listsFolder, storeAs: "listsTab" }, [
  1458. {
  1459. title: "WIP", content:
  1460. `Sorry! No guide yet!`},
  1461. ]);
  1462. initModule({ location: tp.listsTab.pages[0], title: "Whitelist", storeAs: "whitelist", tooltip: "A list of names to use the below configuration. Separate with commas", defaultValue: "User-1, User-2", });
  1463. initFolder({ location: tp.listsTab.pages[0], title: "Whitelist (Target Only) Options", storeAs: "whitelistFolder", });
  1464. initModule({ location: tp.whitelistFolder, title: "WAimbot", storeAs: "enableWhitelistAimbot", tooltip: "Only will aimbot on the specified whitelist player(s). if the player(s) are all dead, you will target nothing", bindLocation: tp.listsTab.pages[1], });
  1465. initModule({ location: tp.whitelistFolder, title: "When None Visible", storeAs: "enableWhenNoneVisible", tooltip: "Still targets non-whitelisted players if no whitelisted player is a valid target", bindLocation: tp.listsTab.pages[1], });
  1466. initModule({ location: tp.whitelistFolder, title: "WESP", storeAs: "enableWhitelistTracers", tooltip: "A special behavior will appear to whitelisted ESP people", bindLocation: tp.listsTab.pages[1], disableConditions: [["tracers", false], ["playerESP", false]], });
  1467. initModule({ location: tp.whitelistFolder, title: "WESPType", storeAs: "whitelistESPType", tooltip: "Make their ESP line a special color, or exclude", bindLocation: tp.listsTab.pages[1], dropdown: [{ text: "Only Include", value: "onlyinclude" }, { text: "Highlight", value: "highlight" },], defaultValue: "onlyinclude", disableConditions: [["tracers", false], ["playerESP", false]], showConditions: [["enableWhitelistTracers", true]], });
  1468. initModule({ location: tp.whitelistFolder, title: "WHighlight", storeAs: "whitelistColor", tooltip: "The color to highlight whitelisted players in", defaultValue: "#e80aac", disableConditions: [["tracers", false], ["playerESP", false]], showConditions: [["enableWhitelistTracers", true], ["whitelistESPType", "highlight"]], });
  1469. tp.listsTab.pages[0].addSeparator();
  1470. initModule({ location: tp.listsTab.pages[0], title: "Blacklist", storeAs: "blacklist", tooltip: "A list of names to use the below configuration. Separate with commas", defaultValue: "User-1, User-2", });
  1471. initFolder({ location: tp.listsTab.pages[0], title: "Blacklist (Exclude) Options", storeAs: "blacklistFolder", });
  1472. initModule({ location: tp.blacklistFolder, title: "BAimbot", storeAs: "enableBlacklistAimbot", tooltip: "Never will aimbot on the specified whitelist player(s)", bindLocation: tp.listsTab.pages[1], });
  1473. initModule({ location: tp.blacklistFolder, title: "BESP", storeAs: "enableBlacklistTracers", tooltip: "A special behavior will appear to blacklisted ESP people", bindLocation: tp.listsTab.pages[1], disableConditions: [["tracers", false], ["playerESP", false]], });
  1474. initModule({ location: tp.blacklistFolder, title: "BESPType", storeAs: "blacklistESPType", tooltip: "what", bindLocation: tp.listsTab.pages[1], dropdown: [{ text: "Just Exclude", value: "justexclude" }, { text: "Highlight", value: "highlight" },], defaultValue: "justexclude", disableConditions: [["tracers", false], ["playerESP", false]], showConditions: [["enableBlacklistTracers", true]], });
  1475. initModule({ location: tp.blacklistFolder, title: "BHighlight", storeAs: "blacklistColor", tooltip: "Color to use for blacklisted highlighting", defaultValue: "#00ff00", disableConditions: [["tracers", false], ["playerESP", false]], showConditions: [["enableBlacklistTracers", true], ["blacklistESPType", "highlight"]], });
  1476. //AUTOMATION MODULES
  1477. initFolder({ location: tp.mainPanel, title: "Automation", storeAs: "automationFolder", });
  1478. initTabs({ location: tp.automationFolder, storeAs: "automationTab" }, [
  1479. {
  1480. title: "WIP", content:
  1481. `Sorry! No guide yet!`},
  1482. ]);
  1483. initModule({
  1484. location: tp.automationTab.pages[0], title: "Flood Report", storeAs: "floodReport", tooltip: "Mass reports everyone. o7, comrade", bindLocation: tp.automationTab.pages[1], button: "Spam Now!", clickFunction: function () {
  1485. createPopup("Thank you for your efforts comrade! o7");
  1486. spamReport();
  1487. },
  1488. });
  1489. tp.automationTab.pages[0].addSeparator();
  1490. initModule({ location: tp.automationTab.pages[0], title: "Bunnyhop", storeAs: "bunnyhop", tooltip: "Makes you automatically bunnyhop when holding down the jump button", bindLocation: tp.automationTab.pages[1], });
  1491. initModule({ location: tp.automationTab.pages[0], title: "Auto Walk", storeAs: "autoWalk", tooltip: "Walks forward automatically", bindLocation: tp.automationTab.pages[1], });
  1492. initModule({ location: tp.automationTab.pages[0], title: "Auto Strafe", storeAs: "autoStrafe", tooltip: "Strafes automatically", bindLocation: tp.automationTab.pages[1], });
  1493. initModule({ location: tp.automationTab.pages[0], title: "Auto Jump", storeAs: "autoJump", tooltip: "Jumps on the specified interval", bindLocation: tp.automationTab.pages[1], });
  1494. initModule({ location: tp.automationTab.pages[0], title: "Jump Delay", storeAs: "autoJumpDelay", tooltip: "How often should AutoJump trigger", slider: { min: 1, max: 10000, step: 1 }, defaultValue: 1, showConditions: [["autoJump", true]], });
  1495. tp.automationTab.pages[0].addSeparator();
  1496. initModule({ location: tp.automationTab.pages[0], title: "AutoWeapon", storeAs: "autoWeapon", tooltip: "Automatically picks a weapon", bindLocation: tp.automationTab.pages[1], dropdown: [{ text: "Disabled", value: "disabled" }, { text: "EggK-47", value: "eggk47" }, { text: "Scrambler", value: "scrambler" }, { text: "Free Ranger", value: "freeranger" }, { text: "RPEGG", value: "rpegg" }, { text: "Whipper", value: "whipper" }, { text: "Crackshot", value: "crackshot" }, { text: "Tri-Hard", value: "trihard" }, { text: "Randomised", value: "random" }], defaultValue: "disabled" });
  1497. initModule({ location: tp.automationTab.pages[0], title: "AutoGrenade", storeAs: "autoGrenade", tooltip: "Automatically grenades w/ a delay", bindLocation: tp.automationTab.pages[1], });
  1498. tp.automationTab.pages[0].addSeparator();
  1499. initFolder({ location: tp.automationTab.pages[0], title: "Auto Join Options", storeAs: "autoJoinFolder", });
  1500. initModule({ location: tp.autoJoinFolder, title: "Auto Join", storeAs: "autoJoin", tooltip: "Automatically joins a game", bindLocation: tp.automationTab.pages[1], });
  1501. initModule({ location: tp.autoJoinFolder, title: "Join Code", storeAs: "joinCode", tooltip: "The gamecode used by AutoJoin", defaultValue: "CODE", enableConditions: [["autoJoin", true]], });
  1502. initModule({ location: tp.autoJoinFolder, title: "Get Code", storeAs: "getCode", tooltip: "Get the current gamecode for the autoJoin code field, uses last code you were in if in menu", button: "Retrieve", clickFunction: function () { change("joinCode", GAMECODE) }, enableConditions: [["autoJoin", true]], });
  1503. initFolder({ location: tp.automationTab.pages[0], title: "Auto Name Options", storeAs: "autoNamesFolder", });
  1504. initModule({ location: tp.autoNamesFolder, title: "Use Name", storeAs: "useCustomName", tooltip: "Automaticaly names yourself", bindLocation: tp.automationTab.pages[1], });
  1505. initModule({ location: tp.autoNamesFolder, title: "New Name", storeAs: "usernameAutoJoin", tooltip: "The name used by useCustomName", defaultValue: "ЅtateFarmer", enableConditions: [["useCustomName", true]], });
  1506. //the name usernameAutoJoin is only kept for compatability
  1507. initModule({ location: tp.autoNamesFolder, title: "Copy Name", storeAs: "copyName", button: "Steal Name", enableConditions: [["useCustomName", true]], tooltip: "Steals a random lobby player's name", bindLocation: tp.automationTab.pages[1], clickFunction: function(){
  1508. const copiedName = retrieveCopiedName();
  1509. log("Retrieved copied name:",copiedName);
  1510. change("usernameAutoJoin",(copiedName||"ЅtateFarmer"));
  1511. },});
  1512. initModule({ location: tp.autoNamesFolder, title: "Random Name", storeAs: "randomName", button: "Randomise Name", enableConditions: [["useCustomName", true]], tooltip: "Gets a random shell shockers default sounding name", bindLocation: tp.automationTab.pages[1], clickFunction: function(){
  1513. const randomisedName = unsafeWindow.extern.generateRandomName();
  1514. change("usernameAutoJoin",(randomisedName||"ЅtateFarmer"));
  1515. },});
  1516. tp.automationTab.pages[0].addSeparator();
  1517. initModule({ location: tp.automationTab.pages[0], title: "AutoRespawn", storeAs: "autoRespawn", tooltip: "Automatically respawn", bindLocation: tp.automationTab.pages[1], });
  1518. initModule({ location: tp.automationTab.pages[0], title: "Auto Team", storeAs: "autoTeam", tooltip: "Automatically picks a team", bindLocation: tp.automationTab.pages[1], dropdown: [{ text: "Disabled", value: "disabled" }, { text: "Red Team", value: "red" }, { text: "Blue Team", value: "blue" }, { text: "Random Team", value: "random" }], defaultValue: "disabled" });
  1519. tp.automationTab.pages[0].addSeparator();
  1520. initFolder({ location: tp.automationTab.pages[0], title: "Game Blacklist Settings", storeAs: "gameBlacklistFolder", });//Game Blacklist Folder
  1521. initModule({ location: tp.gameBlacklistFolder, title: "Blacklist On", storeAs: "gameBlacklist", tooltip: "Prevents you from joining specific games", bindLocation: tp.automationTab.pages[1], });
  1522. initModule({ location: tp.gameBlacklistFolder, title: "Codes:", storeAs: "gameBlacklistCodes", tooltip: "The game list used by GameBlacklist, seperated with commas", defaultValue: "", });
  1523. initModule({ location: tp.gameBlacklistFolder, title: "Get BL Code", storeAs: "getCodeBlacklist", button: "Retrieve", tooltip: "Get the current gamecode for the GameBlacklist code field, uses last code you were in if in menu", bindLocation: tp.automationTab.pages[1], clickFunction: function(){
  1524. if (GAMECODE != undefined && GAMECODE != null){
  1525. if (extract("gameBlacklistCodes") != "" && extract("gameBlacklistCodes") != undefined) { //does the list exist yet?
  1526. let cds = extract("gameBlacklistCodes").split(","); //get the codes as an array
  1527. if(cds.includes(GAMECODE)){ //the code is already in the list!
  1528. createPopup("Gamecode already in list!"); //notify user that we aren't adding the code'
  1529. return; //no need to add code to list, so gtfo
  1530. }
  1531. }
  1532. extract("gameBlacklistCodes") != undefined ? change("gameBlacklistCodes", extract("gameBlacklistCodes")+GAMECODE+",") : change("gameBlacklistCodes", GAMECODE+",");
  1533. } else {
  1534. createPopup("Join a game first");
  1535. };
  1536. },});
  1537. initModule({ location: tp.gameBlacklistFolder, title: "Clear BL Codes", storeAs: "clearCodeBlacklist", button: "Clear", tooltip: "Empties the GameBlacklist code list", bindLocation: tp.automationTab.pages[1], clickFunction: function(){ //capitalise PLS
  1538. //not a big fan of this "logic in init" thing, but it's basically the norm now + the funcs are really designed to be used this way so yh :( (Seq rant)
  1539. if(extract("gameBlacklistCodes") != undefined) //do we have codes yet? Otherwise the log is either gonna be pointless or error...
  1540. log("Clearing BL codes, cleared list: " +extract("gameBlacklistCodes")); //wouldn't be needed but allows for retrival of codes on accidental/partial deletion, and one more line of log can't hurt too much, can it?
  1541. change("gameBlacklistCodes", ""); //just set the blacklist to an empty String
  1542. },});
  1543. tp.automationTab.pages[0].addSeparator();
  1544. initModule({ location: tp.automationTab.pages[0], title: "LeaveGame", storeAs: "leaveGame", button: "Unjoin Game", tooltip: "Leave to the menu", bindLocation: tp.automationTab.pages[1], clickFunction: function () { unsafeWindow.vueApp.onLeaveGameConfirm() }, });
  1545. initModule({ location: tp.automationTab.pages[0], title: "LeaveEmpty", storeAs: "leaveEmpty", tooltip: "Leaves empty games", bindLocation: tp.automationTab.pages[1], });
  1546. initModule({ location: tp.automationTab.pages[0], title: "Auto Leave", storeAs: "autoLeave", tooltip: "Automatically leaves after a specified interval", bindLocation: tp.automationTab.pages[1], });
  1547. initModule({ location: tp.automationTab.pages[0], title: "Delay (s)", storeAs: "autoLeaveDelay", tooltip: "The interval after which autoLeave evacuates to the lobby", slider: { min: 0, max: 3600, step: 1 }, defaultValue: 300, enableConditions: [["autoLeave", true]] });
  1548. tp.automationTab.pages[0].addSeparator();
  1549. initModule({ location: tp.automationTab.pages[0], title: "Gamemode", storeAs: "autoGamemode", tooltip: "Picks a gamemode for autojoin", bindLocation: tp.automationTab.pages[1], dropdown: [{ text: "Disabled", value: "disabled" }, { text: "FFA", value: "ffa" }, { text: "Teams", value: "teams" }, { text: "Captula", value: "captula" }, { text: "KotC", value: "kotc" }, { text: "Randomised", value: "random" }], defaultValue: "disabled" });
  1550. initModule({ location: tp.automationTab.pages[0], title: "Auto Region", storeAs: "autoRegion", tooltip: "Automatically selects a region to play in", bindLocation: tp.automationTab.pages[1], dropdown: [{ text: "Disabled", value: "disabled" }, { text: "Chile", value: "santiago" }, { text: "Germany", value: "germany" }, { text: "Singapore", value: "singapore" }, { text: "Sydney", value: "sydney" }, { text: "US Central", value: "uscentral" }, { text: "US East", value: "useast" }, { text: "US West", value: "uswest" }, { text: "Randomised", value: "random" }], defaultValue: "disabled" });
  1551. tp.automationTab.pages[0].addSeparator();
  1552. initModule({ location: tp.automationTab.pages[0], title: "Egg Color", storeAs: "eggColor", tooltip: "Picks the egg color automatically", bindLocation: tp.automationTab.pages[1], dropdown: [{ text: "Disabled", value: "disabled" }, { text: "White", value: "white" }, { text: "Light Blue", value: "lightblue" }, { text: "Light Eggshell", value: "lighteggshell" }, { text: "Eggshell", value: "eggshell" }, { text: "Dark Eggshell", value: "darkeggshell" }, { text: "Darker Eggshell", value: "darkereggshell" }, { text: "Darkest Eggshell", value: "darkesteggshell" }, { text: "Red (VIP)", value: "red" }, { text: "Purple (VIP)", value: "purple" }, { text: "Pink (VIP)", value: "pink" }, { text: "Yellow (VIP)", value: "yellow" }, { text: "Blue (VIP)", value: "blue" }, { text: "Green (VIP)", value: "green" }, { text: "Lime (VIP)", value: "lime" }, /*{text: "Randomised", value: "random"}*/], defaultValue: "disabled" });
  1553. initModule({ location: tp.automationTab.pages[0], title: "Auto Stamp", storeAs: "autoStamp", tooltip: "Picks the egg stamp automatically", bindLocation: tp.automationTab.pages[1], dropdown: [{ text: "Disabled", value: "disabled" }, { text: "Target Stamp", value: "target" }, { text: "No Sign Stamp", value: "nosign" }, { text: "Question Mark Stamp?", value: "question" }, { text: "Peace Stamp", value: "peace" }, { text: "Thumbs Up Stamp", value: "thumbsup" }, { text: "Pablo Smile Stamp", value: "pablosmile" }], defaultValue: "disabled" });
  1554. initModule({ location: tp.automationTab.pages[0], title: "Auto Hat", storeAs: "autoHat", tooltip: "Picks the egg hat automatically", bindLocation: tp.automationTab.pages[1], dropdown: [{ text: "Disabled", value: "disabled" }, { text: "Ball Cap", value: "ballcap" }, { text: "Boat Fedora", value: "boatfedora" }, { text: "Top Hat", value: "tophat" }, { text: "Derby Hat", value: "derbyhat" }, { text: "Mountie Hat", value: "mountiehat" }, { text: "Pablo Hat", value: "pablohat" }], defaultValue: "disabled" });
  1555. };
  1556. //BOTTING MODULES
  1557. initFolder({ location: tp.mainPanel, title: "Botting", storeAs: "bottingFolder", });
  1558. initTabs({ location: tp.bottingFolder, storeAs: "bottingTab" }, [
  1559. {
  1560. title: "WIP", content:
  1561. `Sorry! No guide yet!
  1562. But check out the GitHub guide.`},
  1563. ]);
  1564. initModule({ location: tp.bottingTab.pages[0], title: "Show Panel", storeAs: "showBotPanel", tooltip: "Show the bot panel", bindLocation: tp.bottingTab.pages[1], button: "Show Panel", defaultBind: "J", clickFunction: () => {
  1565. tp.botPanel.hidden = !tp.botPanel.hidden;
  1566. }});
  1567. tp.bottingTab.pages[0].addSeparator();
  1568. initModule({ location: tp.bottingTab.pages[0], title: "How To?", storeAs: "bottingGuide", tooltip: "Click for infos on how to get started and free candy", button: "Link", clickFunction: function () { GM_openInTab(bottingGuideURL, { active: true }) }, });
  1569. if (allowAccess) {
  1570. //THEMING MODULES
  1571. initFolder({ location: tp.mainPanel, title: "Theming", storeAs: "themingFolder", });
  1572. initTabs({ location: tp.themingFolder, storeAs: "themingTab" }, [
  1573. {
  1574. title: "WIP", content:
  1575. `Sorry! No guide yet!`},
  1576. ]);
  1577. initModule({ location: tp.themingTab.pages[0], title: "Skybox", storeAs: "skybox", tooltip: "Allows you to switch out Shell's default skybox", bindLocation: tp.themingTab.pages[1], dropdown: loadedSkyboxes, changeFunction: (newSkybox) => {
  1578. if (!unsafeWindow[skyboxName]) return;
  1579. unsafeWindow[skyboxName].material.reflectionTexture.coordinatesMode = 5; //L.BABYLON.Texture.SKYBOX_MODE;
  1580. }});
  1581. initModule({ location: tp.themingTab.pages[0], title: "Randomize Skybox", storeAs: "randomSkyBox", tooltip: "Switches the skybox to a random one", bindLocation: tp.themingTab.pages[1], });
  1582. initModule({ location: tp.themingTab.pages[0], title: "Switch Interval", storeAs: "randomSkyBoxInterval", tooltip: "The interval after which the skybox is switched, given that randomSkyBox is enabled. In minutes", slider: { min: 1, max: 10, step: 0.1 }, defaultValue: 3, });
  1583. tp.themingTab.pages[0].addSeparator();
  1584. initModule({ location: tp.themingTab.pages[0], title: "Legacy Models", storeAs: "legacyModels", tooltip: "Switches to the old models", bindLocation: tp.themingTab.pages[1], });
  1585. initModule({ location: tp.themingTab.pages[0], title: "Game Filter", storeAs: "filter", tooltip: "Adds a color tint to the game", bindLocation: tp.themingTab.pages[1], dropdown: [
  1586. {text: "Default", value: 2},
  1587. {text: "Blue", value: 3},
  1588. {text: "Mexico", value: 4},
  1589. ],});
  1590. initModule({ location: tp.themingTab.pages[0], title: "Gun Position", storeAs: "gunPosition", tooltip: "Changes the position of your player's gun", bindLocation: tp.themingTab.pages[1], dropdown: [
  1591. {text: "Right", value: "right"},
  1592. {text: "Left", value: "left"},
  1593. {text: "Hidden", value: "hidden"},
  1594. ],});
  1595. tp.themingTab.pages[0].addSeparator();
  1596. initModule({ location: tp.themingTab.pages[0], title: "Enable Bob Modifier", storeAs: "bobModifierEnabled", tooltip: "Enable/disable setting the bob effect", bindLocation: tp.themingTab.pages[1], });
  1597. initFolder({ location: tp.themingTab.pages[0], title: "Bob Modifier Settings", storeAs: "bobFolder", });
  1598. initModule({ location: tp.bobFolder, title: "Bobbing Value", storeAs: "bobModifier", tooltip: "Set to 0 to disable. Mess with other numbers for funny effects.", slider: { min: 0, max: 99, step: 0.01 }, defaultValue: 0, });
  1599. initModule({ location: tp.bobFolder, title: "Only When Still", storeAs: "bobModifierWhenStill", tooltip: "Disables while you're still.", bindLocation: tp.themingTab.pages[1], });
  1600. tp.themingTab.pages[0].addSeparator();
  1601. initFolder({ location: tp.themingTab.pages[0], title: "Audio Settings", storeAs: "audioFolder", });
  1602. initModule({ location: tp.audioFolder, title: "Mute Game", storeAs: "muteGame", tooltip: "Mute the game?", bindLocation: tp.themingTab.pages[1], });
  1603. initModule({ location: tp.audioFolder, title: "DistanMult", storeAs: "distanceMult", tooltip: "Makes the distance when playing sfx change", slider: { min: 0.01, max: 2, step: 0.01 }, defaultValue: 1, });
  1604. tp.audioFolder.addSeparator();
  1605. initModule({ location: tp.audioFolder, title: "CustomSFX (1st)", storeAs: "customSFX1", tooltip: "Select a custom sound pack. Changes in-game sounds. Three pack slots available at once", bindLocation: tp.themingTab.pages[1], enableConditions: [["muteGame", false]], dropdown: JSON.parse(JSON.stringify(retrievedSFX)), });
  1606. initModule({ location: tp.audioFolder, title: "CustomSFX (2nd)", storeAs: "customSFX2", tooltip: "Select a custom sound pack. Changes in-game sounds. Three pack slots available at once", bindLocation: tp.themingTab.pages[1], enableConditions: [["muteGame", false]], dropdown: JSON.parse(JSON.stringify(retrievedSFX)), });
  1607. initModule({ location: tp.audioFolder, title: "CustomSFX (3rd)", storeAs: "customSFX3", tooltip: "Select a custom sound pack. Changes in-game sounds. Three pack slots available at once", bindLocation: tp.themingTab.pages[1], enableConditions: [["muteGame", false]], dropdown: JSON.parse(JSON.stringify(retrievedSFX)), });
  1608. tp.themingTab.pages[0].addSeparator();
  1609. initModule({ location: tp.themingTab.pages[0], title: "Replace Logo", storeAs: "replaceLogo", tooltip: "Replaces shell shockers' BORING logo with the BEAUTIFUL StateFarm logo", bindLocation: tp.themingTab.pages[1], });
  1610. initModule({ location: tp.themingTab.pages[0], title: "Animate Title", storeAs: "titleAnimation", tooltip: "Makes the page title look cool", bindLocation: tp.themingTab.pages[1], });
  1611. initModule({ location: tp.themingTab.pages[0], title: "Client Theme", storeAs: "themeType", tooltip: "Controls the client's UI theme", bindLocation: tp.themingTab.pages[1], dropdown: [
  1612. {text: "Default", value: "defaultTheme"},
  1613. {text: "Iceberg", value: "icebergTheme"},
  1614. {text: "Jet Black", value: "jetblackTheme"},
  1615. {text: "Light", value: "lightTheme"},
  1616. {text: "Retro", value: "retroTheme"},
  1617. {text: "Translucent", value: "translucentTheme"},
  1618. {text: "StateFarmer", value: "statefarmerTheme"},
  1619. {text: "Blurple", value: "blurpleTheme"},
  1620. {text: "ShellFarm", value: "shellFarmTheme"},
  1621. ], defaultValue: "defaultTheme", changeFunction: function(value) {
  1622. applyTheme(value.value);
  1623. }});
  1624. tp.themingTab.pages[0].addSeparator();
  1625. initModule({ location: tp.themingTab.pages[0], title: "Enable Party Lights", storeAs: "partyLightsEnabled", tooltip: "🥳🥳 Let the party begin 🎉🎉", bindLocation: tp.themingTab.pages[1], });
  1626. initModule({ location: tp.themingTab.pages[0], title: "Party Lights Intensity", storeAs: "partyLightsIntensity", tooltip: "Intensity of the party 🥳", slider: { min: 0.01, max: 20, step: 0.01 }, defaultValue: 0.5, });
  1627. tp.themingTab.pages[0].addSeparator();
  1628. initModule({ location: tp.themingTab.pages[0], title: "World Flattening", storeAs: "worldFlattening", tooltip: "Make the world F-L-A-T", slider: { min: 0.05, max: 10, step: 0.05 }, defaultValue: 1, });
  1629. //ACCOUNT MODULES
  1630. initFolder({ location: tp.mainPanel, title: "Accounts", storeAs: "accountsFolder", });
  1631. initTabs({ location: tp.accountsFolder, storeAs: "accountsTab" }, [
  1632. {
  1633. title: "Basics", content:
  1634. `This is the accounts tab. Here you will find
  1635. options relating to managing your thousands of
  1636. shell accounts and options that will enable you
  1637. to alt like a pro.`},
  1638. {
  1639. title: "Login DB", content:
  1640. `The Login DB allows you to alt with ease. Put
  1641. simply, it is just a list of EmailPass combos.
  1642. It is simpler than AccountRecords, but one does
  1643. not replace the other. Login DB is stored
  1644. universally across all Shell proxies, and
  1645. has a queue system. Each time an account
  1646. from this list is logged into, it moves it
  1647. to the back of the list, allowing you to
  1648. have a steady stream of fresh accounts.
  1649.  
  1650. PRIVACY NOTE: This database will contain some
  1651. important information. All data is stored locally
  1652. and will never be requested by the StateFarm
  1653. development team, but can theoretically be stolen
  1654. via the use of other userscripts not authorised
  1655. by the StateFarm developers. This DB is not
  1656. exposed to the Shell Shockers game (unless you
  1657. have enabled debug mode).`},
  1658. {
  1659. title: "AccRecord", content:
  1660. `The AccountRecords database is similar, but
  1661. different to the Login DB. Whilst the Login DB
  1662. serves to allow you to quickly switch to a new
  1663. account, AccountRecords saves information
  1664. related to accounts you've logged into. It saves
  1665. info such as your egg count, items in your
  1666. inventory and the value of your inventory.
  1667. This feature is even more advanced than the
  1668. Login DB, and is only recommended for use by
  1669. people who really know what they're doing. If
  1670. you just like aimbotting, you really don't need
  1671. to worry about this.
  1672.  
  1673. FYI: This will attempt to save info about any
  1674. account, but will only perform best when you
  1675. are using an account that you logged into using
  1676. StateFarm's login or account creation modules.
  1677. Other accounts will have limited info, such as
  1678. masked emails and no EmailPass combos.
  1679.  
  1680. PRIVACY NOTE: This database will contain some
  1681. important information. You can disable the
  1682. logging of this info in the settings. All data
  1683. is stored locally and will never be requested
  1684. by the StateFarm development team, but can
  1685. theoretically be stolen via the use of other
  1686. userscripts not authorised by the StateFarm
  1687. developers. This DB is not exposed to the
  1688. Shell Shockers game (unless you have enabled
  1689. debug mode).`},
  1690. ]);
  1691. initFolder({ location: tp.accountsTab.pages[0], title: "Account Login (Basic)", storeAs: "loginFolder", });
  1692. initModule({ location: tp.loginFolder, title: 'Email:Pass', storeAs: 'loginEmailPass', tooltip: "Field for loginLogin", defaultValue: "ex@gmail.com:passwd" });
  1693. initModule({ location: tp.loginFolder, title: 'Login Account', storeAs: 'loginLogin', tooltip: "Log into an account using email:pass without using shell's UI", button: 'LOGIN', bindLocation: tp.accountsTab.pages[1], clickFunction: function () {
  1694. let emailPass = extract("loginEmailPass");
  1695. if (emailPass.includes(":")) {
  1696. loginOrCreateWithEmailPass(emailPass);
  1697. } else {
  1698. emailPass = prompt('Your email:pass isn\'t valid. Enter your combo below or input the correct one in the box.', '');
  1699. if (emailPass.includes(":")) {
  1700. loginOrCreateWithEmailPass(emailPass);
  1701. }; //else fuck you. im not doing anything with that.
  1702. };
  1703. } });
  1704. tp.accountsTab.pages[0].addSeparator();
  1705. initFolder({ location: tp.accountsTab.pages[0], title: "Account Login (Login Database)", storeAs: "loginDatabaseFolder", });
  1706. initModule({ location: tp.loginDatabaseFolder, title: 'Login Next Account', storeAs: 'loginDatabaseLogin', button: 'LOGIN', tooltip: "Tools for managing accounts in a Database", bindLocation: tp.accountsTab.pages[1], clickFunction: function () {
  1707. let loginDB = GM_getValue("StateFarm_LoginDB") || []; //why declare this so many times? the DBs need to be constantly rechecked, as other clients may have modified. we wouldnt want to be overwriting each other. (yes this needed to be said again)
  1708. let loginDBlength = loginDB.length;
  1709. if (loginDBlength > 0) {
  1710. let index = extract("loginDatabaseSelection") == "inorder" ? 0 : Math.ceil((Math.random()*0.75)*(loginDBlength-1));
  1711. log(`selecting index ${index}, this is out of ${loginDBlength} entries.`);
  1712. let [emailPass] = loginDB.splice(index, 1); //delete and retrieve
  1713. loginDB.push(emailPass);
  1714. log(`deleted and reinserted ${emailPass} at the end.`);
  1715. loginOrCreateWithEmailPass(emailPass);
  1716. GM_setValue("StateFarm_LoginDB", loginDB);
  1717. createPopup(`Logging in from index ${index}...`);
  1718. } else {
  1719. createPopup("LoginDB is empty!", "error");
  1720. };
  1721. } });
  1722. initModule({ location: tp.loginDatabaseFolder, title: "Selection Type", storeAs: "loginDatabaseSelection", tooltip: "Tools for managing accounts in a Database", bindLocation: tp.accountsTab.pages[1], dropdown: [{ text: "In Order", value: "inorder" }, { text: "Random", value: "random" }], defaultValue: "inorder" });
  1723. initModule({ location: tp.loginDatabaseFolder, title: "Auto Login", storeAs: "autoLogin", tooltip: "Tools for managing accounts in a Database", bindLocation: tp.accountsTab.pages[1], dropdown: [{ text: "Disabled", value: "disabled" }, { text: "When No Account", value: "noaccount" }, { text: "Always", value: "always" }], defaultValue: "disabled" });
  1724. tp.loginDatabaseFolder.addSeparator();
  1725. initModule({ location: tp.loginDatabaseFolder, title: 'Export DB(JSON)', storeAs: 'loginDatabaseExport', tooltip: "Tools for managing accounts in a Database", button: 'EXPORT (COPY)', bindLocation: tp.accountsTab.pages[1], clickFunction: function () {
  1726. GM_setClipboard(JSON.stringify(GM_getValue("StateFarm_LoginDB") || []), "text", () => log("Clipboard set!"));
  1727. createPopup("Login DB copied to clipboard...");
  1728. } });
  1729. initModule({ location: tp.loginDatabaseFolder, title: 'Import Into LoginDB', storeAs: 'loginDatabaseExport', tooltip: "Tools for managing accounts in a Database", button: 'APPEND (PASTE)', bindLocation: tp.accountsTab.pages[1], clickFunction: function () {
  1730. let userInput = prompt(`Input data you would like to add to your LoginDB. This will NOT replace your current data. All data added here will be put at the end of the queue. Also make sure that this data goes here and not into the AccountRecords DB.`, 'Reminder: JSON format!');
  1731. try {
  1732. let loginDB = GM_getValue("StateFarm_LoginDB") || []; //why declare this so many times? the DBs need to be constantly rechecked, as other clients may have modified. we wouldnt want to be overwriting each other. (yes this needed to be said again)
  1733. let appendedData = JSON.parse(userInput);
  1734. appendedData.forEach(data => {
  1735. if (data && !loginDB.includes(data)) loginDB.push(data);
  1736. });
  1737. GM_setValue("StateFarm_LoginDB", loginDB);
  1738. createPopup("Success! Data appended to LoginDB.", "success");
  1739. } catch {
  1740. createPopup("Failed! Check the formatting.", "error");
  1741. };
  1742. } });
  1743. initModule({ location: tp.loginDatabaseFolder, title: 'ImportFromRecords', storeAs: 'loginDatabaseImportRecords', tooltip: "Tools for managing accounts in a Database", button: 'APPEND', bindLocation: tp.accountsTab.pages[1], clickFunction: function () {
  1744. if (prompt("This action will import any Email:Pass combos you have in AccountRecords. Make sure you want to do this, as this will potentially add a lot of new records. Type 'ok' to proceed. This cannot be reversed, export first to be safe. Note: all the new records are added to the end of the queue.") === 'ok') {
  1745. let accountRecords = GM_getValue("StateFarm_AccountRecords") || {}; //why declare this so many times? the DBs need to be constantly rechecked, as other clients may have modified. we wouldnt want to be overwriting each other.
  1746. let loginDB = GM_getValue("StateFarm_LoginDB") || []; //why declare this so many times? the DBs need to be constantly rechecked, as other clients may have modified. we wouldnt want to be overwriting each other. (yes this needed to be said again)
  1747. Object.entries(accountRecords).forEach(([key, account]) => {
  1748. let emailPass = account.emailPass;
  1749. if (emailPass && !loginDB.includes(emailPass)) {
  1750. loginDB.push(emailPass);
  1751. };
  1752. });
  1753. GM_setValue("StateFarm_LoginDB", loginDB);
  1754. createPopup("Appended from AccountDetails!", "success");
  1755. };
  1756. } });
  1757. initModule({ location: tp.loginDatabaseFolder, title: 'Delete LoginDB', storeAs: 'loginDatabaseDelete', tooltip: "Tools for managing accounts in a Database", button: 'DELETE!', bindLocation: tp.accountsTab.pages[1], clickFunction: function () {
  1758. if (prompt("WARNING! This is a destructive action! Type 'ok' if you are really sure you want to delete your LoginDB! This cannot be reversed, export first to be safe.") === 'ok') {
  1759. GM_setValue("StateFarm_LoginDB", []); //o7 data
  1760. };
  1761. } });
  1762. initModule({ location: tp.loginDatabaseFolder, title: 'LoginDB Info', storeAs: 'loginDatabaseInfo', tooltip: "Tools for managing accounts in a Database", button: 'INFO', bindLocation: tp.accountsTab.pages[1], clickFunction: function () {
  1763. let loginDB = GM_getValue("StateFarm_LoginDB") || []; //why declare this so many times? the DBs need to be constantly rechecked, as other clients may have modified. we wouldnt want to be overwriting each other. (yes this needed to be said again)
  1764. alert(`You currently have ${loginDB.length} accounts in LoginDB. For info on what this is, check the guide tab.`);
  1765. } });
  1766. tp.accountsTab.pages[0].addSeparator();
  1767. initFolder({ location: tp.accountsTab.pages[0], title: "Account Generator (Basic)", storeAs: "generatorFolder", });
  1768. initModule({ location: tp.generatorFolder, title: 'Gmail (before @)', storeAs: 'accountGmail', tooltip: "The gmail prefix", defaultValue: "example (NO @gmail.com)" });
  1769. initModule({ location: tp.generatorFolder, title: 'Password to use', storeAs: 'accountPass', tooltip: "The account's password", defaultValue: "password69" });
  1770. initModule({ location: tp.generatorFolder, title: 'Create (Basic)', storeAs: 'accountCreate', tooltip: "Basic Gmail account creation", button: 'CREATE', bindLocation: tp.accountsTab.pages[1], clickFunction: function () {
  1771. loginOrCreateWithEmailPass(extract("accountGmail")+"+"+getScrambled()+"@gmail.com:"+extract("accountPass"));
  1772. } });
  1773. tp.accountsTab.pages[0].addSeparator();
  1774. initFolder({ location: tp.accountsTab.pages[0], title: "Account Records Database", storeAs: "accountRecordsFolder", });
  1775. initModule({ location: tp.accountRecordsFolder, title: "Disable Logging", storeAs: "accountRecordsLogging", tooltip: "Account Records Database options. Only needed when dealing with a lot of accounts", bindLocation: tp.accountsTab.pages[1], });
  1776. initModule({ location: tp.accountRecordsFolder, title: 'Export DB (JSON)', storeAs: 'accountRecordsExport', tooltip: "Account Records Database options. Only needed when dealing with a lot of accounts", button: 'EXPORT (COPY)', bindLocation: tp.accountsTab.pages[1], clickFunction: function () {
  1777. GM_setClipboard(JSON.stringify(GM_getValue("StateFarm_AccountRecords") || {}), "text", () => log("Clipboard set!"));
  1778. createPopup("AccountRecords DB copied to clipboard...");
  1779. } });
  1780. initModule({ location: tp.accountRecordsFolder, title: 'Import Into DB', storeAs: 'accountRecordsImport', tooltip: "Account Records Database options. Only needed when dealing with a lot of accounts", button: 'APPEND (PASTE)', bindLocation: tp.accountsTab.pages[1], clickFunction: function () {
  1781. let userInput = prompt(`Input data you would like to add to your AccountRecords DB. This will NOT replace your current data. All data added here either be added or replace existing records. Also make sure that this data goes here and not into the LoginDB.`, 'Reminder: JSON format!');
  1782. try {
  1783. let accountRecords = GM_getValue("StateFarm_AccountRecords") || {}; //why declare this so many times? the DBs need to be constantly rechecked, as other clients may have modified. we wouldnt want to be overwriting each other.
  1784. let appendedData = JSON.parse(userInput);
  1785. Object.entries(appendedData).forEach(([key, account]) => {
  1786. if (account) accountRecords[key] = account;
  1787. });
  1788. GM_setValue("StateFarm_AccountRecords", accountRecords);
  1789. createPopup("Success! Data appended to AccountRecords.", "success");
  1790. } catch {
  1791. createPopup("Failed! Check the formatting.", "error");
  1792. };
  1793. } });
  1794. initModule({ location: tp.accountRecordsFolder, title: 'Delete DB', storeAs: 'accountRecordsDelete', tooltip: "Account Records Database options. Only needed when dealing with a lot of accounts", button: 'DELETE!', bindLocation: tp.accountsTab.pages[1], clickFunction: function () {
  1795. if (prompt("WARNING! This is a destructive action! Type 'ok' if you are really sure you want to delete your AccountRecords DB! This cannot be reversed, export first to be safe.") === 'ok') {
  1796. GM_setValue("StateFarm_AccountRecords", {}); //o7 data
  1797. };
  1798. } });
  1799. initModule({ location: tp.accountRecordsFolder, title: 'View Info', storeAs: 'accountRecordsInfo', tooltip: "Account Records Database options. Only needed when dealing with a lot of accounts", button: 'INFO', bindLocation: tp.accountsTab.pages[1], clickFunction: function () {
  1800. let userInput = prompt(`This will output some information relating to what information you have in your AccountRecords DB.\nParameters: Enter 1 to only print Email:Pass list of those with items, enter 2 for those with no items.`, '');
  1801. let accountRecords = GM_getValue("StateFarm_AccountRecords") || {}; //why declare this so many times? the DBs need to be constantly rechecked, as other clients may have modified. we wouldnt want to be overwriting each other.
  1802. let tierCache = GM_getValue("StateFarm_TierCache") || {};
  1803. const itemCounts = {};
  1804. const tierCounts = {};
  1805. let emailPassList = [];
  1806. let accountCount = 0;
  1807. let accountWithItemsCount = 0;
  1808. let itemCountTotal = 0;
  1809. Object.entries(accountRecords).forEach(([key, account]) => {
  1810. if (account) {
  1811. let countedAccount = false; accountCount++;
  1812. let inventoryList=[];
  1813. account.inventory.forEach(item=>{inventoryList.push(item.name)});
  1814. if (inventoryList) {
  1815. for (let item of inventoryList) {
  1816. if (!countedAccount) {countedAccount = true; accountWithItemsCount++};
  1817. if (tierCache[item]) {
  1818. item = `${item} [T${tierCache[item]}]`;
  1819. };
  1820. let tier = item.match(/\[T([0-9])\]/);
  1821. if (tier && tier[1]) {
  1822. if (tierCounts.hasOwnProperty(tier[1])) {
  1823. tierCounts[tier[1]]++;
  1824. } else {
  1825. tierCounts[tier[1]] = 1;
  1826. };
  1827. };
  1828. itemCountTotal++;
  1829. if (itemCounts.hasOwnProperty(item)) {
  1830. itemCounts[item]++;
  1831. } else {
  1832. itemCounts[item] = 1;
  1833. };
  1834. };
  1835. if (account.emailPass && !emailPassList.includes(account.emailPass)) {
  1836. if ((userInput == "1" && inventoryList.length > 0) || // with items
  1837. (userInput == "2" && inventoryList.length < 1) || // no items
  1838. (userInput !== "1" && userInput !== "2")) { // do them all
  1839. emailPassList.push(account.emailPass);
  1840. };
  1841. };
  1842. };
  1843. };
  1844. });
  1845. log('%c' + ' '.repeat(500), 'background: white; color: white; font-size: 50px;');
  1846. log('%cAccountRecords Info', 'color: red; font-size: 30px;');
  1847. log("Full AccountRecords:");
  1848. log(accountRecords);
  1849. log(`itemCounts (Total items: ${itemCountTotal}):`);
  1850. log(itemCounts);
  1851. log(`tierCounts:`);
  1852. log(tierCounts);
  1853. log(`tierCache:`);
  1854. log(tierCache);
  1855. log(`emailPassList (Count: ${emailPassList.length}):`);
  1856. log(JSON.stringify(emailPassList));
  1857. log('%c' + ' '.repeat(500), 'background: white; color: white; font-size: 50px;');
  1858. alert(`Results:\nAccounts Total: ${accountCount}; With Items: ${accountWithItemsCount}\nItem Count: ${itemCountTotal}\nOther info has been pasted into console.`);
  1859. } });
  1860. tp.accountsTab.pages[0].addSeparator();
  1861. initFolder({ location: tp.accountsTab.pages[0], title: "Account Generator (Factory)", storeAs: "factoryFolder", });
  1862. initModule({ location: tp.factoryFolder, title: 'Factory Key', storeAs: 'factoryKey', tooltip: "Factory access token (for the lucky few)", defaultValue: "" });
  1863. initModule({ location: tp.factoryFolder, title: 'Factory Gen', storeAs: 'factoryGen', tooltip: "Get an account from the Factory database", button: 'Generate!', clickFunction: () => F.register(), bindLocation: tp.accountsTab.pages[1] });
  1864. tp.accountsTab.pages[0].addSeparator();
  1865. //MISC MODULES
  1866. initFolder({ location: tp.mainPanel, title: "Misc", storeAs: "miscFolder", });
  1867. initTabs({ location: tp.miscFolder, storeAs: "miscTab" }, [
  1868. {
  1869. title: "WIP", content:
  1870. `Sorry! No guide yet!`},
  1871. ]);
  1872. //move this stuff to top bc its more important
  1873. initFolder({ location: tp.miscTab.pages[0], title: "Ban Evasion Options", storeAs: "banFolder", });
  1874. initModule({ location: tp.banFolder, title: "Unban", storeAs: "unban", tooltip: "Unbans you by signing out. You will lose skins if you're not signed in.", bindLocation: tp.miscTab.pages[1], button: "UNBAN NOW", clickFunction: function(){
  1875. if (GM_getValue('StateFarm_Unbanned')) unban();
  1876. else if (prompt("By proceeding, you will be signed out. If you don't have an account, your stats will be lost.\nEnter 'ok' to confirm this.\nThis popup will not be shown again for future unbans.") === 'ok') {
  1877. GM_setValue('StateFarm_Unbanned', 'true');
  1878. unban();
  1879. } else {
  1880. alert('You did not entire "ok", so the unban was cancelled.');
  1881. };
  1882. },});
  1883. initModule({ location: tp.banFolder, title: "Auto Unban", storeAs: "autoUnban", tooltip: "Automatically detects bans & unbans in above fashion", bindLocation: tp.miscTab.pages[1],});
  1884. initModule({ location: tp.banFolder, title: "New Proxy", storeAs: "newProxy", tooltip: "Switches to a new shell shockers link. SF config won't be transferred", bindLocation: tp.miscTab.pages[1], button: "NEW PROXY", clickFunction: function(){
  1885. const userConfirmed=confirm("Switching to a proxy URL. By proceeding, you will enter another URL for Shell Shockers but your data doesn't get transferred.");
  1886. if (userConfirmed) {
  1887. newProxy();
  1888. };
  1889. },});
  1890. initModule({ location: tp.banFolder, title: "Reload Page", storeAs: "reload", tooltip: "Reloads the page", bindLocation: tp.miscTab.pages[1], button: "RELOAD NOW", clickFunction: function(){
  1891. reloadPage();
  1892. },});
  1893. tp.miscTab.pages[0].addSeparator();
  1894. initModule({ location: tp.miscTab.pages[0], title: "AntiAFK", storeAs: "antiAFK", tooltip: "Bypasses AFK kicks", bindLocation: tp.miscTab.pages[1], });
  1895. initModule({ location: tp.miscTab.pages[0], title: "Quick Respawn", storeAs: "quickRespawn", tooltip: "Respawns quicker than usual", bindLocation: tp.miscTab.pages[1], });
  1896. initModule({ location: tp.miscTab.pages[0], title: "Sneaky Despawn", storeAs: "sneakyDespawn", tooltip: "Despawns, similar to the Esc key, but you can move while despawning, not that you cannot deal damage while sneaky despawning", bindLocation: tp.miscTab.pages[1], button: "Despawn... soon!", defaultBind: "Backquote", clickFunction: function(){
  1897. if (!(unsafeWindow.extern.gamePaused || sneakyDespawning)) {
  1898. sneakyDespawning = true;
  1899. ss.PAUSE(); createPopup("SneakyDespawn: 3 seconds.");
  1900. setTimeout(() => { createPopup("SneakyDespawn: 2 seconds.");
  1901. }, 1e3);
  1902. setTimeout(() => { createPopup("SneakyDespawn: 1 second.");
  1903. }, 2e3);
  1904. setTimeout(() => { createPopup("SneakyDespawn: Now despawning!");
  1905. document.exitPointerLock(); document.onpointerlockchange();
  1906. setTimeout(() => {
  1907. sneakyDespawning = false;
  1908. }, 200);
  1909. }, 3e3);
  1910. };
  1911. },});
  1912. initModule({ location: tp.miscTab.pages[0], title: "InstantSpectate", storeAs: "instantSpectate", tooltip: "Don't wait around for the spectate button to appear", bindLocation: tp.miscTab.pages[1], });
  1913. tp.miscTab.pages[0].addSeparator();
  1914. initFolder({ location: tp.miscTab.pages[0], title: "StateFarm UI Options", storeAs: "sfcUIFolder", });
  1915. initModule({ location: tp.sfcUIFolder, title: "StateFarm Updates", storeAs: "statefarmUpdates", tooltip: "Shows a element at the home screen about statefarm's update history, notifies you when update is available", bindLocation: tp.miscTab.pages[1], defaultValue: true, });
  1916. initModule({ location: tp.sfcUIFolder, title: "Replace Feeds", storeAs: "replaceFeeds", tooltip: "Replaces the game menu's news and videos feed with content by the StateFarm dev team", bindLocation: tp.miscTab.pages[1], defaultValue: true, });
  1917. initModule({ location: tp.sfcUIFolder, title: "Custom Badges", storeAs: "customBadges", tooltip: "Enables custom StateFarm badges", bindLocation: tp.miscTab.pages[1], defaultValue: true, });
  1918. tp.miscTab.pages[0].addSeparator();
  1919. initModule({ location: tp.miscTab.pages[0], title: "Unlock Skins (View Only)", storeAs: "unlockSkins", tooltip: "Unlocks all skins in locally (other players will not see these)", bindLocation: tp.miscTab.pages[1], });
  1920. initModule({ location: tp.miscTab.pages[0], title: "Unlock Bros Grenade", storeAs: "brosGrenade", tooltip: "Unlocks the real bros grenade skin to your account", bindLocation: tp.miscTab.pages[1], button: "Unlock, real.", clickFunction: function(){
  1921. unsafeWindow.extern.giveBasketBrosReward();
  1922. },});
  1923. initModule({ location: tp.miscTab.pages[0], title: "Admin Spoof", storeAs: "adminSpoof", tooltip: "Shows admin options such as BOOT and BAN in games. No ACTUAL functionality", bindLocation: tp.miscTab.pages[1], });
  1924. tp.miscTab.pages[0].addSeparator();
  1925. initModule({ location: tp.miscTab.pages[0], title: "Switch Focus", storeAs: "unfocus", tooltip: "Controls the focus of the game. Allows for tabbing out without despawning", bindLocation: tp.miscTab.pages[1], button: "FOCUS/UNFOCUS", defaultBind: "P", clickFunction: function(){
  1926. if (document.pointerLockElement !== null) { //currently locked
  1927. noPointerPause=true; unsafeWindow.document.exitPointerLock();
  1928. } else if (noPointerPause) { //already unlocked?
  1929. noPointerPause=false;
  1930. unsafeWindow.canvas.requestPointerLock();
  1931. };
  1932. },});
  1933. tp.miscTab.pages[0].addSeparator();
  1934. initFolder({ location: tp.miscTab.pages[0], title: "Chicken Winner Options", storeAs: "chwFolder", });
  1935. initModule({ location: tp.chwFolder, title: "FastChickenWinner", storeAs: "chickenWinner", tooltip: "Instantly plays the chick'n winner minigame", bindLocation: tp.miscTab.pages[1], button: "Force Play", clickFunction: function(){
  1936. unsafeWindow.extern.chwTryPlay();
  1937. const eggElement = document.getElementById("eggOne");
  1938. eggElement.click();eggElement.click();eggElement.click();eggElement.click();eggElement.click();eggElement.click();eggElement.click();eggElement.click();eggElement.click();
  1939. let chicknWinnerElementLoaded = false;
  1940. const checkInterval = setInterval(() => {
  1941. const chicknWinnerElement = document.getElementById('chicknWinner');
  1942. chicknWinnerElementLoaded = (chicknWinnerElement?.style?.display == ''); //idk, this is kind of shit? but who actually cares that much...
  1943. if (chicknWinnerElementLoaded) {
  1944. const gotWinnerOkElement = document.getElementById('gotWinnerOk');
  1945. if (gotWinnerOkElement) {
  1946. gotWinnerOkElement.click();
  1947. };
  1948. if (chicknWinnerElement.style.display == 'none') {
  1949. log("ermm, found");
  1950. clearInterval(checkInterval);
  1951. updateAccountRecords();
  1952. accountStatus = "chwDone";
  1953. };
  1954. };
  1955. }, 100);
  1956. },});
  1957. initModule({ location: tp.chwFolder, title: "AutoChickenWinner", storeAs: "autoChickenWinner", tooltip: "Automatically plays the chick'n winner minigame when cooldowns are over", bindLocation: tp.miscTab.pages[1],});
  1958. initModule({ location: tp.chwFolder, title: "Chw Info Notifications", storeAs: "chickenWinnerNotifs", tooltip: "Alerts you of the tier of what you just earned and other infos.", bindLocation: tp.miscTab.pages[1],});
  1959. tp.miscTab.pages[0].addSeparator();
  1960. initModule({ location: tp.miscTab.pages[0], title: "Get Game History", storeAs: "getGameHistory", tooltip: "Displays a list of the last few lobbies you were in", bindLocation: tp.miscTab.pages[1], button: "get", clickFunction: function(){
  1961. let games = GM_getValue("StateFarm_GameHistory");
  1962. //alert(GM_getValue("StateFarm_GameHistory"));
  1963. if(!games) {
  1964. alert("no history!");
  1965. return;
  1966. }
  1967. games = JSON.parse(games);
  1968. let gString = "";
  1969. games.forEach(g => {
  1970. gString+= g.code;
  1971. if(g.amount>1) gString += ` (${g.amount})`;
  1972. gString+= ": ";
  1973. gString+= g.string; //omggggg
  1974.  
  1975. gString+= ` (left at ${new Date(g.time).toLocaleString()} via ${g.closeCode} ${g.message})`
  1976.  
  1977. gString += "\n";
  1978. });
  1979. console.log(gString); //debated using log(), but this is a direct user input so yhhhhhhhh
  1980. gString+="\na copy of this list has been dumped into the console, if you wish to copy a code.";
  1981. alert(gString);
  1982. },});
  1983. initModule({ location: tp.miscTab.pages[0], title: "Clear Game History", storeAs: "clearGameHistory", tooltip: "Clear your stored game history", bindLocation: tp.miscTab.pages[1], button: "clear", clickFunction: function(){
  1984. if(!GM_getValue("StateFarm_GameHistory")) return;
  1985. log("deleting game history: " + GM_getValue("StateFarm_GameHistory"));
  1986. GM_deleteValue("StateFarm_GameHistory");
  1987. createPopup("game history deleted!");
  1988. },});
  1989. initModule({ location: tp.miscTab.pages[0], title: "Custom Macro", storeAs: "customMacro", tooltip: "The JavaScript macro executed via executeMacro", defaultValue: "log('cool');" });
  1990. initModule({ location: tp.miscTab.pages[0], title: "Execute Macro", storeAs: "executeMacro", tooltip: "Allows for JS code to be executed from the client itself. Runs in userscript environment, so use unsafeWindow etc.", bindLocation: tp.miscTab.pages[1], button: "EXECUTE", clickFunction: function(){
  1991. //use at your own risk, i guess. but is this really any more dangerous than pasting something into console? not really.
  1992. (async () => {
  1993. try {
  1994. log(extract("customMacro"));
  1995. // stay safe out there. this runs in the **userscript** environment. make sure to use unsafeWindow for whatever reason you may need the window object.
  1996. await eval(extract("customMacro")); // eslint-disable-line
  1997. } catch (error) {
  1998. console.error("Error executing code:", error);
  1999. }
  2000. })();
  2001. },}); //but yes, as you can see "macros" are just scripts you can execute for whatever purposes you need. reminds me of userscripts...
  2002. initModule({ location: tp.miscTab.pages[0], title: "Do At Startup", storeAs: "autoMacro", tooltip: "Executes the entered macro at client startup", bindLocation: tp.miscTab.pages[1],});
  2003. tp.miscTab.pages[0].addSeparator();
  2004. initModule({ location: tp.miscTab.pages[0], title: "[WIP]RandomPath", storeAs: "randomPath", tooltip: "Forces a new random path (pathfinding currently disabled)", bindLocation: tp.miscTab.pages[1], button: "Random Path", clickFunction: function(){
  2005. findNewPath = true;
  2006. },});
  2007. findNewPath = false;
  2008. tp.miscTab.pages[0].addSeparator();
  2009. initModule({ location: tp.miscTab.pages[0], title: "SilentRoll", storeAs: "silentRoll", tooltip: "Rolls around without showing it client sided", bindLocation: tp.miscTab.pages[1], });
  2010. initFolder({ location: tp.miscTab.pages[0], title: "Seizure Options", storeAs: "seizureFolder", });
  2011. initModule({ location: tp.seizureFolder, title: "SeizureX", storeAs: "enableSeizureX", tooltip: "Rotates the player by the specified amount around the y-axis (yaw)", bindLocation: tp.miscTab.pages[1], });
  2012. initModule({ location: tp.seizureFolder, title: "X Amount", storeAs: "amountSeizureX", tooltip: "Amount to roll", slider: { min: -6.283185307179586, max: 6.283185307179586, step: Math.PI / 280 }, defaultValue: 2, });
  2013. initModule({ location: tp.seizureFolder, title: "SeizureY", storeAs: "enableSeizureY", tooltip: "Rotates the player by the specified amount around the x-axis (pitch)", bindLocation: tp.miscTab.pages[1], });
  2014. initModule({ location: tp.seizureFolder, title: "Y Amount", storeAs: "amountSeizureY", tooltip: "Amount to roll", slider: { min: -6.283185307179586, max: 6.283185307179586, step: Math.PI / 280 }, defaultValue: 2, });
  2015. };
  2016. //CLIENT MODULES
  2017. initFolder({ location: tp.mainPanel, title: "Client & About", storeAs: "clientFolder", });
  2018. initTabs({ location: tp.clientFolder, storeAs: "clientTab" }, [
  2019. {
  2020. title: "WIP", content:
  2021. `Sorry! No guide yet!`},
  2022. ]);
  2023. initModule({ location: tp.clientTab.pages[0], title: "VarData Fallback", storeAs: "vardataFallback", tooltip: "What to try if varData loading fails", bindLocation: tp.clientTab.pages[1], dropdown: [{ text: "None", value: "none" }, { text: "Load Latest (online)", value: "loadLatest" }, { text: "Load Cached (current hash)", value: "loadCached" }, { text: "Load Cached (latest cache)", value: "loadRecent" }, { text: "Custom String", value: "loadCustom" }], defaultValue: "loadLatest", });
  2024. initModule({ location: tp.clientTab.pages[0], title: "Fallback Behavior", storeAs: "vardataType", tooltip: "When to use fallback", bindLocation: tp.clientTab.pages[1], dropdown: [{ text: "Never", value: "never" }, { text: "Just This Once", value: "justOnce" }, { text: "Until Next Hash", value: "nextHash" }, { text: "Always", value: "always" }], defaultValue: "always", });
  2025. initModule({ location: tp.clientTab.pages[0], title: "Custom VarData", storeAs: "vardataCustom", tooltip: "Uses the entered varData", defaultValue: "{}", enableConditions: [["vardataFallback", "loadCustom"]] });
  2026. tp.clientTab.pages[0].addSeparator();
  2027. initModule({ location: tp.clientTab.pages[0], title: "Hide GUI", storeAs: "hide", tooltip: "Hides the big StateFarm menu. default key to do this is H", bindLocation: tp.clientTab.pages[1], button: "Hide!", clickFunction: function () { tp.mainPanel.hidden = !tp.mainPanel.hidden }, defaultBind: "H", });
  2028. initModule({ location: tp.clientTab.pages[0], title: "Hide at Startup", storeAs: "hideAtStartup", tooltip: "Hides the StateFarm menu by default", bindLocation: tp.clientTab.pages[1], defaultValue: false,});
  2029. initModule({ location: tp.clientTab.pages[0], title: "No Console Logs", storeAs: "consoleLogs", tooltip: "Blocks the client frome sending messages to the browser console", bindLocation: tp.clientTab.pages[1], defaultValue: false,});
  2030. initModule({ location: tp.clientTab.pages[0], title: "Pop-ups", storeAs: "popups", tooltip: "Disables/enables bottom-left corner popups of configs changed & notifications", bindLocation: tp.clientTab.pages[1], defaultValue: true, });
  2031. initModule({ location: tp.clientTab.pages[0], title: "Tooltips", storeAs: "tooltips", tooltip: "Controls whether you want to see tooltips (the box displaying this very message!) (I'm just an innocent tooltip! I did nothing! Let me live! Don't disable me :( )", bindLocation: tp.clientTab.pages[1], defaultValue: true, });
  2032. tp.clientTab.pages[0].addSeparator();
  2033. initModule({ location: tp.clientTab.pages[0], title: "Panic", storeAs: "panic", tooltip: "Allows you to quickly exit to a set URL. great for hacking in class", bindLocation: tp.clientTab.pages[1], button: "EXIT!", clickFunction: function () { if (extract("enablePanic")) { unsafeWindow.location.replace(extract("panicURL")) } }, defaultBind: "X", enableConditions: [["enablePanic", true]], });
  2034. initFolder({ location: tp.clientTab.pages[0], title: "Panic Options", storeAs: "panicFolder", });
  2035. initModule({ location: tp.panicFolder, title: "Enable", storeAs: "enablePanic", tooltip: "Enable evacuation", bindLocation: tp.clientTab.pages[1], defaultValue: false, });
  2036. initModule({ location: tp.panicFolder, title: "Set URL", storeAs: "panicURL", tooltip: "What url to evacuate to", defaultValue: "https://classroom.google.com/", enableConditions: [["enablePanic", true]], });
  2037. tp.clientTab.pages[0].addSeparator();
  2038. let presetList = [];
  2039. Object.entries(inbuiltPresets).forEach(([key, value]) => {//Get all presets from inbuilt presets var
  2040. let options = {};
  2041. options.text = key;//not the best way to add things to a dictionary, but the only way i could get to work
  2042. options.value = key; // idiot could've not violated eslint smfh
  2043. presetList.push(options);
  2044. });
  2045. //PRESETS: OakSwingZZZ 😎
  2046. initFolder({ location: tp.clientTab.pages[0], title: "Presets", storeAs: "presetFolder",});
  2047. initModule({ location: tp.presetFolder, title: "Preset List", storeAs: "selectedPreset", tooltip: "A set of predefined configs made by the StateFarm developers", defaultValue: "onlypuppy7's Config", bindLocation: tp.clientTab.pages[1], dropdown: presetList, });
  2048. initModule({ location: tp.presetFolder, title: "Apply", storeAs: "applyPreset", tooltip: "Apply the preset selected in the comboBox above", button: "Apply Preset", clickFunction: function () {
  2049. const userConfirmed = confirm( "Are you sure you want to continue? This will replace most of your current config." );
  2050. if (userConfirmed) { applySettings(inbuiltPresets[extract("selectedPreset")], true); };
  2051. },
  2052. });
  2053. tp.presetFolder.addSeparator();
  2054. initModule({ location: tp.presetFolder, title: "Save", storeAs: "savePreset", tooltip: "Saves your current settings as a preset", button: "Save As Preset", clickFunction: function () {
  2055. // log("Config Main: ", configMain);
  2056. let saveString = '';
  2057. const addParam = function(module,setTo) {saveString=saveString+module+">"+JSON.stringify(setTo)+"<"};
  2058. Object.entries(configMain).forEach(([key, value]) => {
  2059. log(key, value);
  2060. if (typeof(value) == 'string') {
  2061. try {
  2062. let dropdown = extractAsDropdownInt(key)
  2063. value = dropdown;
  2064. } catch (error) {
  2065. //dont care lmaoooo
  2066. };
  2067. };
  2068. if (!presetIgnore.includes(key)){
  2069. addParam(key, value);
  2070. }
  2071. });
  2072. saveString = saveString.substring(0, saveString.length - 1);
  2073. let presetName = prompt("Name of preset:"); // asks user for name of preset
  2074. if (presetName == "" || presetName == null) {
  2075. log("User cancelled save");
  2076. } else {
  2077. let result = saveUserPreset(presetName, saveString);//saves user preset
  2078. addUserPresets(loadUserPresets()); //updates inbuiltPresets to include
  2079. log("Saved Preset: ", saveString);
  2080. log("User Preset Result: ", result);
  2081. };
  2082. log("InbuiltPrests:");
  2083. log(inbuiltPresets);
  2084. initMenu(false); //Reloads menu to add to dropdown list
  2085. },});
  2086. initModule({ location: tp.presetFolder, title: "Delete", storeAs: "deletePreset", tooltip: "Deletes a preset", button: "Remove Preset", clickFunction: function () { // Function won't do anything if they select a preset that was loaded in the gamecode
  2087. let currUserPresets = loadUserPresets(); //gets current presets from storage
  2088. delete currUserPresets[extract("selectedPreset")];//deletes
  2089. delete inbuiltPresets[extract("selectedPreset")];//deletes
  2090. save(presetStorageLocation, currUserPresets); // saves cnages to file.
  2091. log("Current User Presets: ",currUserPresets);
  2092. initMenu(false); //reloads menu
  2093. },});
  2094. tp.presetFolder.addSeparator();
  2095. initModule({ location: tp.presetFolder, title: "Import", storeAs: "importPreset", tooltip: "Imports a custom preset", button: "Import Preset", clickFunction: function () {
  2096. let preset = prompt("Paste preset here:"); // asks user to paste preset
  2097. if (preset == "" || preset == null) {
  2098. log("User cancelled save");
  2099. } else {
  2100. const pattern = /([a-zA-Z]*>[^<]*<)+[a-zA-Z]*>[^<]*/;
  2101. if (pattern.test(preset)){
  2102. let presetName = prompt("Name of preset:"); // asks user for name of preset
  2103. if (presetName == "" || presetName == null) {
  2104. log("User cancelled save");
  2105. } else {
  2106. let result = saveUserPreset(presetName, preset);//saves user preset
  2107. addUserPresets(loadUserPresets()); //updates inbuiltPresets to include
  2108. log("Saved Preset: ", preset);
  2109. log("User Preset Result: ", result);
  2110. }
  2111. } else {
  2112. alert("Not A Valid Preset!");
  2113. log("Preset Not Valid");
  2114. };
  2115. initMenu(false);
  2116. };
  2117. },});
  2118. initModule({ location: tp.presetFolder, title: "Export", storeAs: "exportPreset", tooltip: "Copies your current preset to the clipboard", button: "Copy To Clipboard", clickFunction: function () {
  2119. let saveString = '';
  2120. const addParam = function(module,setTo) {saveString=saveString+module+">"+JSON.stringify(setTo)+"<"};
  2121. Object.entries(configMain).forEach(([key, value]) => {
  2122. log(key, value);
  2123. if (typeof(value) == 'string') {
  2124. try {
  2125. let dropdown = extractAsDropdownInt(key)
  2126. value = dropdown;
  2127. } catch (error) {
  2128. //dont care lmaoooo
  2129. };
  2130. };
  2131. if (!presetIgnore.includes(key)){
  2132. addParam(key, value);
  2133. }
  2134. });
  2135. saveString = saveString.substring(0, saveString.length - 1);
  2136. GM_setClipboard(saveString, "text", () => log("Clipboard set!"));
  2137. createPopup("Preset copied to clipboard...");
  2138. },});
  2139. tp.clientTab.pages[0].addSeparator();
  2140. initFolder({ location: tp.clientTab.pages[0], title: "Creator's Links", storeAs: "linksFolder",});
  2141. initModule({ location: tp.linksFolder, title: "Discord", storeAs: "discord", tooltip: "The official StateFarm Client Discord server", button: "Link", clickFunction: () => GM_openInTab(discordURL, { active: true }) });
  2142. initModule({ location: tp.linksFolder, title: "GitHub", storeAs: "github", tooltip: "The official StateFarm Client GitHub Repository! Check out the devs suffering here", button: "Link", clickFunction: () => GM_openInTab(githubURL, { active: true }) });
  2143. tp.clientTab.pages[0].addSeparator();
  2144. initModule({ location: tp.clientTab.pages[0], title: "Reset", storeAs: "clear", tooltip: "Powerwashes StateFarm completely", button: "DELETE", clickFunction: function(){
  2145. const userConfirmed=confirm("Are you sure you want to continue? This will clear all stored module states and keybinds.");
  2146. if (userConfirmed) {
  2147. initMenu(true);
  2148. alert("Reset to defaults.");
  2149. };
  2150. },});
  2151. tp.clientTab.pages[0].addSeparator();
  2152. initFolder({ location: tp.clientTab.pages[0], title: "Developer Options", storeAs: "devFolder",});
  2153. initModule({ location: tp.devFolder, title: "Debug", storeAs: "debug", tooltip: "Converts SFC into a development tool.\nExposes globalSS to the window (allowing you to manipulate many game variables directly) and also enables some extra logs.", bindLocation: tp.clientTab.pages[1], });
  2154. initModule({ location: tp.devFolder, title: "Force Import", storeAs: "forceImport", tooltip: "Forces importing of Babylon instead of making fake babylon. Use only for testing or if fake babylon doesn't work.", bindLocation: tp.clientTab.pages[1], });
  2155. tp.mainPanel.addSeparator();
  2156. initModule({ location: tp.mainPanel, title: "Update", storeAs: "update", tooltip: "Go to the client's update page", button: "Link", clickFunction: () => GM_openInTab(downloadURL, { active: true }) });
  2157. initModule({ location: tp.mainPanel, title: "Guide", storeAs: "documentation", tooltip: "A guide with more in-depth information on modules", button: "Link", clickFunction: () => GM_openInTab(featuresGuideURL, { active: true }) });
  2158.  
  2159.  
  2160. tp.botPanel = new Tweakpane.Pane(); // eslint-disable-line
  2161. tp.botPanel.title = "StateFarm Bot Control Panel";
  2162. tp.botPanel.containerElem_.style.left = "15%";
  2163. tp.botPanel.containerElem_.style.top = "25%";
  2164. tp.botPanel.hidden = true;
  2165.  
  2166. tp.botTabs = tp.botPanel.addTab({
  2167. pages: [
  2168. { title: 'Deploy' },
  2169. { title: 'Manage' },
  2170. { title: 'Params' },
  2171. { title: 'Info' },
  2172. ],
  2173. });
  2174.  
  2175. //DEPLOY STUFF
  2176. initModule({ location: tp.botTabs.pages[0], title: "Bots Amount", storeAs: "numberBots", tooltip: "The number of bots/windows opened", slider: { min: 1, max: 18, step: 1 }, defaultValue: 1, });
  2177. initModule({ location: tp.botTabs.pages[0], title: "Deploy", storeAs: "deployBots", tooltip: "Open the bot's windows. If only one opens, make sure you have popups allowed", button: "START BOTS!", bindLocation: tp.bottingTab.pages[1], clickFunction: function () { deployBots() }, });
  2178. initModule({ location: tp.botTabs.pages[0], title: "Restart Bots", storeAs: "restartBots", tooltip: "Completely closes and restarts all bot instances", button: "RESTART BOTS", bindLocation: tp.bottingTab.pages[1], clickFunction: function () { broadcastToBots("kill"); setTimeout(function(){deployBots()}, 1000) }, });
  2179. tp.botTabs.pages[0].addSeparator();
  2180. initModule({ location: tp.botTabs.pages[0], title: "Window Width", storeAs: "botWindowWidth", tooltip: "Horizontal size of the bot's windows", slider: { min: 0, max: 10000, step: 1 }, defaultValue: 450, botParam: true, });
  2181. initModule({ location: tp.botTabs.pages[0], title: "Window Height", storeAs: "botWindowHeight", tooltip: "Vertical size of the bot's windows", slider: { min: 0, max: 10000, step: 1 }, defaultValue: 300, botParam: true, });
  2182. tp.botTabs.pages[0].addSeparator();
  2183. initModule({ location: tp.botTabs.pages[0], title: "Use Names", storeAs: "useCustomNameBots", tooltip: "Use special customized names", defaultValue: true, botParam: true, });
  2184. initModule({ location: tp.botTabs.pages[0], title: "Bot Name", storeAs: "botUsername", tooltip: "The names used by the bots", defaultValue: "ЅtateFarmer", enableConditions: [["useCustomNameBots", true]], });
  2185. initModule({ location: tp.botTabs.pages[0], title: "AntiDupe", storeAs: "botAntiDupe", tooltip: "Prevents duplication of names with a random letter at the end", enableConditions: [["useCustomNameBots", true]], });
  2186. initModule({ location: tp.botTabs.pages[0], title: "CopyNames", storeAs: "botCopyName", tooltip: "Copies names from other players in the lobby", enableConditions: [["useCustomNameBots", true]], });
  2187. tp.botTabs.pages[0].addSeparator();
  2188. initModule({ location: tp.botTabs.pages[0], title: "Use Macro", storeAs: "useBotMacro", tooltip: "Execute a macro at bot startup", defaultValue: true, botParam: true, });
  2189. initModule({ location: tp.botTabs.pages[0], title: "Bot Macro", storeAs: "botMacro", tooltip: "The macro to be executed by the module above", defaultValue: "createPopup('success?');", botParam: true, });
  2190. tp.botTabs.pages[0].addSeparator();
  2191. initModule({ location: tp.botTabs.pages[0], title: "Proxy URL", storeAs: "proxyBots", tooltip: "Use random proxy urls for each bot instance", dropdown: [{ text: "Randomised", value: "randomised" }, { text: "Static", value: "static" },], defaultValue: "darkesteggshell", });
  2192. tp.botTabs.pages[0].addSeparator();
  2193. initModule({ location: tp.botTabs.pages[0], title: "Bot Color", storeAs: "eggColorBots", tooltip: "Sets the egg skin color of your bots", dropdown: [{ text: "Disabled", value: "disabled" }, { text: "White", value: "white" }, { text: "Light Blue", value: "lightblue" }, { text: "Light Eggshell", value: "lighteggshell" }, { text: "Eggshell", value: "eggshell" }, { text: "Dark Eggshell", value: "darkeggshell" }, { text: "Darker Eggshell", value: "darkereggshell" }, { text: "Darkest Eggshell", value: "darkesteggshell" }, { text: "Red (VIP)", value: "red" }, { text: "Purple (VIP)", value: "purple" }, { text: "Pink (VIP)", value: "pink" }, { text: "Yellow (VIP)", value: "yellow" }, { text: "Blue (VIP)", value: "blue" }, { text: "Green (VIP)", value: "green" }, { text: "Lime (VIP)", value: "lime" }, { text: "Randomised", value: "random" }], defaultValue: "darkesteggshell", });
  2194. initModule({ location: tp.botTabs.pages[0], title: "Bot Stamp", storeAs: "autoStampBots", tooltip: "Sets the stamp of your bots", dropdown: [{ text: "Disabled", value: "disabled" }, { text: "Target Stamp", value: "target" }, { text: "No Sign Stamp", value: "nosign" }, { text: "Question Mark Stamp?", value: "question" }, { text: "Peace Stamp", value: "peace" }, { text: "Thumbs Up Stamp", value: "thumbsup" }, { text: "Pablo Smile Stamp", value: "pablosmile" }, { text: "Randomised", value: "random" }], defaultValue: "pablosmile", });
  2195. initModule({ location: tp.botTabs.pages[0], title: "Bot Hat", storeAs: "autoHatBots", tooltip: "Sets the hat of your bots", dropdown: [{ text: "Disabled", value: "disabled" }, { text: "Ball Cap", value: "ballcap" }, { text: "Boat Fedora", value: "boatfedora" }, { text: "Top Hat", value: "tophat" }, { text: "Derby Hat", value: "derbyhat" }, { text: "Mountie Hat", value: "mountiehat" }, { text: "Pablo Hat", value: "pablohat" }, { text: "Randomised", value: "random" }], defaultValue: "pablohat", });
  2196. //MANAGE STUFF
  2197. initModule({ location: tp.botTabs.pages[1], title: "Close Bots", storeAs: "killBots", tooltip: "Closes all bot tabs & kills all bots", button: "CLOSE TABS", clickFunction: function () { broadcastToBots("kill") }, });
  2198. initModule({ location: tp.botTabs.pages[1], title: "Refresh Pages", storeAs: "refreshBots", tooltip: "Reloads all bot tabs", button: "REFRESH", clickFunction: function () { broadcastToBots("refresh") }, });
  2199. tp.botTabs.pages[1].addSeparator();
  2200. initModule({ location: tp.botTabs.pages[1], title: "New Proxies", storeAs: "newProxyBots", tooltip: "Moves bots to new proxies", button: "NEW PROXIES", clickFunction: function () { broadcastToBots("newproxy") }, });
  2201. initModule({ location: tp.botTabs.pages[1], title: "Unban All", storeAs: "unbanBots", tooltip: "Unbans all bots", button: "UNBAN BOTS", clickFunction: function () { broadcastToBots("unban") }, });
  2202. initModule({ location: tp.botTabs.pages[1], title: "AutoUnbanBot", storeAs: "botAutoUnban", tooltip: "Automatically unbans all bots when they're banned", botParam: true, });
  2203. initModule({ location: tp.botTabs.pages[1], title: "AutoLoginBot", storeAs: "botAutoLogin", tooltip: "Automatically logs bots into accounts", dropdown: [{ text: "Disabled", value: "disabled" }, { text: "When No Account", value: "noaccount" }, { text: "Always", value: "always" }], defaultValue: "disabled", botParam: true, });
  2204. tp.botTabs.pages[1].addSeparator();
  2205. initModule({ location: tp.botTabs.pages[1], title: "Don'tKillMe", storeAs: "botNoKillMe", tooltip: "Forces bots to ignore you", botParam: true, });
  2206. initModule({ location: tp.botTabs.pages[1], title: "Don'tKillBot", storeAs: "botNoKillBots", tooltip: "Forces bots to ignore other bots", botParam: true, });
  2207. initModule({ location: tp.botTabs.pages[1], title: "FollowMe", storeAs: "botFollowMe", tooltip: "semibroken", botParam: true, });
  2208. initModule({ location: tp.botTabs.pages[1], title: "FollowBots", storeAs: "botFollowBots", tooltip: "semibroken", botParam: true, });
  2209. tp.botTabs.pages[1].addSeparator();
  2210. initModule({ location: tp.botTabs.pages[1], title: "Leave Games", storeAs: "leaveBots", tooltip: "Makes all bots leave their games", button: "LEAVE", clickFunction: function () { broadcastToBots("leave") }, });
  2211. initModule({ location: tp.botTabs.pages[1], title: "Leave Empty", storeAs: "leaveEmptyBots", tooltip: "Makes bots leave empty games", botParam: true, });
  2212. initModule({ location: tp.botTabs.pages[1], title: "AutoLeave", storeAs: "autoLeaveBots", tooltip: "Makes bots leave after the specified interval", botParam: true, });
  2213. initModule({ location: tp.botTabs.pages[1], title: "Delay (s)", storeAs: "autoLeaveDelayBots", tooltip: "Interval to leave after", slider: { min: 0, max: 3600, step: 1 }, defaultValue: 300, enableConditions: [["autoLeaveBots", true]], botParam: true, });
  2214. tp.botTabs.pages[1].addSeparator();
  2215. initModule({ location: tp.botTabs.pages[1], title: "Spam Report", storeAs: "reportBots", tooltip: "Makes the bots report everyone in the lobby", button: "SPAM REPORT!", clickFunction: function () { broadcastToBots("report") }, });
  2216. tp.botTabs.pages[1].addSeparator();
  2217. initModule({ location: tp.botTabs.pages[1], title: "Join Game", storeAs: "botAutoJoin", tooltip: "Forces bots to join a game", botParam: true, });
  2218. initModule({ location: tp.botTabs.pages[1], title: "Game Code", storeAs: "botJoinCode", tooltip: "The code of the game the bots will join. If not specified, they'll find a random game", defaultValue: "CODE", botParam: true, });
  2219. initModule({ location: tp.botTabs.pages[1], title: "Get Code", storeAs: "getCodeBots", tooltip: "Get your current game as ID", button: "Retrieve", clickFunction: function () { change("botJoinCode", GAMECODE) }, botParam: true, });
  2220. tp.botTabs.pages[1].addSeparator();
  2221. initModule({ location: tp.botTabs.pages[1], title: "GameType", storeAs: "autoGamemodeBots", tooltip: "The game type the bots join - ffa, kotc, etc. can be random or disabled", dropdown: [{ text: "Disabled", value: "disabled" }, { text: "FFA", value: "ffa" }, { text: "Teams", value: "teams" }, { text: "Captula", value: "captula" }, { text: "KotC", value: "kotc" }, { text: "Randomised", value: "random" }], defaultValue: "disabled", botParam: true, });
  2222. initModule({ location: tp.botTabs.pages[1], title: "AutoRegion", storeAs: "autoRegionBots", tooltip: "The region the bots join - use, usc, etc. can be random or disabled", dropdown: [{ text: "Disabled", value: "disabled" }, { text: "Chile", value: "santiago" }, { text: "Germany", value: "germany" }, { text: "Singapore", value: "singapore" }, { text: "Sydney", value: "sydney" }, { text: "US Central", value: "uscentral" }, { text: "US East", value: "useast" }, { text: "US West", value: "uswest" }, { text: "Randomised", value: "random" }], defaultValue: "disabled", botParam: true, });
  2223. tp.botTabs.pages[1].addSeparator();
  2224. initModule({ location: tp.botTabs.pages[1], title: "Select Team", storeAs: "botTeam", tooltip: "Automatically picks the bots' teams", botParam: true, dropdown: [{ text: "Disabled", value: "disabled" }, { text: "Red Team", value: "red" }, { text: "Blue Team", value: "blue" }, { text: "Random Team", value: "random" }], defaultValue: "disabled", });
  2225. //PARAMS STUFF
  2226. initModule({ location: tp.botTabs.pages[2], title: "DoPlay", storeAs: "botRespawn", tooltip: "Make the bots spawn", botParam: true, });
  2227. initModule({ location: tp.botTabs.pages[2], title: "LowRes", storeAs: "botLowRes", tooltip: "Keeps resolution of the game low, reduces resources needed", botParam: true, })
  2228. initModule({ location: tp.botTabs.pages[2], title: "RenderDelay", storeAs: "renderDelayBots", tooltip: "Adds a forced fps buffer, makes game laggier", slider: { min: 0, max: 30000, step: 10 }, defaultValue: 0, botParam: true, });
  2229. initModule({ location: tp.botTabs.pages[2], title: "MuteGame", storeAs: "botMuteGame", tooltip: "Shuts the game up", botParam: true, })
  2230. tp.botTabs.pages[2].addSeparator();
  2231. initModule({ location: tp.botTabs.pages[2], title: "DoSeizure", storeAs: "botSeizure", tooltip: "Will the bots enable seizure mode?", botParam: true, enableConditions: [["botRespawn", true]], });
  2232. tp.botTabs.pages[2].addSeparator();
  2233. initModule({ location: tp.botTabs.pages[2], title: "DoTallChat", storeAs: "botTallChat", tooltip: "Enables the Tall Chat module for bots", botParam: true, });
  2234. initModule({ location: tp.botTabs.pages[2], title: "DoMock", storeAs: "botMock", tooltip: "Makes the bots mock chatting players", botParam: true, });
  2235. initModule({ location: tp.botTabs.pages[2], title: "DoAutoEZ", storeAs: "botAutoEZ", tooltip: "Makes the bots gloat about their kills", botParam: true, });
  2236. initModule({ location: tp.botTabs.pages[2], title: "DoChAccuse", storeAs: "botCheatAccuse", tooltip: "Makes the bots accuse their killers when dying", botParam: true, });
  2237. tp.botTabs.pages[2].addSeparator();
  2238. initModule({ location: tp.botTabs.pages[2], title: "DoSpam", storeAs: "botSpam", tooltip: "Makes the bots spam", botParam: true, });
  2239. initModule({ location: tp.botTabs.pages[2], title: "SpamText", storeAs: "spamChatTextBot", tooltip: "The message spammed by the bots", defaultValue: "ЅtateFarm Client On Top! ", botParam: true, });
  2240. tp.botTabs.pages[2].addSeparator();
  2241. initModule({ location: tp.botTabs.pages[2], title: "SelectWeapon", storeAs: "botWeapon", tooltip: "Makes the bots pick a weapon", dropdown: [{ text: "EggK-47", value: "eggk47" }, { text: "Scrambler", value: "scrambler" }, { text: "Free Ranger", value: "freeranger" }, { text: "RPEGG", value: "rpegg" }, { text: "Whipper", value: "whipper" }, { text: "Crackshot", value: "crackshot" }, { text: "Tri-Hard", value: "trihard" }, { text: "Randomised", value: "random" }], botParam: true, defaultValue: "eggk47", enableConditions: [["botRespawn", true]], });
  2242. initModule({ location: tp.botTabs.pages[2], title: "DoMove", storeAs: "botAutoMove", tooltip: "Makes the bots move around", botParam: true, enableConditions: [["botRespawn", true]], });
  2243. initModule({ location: tp.botTabs.pages[2], title: "DoShoot", storeAs: "botAutoShoot", tooltip: "Makes the bots shoot", tooltip: "Makes the bot autoshoot.", botParam: true, enableConditions: [["botRespawn", true]], });
  2244. initModule({ location: tp.botTabs.pages[2], title: "DoAimbot", storeAs: "botAimbot", tooltip: "Makes the bots have aimbot", botParam: true, enableConditions: [["botRespawn", true]], });;
  2245. initModule({ location: tp.botTabs.pages[2], title: "UseMinAccuracy", storeAs: "botAccuracy", tooltip: "Makes the bots only fire if the spread is lower than the given value", slider: { min: 0, max: 1, step: 0.05 }, defaultValue: 0, botParam: true, enableConditions: [["botRespawn", true]], });
  2246. //INFO STUFF
  2247. initModule({ location: tp.botTabs.pages[3], storeAs: "botOnline", tooltip: "Sex", monitor: 17.5, botParam: true, });
  2248.  
  2249. if (!AUTOMATED) {
  2250. try {
  2251. if (!load("StateFarmConfigMainPanel") || reset===true) {
  2252. saveConfig();
  2253. } else {
  2254. log("##############################################")
  2255. tp.mainPanel.importPreset(load("StateFarmConfigMainPanel"));
  2256. tp.botPanel.importPreset(load("StateFarmConfigBotPanel"));
  2257. try {
  2258. let specialItems = load("StateFarmConfigSpecialItems"); //this is for the fucking shit that doesnt apply for NO reason!!
  2259. if (specialItems) {
  2260. specialItems.forEach(item => {
  2261. change(item[0], item[1]);
  2262. log(item[0], item[1]);
  2263. });
  2264. };
  2265. } catch (error) {
  2266.  
  2267. }
  2268. };
  2269. } catch (error) {
  2270. log("error in initmenu !AUTOMATED part thing, idk", error);
  2271. };
  2272. };
  2273.  
  2274. updateConfig();
  2275.  
  2276. setTimeout(() => {
  2277. if (AUTOMATED) { //why after 500ms? perhaps we'll never know. maybe because it gives a visual indication that statefarm is statefarming.
  2278. tp.mainPanel.hidden = true;
  2279. };
  2280. updateHiddenAndDisabled();
  2281. let specialItems = load("StateFarmConfigSpecialItems"); //this is for the fucking shit that doesnt apply for NO reason!!
  2282. if (specialItems) {
  2283. specialItems.forEach(item => {
  2284. change(item[0], item[1]);
  2285. log(item[0], item[1]);
  2286. });
  2287. };
  2288. //tooltip events
  2289. unsafeWindow.document.querySelectorAll('.tp-lblv_l').forEach(label => {
  2290. // if (extract("debug") && !tooltips[label.innerText]) log("Warning: no tooltip assigned for module:", label.innerText);
  2291. // shut up - 1ust
  2292.  
  2293. label.addEventListener('mouseenter', () => {
  2294. if (extract("tooltips")) {
  2295. tooltipElement.innerText = tooltips[label.innerText] || 'Tooltip parameter not found';
  2296. tooltipElement.style.opacity = '1';
  2297. const rect = label.getBoundingClientRect();
  2298. tooltipElement.style.top = `${rect.top + window.scrollY - 12}px`;
  2299. tooltipElement.style.left = `${rect.left + window.scrollX - tooltipElement.offsetWidth - 10}px`;
  2300. }
  2301. });
  2302. label.addEventListener('mouseleave', () => {
  2303. tooltipElement.style.opacity = '0';
  2304. });
  2305. });
  2306. }, 500);
  2307.  
  2308. menuInitiated = reset == "init" ? "init" : true;
  2309.  
  2310. if (allowAccess) {
  2311. const defaultSpamText = ("dsc.gg/s𝖿network: " + menuTitle + " On Top! ");
  2312.  
  2313. if (extract("spamChatText").includes("On Top!")) { change("spamChatText", defaultSpamText) };
  2314. if (extract("spamChatTextBot").includes("On Top!")) { change("spamChatTextBot", defaultSpamText) };
  2315. if (extract("fakeMessageText").includes("On Top!")) { change("fakeMessageText", defaultSpamText) };
  2316.  
  2317. makeDraggable(tp.mainPanel.containerElem_);
  2318. makeDraggable(tp.botPanel.containerElem_);
  2319. };
  2320. };
  2321. const onContentLoaded = function () {
  2322. log("StateFarm: initMenu()");
  2323. initMenu("init");
  2324. log("StateFarm: applyStylesAddElements()");
  2325. applyStylesAddElements(); //set font and change menu cass, and other stuff to do with the page
  2326. const intervalId1 = setInterval(every15Seconds, 15000);
  2327. const intervalId2 = setInterval(everySecond, 1000);
  2328. const intervalId3 = setInterval(everyDecisecond, 100);
  2329. applyStateFarmLogo();
  2330. const observer = new MutationObserver(applyStateFarmLogo);
  2331. observer.observe(document.body, { subtree: true, childList: true });
  2332. };
  2333. //visual functions
  2334. const createPopup = function (text, type) {
  2335. log("Creating Popup Type:", type, "With Text:", text);
  2336. try {
  2337. if (extract("popups")) {
  2338. const messageContainer = document.getElementById('message-container');
  2339. const messages = messageContainer.getElementsByClassName(scrambledMsgEl);
  2340. if (messages.length > 5) {
  2341. messageContainer.removeChild(messages[0]);
  2342. };
  2343. const clonedMsgElement = msgElement.cloneNode(true);
  2344. clonedMsgElement.innerText = text;
  2345. switch (type) {
  2346. case ("success"):
  2347. clonedMsgElement.style.border = '2px solid rgba(0, 255, 0, 0.5)'; break;
  2348. case ("error"):
  2349. clonedMsgElement.style.border = '2px solid rgba(255, 0, 0, 0.5)'; break;
  2350. };
  2351. clonedMsgElement.style.display = 'none';
  2352. const messageOffset = (messages.length + 1) * 50;
  2353. clonedMsgElement.style.bottom = messageOffset + "px";
  2354. void clonedMsgElement.offsetWidth;
  2355. clonedMsgElement.style.display = '';
  2356. messageContainer.appendChild(clonedMsgElement);
  2357. //reorder such that newest is lowest
  2358. for (let i = messages.length - 1; i >= 0; i--) {
  2359. messages[i].style.bottom = (((messages.length - i) * 50) - 40) + "px";
  2360. };
  2361. };
  2362. } catch (error) {
  2363. // Handle the error and display an error message onscreen
  2364. console.error("An error occurred:", error);
  2365. 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 developers.");
  2366. };
  2367. };
  2368. const createPrompt = function(text = "No text set", buttons = [], duration = 5000) {
  2369. unsafeWindow.BAWK.play("kotc_zonespawn");
  2370. // log(arguments);
  2371. const promptElement = document.createElement('div');
  2372. promptElement.innerText = text;
  2373. promptElement.setAttribute('style', `
  2374. position: absolute;
  2375. left: 10px;
  2376. top: 50%;
  2377. transform: translateY(-50%);
  2378. color: #fff;
  2379. background: rgba(0, 0, 0, 0.7);
  2380. font-weight: normal;
  2381. padding: 10px;
  2382. border-radius: 5px;
  2383. box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
  2384. border: 2px solid rgba(255, 255, 255, 0.5);
  2385. animation: msg 0.5s forwards, msg 0.5s reverse forwards ${duration/1000}s;
  2386. pointer-events: none;
  2387. opacity: 0;
  2388. transition: opacity 0.3s ease-in-out;
  2389. font-family: 'Bahnschrift', sans-serif !important;
  2390. font-size: 16px;
  2391. z-index: 9999 !important;
  2392. white-space: pre-wrap;
  2393. width: 300px;
  2394. `);
  2395. const buttonContainer = document.createElement('div');
  2396. buttonContainer.setAttribute('style', 'margin-top: 10px; pointer-events: auto; text-align: center;');
  2397.  
  2398. const deleteButton = function(){
  2399. try {
  2400. document.body.removeChild(promptElement);
  2401. } catch (error) {
  2402. log("Error deleting prompt element:", error);
  2403. };
  2404. };
  2405.  
  2406. buttons = [...buttons,
  2407. [`Dismiss (${Math.ceil(duration/1000)}s)`, () => deleteButton()]
  2408. ];
  2409.  
  2410. buttons.forEach(([buttonText, buttonFunction]) => {
  2411. const button = document.createElement('button');
  2412. button.innerText = buttonText;
  2413. button.setAttribute('style', `
  2414. background: #6c757d;
  2415. color: #fff;
  2416. border: none;
  2417. padding: 5px 10px;
  2418. margin-right: 5px;
  2419. border-radius: 3px;
  2420. cursor: pointer;
  2421. font-family: 'Bahnschrift', sans-serif !important;
  2422. `);
  2423. button.onclick = buttonFunction;
  2424. buttonContainer.appendChild(button);
  2425. });
  2426. promptElement.appendChild(buttonContainer);
  2427. document.body.appendChild(promptElement);
  2428. setTimeout(() => {
  2429. promptElement.style.opacity = '1';
  2430. }, 100);
  2431. setTimeout(() => {
  2432. promptElement.style.opacity = '0';
  2433. setTimeout(() => {
  2434. deleteButton();
  2435. }, 800);
  2436. }, duration);
  2437. };
  2438. const createVarDataOverlay = function () {
  2439. //create vardataOverlay
  2440. vardataOverlay = document.createElement('div');
  2441. vardataOverlay.style.position = 'fixed';
  2442. vardataOverlay.style.top = '0';
  2443. vardataOverlay.style.left = '0';
  2444. vardataOverlay.style.width = '100%';
  2445. vardataOverlay.style.height = '100%';
  2446. vardataOverlay.style.backgroundColor = 'rgba(0, 0, 0, 0.75)';
  2447. vardataOverlay.style.zIndex = '9998';
  2448. vardataOverlay.style.opacity = '0';
  2449. vardataOverlay.style.transition = 'opacity 0.4s ease-in-out';
  2450.  
  2451. document.body.appendChild(vardataOverlay);
  2452.  
  2453. //fade anims
  2454. setTimeout(() => {
  2455. vardataOverlay.style.opacity = '1';
  2456. }, 10);
  2457. };
  2458. const createVarDataPopup = function (vardataButtonsInfo) {
  2459. closeVardataPopup = () => {
  2460. vardataPopup.style.opacity = '0';
  2461. vardataOverlay.style.opacity = '0';
  2462. setTimeout(() => {
  2463. document.body.removeChild(vardataPopup);
  2464. document.body.removeChild(vardataOverlay);
  2465. reloadPage();
  2466. }, 400);
  2467. };
  2468.  
  2469. createVarDataOverlay();
  2470.  
  2471. //create vardataPopup
  2472. vardataPopup = document.createElement('div');
  2473. vardataPopup.style.position = 'fixed';
  2474. vardataPopup.style.left = '50%';
  2475. vardataPopup.style.top = '50%';
  2476. vardataPopup.style.width = '50em';
  2477. vardataPopup.style.transform = 'translate(-50%, -50%)';
  2478. vardataPopup.style.color = '#fff';
  2479. vardataPopup.style.backgroundColor = 'rgba(0, 0, 0, 0.7)';
  2480. vardataPopup.style.padding = '15px';
  2481. vardataPopup.style.borderRadius = '5px';
  2482. vardataPopup.style.boxShadow = '0 2px 10px rgba(0, 0, 0, 0.2)';
  2483. vardataPopup.style.border = '2px solid rgba(255, 255, 255, 0.5)';
  2484. vardataPopup.style.pointerEvents = 'auto';
  2485. vardataPopup.style.opacity = '0';
  2486. vardataPopup.style.transition = 'opacity 0.4s ease-in-out';
  2487. vardataPopup.style.fontFamily = 'Nunito, sans-serif';
  2488. vardataPopup.style.fontSize = '16px';
  2489. vardataPopup.style.letterSpacing = '0.3px';
  2490. vardataPopup.style.zIndex = '9999';
  2491. vardataPopup.style.whiteSpace = 'pre-wrap';
  2492. vardataPopup.style.fontWeight = 'bold';
  2493.  
  2494. //set vardataPopup content
  2495. const title = "Valid VarData failed to load!"
  2496. const message = `This is likely because you have two versions of StateFarm installed, or that your client needs to be updated.<br>
  2497. <strong>Steps to fix (go through until it works)</strong>
  2498. 1. click the "load latest" button below (most likely fix)
  2499. 2. confirm that you only have either Violentmonkey OR Tampermonkey with ONE version of StateFarm installed
  2500. 3. update statefarm by clicking <a href="${GM_info.script.downloadURL}" target="_blank" style="color: #1944ff; text-decoration: underline; font-size: inherit;">here</a> and clicking the "Update" button
  2501. 4. join our <a href="${discordURL}" target="_blank" style="color: #1944ff; text-decoration: underline; font-size: inherit;">Discord server</a> and opening a ticket in #sfc-support`;
  2502.  
  2503. const image = `<img src='${itsOverURL}' style='width: 7%; height: 7%; margin-right: 15px; vertical-align: middle;'>`;
  2504. vardataPopup.innerHTML = `${image}<strong style="font-size: 20px; margin-top: 5px;">${title}</strong><br><br>${message}<br><br>`;
  2505.  
  2506. //create buttons
  2507. const vardataButtonContainer = document.createElement('div');
  2508. vardataButtonContainer.style.display = 'flex';
  2509. vardataButtonContainer.style.justifyContent = 'space-between';
  2510. vardataButtonContainer.style.marginTop = '10px';
  2511.  
  2512. vardataButtonsInfo.forEach(({ id, text, isHighlighted, action }) => {
  2513. const button = document.createElement('button');
  2514. button.id = id;
  2515. button.innerHTML = text;
  2516. button.style.padding = '7px 10px';
  2517. button.style.backgroundColor = 'rgba(255, 255, 255, 0.1)';
  2518. button.style.color = '#fff';
  2519. button.style.border = '1px solid rgba(255, 255, 255, 0.5)';
  2520. button.style.borderRadius = '5px';
  2521. button.style.cursor = 'pointer';
  2522. button.style.transition = 'background-color 0.2s';
  2523. button.style.flex = '1';
  2524. button.style.marginRight = '10px';
  2525. button.style.fontSize = '14px';
  2526. button.style.whiteSpace = 'pre-wrap';
  2527. button.style.fontFamily = vardataPopup.style.fontFamily;
  2528. button.style.fontWeight = vardataPopup.style.fontWeight;
  2529.  
  2530. button.addEventListener('click', action);
  2531. button.addEventListener('mouseenter', () => button.style.backgroundColor = 'rgba(255, 255, 255, 0.3)');
  2532. button.addEventListener('mouseleave', () => button.style.backgroundColor = 'rgba(255, 255, 255, 0.1)');
  2533.  
  2534. if (isHighlighted) {
  2535. button.style.border = '3px solid lime';
  2536. }
  2537.  
  2538. vardataButtonContainer.appendChild(button);
  2539. });
  2540.  
  2541. vardataPopup.appendChild(vardataButtonContainer);
  2542.  
  2543. const setButtonState = function (buttonId, isEnabled) {
  2544. const button = unsafeWindow.document.getElementById(buttonId);
  2545. if (button) {
  2546. button.disabled = !isEnabled;
  2547. button.style.opacity = isEnabled ? '1' : '0.5';
  2548. button.style.pointerEvents = isEnabled ? 'auto' : 'none';
  2549. }
  2550. };
  2551.  
  2552. (setTimeout(() => {
  2553. vardataButtonsInfo.forEach(({ id, enabled }) => {
  2554. setButtonState(id, enabled);
  2555. });
  2556. }, 200));
  2557.  
  2558. //create checkbox
  2559. const vardataCheckboxContainer = document.createElement('div');
  2560. vardataCheckboxContainer.style.display = 'flex';
  2561. vardataCheckboxContainer.style.justifyContent = 'center';
  2562. vardataCheckboxContainer.style.alignItems = 'center';
  2563. vardataCheckboxContainer.style.marginTop = '15px';
  2564. vardataCheckboxContainer.style.fontSize = '16px';
  2565.  
  2566. const checkbox = document.createElement('input');
  2567. checkbox.type = 'checkbox';
  2568. checkbox.id = 'rememberCheckbox';
  2569. checkbox.style.display = 'none';
  2570.  
  2571. const customCheckbox = document.createElement('span');
  2572. customCheckbox.style.width = '20px';
  2573. customCheckbox.style.height = '20px';
  2574. customCheckbox.style.display = 'inline-block';
  2575. customCheckbox.style.backgroundColor = 'rgba(255, 255, 255, 0.1)';
  2576. customCheckbox.style.border = '1px solid rgba(255, 255, 255, 0.5)';
  2577. customCheckbox.style.borderRadius = '5px';
  2578. customCheckbox.style.marginRight = '8px';
  2579. customCheckbox.style.cursor = 'pointer';
  2580.  
  2581. customCheckbox.addEventListener('click', () => {
  2582. checkbox.checked = !checkbox.checked;
  2583. change("vardataType", checkbox.checked ? 2 : 1);
  2584. customCheckbox.style.backgroundColor = checkbox.checked ? 'rgba(255, 255, 255, 0.8)' : 'rgba(255, 255, 255, 0.1)';
  2585. });
  2586.  
  2587. vardataCheckboxContainer.appendChild(customCheckbox);
  2588. vardataCheckboxContainer.appendChild(checkbox);
  2589. vardataCheckboxContainer.appendChild(document.createTextNode('Remember until next hash'));
  2590. vardataPopup.appendChild(vardataCheckboxContainer);
  2591.  
  2592. document.body.appendChild(vardataPopup);
  2593.  
  2594. /*
  2595. //add inputs stuff
  2596. const input = document.getElementById('vardataInput');
  2597. const submitButton = document.getElementById('submitVarData');
  2598.  
  2599. submitButton.addEventListener('click', () => {
  2600. const inputValue = input.value;
  2601.  
  2602. const error = function () {
  2603. createPopup("Inputted VarData isn't valid.", "error");
  2604. };
  2605.  
  2606. try {
  2607. let converted = JSON.parse(inputValue);
  2608. if (converted.vars && converted.checksum) {
  2609. change("vardataCustom", inputValue);
  2610. change("vardataFallback", 4);
  2611. change("vardataType", 1); //custom isnt consistent enough
  2612. closeVardataPopup();
  2613. } else {
  2614. error();
  2615. };
  2616. } catch (e) {
  2617. error();
  2618. }
  2619. });
  2620.  
  2621. input.addEventListener('keypress', (event) => {
  2622. if (event.key === 'Enter') {
  2623. submitButton.click();
  2624. }
  2625. });
  2626. */
  2627.  
  2628. //fade anims
  2629. setTimeout(() => {
  2630. vardataPopup.style.opacity = '1';
  2631. }, 10);
  2632. };
  2633.  
  2634. //StateFarmChat functions
  2635. const sfChatUsernameSet = function () {
  2636. let tagAdded = `[Shell] ${extract("sfChatUsername")}`;
  2637. if (sfChatUsername != tagAdded && sfChatIframe != undefined) {
  2638. sfChatUsername = tagAdded; log(sfChatUsername);
  2639. sfChatIframe.contentWindow.postMessage("SFCHAT-UPDATE" + JSON.stringify({ name: sfChatUsername }), "*");
  2640. };
  2641. };
  2642. const startStateFarmChat = function (startHidden) {
  2643. //UnsafewindowVars
  2644. const makeChatDragable = function (element) {
  2645. if (element.getAttribute("drag-true") != "true") {
  2646. element.addEventListener("mousedown", function (e) {
  2647. let offsetX = e.clientX - parseInt(window.getComputedStyle(this).left);
  2648. let offsetY = e.clientY - parseInt(window.getComputedStyle(this).top);
  2649. function mouseMoveHandler(e) {
  2650. let newX = e.clientX - offsetX;
  2651. let newY = e.clientY - offsetY;
  2652. if (newX >= 0 && newX + element.getBoundingClientRect().width <= window.innerWidth) {
  2653. element.style.left = newX + "px";
  2654. }
  2655. if (newY >= 0 && newY + element.getBoundingClientRect().height <= window.innerHeight) {
  2656. element.style.top = newY + "px";
  2657. }
  2658. }
  2659.  
  2660. function reset() {
  2661. window.removeEventListener("mousemove", mouseMoveHandler);
  2662. window.removeEventListener("mouseup", reset);
  2663. }
  2664.  
  2665. window.addEventListener("mousemove", mouseMoveHandler);
  2666. window.addEventListener("mouseup", reset);
  2667. });
  2668.  
  2669. element.setAttribute("drag-true", "true");
  2670. };
  2671. };
  2672.  
  2673. sfChatContainer = document.createElement("div");
  2674. sfChatContainer.style.padding = "1px";
  2675. let title = document.createElement("p");
  2676. title.style.fontSize = "medium";
  2677. title.style.color = "#D6D6D6";
  2678. title.innerHTML = "StateFarm Chat";
  2679. sfChatContainer.appendChild(title);
  2680. sfChatContainer.style.backgroundColor = "#555";
  2681. sfChatContainer.style.position = "absolute";
  2682. sfChatContainer.style.borderRadius = "10px";
  2683. sfChatContainer.style.textAlign = "center";
  2684. sfChatContainer.style.top = "20px";
  2685. sfChatContainer.style.left = "20px";
  2686. sfChatContainer.style.zIndex = 100000000;
  2687. if (startHidden){
  2688. sfChatContainer.style.display = 'none';
  2689. }
  2690.  
  2691. const sendSettings = function () {
  2692. let settings = GM_getValue("SFCHAT-SETTINGS");
  2693. if (settings) {
  2694. sfChatIframe.contentWindow.postMessage("SFCHAT-SETTINGS" + settings, "*");
  2695. } else {
  2696. sfChatIframe.contentWindow.postMessage("SFCHAT-SETTINGS", "*");
  2697. };
  2698. };
  2699.  
  2700. makeChatDragable(sfChatContainer);
  2701. sfChatIframe = document.createElement("iframe");
  2702. sfChatIframe.setAttribute(
  2703. "src", sfChatURL
  2704. );
  2705. sfChatIframe.id = "sfChat-iframe";
  2706. sfChatIframe.setAttribute("style", "width: 600px; height:700px; z-index: 10000;");
  2707. sfChatContainer.appendChild(sfChatIframe);
  2708. document.getElementsByTagName("body")[0].appendChild(sfChatContainer);
  2709.  
  2710. const startTimeout = setTimeout(function () {
  2711. log("settings");
  2712. sendSettings();
  2713. let nameChange = setTimeout(function () {
  2714. sfChatUsername = `[Shell] ${extract("sfChatUsername")}`;
  2715. sfChatIframe.contentWindow.postMessage("SFCHAT-UPDATE" + JSON.stringify({ name: sfChatUsername }), "*");
  2716. }, 500);
  2717. }, 1000);
  2718.  
  2719. unsafeWindow.addEventListener("message", (e) => {
  2720. if (typeof e.data == "string"){
  2721. if (e.data.startsWith("SFCHAT-UPDATE")) {
  2722. GM_setValue("SFCHAT-SETTINGS", e.data.replace(/SFCHAT-UPDATE/gm, ""));
  2723. }
  2724. if (e.data.startsWith("SFCHAT-REQUEST")) {
  2725. sendSettings();
  2726. };
  2727. if (e.data.startsWith("SFCHAT-MESSAGE")) {
  2728. let stringMessage = e.data.replace(/SFCHAT-MESSAGE/gm, "");
  2729. let message = JSON.parse(stringMessage);
  2730. if (extract("sfChatNotifications") && message.user && message.message && (sfChatContainer.style.display == "none")){
  2731. if (message.message.length <= 50){
  2732. createPopup(message.user.name + ": " + message.message);
  2733. } else {
  2734. createPopup(message.user.name + ": " + message.message.substring(0, 50) + "...");
  2735. }
  2736. if (extract("sfChatNotificationSound")){
  2737. unsafeWindow.BAWK.play("grenade_cellphone");
  2738. };
  2739. };
  2740.  
  2741. if (extract("sfChatInvitations")) {
  2742. let uppercaseMsg = message.message.toUpperCase();
  2743. const findCode = (input) => {
  2744. const allMatches = input.match(/(?:[A-Z]{4}-[A-Z]{4}-[A-Z]{4})/g);
  2745. if (allMatches) {
  2746. for (const match of allMatches) {
  2747. if (/[A-z]/.test(match)) {
  2748. return match;
  2749. };
  2750. };
  2751. };
  2752. return null;
  2753. };
  2754. let foundCode = findCode(uppercaseMsg);
  2755. if (foundCode) {
  2756. createPrompt(`INVITE! User "${message.user.name}" has invited you to join game "${foundCode}"! (via SFChat)`, [
  2757. ['JOIN', () => {
  2758. change("leaveGame");
  2759. setTimeout(() => {
  2760. vueApp.externPlayObject(
  2761. 2,
  2762. vueApp.currentGameType,
  2763. vueApp.playerName,
  2764. '',
  2765. foundCode,
  2766. );
  2767. }, 500);
  2768. }]
  2769. ], 10000);
  2770. };
  2771. };
  2772. };
  2773. };
  2774. });
  2775. };
  2776.  
  2777. const applyStylesAddElements = function (themeToApply = "null") {
  2778. const head = document.head || document.getElementsByTagName('head').pages[0];
  2779.  
  2780. if (AUTOMATED) {
  2781. automatedBorder = document.createElement('div');
  2782. automatedBorder.setAttribute('id', 'automated-border');
  2783. document.body.appendChild(automatedBorder);
  2784.  
  2785. const automatedBorderStyle = `
  2786. position: fixed;
  2787. top: 0;
  2788. left: 0;
  2789. width: 100%;
  2790. height: 100%;
  2791. border: 5px solid rgba(255, 0, 0, 1);
  2792. pointer-events: none;
  2793. z-index: 999999999;
  2794. `;
  2795. automatedBorder.style.cssText = automatedBorderStyle;
  2796. };
  2797.  
  2798. //menu customisation (apply font, button widths, adjust checkbox right slightly, make menu appear on top, add anim to message)
  2799. const styleElement = document.createElement('style');
  2800. styleElement.textContent = `
  2801. @font-face {
  2802. font-family: "Bahnschrift";
  2803. src: url("https://db.onlinewebfonts.com/t/0a6ee448d1bd65c56f6cf256a7c6f20a.eot");
  2804. src: url("https://db.onlinewebfonts.com/t/0a6ee448d1bd65c56f6cf256a7c6f20a.eot?#iefix")format("embedded-opentype"),
  2805. url("https://db.onlinewebfonts.com/t/0a6ee448d1bd65c56f6cf256a7c6f20a.woff2")format("woff2"),
  2806. url("https://db.onlinewebfonts.com/t/0a6ee448d1bd65c56f6cf256a7c6f20a.woff")format("woff"),
  2807. url("https://db.onlinewebfonts.com/t/0a6ee448d1bd65c56f6cf256a7c6f20a.ttf")format("truetype"),
  2808. url("https://db.onlinewebfonts.com/t/0a6ee448d1bd65c56f6cf256a7c6f20a.svg#Bahnschrift")format("svg");
  2809. }
  2810. .tp-dfwv, .tp-sglv_i, .tp-rotv_t, .tp-fldv_t, .tp-ckbv_l, .tp-txtv_i, .tp-lblv_l, .tp-tbiv_t, .coords, .gameinfo, .playerstats, .playerinfo, .performanceinfo, .automated {
  2811. font-family: 'Bahnschrift', sans-serif !important;
  2812. font-size: 16px;
  2813. z-index: 9999 !important;
  2814. }
  2815. .tp-rotv_m, .tp-fldv_m {
  2816. display: none;
  2817. }
  2818. .tp-dfwv {
  2819. min-width: 300px;
  2820. }
  2821. .tp-rotv_t {
  2822. cursor: move;
  2823. user-select: none;
  2824. }
  2825. .tp-tbiv_t {
  2826. font-family: 'Bahnschrift';
  2827. font-size: 13px;
  2828. }
  2829. .tp-lblv_v, .tp-lstv, .tp-btnv_b, .tp-btnv_t {
  2830. font-family: 'Bahnschrift';
  2831. font-size: 12px;
  2832. }
  2833. .tp-mllv {
  2834. font-family: 'Bahnschrift';
  2835. font-size: 12px;
  2836. letter-spacing: -1px;
  2837. width: 290px;
  2838. margin-left: -130px !important;
  2839. }
  2840. .tp-mllv_i::-webkit-scrollbar-thumb {
  2841. background-color: #888; /* Adjust the color as needed */
  2842. border: 2px solid #555; /* Change the color of the border and adjust the width as needed */
  2843. }
  2844. .tp-mllv_i::-webkit-scrollbar-track {
  2845. background-color: #000; /* Change the color as needed */
  2846. }
  2847. .tp-lblv_l {
  2848. font-size: 14px;
  2849. letter-spacing: -1px;
  2850. }
  2851. .tp-btnv {
  2852. width: 100px;
  2853. margin-left: 60px !important;
  2854. }
  2855. .tp-ckbv_w {
  2856. margin-left: 4px !important;
  2857. }
  2858. .tp-dfwv, .tp-rotv, .tp-rotv_c, .tp-fldv, .tp-fldv_c, .tp-lblv, .tp-lstv, .tp-btnv, .tp-sldv {
  2859. z-index: 99999 !important;
  2860. white-space: nowrap !important;
  2861. }
  2862. @keyframes msg {
  2863. from {
  2864. transform: translate(-120%, 0);
  2865. opacity: 0;
  2866. }
  2867. to {
  2868. transform: none;
  2869. opacity: 1;
  2870. }
  2871. }
  2872. `;
  2873.  
  2874. document.head.appendChild(styleElement);
  2875. applyTheme();
  2876.  
  2877. //initiate message div and css and shit
  2878. msgElement = document.createElement('div'); // create the element directly
  2879. scrambledMsgEl = getScrambled();
  2880. msgElement.classList.add(scrambledMsgEl);
  2881. msgElement.setAttribute('style', `
  2882. position: absolute;
  2883. left: 10px;
  2884. color: #fff;
  2885. background: rgba(0, 0, 0, 0.7);
  2886. font-weight: normal;
  2887. padding: 10px;
  2888. border-radius: 5px;
  2889. box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
  2890. border: 2px solid rgba(255, 255, 255, 0.5);
  2891. animation: msg 0.5s forwards, msg 0.5s reverse forwards 3s;
  2892. pointer-events: none;
  2893. opacity: 0;
  2894. transition: opacity 0.3s ease-in-out;
  2895. font-family: 'Bahnschrift', sans-serif !important;
  2896. font-size: 16px;
  2897. z-index: 9999 !important;
  2898. `);
  2899. document.body.appendChild(msgElement);
  2900. msgElement.style.display = 'none';
  2901. const messageContainer = document.createElement('div'); //so it can be cloned. i think.
  2902. messageContainer.id = 'message-container';
  2903. document.body.appendChild(messageContainer);
  2904. //initiate tooltip div and css and shit
  2905. tooltipElement = document.createElement('div');
  2906. tooltipElement.style.cssText = `
  2907. position: absolute;
  2908. color: #fff;
  2909. background: rgba(0, 0, 0, 0.7);
  2910. font-weight: normal;
  2911. padding: 10px;
  2912. border-radius: 5px;
  2913. box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
  2914. border: 2px solid rgba(255, 255, 255, 0.5);
  2915. animation: fadeIn 0.5s forwards, fadeOut 0.5s reverse forwards 3s;
  2916. pointer-events: none;
  2917. opacity: 0;
  2918. transition: opacity 0.3s ease-in-out;
  2919. font-family: 'Bahnschrift', sans-serif !important;
  2920. font-size: 16px;
  2921. z-index: 9999999 !important;
  2922. max-width: 300px;
  2923. word-wrap: break-word;
  2924. `;
  2925. document.body.appendChild(tooltipElement);
  2926. //initiate coord div and css and shit
  2927. coordElement = document.createElement('div'); // create the element directly
  2928. coordElement.classList.add('coords');
  2929. coordElement.setAttribute('style', `
  2930. position: fixed;
  2931. top: 0px;
  2932. left: 0px;
  2933. height: auto;
  2934. max-height: 30px;
  2935. min-height: 30px;
  2936. text-wrap: nowrap;
  2937. color: #fff;
  2938. background: rgba(0, 0, 0, 0.6);
  2939. font-weight: bolder;
  2940. padding: 2px;
  2941. border-radius: 5px;
  2942. box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
  2943. border: 2px solid rgba(255, 255, 255, 0.5);
  2944. z-index: 999999;
  2945. `);
  2946. document.body.appendChild(coordElement);
  2947. coordElement.style.display = 'none';
  2948. //initiate game info div and css and shit
  2949. gameInfoElement = document.createElement('div'); // create the element directly
  2950. gameInfoElement.classList.add('gameinfo');
  2951. gameInfoElement.setAttribute('style', `
  2952. position: fixed;
  2953. bottom: 0px;
  2954. left: 0px;
  2955. height: auto;
  2956. max-height: 30px;
  2957. min-height: 30px;
  2958. text-wrap: nowrap;
  2959. color: #fff;
  2960. background: rgba(0, 0, 0, 0.6);
  2961. font-weight: bolder;
  2962. padding: 2px;
  2963. border-radius: 5px;
  2964. box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
  2965. border: 2px solid rgba(255, 255, 255, 0.5);
  2966. z-index: 999999;
  2967. `);
  2968. document.body.appendChild(gameInfoElement);
  2969. gameInfoElement.style.display = 'none';
  2970. //initiate hp div and css and shit
  2971. playerstatsElement = document.createElement('div'); // create the element directly
  2972. playerstatsElement.classList.add('playerstats');
  2973. playerstatsElement.setAttribute('style', `
  2974. position: absolute;
  2975. top: 20px;
  2976. left: 280px;
  2977. height: auto;
  2978. min-height: 30px;
  2979. text-wrap: nowrap;
  2980. color: #fff;
  2981. background: rgba(0, 0, 0, 0.6);
  2982. font-weight: bolder;
  2983. padding: 10px;
  2984. border-radius: 5px;
  2985. box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
  2986. border: 2px solid rgba(255, 255, 255, 0.5);
  2987. z-index: 999999;
  2988. `);
  2989. document.body.appendChild(playerstatsElement);
  2990. playerstatsElement.style.display = 'none';
  2991. //initiate player info div and css and shit
  2992. playerinfoElement = document.createElement('div'); // create the element directly
  2993. playerinfoElement.classList.add('playerinfo');
  2994. playerinfoElement.setAttribute('style', `
  2995. position: absolute;
  2996. top: 80%;
  2997. left: 90%;
  2998. height: auto;
  2999. max-height: 102;
  3000. text-wrap: nowrap;
  3001. color: #fff;
  3002. background: rgba(0, 0, 0, 0.6);
  3003. font-weight: bolder;
  3004. padding: 10px;
  3005. border-radius: 5px;
  3006. box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
  3007. border: 2px solid rgba(255, 255, 255, 0.5);
  3008. z-index: 999999;
  3009. `);
  3010. document.body.appendChild(playerinfoElement);
  3011. playerinfoElement.style.display = 'none';
  3012. //initiate player info div and css and shit
  3013. performanceElement = document.createElement('div'); // create the element directly
  3014. performanceElement.classList.add('performanceinfo');
  3015. performanceElement.setAttribute('style', `
  3016. position: absolute;
  3017. top: 35%;
  3018. left: 90%;
  3019. height: auto;
  3020. max-height: 102;
  3021. text-wrap: nowrap;
  3022. color: #fff;
  3023. background: rgba(0, 0, 0, 0.6);
  3024. font-weight: bolder;
  3025. padding: 10px;
  3026. border-radius: 5px;
  3027. box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
  3028. border: 2px solid rgba(255, 255, 255, 0.5);
  3029. z-index: 999999;
  3030. `);
  3031. document.body.appendChild(performanceElement);
  3032. performanceElement.style.display = 'none';
  3033. //initiate first use div and css and shit
  3034. firstUseElement = document.createElement('div'); // create the element directly
  3035. firstUseElement.classList.add('firstuse');
  3036. firstUseElement.setAttribute('style', `
  3037. position: fixed;
  3038. top: 0;
  3039. left: 0;
  3040. width: 100%;
  3041. height: 100%;
  3042. background-color: rgba(0, 0, 0, 0.8);
  3043. z-index: 99999999;
  3044. display: flex;
  3045. justify-content: center;
  3046. align-items: center;
  3047. `);
  3048. document.body.appendChild(firstUseElement);
  3049. firstUseElement.style.display = 'none';
  3050. //initiate bloom indicator div and css and shit
  3051. redCircle = document.createElement('div');
  3052. redCircle.style.position = 'fixed';
  3053. redCircle.style.width = '5px';
  3054. redCircle.style.height = '5px';
  3055. redCircle.style.borderRadius = '50%';
  3056. redCircle.style.backgroundColor = 'red';
  3057. redCircle.style.transform = 'translate(-50%, -50%)';
  3058. document.body.appendChild(redCircle);
  3059. //initiate minangle indicator div and css and shit
  3060. minangleCircle = document.createElement('div');
  3061. minangleCircle.style.position = 'fixed';
  3062. minangleCircle.style.borderRadius = '100%';
  3063. minangleCircle.style.border = 'thin solid red'
  3064. minangleCircle.style.transform = 'translate(50%, 50%)';
  3065. minangleCircle.style.pointerEvents = 'none';
  3066. document.body.appendChild(minangleCircle);
  3067.  
  3068. try {
  3069. hudElementPositions = load("HUD-Positions");
  3070.  
  3071. coordElement.style.top = hudElementPositions.coordElement.top + "px";
  3072. gameInfoElement.style.top = hudElementPositions.gameInfoElement.top + "px";
  3073. playerstatsElement.style.top = hudElementPositions.playerstatsElement.top + "px";
  3074. playerinfoElement.style.top = hudElementPositions.playerinfoElement.top + "px";
  3075. performanceElement.style.top = hudElementPositions.performanceElement.top + "px";
  3076.  
  3077. coordElement.style.left = hudElementPositions.coordElement.left + "px";
  3078. gameInfoElement.style.left = hudElementPositions.gameInfoElement.left + "px";
  3079. playerstatsElement.style.left = hudElementPositions.playerstatsElement.left + "px";
  3080. playerinfoElement.style.left = hudElementPositions.playerinfoElement.left + "px";
  3081. performanceElement.style.left = hudElementPositions.performanceElement.left + "px";
  3082. } catch (error) {
  3083. console.error(error);
  3084. hudElementPositions = {};
  3085.  
  3086. hudElementPositions.coordElement = { top: coordElement.getBoundingClientRect().top, left: coordElement.getBoundingClientRect().left };
  3087. hudElementPositions.gameInfoElement = { top: gameInfoElement.getBoundingClientRect().top, left: gameInfoElement.getBoundingClientRect().left };
  3088. hudElementPositions.playerstatsElement = { top: playerstatsElement.getBoundingClientRect().top, left: playerstatsElement.getBoundingClientRect().left };
  3089. hudElementPositions.playerinfoElement = { top: playerinfoElement.getBoundingClientRect().top, left: playerinfoElement.getBoundingClientRect().left };
  3090. hudElementPositions.performanceElement = { top: performanceElement.getBoundingClientRect().top, left: performanceElement.getBoundingClientRect().left };
  3091. save("HUD-Positions", hudElementPositions);
  3092. };
  3093. };
  3094.  
  3095. const makeDraggable = function (element, notMenu) {
  3096. if (element) {
  3097. let offsetX, offsetY;
  3098. element.addEventListener('mousedown', function (e) {
  3099. const dragElement = function (e) {
  3100. const x = (e.clientX - offsetX) / unsafeWindow.innerWidth * 100;
  3101. const y = (e.clientY - offsetY) / unsafeWindow.innerHeight * 100;
  3102. const maxX = 100 - (element.offsetWidth / unsafeWindow.innerWidth * 100);
  3103. const maxY = 100 - (element.offsetHeight / unsafeWindow.innerHeight * 100);
  3104. element.style.left = `${Math.max(0, Math.min(x, maxX))}%`;
  3105. element.style.top = `${Math.max(0, Math.min(y, maxY))}%`;
  3106. };
  3107. if (notMenu || e.target.classList.contains('tp-rotv_t')) {
  3108. offsetX = e.clientX - element.getBoundingClientRect().left;
  3109. offsetY = e.clientY - element.getBoundingClientRect().top;
  3110. document.addEventListener('mousemove', dragElement);
  3111. document.addEventListener('mouseup', function () {
  3112. document.removeEventListener('mousemove', dragElement);
  3113. });
  3114. e.preventDefault(); // Prevent text selection during drag
  3115. };
  3116. });
  3117. };
  3118. };
  3119.  
  3120. const makeHudElementDragable = function (element) {
  3121. if (element.getAttribute("drag-true") != "true") {
  3122. element.addEventListener("mousedown", function (e) {
  3123. let offsetX = e.clientX - parseInt(window.getComputedStyle(this).left);
  3124. let offsetY = e.clientY - parseInt(window.getComputedStyle(this).top);
  3125.  
  3126. function mouseMoveHandler(e) {
  3127. let newX = e.clientX - offsetX;
  3128. let newY = e.clientY - offsetY;
  3129. if (newX >= 0 && newX + element.getBoundingClientRect().width <= window.innerWidth) {
  3130. element.style.left = newX + "px";
  3131. };
  3132. if (newY >= 0 && newY + element.getBoundingClientRect().height <= window.innerHeight) {
  3133. element.style.top = newY + "px";
  3134. };
  3135. };
  3136.  
  3137. function reset() {
  3138. window.removeEventListener("mousemove", mouseMoveHandler);
  3139. window.removeEventListener("mouseup", reset);
  3140.  
  3141. //saves new positions
  3142. hudElementPositions.coordElement = { "top": coordElement.getBoundingClientRect().top, "left": coordElement.getBoundingClientRect().left };
  3143. hudElementPositions.gameInfoElement = { "top": gameInfoElement.getBoundingClientRect().top, "left": gameInfoElement.getBoundingClientRect().left };
  3144. hudElementPositions.playerstatsElement = { "top": playerstatsElement.getBoundingClientRect().top, "left": playerstatsElement.getBoundingClientRect().left };
  3145. hudElementPositions.playerinfoElement = { "top": playerinfoElement.getBoundingClientRect().top, "left": playerinfoElement.getBoundingClientRect().left };
  3146. hudElementPositions.performanceElement = { "top": performanceElement.getBoundingClientRect().top, "left": performanceElement.getBoundingClientRect().left };
  3147. save("HUD-Positions", hudElementPositions);
  3148. };
  3149.  
  3150. window.addEventListener("mousemove", mouseMoveHandler);
  3151. window.addEventListener("mouseup", reset);
  3152. });
  3153.  
  3154. element.setAttribute("drag-true", "true");
  3155. };
  3156. };
  3157.  
  3158. const applyTheme = function (setTheme) {
  3159. setTheme = (setTheme || extract("themeType") || "defaultTheme");
  3160. let rootTheme
  3161. switch (setTheme) {
  3162. case ("defaultTheme"):
  3163. rootTheme = `
  3164. --tp-base-background-color: hsla(230, 7%, 17%, 1.00);
  3165. --tp-base-shadow-color: hsla(0, 0%, 0%, 0.2);
  3166. --tp-button-background-color: hsla(230, 7%, 70%, 1.00);
  3167. --tp-button-background-color-active: hsla(230, 7%, 85%, 1.00);
  3168. --tp-button-background-color-focus: hsla(230, 7%, 80%, 1.00);
  3169. --tp-button-background-color-hover: hsla(230, 7%, 75%, 1.00);
  3170. --tp-button-foreground-color: hsla(230, 7%, 17%, 1.00);
  3171. --tp-container-background-color: hsla(230, 7%, 75%, 0.10);
  3172. --tp-container-background-color-active: hsla(230, 7%, 75%, 0.25);
  3173. --tp-container-background-color-focus: hsla(230, 7%, 75%, 0.20);
  3174. --tp-container-background-color-hover: hsla(230, 7%, 75%, 0.15);
  3175. --tp-container-foreground-color: hsla(230, 7%, 75%, 1.00);
  3176. --tp-groove-foreground-color: hsla(230, 7%, 75%, 0.10);
  3177. --tp-input-background-color: hsla(230, 7%, 75%, 0.10);
  3178. --tp-input-background-color-active: hsla(230, 7%, 75%, 0.25);
  3179. --tp-input-background-color-focus: hsla(230, 7%, 75%, 0.20);
  3180. --tp-input-background-color-hover: hsla(230, 7%, 75%, 0.15);
  3181. --tp-input-foreground-color: hsla(230, 7%, 75%, 1.00);
  3182. --tp-label-foreground-color: hsla(230, 7%, 75%, 0.70);
  3183. --tp-monitor-background-color: hsla(230, 7%, 0%, 0.20);
  3184. --tp-monitor-foreground-color: hsla(230, 7%, 75%, 0.70);`; break;
  3185. case ("icebergTheme"):
  3186. rootTheme = `
  3187. --tp-base-background-color: hsla(230, 20%, 11%, 1.00);
  3188. --tp-base-shadow-color: hsla(0, 0%, 0%, 0.2);
  3189. --tp-button-background-color: hsla(230, 10%, 80%, 1.00);
  3190. --tp-button-background-color-active: hsla(230, 10%, 95%, 1.00);
  3191. --tp-button-background-color-focus: hsla(230, 10%, 90%, 1.00);
  3192. --tp-button-background-color-hover: hsla(230, 10%, 85%, 1.00);
  3193. --tp-button-foreground-color: hsla(230, 20%, 11%, 1);
  3194. --tp-container-background-color: hsla(230, 25%, 16%, 1.00);
  3195. --tp-container-background-color-active: hsla(230, 25%, 31%, 1.00);
  3196. --tp-container-background-color-focus: hsla(230, 25%, 26%, 1.00);
  3197. --tp-container-background-color-hover: hsla(230, 25%, 21%, 1.00);
  3198. --tp-container-foreground-color: hsla(230, 10%, 80%, 1.00);
  3199. --tp-groove-foreground-color: hsla(230, 20%, 8%, 1.00);
  3200. --tp-input-background-color: hsla(230, 20%, 8%, 1.00);
  3201. --tp-input-background-color-active: hsla(230, 28%, 23%, 1.00);
  3202. --tp-input-background-color-focus: hsla(230, 28%, 18%, 1.00);
  3203. --tp-input-background-color-hover: hsla(230, 20%, 13%, 1.00);
  3204. --tp-input-foreground-color: hsla(230, 10%, 80%, 1.00);
  3205. --tp-label-foreground-color: hsla(230, 12%, 48%, 1.00);
  3206. --tp-monitor-background-color: hsla(230, 20%, 8%, 1.00);
  3207. --tp-monitor-foreground-color: hsla(230, 12%, 48%, 1.00);`; break;
  3208. case ("jetblackTheme"):
  3209. rootTheme = `
  3210. --tp-base-background-color: hsla(0, 0%, 0%, 1.00);
  3211. --tp-base-shadow-color: hsla(0, 0%, 0%, 0.2);
  3212. --tp-button-background-color: hsla(0, 0%, 70%, 1.00);
  3213. --tp-button-background-color-active: hsla(0, 0%, 85%, 1);
  3214. --tp-button-background-color-focus: hsla(0, 0%, 80%, 1.00);
  3215. --tp-button-background-color-hover: hsla(0, 0%, 75%, 1.00);
  3216. --tp-button-foreground-color: hsla(0, 0%, 0%, 1.00);
  3217. --tp-container-background-color: hsla(0, 0%, 10%, 1.00);
  3218. --tp-container-background-color-active: hsla(0, 0%, 25%, 1.00);
  3219. --tp-container-background-color-focus: hsla(0, 0%, 20%, 1.00);
  3220. --tp-container-background-color-hover: hsla(0, 0%, 15%, 1.00);
  3221. --tp-container-foreground-color: hsla(0, 0%, 50%, 1.00);
  3222. --tp-groove-foreground-color: hsla(0, 0%, 10%, 1.00);
  3223. --tp-input-background-color: hsla(0, 0%, 10%, 1.00);
  3224. --tp-input-background-color-active: hsla(0, 0%, 25%, 1.00);
  3225. --tp-input-background-color-focus: hsla(0, 0%, 20%, 1.00);
  3226. --tp-input-background-color-hover: hsla(0, 0%, 15%, 1.00);
  3227. --tp-input-foreground-color: hsla(0, 0%, 70%, 1.00);
  3228. --tp-label-foreground-color: hsla(0, 0%, 50%, 1.00);
  3229. --tp-monitor-background-color: hsla(0, 0%, 8%, 1.00);
  3230. --tp-monitor-foreground-color: hsla(0, 0%, 48%, 1.00);`; break;
  3231. case ("lightTheme"):
  3232. rootTheme = `
  3233. --tp-base-background-color: hsla(230, 5%, 90%, 1.00);
  3234. --tp-base-shadow-color: hsla(0, 0%, 0%, 0.10);
  3235. --tp-button-background-color: hsla(230, 7%, 75%, 1.00);
  3236. --tp-button-background-color-active: hsla(230, 7%, 60%, 1.00);
  3237. --tp-button-background-color-focus: hsla(230, 7%, 65%, 1.00);
  3238. --tp-button-background-color-hover: hsla(230, 7%, 70%, 1.00);
  3239. --tp-button-foreground-color: hsla(230, 10%, 30%, 1.00);
  3240. --tp-container-background-color: hsla(230, 15%, 30%, 0.20);
  3241. --tp-container-background-color-active: hsla(230, 15%, 30%, 0.32);
  3242. --tp-container-background-color-focus: hsla(230, 15%, 30%, 0.28);
  3243. --tp-container-background-color-hover: hsla(230, 15%, 30%, 0.24);
  3244. --tp-container-foreground-color: hsla(230, 10%, 30%, 1.00);
  3245. --tp-groove-foreground-color: hsla(230, 15%, 30%, 0.10);
  3246. --tp-input-background-color: hsla(230, 15%, 30%, 0.10);
  3247. --tp-input-background-color-active: hsla(230, 15%, 30%, 0.22);
  3248. --tp-input-background-color-focus: hsla(230, 15%, 30%, 0.18);
  3249. --tp-input-background-color-hover: hsla(230, 15%, 30%, 0.14);
  3250. --tp-input-foreground-color: hsla(230, 10%, 30%, 1.00);
  3251. --tp-label-foreground-color: hsla(230, 10%, 30%, 0.70);
  3252. --tp-monitor-background-color: hsla(230, 15%, 30%, 0.10);
  3253. --tp-monitor-foreground-color: hsla(230, 10%, 30%, 0.50);`; break;
  3254. case ("retroTheme"):
  3255. rootTheme = `
  3256. --tp-base-background-color: hsla(40, 3%, 90%, 1.00);
  3257. --tp-base-shadow-color: hsla(0, 0%, 0%, 0.30);
  3258. --tp-button-background-color: hsla(40, 3%, 70%, 1.00);
  3259. --tp-button-background-color-active: hsla(40, 3%, 55%, 1.00);
  3260. --tp-button-background-color-focus: hsla(40, 3%, 60%, 1.00);
  3261. --tp-button-background-color-hover: hsla(40, 3%, 65%, 1.00);
  3262. --tp-button-foreground-color: hsla(40, 3%, 20%, 1.00);
  3263. --tp-container-background-color: hsla(40, 3%, 70%, 1.00);
  3264. --tp-container-background-color-active: hsla(40, 3%, 55%, 1.00);
  3265. --tp-container-background-color-focus: hsla(40, 3%, 60%, 1.00);
  3266. --tp-container-background-color-hover: hsla(40, 3%, 65%, 1.00);
  3267. --tp-container-foreground-color: hsla(40, 3%, 20%, 1.00);
  3268. --tp-groove-foreground-color: hsla(40, 3%, 40%, 1.00);
  3269. --tp-input-background-color: hsla(120, 3%, 20%, 1.00);
  3270. --tp-input-background-color-active: hsla(120, 3%, 35%, 1.00);
  3271. --tp-input-background-color-focus: hsla(120, 3%, 30%, 1.00);
  3272. --tp-input-background-color-hover: hsla(120, 3%, 25%, 1.00);
  3273. --tp-input-foreground-color: hsla(120, 40%, 60%, 1.00);
  3274. --tp-label-foreground-color: hsla(40, 3%, 50%, 1.00);
  3275. --tp-monitor-background-color: hsla(120, 3%, 20%, 1.00);
  3276. --tp-monitor-foreground-color: hsla(120, 40%, 60%, 0.80);`; break;
  3277. case ("translucentTheme"):
  3278. rootTheme = `
  3279. --tp-base-background-color: hsla(0, 0%, 10%, 0.80);
  3280. --tp-base-shadow-color: hsla(0, 0%, 0%, 0.20);
  3281. --tp-button-background-color: hsla(0, 0%, 80%, 1.00);
  3282. --tp-button-background-color-active: hsla(0, 0%, 100%, 1.00);
  3283. --tp-button-background-color-focus: hsla(0, 0%, 95%, 1.00);
  3284. --tp-button-background-color-hover: hsla(0, 0%, 85%, 1.00);
  3285. --tp-button-foreground-color: hsla(0, 0%, 0%, 0.80);
  3286. --tp-container-background-color: hsla(0, 0%, 0%, 0.30);
  3287. --tp-container-background-color-active: hsla(0, 0%, 0%, 0.60);
  3288. --tp-container-background-color-focus: hsla(0, 0%, 0%, 0.50);
  3289. --tp-container-background-color-hover: hsla(0, 0%, 0%, 0.40);
  3290. --tp-container-foreground-color: hsla(0, 0%, 100%, 0.50);
  3291. --tp-groove-foreground-color: hsla(0, 0%, 0%, 0.20);
  3292. --tp-input-background-color: hsla(0, 0%, 0%, 0.30);
  3293. --tp-input-background-color-active: hsla(0, 0%, 0%, 0.60);
  3294. --tp-input-background-color-focus: hsla(0, 0%, 0%, 0.50);
  3295. --tp-input-background-color-hover: hsla(0, 0%, 0%, 0.40);
  3296. --tp-input-foreground-color: hsla(0, 0%, 100%, 0.50);
  3297. --tp-label-foreground-color: hsla(0, 0%, 100%, 0.50);
  3298. --tp-monitor-background-color: hsla(0, 0%, 0%, 0.30);
  3299. --tp-monitor-foreground-color: hsla(0, 0%, 100%, 0.30);`; break;
  3300. case ("statefarmerTheme"):
  3301. rootTheme = `
  3302. --tp-base-background-color: hsla(0, 80%, 40%, 1.00);
  3303. --tp-base-shadow-color: hsla(0, 0%, 0%, 0.2);
  3304. --tp-button-background-color: hsla(0, 0%, 100%, 1.00);
  3305. --tp-button-background-color-active: hsla(0, 0%, 85%, 1.00);
  3306. --tp-button-background-color-focus: hsla(0, 0%, 90%, 1.00);
  3307. --tp-button-background-color-hover: hsla(0, 0%, 95%, 1.00);
  3308. --tp-button-foreground-color: hsla(230, 20%, 11%, 1.00);
  3309. --tp-container-background-color: hsla(0, 0%, 0%, 0.20);
  3310. --tp-container-background-color-active: hsla(0, 0%, 0%, 0.35);
  3311. --tp-container-background-color-focus: hsla(0, 0%, 0%, 0.30);
  3312. --tp-container-background-color-hover: hsla(0, 0%, 0%, 0.25);
  3313. --tp-container-foreground-color: hsla(0, 0%, 100%, 0.90);
  3314. --tp-groove-foreground-color: hsla(0, 0%, 0%, 0.50);
  3315. --tp-input-background-color: hsla(0, 0%, 0%, 0.50);
  3316. --tp-input-background-color-active: hsla(0, 0%, 0%, 0.65);
  3317. --tp-input-background-color-focus: hsla(0, 0%, 0%, 0.60);
  3318. --tp-input-background-color-hover: hsla(0, 0%, 0%, 0.55);
  3319. --tp-input-foreground-color: hsla(0, 0%, 100%, 0.90);
  3320. --tp-label-foreground-color: hsla(0, 0%, 100%, 0.90);
  3321. --tp-monitor-background-color: hsla(0, 0%, 0%, 0.50);
  3322. --tp-monitor-foreground-color: hsla(0, 0%, 100%, 0.50);`; break;
  3323. case ("blurpleTheme"):
  3324. rootTheme = `
  3325. --tp-base-background-color: hsla(255, 68%, 39%, 1.00);
  3326. --tp-base-shadow-color: hsla(0, 0%, 0%, 0.2);
  3327. --tp-button-background-color: hsla(0, 0%, 100%, 1.00);
  3328. --tp-button-background-color-active: hsla(0, 0%, 85%, 1.00);
  3329. --tp-button-background-color-focus: hsla(0, 0%, 90%, 1.00);
  3330. --tp-button-background-color-hover: hsla(0, 0%, 95%, 1.00);
  3331. --tp-button-foreground-color: hsla(230, 20%, 11%, 1.00);
  3332. --tp-container-background-color: hsla(0, 0%, 0%, 0.20);
  3333. --tp-container-background-color-active: hsla(0, 0%, 0%, 0.35);
  3334. --tp-container-background-color-focus: hsla(0, 0%, 0%, 0.30);
  3335. --tp-container-background-color-hover: hsla(0, 0%, 0%, 0.25);
  3336. --tp-container-foreground-color: hsla(0, 0%, 100%, 0.90);
  3337. --tp-groove-foreground-color: hsla(0, 0%, 0%, 0.50);
  3338. --tp-input-background-color: hsla(0, 0%, 0%, 0.50);
  3339. --tp-input-background-color-active: hsla(0, 0%, 0%, 0.65);
  3340. --tp-input-background-color-focus: hsla(0, 0%, 0%, 0.60);
  3341. --tp-input-background-color-hover: hsla(0, 0%, 0%, 0.55);
  3342. --tp-input-foreground-color: hsla(0, 0%, 100%, 0.90);
  3343. --tp-label-foreground-color: hsla(0, 0%, 100%, 0.90);
  3344. --tp-monitor-background-color: hsla(0, 0%, 0%, 0.50);
  3345. --tp-monitor-foreground-color: hsla(0, 0%, 100%, 0.50);`; break;
  3346. case ("shellFarmTheme"):
  3347. rootTheme = `
  3348. --tp-base-background-color: hsla(198, 100%, 50%, 1.00);
  3349. --tp-base-shadow-color: hsla(0, 0%, 0%, 0.2);
  3350. --tp-button-background-color: hsla(0, 0%, 100%, 1.00);
  3351. --tp-button-background-color-active: hsla(0, 0%, 85%, 1.00);
  3352. --tp-button-background-color-focus: hsla(0, 0%, 90%, 1.00);
  3353. --tp-button-background-color-hover: hsla(0, 0%, 95%, 1.00);
  3354. --tp-button-foreground-color: hsla(230, 20%, 11%, 1.00);
  3355. --tp-container-background-color: hsla(0, 0%, 0%, 0.20);
  3356. --tp-container-background-color-active: hsla(0, 0%, 0%, 0.35);
  3357. --tp-container-background-color-focus: hsla(0, 0%, 0%, 0.30);
  3358. --tp-container-background-color-hover: hsla(0, 0%, 0%, 0.25);
  3359. --tp-container-foreground-color: hsla(0, 0%, 100%, 0.90);
  3360. --tp-groove-foreground-color: hsla(0, 0%, 0%, 0.50);
  3361. --tp-input-background-color: hsla(0, 0%, 0%, 0.50);
  3362. --tp-input-background-color-active: hsla(0, 0%, 0%, 0.65);
  3363. --tp-input-background-color-focus: hsla(0, 0%, 0%, 0.60);
  3364. --tp-input-background-color-hover: hsla(0, 0%, 0%, 0.55);
  3365. --tp-input-foreground-color: hsla(0, 0%, 100%, 0.90);
  3366. --tp-label-foreground-color: hsla(0, 0%, 100%, 0.90);
  3367. --tp-monitor-background-color: hsla(0, 0%, 0%, 0.50);
  3368. --tp-monitor-foreground-color: hsla(0, 0%, 100%, 0.50);`; break;
  3369. };
  3370.  
  3371. //menu customisation (apply font, button widths, adjust checkbox right slightly, make menu appear on top, add anim to message)
  3372. const styleElement = document.createElement('style');
  3373. styleElement.textContent = `
  3374. :root { ${rootTheme} }
  3375. `;
  3376. document.head.appendChild(styleElement);
  3377. };
  3378. const temp = document.createElement('div');
  3379. temp.innerHTML = `
  3380. <style>
  3381. .notif {
  3382. position: absolute;
  3383. border: 5px solid lightblue;
  3384. left: 70%;
  3385. top: 85%;
  3386. transform: translate(-50%, -50%);
  3387. display: flex;
  3388. align-items: center;
  3389. justify-content: center;
  3390. color: #fff;
  3391. text-align: center;
  3392. background: rgba(0, 0, 0, 0.6);
  3393. font-weight: bolder;
  3394. padding: 15px;
  3395. z-index: 999999;
  3396. border-radius: 2vw;
  3397. overflow: auto;
  3398. resize: both;
  3399. backdrop-filter: blur(4px);
  3400. overflow: hidden;
  3401. min-width: 10vw;
  3402. min-height: 4vh;
  3403. pointer-events: none;
  3404. }
  3405. .MiniMap {
  3406. position: absolute;
  3407. left: 50%;
  3408. top: 50%;
  3409. transform: translate(-50%, -50%);
  3410. width: 1000px;
  3411. height:1000px;
  3412. display: flex;
  3413. align-items: center;
  3414. justify-content: center;
  3415. color: #fff;
  3416. text-align: center;
  3417. background: rgba(0, 0, 0, 0);
  3418. font-weight: bolder;
  3419. padding: 15px;
  3420. z-index: 999999;
  3421. border-radius: 2vw;
  3422. overflow: auto;
  3423. overflow: hidden;
  3424. pointer-events: none;
  3425. }
  3426. .playerDot {
  3427. position: absolute;
  3428. width: 0;
  3429. height: 0;
  3430. border-left: 10px solid transparent;
  3431. border-right: 10px solid transparent;
  3432. border-bottom: 20px solid green;
  3433. color: white;
  3434. transform: translate(-50%, -50%);
  3435. z-index: 999999;
  3436. }
  3437. </style>
  3438. <div id = "minimap" class="MiniMap"></div>
  3439. <div id = "playerDot" class="playerDot">playerdot</div>
  3440. `;
  3441. const mapEl = temp.querySelector('.MiniMap');
  3442. let myPlayerDot = temp.querySelector('.playerDot');
  3443. const playerDotsMap = new Map();
  3444. window.addEventListener('DOMContentLoaded', async function () {
  3445. while (temp.children.length > 0) {
  3446. document.body.appendChild(temp.children[0]);
  3447. }
  3448. });
  3449. function updateRadar(player, myPlayer) {
  3450. const windowWidth = window.innerWidth;
  3451. const windowHeight = window.innerHeight;
  3452. // Check if a player dot with the unique ID already exists, then do flow of control
  3453. let xPosition = (player[H.x] / 100) * windowWidth; xPosition += (windowWidth + xPosition) / 2;
  3454. let yPosition = (player[H.z] / 100) * windowHeight; yPosition += (windowHeight + yPosition) / 2;
  3455. if (!player[H.playing] || !player) {
  3456. if (playerDotsMap.has(player[H.uniqueId])) {
  3457. const playerDotToRemove = playerDotsMap.get(player[H.uniqueId]);
  3458. mapEl.removeChild(playerDotToRemove); // Remove the dot from the DOM
  3459. playerDotsMap.delete(player[H.uniqueId]); // Remove the dot from the map
  3460. };
  3461. } else if (player === myPlayer) {
  3462. myPlayerDot.style.left = `${xPosition}px`;
  3463. myPlayerDot.style.top = `${yPosition}px`;
  3464. myPlayerDot.textContent = myPlayer.name;
  3465. myPlayerDot.style.transform = 'translate(-50%, -50%) rotate(' + yawToDeg(player[H.yaw]) + 'deg)';
  3466. } else if (playerDotsMap.has(player[H.uniqueId])) {
  3467. // If it exists, update its position
  3468. const existingPlayerDot = playerDotsMap.get(player[H.uniqueId]);
  3469. existingPlayerDot.style.left = `${xPosition}px`;
  3470. existingPlayerDot.style.top = `${yPosition}px`;
  3471. //existingPlayerDot.style.transform = 'translate(-50%, -50%) rotate(' + yawToDeg(player[H.yaw]) + 'deg)'; // could uncomment but then names unreadable,
  3472. } else {
  3473. // If it doesn't exist, create a new player dot element
  3474. const newPlayerDot = document.createElement('div');
  3475. newPlayerDot.className = 'playerDot';
  3476. newPlayerDot.style.border = player.team === 1 ? '5px solid blue' : '5px solid red';
  3477.  
  3478. newPlayerDot.style.left = `${xPosition}px`;
  3479. newPlayerDot.style.top = `${yPosition}px`;
  3480. newPlayerDot.textContent = player.name;
  3481. // append to the MiniMap element, for later purposes once we can set inside the element instead
  3482. mapEl.appendChild(newPlayerDot);
  3483.  
  3484. // Store in the Map
  3485. playerDotsMap.set(player[H.uniqueId], newPlayerDot);
  3486. };
  3487. };
  3488. function yawToDeg(yaw) {
  3489. let yaw_degrees = yaw * 180.0 / Math.PI; // conversion to degrees
  3490. if (yaw_degrees < 0) yaw_degrees += 360.0; // convert negative to positive angles
  3491. return yaw_degrees;
  3492. };
  3493. const hslToRgb = function(h, s, l) {
  3494. var r, g, b;
  3495. if (s === 0) {
  3496. r = g = b = l;
  3497. } else {
  3498. function hue2rgb(p, q, t) {
  3499. if (t < 0) t += 1;
  3500. if (t > 1) t -= 1;
  3501. if (t < 1 / 6) return p + (q - p) * 6 * t;
  3502. if (t < 1 / 2) return q;
  3503. if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
  3504. return p;
  3505. };
  3506. var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
  3507. var p = 2 * l - q;
  3508. r = hue2rgb(p, q, h + 1 / 3);
  3509. g = hue2rgb(p, q, h);
  3510. b = hue2rgb(p, q, h - 1 / 3);
  3511. };
  3512. return new L.BABYLON.Color3(r, g, b);
  3513. };
  3514. /**
  3515. *
  3516. * @param {String} colorSelectName name of the color module. Will be used for extract. EG. aimbotColor
  3517. * @param {String} isRainbowName name of the rainbow checkbox mod. Will be used for extract.
  3518. */
  3519. const getColor = function (colorSelectName, isRainbowName) {
  3520. //non rainbow
  3521. if (!extract(isRainbowName)) return extract(colorSelectName);
  3522. //rainbow
  3523. const time = Date.now();
  3524. const r = (time % 1000) / 1000;
  3525. const g = (time % 2000) / 2000;
  3526. const b = (time % 3000) / 3000;
  3527. const rS = time % 2000 < 1000 ? 1 - r : r;
  3528. const gS = time % 4000 < 2000 ? 1 - g : g;
  3529. const bS = time % 6000 < 3000 ? 1 - b : b;
  3530. const rF = Math.round(rS * 255);
  3531. const gF = Math.round(gS * 255);
  3532. const bF = Math.round(bS * 255);
  3533. //hacky bc it's prob gonna get converted back to rgb but not gonna rewrite color code................................
  3534. const componentToHex = (c) => {
  3535. var hex = c.toString(16);
  3536. return hex.length == 1 ? "0" + hex : hex;
  3537. };
  3538. const rgbToHex = (r, g, b) => {
  3539. return "#" + componentToHex(r) + componentToHex(g) + componentToHex(b);
  3540. };
  3541. return rgbToHex(rF, gF, bF);
  3542. };
  3543. const applyStateFarmLogo = function () {
  3544. if (extract("replaceLogo")) {
  3545. const images = document.getElementsByTagName('img');
  3546. let imgURL = replacementLogoURL;
  3547. const month = new Date().getMonth();
  3548. if (replacementLogoHalloweenURL && replacementLogoHalloweenURL !== "" && month == 9) imgURL = replacementLogoHalloweenURL;
  3549. if (replacementLogoChristmasURL && replacementLogoChristmasURL !== "" && month == 11) imgURL = replacementLogoChristmasURL;
  3550. if (replacementLogoNewYearsURL && replacementLogoNewYearsURL !== "" && month == 0) imgURL = replacementLogoNewYearsURL;
  3551.  
  3552. for (let i = 0; i < images.length; i++) {
  3553. const src = images[i].getAttribute('src');
  3554. if (src && src.includes('img/logo.svg')) {
  3555. images[i].setAttribute('src', imgURL);
  3556. };
  3557. };
  3558. const logoDiv = document.getElementById('logo');
  3559. if (logoDiv) {
  3560. const logoImg = logoDiv.querySelector('img');
  3561. if (logoImg) {
  3562. logoImg.setAttribute('src', imgURL);
  3563. logoImg.setAttribute('width', 300);
  3564. logoImg.setAttribute('height', 104);
  3565. };
  3566. };
  3567. };
  3568. };
  3569. //1337 H4X
  3570. const getSearchParam = function (param) {
  3571. const queryParams = new URLSearchParams(unsafeWindow.location.search);
  3572. return queryParams.get(param);
  3573. };
  3574. const fetchTextContent = function (url) {
  3575. try {
  3576. var xhr = new XMLHttpRequest();
  3577. xhr.open('GET', url, false);
  3578. xhr.send();
  3579. if (xhr.status === 200) {
  3580. return xhr.responseText;
  3581. } else {
  3582. console.error("Error fetching " + url);
  3583. return null;
  3584. };
  3585. } catch (err) {
  3586. return null
  3587. };
  3588. };
  3589. const findKeyByValue = function (obj, value) {
  3590. for (const key in obj) {
  3591. if (obj[key] === value) {
  3592. return key;
  3593. };
  3594. };
  3595. return null; // Return null if the value is not found
  3596. };
  3597. const newProxy = function () {
  3598. unsafeWindow.location.replace(unsafeWindow.location.href.replace(unsafeWindow.location.hostname, proxyList[3]));
  3599. };
  3600. const unban = function () {
  3601. log("STATEFARM UNBANNING...");
  3602. updateAccountRecords();
  3603. unsafeWindow.extern.signOut();
  3604. accountStatus = "logged out";
  3605. setTimeout(() => {
  3606. const banPopup = document.getElementById("bannedPopup");
  3607. if (banPopup) { banPopup.style.display = 'none' }; //hide it
  3608. }, 10000);
  3609. };
  3610. const reloadPage = function () {
  3611. unsafeWindow.location.reload(true);
  3612. };
  3613. const spamReport = function () {
  3614. (async function () {
  3615. const sleep = function (ms) {
  3616. return new Promise(resolve => setTimeout(resolve, ms));
  3617. };
  3618. let playerList = document.getElementById("playerList").children;
  3619. for (let i = 0; i < playerList.length; i++) {
  3620. playerList[i].click();
  3621. await sleep(400);
  3622. document.getElementsByClassName("ss_button btn_medium btn_red bevel_red")[0].click();
  3623. await sleep(400);
  3624. document.getElementsByClassName("ss_checkbox label")[randomInt(0, 3)].click();
  3625. await sleep(400);
  3626. document.getElementsByClassName("ss_button btn_medium btn_green bevel_green")[0].click();
  3627. await sleep(400);
  3628. document.getElementById("genericPopup").children[2].children[1].click();
  3629. };
  3630. })();
  3631. };
  3632.  
  3633. const broadcastToBots = function (command) {
  3634. const commandTime = Date.now();
  3635. log("StateFarm: sending command to bots:", command, "| at time:", commandTime);
  3636. GM_setValue("StateFarm_Command", command);
  3637. GM_setValue("StateFarm_CommandTime", commandTime);
  3638. };
  3639.  
  3640. const hexToRgb = function (hex) {
  3641. hex = hex.replace(/^#/, '');
  3642. const bigint = parseInt(hex, 16);
  3643. const r = (bigint >> 16) & 255;
  3644. const g = (bigint >> 8) & 255;
  3645. const b = bigint & 255;
  3646. return [r / 255, g / 255, b / 255];
  3647. };
  3648. const fadeBetweenColors = function (color1, color2, progress) {
  3649. const rgb1 = hexToRgb(color1);
  3650. const rgb2 = hexToRgb(color2);
  3651. const resultRgb = [
  3652. rgb1[0] + (rgb2[0] - rgb1[0]) * progress,
  3653. rgb1[1] + (rgb2[1] - rgb1[1]) * progress,
  3654. rgb1[2] + (rgb2[2] - rgb1[2]) * progress
  3655. ];
  3656. return resultRgb;
  3657. };
  3658. const distancePlayers = function (player, yMultiplier) {
  3659. if (player && player[H.actor] && player[H.actor][H.mesh]) {
  3660. yMultiplier = yMultiplier || 1;
  3661. let vector = getDirectionVectorFacingTarget(player);
  3662. return Math.hypot(vector.x, vector.y * yMultiplier, vector.z); //pythagoras' theorem in 3 dimensions. no one owns maths, zert.
  3663. } else log("fuck2", player); return 0;
  3664. };
  3665. const lerp = function (start, end, alpha) {
  3666. let value = (1 - alpha) * start + alpha * end;
  3667. return value;
  3668. };
  3669. const setPrecision = function (value) { return Math.round(value * 8192) / 8192 }; //required precision
  3670. const calculateYaw = function (pos) {
  3671. return setPrecision(Math.mod(Math.atan2(pos.x, pos.z), Math.PI2));
  3672. };
  3673. const calculatePitch = function (pos) {
  3674. return setPrecision(-Math.atan2(pos.y, Math.hypot(pos.x, pos.z)) % 1.5);
  3675. };
  3676. const getAngularDifference = function (obj1, obj2) { //this is super scuffed
  3677. return Math.abs(obj1[H.yaw] - obj2.yawReal) + Math.abs(obj1[H.pitch] - obj2.pitchReal);
  3678. };
  3679. const getDirectionVectorFacingTarget = function (target, vectorPassed, offsetY) {
  3680. if (vectorPassed || (target && target[H.actor] && target[H.actor][H.mesh])) { //in case of zizzy's weird error
  3681. target = vectorPassed ? target : target[H.actor][H.mesh].position;
  3682. offsetY = offsetY || 0;
  3683. return {
  3684. x: - (target.x - ss.MYPLAYER[H.actor][H.mesh].position.x),
  3685. y: - (target.y - ss.MYPLAYER[H.actor][H.mesh].position.y + offsetY),
  3686. z: - (target.z - ss.MYPLAYER[H.actor][H.mesh].position.z),
  3687. };
  3688. } else { //we really dont want this happening tho
  3689. log("fuck");
  3690. // log(vectorPassed);
  3691. // log(target);
  3692. // console.trace();
  3693. return {
  3694. x: 0,
  3695. y: 0,
  3696. z: 0,
  3697. };
  3698. };
  3699. };
  3700. const deg2rad = function (deg) {
  3701. return deg * (Math.PI / 180);
  3702. };
  3703. const reverseString = function (str) { return str.split("").reverse().join("") };
  3704. const isPartialMatch = function (array, searchString) {
  3705. return array.some(item => item !== "" && searchString.toLowerCase().includes(item.toLowerCase()));
  3706. };
  3707. const findBadgesForUsername = function(username) {
  3708. let found = [];
  3709. if (badgeList && username) {
  3710. username = username.toLowerCase().replaceAll("_","").replaceAll(" ","");
  3711. for (const [key, userList] of Object.entries(badgeList)) {
  3712. for (const user of userList) {
  3713. if (username.includes(user.toLowerCase())) {
  3714. found.push(key);
  3715. };
  3716. };
  3717. };
  3718. };
  3719. return found;
  3720. };
  3721.  
  3722. const playAudio = function (name, panner, contextName) {
  3723. contextName = findStringInLists(divertContexts, name) || "OTHER"+randomInt(1,9)
  3724. let audioContext;
  3725. audioContext = audioContexts[contextName];
  3726. let source = audioContext.createBufferSource();
  3727. source.buffer = soundsSFC[name];
  3728.  
  3729. const newPanner = audioContext.createPanner();
  3730. audioContext.listener.setPosition(0, 0, 0);
  3731.  
  3732. if (panner) {
  3733. newPanner.context.listener.setPosition(panner.context.listener.positionX.value, panner.context.listener.positionY.value, panner.context.listener.positionZ.value);
  3734. newPanner.setPosition(
  3735. panner.context.listener.positionX.value - ((panner.context.listener.positionX.value - panner.positionX.value) * extract("distanceMult")),
  3736. panner.context.listener.positionY.value - ((panner.context.listener.positionY.value - panner.positionY.value) * extract("distanceMult")),
  3737. panner.context.listener.positionZ.value - ((panner.context.listener.positionZ.value - panner.positionZ.value) * extract("distanceMult")),
  3738. );
  3739. newPanner.setOrientation(panner.orientationX.value, panner.orientationY.value, panner.orientationZ.value);
  3740. newPanner.refDistance = panner.refDistance;
  3741. newPanner.maxDistance = panner.maxDistance;
  3742. newPanner.rolloffFactor = panner.rolloffFactor;
  3743. newPanner.coneInnerAngle = panner.coneInnerAngle;
  3744. newPanner.coneOuterAngle = panner.coneOuterAngle;
  3745. newPanner.coneOuterGain = panner.coneOuterGain;
  3746. };
  3747. if (audioContext.state === 'suspended') {
  3748. audioContext.resume();
  3749. };
  3750. // log(contextName);
  3751. source.connect(newPanner);
  3752. newPanner.connect(audioContext.destination);
  3753. source.start();
  3754. };
  3755. const playerMatchesList = function (array, player) {
  3756. let nameMatched = isPartialMatch(array, player.name);
  3757. let idMatched = isPartialMatch(array, player[H.uniqueId]);
  3758. return nameMatched || idMatched;
  3759. };
  3760. const randomInt = function (min, max) {
  3761. return Math.floor(Math.random() * (max - min + 1)) + min;
  3762. };
  3763. const radianAngleDiff = function (angle1, angle2) {
  3764. const fullCircle = 2 * Math.PI;
  3765. // Normalize angles to be within [0, 2π)
  3766. angle1 = (angle1 % fullCircle + fullCircle) % fullCircle;
  3767. angle2 = (angle2 % fullCircle + fullCircle) % fullCircle;
  3768. // Find the absolute angular difference
  3769. let diff = Math.abs(angle1 - angle2);
  3770. // Ensure the difference is within [0, π)
  3771. diff = Math.min(diff, fullCircle - diff);
  3772. // Determine the sign of the difference correctly
  3773. if ((angle1 - angle2 + fullCircle) % fullCircle > Math.PI) {
  3774. return -diff;
  3775. } else {
  3776. return diff;
  3777. };
  3778. };
  3779. clientID = (getScrambled() + "noID");
  3780. const createAnonFunction = function (name, func) {
  3781. const funcName = getScrambled();
  3782. unsafeWindow[funcName] = func;
  3783. unsafeWindow[funcName] = function () {
  3784. try {
  3785. return func.apply(this, arguments);
  3786. } catch (error) {
  3787. log("Error in anonymous function:", error);
  3788. }
  3789. };
  3790.  
  3791. F[name] = unsafeWindow[funcName];
  3792. functionNames[name] = funcName
  3793. };
  3794. const processChatItem = function (text, playerName, playerTeam, highlightColor) {
  3795. let chatItem = document.createElement("div");
  3796. let playerNameSpan = document.createElement("span");
  3797. let playerInfoContainer = document.createElement("div");
  3798. let serverIcon = document.createElement("i");
  3799.  
  3800. chatItem.classList.add("chat-item");
  3801. playerInfoContainer.style.display = "inline-block";
  3802.  
  3803. playerNameSpan.classList.add("chat-player-name", "ss_marginright_xs");
  3804. playerNameSpan.textContent = playerName + " ";
  3805.  
  3806. playerInfoContainer.style.color = ss.teamColors.text[playerTeam];
  3807. playerInfoContainer.appendChild(serverIcon);
  3808. playerInfoContainer.appendChild(playerNameSpan);
  3809.  
  3810. let messageSpan = document.createElement("span");
  3811. messageSpan.innerHTML = text;
  3812. chatItem.style.fontStyle = "italic";
  3813. messageSpan.style.backgroundColor = highlightColor;
  3814. playerInfoContainer.style.backgroundColor = highlightColor;
  3815.  
  3816. chatItem.appendChild(playerInfoContainer);
  3817. chatItem.appendChild(messageSpan);
  3818.  
  3819. document.getElementById("chatOut").appendChild(chatItem);
  3820.  
  3821. if (document.querySelector(".chat-container")) {
  3822. document.querySelector(".chat-container").scrollTop = document.querySelector(".chat-container").scrollHeight;
  3823. };
  3824. };
  3825.  
  3826. var vertexVector1, vertexVector2, vertexVector3, vertexVector4, vertexVector5, vertexVector6, vertexVector7, vertexVector8;
  3827. const updateOrCreateLinesESP = function (object, type, color) {
  3828. let newPosition, newScene, newParent
  3829. if (type == "playerESP") {
  3830. newPosition = object[H.actor][H.mesh].position;
  3831. newScene = object[H.actor].scene;
  3832. newParent = object[H.actor][H.mesh];
  3833. } else if (type == "pPredESP") { //objects will be player.pred, object of BABYLON.TransformNode. https://doc.babylonjs.com/typedoc/classes/BABYLON.TransformNode
  3834. newPosition = object.getAbsolutePosition(); //we now use the TN's absolutePosition instead of an own var. It's just cleaner this way imo
  3835. newScene = object.getScene(); //getters, yummy
  3836. newParent = object; //will be the TransformNode stored in player.pred, so we can keep this as parent.
  3837. } else {
  3838. newPosition = object.position;
  3839. newScene = object._scene;
  3840. newParent = object;
  3841. };
  3842. if (!object.generatedESP) {
  3843. //tracers
  3844. const tracerLines = L.BABYLON.MeshBuilder.CreateLines("tracerLines", { points: [newPosition, crosshairsPosition] }, newScene);
  3845. tracerLines.color = new L.BABYLON.Color3(1, 1, 1);
  3846. tracerLines[H.renderingGroupId] = 1;
  3847. object.tracerLines = tracerLines;
  3848. //ESP
  3849. //FUCK WIREFRAME BOXES! LIBERTYMUTUAL dictates we making our own MANUALLY bitch! to hell with those diagonal lines
  3850. const boxSize = {
  3851. playerESP: { width: 0.5, height: 0.75, depth: 0.5 },
  3852. pPredESP: { width: 0.5, height: 0.75, depth: 0.5 },
  3853. ammoESP: { width: 0.25, height: 0.35, depth: 0.25 },
  3854. };
  3855. const boxOffset = {
  3856. playerESP: 0,
  3857. pPredESP: 0,
  3858. ammoESP: -0.05,
  3859. };
  3860. vertexVector1 = vertexVector1 || new L.BABYLON.Vector3(0, 0, 0);
  3861. vertexVector1.x = -boxSize[type].width / 2; vertexVector1.y = boxOffset[type]; vertexVector1.z = -boxSize[type].depth / 2;
  3862.  
  3863. vertexVector2 = vertexVector2 || new L.BABYLON.Vector3(0, 0, 0);
  3864. vertexVector2.x = boxSize[type].width / 2; vertexVector2.y = boxOffset[type]; vertexVector2.z = -boxSize[type].depth / 2;
  3865.  
  3866. vertexVector3 = vertexVector3 || new L.BABYLON.Vector3(0, 0, 0);
  3867. vertexVector3.x = boxSize[type].width / 2; vertexVector3.y = boxOffset[type] + boxSize[type].height; vertexVector3.z = -boxSize[type].depth / 2;
  3868.  
  3869. vertexVector4 = vertexVector4 || new L.BABYLON.Vector3(0, 0, 0);
  3870. vertexVector4.x = -boxSize[type].width / 2; vertexVector4.y = boxOffset[type] + boxSize[type].height; vertexVector4.z = -boxSize[type].depth / 2;
  3871.  
  3872. vertexVector5 = vertexVector5 || new L.BABYLON.Vector3(0, 0, 0);
  3873. vertexVector5.x = -boxSize[type].width / 2; vertexVector5.y = boxOffset[type]; vertexVector5.z = boxSize[type].depth / 2;
  3874.  
  3875. vertexVector6 = vertexVector6 || new L.BABYLON.Vector3(0, 0, 0);
  3876. vertexVector6.x = boxSize[type].width / 2; vertexVector6.y = boxOffset[type]; vertexVector6.z = boxSize[type].depth / 2;
  3877.  
  3878. vertexVector7 = vertexVector7 || new L.BABYLON.Vector3(0, 0, 0);
  3879. vertexVector7.x = boxSize[type].width / 2; vertexVector7.y = boxOffset[type] + boxSize[type].height; vertexVector7.z = boxSize[type].depth / 2;
  3880.  
  3881. vertexVector8 = vertexVector8 || new L.BABYLON.Vector3(0, 0, 0);
  3882. vertexVector8.x = -boxSize[type].width / 2; vertexVector8.y = boxOffset[type] + boxSize[type].height; vertexVector8.z = boxSize[type].depth / 2;
  3883.  
  3884. const vertices = [
  3885. vertexVector1,
  3886. vertexVector2,
  3887. vertexVector3,
  3888. vertexVector4,
  3889. vertexVector5,
  3890. vertexVector6,
  3891. vertexVector7,
  3892. vertexVector8
  3893. ];
  3894. const lines = [];
  3895. for (let i = 0; i < 4; i++) {
  3896. lines.push([vertices[i], vertices[(i + 1) % 4]]);
  3897. lines.push([vertices[i + 4], vertices[(i + 1) % 4 + 4]]);
  3898. lines.push([vertices[i], vertices[i + 4]]);
  3899. };
  3900. const box = L.BABYLON.MeshBuilder.CreateLineSystem(getScrambled(), { lines }, newScene);
  3901. box.color = new L.BABYLON.Color3(1, 1, 1);
  3902. box.position.y = boxOffset[type];
  3903. box[H.renderingGroupId] = 1;
  3904. box.parent = newParent;
  3905. object.box = box;
  3906. /*
  3907. //TARGETS
  3908. let target;
  3909. if (type == "playerESP") {
  3910. target = L.BABYLON.MeshBuilder.CreateSphere(getScrambled(), { diameter: 0.05 }, newScene);
  3911. target.material = new L.BABYLON.StandardMaterial(getScrambled(), newScene);
  3912. target.material.diffuseColor = new L.BABYLON.Color3(1, 0, 0);
  3913. target.material.alpha = 0.5;
  3914. target.position.y = 0.3;
  3915. target[H.renderingGroupId] = 1;
  3916. target.parent = newParent;
  3917. object.target = target;
  3918. };
  3919. */
  3920. /*---fwltv2---*/
  3921. if (type == "playerESP"){
  3922. //create line. other shit later
  3923. const l = L.BABYLON.MeshBuilder.CreateLines(getScrambled(),{points: [new L.BABYLON.Vector3(0, 0, 0),new L.BABYLON.Vector3(0, 0, 0)]}, newScene); //empty lines. will be edited l8er
  3924. //l[H.renderingGroupId] = 1;
  3925.  
  3926. object.lookDirLine = l;
  3927. //line will be updated every call, not just creation. I hate this but fuck you
  3928. }
  3929. /*----------------------*/
  3930. //stuff
  3931. object.generatedESP = true;
  3932. ESPArray.push([object, tracerLines, box, object.lookDirLine]); //, target
  3933. };
  3934. if (object.lookDirLine && (extract("lookTracers") || extract("aimbotTargetMode") === "aimingAt")){ //no need to update if module disabled. Raycasts aren't the best thing to run every frame without any use...
  3935. const TRACE_LENGTH_MULTIPLIER = 75; //how long is the trace max?
  3936. const playerEye = object[H.actor].eye; // BABYLON.TransformNode (https://doc.babylonjs.com/typedoc/classes/BABYLON.TransformNode). TN of the "eye", as shell calls it. Basically camera pos.
  3937.  
  3938. let conclusion /*:trol:*/ = playerEye.forward.clone(); // BABYLON.Vector3 (https://doc.babylonjs.com/typedoc/classes/BABYLON.Vector3). this vector is NORMALIZED
  3939. conclusion= conclusion.scale(TRACE_LENGTH_MULTIPLIER); //scale by the multiplier to extend the normalized vector. TODO: make multiplier customizable by USER
  3940. conclusion= conclusion.add(playerEye.absolutePosition); //add pos so we are relative to eye
  3941.  
  3942. //RAYCAST
  3943. const rayToGround = ss.RAYS[H.rayCollidesWithMap](object[H.actor].eye.absolutePosition, conclusion, ss.RAYS.grenadeCollidesWithCell); //does player look at object, if yes, where?
  3944. const g = playerEye.absolutePosition; //easier access
  3945. // console.log("RAYCAST", g, g.x, g._x)
  3946. if(rayToGround){
  3947. object.lookDirLine.setVerticesData(L.BABYLON.VertexBuffer.PositionKind, [g.x, g.y, g.z, rayToGround.pick.pickedPoint.x, rayToGround.pick.pickedPoint.y, rayToGround.pick.pickedPoint.z]);
  3948. //set line to correct points, with the map collision as endpoint
  3949. }
  3950. if(!rayToGround){
  3951. const f = conclusion;//easier acess
  3952. object.lookDirLine.setVerticesData(L.BABYLON.VertexBuffer.PositionKind, [g.x, g.y, g.z, f.x, f.y, f.z]);
  3953. //set line to correct points, with the max dist scaled dirVec3 as endpoint
  3954. }
  3955. if (object && (object !== ss.MYPLAYER) && object[H.playing] && (object[H.hp] > 0) && ((!ss.MYPLAYER.team) || (object.team !== ss.MYPLAYER.team))) {
  3956. object.lookLineData = object.lookDirLine.getVerticesData(L.BABYLON.VertexBuffer.PositionKind);//error here only works in teams, fix
  3957.  
  3958. };
  3959. object.lookDirLine.color = new L.BABYLON.Color3(...hexToRgb(extract("lookTracersColor"))); //updaté line colo(u)r
  3960. object.lookDirLine[H.renderingGroupId] = extract("lookTracersRGI1")? 1 : 0; //render in front shell?
  3961. //I dont really like the implementation without parenting, but IDK how the fuck bab's parenting system works and we need to update anyway. :/
  3962. }
  3963. object.tracerLines.setVerticesData(L.BABYLON.VertexBuffer.PositionKind, [crosshairsPosition.x, crosshairsPosition.y, crosshairsPosition.z, newPosition.x, newPosition.y, newPosition.z]);
  3964. object.tracerLines.color = new L.BABYLON.Color3(...color);
  3965. object.box.color = new L.BABYLON.Color3(...color);
  3966. };
  3967.  
  3968. const obfuscateEmail = function(email) {
  3969. const parts = email.split('@');
  3970. const modifiedFirstPart = parts[0].substring(0, 1) +
  3971. parts[0].substring(1, parts[0].length - 1).replace(/./g, '*') +
  3972. parts[0].substring(parts[0].length - 1);
  3973. return modifiedFirstPart + '@' + parts[1];
  3974. };
  3975. const updateAccountRecords = function(key, value) {
  3976. let currentEmail = load("MostRecentEmail");
  3977. let maskedEmail = unsafeWindow.extern.account.maskedEmail;
  3978. if (currentEmail && obfuscateEmail(currentEmail) == maskedEmail) {
  3979. log("no change in email");
  3980. //do nothing i guess. its good.
  3981. } else {
  3982. log("not using obfuscated email (sadly)");
  3983. currentEmail = maskedEmail; //better than nothing, eh? :<
  3984. };
  3985. log("the email is:", currentEmail);
  3986.  
  3987. let accountRecords = GM_getValue("StateFarm_AccountRecords") || {};
  3988. let tierCache = GM_getValue("StateFarm_TierCache") || {};
  3989.  
  3990. let accountDetails = accountRecords[currentEmail] || {};
  3991. accountDetails.inventory = JSON.parse(JSON.stringify(unsafeWindow.extern.account.inventory));
  3992. accountDetails.eggCount = unsafeWindow.extern.account.currentBalance;
  3993. delete accountDetails.inventoryWorth;
  3994. accountDetails.dateCreated = unsafeWindow.extern.account.dateCreated;
  3995. accountDetails.eggsSpent = unsafeWindow.extern.account.eggsSpent;
  3996. accountDetails.totalWorth = accountDetails.eggCount + accountDetails.eggsSpent;
  3997. accountDetails.inventoryList = [];
  3998. accountDetails.inventory.forEach(item => {
  3999. let itemName = item.name;
  4000. if (tierCache[itemName] !== undefined) itemName = itemName+" [T"+tierCache[itemName]+"]";
  4001. accountDetails.inventoryList.push(itemName);
  4002. });
  4003. if (key && value) {
  4004. accountDetails[key] = value;
  4005. };
  4006.  
  4007. accountRecords[currentEmail] = accountDetails;
  4008. GM_setValue("StateFarm_AccountRecords", accountRecords);
  4009. };
  4010.  
  4011. const getRoomAsString = function () {
  4012. return findKeyByValue(unsafeWindow.extern.GameType, unsafeWindow.vueApp.game.gameType) + ", " + unsafeWindow.vueData.currentRegionId + ", " + unsafeWindow.vueApp.game.mapName + ", team" + unsafeWindow.vueApp.game.team;
  4013. };
  4014.  
  4015. const every15Seconds = function () {
  4016. //i forgot myself what this is for
  4017. // if (extract("debug")) log("goodness", extract("antiAFK"), unsafeWindow.extern.inGame, (document.getElementById("spectate").style.display == "none"), ss, ss.MYPLAYER, ss.MYPLAYER.ws, (!ss.MYPLAYER[H.playing]));
  4018. if (extract("antiAFK") && unsafeWindow.extern.inGame && (document.getElementById("spectate").style.display == "none") && ss && ss.MYPLAYER && ss.MYPLAYER.ws && (!ss.MYPLAYER[H.playing])) {
  4019. if (extract("debug")) log("lets'r try'r to keep alive'r");
  4020. let out = ss.commOut.getBuffer();
  4021. out.packInt8(C.keepAlive);
  4022. out.send(ss.MYPLAYER.ws);
  4023. };
  4024. };
  4025. const everySecond = function () {
  4026. let oldMonitorObjects = JSON.parse(JSON.stringify(monitorObjects));
  4027.  
  4028. if (extract("debug")) {
  4029. unsafeWindow.globalSS = {};
  4030. unsafeWindow.globalSS.ss = ss;
  4031. unsafeWindow.globalSS.H = H;
  4032. unsafeWindow.globalSS.F = F;
  4033. unsafeWindow.globalSS.L = L;
  4034. unsafeWindow.globalSS.C = C;
  4035. unsafeWindow.globalSS.tp = tp;
  4036. unsafeWindow.globalSS.initMenu = initMenu;
  4037. unsafeWindow.globalSS.extractAsDropdownInt = extractAsDropdownInt;
  4038. unsafeWindow.globalSS.extract = extract;
  4039. unsafeWindow.globalSS.extractDropdownList = extractDropdownList;
  4040. unsafeWindow.globalSS.save = save;
  4041. unsafeWindow.globalSS.load = load;
  4042. unsafeWindow.globalSS.GM_listValues = GM_listValues;
  4043. unsafeWindow.globalSS.GM_getValue = GM_getValue;
  4044. unsafeWindow.globalSS.GM_setValue = GM_setValue;
  4045. unsafeWindow.globalSS.crackedShell = crackedShell;
  4046. unsafeWindow.globalSS.createPopup = createPopup;
  4047. unsafeWindow.globalSS.createPrompt = createPrompt;
  4048. unsafeWindow.globalSS.remove = remove;
  4049. unsafeWindow.globalSS.change = change;
  4050. unsafeWindow.globalSS.unban = unban;
  4051. if (typeof GM_info !== 'undefined') unsafeWindow.globalSS.GM_info = GM_info;
  4052. if (typeof GM !== 'undefined') unsafeWindow.globalSS.GM = GM;
  4053. unsafeWindow.globalSS.getScrambled = getScrambled;
  4054. unsafeWindow.globalSS.soundsSFC = soundsSFC;
  4055. unsafeWindow.globalSS.accountStatus = accountStatus;
  4056. unsafeWindow.globalSS.cachedRealData = cachedRealData;
  4057. unsafeWindow.globalSS.retrievedSFX = retrievedSFX;
  4058. unsafeWindow.globalSS.findBadgesForUsername = findBadgesForUsername;
  4059. unsafeWindow.globalSS.badgeList = badgeList;
  4060. unsafeWindow.globalSS.crosshairsPosition = crosshairsPosition;
  4061. unsafeWindow.globalSS.predictGrenade = newPredictGrenade;
  4062. unsafeWindow.globalSS.miniCamera = miniCamera;
  4063. unsafeWindow.globalSS.configMain = configMain;
  4064. unsafeWindow.globalSS.configBots = configBots;
  4065. unsafeWindow.globalSS.predictBloom = predictBloom;
  4066. unsafeWindow.globalSS.verification = verification;
  4067. unsafeWindow.globalSS.createVarDataPopup = createVarDataPopup;
  4068. // unsafeWindow.globalSS.pathfindingInfo = {
  4069. // activePath: activePath,
  4070. // pathfindingTargetOverride: pathfindingTargetOverride,
  4071. // activePath: activePath,
  4072. // activeNodeTarget: activeNodeTarget,
  4073. // mapNodes: GLOBAL_NODE_LIST,
  4074. // };
  4075. };
  4076. save("DisableLogs", extract("consoleLogs"));
  4077. if (extract('sfChatAutoStart') && !sfChatContainer){
  4078. startStateFarmChat(true);
  4079. };
  4080. startUpComplete = (!document.getElementById("progressBar"));
  4081.  
  4082. if (startUpComplete) {
  4083. verification.beginVerificationCheck();
  4084. };
  4085.  
  4086. let botsDict = GM_getValue("StateFarm_BotStatus");
  4087. sfChatUsernameSet();
  4088. if (!botsDict) botsDict = {};
  4089. if (AUTOMATED) {
  4090. if (clientID) {
  4091. const autoLeave = extract("autoLeave") ? " AL: " + Math.round(((timeJoinedGame + (1000 * extract("autoLeaveDelay"))) - Date.now()) / 100) / 10 : "";
  4092. const newArray = {
  4093. noConfig: ((botsDict[clientID] && configNotSet) ? (
  4094. (botsDict[clientID].noConfig > Date.now()) ? botsDict[clientID].noConfig : Date.now()
  4095. ) : 0),
  4096. username: ((ss && ss.MYPLAYER && ss.MYPLAYER.name) || (unsafeWindow.vueApp.playerName)),
  4097. uniqueId: ((ss && ss.MYPLAYER && ss.MYPLAYER[H.uniqueId]) || "value_undefined"),
  4098. startTime: startTime,
  4099. timecode: Date.now(),
  4100. status: ((isBanned && "banned") ||
  4101. (unsafeWindow.extern.inGame && (((ss.MYPLAYER && ss.MYPLAYER[H.playing]) ? "playing " : (unsafeWindow.vueApp.game.respawnTime + "s cooldown ")) + GAMECODE + autoLeave + " (" + getRoomAsString() + ")")) ||
  4102. (errorString || "idle")),
  4103. };
  4104.  
  4105. delete botsDict[clientID];
  4106.  
  4107. clientID = (unsafeWindow.vueData.firebaseId || clientID);
  4108.  
  4109. botsDict[clientID] = newArray;
  4110. };
  4111. if (attemptedInjection && automatedBorder && automatedBorder.style && automatedBorder.style.borderColor == "rgb(255, 0, 0)") {
  4112. automatedBorder.style.borderColor = 'rgba(0, 255, 0, 1)';
  4113. };
  4114. } else {
  4115. let oldBlacklist = botBlacklist;
  4116. botBlacklist = "";
  4117. let oldWhitelist = botWhitelist;
  4118. botWhitelist = "";
  4119. if (extract("botNoKillMe")) {
  4120. botBlacklist += botBlacklist + ((ss && ss.MYPLAYER && ss.MYPLAYER[H.uniqueId]) || "value_undefined") + ",";
  4121. };
  4122. if (extract("botFollowMe")) {
  4123. botWhitelist += botWhitelist + ((ss && ss.MYPLAYER && ss.MYPLAYER[H.uniqueId]) || "value_undefined") + ",";
  4124. };
  4125. monitorObjects.botOnline = "";
  4126. amountOnline = 0;
  4127. const botsArray = Object.keys(botsDict).sort();
  4128. for (let i in botsArray) {
  4129. if (i !== "shallowClone") {
  4130. i = Number(i);
  4131. const botID = botsArray[i];
  4132. const data = botsDict[botID];
  4133. if (data.noConfig) {
  4134. updateBotParams();
  4135. botsDict[botID].noConfig = Date.now() + 5000;
  4136. };
  4137. if (extract("botNoKillBots") && data.uniqueId !== "value_undefined") {
  4138. botBlacklist += data.uniqueId + ",";
  4139. };
  4140. if (extract("botFollowBots") && data.uniqueId !== "value_undefined") {
  4141. botWhitelist += data.uniqueId + ",";
  4142. };
  4143. if ((data.timecode + 10000) < Date.now()) { //give up on this bot lmao
  4144. delete botsDict[botID];
  4145. } else if ((data.timecode + 4000) < Date.now()) { //maybe it will come back
  4146. botsDict[botID].status = "not responding " + (Date.now() - data.timecode) + "ms elapsed";
  4147. }; //bot is doing fine... hopefully
  4148. amountOnline += 1;
  4149. monitorObjects.botOnline = monitorObjects.botOnline + "\n" + data.username + " [..." + botID.slice(-4) + "]: " + data.status;
  4150. };
  4151. };
  4152. if (oldBlacklist !== botBlacklist) {
  4153. log("old:", oldBlacklist, "new:", botBlacklist);
  4154. updateBotParams();
  4155. };
  4156. if (oldWhitelist !== botWhitelist) {
  4157. log("old:", oldWhitelist, "new:", botWhitelist);
  4158. updateBotParams();
  4159. };
  4160. monitorObjects.botOnline = ((amountOnline) + " bots online.") + monitorObjects.botOnline;
  4161. };
  4162. GM_setValue("StateFarm_BotStatus", botsDict);
  4163.  
  4164. allFolders.forEach(function (name) {
  4165. save(name, tp[name].expanded);
  4166. });
  4167.  
  4168. coordElement.style.display = "none";
  4169. gameInfoElement.style.display = "none";
  4170. playerstatsElement.style.display = "none";
  4171. playerinfoElement.style.display = "none";
  4172. redCircle.style.display = "none";
  4173. performanceElement.style.display = "none";
  4174. firstUseElement.style.display = "none";
  4175.  
  4176. makeHudElementDragable(coordElement);
  4177. makeHudElementDragable(gameInfoElement);
  4178. makeHudElementDragable(playerstatsElement);
  4179. makeHudElementDragable(playerinfoElement);
  4180. makeHudElementDragable(performanceElement);
  4181.  
  4182. if (extract("gameBlacklistCodes") != "" && extract("gameBlacklistCodes") != undefined) {
  4183. let input = extract("gameBlacklistCodes");
  4184. input = input.split(",");
  4185. input.forEach(function (code) {
  4186. if (code != "" && code.length == 14) {
  4187. blacklistedGameCodes.push(code);
  4188. }
  4189. });
  4190. };
  4191.  
  4192. if (extract("noAnnoyances") && !annoyancesRemoved) {
  4193. const styleElement = document.createElement('style');
  4194. styleElement.textContent = `
  4195. /* remove ads because annoying stop adding spyware yarg */
  4196. .house-small,
  4197. #big-house-ad,
  4198. .house-ad-wrapper,
  4199. .display-ad-container,
  4200. .respawn-one,
  4201. .respawn-two,
  4202. #ShellShockers_LoadingScreen_HouseAds,
  4203. #display-ad-header-home,
  4204. .display-ad-header-home,
  4205. #display-ad-header-equip,
  4206. #shellshockers_respawn_banner_3_ad {
  4207. display: none;
  4208. }
  4209. `;
  4210. document.head.appendChild(styleElement);
  4211. annoyancesRemoved = true;
  4212. };
  4213.  
  4214. async function unzip(arrayBuffer) {
  4215. const dataView = new DataView(arrayBuffer);
  4216. let offset = 0;
  4217. const files = {};
  4218.  
  4219. while (offset < dataView.byteLength) {
  4220. if (dataView.getUint32(offset, true) !== 0x04034b50) {
  4221. log("ZIP header not found at offset (ZIP has likely ended):", offset);
  4222. break;
  4223. }
  4224.  
  4225. const fileNameLength = dataView.getUint16(offset + 26, true);
  4226. const fileName = new TextDecoder().decode(new Uint8Array(arrayBuffer, offset + 30, fileNameLength));
  4227. const compressedSize = dataView.getUint32(offset + 18, true);
  4228. const compressionMethod = dataView.getUint16(offset + 8, true);
  4229.  
  4230. offset += 30 + fileNameLength;
  4231. const compressedData = new Uint8Array(arrayBuffer, offset, compressedSize);
  4232.  
  4233. if (compressionMethod === 0) {
  4234. files[fileName] = compressedData;
  4235. } else if (compressionMethod === 8) {
  4236. try {
  4237. const stream = new Response(compressedData).body.pipeThrough(new DecompressionStream("deflate-raw"));
  4238. const decompressed = await new Response(stream).arrayBuffer();
  4239. files[fileName] = decompressed;
  4240. } catch (error) {
  4241. console.error("Decompression failed:", error);
  4242. }
  4243. } else {
  4244. console.warn("Unsupported compression method:", compressionMethod);
  4245. }
  4246.  
  4247. offset += compressedSize;
  4248. }
  4249.  
  4250. log('finished unzipping :v')
  4251.  
  4252. return files;
  4253. }
  4254.  
  4255. const fetchAndProcessAudioFromZip = async function (zipURL) {
  4256. try {
  4257. const response = await fetch(zipURL);
  4258. if (!response.ok) throw new Error('Failed to fetch ZIP:', response.statusText);
  4259.  
  4260. const arrayBuffer = await response.arrayBuffer();
  4261. const files = await unzip(arrayBuffer);
  4262.  
  4263. log('finished files', files);
  4264.  
  4265. const mp3Files = Object.keys(files).filter(f => f.endsWith('.mp3'));
  4266. const jsonFiles = Object.keys(files).filter(f => f.endsWith('.json'));
  4267. let config = {};
  4268.  
  4269. if (jsonFiles.length > 0) {
  4270. config = JSON.parse(new TextDecoder().decode(files[jsonFiles[0]]));
  4271. }
  4272.  
  4273. let loadedCount = 0;
  4274. const totalRequests = mp3Files.length + jsonFiles.length;
  4275.  
  4276. for (const fileName of mp3Files) {
  4277. const fileData = files[fileName];
  4278. const audioBuffer = await audioContexts.SOUNDS.decodeAudioData(fileData);
  4279. const key = fileName.replace('.mp3', '');
  4280. audioBuffer.disablePanning = !!config.disablePanning;
  4281. soundsSFC[key] = audioBuffer;
  4282. log("Loaded sound for:", key);
  4283.  
  4284. loadedCount++;
  4285. if (loadedCount === totalRequests) {
  4286. createPopup("Loaded Custom SFX!", "success");
  4287. log("LOADED!");
  4288. }
  4289. }
  4290. } catch (error) {
  4291. console.error('Error fetching/decoding audio from ZIP:', error);
  4292. };
  4293. };
  4294.  
  4295. let customSFXConfig = `${extract("customSFX1")}+${extract("customSFX2")}+${extract("customSFX3")}`;
  4296. if (initialisedCustomSFX !== customSFXConfig) {
  4297. initialisedCustomSFX = customSFXConfig;
  4298. log("STARTING TO LOAD CUSTOM SFX...", initialisedCustomSFX);
  4299. soundsSFC = {};
  4300. if (extract("customSFX3") !== true && extract("customSFX3") !== "default") { //wa wa wa repeated code YOU FUNCTION IT THEN I DONT CARE!!!!! -onlypuppy7
  4301. createPopup("Loading Custom SFX...");
  4302. fetchAndProcessAudioFromZip(atob(extract("customSFX3")));
  4303. };
  4304. if (extract("customSFX2") !== true && extract("customSFX2") !== "default") {
  4305. createPopup("Loading Custom SFX...");
  4306. fetchAndProcessAudioFromZip(atob(extract("customSFX2")));
  4307. };
  4308. if (extract("customSFX1") !== true && extract("customSFX1") !== "default") {
  4309. createPopup("Loading Custom SFX...");
  4310. fetchAndProcessAudioFromZip(atob(extract("customSFX1")));
  4311. };
  4312. };
  4313.  
  4314. if (startUpComplete && ss && ss.MYPLAYER && unsafeWindow.extern.inGame) {
  4315. if (extract("mockMode")) {
  4316. let textAfterLastColon = document.getElementById("chatOut").children[document.getElementById("chatOut").children.length - 1].children[1].textContent;
  4317. let chatName = document.getElementById("chatOut").children[document.getElementById("chatOut").children.length - 1].children[0].textContent.slice(0, -2);
  4318. // log("Chat Name:", chatName);
  4319. if (chatName && chatName !== username && textAfterLastColon !== "joined." && textAfterLastColon !== "left." && !handleChat(textAfterLastColon) && !extract("mockModeNoRePeat")) {
  4320. sendChatMessage(textAfterLastColon);
  4321. }; //mockMode, this will copy and send the chat into message when joining, but doesn't show to other players, so it's fine. solvable with an if statement bool
  4322. };
  4323. // if (extract("antiAFK")) {
  4324. // if (Date.now() > (lastAntiAFKMessage + 270000)) {
  4325. // if (sendChatMessage(antiAFKString + filteredList[randomInt(0, filteredList.length - 1)])) {
  4326. // lastAntiAFKMessage = Date.now();
  4327. // };
  4328. // };
  4329. // };
  4330. if (extract("gameInfo")) {
  4331. let gameInfoText = 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 + " | Time in game: " + (Math.floor((Date.now() - timeJoinedGame) / 1000)) + "s" + (extract("autoLeave") ? " | AutoLeave: " + (Math.ceil(((timeJoinedGame + (1000 * extract("autoLeaveDelay"))) - Date.now()) / 1000)) + "s" : "");
  4332. gameInfoElement.innerText = gameInfoText;
  4333. void gameInfoElement.offsetWidth;
  4334. gameInfoElement.style.display = '';
  4335. };
  4336. if (extract("leaveEmpty")) {
  4337. if (playersInGame == 1 || playersInGame == 2) { //if literally empty or there is one person remaining
  4338. createPopup("Left empty game. [LeaveEmpty]")
  4339. change("leaveGame");
  4340. playersInGame = 0;
  4341. };
  4342. };
  4343. if (extract("autoLeave")) {
  4344. const remaining = ((timeJoinedGame + (1000 * extract("autoLeaveDelay"))) - Date.now()) / 1000;
  4345. if (remaining <= 0) {
  4346. createPopup("AutoLeave: Leaving now...");
  4347. change("leaveGame");
  4348. } else if (autoLeaveReminder > 5 && remaining <= 5) {
  4349. createPopup("AutoLeave: 5 seconds remaining!");
  4350. } else if (autoLeaveReminder > 10 && remaining <= 10) {
  4351. createPopup("AutoLeave: 10 seconds remaining");
  4352. };
  4353. // log(autoLeaveReminder, remaining);
  4354. autoLeaveReminder = remaining;
  4355. };
  4356.  
  4357. //credits: @2lars and @macintosh2 in the discord :)
  4358. if ((extract("autoTeam") !== "disabled") && ss.MYPLAYER.team !== 0) {
  4359. if ((extract("autoTeam") == "random") ||
  4360. (extract("autoTeam") == "red") && (ss.MYPLAYER.team == 1) ||
  4361. (extract("autoTeam") == "blue") && (ss.MYPLAYER.team == 2)) {
  4362. unsafeWindow.extern.switchTeam();
  4363. };
  4364. };
  4365. if (!ss.MYPLAYER[H.playing]) {
  4366. GAMECODE = unsafeWindow.vueApp.game.shareLinkPopup.url.slice(-14);
  4367. if (extract("autoRespawn")) {
  4368. var button = document.querySelector('.ss_button.btn_big.btn-dark-bevel.btn-respawn.ss_button.btn_green.bevel_green');
  4369. if (button) {
  4370. button.click();
  4371. };
  4372. };
  4373. };
  4374.  
  4375. Array.from(document.getElementById("playerList").children).forEach(playerListItem => {
  4376. const playerSlotNameElement = playerListItem.children[0];
  4377. if (playerSlotNameElement) {
  4378. let highlightSpan = playerSlotNameElement.querySelector('span');
  4379. if (!highlightSpan) {
  4380. highlightSpan = document.createElement('span');
  4381. highlightSpan.textContent = playerSlotNameElement.textContent;
  4382. playerSlotNameElement.textContent = '';
  4383. playerSlotNameElement.appendChild(highlightSpan);
  4384. };
  4385. if (extract("unfilterNames") && ss.isBadWord(playerListItem.textContent)) {
  4386. highlightSpan.style.backgroundColor = "rgba(255, 255, 255, 0.6)";
  4387. highlightSpan.style.color = 'red';
  4388. } else {
  4389. highlightSpan.style.backgroundColor = '';
  4390. highlightSpan.style.color = '';
  4391. };
  4392. };
  4393. });
  4394.  
  4395. // addStreamsToInGameUI(); //broken rn anyways
  4396.  
  4397. const pausedGameUI = document.querySelector('.paused-game-ui');
  4398. const hasZIndex1 = pausedGameUI.classList.contains('z-index-1');
  4399. const hasZIndex10000 = pausedGameUI.classList.contains('z-index-10000');
  4400. if (extract("restoreScroll") && (hasZIndex1 || !hasZIndex10000)) {
  4401. pausedGameUI.classList.remove('z-index-1', 'z-index-10000');
  4402. pausedGameUI.classList.add("z-index-10000");
  4403. } else if ((!extract("restoreScroll")) && (hasZIndex10000 || !hasZIndex1)) {
  4404. pausedGameUI.classList.remove('z-index-1', 'z-index-10000');
  4405. pausedGameUI.classList.add("z-index-1");
  4406. };
  4407.  
  4408. if (extract("minimap")) {
  4409. if (!miniCamera) {
  4410. var camPos = new L.BABYLON.Vector3(0, -20, 0);
  4411. miniCamera = new L.BABYLON.ArcRotateCamera("minimapCamera", -1.5707963267948966, 0, 30, camPos, ss.SCENE);
  4412. miniCamera.mode = 1; //L.BABYLON.Camera.ORTHOGRAPHIC_CAMERA
  4413. ss.SCENE.activeCameras.push(miniCamera);
  4414. miniCamera.parent = ss.MYPLAYER[H.actor][H.mesh];
  4415. };
  4416. miniCamera._skipRendering = false;
  4417.  
  4418. let cameraScale = extract("minimapZoom");
  4419.  
  4420. miniCamera.orthoLeft = -cameraScale;
  4421. miniCamera.orthoRight = cameraScale;
  4422. miniCamera.orthoBottom =- cameraScale;
  4423. miniCamera.orthoTop = cameraScale;
  4424.  
  4425. let mapScale = extract("minimapSize");
  4426.  
  4427. var relativeWidth = 200 / window.innerWidth;
  4428. var relativeHeight = 200 / window.innerHeight;
  4429.  
  4430. miniCamera.viewport = new L.BABYLON.Viewport(0.2, 0.2, relativeWidth * mapScale, relativeHeight * mapScale);
  4431. } else if (miniCamera) {
  4432. miniCamera._skipRendering = true;
  4433. };
  4434.  
  4435. if (extract("instantSpectate")) {
  4436. if (document.getElementsByClassName("pause-container centered")[0].style.display == "") {
  4437. document.getElementsByClassName("pause-screen-btn-spectate")[0].style.display = '';
  4438. document.getElementsByClassName("pause-screen-btn-spectate")[0].disabled = null;
  4439. };
  4440. };
  4441. } else {
  4442. if (!document.getElementById("progressBar")) {
  4443. if (extract("autoJoin") && (extract("autoLogin") == "disabled" || unsafeWindow.vueApp.accountCreated !== null)) {
  4444. unsafeWindow.vueApp.externPlayObject(
  4445. (extract("joinCode").length === 14) ? 2 : 0,
  4446. unsafeWindow.vueApp.currentGameType,
  4447. unsafeWindow.vueApp.playerName,
  4448. '',
  4449. (extract("joinCode").length === 14) ? extract("joinCode") : '',
  4450. );
  4451. };
  4452. };
  4453. if (extract("autoRegion") !== "disabled") {
  4454. const region = (extract("autoRegion") == "random" ? extractDropdownList("autoRegion")[randomInt(1, 7)].value : extract("autoRegion"));
  4455. unsafeWindow.vueData.currentRegionId = region;
  4456. };
  4457. if (extract("autoGamemode") !== "disabled") {
  4458. const gamemode = ((extract("autoGamemode") == "random") ? randomInt(0, 3) : (extractAsDropdownInt("autoGamemode") - 1));
  4459. unsafeWindow.vueApp.onGameTypeChanged(gamemode);
  4460. };
  4461. };
  4462.  
  4463. if (startUpComplete) {
  4464. // check if it is a user's first time to run the script
  4465. if (GM_getValue("StateFarm_firstRun") !== 1) {
  4466. firstExecution = true;
  4467. };
  4468.  
  4469. if ((extract("legacyModels") !== previousLegacyModels)) {
  4470. let models = [3000, 3100, 3400, 3600, 3800, 4000, 4200];
  4471. models.forEach(ID => {
  4472. let item = unsafeWindow.extern.catalog.findItemById(ID);
  4473. item.item_data.meshName.replaceAll("_Legacy","");
  4474. if (extract("legacyModels")) item.item_data.meshName = `${item.item_data.meshName}_Legacy`;
  4475. });
  4476. };
  4477. previousLegacyModels = extract("legacyModels");
  4478.  
  4479. if ((extract("setDetail") !== previousDetail) && (extract("setDetail") !== "disabled")) {
  4480. unsafeWindow.vueApp.settingsUi.togglers.misc[3].value = false;
  4481. if (extract("setDetail") == "autodetail") {
  4482. unsafeWindow.vueApp.settingsUi.togglers.misc[3].value = true;
  4483. } else if (extract("setDetail") == "nodetails") {
  4484. unsafeWindow.vueApp.settingsUi.togglers.misc[4].value = false;
  4485. unsafeWindow.vueApp.settingsUi.togglers.misc[5].value = false;
  4486. } else if (extract("setDetail") == "shadows") {
  4487. unsafeWindow.vueApp.settingsUi.togglers.misc[4].value = true;
  4488. unsafeWindow.vueApp.settingsUi.togglers.misc[5].value = false;
  4489. } else if (extract("setDetail") == "highres") {
  4490. unsafeWindow.vueApp.settingsUi.togglers.misc[4].value = false;
  4491. unsafeWindow.vueApp.settingsUi.togglers.misc[5].value = true;
  4492. } else if (extract("setDetail") == "shadowshighres") {
  4493. unsafeWindow.vueApp.settingsUi.togglers.misc[4].value = true;
  4494. unsafeWindow.vueApp.settingsUi.togglers.misc[5].value = true;
  4495. };
  4496. unsafeWindow.extern.applyUiSettings(unsafeWindow.vueApp.settingsUi);
  4497. };
  4498. previousDetail = extract("setDetail");
  4499.  
  4500. if (previousTitleAnimation !== extract("titleAnimation")) {
  4501. let existingFavicons = document.querySelectorAll("link[rel*='icon']");
  4502. existingFavicons.forEach(function (favicon) {
  4503. favicon.parentNode.removeChild(favicon);
  4504. });
  4505. let favicon = document.createElement('link');
  4506. favicon.type = 'image/x-icon';
  4507. favicon.rel = 'shortcut icon';
  4508. if (extract("titleAnimation")) {
  4509. favicon.href = (GM_info?.script?.icon || iconURL);
  4510. } else {
  4511. favicon.href = 'https://www.google.com/s2/favicons?domain=shellshock.io';
  4512. };
  4513. document.getElementsByTagName('head')[0].appendChild(favicon);
  4514. previousTitleAnimation = extract("titleAnimation");
  4515. };
  4516. };
  4517.  
  4518. const banPopup = document.getElementById("bannedPopup");
  4519. if (attemptedInjection && banPopup && unsafeWindow.vueApp?.bannedPopup?.expire && (unsafeWindow.vueApp.bannedPopup.expire !== "")) isBanned = true;
  4520. if (isBanned && extract("autoUnban") && (!attemptedAutoUnban) && unsafeWindow.vueApp?.bannedPopup) {
  4521. log("eep!");
  4522. banPopup.textContent = 'StateFarm AutoUnban:\nYou now have a new database\nID for unban. Enjoy! :)\nBan message will be automatically removed from screen in 15 seconds.';
  4523. unban();
  4524. attemptedAutoUnban = true;
  4525. createPopup("AutoUnban: Attempting to Unban...");
  4526. setTimeout(() => {
  4527. createPopup("AutoUnban: Removed ban message.");
  4528. banPopup.style.display = "none";
  4529. attemptedAutoUnban = false;
  4530. isBanned = false;
  4531. unsafeWindow.vueApp.bannedPopup.expire = "";
  4532. }, 15000);
  4533. };
  4534.  
  4535. if (extract("eggColor") !== "disabled" && ss?.USERDATA) {
  4536. const color = extract("eggColor") == "random" ? randomInt(0, 6) : extractAsDropdownInt("eggColor") - 1;
  4537. if (color !== ss.USERDATA.playerAccount.colorIdx) {
  4538. unsafeWindow.extern.setShellColor(color);
  4539. unsafeWindow.vueApp.onBackClick();
  4540. };
  4541. };
  4542. if (extract("autoStamp") !== "disabled" && ss?.USERDATA) {
  4543. const stampID = 2000 + (extract("autoStamp") == "random" ? randomInt(1, 6) : extractAsDropdownInt("autoStamp"));
  4544. if (ss.USERDATA && ss.USERDATA.playerAccount) {
  4545. if (stampID !== ((ss.USERDATA.playerAccount.stampItem && ss.USERDATA.playerAccount.stampItem?.id) || -1)) {
  4546. ss.USERDATA.playerAccount.stampItem = unsafeWindow.extern.catalog.findItemById(stampID);
  4547. unsafeWindow.vueApp.onBackClick();
  4548. };
  4549. };
  4550. };
  4551. if (extract("autoHat") !== "disabled" && ss?.USERDATA) {
  4552. const hatID = 1000 + (extract("autoHat") == "random" ? randomInt(1, 6) : extractAsDropdownInt("autoHat"));
  4553. if (ss.USERDATA && ss.USERDATA.playerAccount) {
  4554. if (hatID !== ((ss.USERDATA.playerAccount.hatItem && ss.USERDATA.playerAccount.hatItem?.id) || -1)) {
  4555. ss.USERDATA.playerAccount.hatItem = unsafeWindow.extern.catalog.findItemById(hatID);
  4556. unsafeWindow.vueApp.onBackClick();
  4557. };
  4558. };
  4559. };
  4560. if (extract("useCustomName")) {
  4561. unsafeWindow.vueApp?.setPlayerName(extract("usernameAutoJoin"));
  4562. };
  4563. if ((!ranEverySecond) && startUpComplete) {
  4564. if (extract("autoChickenWinner")) {
  4565. log("automatically do chw");
  4566. change("chickenWinner");
  4567. };
  4568. updateAccountRecords();
  4569. if (extract("autoMacro")) {
  4570. log("automatically do your macro");
  4571. change("executeMacro");
  4572. };
  4573.  
  4574. log("swapping out google analytics...");
  4575.  
  4576. ranEverySecond = true;
  4577. };
  4578.  
  4579. //block ads or something kek
  4580. localStorage.timesPlayed = 0;
  4581.  
  4582. for (let storeAs of Object.keys(monitorObjects)) {
  4583. let object = monitorObjects[storeAs];
  4584. if (monitorObjects[object] !== oldMonitorObjects[object]) {
  4585. log(object, monitorObjects[object]);
  4586. tp[storeAs+"Button"].refresh();
  4587. };
  4588. };
  4589. };
  4590. const everyDecisecond = function () {
  4591. // updateConfig();
  4592. deciSecondsPassed++;
  4593.  
  4594. if (extract("titleAnimation")) {
  4595. if (deciSecondsPassed % 3 == 0) {
  4596. unsafeWindow.document.title = titleAnimationFrames[currentFrameIndex];
  4597. currentFrameIndex = (currentFrameIndex + 1) % titleAnimationFrames.length;
  4598. };
  4599. } else if (unsafeWindow.document.title != "Shell Shockers 🍳 Multiplayer io game") {
  4600. unsafeWindow.document.title = "Shell Shockers 🍳 Multiplayer io game";
  4601. };
  4602.  
  4603. if (startUpComplete && (!unsafeWindow.extern.inGame) && extract("autoLogin") !== "disabled" && (extract("autoLogin") == "always" || extract("autoLogin") == "noaccount" && unsafeWindow.vueApp.accountCreated == null)) {
  4604. if ((previousLogin + 5000) < Date.now()) {
  4605. unban();
  4606. change("loginDatabaseLogin");
  4607. previousLogin = Date.now();
  4608. };
  4609. };
  4610.  
  4611. if (ss && ss?.MYPLAYER && unsafeWindow?.extern?.inGame) {
  4612. //innertext stuff, fairly resource intensive. disable these for performance
  4613. if (extract("playerStats")) {
  4614. let playerStates = "";
  4615. ss.PLAYERS.forEach(player => {
  4616. if (player && (player !== ss.MYPLAYER) && (player[H.hp] > 0) && ((!ss.MYPLAYER.team) || (player.team !== ss.MYPLAYER.team))) {
  4617. playerStates = playerStates + player.name + ": " + Math.round(player[H.hp]) + " HP\n";
  4618. };
  4619. });
  4620. if (playerStates == "") { playerStates = "No Enemy Players" };
  4621. playerstatsElement.innerText = playerStates;
  4622. void playerstatsElement.offsetWidth;
  4623. playerstatsElement.style.display = '';
  4624. };
  4625. if (extract("playerInfo")) {
  4626. let playerInfoString = "";
  4627. const player = currentlyTargeting || playerLookingAt || undefined
  4628. if (player && player.distance && player[H.playing]) {
  4629. playerInfoString = playerInfoString + player.name + "\n"
  4630. playerInfoString = playerInfoString + "HP: " + Math.round(player[H.hp]) + "\n"
  4631. playerInfoString = playerInfoString + "Distance: " + player.distance.toFixed(3) + "\n"
  4632. playerInfoString = playerInfoString + "AngleDiff: " + player.angleDiff.toFixed(3) + "\n"
  4633. };
  4634. if (playerInfoString == "") { playerInfoString = "Not Looking At Player" };
  4635. playerinfoElement.innerText = playerInfoString;
  4636. void playerinfoElement.offsetWidth;
  4637. playerinfoElement.style.display = '';
  4638. };
  4639. if (ss.MYPLAYER && ss.MYPLAYER[H.actor] && ss.MYPLAYER[H.actor][H.mesh] && extract("showCoordinates")) {
  4640. const fonx = Number((ss.MYPLAYER[H.actor][H.mesh].position.x).toFixed(3));
  4641. const fony = Number((ss.MYPLAYER[H.actor][H.mesh].position.y).toFixed(3));
  4642. const fonz = Number((ss.MYPLAYER[H.actor][H.mesh].position.z).toFixed(3));
  4643. const yaw = Number((ss.MYPLAYER[H.yaw]).toFixed(3)); //could i function this? yea
  4644. const pitch = Number((ss.MYPLAYER[H.pitch]).toFixed(3));
  4645. const personalCoordinate = `XYZ: ${fonx}, ${fony}, ${fonz} Rot: ${yaw}, ${pitch} Acc: ${Number(accuracyPercentage).toFixed(3)}`;
  4646. coordElement.innerText = personalCoordinate;
  4647. void coordElement.offsetWidth;
  4648. coordElement.style.display = '';
  4649. };
  4650. if (ss.MYPLAYER && ss.MYPLAYER[H.actor] && ss.MYPLAYER[H.actor][H.mesh] && extract("performanceInfo")) {
  4651. if (performance.memory) {
  4652. const memoryUsage = performance.memory;
  4653. const jsHeapSizeLimit = (memoryUsage.jsHeapSizeLimit / 1024 / 1024).toFixed(2);
  4654. const totalJSHeapSize = (memoryUsage.totalJSHeapSize / 1024 / 1024).toFixed(2);
  4655. const usedJSHeapSize = (memoryUsage.usedJSHeapSize / 1024 / 1024).toFixed(2);
  4656.  
  4657. performanceElement.textContent = `
  4658. Memory Usage:
  4659. ${usedJSHeapSize} MB / ${jsHeapSizeLimit} MB
  4660. `.trim();
  4661. } else {
  4662. performanceElement.textContent = "Performance.memory API is not supported in this browser.";
  4663. };
  4664. performanceElement.style.display = '';
  4665. };
  4666. // create an info box for the first execution, i have 69697935 iq
  4667. if (firstExecution == true) {
  4668. firstUseElement.innerHTML = `
  4669. <style>
  4670. @font-face {
  4671. font-family: "Bahnschrift";
  4672. src: url("https://db.onlinewebfonts.com/t/0a6ee448d1bd65c56f6cf256a7c6f20a.eot");
  4673. src: url("https://db.onlinewebfonts.com/t/0a6ee448d1bd65c56f6cf256a7c6f20a.eot?#iefix")format("embedded-opentype"),
  4674. url("https://db.onlinewebfonts.com/t/0a6ee448d1bd65c56f6cf256a7c6f20a.woff2")format("woff2"),
  4675. url("https://db.onlinewebfonts.com/t/0a6ee448d1bd65c56f6cf256a7c6f20a.woff")format("woff"),
  4676. url("https://db.onlinewebfonts.com/t/0a6ee448d1bd65c56f6cf256a7c6f20a.ttf")format("truetype"),
  4677. url("https://db.onlinewebfonts.com/t/0a6ee448d1bd65c56f6cf256a7c6f20a.svg#Bahnschrift")format("svg");
  4678. }
  4679. .overlay {
  4680. position: fixed;
  4681. top: 0;
  4682. left: 0;
  4683. width: 100%;
  4684. height: 100%;
  4685. background-color: rgba(0, 0, 0, 0.7);
  4686. z-index: 9999;
  4687. display: flex;
  4688. justify-content: center;
  4689. align-items: center;
  4690. opacity: 1;
  4691. }
  4692. .overlay-content {
  4693. text-align: center;
  4694. color: white;
  4695. }
  4696. h100 {
  4697. color: white;
  4698. font-weight: bold;
  4699. font-family: Bahnschrift;
  4700. font-size: 36px;
  4701. }
  4702. a {
  4703. text-decoration: none;
  4704. font-family: Bahnschrift;
  4705. font-size: 24px;
  4706. }
  4707. p {
  4708. text-decoration: none;
  4709. font-family: Bahnschrift;
  4710. font-size: 15px;
  4711. }
  4712. </style>
  4713. </head>
  4714. <body>
  4715.  
  4716. <div class="overlay">
  4717. <div class="overlay-content">
  4718. <h100>Welcome to StateFarm Client V3</h100>
  4719. <br>
  4720. <br>
  4721. <a href="${discordURL}">Discord&emsp;</a>
  4722. <a href="${githubURL}">Github&emsp;</a>
  4723. <a href="${greasyforkURL}">Greasyfork&emsp;</a>
  4724. <a href="${youtubeURL}">YouTube</a>
  4725. <br>
  4726. <br>
  4727. <p>Press 'Escape' to close</p>
  4728. </div>
  4729. </div>
  4730. </body>
  4731. `
  4732. firstUseElement.style.display = '';
  4733. document.addEventListener('keydown', function (event) {
  4734. if (event.keyCode === 27) {
  4735. firstUseElement.style.opacity = '0';
  4736. firstUseElement.style.display = "none";
  4737. setTimeout(function () {
  4738. firstUseElement.parentNode.removeChild(firstUseElement);
  4739. }, 1000)
  4740. }
  4741. GM_setValue("StateFarm_firstRun", 1);
  4742. });
  4743. };
  4744. };
  4745. if (AUTOMATED) { //i know what youre saying looking at this. i am the greatest programmer to have ever lived
  4746. if (GM_getValue("StateFarm_CommandTime") > cachedCommandTime) {
  4747. // alert("New command incoming");
  4748. cachedCommand = GM_getValue("StateFarm_Command");
  4749. cachedCommandTime = GM_getValue("StateFarm_CommandTime");
  4750. log("Command received:", cachedCommand);
  4751. handleCommand(cachedCommand);
  4752. } else {
  4753. // uncommment if needed
  4754. // log("No new command, cached command:", cachedCommand, "cached time:", cachedCommandTime, "diff to now:", Date.now() - cachedCommandTime);
  4755. };
  4756. };
  4757. };
  4758.  
  4759. const handleCommand = function (command) {
  4760. let args = command.split(" ");
  4761.  
  4762. switch (args[0]) {
  4763. case "setconfig":
  4764. let receivedConfig = decodeURIComponent(unsafeWindow.escape(window.atob(args[1]))); // eslint-disable-line
  4765. if (URLParams !== "") { receivedConfig = URLParams + "<" + receivedConfig };
  4766. log("StateFarm: Change in Bot Panel detected.", receivedConfig);
  4767. applySettings(receivedConfig);
  4768. configNotSet = false;
  4769. break;
  4770. case "ping":
  4771. createPopup("Pong! " + ((Date.now() - cachedCommandTime)) + "ms", "success");
  4772. break;
  4773. case "kill":
  4774. unsafeWindow.close();
  4775. break;
  4776. case "leave":
  4777. change("leaveGame");
  4778. break;
  4779. case "unban":
  4780. unban();
  4781. break;
  4782. case "newproxy":
  4783. newProxy();
  4784. break;
  4785. case "refresh":
  4786. reloadPage();
  4787. break;
  4788. case "report":
  4789. spamReport();
  4790. break;
  4791. case "join":
  4792. if (args[1]) unsafeWindow.vueApp.externPlayObject(0, 0, unsafeWindow.vueApp.playerName, -1, args[1]);
  4793. else alert("Invalid code");
  4794. break;
  4795. case "repeat":
  4796. if (args[1]) {
  4797. sendChatMessage(args.slice(1).join(" "));
  4798. } else {
  4799. sendChatMessage("Invalid repeat message");
  4800. }
  4801. break;
  4802. /*
  4803. case "pathtarget": // pathfinding target
  4804. let option = args[1]; // eslint-disable-line
  4805. if (option) {
  4806. if (option === "set") {
  4807. let x = args[2];
  4808. let y = args[3];
  4809. let z = args[4];
  4810. if (x && y && z) {
  4811. pathfindingTargetOverride = { x: x, y: y, z: z };
  4812. isFirstFrameAttemptingToPathfind = true;
  4813. } else {
  4814. sendChatMessage("Invalid pathtarget coordinates")
  4815. };
  4816. };
  4817. };
  4818. break;
  4819. case "clearpath":
  4820. clearPath();
  4821. break;
  4822. case "clearpath_t":
  4823. clearPath_andTarget();
  4824. break;
  4825. case "setpathdespawn":
  4826. if (args[1]) {
  4827. if (args[1] === "true") {
  4828. despawnIfNoPath = true;
  4829. } else if (args[1] === "false") {
  4830. despawnIfNoPath = false;
  4831. } else if (args[1] === "toggle") {
  4832. despawnIfNoPath = !despawnIfNoPath;
  4833. } else {
  4834. sendChatMessage("Invalid setpathdespawn argument");
  4835. }
  4836. } else {
  4837. sendChatMessage("Invalid setpathdespawn message");
  4838. };
  4839. */
  4840. };
  4841. };
  4842.  
  4843. const onOptionChanged = function(module, value) {
  4844. if ((!configMain) || (!configBots)) {
  4845. updateConfig();
  4846. };
  4847. if (configBots[module.storeAs] !== undefined) {
  4848. configBots[module.storeAs] = value.value;
  4849. } else {
  4850. configMain[module.storeAs] = value.value;
  4851. };
  4852. };
  4853.  
  4854. const updateConfig = function () {
  4855. configMain = tp.mainPanel.exportPreset();
  4856. configBots = tp.botPanel.exportPreset();
  4857. };
  4858.  
  4859. const updateHiddenAndDisabledHelper = function (array) { //determines if all conditions are met
  4860. let conditionMet = false;
  4861. array.forEach(condition => {
  4862. if ((extract(condition[0]) ? extract(condition[0]) : false) !== condition[1]) {
  4863. conditionMet = true;
  4864. return;
  4865. };
  4866. });
  4867. return conditionMet;
  4868. };
  4869. const updateHiddenAndDisabled = function () {
  4870. //the format for hidden/disabled modules is as follows:
  4871. //hidden/disabled is an array of arrays. within each of the items, there is the condition required for the module to be shown
  4872. //eg: [["aimbot",true],...] (will only be shown if extract("aimbot")==true)
  4873. if (menuInitiated) {
  4874. allModules.forEach(module => {
  4875. const tiedModules = tp[module + "TiedModules"];
  4876. if (tiedModules) {
  4877. if (tiedModules.showConditions) {
  4878. tp[module + "Button"].hidden = updateHiddenAndDisabledHelper(tiedModules.showConditions);
  4879. };
  4880. if (tiedModules.hideConditions) {
  4881. tp[module + "Button"].hidden = !updateHiddenAndDisabledHelper(tiedModules.hideConditions);
  4882. };
  4883. if (tiedModules.enableConditions) {
  4884. tp[module + "Button"].disabled = updateHiddenAndDisabledHelper(tiedModules.enableConditions);
  4885. };
  4886. if (tiedModules.disableConditions) {
  4887. tp[module + "Button"].disabled = !updateHiddenAndDisabledHelper(tiedModules.disableConditions);
  4888. };
  4889. };
  4890. });
  4891. };
  4892. };
  4893. const loginOrCreateWithEmailPass = function (emailPass) {
  4894. let email, pass;
  4895. [email, pass] = emailPass.split(":");
  4896. log("gonna create/login an account that will send/has email to", email, "with the password", pass);
  4897. save("MostRecentEmail", email);
  4898. //try both. who cares about some stupid errors?
  4899. unsafeWindow.firebase.auth().createUserWithEmailAndPassword(email, pass)
  4900. .then(response => {
  4901. log("success?!?!?!? created account");
  4902. setTimeout(function(){
  4903. updateAccountRecords("emailPass", emailPass);
  4904. accountStatus = "created account";
  4905. }, 2000);
  4906. })
  4907. .catch(() => { });
  4908. unsafeWindow.firebase.auth().signInWithEmailAndPassword(email, pass)
  4909. .then(response => {
  4910. log("success?!?!?!? signed in");
  4911. setTimeout(function(){
  4912. updateAccountRecords("emailPass", emailPass);
  4913. accountStatus = "created account";
  4914. }, 2000);
  4915. accountStatus = "signed in";
  4916. })
  4917. .catch(() => { });
  4918. };
  4919. const saveConfig = function () {
  4920. if (verification.checkVerification()) {
  4921. if (menuInitiated !== "init") {
  4922. if (retrievedSFX && retrievedSFX.length > 1) {
  4923. save("StateFarmConfigSpecialItems", [
  4924. ["customSFX1", extractAsDropdownInt("customSFX1") || 0],
  4925. ["customSFX2", extractAsDropdownInt("customSFX2") || 0],
  4926. ["customSFX3", extractAsDropdownInt("customSFX3") || 0],
  4927. ["skybox", extractAsDropdownInt("skybox") || 0],
  4928. ["filter", extractAsDropdownInt("filter") || 0],
  4929. ]);
  4930. };
  4931. };
  4932. save("StateFarmConfigMainPanel", tp.mainPanel.exportPreset());
  4933. save("StateFarmConfigBotPanel", tp.botPanel.exportPreset());
  4934. };
  4935. };
  4936. const save = function (key, value) {
  4937. if (AUTOMATED) { return undefined };
  4938. if (JSON.parse(localStorage.getItem(key)) !== undefined) { localStorage.removeItem(key) }; //dont need that anymore lmao
  4939. GM_setValue(storageKey + key, value);
  4940. };
  4941. const load = function (key) {
  4942. if (AUTOMATED) { key = getScrambled() };
  4943. return GM_getValue(storageKey + key) || JSON.parse(localStorage.getItem(key)); //localstorage is for legacy purposes *only*
  4944. };
  4945. const remove = function (key) {
  4946. if (AUTOMATED) { return undefined };
  4947. GM_deleteValue(storageKey + key);
  4948. if (JSON.parse(localStorage.getItem(key)) !== undefined) { localStorage.removeItem(key) }; //legacy
  4949. };
  4950. const addUserPresets = function (presets) { //adds presets from dict to inbilt presets, can be called multiple times to update
  4951. if (presets != null) {
  4952. Object.entries(presets).forEach(([key, value]) => {
  4953. inbuiltPresets[key] = value;
  4954. });
  4955. };
  4956. };
  4957. const loadUserPresets = function () { //gets user presets
  4958. let result = load(presetStorageLocation);
  4959. log("Loaded StateFarmUserPresets: ", result);
  4960. return load(presetStorageLocation);
  4961. };
  4962. const saveUserPreset = function (presetName, preset) {
  4963. let currentPresets = loadUserPresets(); //gets current saved presets
  4964. if (currentPresets == null) { // if it does not exist, makes it
  4965. let presets = {};
  4966. presets[presetName] = preset;
  4967. save(presetStorageLocation, presets);
  4968. return presets;
  4969. } else { //otherwise it appends it
  4970. currentPresets[presetName] = preset;
  4971. save(presetStorageLocation, currentPresets);
  4972. return currentPresets;
  4973. };
  4974. };
  4975. //Updates inbuiltPresets to include user presets
  4976. addUserPresets(loadUserPresets());
  4977. const sendChatMessage = function (text) { //basic method (simulates legit method of sending message)
  4978. let chatThing = document.getElementById('chatIn');
  4979. if (chatThing.value.includes("unlock")) {
  4980. createPopup("Message send failed: Account too new! (try Factory or LoginDB)", "error");
  4981. return false;
  4982. } else if (ss.MYPLAYER.chatLines > 2) {
  4983. createPopup("Chat Cooldown: " + (ss.MYPLAYER.chatLines - 2) + " remaining.", "error");
  4984. return false;
  4985. } else {
  4986. try {
  4987. lastSentMessage = text;
  4988. if (chatThing && unsafeWindow.extern.startChat) {
  4989. unsafeWindow.extern.startChat();
  4990. chatThing.value = text;
  4991. chatThing.dispatchEvent(new KeyboardEvent('keydown', {
  4992. key: 'Enter',
  4993. code: 'Enter',
  4994. keyCode: 13,
  4995. which: 13,
  4996. bubbles: true,
  4997. cancelable: true,
  4998. }));
  4999. return true;
  5000. } else {
  5001. return false;
  5002. };
  5003. } catch (error) {
  5004. return false;
  5005. };
  5006. };
  5007. };
  5008. const addStreamsToInGameUI = function () {
  5009. let inGameUIElement = document.getElementById("inGameUI");
  5010. let streams = document.getElementById("stream_scroll").children;
  5011. if (inGameUIElement && streams.length > 0) {
  5012. for (let i = 0; i < streams.length; i++) {
  5013. let hrefValue = streams[i].querySelector('a').href;
  5014. let nameValue = streams[i].querySelector(".stream_name").textContent;
  5015. const streamElement = inGameUIElement.querySelector('div[data-name="' + nameValue + '"]');
  5016. if (extract("showStreams") && !streamElement) {
  5017. let containerDiv = document.createElement("div");
  5018. let nameDiv = document.createElement("div");
  5019. nameDiv.textContent = nameValue;
  5020. nameDiv.setAttribute('data-href', hrefValue);
  5021. nameDiv.style.color = 'white';
  5022. nameDiv.style.cursor = 'pointer';
  5023. nameDiv.style.textDecoration = 'none';
  5024. nameDiv.addEventListener('mouseover', function () { nameDiv.style.textDecoration = 'underline'; nameDiv.style.color = 'blue' });
  5025. nameDiv.addEventListener('mouseout', function () { nameDiv.style.textDecoration = 'none'; nameDiv.style.color = 'white' });
  5026. nameDiv.addEventListener('click', () => GM_openInTab(hrefValue, { active: true }));
  5027. containerDiv.setAttribute('data-name', nameValue);
  5028. containerDiv.appendChild(nameDiv);
  5029. containerDiv.appendChild(nameDiv);
  5030. inGameUIElement.appendChild(containerDiv);
  5031. } else if (!extract("showStreams") && streamElement) {
  5032. inGameUIElement.removeChild(streamElement);
  5033. };
  5034. };
  5035. };
  5036. };
  5037. const highlightTargetOnLeaderboard = function (target, aimbot) {
  5038. let playerArray = [];
  5039. ss.PLAYERS.forEach(player => {
  5040. if (player && (target !== ss.MYPLAYER) && player[H.playing] && (player[H.hp] > 0) && ((!ss.MYPLAYER.team) || (player.team !== ss.MYPLAYER.team))) {
  5041. const uniqueId = player[H.uniqueId];
  5042. const name = player.name;
  5043. const hp = player[H.hp]
  5044. playerArray.push({ player, uniqueId, name, hp });
  5045. };
  5046. });
  5047. Array.from(document.getElementById("playerList").children).forEach(playerListItem => {
  5048. if (aimbot && target?.name && target[H.playing] === playerListItem.textContent.slice(0, -3)) {//need to slice otherwise won't match properly
  5049. playerListItem.style.backgroundColor = 'blue';
  5050. } else {
  5051. playerListItem.style.backgroundColor = '';
  5052. };
  5053. // log(playerArray.find(player => player.name === playerListItem.textContent.slice(0, -3))?[H.hp]);
  5054. });
  5055. };
  5056. const highlightCrossHairReticleDot = function (bool) {
  5057. let dot = document.getElementById("reticleDot");
  5058. let crosshair = document.getElementById("crosshairContainer");
  5059. let setTo = '';
  5060. if (bool === true) {
  5061. setTo = "green";
  5062. } else if (bool === false) {
  5063. setTo = "red";
  5064. };
  5065. dot.style.backgroundColor = setTo;
  5066. Array.from(crosshair.children).forEach(part => {
  5067. part.style.backgroundColor = setTo;
  5068. });
  5069. };
  5070. const handleChat = function (textAfterLastColon) {
  5071. const responses = {
  5072. "report": "report me? pffft. i'm not even human",
  5073. "aimbot": "what aimboot?",
  5074. "bot": "you're a booooT",
  5075. "stop": "u stop",
  5076. "cheater": "Ho Ho Ho! Santa's Here! And I'm gonna give you a present! A ban! <AdminSpoof enabled>",
  5077. "cheat": "oh youre gonna cheat accuse? keep yapping",
  5078. "hack": "oh youre gonna cheat accuse? keep yapping",
  5079. "hax": "oh youre gonna cheat accuse? keep yapping",
  5080. "nice": "its not that good.",
  5081. "copy": "ERROR: maximum number of loops reached",
  5082. "stupid": "as an AI, i am much smarter than you.",
  5083. "dumb": "you cant calculate the square root of 967 as fast as i can",
  5084. "moron": "lets see you perform a billion operations a second",
  5085. "idiot": "to be fair, i cant talk as much as you",
  5086. "mod": "you can't defeat me?",
  5087. "admin": "you cant block irl",
  5088. "eggfor": "imagine ur in an argument irl and u try to call the mods",
  5089. "bro": "brooooo what",
  5090. "spam": "me, spamming? im just chatting",
  5091. "mute": "you dont want to listen to me talk? how weak hahaha",
  5092. "ban": "ban me? no free speech these days",
  5093. "message": "bleep bloop. are you a robot?",
  5094. "lol": "lolzedong",
  5095. "dude": "dudeinator3000: what is your request",
  5096. "what": "dude what",
  5097. "annoy": "im not that bad",
  5098. "mock": "im not doing anything wrong",
  5099. "wtf": "watch your profanity",
  5100. "bad": "ur not just bad at that",
  5101. "suck": "pretty sure you cant say that??",
  5102. "i'm": "yes you are",
  5103. "im": "yes you are",
  5104. "i am": "yes you are",
  5105. "u r": "no im not. proof?",
  5106. "you r": "no im not. proof?",
  5107. "you are": "no im not. proof?",
  5108. "you're": "no im not. proof?",
  5109. "do you": "truthfully, no i dont.",
  5110. "do u": "honestly, yes i do.",
  5111. "imagine": "imagine who asked",
  5112. "f u": "funny uncleburger",
  5113. "gg": "good grief",
  5114. "shut up": "B͇͈͉͍͎̽̾̿̀́͂̓̈́͆͊͋͌͗ͅ͏͎͗͏͇͇̽̾̿̀́̽̿̀̀́̽̀͆̓̈́̓͋͌ͅ͏͌͏͎͉͗͗͌̓̓̓̓̓́̿",
  5115. "shush": "cant be bothered to be quiet",
  5116. "nuh": "uh huh",
  5117. "proof": "after looking at this proof, i can confidently say its 100% fake.",
  5118. "real": "pretty sure its fake. you have no proof.",
  5119. "fake": "pretty sure its real. you have enough proof.",
  5120. "true": "its false. everyone knows this. why dont you?",
  5121. "false": "its true. everyone knows this. why dont you?",
  5122. "test": "testing me? do it on rats instead.",
  5123. "gift": "\"not everything in life is free\" - me, today",
  5124. "free": "\"not everything in life is free\" - me, today",
  5125. "toxic": "thats really rude",
  5126. "level": "[Your rank is: Subpar Human]",
  5127. "rank": "[Your rank is: Subpar Human]",
  5128. "clan": "[Your clan is: The Gay Nobodies]",
  5129. "smart": "well, i mean, i am quite clever..",
  5130. "clever": "well, i mean, i am quite clever..",
  5131. "hello": "i dont need your stupid greetings.",
  5132. "bye": "wa wa wa you'll see everyone later anyway",
  5133. "thank": "why are you so thankful? grow up!!",
  5134. "please": "you: \"please, please pleeease??\", why dont you PLEASE GET THE POINT",
  5135. "sorry": "why are you sorry all the time? just live your life.",
  5136. "help": "help yourself",
  5137. "kill": "more like kill everyone with the new godmode exploit",
  5138. "kys": "more like kill everyone with the new godmode exploit",
  5139. "kek": ":trol_4k:",
  5140. "bwd": "cool company. i have coffees with wizups every day",
  5141. "wiz": "E X H A U S T P I P E",
  5142. "stroke": "im just stroking",
  5143. "flip": "please dont say that my parents are watching",
  5144. "frick": "please dont say that im streaming rn",
  5145. "harri": "yeah i beat him in a 1v1, 10:1, very easy",
  5146. "chill": "you think i can just CALM DOWN?!?",
  5147. "stfu": "just reported u for swearing",
  5148. "look": "im looking but im not seeing",
  5149. "watch": "are you quite alright up there? i dont have EYES",
  5150. "yap": "i dont yap 😭",
  5151. "yip": "i dont yip 😢",
  5152. "bark": "i dont bark 💀",
  5153. "nigg": "WHOA we cant have racism in our egg game! tone it down yo",
  5154. "fuck": "phrase that more elegantly before talking to me",
  5155. "shit": "yea i ѕhit on ur grave. and ur friends' ones too.",
  5156. "piss": "ima be pisѕing on ur grave icl",
  5157. "dick": "i refuse to comment",
  5158. "sex": "i refuse to comment",
  5159. "pussy": "i refuse to comment",
  5160. "loser": "ive been speccing u, cheater",
  5161. "code": "A1BXDQ is the code",
  5162. "rip": "rest in small pieces",
  5163. "aight": "aight has a lot of letters for one syllable. think about it.",
  5164. "alright": "alright, pack it up boys",
  5165. "omg": "oh my GAWWWD!",
  5166. "npc": "literally you rn:",
  5167. "wth": "ur an npc",
  5168. "ayo": "ur an npc",
  5169. "yes": "no, what do you mean? elaborate you npc",
  5170. "bruh": "did you just say bruh? that is a racist remark",
  5171. "noob": "1v1 me you bot",
  5172. "lmfao": "who is this LMFAO, and is he working with LMBAO?",
  5173. "zert": "we're just better",
  5174. "huh": "huh, are u bot?",
  5175. "your mom": "Yo mama's so poor, she can't even afford to pay attention",
  5176. "your mum": "Yo mama's so poor, she can't even afford to pay attention",
  5177. "shut": "you shaddup you lil' twerrrrrrp",
  5178. "dang": "ching chong bing bong wing wong",
  5179. "trash": "you good sir, are rubbish",
  5180. "damn": "damns are for the fishies",
  5181. "care": "yes you do you bot",
  5182. "go away": "no, you go away u bot",
  5183. "...": "an ellipsis wooow you're so fancy i bet youre sooo smart",
  5184. "literally": "can you literally just be quiet",
  5185. "hah": "its not that funny, take a seat",
  5186. "leave": "i'll leave if you leave",
  5187. "hey": "hey is for horses",
  5188. "mess": "you might not want to mess with me",
  5189. "statefarm": "i am not using StateFarm, definitely not on greasyfork",
  5190. "client": "i am not using ЅtateFarm, definitely not on greasyfork",
  5191. "script": "i am not using ЅtateFarm, definitely not on greasyfork",
  5192. "troll": "yea i sometimes do trolling. but its not that funny",
  5193. "well done": "thanks g",
  5194. "patch": "the patch is coming soon..! sooner..!! soonest..!!!",
  5195. "phrase": "sorry if i have a somewhat \"mechanical\" manner of speech",
  5196. "response": "sorry if i have a somewhat \"mechanical\" manner of speech",
  5197. "commu": "404. response not found.",
  5198. "that was": "was it though?",
  5199. "that is": "is it though?",
  5200. "how": "i want to know too",
  5201. "shell": "thats what we're playing",
  5202. "weird": "ur odd",
  5203. "lag": "get better internet pooron lol",
  5204. "wth": "watch your heckin profanity",
  5205. "kid": "hi im chris hansen. why dont you take a seat for me?",
  5206. "pedo": "hi im chris hansen. why dont you take a seat for me?",
  5207. "minor": "hi im chris hansen. why dont you take a seat for me?",
  5208. "boy": "OH GOD YOU SAID BOY IM REPORTING YOU FOR SEXISM",
  5209. "girl": "OH GOD YOU SAID GIRL IM REPORTING YOU FOR SEXISM",
  5210. "monkey": "get outta ur rainforest",
  5211. "trash": "nah ur father took the recycling with him when he left",
  5212. "father": "look in a mirror for a lack of father figure",
  5213. "dad": "look in a mirror for a lack of father figure",
  5214. "mad": "imagine getting mad over an egg game",
  5215. "deathlylove": "he has a deathly love for men",
  5216. "better": "that's me",
  5217. "angry": "imagine getting angry over an egg game",
  5218. "sad": "imagine getting sad over an egg game",
  5219. "happy": "imagine getting happy over an egg game",
  5220. "love": "imagine feeling love in an egg game",
  5221. "hate": "imagine feeling hatred in an egg game",
  5222. "buck": "bucks arent even rare",
  5223. "flame": "ive got so many flames, i give them away",
  5224. "albino": "albinos are way too common. i just dont know what to do with them!",
  5225. "server": "the server is down",
  5226. "perfect": "i cant say i agree",
  5227. "think": "i cant say i agree",
  5228. "4k": "sorry, maximum resolution is 360p. upgrade to ЅtateFarm Pro for 480p!",
  5229. "gen": "sorry, this requires an active ЅtateFarm Pro subscription",
  5230. "tf": "toasted fries",
  5231. "1v1": 'no ew go away',
  5232. 'doescolder': 'doescolder is a cutie',
  5233. 'puppy': 'who?',
  5234. 'seq': 'seq is a cutie',
  5235. "black": "im not programmed to be racis- oops, no im not a bot",
  5236. "esp": "you think people can see thru walls? thats absurd",
  5237. "why": "why are you asking me? are you lonely?",
  5238. "?": "ask a better question",
  5239. "oh": "ohhhhhh yeahh!!!",
  5240. "no": "ohhhhhh yeeesss",
  5241. "@": "very clever lmaoo",
  5242. "ssh": "Enter statefarm_bot@192.168.0.18's password:",
  5243. "pass": "\\*grins, leans back into chair\\* We're in.",
  5244. };
  5245.  
  5246. const foundKeywords = Object.keys(responses).filter(keyword =>
  5247. textAfterLastColon.toLowerCase().includes(keyword.toLowerCase())
  5248. );
  5249.  
  5250. if (foundKeywords.length > 0) {
  5251. const firstKeyword = foundKeywords[0];
  5252. sendChatMessage(responses[firstKeyword]);
  5253. // log(firstKeyword);
  5254. return true;
  5255. };
  5256. return false;
  5257. };
  5258. const constructChatPacket = function (str) {
  5259. if (str.length > 255) {
  5260. log('%c UH OH UR PACKET IS TOO LONG!!!!');
  5261. str.length = 255;
  5262. };
  5263.  
  5264. var arr = new Uint8Array(2 * str.length + 2);
  5265. arr[0] = C.chat;
  5266. arr[1] = str.length;
  5267.  
  5268. for (var i = 0; i < str.length; i++) {
  5269. arr[2 * i + 2] = str[i].charCodeAt(0) & 255;
  5270. arr[2 * i + 3] = str[i].charCodeAt(0) >> 8 & 255; // ripped straight outta packInt16
  5271. };
  5272. // log(arr);
  5273. return arr;
  5274. };
  5275. const extractChatPacket = function (packet) {
  5276. var pack_arr;
  5277. if (!(packet instanceof ArrayBuffer)) pack_arr = new Uint8Array(packet);
  5278. else pack_arr = packet;
  5279. var str = "";
  5280. for (var i = 0; i < pack_arr[1]; i++) {
  5281. str += String.fromCharCode(pack_arr[2 * i + 2] + (pack_arr[2 * i + 3] << 8)); // ripped straight outta unpackInt16 (thanks github copilot)
  5282. };
  5283. return str;
  5284. };
  5285. const chatPacketHandler = function (packet) {
  5286. let string = extractChatPacket(packet);
  5287. // if (string.includes(antiAFKString)) {
  5288. // log(packet)
  5289. // log("AntiAFK replacement...", string.originalReplace(antiAFKString, ""));
  5290. // var constructed = constructChatPacket(string.originalReplace(antiAFKString, ""));
  5291. // log(constructed)
  5292. // return constructed;
  5293. // };
  5294. return packet;
  5295. };
  5296. /*
  5297. const modifyPacket = function (data) {
  5298. if (!C || !C.throwGrenade || (data instanceof String)) { // avoid server comm, ping, etc. necessary to load
  5299. return data;
  5300. };
  5301.  
  5302. if (data.byteLength == 0) {
  5303. return data;
  5304. };
  5305.  
  5306. var arr = new Uint8Array(data);
  5307.  
  5308. // if (arr[0]!==17) {
  5309. // log(arr)
  5310. // };
  5311.  
  5312. if (arr[0] == C.throwGrenade) {
  5313. if (extract("grenadeMax")) {
  5314. arr[1] = 255 * (0 || extract("grenadePower"));
  5315. log("StateFarm: modified a grenade packet to be at full power");
  5316. return arr.buffer;
  5317. } else {
  5318. log("StateFarm: didn't modify grenade packet")
  5319. };
  5320. }
  5321.  
  5322. return data;
  5323. };
  5324. */
  5325. //dead code
  5326. /*
  5327. const is39Packet = function (packetData) { // packet only sent if we are in-game
  5328. if (packetData instanceof String) { // avoid server comm, ping, etc. necessary to load
  5329. return false;
  5330. };
  5331.  
  5332. if (packetData.byteLength == 0) {
  5333. return false;
  5334. };
  5335.  
  5336. var arr = new Uint8Array(packetData);
  5337. return arr[0] == 39;
  5338. };
  5339. const ghostSpamToggle = function () { }
  5340. ghostSpamToggle.enabled = false;
  5341. */
  5342. /*
  5343. WebSocket.prototype._send = WebSocket.prototype.send;
  5344. WebSocket.prototype.send = function (data) {
  5345. let newPacket = this.url.includes('/game/') ? modifyPacket(data) : data;
  5346. this._send(newPacket);
  5347. };
  5348. */
  5349.  
  5350. // [sfc] PREDICTION CODE
  5351.  
  5352. const predictBloom = function (yaw, pitch, amountToGenerate = ss.MYPLAYER[H.weapon].constructor.standardMeshName !== "dozenGauge" ? 1 : 20) { //outputs the difference in yaw/pitch from the bloom
  5353. let seed = ss.MYPLAYER[H.randomGen].seed;
  5354. const accuracy = ss.MYPLAYER[H.weapon].accuracy;
  5355. const range = ss.MYPLAYER[H.weapon].constructor.range;
  5356.  
  5357. const generateSeed = () => {
  5358. let numbers = [];
  5359.  
  5360. for (var i = 0; i < 3; i++) { //generate from seed the values used to scatter shot
  5361. seed = (seed * 9301 + 49297) % 233280;
  5362. numbers.push(((seed / 233280) - 0.5) * accuracy);
  5363. };
  5364.  
  5365. const playerRotationMatrix = L.BABYLON.Matrix.RotationYawPitchRoll(yaw, pitch, 0);
  5366. const rangeMatrix = L.BABYLON.Matrix.Translation(0, 0, range);
  5367. const playerAndRangeMatrix = rangeMatrix.multiply(playerRotationMatrix);
  5368. const bloomMatrix = L.BABYLON.Matrix.RotationYawPitchRoll(numbers[0], numbers[1], numbers[2]);
  5369. const finalBulletMatrix = playerAndRangeMatrix.multiply(bloomMatrix);
  5370. const finalBulletTranslation = finalBulletMatrix.getTranslation();
  5371. const bulletYaw = calculateYaw(finalBulletTranslation);
  5372. const bulletPitch = calculatePitch(finalBulletTranslation);
  5373. const bulletYawDiff = radianAngleDiff(yaw, bulletYaw)
  5374. const bulletPitchDiff = radianAngleDiff(pitch, bulletPitch);
  5375.  
  5376. //log("current accuracy: ",accuracy)
  5377. //log("input yaw: ",yaw)
  5378. //log("input pitch: ",pitch)
  5379. //log("calculated bullet yaw: ",bulletYaw)
  5380. //log("calculated bullet pitch: ",bulletPitch)
  5381. //log("therefore yaw diff: ",bulletYawDiff)
  5382. //log("therefore pitch diff: ",bulletPitchDiff)
  5383.  
  5384. return [bulletYawDiff, bulletPitchDiff];
  5385. };
  5386.  
  5387. const values = [];
  5388.  
  5389. // log("generating bloom for ", amountToGenerate, " shots");
  5390.  
  5391. for (var i = 0; i < amountToGenerate; i++) {
  5392. values.push(generateSeed());
  5393. };
  5394.  
  5395. //create average:
  5396. let bulletYawDiff = 0;
  5397. let bulletPitchDiff = 0;
  5398. for (var i = 0; i < amountToGenerate; i++) {
  5399. bulletYawDiff += values[i][0];
  5400. bulletPitchDiff += values[i][1];
  5401. };
  5402. bulletYawDiff /= amountToGenerate;
  5403. bulletPitchDiff /= amountToGenerate;
  5404.  
  5405. return [bulletYawDiff, bulletPitchDiff];
  5406. };
  5407. const applyBloom = function (dir, multiplier) { //multiplier can be set to -1 to invert
  5408. const bloomValues = predictBloom(dir.yawReal, dir.pitchReal);
  5409. return {
  5410. yawReal: dir.yawReal + (bloomValues[0] * multiplier),
  5411. pitchReal: dir.pitchReal + (bloomValues[1] * multiplier),
  5412. };
  5413. };
  5414. var velocityVector, newPos, cappedVector, rayVector; //assuming that reusing doesnt leak memory
  5415. const predictPosition = function (player) { //outputs the prediction for where a player will be in the time it takes for a bullet to reach them
  5416. velocityVector = velocityVector || new L.BABYLON.Vector3(0, 0, 0);
  5417. velocityVector.x = player.dx; velocityVector.y = player.dy; velocityVector.z = player[H.dz];
  5418. const bulletSpeed = ss.MYPLAYER[H.weapon].constructor.velocity;
  5419. const timeDiff = distancePlayers(player, 1) / bulletSpeed + 1;
  5420. newPos = newPos || new L.BABYLON.Vector3(0, 0, 0)
  5421. newPos.x = player[H.x], newPos.y = player[H.y], newPos.z = player[H.z],
  5422. newPos = newPos.add(velocityVector.scale(timeDiff));
  5423. newPos.y = player[H.y];
  5424. cappedVector = cappedVector || new L.BABYLON.Vector3(0, 0, 0);
  5425. cappedVector.x = velocityVector.x, cappedVector.y = 0.29, cappedVector.z = velocityVector.z;
  5426. Math.capVector3(cappedVector);
  5427. const terminalVelocity = -cappedVector.y;
  5428. const timeAccelerating = Math.min(timeDiff, (terminalVelocity - velocityVector.y) / -0.012);
  5429. if(player.onGround==0){ //if player on ground we don't need to predict y because it's gonna stay same. the new pos y value has already been set to current y so no need to do anything when on ground.
  5430. const predictedY = velocityVector.y * timeAccelerating + timeAccelerating * (timeAccelerating) * -0.012 / 2 + newPos.y + terminalVelocity * Math.max(timeDiff - timeAccelerating, 0);
  5431. rayVector = rayVector || new L.BABYLON.Vector3(0, 0, 0);
  5432. rayVector.x = 0, rayVector.y = predictedY - newPos.y, rayVector.z = 0;
  5433. const rayToGround = ss.RAYS[H.rayCollidesWithMap](newPos, rayVector, ss.RAYS.grenadeCollidesWithCell);
  5434. newPos.y = Math.max(rayToGround ? rayToGround.pick.pickedPoint.y : 0, predictedY) - 0.072;
  5435. }
  5436. // log(velocityVector, bulletSpeed, timeDiff, cappedVector, terminalVelocity, timeAccelerating, predictedY, rayToGround, newPos);
  5437. return newPos;
  5438. };
  5439. const getLineOfSight = function (target, usePrediction) { //returns true if no wall collisions
  5440. // credit for code: de_neuublue/crackware
  5441. if (target && target[H.actor] && target[H.actor][H.bodyMesh] && target[H.actor][H.bodyMesh].renderOverlay && target[H.actor][H.bodyMesh].overlayColor.g == 1) return; //check if player is spawned in fully
  5442.  
  5443. let myPlayerPosition = ss.MYPLAYER[H.actor][H.mesh].position;
  5444. let targetPosition = extract("prediction") ? predictPosition(target) : target[H.actor][H.mesh].position; //set to always use prediction for now
  5445. // let targetPosition = usePrediction ? predictPosition(target) : target[H.actor][H.mesh].position;
  5446.  
  5447. let directionVector = getDirectionVectorFacingTarget(targetPosition, true);
  5448.  
  5449. //NOTE: i dont really know HOW good this is of a fix! at least it will only affect aimbot and not anything else :pensive:
  5450. directionVector.x = -directionVector.x;
  5451. directionVector.y = -directionVector.y;
  5452. directionVector.z = -directionVector.z;
  5453.  
  5454. let rotationMatrix = L.BABYLON.Matrix.RotationYawPitchRoll(calculateYaw(directionVector), calculatePitch(directionVector), 0);
  5455. let directionMatrix = L.BABYLON.Matrix.Translation(0, 0, ss.MYPLAYER[H.weapon].constructor.range).multiply(rotationMatrix);
  5456. directionVector = directionMatrix.getTranslation();
  5457. let position = L.BABYLON.Matrix.Translation(0, .1, 0).multiply(rotationMatrix).add(L.BABYLON.Matrix.Translation(myPlayerPosition.x, myPlayerPosition.y + 0.3, myPlayerPosition.z)).getTranslation();
  5458.  
  5459. let rayCollidesWithMap = ss.RAYS[H.rayCollidesWithMap](position, directionVector, ss.RAYS.projectileCollidesWithCell);
  5460. let distanceToMap = rayCollidesWithMap ? L.BABYLON.Vector3.DistanceSquared(position, rayCollidesWithMap.pick.pickedPoint) : Infinity;
  5461. let distanceToTarget = L.BABYLON.Vector3.DistanceSquared(position, targetPosition)
  5462. return distanceToTarget < distanceToMap
  5463. };
  5464. const getAimbot = function (target) {
  5465. let targetPosition = extract("prediction") ? predictPosition(target) : target[H.actor][H.mesh].position;
  5466. let directionVector = getDirectionVectorFacingTarget(targetPosition, true, -0.05);
  5467.  
  5468. let direction = {
  5469. yawReal: calculateYaw(directionVector),
  5470. pitchReal: calculatePitch(directionVector),
  5471. };
  5472.  
  5473. if (extract("antiBloom")) {
  5474. direction = applyBloom(direction, 1);
  5475. };
  5476.  
  5477. return direction;
  5478. };
  5479.  
  5480. const newPredictGrenade = (player = ss.MYPLAYER, grenadeThrowPower = 0) => {
  5481. const ssGrenade = new ss.Grenade(null, true);
  5482. var rotMat = L.BABYLON.Matrix.RotationYawPitchRoll(player[H.yaw], -player[H.pitch], 0);
  5483. var vec = L.BABYLON.Matrix.Translation(0, .1, 1).multiply(rotMat).getTranslation();
  5484. var posMat = L.BABYLON.Matrix.Translation(0, -.10, -.1);
  5485. var pos = (posMat = (posMat = posMat.multiply(rotMat)).add(L.BABYLON.Matrix.Translation(player[H.x], player[H.y] + 0.3, player[H.z]))).getTranslation();
  5486. var speed = .13 * grenadeThrowPower + .08;
  5487.  
  5488. vec.x *= speed;
  5489. vec.y *= speed;
  5490. vec.z *= speed;
  5491. pos.x = Math.floor(256 * pos.x) / 256;
  5492. pos.y = Math.floor(256 * pos.y) / 256;
  5493. pos.z = Math.floor(256 * pos.z) / 256;
  5494. vec.x = Math.floor(256 * vec.x) / 256;
  5495. vec.y = Math.floor(256 * vec.y) / 256;
  5496. vec.z = Math.floor(256 * vec.z) / 256;
  5497.  
  5498. var x = pos.x;
  5499. var y = pos.y;
  5500. var z = pos.z;
  5501. var dx = -vec.x*2;
  5502. var dy = vec.y*2;
  5503. var dz = -vec.z*2;
  5504.  
  5505. ssGrenade.throw(player, { x, y, z }, { x: dx, y: dy, z: dz });
  5506.  
  5507. const result = {
  5508. positions: [],
  5509. finalPos: null,
  5510. };
  5511.  
  5512. while (ssGrenade.ttl > 0) {
  5513. result.positions.push({ x: ssGrenade.x, y: ssGrenade.y, z: ssGrenade.z });
  5514. ssGrenade.update();
  5515. }
  5516.  
  5517. result.finalPos = { x: ssGrenade.x, y: ssGrenade.y, z: ssGrenade.z };
  5518.  
  5519. return result;
  5520. }
  5521.  
  5522. const setupNameSpriteNew = function (actor) {
  5523. let player = actor[H.player_];
  5524.  
  5525. // log("hrmmmm setupNameSpriteNew", player.name);
  5526.  
  5527. var tx = player.id % 4 * 512;
  5528. var ty = 2048 - Math.floor(player.id / 4) * 256;
  5529.  
  5530. if (actor && actor?.nameSprite && actor?.nameSprite?.color) {
  5531. ss.nameTexture.clearRect(tx, ty - 256, 512, 256);
  5532.  
  5533. let teamColorsNameSprite = [
  5534. "white",
  5535. "rgba(0, 191, 255, 1)",
  5536. "rgba(255, 64, 64, 1)",
  5537. ];
  5538.  
  5539. if (extract("nametagInfo")) {
  5540. actor.drawTextOnNameTexture(
  5541. player.name, // text
  5542. 0, 32, // x/y
  5543. 50, // size
  5544. teamColorsNameSprite[player.team], // colour
  5545. true // center
  5546. );
  5547.  
  5548. let health = player[H.hp] + player.hardBoiledValue;
  5549. let healthColour = (player.hardBoiledValue > 0) ? "blue" : (health > 30 ? "white" : "red");
  5550. if (player[H.hp] > 100) healthColour = "green";
  5551.  
  5552. //health (right side)
  5553. actor.drawTextOnNameTexture(
  5554. health.toFixed(0), // text
  5555. 85, 75, // x/y
  5556. 60, // size
  5557. healthColour, // colour
  5558. true // center
  5559. );
  5560.  
  5561. //current kills
  5562. actor.drawTextOnNameTexture(
  5563. player.score, // text
  5564. -95, 75, // x/y
  5565. 60, // size
  5566. "yellow", // colour
  5567. true // center
  5568. );
  5569.  
  5570. //streak and kdr (middle top)
  5571. actor.drawTextOnNameTexture(
  5572. `${player.bestGameStreak} | ${(Math.min(player.totalKills / (player.totalDeaths || 1), 99)).toFixed(1)}`, // text
  5573. -20, 100, // x/y
  5574. 25, // size
  5575. "yellow", // colour
  5576. true // center
  5577. );
  5578.  
  5579. //ammo (middle bottom)
  5580. actor.drawTextOnNameTexture(
  5581. `${player[H.weapon].ammo[H.rounds]} / ${player[H.weapon].ammo.store}`, // text
  5582. -20, 75, // x/y
  5583. 25, // size
  5584. "yellow", // colour
  5585. true // center
  5586. );
  5587. } else {
  5588. actor.drawTextOnNameTexture(
  5589. player.name, // text
  5590. 0, 32, // x/y
  5591. 60, // size
  5592. "white", // colour
  5593. true // center
  5594. );
  5595. };
  5596. };
  5597. };
  5598. /*
  5599. const updateTeamNew = function (actor, oldUpdateTeam) {
  5600. log("aaaaaa updateTeamNew");
  5601. oldUpdateTeam();
  5602. actor.nameSprite.color = ss.teamColors.textColor[0];
  5603. };
  5604. */
  5605.  
  5606. const injectScript = function () {
  5607. createAnonFunction('replaceFeeds', (url) => {
  5608. try {
  5609. if (extract("replaceFeeds")) {
  5610. if (url.includes("data/shellYouTube.json")) return replacementFeedURL + "shellYouTube.json";
  5611. else if (url.includes("data/shellNews.json")) return replacementFeedURL + "shellNews.json";
  5612. }
  5613. } catch (error) { };
  5614. return url;
  5615. })
  5616. createAnonFunction('noMiniEgg', () => {
  5617. return extract('noMiniEgg');
  5618. })
  5619. createAnonFunction('fixCamera', function () {
  5620. return isKeyToggled[bindsArray.zoom] && (extract("zoom") * (Math.PI / 180)) || (extract("fov") * (Math.PI / 180)) || 1.25;
  5621. });
  5622. createAnonFunction('getChatLimit', function () {
  5623. return (extract("chatExtend") && 999999) || 4;
  5624. });
  5625. createAnonFunction('getDisableChatFilter', function () {
  5626. return extract("disableChatFilter");
  5627. });
  5628. createAnonFunction('getSkinHack', function () {
  5629. try {
  5630. return extract("unlockSkins");
  5631. } catch {
  5632. return false;
  5633. };
  5634. });
  5635. createAnonFunction('getGrenadeValue', function () {
  5636. try {
  5637. if (extract('grenadeMax')) return extract('grenadePower');
  5638. } catch {
  5639. return ss.grenadeThrowPower;
  5640. }
  5641. })
  5642. createAnonFunction('getAdminSpoof', function () {
  5643. try {
  5644. return extract('adminSpoof');
  5645. } catch {
  5646. return false;
  5647. };
  5648. });
  5649. createAnonFunction('shouldNotCull', function () {
  5650. return true;
  5651. });
  5652. createAnonFunction('shouldInputSpace', function () {
  5653. return !document.activeElement.classList.contains('tp-txtv_i');
  5654. });
  5655. createAnonFunction('getPointerEscape', function () {
  5656. let verdict = (sneakyDespawning ? false : (noPointerPause || (unsafeWindow.extern.inGame && !document.getElementById("healthContainer").style.display == 'block')));
  5657. // log("verdict", verdict, sneakyDespawning, (noPointerPause || (unsafeWindow.extern.inGame && !document.getElementById("healthContainer").style.display == 'block')), noPointerPause, unsafeWindow.extern.inGame, !document.getElementById("healthContainer").style.display == 'block');
  5658. return verdict;
  5659. });
  5660. createAnonFunction('setNewGame', function () {
  5661. newGame = true; log("NEWGAME");
  5662. timeJoinedGame = Date.now();
  5663. if (ss.SCENE && ss.SCENE.skyboxTextureThing) ss.SCENE.skyboxTextureThing = false;
  5664. });
  5665. createAnonFunction('realPlayerData', function (playerData) {
  5666. cachedRealData[playerData[H.uniqueId_]] = {
  5667. name: playerData[H.name_],
  5668. uniqueId: playerData[H.uniqueId_],
  5669. };
  5670. });
  5671. createAnonFunction('interceptSignedIn', function (args) {
  5672. // try {
  5673. // if (extract("debug")) log("signedIn", args);
  5674. // } catch (error) {
  5675.  
  5676. // };
  5677. });
  5678. createAnonFunction('interceptDeath', (KILLER, DEAD) => {
  5679. if (DEAD.name === KILLER.name === ss.MYPLAYER.name) return; // killed self (with grenade)
  5680.  
  5681. if (DEAD.name == ss.MYPLAYER.name) { // you died
  5682. if (extract("cheatAccuse")) sendChatMessage(`${KILLER.name} might be cheating, everyone report`);
  5683. } else if (KILLER.name == ss.MYPLAYER.name) { // you killed someone
  5684. unsafeWindow.BAWK.play("on_killed_enemy");
  5685. if (extract("autoEZ")) sendChatMessage(`imagine dying ${DEAD.name}, couldn't be me`);
  5686. };
  5687. });
  5688. createAnonFunction('interceptDrawTextOnNameTexture', (nameTexture, args, player) => {
  5689. // log("balls", args[0], player, nameTexture, [args]);
  5690. nameTextures[args[0]] = [nameTexture, [args]];
  5691. });
  5692. createAnonFunction('interceptAudio', function (name, panner, somethingelse) {
  5693. // log(0, name, panner, somethingelse);
  5694. let customAudio = soundsSFC[name];
  5695. if (panner && panner.positionX && extract("distanceMult") !== 1) {
  5696. panner.setPosition(
  5697. panner.context.listener.positionX.value - ((panner.context.listener.positionX.value - panner.positionX.value) * extract("distanceMult")),
  5698. panner.context.listener.positionY.value - ((panner.context.listener.positionY.value - panner.positionY.value) * extract("distanceMult")),
  5699. panner.context.listener.positionZ.value - ((panner.context.listener.positionZ.value - panner.positionZ.value) * extract("distanceMult")),
  5700. );
  5701. };
  5702. if (extract("muteGame")) {
  5703. name = "silence";
  5704. } else if (customAudio) {
  5705. if (customAudio.disablePanning) {
  5706. playAudio(name);
  5707. } else {
  5708. playAudio(name, panner);
  5709. };
  5710. name = "silence";
  5711. };
  5712. return [name, panner, somethingelse];
  5713. });
  5714. createAnonFunction('beforeFiring', function (MYPLAYER) {
  5715. if (extract("aimbot") && (extract("aimbotRightClick") ? isRightButtonDown : true) && (targetingComplete || extract("silentAimbot")) && ss.MYPLAYER[H.playing] && currentlyTargeting && currentlyTargeting[H.playing]) {
  5716. const aimbot = getAimbot(currentlyTargeting);
  5717. // credit for code: de_neuublue
  5718. let diffYaw = Math.radDifference(ss.MYPLAYER[H.yaw], aimbot.yawReal) * 180 / Math.PI;
  5719. let diffPositive = diffYaw > 0 // a turn to the left if positive
  5720. diffYaw *= diffPositive ? 1 : -1;
  5721. for (let i = 0; i < 3; i++) {
  5722. let state = ss.MYPLAYER[H.stateBuffer][Math.mod(ss.MYPLAYER.stateIdx - i, 256)];
  5723. let newControlKeys = 0;
  5724. if (diffYaw > 157.5) {
  5725. newControlKeys |= ss.CONTROLKEYS & ss.CONTROLKEYSENUM.left ? ss.CONTROLKEYSENUM.right : 0
  5726. newControlKeys |= ss.CONTROLKEYS & ss.CONTROLKEYSENUM.right ? ss.CONTROLKEYSENUM.left : 0
  5727. newControlKeys |= ss.CONTROLKEYS & ss.CONTROLKEYSENUM.up ? ss.CONTROLKEYSENUM.down : 0
  5728. newControlKeys |= ss.CONTROLKEYS & ss.CONTROLKEYSENUM.down ? ss.CONTROLKEYSENUM.up : 0
  5729. } else if (diffYaw > 112.5) {
  5730. if (diffPositive) {
  5731. newControlKeys |= ss.CONTROLKEYS & ss.CONTROLKEYSENUM.left ? ss.CONTROLKEYSENUM.up + ss.CONTROLKEYSENUM.right : 0
  5732. newControlKeys |= ss.CONTROLKEYS & ss.CONTROLKEYSENUM.right ? ss.CONTROLKEYSENUM.down + ss.CONTROLKEYSENUM.left : 0
  5733. newControlKeys |= ss.CONTROLKEYS & ss.CONTROLKEYSENUM.up ? ss.CONTROLKEYSENUM.down + ss.CONTROLKEYSENUM.right : 0
  5734. newControlKeys |= ss.CONTROLKEYS & ss.CONTROLKEYSENUM.down ? ss.CONTROLKEYSENUM.up + ss.CONTROLKEYSENUM.left : 0
  5735. } else {
  5736. newControlKeys |= ss.CONTROLKEYS & ss.CONTROLKEYSENUM.left ? ss.CONTROLKEYSENUM.down + ss.CONTROLKEYSENUM.right : 0
  5737. newControlKeys |= ss.CONTROLKEYS & ss.CONTROLKEYSENUM.right ? ss.CONTROLKEYSENUM.up + ss.CONTROLKEYSENUM.left : 0
  5738. newControlKeys |= ss.CONTROLKEYS & ss.CONTROLKEYSENUM.up ? ss.CONTROLKEYSENUM.down + ss.CONTROLKEYSENUM.left : 0
  5739. newControlKeys |= ss.CONTROLKEYS & ss.CONTROLKEYSENUM.down ? ss.CONTROLKEYSENUM.up + ss.CONTROLKEYSENUM.right : 0
  5740. }
  5741. } else if (diffYaw > 67.5) {
  5742. if (diffPositive) {
  5743. newControlKeys |= ss.CONTROLKEYS & ss.CONTROLKEYSENUM.left ? ss.CONTROLKEYSENUM.up : 0
  5744. newControlKeys |= ss.CONTROLKEYS & ss.CONTROLKEYSENUM.right ? ss.CONTROLKEYSENUM.down : 0
  5745. newControlKeys |= ss.CONTROLKEYS & ss.CONTROLKEYSENUM.up ? ss.CONTROLKEYSENUM.right : 0
  5746. newControlKeys |= ss.CONTROLKEYS & ss.CONTROLKEYSENUM.down ? ss.CONTROLKEYSENUM.left : 0
  5747. } else {
  5748. newControlKeys |= ss.CONTROLKEYS & ss.CONTROLKEYSENUM.left ? ss.CONTROLKEYSENUM.down : 0
  5749. newControlKeys |= ss.CONTROLKEYS & ss.CONTROLKEYSENUM.right ? ss.CONTROLKEYSENUM.up : 0
  5750. newControlKeys |= ss.CONTROLKEYS & ss.CONTROLKEYSENUM.up ? ss.CONTROLKEYSENUM.left : 0
  5751. newControlKeys |= ss.CONTROLKEYS & ss.CONTROLKEYSENUM.down ? ss.CONTROLKEYSENUM.right : 0
  5752. }
  5753. } else if (diffYaw > 22.5) {
  5754. if (diffPositive) {
  5755. newControlKeys |= ss.CONTROLKEYS & ss.CONTROLKEYSENUM.left ? ss.CONTROLKEYSENUM.up + ss.CONTROLKEYSENUM.left : 0
  5756. newControlKeys |= ss.CONTROLKEYS & ss.CONTROLKEYSENUM.right ? ss.CONTROLKEYSENUM.down + ss.CONTROLKEYSENUM.right : 0
  5757. newControlKeys |= ss.CONTROLKEYS & ss.CONTROLKEYSENUM.up ? ss.CONTROLKEYSENUM.up + ss.CONTROLKEYSENUM.right : 0
  5758. newControlKeys |= ss.CONTROLKEYS & ss.CONTROLKEYSENUM.down ? ss.CONTROLKEYSENUM.down + ss.CONTROLKEYSENUM.left : 0
  5759. } else {
  5760. newControlKeys |= ss.CONTROLKEYS & ss.CONTROLKEYSENUM.left ? ss.CONTROLKEYSENUM.down + ss.CONTROLKEYSENUM.left : 0
  5761. newControlKeys |= ss.CONTROLKEYS & ss.CONTROLKEYSENUM.right ? ss.CONTROLKEYSENUM.up + ss.CONTROLKEYSENUM.right : 0
  5762. newControlKeys |= ss.CONTROLKEYS & ss.CONTROLKEYSENUM.up ? ss.CONTROLKEYSENUM.up + ss.CONTROLKEYSENUM.left : 0
  5763. newControlKeys |= ss.CONTROLKEYS & ss.CONTROLKEYSENUM.down ? ss.CONTROLKEYSENUM.down + ss.CONTROLKEYSENUM.right : 0
  5764. };
  5765. };
  5766. // log(ss.CONTROLKEYS, newControlKeys);
  5767. state.controlKeys |= newControlKeys;
  5768. state[H.yaw] = setPrecision(aimbot.yawReal);
  5769. state[H.pitch] = setPrecision(aimbot.pitchReal);
  5770. ss.MYPLAYER[H.stateBuffer][Math.mod(ss.MYPLAYER.stateIdx - i, 256)] = state;
  5771. };
  5772. if(extract("aimbSemiSilent") && extract("silentAimbot")){
  5773. ss.MYPLAYER[H.yaw] = getAimbot(currentlyTargeting).yawReal;
  5774. ss.MYPLAYER[H.pitch] = getAimbot(currentlyTargeting).pitchReal;
  5775. }
  5776. log("force update?");
  5777. ss.SERVERSYNC();
  5778. };
  5779. });
  5780. createAnonFunction('onConnectFail', function (ERRORCODE, ERRORARRAY) {
  5781. const terminationMessage = findKeyByValue(ERRORARRAY, ERRORCODE); //don't want to fuck with errorString so here's a new var!
  5782. if (ERRORCODE !== ERRORARRAY.mainMenu) {
  5783. errorString = terminationMessage;
  5784. log("StateFarm has detected a connection error...", errorString, ERRORCODE, ERRORARRAY);
  5785. if (document.getElementById("genericPopup").textContent === ' Game Not Found Sorry! This game ID is either invalid, or no longer exists. OK ') {
  5786. document.getElementById("genericPopup").children[1].textContent = 'joinCode not found! check your autoJoin settings and get a new code';
  5787. document.getElementById("genericPopup").children[2].children[1].textContent = "heeheeheehaw";
  5788. document.getElementById("genericPopup").children[0].children[1].textContent = 'MAKE NEW AUTOJOIN CODE';
  5789. };
  5790. if (extract("autoUnban") && (errorString == "sessionNotFound" || errorString == "readyBeforeReady")) {
  5791. if (!attemptedAutoUnban) {
  5792. isBanned = true;
  5793. } else if (isBanned) {
  5794. log("StateFarm: Gonna refresh, could be banned but you can't play with this error anyways.");
  5795. createPopup("AutoUnban: Reloading page in 5 seconds...");
  5796. attemptedAutoUnban = true;
  5797. setTimeout(() => {
  5798. if (extract("autoUnban")) { //you get a bit of time to stop it
  5799. createPopup("AutoUnban: Reloading page now.");
  5800. reloadPage(); attemptedAutoUnban = false;
  5801. } else {
  5802. createPopup("AutoUnban: Reload page cancelled.");
  5803. };
  5804. }, 5000);
  5805. };
  5806. };
  5807. createPopup("Leaving due to connection error " + ERRORCODE + " (" + errorString + ")" + ".");
  5808. change("leaveGame");
  5809. };
  5810. //GAME HISTORY gr
  5811. if(!GAMECODE || GAMECODE==undefined) return;
  5812. const HISTORY_MAX_ENTRIES = 6;
  5813. let history = GM_getValue("StateFarm_GameHistory");
  5814. if(history) history = JSON.parse(history); //should be an ARRAY kxdnfgoisdhngfiosdhjgoisdhgfjo
  5815. if(!history) history = [];
  5816. const recent = history[0]; // first indeX
  5817. if(history.length>0 && recent.code && recent.code == GAMECODE){
  5818. ++recent.amount;
  5819. recent.time = Date.now();
  5820. recent.message = terminationMessage;
  5821. recent.closeCode = ERRORCODE;
  5822. } else {
  5823. const arrElem = {
  5824. amount: 1,
  5825. code: GAMECODE,
  5826. string: getRoomAsString(),
  5827. time: Date.now(),
  5828. message: terminationMessage,
  5829. closeCode: ERRORCODE
  5830. };
  5831. history.unshift(arrElem);
  5832. }
  5833. while(history.length > HISTORY_MAX_ENTRIES) history.pop();
  5834. GM_setValue("StateFarm_GameHistory", JSON.stringify(history));
  5835. });
  5836. createAnonFunction('modifyChat', function (msg) {
  5837. if (msg[0] === '%') { //message is a command
  5838. let command = msg.slice(1);
  5839. msg = ""; //dont send anything
  5840. if (command != "pts") {
  5841. broadcastToBots(command);
  5842. } else {
  5843. handleCommand('pathtarget set 9 1 9')
  5844. }
  5845. } else {
  5846. if (msg !== lastSentMessage) { //not spammed or afked
  5847. //NOTE: never, NEVER, never under any otherworldly circumstances use Notepad++ for editing nested stuff like this. IT WILL FUCK UP THE FORMATTING
  5848. //ITS STILL FUCKED UP IN THE GH EDITOR WTF PLEASE END ME
  5849. //TODO: FIX THIS FUCKING FORMATTING fuckfuckFUCK
  5850. if(extract("chatFilterBypass")) msg=msg.replaceAll("fuck", "ꬵսсk"); //special case bc they check f.ck; this basically just gets the f from the nonexacts.
  5851. if (extract("chatFilterBypass") && ss.isBadWord(msg)) { //apply filter bypass
  5852. //#freedomOfSpeech #againstInternetCensorship
  5853. //Bl*e W*zard D*gital will not c*nsor me!!!!!
  5854. const exactLookAlikes = {
  5855. //(almost) exact lookalikes, will make it look better if it is enough
  5856. 'a': 'а', 'c': 'с', 'e': 'е',
  5857. 'h': 'հ', 'i': 'і', 'j': 'ј',
  5858. 'n': '𝗇', 'o': 'о', 'p': 'р',
  5859. 'q': 'q', 'u': 'ս', 'w': 'ԝ',
  5860. 'y': 'у',
  5861. //uppercase
  5862. 'B': 'В', 'D': 'ꓓ', 'E': 'Е',
  5863. 'H': 'Η', 'I': 'І', 'J': 'Ј',
  5864. 'U': '𐓎',
  5865. 'V': 'ⴸ', 'W': 'Ԝ', 'X': 'Χ', 'Y': 'Υ',
  5866. 'Z': 'Ζ',
  5867. };
  5868. const lookAlikes = {
  5869. //nvm, found this complete list on reddit: https://www.reddit.com/r/Unicode/comments/gpgmb7/unique_unicode_chars_that_look_the_exact_same_as/
  5870. //should literally cover 100% of the thing now, still keeping fallback though
  5871. '0': 'O',
  5872. '1': '𝟷', '2': '𝟸', '3': 'Ꝫ', '4': '4',
  5873. '5': '𝟻', '6': '𝟨', '7': '𝟽', '8': '𝟪',
  5874. '9': '𝟫', '@': '@',
  5875. 'b': 'ᖯ',
  5876. 'd': '𝚍', 'f': 'ꬵ', 'g': '𝗀',
  5877. 'k': '𝚔',
  5878. 'l': 'ⅼ', 'm': 'm', 'r': '𝗋', 's': '𐑈',
  5879. 't': '𝚝', 'v': '∨',
  5880. 'x': 'ⅹ', 'z': '𝗓', 'A': '𐊠',
  5881. 'C': '𐊢',
  5882. 'F': '𐊇', 'G': 'Ԍ', 'K': 'Κ', 'L': 'Ⅼ', 'M': 'Μ',
  5883. 'N': 'Ν', 'O': 'Ο', 'P': 'Ρ', 'Q': '𝖰',
  5884. 'R': '𖼵', 'S': 'Ѕ', 'T': 'Τ',
  5885. };
  5886. let onlyReplace = msg;
  5887. //exact
  5888. for (let char in exactLookAlikes) {
  5889. //replace all chars with lookalikes
  5890. onlyReplace = onlyReplace.replaceAll(char, exactLookAlikes[char]);
  5891. };
  5892. //did that work?
  5893. if(ss.isBadWord(onlyReplace)){
  5894. log("chatFilterBypass: exacts were not enough, trying full...");
  5895. for (let char in lookAlikes) {
  5896. onlyReplace = onlyReplace.replaceAll(char, lookAlikes[char]);
  5897. };
  5898. };
  5899. if(!ss.isBadWord(onlyReplace)){
  5900. //did the lookalike replace do the job? Set it as the new message
  5901. log("chatFilterBypass: lookalike replace worked!");
  5902. msg = onlyReplace;
  5903. };
  5904. if(ss.isBadWord(onlyReplace)){
  5905. //if lookalike replace did NOT work, we use the old method.
  5906. log("chatFilterBypass: lookalike did NOT work, falling back to reverse...");
  5907. const UNICODE_RTL_OVERRIDE = '\u202e'
  5908. msg = ([UNICODE_RTL_OVERRIDE,].concat(reverseString(msg).split(""))).join("");
  5909. };
  5910. };
  5911. };
  5912.  
  5913. if (extract("tallChat") && !(msg.includes("᥊"))) {
  5914. msg = msg + "᥊";
  5915. };
  5916. };
  5917. return msg;
  5918. });
  5919. createAnonFunction('modifyControls', function (CONTROLKEYS) {
  5920. // if (AUTOMATED) { CONTROLKEYS=0 };
  5921. if (startUpComplete) {
  5922. if (forceControlKeys) {
  5923. forceControlKeysCache = true;
  5924. return forceControlKeys;
  5925. } else if (forceControlKeysCache) {
  5926. forceControlKeysCache = false;
  5927. return 0;
  5928. } else {
  5929. if (extract("autoWalk")) { CONTROLKEYS |= ss.CONTROLKEYSENUM.up };
  5930. // credit for code: de_neuublue
  5931. if (extract("bunnyhop") && isKeyToggled.Space) {
  5932. CONTROLKEYS |= ss.CONTROLKEYSENUM.jump;
  5933. };
  5934. if (extract("autoJump")) {
  5935. if (Date.now() > (lastAutoJump + extract("autoJumpDelay"))) {
  5936. CONTROLKEYS |= ss.CONTROLKEYSENUM.jump;
  5937. lastAutoJump = Date.now();
  5938. };
  5939. };
  5940. if (extract("autoStrafe")) {
  5941. if (Date.now() > (autoStrafeValue[0])) {
  5942. if (autoStrafeValue[1] == 0) { //decide new strafe delay
  5943. autoStrafeValue[0] = Date.now() + randomInt(500, 3000);
  5944. autoStrafeValue[2] = (Math.random() > 0.5) ? "left" : "right";
  5945. autoStrafeValue[1] = 1;
  5946. } else if (autoStrafeValue[1] == 1) { //time to start strafe
  5947. autoStrafeValue[3] = Date.now() + randomInt(500, 2000);
  5948. autoStrafeValue[1] = 2;
  5949. } else if (autoStrafeValue[1] == 2 && Date.now() < autoStrafeValue[3]) { //do strafe
  5950. CONTROLKEYS |= ss.CONTROLKEYSENUM[autoStrafeValue[2]];
  5951. } else if (autoStrafeValue[1] == 2) { //stop strafe
  5952. CONTROLKEYS &= ~ss.CONTROLKEYSENUM.left;
  5953. CONTROLKEYS &= ~ss.CONTROLKEYSENUM.right;
  5954. autoStrafeValue[1] = 0;
  5955. };
  5956. };
  5957. };
  5958. return CONTROLKEYS;
  5959. };
  5960. };
  5961. });
  5962. createAnonFunction("quickRespawn", function (input) {
  5963. if (input == 3e3) {
  5964. return sneakyDespawning ? 0 : 3e3;
  5965. } else if (input == 5 && sneakyDespawning) {
  5966. return 1;
  5967. } else if (extract("quickRespawn")) {
  5968. if (input == 5) {
  5969. return 4;
  5970. };
  5971. };
  5972. return input;
  5973. });
  5974. createAnonFunction("getInstantSpectateEnterSpectatorModeBlocked", function (enterSpectatorModeBlocked) {
  5975. return extract("instantSpectate") ? false : enterSpectatorModeBlocked;
  5976. });
  5977. createAnonFunction("getInstantSpectateRespawnTime", function (respawnTime) {
  5978. return extract("instantSpectate") ? -1 : respawnTime;
  5979. });
  5980. createAnonFunction('gameBlacklisted', function (t) {
  5981. let result = false;
  5982. if (blacklistedGameCodes.length >= 1) {
  5983. blacklistedGameCodes.forEach(function (code) {
  5984. if (t.id == code) {
  5985. log("Blacklisted Game: ", t.id, code);
  5986. result = true;
  5987. return true;
  5988. }
  5989. });
  5990. };
  5991.  
  5992. return extract('gameBlacklist') == false || extract('gameBlacklist') == undefined ? false : result;
  5993. });
  5994. createAnonFunction("getParticleSpeedMultiplier", function(){
  5995. return extract("particleSpeedMultiplier");
  5996. });
  5997.  
  5998. const originalFunction = Function;
  5999.  
  6000. unsafeWindow.Function = function (...args) {
  6001. log(args.join(""));
  6002. if (args.join('').includes('(()=>{var ')) {
  6003. unsafeWindow.Function = originalFunction;
  6004. unsafeWindow.Date.now = _dateNow;
  6005.  
  6006. // this is the right script
  6007. return originalFunction(applyStateFarm(...args));
  6008. }
  6009. return originalFunction(...args);
  6010. };
  6011. function sha256(str) {
  6012. const utf8 = new TextEncoder().encode(str);
  6013. const k = Uint32Array.of(
  6014. 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
  6015. 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
  6016. 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
  6017. 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
  6018. 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
  6019. 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
  6020. 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
  6021. 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
  6022. );
  6023. let h = Uint32Array.of(
  6024. 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
  6025. 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
  6026. );
  6027.  
  6028. const pad = new Uint8Array(((utf8.length + 9) & ~63) + 64);
  6029. pad.set(utf8), pad[utf8.length] = 0x80;
  6030. new DataView(pad.buffer).setUint32(pad.length - 4, utf8.length << 3, false);
  6031.  
  6032. let w = new Uint32Array(64),
  6033. v, i, j, a, b, c, d, e, f, g, h0, S0, S1, ch, maj, temp1, temp2;
  6034. for (i = 0; i < pad.length; i += 64) {
  6035. v = new DataView(pad.buffer, i, 64);
  6036. for (j = 0; j < 16; j++) w[j] = v.getUint32(j << 2, false);
  6037. for (; j < 64; j++) w[j] = ((w[j - 16] + (w[j - 15] >>> 7 ^ w[j - 15] << 25 ^ w[j - 15] >>> 18 ^ w[j - 15] << 14 ^ w[j - 15] >>> 3) + w[j - 7] + (w[j - 2] >>> 17 ^ w[j - 2] << 15 ^ w[j - 2] >>> 19 ^ w[j - 2] << 13 ^ w[j - 2] >>> 10)) >>> 0);
  6038.  
  6039. [a, b, c, d, e, f, g, h0] = h;
  6040. for (j = 0; j < 64; j++) {
  6041. S1 = (e >>> 6 | e << 26) ^ (e >>> 11 | e << 21) ^ (e >>> 25 | e << 7);
  6042. ch = (e & f) ^ (~e & g);
  6043. temp1 = (h0 + S1 + ch + k[j] + w[j]) >>> 0;
  6044. S0 = (a >>> 2 | a << 30) ^ (a >>> 13 | a << 19) ^ (a >>> 22 | a << 10);
  6045. maj = (a & b) ^ (a & c) ^ (b & c);
  6046. temp2 = (S0 + maj) >>> 0;
  6047. h0 = g, g = f, f = e, e = (d + temp1) >>> 0, d = c, c = b, b = a, a = (temp1 + temp2) >>> 0;
  6048. }
  6049. h[0] += a, h[1] += b, h[2] += c, h[3] += d, h[4] += e, h[5] += f, h[6] += g, h[7] += h0;
  6050. }
  6051.  
  6052. return h.reduce((s, x) => s + x.toString(16).padStart(8, '0'), '');
  6053. }
  6054. const applyStateFarm = function (js) {
  6055. log('%cATTEMPTING TO START STATEFARM', 'color: magenta; font-weight: bold; font-size: 1.5em; text-decoration: underline;');
  6056. let match;
  6057. let clientKeys;
  6058.  
  6059. let originalJS = fetchTextContent('/js/shellshock.js');
  6060. if (crackedShell) originalJS = fetchTextContent('/js/shellshock.og.js');
  6061.  
  6062. const getVardata = function (hash) {
  6063. return fetchTextContent(clientKeysURL + hash + ".json?v=" + Date.now());
  6064. };
  6065.  
  6066. hash = sha256(js);
  6067. onlineClientKeys = getVardata(hash);
  6068.  
  6069. const vardataCache = GM_getValue("StateFarm_VarDataCache") || {};
  6070. const previousHash = GM_getValue("StateFarm_PreviousHash") || "";
  6071.  
  6072. if (onlineClientKeys == "value_undefined" || onlineClientKeys == null || __DEBUG__.forceTriggerVarData) {
  6073. onlineClientKeys = getVardata("latest");
  6074.  
  6075. const vardataFallback = extract("vardataFallback");
  6076. const customVarData = extract("vardataCustom");
  6077. let vardataType = extract("vardataType");
  6078.  
  6079. if (vardataType == "justOnce") change("vardataType", 0);
  6080. if (vardataType == "nextHash" && hash !== previousHash) {
  6081. change("vardataType", 0);
  6082. vardataType = "never";
  6083. };
  6084.  
  6085. let convertedCustom;
  6086.  
  6087. try {
  6088. convertedCustom = JSON.parse(customVarData);
  6089. log("did convert");
  6090. } catch (e) {
  6091. log("did not convert");
  6092. convertedCustom = false;
  6093. };
  6094.  
  6095. const cachedForHash = vardataCache && vardataCache[hash];
  6096. const cachedRecent = vardataCache && vardataCache.latest;
  6097.  
  6098. log(cachedForHash, cachedRecent)
  6099.  
  6100. if (vardataType != "never" && convertedCustom && vardataFallback == "loadCustom" && convertedCustom.vars && convertedCustom.checksum && !__DEBUG__.forceTriggerVarData) {
  6101. clientKeys = convertedCustom;
  6102. } else if (vardataType != "never" && onlineClientKeys && vardataFallback == "loadLatest" && !__DEBUG__.forceTriggerVarData) {
  6103. //l8er dealt with
  6104. } else if (vardataType != "never" && cachedForHash && vardataFallback == "loadCached" && !__DEBUG__.forceTriggerVarData) {
  6105. clientKeys = JSON.parse(cachedForHash);
  6106. } else if (vardataType != "never" && cachedRecent && vardataFallback == "loadRecent" && !__DEBUG__.forceTriggerVarData) {
  6107. clientKeys = JSON.parse(cachedRecent);
  6108. } else {
  6109. const vardataButtonsInfo = [
  6110. { id: 'loadLatest', enabled: !!onlineClientKeys, text: 'Load Latest\n(online) (RECOMMENDED)', isHighlighted: true, action: () => {
  6111. change("vardataFallback", 1);
  6112. if (extract("vardataType") == "never") change("vardataType", 1);
  6113. if (extract("vardataType") == "justOnce") change("vardataType", 3);
  6114. closeVardataPopup();
  6115. }},
  6116. { id: 'loadCached', enabled: true, text: 'Input Custom', isHighlighted: false, action: () => {
  6117. const error = () => createPopup("Inputted VarData isn't valid.", "error");
  6118.  
  6119. try {
  6120. let converted = JSON.parse(inputValue);
  6121. if (converted.vars && converted.checksum) {
  6122. change("vardataCustom", inputValue);
  6123. change("vardataFallback", 4);
  6124. change("vardataType", 1); //custom isnt consistent enough
  6125. closeVardataPopup();
  6126. } else {
  6127. error();
  6128. };
  6129. } catch (e) {
  6130. error();
  6131. }
  6132. }},
  6133. { id: 'loadRecent', enabled: !!vardataCache.latest, text: 'Load Cached\n(most recent)', isHighlighted: false, action: () => {
  6134. change("vardataFallback", 3);
  6135. if (extract("vardataType") == "never") change("vardataType", 1);
  6136. closeVardataPopup();
  6137. }}
  6138. ];
  6139.  
  6140. createVarDataPopup(vardataButtonsInfo);
  6141.  
  6142. return;
  6143. };
  6144. };
  6145.  
  6146. if (onlineClientKeys && !clientKeys) clientKeys = JSON.parse(onlineClientKeys);
  6147.  
  6148. GM_setValue("StateFarm_PreviousHash", hash);
  6149.  
  6150. if (vardataCache && onlineClientKeys) {
  6151. vardataCache[clientKeys.checksum] = onlineClientKeys;
  6152. vardataCache.latest = onlineClientKeys;
  6153. GM_setValue("StateFarm_VarDataCache", vardataCache);
  6154. };
  6155.  
  6156. // removed feature
  6157. // log("maybe they did a hash??");
  6158. // try {
  6159. // const archivedJS = fetchTextContent(`${jsArchiveURL}${userInput}.js`);
  6160. // log("did that just work??");
  6161. // js = archivedJS;
  6162. // hash = userInput.split("_")[5];
  6163. // onlineClientKeys = getVardata(hash);
  6164. // clientKeys = JSON.parse(onlineClientKeys);
  6165. // } catch {
  6166. // //at this point, fuck it. it's not happening
  6167. // };
  6168.  
  6169. log(hash, onlineClientKeys, clientKeys);
  6170.  
  6171. H = clientKeys.vars;
  6172. //C = clientKeys.commCodes?.codes;
  6173.  
  6174. if (!C) log('WARNING: YOU SHOULD REALLY ADD COMMCODES TO YOUR VARDATA')
  6175.  
  6176. let injectionString = "";
  6177.  
  6178. try {
  6179. //SERVERSYNC
  6180. match = new RegExp(`function serverSync\\(\\)\\{(.*?)\\)\\}`).exec(js)
  6181. log("SERVERSYNC:", match);
  6182. H.SERVERSYNC = match ? match[1].replace(/[a-zA-Z$_\.\[\]]+shots/, 0) + ')' : "function(){log('no serversync womp womp')}";
  6183. //PAUSE
  6184. match = new RegExp(`,setTimeout\\(\\(\\(\\)=>\\{([=A-z0-9\\(\\),\\{ \\.;!\\|\\?:\\}]+send\\([a-zA-Z$_]+\\))`).exec(js);
  6185. log("PAUSE:", match);
  6186. H.PAUSE = match ? `function(){${match[1]}}` : "function(){log('no pause womp womp')}";
  6187.  
  6188. const variableNameRegex = /^[a-zA-Z0-9_$\[\]"\\\.,]*$/;
  6189. for (let name in H) {
  6190. let deobf = H[name];
  6191. if (name == "SERVERSYNC" || name == "PAUSE" || variableNameRegex.test(deobf)) { //serversync should only be defined just before...
  6192. injectionString = `${injectionString}${name}: (() => { let variable = "value_undefined"; try { eval("variable = ${deobf};"); } catch (error) { return "value_undefined"; }; return variable; })(),`;
  6193. } else {
  6194. alert("Message from the StateFarm Devs: WARNING! The keys inputted contain non-variable characters! There is a possibility that this could run code unintended by the StateFarm team, although possibly there is also a mistake. Do NOT proceed with using this, and report to the StateFarm developers what is printed in the console.");
  6195. log("REPORT THIS IN THE DISCORD SERVER:", name, deobf, clientKeys);
  6196. const crashplease = "balls";
  6197. crashplease = "balls2";
  6198. };
  6199. };
  6200.  
  6201. log('%cSTATEFARM INJECTION STAGE 1: GATHER VARS', 'color: yellow; font-weight: bold; font-size: 1.2em; text-decoration: underline;');
  6202.  
  6203. const modifyJS = function (find, replace) {
  6204. let oldJS = js;
  6205. try {
  6206. js = js.originalReplaceAll(find, replace);
  6207. } catch (err) {
  6208. 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;');
  6209. };
  6210. if (oldJS !== js) {
  6211. log("%cReplacement successful! Injected code: replaced: " + find + " with: " + replace, 'color: green; font-weight: bold; font-size: 0.6em; text-decoration: italic;');
  6212. } else {
  6213. log("%cReplacement failed! Attempted to replace " + find + " with: " + replace, 'color: red; font-weight: bold; font-size: 0.6em; text-decoration: italic;');
  6214. };
  6215. };
  6216.  
  6217. const f = function (varName) { return varName.replace("$", "\\$") };
  6218.  
  6219. log('%cSTATEFARM INJECTION STAGE 2: INJECT VAR RETRIEVAL FUNCTION AND MAIN LOOP', 'color: yellow; font-weight: bold; font-size: 1.2em; text-decoration: underline;');
  6220. //hook for main loop function in render loop
  6221. modifyJS(f(H.SCENE) + '.' + f(H.render), `window["${functionNames.retrieveFunctions}"]({${injectionString}},true)||${f(H.SCENE)}.render`);
  6222. modifyJS('log("After Game Ready"),', `log("After Game Ready"),window["${functionNames.retrieveFunctions}"]({${injectionString}}),`);
  6223. log('%cSuccess! Variable retrieval and main loop hooked.', 'color: green; font-weight: bold;');
  6224. log('%cSTATEFARM INJECTION STAGE 3: INJECT CULL INHIBITION', 'color: yellow; font-weight: bold; font-size: 1.2em; text-decoration: underline;');
  6225. //stop removal of objects
  6226. modifyJS(`if(${f(H.CULL)})return`, `if(${functionNames.shouldNotCull}())return`);
  6227. log('%cSuccess! Cull inhibition hooked ' + f(H.CULL), 'color: green; font-weight: bold;');
  6228. log('%cSTATEFARM INJECTION STAGE 4: INJECT OTHER FUNCTIONS', 'color: yellow; font-weight: bold; font-size: 1.2em; text-decoration: underline;');
  6229. //hook for modifications just before firing
  6230. modifyJS('fire(){var', 'fire(){window.' + functionNames.beforeFiring + '(this.player);var');
  6231. //hook for fov mods
  6232. modifyJS(`${H.fov}=1.25`, 'fov=window.' + functionNames.fixCamera + '()');
  6233. modifyJS(`${H.fov}+(1.25`, 'fov+(window.' + functionNames.fixCamera + '()');
  6234. //chat mods: disable chat culling
  6235. const chatCull = /return\}[a-zA-Z$_]+\.length>4/.exec(js)[0];
  6236. modifyJS(chatCull, chatCull.originalReplace('4', `window.${functionNames.getChatLimit}()`));
  6237. //chat mods: disable filter (credit to A3+++ for this finding)
  6238. modifyJS(`!${f(H.isBadWord)}(${f(H._insideFilterFunction)})`, `((!${f(H.isBadWord)}(${f(H._insideFilterFunction)}))||window.${functionNames.getDisableChatFilter}())`);
  6239. //chat mods: make filtered text red
  6240. let [_, elm, str] = js.match(/\)\),([a-zA-Z$_]+)\.innerHTML=([a-zA-Z$_]+),/);
  6241. modifyJS(_, _ + `${f(H.isBadWord)}(${str})&&window.${functionNames.getDisableChatFilter}()&&!arguments[3]&&(${elm}.style.color="red"),`);
  6242. //skins
  6243. match = js.match(/inventory\[[a-zA-Z$_]+\].id===[a-zA-Z$_]+.id\)return!0;return!1/);
  6244. if (match) { modifyJS(match[0], match[0] + `||window.${functionNames.getSkinHack}()`) };
  6245. //reset join/leave msgs
  6246. modifyJS('gameJoined_ received"),', 'gameJoined_ received"),window.' + functionNames.setNewGame + '(),');
  6247. //bypass chat filter
  6248. modifyJS('value.trim();', 'value.trim();' + f(H._chat) + '=window.' + functionNames.modifyChat + '(' + f(H._chat) + ');')
  6249. //hook for control interception
  6250. match = new RegExp(`\\.prototype\\.${H._update}=function\\([a-zA-Z$_,]+\\)\\{`).exec(js)?.[0];
  6251. log("player update function:", match);
  6252. if (match) modifyJS(match, `${match}${f(H.CONTROLKEYS)}=window.${functionNames.modifyControls}(${f(H.CONTROLKEYS)});`);
  6253. //admin spoof lol
  6254. modifyJS('isGameOwner(){return ', 'isGameOwner(){return window.' + functionNames.getAdminSpoof + '()?true:')
  6255. modifyJS('adminRoles(){return ', 'adminRoles(){return window.' + functionNames.getAdminSpoof + '()?255:')
  6256. //grab reason for connect fail
  6257. const FUNCTIONPARAM = new RegExp('function ' + f(H._connectFail) + '\\(([a-zA-Z$_]+)\\)').exec(js)[1];
  6258. log("FUNCTIONPARAM:", FUNCTIONPARAM);
  6259. modifyJS('function ' + f(H._connectFail) + '(' + f(FUNCTIONPARAM) + '){', 'function ' + f(H._connectFail) + '(' + f(FUNCTIONPARAM) + '){window.' + functionNames.onConnectFail + '(' + f(FUNCTIONPARAM) + ',' + f(H.ERRORARRAY) + ');')
  6260. //get rid of tutorial popup because its a stupid piece of shit
  6261. modifyJS(',vueApp.onTutorialPopupClick()', '');
  6262. //annoying shit
  6263. modifyJS('alert', 'console.log');
  6264. //pointer escape
  6265. modifyJS('onpointerlockchange=function(){', 'onpointerlockchange=function(){if (window.' + functionNames.getPointerEscape + '(arguments)) {return};');
  6266. //death hook
  6267. const DEATHARGS = new RegExp('function ' + f(H._deathFunction) + '\\(([a-zA-Z$_]+,[a-zA-Z$_]+)\\)').exec(js)[1];
  6268. log("DEATHARGS", DEATHARGS);
  6269. modifyJS('function ' + f(H._deathFunction) + '(' + DEATHARGS + '){', 'function ' + f(H._deathFunction) + '(' + f(DEATHARGS) + '){window.' + functionNames.interceptDeath + '(' + f(DEATHARGS) + ');');
  6270. //vip spoof/no ads credit absolutely goes to OakSwingZZZ
  6271. modifyJS('showAdBlockerVideo', 'hideAdBlockerVideo'); //hello eggs bullshit
  6272. //respawn time stuff
  6273. modifyJS('5:10', functionNames.quickRespawn + '(5):' + functionNames.adBlocker + '(10)');
  6274. modifyJS(',3e3),console.log', `,window["${functionNames.quickRespawn}"](3e3)),console.log`);
  6275. // modifyJS(H.respawnTime+'=Math.max',H.respawnTime+'=Math.min');
  6276.  
  6277. //instant spectate
  6278. modifyJS(`\{${H.enterSpectatorModeBlocked}\|\|`,`\{(window["${functionNames.getInstantSpectateEnterSpectatorModeBlocked}"](${H.enterSpectatorModeBlocked}))\|\|`);
  6279. modifyJS(`\),${H.respawnTime}<0&&`,`\),(window["${functionNames.getInstantSpectateRespawnTime}"](${H.respawnTime}))&&`);
  6280.  
  6281. //Modifies matchmaker JS to block gamecodes.
  6282. match = js.match(/region,([a-zA-Z$_]+)\(([a-zA-Z$_]+)/); //im so sorry i thought i was slick
  6283. if (match) {
  6284. modifyJS('region,', `region,window.${functionNames.gameBlacklisted}(${match[2]})?(${match[2]}.uuid="${getScrambled()}",${match[1]}(${match[2]}),vueApp.hideSpinner()):`);
  6285. };
  6286. //intercept and replace audio
  6287. match = js.match(/static play\(([a-zA-Z$_,]+)\){/);
  6288. log("AUDIO INTERCEPTION", match);
  6289. modifyJS(match[0], `${match[0]}[${match[1]}] = window.${functionNames.interceptAudio}(${match[1]});`);
  6290. modifyJS('"IFRAME"==document.activeElement.tagName', `("IFRAME"==document.activeElement.tagName&&document.activeElement.id!=='sfChat-iframe')`);
  6291. // skybox (yay)
  6292. modifyJS(`infiniteDistance=!0;`, `infiniteDistance=!0;window["${skyboxName}"]=${H.skybox};`);
  6293. //intercept player names before they are censored
  6294. modifyJS(`:{}};if(${H.playerData}.`, `:{}};window.${functionNames.realPlayerData}(${H.playerData});if(${H.playerData}.`);
  6295. //intercept player names before they are censored
  6296. modifyJS(`"transparent")},`, `"transparent");window.${functionNames.interceptDrawTextOnNameTexture}(${H.nameTexture}, arguments, this.${H.player_})},`);
  6297. //intercept signedIn function
  6298. modifyJS(`if(this.isAnonymous`, `window.${functionNames.interceptSignedIn}(arguments);if(this.isAnonymous`);
  6299.  
  6300. modifyJS(`="SPACE",`,`="SPACE",window.${functionNames.shouldInputSpace}()&&`)
  6301.  
  6302. modifyJS(/tp-/g, '');
  6303. modifyJS(`window.location.href="https://free`, `let ballsack="https://free`);
  6304.  
  6305. // modifyJS(`${H.Grenade}.prototype.remove=function(){`, `${H.Grenade}.prototype.remove=function(){console.log("nade explosion", this, this.x, this.y, this.z);`);
  6306. // modifyJS(`this.grenadePool.retrieve`, `window.cock=arguments;this.grenadePool.retrieve`);
  6307.  
  6308. match = js.match(/0===[a-zA-Z0-9$_]+\)return!1;/);
  6309. log("COLLIDER", match);
  6310. modifyJS(match[0], match[0] + "var iterations=0;");
  6311. modifyJS(">=0);){", ">=0);){iterations++;if (iterations >= 1e3) {console.log('oops lol');return false};")
  6312.  
  6313. //intercept updateParticles for particle speed control
  6314. //deobf is: updateParticles(manager, delta)
  6315. match = js.match(/function [a-zA-Z$_]+\([a-zA-Z$_]+,[a-zA-Z$_]+\)\{for\(var [a-zA-Z$_]+=0;[a-zA-Z$_]+<[a-zA-Z$_]+\.sprites/); //this should only give one match.
  6316. const splitted = match[0].split("{"); //split right bevor function opens to inject delta manipulator. Might not be the best way but it works fine.
  6317. const delta = splitted[0].charAt(splitted[0].length - 2); //name of the delta argument.
  6318. modifyJS(match[0], splitted[0] + "{" //add curly bracket because the split removed it. ehhhhhh
  6319. +`${delta}=${delta}*window.${functionNames.getParticleSpeedMultiplier}();` //get mutiplier value for delta.
  6320. +splitted[1]
  6321. )
  6322.  
  6323. // grenade trajectories
  6324. match = js.match(/function Grenade\(([a-zA-Z$_]+)\)\{/);
  6325. modifyJS(`function Grenade(${match[1]}){`, `function Grenade(${match[1]}, ignoreActor){`);
  6326. match = js.match(/this\.([a-zA-Z$_]+)=new GrenadeActor\(this\)/);
  6327. modifyJS(`this.${match[1]}=new GrenadeActor(this)`, `this.${match[1]}=ignoreActor?new Proxy({},{get: () => () => {}}):new GrenadeActor(this)`)
  6328.  
  6329. // grenademax
  6330. modifyJS(`${H.grenadeThrowPower},0,1))`, `window.${functionNames.getGrenadeValue}(),0,1))`)
  6331.  
  6332. // replacefeeds
  6333. match = js.match(/requestJson\(([a-zA-Z$_]+),([a-zA-Z$_]+)\)\{getRequest\(/);
  6334. modifyJS(match[0], `requestJson(${match[1]},${match[2]}){${match[1]}=window.${functionNames.replaceFeeds}(${match[1]});getRequest(`)
  6335.  
  6336. // nominiegg
  6337. match = js.match(/\.prototype\.shellStreakShrinkPlayer=function\([a-zA-Z$_]+,[a-zA-Z$_]+,[a-zA-Z$_]+,[a-zA-Z$_]+\)\{/)
  6338. modifyJS(match[0], `${match[0]}if (window.${functionNames.noMiniEgg}())return;`)
  6339.  
  6340. try {
  6341. if (extract('debug')) {
  6342. modifyJS(`(()=>{var __defProp`, 'var __defProp');
  6343. modifyJS(`})();`, '');
  6344. }
  6345. } catch { }
  6346.  
  6347. log(H);
  6348. log(js);
  6349.  
  6350. attemptedInjection = true;
  6351. return js;
  6352. } catch (error) {
  6353. log(error);
  6354. change("vardataType", 0);
  6355. alert("An error occured, probably on our end. We recommend you use CTRL (cmd on mac) + SHIFT + R to \"hard reload\" the page. If this does not fix it, join our Discord server: " + discordURL);
  6356. createPopup("Reloading page in 5 seconds...");
  6357. setTimeout(() => {
  6358. reloadPage();
  6359. }, 5000);
  6360. };
  6361. };
  6362. };
  6363.  
  6364. //dead code
  6365. /*
  6366. JSON.safeStringify = (obj, indent = 2) => {
  6367. let cache = [];
  6368. const retVal = JSON.stringify(
  6369. obj,
  6370. (key, value) =>
  6371. typeof value === "object" && value !== null
  6372. ? cache.includes(value)
  6373. ? undefined // Duplicate reference found, discard key
  6374. : cache.push(value) && value // Store value in our collection
  6375. : value,
  6376. indent
  6377. );
  6378. cache = null;
  6379. return retVal;
  6380. };
  6381. */
  6382.  
  6383. const deployBots = async () => {
  6384. updateBotParams();
  6385. if (!load("firstTimeBots")) {
  6386. save("firstTimeBots", true);
  6387. GM_openInTab(bottingGuideURL, { active: true });
  6388. };
  6389.  
  6390. GM_setValue("StateFarm_BotStatus", {});
  6391.  
  6392. log("Deploying " + extract("numberBots") + " bots...");
  6393.  
  6394. let botNames = [];
  6395. for (let i = 0; i < extract("numberBots"); i++) {
  6396. let name = (extract("botUsername"));
  6397. if (extract("botCopyName")) {
  6398. name = retrieveCopiedName();
  6399. if (!name) {
  6400. alert("StateFarm: Cannot copy names if you haven't been in a game!");
  6401. return;
  6402. };
  6403. };
  6404. botNames.push(name);
  6405. };
  6406.  
  6407. let canMassBot = undefined;
  6408.  
  6409. for (let i = 0; i < extract("numberBots"); i++) {
  6410. let leftOffset = ((i % 15) * 100);
  6411. // let topOffset=((i%3)*100);
  6412. let topOffset = 0;
  6413. let proxyURL = extract("proxyBots") == "static" ? window.location.host : proxyList[proxyListIndex] ;
  6414. proxyListIndex = (proxyListIndex + 1) % proxyList.length;
  6415. let params = "?AUTOMATED=true&StateFarm=";
  6416. let name = botNames[i];
  6417. if (extract("botAntiDupe")) { name = name + String.fromCharCode(97 + Math.floor(Math.random() * 26)) };
  6418.  
  6419. const addParam = function (module, setTo, noEnding) { params = params + module + ">" + JSON.stringify(setTo) + (noEnding ? "" : "<") };
  6420.  
  6421. addParam("eggColor", extract("eggColorBots") == "random" ? randomInt(1, 7) : extractAsDropdownInt("eggColorBots"));
  6422. addParam("autoStamp", extract("autoStampBots") == "random" ? randomInt(0, 6) : extractAsDropdownInt("autoStampBots"));
  6423. addParam("autoHat", extract("autoHatBots") == "random" ? randomInt(0, 6) : extractAsDropdownInt("autoHatBots"));
  6424.  
  6425. addParam("usernameAutoJoin", name, true);
  6426.  
  6427. log("PARAMS:", params)
  6428. if (!crackedShell) {
  6429. unsafeWindow.open("https://" + proxyURL + "/" + params, '_blank', `width=${extract("botWindowWidth")}},height=${extract("botWindowHeight")},left=` + leftOffset + ',top=' + topOffset)
  6430. } else {
  6431. try {
  6432. if (canMassBot === undefined) {
  6433. let data = await fetch(`https://${getScrambled().replace([0-9], '')}.${location.host}/$/ping`);
  6434. data = await data.text();
  6435. if (data !== 'OK') {
  6436. alert('You are not on a version of CrackedShell that supports botting.');
  6437. canMassBot = false;
  6438. return;
  6439. } else canMassBot = true;
  6440. };
  6441. } catch (err) {
  6442. log(err);
  6443. canMassBot = false;
  6444. alert('You are not on a version of CrackedShell that supports botting.');
  6445. };
  6446.  
  6447. if (canMassBot === true)
  6448. unsafeWindow.open(`https://${getScrambled().replace([0-9], '')}.${location.host}/${params}&cs=${new URLSearchParams(new URL(location.href).searchParams).get('cs')}`, '_blank', `width=${extract("botWindowWidth")}},height=${extract("botWindowHeight")},left=` + leftOffset + ',top=' + topOffset);
  6449. };
  6450. };
  6451. };
  6452.  
  6453. const constructBotParams = function () {
  6454. const addParam = function (module, setTo, noEnding) { params = params + module + ">" + JSON.stringify(setTo) + (noEnding ? "" : "<") };
  6455. let params = "";
  6456.  
  6457. addParam("autoFireType", 1); //while visible
  6458.  
  6459. //blacklist stuff
  6460. addParam("blacklist", botBlacklist);
  6461. addParam("enableBlacklistAimbot", true);
  6462. //whitelist stuff
  6463. addParam("whitelist", botWhitelist);
  6464. addParam("enableWhitelistAimbot", true);
  6465. addParam("enableWhenNoneVisible", true);
  6466. //do aimbot
  6467. addParam("aimbotTargetMode", 1);
  6468. addParam("aimbotVisibilityMode", 1);
  6469. addParam("prediction", extract("botAimbot"));
  6470. addParam("aimbot", extract("botAimbot"));
  6471. addParam("antiBloom", extract("botAimbot"));
  6472. addParam("grenadeMax", extract("botAimbot"));
  6473. addParam("autoRefill", extract("botAimbot"));
  6474. addParam("autoFireAccuracy", extract("botAccuracy"));
  6475. //do shoot
  6476. addParam("antiSneak", extract("botAutoShoot") ? 1.4 : 0);
  6477. addParam("enableAutoFire", extract("botAutoShoot"));
  6478. addParam("autoGrenade", extract("botAutoShoot"));
  6479. //automove
  6480. addParam("autoWalk", extract("botAutoMove"));
  6481. addParam("autoStrafe", extract("botAutoMove"));
  6482. addParam("autoJump", extract("botAutoMove"));
  6483. addParam("autoJumpDelay", 1500);
  6484. //low res
  6485. addParam("enableTextures", !extract("botLowRes"));
  6486. addParam("setDetail", extract("botLowRes") ? 2 : 0);
  6487. //seizure
  6488. addParam("enableSeizureX", extract("botSeizure"));
  6489. addParam("enableSeizureY", extract("botSeizure"));
  6490.  
  6491. addParam("renderDelay", extract("renderDelayBots"));
  6492. addParam("muteGame", extract("botMuteGame"));
  6493. addParam("autoJoin", extract("botAutoJoin"));
  6494. addParam("mockMode", extract("botMock"));
  6495. addParam("autoRespawn", extract("botRespawn"));
  6496. addParam("autoEZ", extract("botAutoEZ"));
  6497. addParam("cheatAccuse", extract("botCheatAccuse"));
  6498. addParam("joinCode", extract("botJoinCode"));
  6499. addParam("autoWeapon", extractAsDropdownInt("botWeapon") + 1);
  6500. addParam("autoTeam", extractAsDropdownInt("botTeam"));
  6501. addParam("autoUnban", extract("botAutoUnban"));
  6502. addParam("autoLogin", extractAsDropdownInt("botAutoLogin"));
  6503. addParam("loginDatabaseSelection", 1);
  6504. addParam("autoRegion", extractAsDropdownInt("autoRegionBots"));
  6505. addParam("autoGamemode", extractAsDropdownInt("autoGamemodeBots"));
  6506. addParam("useCustomName", extract("useCustomNameBots"));
  6507. addParam("autoMacro", extract("useBotMacro"));
  6508. addParam("customMacro", extract("botMacro").replaceAll(">","{greater}").replaceAll("<","{less}"));
  6509. addParam("leaveEmpty", extract("leaveEmptyBots"));
  6510. addParam("autoLeave", extract("autoLeaveBots"));
  6511. addParam("autoLeaveDelay", extract("autoLeaveDelayBots"));
  6512. addParam("spamChat", extract("botSpam"));
  6513. addParam("spamChatText", extract("spamChatTextBot"));
  6514. addParam("tallChat", extract("botTallChat"), true);
  6515.  
  6516. return params;
  6517. };
  6518.  
  6519. const detectURLParams = function () {
  6520. if (getSearchParam("AUTOMATED") == "true") {
  6521. log("Automated Window!");
  6522. AUTOMATED = true;
  6523. };
  6524. let customSettings = getSearchParam("StateFarm")
  6525. if (customSettings !== null) {
  6526. customSettings = customSettings.split("|");
  6527. URLParams = customSettings[0];
  6528. log("StateFarm: Custom Settings in URL!", URLParams);
  6529. /*
  6530. let setVars=[];
  6531. let setBinds=[];
  6532. if (customSettings[0]) {setVars=customSettings[0].split("<")};
  6533. if (customSettings[1]) {setVars=customSettings[0].split("<")};
  6534. log(setVars,setBinds);
  6535. setBinds.forEach(element=>{ //not yet done
  6536. });
  6537. */
  6538. };
  6539. };
  6540.  
  6541. const applySettings = function (receivedConfig, reset, secondPassThru) {
  6542. log(AUTOMATED, receivedConfig);
  6543. let settings = receivedConfig.split("<");
  6544. if (reset) { initMenu(true); log("StateFarm: clearing before applying settings") };
  6545. settings.forEach(element => {
  6546. element = element.split(">");
  6547. if (element[0] == "customMacro") {element[1] = element[1].replaceAll("{less}","<").replaceAll("{greater}",">")};
  6548. try {
  6549. change(element[0], JSON.parse(element[1]));
  6550. } catch (error) {
  6551. log("fuck that was an error", element[0], error);
  6552. };
  6553. });
  6554. createPopup("Custom StateFarm Settings Applying...");
  6555. if (!secondPassThru) {
  6556. setTimeout(() => {
  6557. if (receivedConfig) {
  6558. applySettings(receivedConfig, false, true);
  6559. };
  6560. }, 150);
  6561. };
  6562. };
  6563.  
  6564. const updateBotParams = function () {
  6565. if (AUTOMATED) { // nuh uh.
  6566. createPopup("Automated window cannot config bots.", "error");
  6567. } else {
  6568. const botParams = constructBotParams();
  6569. broadcastToBots("setconfig " + btoa(unsafeWindow.unescape(encodeURIComponent(botParams))));
  6570. log("StateFarm: attempted to set bot params.");
  6571. };
  6572. };
  6573.  
  6574. const retrieveCopiedName = function () {
  6575. const playerSlots = document.querySelectorAll('.playerSlot--name');
  6576. const mapNames = Array.from(playerSlots).map(playerSlot => playerSlot.textContent.trim());
  6577. return mapNames[Math.floor(Math.random() * mapNames.length)];
  6578. };
  6579.  
  6580. //dead code (for now ig)
  6581.  
  6582. // const pathfindingCode = function () { //wrapped in a function just to stop its execution
  6583. // loggedGameMap = false;
  6584.  
  6585. // // begin pathfinding
  6586.  
  6587. // const BinaryHeap = function(scoreFunction) {
  6588. // this.content = [];
  6589. // this.scoreFunction = scoreFunction;
  6590. // };
  6591.  
  6592. // BinaryHeap.prototype = {
  6593. // push: function (element) {
  6594. // // Add the new element to the end of the array.
  6595. // this.content.push(element);
  6596. // // Allow it to bubble up.
  6597. // this.bubbleUp(this.content.length - 1);
  6598. // },
  6599.  
  6600. // rescoreElement: function (node) {
  6601. // this.sinkDown(this.content.indexOf(node));
  6602. // },
  6603.  
  6604. // pop: function () {
  6605. // // Store the first element so we can return it later.
  6606. // var result = this.content[0];
  6607. // // Get the element at the end of the array.
  6608. // var end = this.content.pop();
  6609. // // If there are any elements left, put the end element at the
  6610. // // start, and let it sink down.
  6611. // if (this.content.length > 0) {
  6612. // this.content[0] = end;
  6613. // this.sinkDown(0);
  6614. // }
  6615. // return result;
  6616. // },
  6617.  
  6618. // remove: function (node) {
  6619. // var length = this.content.length;
  6620. // // To remove a value, we must search through the array to find
  6621. // // it.
  6622. // for (var i = 0; i < length; i++) {
  6623. // if (this.content[i] != node) continue;
  6624. // // When it is found, the process seen in 'pop' is repeated
  6625. // // to fill up the hole.
  6626. // var end = this.content.pop();
  6627. // // If the element we popped was the one we needed to remove,
  6628. // // we're done.
  6629. // if (i == length - 1) break;
  6630. // // Otherwise, we replace the removed element with the popped
  6631. // // one, and allow it to float up or sink down as appropriate.
  6632. // this.content[i] = end;
  6633. // this.bubbleUp(i);
  6634. // this.sinkDown(i);
  6635. // break;
  6636. // }
  6637. // },
  6638.  
  6639. // size: function () {
  6640. // return this.content.length;
  6641. // },
  6642.  
  6643. // bubbleUp: function (n) {
  6644. // // Fetch the element that has to be moved.
  6645. // var element = this.content[n], score = this.scoreFunction(element);
  6646. // // When at 0, an element can not go up any further.
  6647. // while (n > 0) {
  6648. // // Compute the parent element's index, and fetch it.
  6649. // var parentN = Math.floor((n + 1) / 2) - 1,
  6650. // parent = this.content[parentN];
  6651. // // If the parent has a lesser score, things are in order and we
  6652. // // are done.
  6653. // if (score >= this.scoreFunction(parent)) break;
  6654.  
  6655. // // Otherwise, swap the parent with the current element and
  6656. // // continue.
  6657. // this.content[parentN] = element;
  6658. // this.content[n] = parent;
  6659. // n = parentN;
  6660. // }
  6661. // },
  6662.  
  6663. // includes: function (n) {
  6664. // return this.content.includes(n);
  6665. // },
  6666.  
  6667. // sinkDown: function (n) {
  6668. // // Look up the target element and its score.
  6669. // var length = this.content.length,
  6670. // element = this.content[n],
  6671. // elemScore = this.scoreFunction(element);
  6672.  
  6673. // while (true) {
  6674. // // Compute the indices of the child elements.
  6675. // var child2N = (n + 1) * 2, child1N = child2N - 1;
  6676. // // This is used to store the new position of the element,
  6677. // // if any.
  6678. // var swap = null;
  6679. // // If the first child exists (is inside the array)...
  6680. // if (child1N < length) {
  6681. // // Look it up and compute its score.
  6682. // var child1 = this.content[child1N],
  6683. // child1Score = this.scoreFunction(child1);
  6684. // // If the score is less than our element's, we need to swap.
  6685. // if (child1Score < elemScore) swap = child1N;
  6686. // }
  6687. // // Do the same checks for the other child.
  6688. // if (child2N < length) {
  6689. // var child2 = this.content[child2N],
  6690. // child2Score = this.scoreFunction(child2);
  6691. // if (child2Score < (swap == null ? elemScore : child1Score)) swap = child2N;
  6692. // }
  6693.  
  6694. // // No need to swap further, we are done.
  6695. // if (swap == null) break;
  6696.  
  6697. // // Otherwise, swap and continue.
  6698. // this.content[n] = this.content[swap];
  6699. // this.content[swap] = element;
  6700. // n = swap;
  6701. // };
  6702. // }
  6703. // };
  6704.  
  6705. // const isNodeAir = function(item) {
  6706. // return item.mesh === undefined
  6707. // };
  6708.  
  6709. // const canTravelThroughNode = function(item) {
  6710. // return isNodeAir(item) || item.mesh.name.includes("none")
  6711. // };
  6712.  
  6713. // class Position {
  6714. // constructor(x, y, z) {
  6715. // this.x = x;
  6716. // this.y = y;
  6717. // this.z = z;
  6718. // }
  6719. // }
  6720.  
  6721. // var GLOBAL_NODE_LIST = [];
  6722.  
  6723. // class MapNode {
  6724. // constructor(position, linked, map) {
  6725. // this.position = position;
  6726. // this.linked = linked;
  6727. // GLOBAL_NODE_LIST.push(this);
  6728. // this.add_children_from_map_data(map);
  6729. // this.f = undefined;
  6730. // this.g = undefined;
  6731. // this.h = undefined;
  6732. // }
  6733. // add_link(node) {
  6734. // this.linked.push(node);
  6735. // }
  6736. // remove_link(node) {
  6737. // this.linked = this.linked.filter(item => item !== node);
  6738. // }
  6739. // can_move(node) {
  6740. // return this.linked.includes(node);
  6741. // }
  6742. // add_children_from_map_data(map_data) {
  6743. // // for each thing around us in a 3x3x3 cube, add a link if it's air and it's not above us
  6744. // let found_node = 0; let found_link = 0
  6745. // for (var x = -1; x <= 1; x++) {
  6746. // for (var y = -1; y <= 0; y++) {
  6747. // for (var z = -1; z <= 1; z++) {
  6748. // if (x == 0 && y == 0 && z == 0) {
  6749. // continue;
  6750. // };
  6751. // if (Math.abs(x) + Math.abs(y) + Math.abs(z) > 1) {
  6752. // continue;
  6753. // };
  6754. // var map_data_x = this.position.x + x;
  6755. // var map_data_y = this.position.y + y;
  6756. // var map_data_z = this.position.z + z;
  6757. // if (map_data_x < 0 || map_data_y < 0 || map_data_z < 0) {
  6758. // continue;
  6759.  
  6760. // };
  6761. // if (map_data_x >= map_data.length || map_data_y >= map_data[0].length || map_data_z >= map_data[0][0].length) {
  6762. // continue;
  6763. // };
  6764.  
  6765. // var attemptedNode = map_data[map_data_x][map_data_y][map_data_z];
  6766.  
  6767. // if (!canTravelThroughNode(attemptedNode)) {
  6768. // ;continue;
  6769. // }
  6770.  
  6771. // /* for the tested node:
  6772. // continue if:
  6773. // can't travel through it
  6774. // a nonsolid is directly below it
  6775. // */
  6776.  
  6777. // try {
  6778. // var node_below_checked_node = map_data[map_data_x][map_data_y - 1][map_data_z];
  6779. // } catch (error) {
  6780. // log(error)
  6781. // continue;
  6782. // };
  6783.  
  6784. // var is_air_directly_below = isNodeAir(node_below_checked_node); // self explanatory
  6785. // var is_solid_directly_below = !is_air_directly_below ? node_below_checked_node.mesh.name.includes("full") : false;
  6786. // var is_partial_directly_below = !is_air_directly_below && !is_solid_directly_below
  6787.  
  6788. // var node_directly_below_node_doing_the_checking;
  6789.  
  6790. // try {
  6791. // node_directly_below_node_doing_the_checking = map_data[this.position.x][this.position.y - 1][this.position.z];
  6792. // } catch (error) {
  6793. // log(error);
  6794. // node_directly_below_node_doing_the_checking = {};
  6795. // };
  6796.  
  6797. // var is_solid_directly_below_node_doing_checking = !isNodeAir(node_directly_below_node_doing_the_checking) && node_directly_below_node_doing_the_checking.mesh.name.includes("full");
  6798.  
  6799. // var is_valid_candidate = (
  6800. // is_solid_directly_below ||
  6801. // y == -1 && !is_partial_directly_below ||
  6802. // (is_air_directly_below || is_solid_directly_below) && is_solid_directly_below_node_doing_checking
  6803. // // TODO: when falling long distances this can cause it to crash
  6804. // // ideally if there's a partial below it prunes back to the start of the fall
  6805. // // that's hard
  6806. // // i just want this to work
  6807. // );
  6808.  
  6809. // if (y == -1 && !is_partial_directly_below) {
  6810. // // log('weird case, looking downwards to x/y/z from x/y/z', map_data_x, map_data_y, map_data_z, this.position.x, this.position.y, this.position.z, 'is air directly below?', is_air_directly_below, 'is solid directly below?', is_solid_directly_below, 'is partial directly below?', is_partial_directly_below, 'is valid candidate?', is_valid_candidate)
  6811. // //shit lags, lol
  6812. // };
  6813.  
  6814. // // if the node is already in the list, add a link to it. Otherwise create it and then add a link to it.
  6815. // // if it's air / equivalent to air we can create it (but not necessarily link to it)
  6816. // if (GLOBAL_NODE_LIST.some(item => item.position.x == map_data_x && item.position.y == map_data_y && item.position.z == map_data_z)) { // eslint-disable-line
  6817. // // ^^ this node already exists, link to it
  6818. // if (is_valid_candidate) {
  6819. // found_link++;
  6820. // this.add_link(GLOBAL_NODE_LIST.find(item => item.position.x == map_data_x && item.position.y == map_data_y && item.position.z == map_data_z)); // eslint-disable-line
  6821. // }
  6822.  
  6823. // } else {
  6824.  
  6825. // found_node++;
  6826.  
  6827. // var new_node = new MapNode(new Position(map_data_x, map_data_y, map_data_z), [], map_data);
  6828. // // the new node doesn't exist yet
  6829. // // we create it
  6830. // // if it's possible to move to we add the link
  6831.  
  6832. // if (is_valid_candidate) {
  6833. // found_link++;
  6834. // this.add_link(new_node);
  6835.  
  6836. // };
  6837. // };
  6838. // };
  6839. // };
  6840. // };
  6841. // // log("done with recursive for node at x/y/z", this.position.x, this.position.y, this.position.z, "found", found_node, "new nodes and", found_link, "links, this is the nth node created", GLOBAL_NODE_LIST.length)
  6842. // //shit lags, lol
  6843. // }
  6844. // };
  6845.  
  6846. // const get_node_at = function(position) {
  6847. // return GLOBAL_NODE_LIST.find(item => item.position.x == position.x && item.position.y == position.y && item.position.z == position.z);
  6848. // };
  6849.  
  6850. // const get_player_position = function(player) {
  6851. // var x = Math.floor(player[H.actor][H.mesh].position.x);
  6852. // var y = Math.floor(player[H.actor][H.mesh].position.y);
  6853. // var z = Math.floor(player[H.actor][H.mesh].position.z);
  6854. // return new Position(x, y, z);
  6855. // }
  6856.  
  6857. // const get_player_linked_nodes = function(player) {
  6858. // var position = get_player_position(player);
  6859. // var node = get_node_at(position);
  6860. // if (node) {
  6861. // return node.linked;
  6862. // } else {
  6863. // return [];
  6864. // };
  6865. // };
  6866.  
  6867. // var map_data_created = false;
  6868.  
  6869. // // kazowie
  6870.  
  6871. // const TaxicabDist3D = function(pos1, pos2) {
  6872. // return Math.abs(pos1.x - pos2.x) + Math.abs(pos1.y - pos2.y) + Math.abs(pos1.z - pos2.z);
  6873. // };
  6874.  
  6875. // const pathTo = function(node) {
  6876. // var current = node;
  6877. // var path = [];
  6878. // while (current.parent) {
  6879. // path.unshift(current);
  6880. // if (current.parent === undefined) { log("parent undefined; path nodes successfully acquired:", path.length) }
  6881. // current = current.parent;
  6882. // }
  6883. // //log("done")
  6884. // return path;
  6885. // };
  6886.  
  6887. // const getHeap = function() {
  6888. // return new BinaryHeap(function (node) {
  6889. // return node.f;
  6890. // });
  6891. // };
  6892.  
  6893. // const cleanList = function(items) {
  6894. // for (var i = 0; i < items.length; i++) {
  6895. // var item = items[i];
  6896. // item.f = undefined;
  6897. // item.g = undefined;
  6898. // item.h = undefined;
  6899. // item.closed = undefined;
  6900. // item.parent = undefined;
  6901. // item.visited = undefined;
  6902. // };
  6903. // };
  6904.  
  6905. // const AStar = function(start, goal) {
  6906. // log("astar called")
  6907. // cleanList(GLOBAL_NODE_LIST)
  6908. // // start and goal are map nodes
  6909. // // map data is the list of all the nodes
  6910. // // each node has a .linked indicating which nodes can be traveled to from it
  6911. // // returns a list of nodes to travel through, ordered from start to goal
  6912. // // if no path is found, returns null
  6913.  
  6914. // var closed_set = [];
  6915.  
  6916.  
  6917. // var heuristic = TaxicabDist3D;
  6918. // var open_heap = getHeap();
  6919.  
  6920. // start.h = heuristic(start.position, goal.position);
  6921. // start.g = 0;
  6922. // start.f = start.g + start.h;
  6923.  
  6924. // open_heap.push(start);
  6925.  
  6926.  
  6927. // while (open_heap.size() != 0) {
  6928. // var current = open_heap.pop();
  6929.  
  6930. // if (current === goal) {
  6931. // log("done with astar - path found")
  6932. // var val = pathTo(current);
  6933. // log("path length:", val.length)
  6934. // print_node_list(val);
  6935. // return val;
  6936. // }
  6937.  
  6938. // closed_set.push(current);
  6939.  
  6940. // var neighbors = current.linked;
  6941.  
  6942. // for (var i = 0; i < neighbors.length; i++) {
  6943. // var neighbor = neighbors[i];
  6944.  
  6945. // if (closed_set.includes(neighbor)) {
  6946. // continue;
  6947. // }
  6948.  
  6949. // var tentative_g_score = current.g + 1;
  6950. // var visited = neighbor.visited;
  6951. // if (!visited || tentative_g_score < neighbor.g) {
  6952. // neighbor.visited = true;
  6953. // neighbor.parent = current;
  6954. // neighbor.g = tentative_g_score;
  6955. // neighbor.h = heuristic(neighbor.position, goal.position);
  6956. // neighbor.f = neighbor.g + neighbor.h;
  6957. // if (!visited) {
  6958. // open_heap.push(neighbor);
  6959. // } else {
  6960. // open_heap.rescoreElement(neighbor);
  6961. // };
  6962. // };
  6963. // };
  6964. // };
  6965.  
  6966. // log("done with astar - no path found")
  6967. // // return null if no path has been found
  6968. // return null
  6969. // };
  6970.  
  6971. // const print_node_list = function(list) {
  6972. // var output = "";
  6973. // log("printing node list, length:", list.length, "list:", list);
  6974. // for (var i = 0; i < list.length; i++) {
  6975. // output += list[i].position.x + ", " + list[i].position.y + ", " + list[i].position.z + "\n";
  6976. // };
  6977. // log(output);
  6978. // };
  6979.  
  6980. // const create_red_line_between_nodes = function(ss, node1, node2) {
  6981. // // const tracerLines = L.BABYLON.MeshBuilder.CreateLines("tracerLines", { points: [newPosition, crosshairsPosition] }, newScene);
  6982. // let pos1 = [node1.position.x - 0.5, node1.position.y - 0.5, node1.position.z - 0.5];
  6983. // let pos2 = [node2.position.x - 0.5, node2.position.y - 0.5, node2.position.z - 0.5];
  6984. // if (window.pathLines === undefined) {
  6985. // let node_lines = L.BABYLON.MeshBuilder.CreateLines(new Date().getTime().toString(), { points: [ss.MYPLAYER[H.actor][H.mesh].position, pos2] }, ss.MYPLAYER[H.actor].scene);
  6986. // node_lines.color = new L.BABYLON.Color3(1, 0, 0);
  6987. // node_lines[H.renderingGroupId] = 1;
  6988. // window.pathLines = [node_lines];
  6989. // } else {
  6990. // let node_lines = L.BABYLON.MeshBuilder.CreateLines(new Date().getTime().toString(), { points: [ss.MYPLAYER[H.actor][H.mesh].position, pos2] }, ss.MYPLAYER[H.actor].scene);
  6991. // node_lines.color = new L.BABYLON.Color3(1, 0, 0);
  6992. // node_lines[H.renderingGroupId] = 1;
  6993. // window.pathLines.push(node_lines);
  6994. // };
  6995. // };
  6996.  
  6997. // const create_pathfinding_lines = function(ss, path) {
  6998. // for (var i = 0; i < path.length - 1; i++) {
  6999. // create_red_line_between_nodes(ss, path[i], path[i + 1]);
  7000. // };
  7001. // };
  7002.  
  7003. // // end pathfinding
  7004.  
  7005. // const createMapData = function () {
  7006. // if (!map_data_created) {
  7007. // log("Creating map data");
  7008. // new MapNode(new Position(ss.GAMEMAP.data.length - 1, ss.GAMEMAP.data[0].length - 1, ss.GAMEMAP.data[0][0].length - 1), [], ss.GAMEMAP.data);
  7009. // map_data_created = true;
  7010. // return true;
  7011. // }
  7012. // }
  7013.  
  7014. // const mapStuff = function () {
  7015.  
  7016. // //log("node = " + get_node_at(get_player_position(ss.MYPLAYER)), "nodelist len = " + GLOBAL_NODE_LIST.length);
  7017.  
  7018. // if (findNewPath && !activePath && !activeNodeTarget && get_node_at(get_player_position(ss.MYPLAYER))) {
  7019.  
  7020. // let player_pos = get_player_position(ss.MYPLAYER);
  7021. // let player_node = get_node_at(player_pos);
  7022. // if (player_node) {
  7023. // let position = {
  7024. // x: player_pos.x + Math.floor(Math.random() * 5) - 1,
  7025. // y: player_pos.y,
  7026. // z: player_pos.z + Math.floor(Math.random() * 5) - 1
  7027. // }
  7028. // // check if node at position exists
  7029. // let random_node = get_node_at(position);
  7030.  
  7031. // if (!(player_node === random_node) && random_node) {
  7032. // log("location, target:")
  7033. // print_node_list([player_node, random_node])
  7034. // activePath = AStar(player_node, random_node);
  7035. // if (activePath) {
  7036. // log("setting active node target");
  7037. // print_node_list(activePath);
  7038. // activeNodeTarget = activePath[0];
  7039. // log("list printed, target set, creating pathfinding lines")
  7040. // create_pathfinding_lines(ss, activePath);
  7041. // findNewPath = false;
  7042. // log("found path to random node")
  7043. // } else {
  7044. // log("unable to find path to random node")
  7045. // }
  7046. // } else {
  7047. // log("player node / random node not air")
  7048. // }
  7049. // } else {
  7050. // log("player not on air node currently")
  7051. // }
  7052. // }
  7053.  
  7054.  
  7055. // if (pathfindingTargetOverride !== undefined) {
  7056. // createMapData();
  7057. // let player_node = get_node_at(get_player_position(ss.MYPLAYER));
  7058. // let target_node = get_node_at(pathfindingTargetOverride);
  7059. // if (player_node && target_node && !activePath) {
  7060. // let path = AStar(player_node, target_node);
  7061.  
  7062. // if (path) {
  7063. // if (path.length > 0) {
  7064. // activePath = path;
  7065. // activeNodeTarget = path[0];
  7066. // } else {
  7067. // log('already at target')
  7068. // activePath = null;
  7069. // activeNodeTarget = null;
  7070. // pathfindingTargetOverride = undefined;
  7071. // }
  7072. // } else {
  7073. // if (despawnIfNoPath) {
  7074. // sendChatMessage("despawnIfNoPath");
  7075. // }
  7076. // }
  7077. // } else {
  7078. // if (!activePath) {
  7079. // if (player_node) {
  7080. // log("playernode good")
  7081. // }
  7082. // if (target_node) {
  7083. // log("targetnode good")
  7084. // }
  7085. // if (!player_node) {
  7086. // log("playernode bad")
  7087. // }
  7088. // if (!target_node) {
  7089. // log("targetnode bad")
  7090. // }
  7091. // }
  7092. // }
  7093. // }
  7094.  
  7095. // if (activeNodeTarget && activePath) {
  7096. // //log("found target and path");
  7097. // let player_node = get_node_at(get_player_position(ss.MYPLAYER));
  7098. // if (player_node == activeNodeTarget || activePath.includes(player_node)) { // if we are at the target or have somehow skipped ahead in the list
  7099. // if (player_node == activeNodeTarget) {
  7100. // activeNodeTarget = activePath.shift();
  7101. // log("update target");
  7102. // if (activePath.length == 0) {
  7103. // log("path completed");
  7104. // activePath = null;
  7105. // activeNodeTarget = null;
  7106. // pathfindingTargetOverride = undefined;
  7107. // }
  7108. // } else {
  7109. // while (activePath.includes(player_node)) {
  7110. // activeNodeTarget = activePath.shift();
  7111. // }
  7112. // if (activePath.length == 0) {
  7113. // log("path completed");
  7114. // activePath = null;
  7115. // activeNodeTarget = null;
  7116. // pathfindingTargetOverride = undefined;
  7117. // }
  7118.  
  7119. // }
  7120. // } else {
  7121. // //log("not at target");
  7122. // }
  7123. // /* if (!(activePath.includes(get_node_at(get_player_position(ss.MYPLAYER))))) { // went off path somehow, need to find new path
  7124. // findNewPath = true;
  7125. // activePath = null;
  7126. // activeNodeTarget = null;
  7127. // log("went off path, finding new path")
  7128. // } */
  7129. // }
  7130.  
  7131. // if (activeNodeTarget) {
  7132. // // look towards the node
  7133. // if (isFirstFrameAttemptingToPathfind) {
  7134. // /* let vec = new L.BABYLON.Vector3(0, 0, 1)
  7135. // let calcYaw = calculateYaw(vec);
  7136. // let calcPitch = calculatePitch(vec);
  7137. // ss.MYPLAYER[H.yaw] = 0;
  7138. // ss.MYPLAYER[H.pitch] = 0; */
  7139. // isFirstFrameAttemptingToPathfind = false;
  7140.  
  7141. // } else {
  7142. // //log("looking towards node");
  7143.  
  7144. // let playerPosition = get_player_position(ss.MYPLAYER);
  7145. // let directionVector = new L.BABYLON.Vector3(activeNodeTarget.position.x - playerPosition.x, activeNodeTarget.position.y - playerPosition.y, activeNodeTarget.position.z - playerPosition.z);
  7146. // /* log(`
  7147. // --PATHING UPDATE--
  7148. // target: ${activeNodeTarget.position.x}, ${activeNodeTarget.position.y}, ${activeNodeTarget.position.z}
  7149. // current: ${playerPosition.x}, ${playerPosition.y}, ${playerPosition.z}
  7150. // directionVector: ${directionVector.x}, ${directionVector.y}, ${directionVector.z}
  7151. // calc yaw: ${calculateYaw(directionVector)}
  7152. // targ -> current diff:
  7153. // `) */
  7154. // //shit lags, lol
  7155. // ss.MYPLAYER[H.yaw] = calculateYaw(directionVector);
  7156. // ss.MYPLAYER[H.pitch] = 0;
  7157. // forceControlKeys = ss.CONTROLKEYSENUM.up;
  7158. // }
  7159. // };
  7160. // };
  7161.  
  7162. // const clearPath = function () {
  7163. // activePath = undefined;
  7164. // activeNodeTarget = undefined;
  7165. // };
  7166. // const clearPath_andTarget = function () {
  7167. // clearPath();
  7168. // pathfindingTargetOverride = undefined;
  7169. // };
  7170. // };
  7171.  
  7172.  
  7173. const findKeyWithProperty = function (obj, propertyToFind) {
  7174. for (const key in obj) {
  7175. if (obj[key] === null || obj[key] === undefined) {
  7176. continue;
  7177. };
  7178. if (!!obj[key] && (typeof (obj[key]) == 'object' || typeof (obj[key]) == 'function') && obj[key].hasOwnProperty(propertyToFind)) {
  7179. return key;
  7180. };
  7181. };
  7182. // Property not found
  7183. return null;
  7184. };
  7185.  
  7186. const findStringInLists = function (dictWithLists, str) {
  7187. for (const key in dictWithLists) {
  7188. if (dictWithLists.hasOwnProperty(key)) {
  7189. const list = dictWithLists[key];
  7190. if (list.includes(str)) {
  7191. return key; // Return the key where the string is found
  7192. };
  7193. };
  7194. };
  7195. return null; // Return null if the string is not found in any list
  7196. };
  7197.  
  7198. const mainLoop = function () {
  7199. const oneTime = function () {
  7200. //xd lmao
  7201. if (ss.MYPLAYER) {
  7202. log('%cSTATEFARM IS ATTEMPTING TO CREATE FAKE BABYLON', 'color: yellow; font-weight: bold; font-size: 1.2em; text-decoration: underline;');
  7203.  
  7204. const found = (babylon) => {
  7205. L.BABYLON = babylon;
  7206.  
  7207. H.actor = findKeyWithProperty(ss.MYPLAYER, H.mesh);
  7208. // Math.capVector3 = Math[H.capVector3];
  7209.  
  7210. log("StateFarm: found vars:", H);
  7211.  
  7212. crosshairsPosition = new L.BABYLON.Vector3();
  7213.  
  7214. Object.defineProperty(ss.MYPLAYER.scene, 'forceWireframe', {
  7215. configurable: false,
  7216. get: () => {
  7217. return extract("wireframe");
  7218. },
  7219. set: () => {}
  7220. });
  7221.  
  7222. if (AUTOMATED) {
  7223. automatedBorder.style.borderColor = 'rgba(0, 0, 255, 1)';
  7224. };
  7225. };
  7226.  
  7227. const doFake = () => {
  7228. L.BABYLONfake = {
  7229. //can use GetBabylon
  7230. Color3: ss.GetBabylon("BABYLON.Color3"),
  7231. Vector3: ss.GetBabylon("BABYLON.Vector3"),
  7232. CubeTexture: ss.GetBabylon("BABYLON.CubeTexture"),
  7233. PointLight: ss.GetBabylon("BABYLON.PointLight"),
  7234. ArcRotateCamera: ss.GetBabylon("BABYLON.ArcRotateCamera"),
  7235. Matrix: ss.GetBabylon("BABYLON.Matrix"),
  7236.  
  7237. //can use ss
  7238. TransformNode: ss.TransformNode,
  7239. MeshBuilder: ss.MeshBuilder,
  7240. Viewport: ss.Viewport,
  7241. VertexBuffer: ss.VertexBuffer,
  7242. VertexData: ss.VertexData,
  7243. SceneLoader: ss.SceneLoader,
  7244. };
  7245.  
  7246. L.BABYLONfake.Matrix.RotationYawPitchRoll = L.BABYLONfake.Matrix[H.RotationYawPitchRoll];
  7247. L.BABYLONfake.MeshBuilder.CreateLines = ss.CreateLines; //initially i meant to just make this an attribute but this also works
  7248.  
  7249. createPopup("Created BabylonFake", "success");
  7250. log('%cSTATEFARM SUCCESSFULLY LOADED FAKE BABYLON!', 'color: green; font-weight: bold; font-size: 1.2em; text-decoration: underline;');
  7251. found(L.BABYLONfake);
  7252. };
  7253.  
  7254. const doImport = () => {
  7255. log('%c(Fallback) STATEFARM IS ATTEMPTING TO LOAD L.BABYLON', 'color: yellow; font-weight: bold; font-size: 1.2em; text-decoration: underline;');
  7256. var script = document.createElement("script");
  7257. script.src = babylonURL.format(H?.BabylonVersion || "7.21.1");
  7258. script.onload = function () {
  7259. if (unsafeWindow.BABYLON) {
  7260. L.BABYLONimported = unsafeWindow.BABYLON;
  7261. delete unsafeWindow.BABYLON;
  7262.  
  7263. log("Imported Babylon.js successfully");
  7264. log(L.BABYLONimported.Engine.Version);
  7265.  
  7266. createPopup("Imported Babylon", "success");
  7267. log('%cSTATEFARM SUCCESSFULLY IMPORTED BABYLON!', 'color: green; font-weight: bold; font-size: 1.2em; text-decoration: underline;');
  7268. found(L.BABYLONimported);
  7269. } else {
  7270. log('%cSTATEFARM COULD NOT LOAD L.BABYLON', 'color: red; font-weight: bold; font-size: 1.2em; text-decoration: underline;');
  7271. };
  7272. };
  7273. document.body.appendChild(script);
  7274. };
  7275.  
  7276. // chrome web store reviewers, GM_info is never declared and this will always be false in the web store environment
  7277. if (extract("forceImport") && typeof GM_info !== 'undefined') {
  7278. doImport();
  7279. } else {
  7280. try {
  7281. doFake();
  7282. } catch (error) {
  7283. log("fake babylon creation failed");
  7284. log(error);
  7285. doImport();
  7286. };
  7287. };
  7288.  
  7289. ranOneTime = true;
  7290. };
  7291. };
  7292.  
  7293.  
  7294. const initVars = function () {
  7295.  
  7296. isBanned = false; //cant be banned if in a game /shrug
  7297. errorString = undefined; //no error if ur playing
  7298. forceControlKeys = undefined; //reset every frame
  7299.  
  7300. if (newGame) {
  7301. onlinePlayersArray = [];
  7302. miniCamera = null;
  7303. };
  7304. if (extract("debug") && (typeof playerLogger === 'undefined')) {
  7305. playerLogger = [];
  7306. };
  7307. const weaponBox = document.getElementById("weaponBox");
  7308. const chatContainer = document.getElementById('chatOut');
  7309. const chatItems = chatContainer.getElementsByClassName('chat-item');
  7310. if ((weaponBox.style.display != lastWeaponBox) || (chatItems.length != lastChatItemLength)) {
  7311. lastWeaponBox = weaponBox.style.display;
  7312. lastChatItemLength = chatItems.length;
  7313.  
  7314. const maxChat = extract("maxChat");
  7315. const maxMessages = (weaponBox.style.display === "block" && maxChat) || 9999999;
  7316.  
  7317. const startIndex = Math.max(0, chatItems.length - maxMessages);
  7318.  
  7319. for (let i = chatItems.length - 1; i >= 0; i--) {
  7320. const chatIndex = i - startIndex;
  7321. const isInRange = chatIndex >= 0 && chatIndex < maxMessages;
  7322. chatItems[i].style.display = isInRange ? '' : 'none';
  7323. };
  7324. };
  7325.  
  7326. if (didStateFarm) {
  7327. if (!loggedGameMap) {
  7328. log(ss.GAMEMAP.width, ss.GAMEMAP.height, ss.GAMEMAP.data);
  7329. loggedGameMap = true;
  7330. };
  7331. username = ss.MYPLAYER?.name;
  7332.  
  7333. crosshairsPosition.copyFrom(ss.MYPLAYER[H.actor][H.mesh].position);
  7334.  
  7335. // //eye level
  7336. crosshairsPosition.y += 0.4;
  7337. const forwardOffset = -5;
  7338. const yaw = ss.MYPLAYER[H.yaw];
  7339. const pitch = -ss.MYPLAYER[H.pitch];
  7340. const forwardX = Math.sin(yaw) * Math.cos(pitch);
  7341. const forwardY = Math.sin(pitch);
  7342. const forwardZ = Math.cos(yaw) * Math.cos(pitch);
  7343. crosshairsPosition.x += forwardX * forwardOffset;
  7344. crosshairsPosition.y += forwardY * forwardOffset;
  7345. crosshairsPosition.z += forwardZ * forwardOffset;
  7346.  
  7347. ammo = ss.MYPLAYER[H.weapon].ammo;
  7348.  
  7349. whitelistPlayers = (extract("whitelist") || "").split(',');
  7350. blacklistPlayers = (extract("blacklist") || "").split(',');
  7351.  
  7352. ss.MYPLAYER[H.actor].scene.texturesEnabled = extract("enableTextures");
  7353. };
  7354. };
  7355. const updateLinesESP = function () {
  7356. const objExists = Date.now();
  7357.  
  7358. //update playerESP boxes, tracer lines, colors
  7359. ss.PLAYERS.forEach(player => {
  7360. if (player && (player !== ss.MYPLAYER) && player[H.playing] && (player[H.hp] > 0) && ((!ss.MYPLAYER.team) || (player.team !== ss.MYPLAYER.team))) {
  7361. const whitelisted = (extract("whitelistESPType") == "highlight" || !extract("enableWhitelistTracers") || playerMatchesList(whitelistPlayers, player));
  7362. const blacklisted = (extract("blacklistESPType") == "justexclude" && extract("enableBlacklistTracers") && playerMatchesList(blacklistPlayers, player));
  7363. const passedLists = whitelisted && (!blacklisted);
  7364. const tracersType = extract("tracersType");
  7365.  
  7366. if (player.lookLineData && player.lookLineData.length === 6) {
  7367. // player.lookLineData
  7368. const x1 = player.lookLineData[0],
  7369. y1 = player.lookLineData[1],
  7370. z1 = player.lookLineData[2],
  7371. x2 = player.lookLineData[3],
  7372. y2 = player.lookLineData[4],
  7373. z2 = player.lookLineData[5];
  7374.  
  7375. // ss.MYPLAYER pos
  7376. const rx = ss.MYPLAYER[H.actor][H.mesh].position.x,
  7377. ry = ss.MYPLAYER[H.actor][H.mesh].position.y,
  7378. rz = ss.MYPLAYER[H.actor][H.mesh].position.z;
  7379. // not speed
  7380. const dx = x2 - x1, dy = y2 - y1, dz = z2 - z1;
  7381. // , also not spped
  7382. const rpx = rx - x1, rpy = ry - y1, rpz = rz - z1;
  7383. // cross = (r - p) x (q - p)
  7384. const cx = rpy * dz - rpz * dy, cy = rpz * dx - rpx * dz, cz = rpx * dy - rpy * dx;
  7385. const crossLength = Math.sqrt(cx * cx + cy * cy + cz * cz);
  7386. // length of the line vector (q - p)
  7387. const lineLength = Math.sqrt(dx * dx + dy * dy + dz * dz);
  7388. // min distance point to line is crossp magnitude / line length
  7389. player.aimdistance = crossLength / lineLength;
  7390. //console.log(`Minimum distance from ${player.name}'s look line to my position:`, aimdistance);
  7391. };
  7392.  
  7393. //predEsp
  7394. if (extract("predictionESP")) { //important note here is that we only create/update the predESP if the module is toggled on. saves resources from predictPosition raycast
  7395. if (!player.pred) { //do we need a new TN as parent?
  7396. const pPTransformNode = new L.BABYLON.TransformNode("pPredTNode", player[H.actor].scene); //TN's are literally perfect for this wtf
  7397. pPTransformNode.parent = player[H.actor][H.mesh]; //parent to the player's mesh. Not really needed, but good practise.
  7398. player.pred = pPTransformNode; //why use object actually? All the info is stored right in the TN :)
  7399. };
  7400. if (player.pred && player.pred.getScene()) { //does pred exist and is on a valid scene? not really needed, as we literally
  7401. //create the thing above if this is not the case, but eh. Better safe than sorry
  7402. player.pred.setAbsolutePosition(predictPosition(player)); //transformNode is attached to mesh, so we need absolute pos here.
  7403. updateOrCreateLinesESP(player.pred, "pPredESP", hexToRgb(getColor("predictionESPColor", "predictionESPColorRainbow"))); //I love names. pPredESP, pPTransformNode. Truly nice
  7404. player.pred.exists = objExists; //make sure the lines don't get picked up by the ESPLines Garbage collector afterwards
  7405. player.pred.tracerLines.visibility = false; //they just don't work for this.
  7406. };
  7407. };
  7408.  
  7409. let color, progress;
  7410. if (extract("enableWhitelistTracers") && extract("whitelistESPType") == "highlight" && playerMatchesList(whitelistPlayers, player)) {
  7411. color = hexToRgb(extract("whitelistColor"));
  7412. } else if (extract("enableBlacklistTracers") && extract("blacklistESPType") == "highlight" && playerMatchesList(blacklistPlayers, player)) {
  7413. color = hexToRgb(extract("blacklistColor"));
  7414. } else if (tracersType == "proximity") {
  7415. const distance = distancePlayers(player);
  7416. if (distance < extract("tracersColor1to2")) { //fade between first set
  7417. progress = (distance / extract("tracersColor1to2"));
  7418. color = fadeBetweenColors(extract("tracersColor1"), extract("tracersColor2"), progress); //ye fade look dumb dumb with fade
  7419. } else if (distance < extract("tracersColor2to3")) { //fade between second set
  7420. progress = ((distance - extract("tracersColor1to2")) / (extract("tracersColor2to3") - extract("tracersColor1to2")));
  7421. color = fadeBetweenColors(extract("tracersColor2"), extract("tracersColor3"), progress);
  7422. } else {
  7423. color = hexToRgb(extract("tracersColor3"));
  7424. };
  7425. } else if (tracersType == "static") {
  7426. color = hexToRgb(getColor("tracersColor1", "tracersColor1Rainbow"));
  7427. } else if (tracersType == "visibility") {
  7428. color = getLineOfSight(player) ? hexToRgb(getColor("tracersColor2", "tracersColor2Rainbow")) : hexToRgb(getColor("tracersColor1", "tracersColor1Rainbow") )
  7429. };
  7430. updateOrCreateLinesESP(player, "playerESP", color);
  7431.  
  7432. player.tracerLines.visibility = player[H.playing] && extract("tracers") && passedLists;
  7433. player.lookDirLine.visibility = player[H.playing] && extract("lookTracers") && passedLists;
  7434. player.box.visibility = extract("playerESP") && passedLists;
  7435. // player.target.visibility = extract("targets") && passedLists;
  7436. // player.target.visibility = false;
  7437.  
  7438. if (player[H.actor]) {
  7439. let eggSize = extract("eggSize")
  7440. player[H.actor][H.bodyMesh].scaling._x = eggSize;
  7441. player[H.actor][H.bodyMesh].scaling._y = eggSize;
  7442. player[H.actor][H.bodyMesh].scaling._z = eggSize;
  7443. };
  7444.  
  7445. player[H.actor][H.bodyMesh][H.renderingGroupId] = extract("chams") ? 1 : 0;
  7446.  
  7447. player.exists = objExists;
  7448. };
  7449. if (player) {
  7450. if (!ss.SETTINGS.safeNames) {
  7451. };
  7452. if (extract("unfilterNames")) { player.name = (cachedRealData[player.uniqueId]?.name || player.name);
  7453. } else player.name = (player?.normalName || player.name);
  7454. if (extract("nametags") && player[H.actor] && player[H.actor].nameSprite) { //taken from shellshock.js, so var names are weird
  7455. player[H.actor].nameSprite._manager[H.renderingGroupId] = 1;
  7456. player[H.actor].nameSprite[H.renderingGroupId] = 1;
  7457. var h = Math.length3(player[H.x] - ss.MYPLAYER[H.x], player[H.y] - ss.MYPLAYER[H.y], player[H.z] - ss.MYPLAYER[H.z]),
  7458. d = Math.pow(h, 1.25) * 2;
  7459. player[H.actor].nameSprite.width = d / 10 + .6;
  7460. player[H.actor].nameSprite.height = d / 20 + .3;
  7461. ss.MYPLAYER[H.actor].scene.activeCamera.fov = 0.75
  7462. };
  7463. if (!player.logged) {
  7464. player.logged = true;
  7465. if (extract("debug")) {
  7466. playerLogger.push(player);
  7467. log("Logged player: " + player.name, player)
  7468. }; //if youre a l33t kiddy who did a search for the term "logger", this does not in fact log any of the user's info. it just keeps track of players who joined and prints them to console.
  7469. if (extract("joinMessages") && (!newGame)) {
  7470. if (extract("publicBroadcast")) {
  7471. sendChatMessage((extract("joinLeaveBranding") ? "[SFC] " : "") + player.name + " joined.")
  7472. } else {
  7473. processChatItem("joined.", player.name, player.team, "rgba(0, 255, 0, 0.2)");
  7474. };
  7475. };
  7476. onlinePlayersArray.push([player, player.name, player.team]);
  7477.  
  7478. player[H.actor].setupNameSprite = (()=>{
  7479. setupNameSpriteNew(player[H.actor])
  7480. });
  7481. player[H.actor].setupNameSprite();
  7482. // let oldUpdateTeam = player[H.actor].updateTeam;
  7483. // player[H.actor].updateTeam = (()=>{
  7484. // updateTeamNew(player[H.actor], oldUpdateTeam)
  7485. // });
  7486. };
  7487.  
  7488. if (framesPassed % extract("nametagInfoInterval") === 0) {
  7489. //cache triggers
  7490. let playerInfo = {
  7491. score: player.score,
  7492. totalDeaths: player.totalDeaths,
  7493. bestGameStreak: player.bestGameStreak,
  7494.  
  7495. team: player.team,
  7496.  
  7497. hp: player[H.hp],
  7498. hardBoiledValue: player.hardBoiledValue,
  7499.  
  7500. shouldReplace: extract("nametagInfo"), //replace with the extract l8r
  7501. };
  7502.  
  7503. let playerInfoOld = playerInfoCache[player[H.uniqueId]];
  7504.  
  7505. if ((playerInfoOld) && (
  7506. (playerInfo.shouldReplace != playerInfoOld.shouldReplace) || ((playerInfo.shouldReplace) && (
  7507. (playerInfo.score != playerInfoOld.score) ||
  7508. (playerInfo.totalDeaths != playerInfoOld.totalDeaths) ||
  7509. (playerInfo.bestGameStreak != playerInfoOld.bestGameStreak) ||
  7510. (playerInfo.team != playerInfoOld.team) ||
  7511. (playerInfo.hp != playerInfoOld.hp) ||
  7512. (playerInfo.hardBoiledValue != playerInfoOld.hardBoiledValue)
  7513. ))
  7514. )) {
  7515. player[H.actor].setupNameSprite();
  7516. };
  7517.  
  7518. playerInfoCache[player[H.uniqueId]] = playerInfo;
  7519.  
  7520. if (player[H.actor]?.nameSprite?.color) {
  7521. playerInfo.shouldReplace ?
  7522. (player[H.actor].nameSprite.color = ss.teamColors.textColor[0]) :
  7523. (player[H.actor].nameSprite.color = ss.teamColors.textColor[player.team]);
  7524. }
  7525. };
  7526.  
  7527. player.isOnline = objExists;
  7528. };
  7529. });
  7530. playersInGame = onlinePlayersArray.length;
  7531. for (let i = 0; i < onlinePlayersArray.length; i++) {
  7532. if (onlinePlayersArray[i][0] && onlinePlayersArray[i][0].isOnline == objExists) { //player still online
  7533. onlinePlayersArray[i][2] = onlinePlayersArray[i][0].team;
  7534. } else {
  7535. if (extract("leaveMessages") && (!newGame)) {
  7536. if (extract("publicBroadcast")) {
  7537. sendChatMessage((extract("joinLeaveBranding") ? "[SFC] " : "") + onlinePlayersArray[i][1] + " left.")
  7538. } else {
  7539. processChatItem("left.", onlinePlayersArray[i][1], onlinePlayersArray[i][2], "rgba(255, 0, 0, 0.2)");
  7540. };
  7541. };
  7542. onlinePlayersArray.splice(i, 1);
  7543. };
  7544. };
  7545. //update ammoESP boxes, tracer lines, colors
  7546. if (extract("ammoESP") || extract("ammoTracers") || extract("grenadeESP") || extract("grenadeTracers")) {
  7547. ss.OBJECTSVAR.getShadowMap()[H.renderList].forEach(item => {
  7548. if (item.isEnabled && item.isEnabled() && item[H.sourceMesh] && item[H.sourceMesh].name && (item[H.sourceMesh].name == "grenadeItem" || item[H.sourceMesh].name == "ammo")) { //this is what we want
  7549. const itemType = item[H.sourceMesh].name;
  7550. let color = itemType == "ammo" && extract("ammoESPColor") || extract("grenadeESPColor");
  7551. color = hexToRgb(color);
  7552.  
  7553. updateOrCreateLinesESP(item, "ammoESP", color)
  7554.  
  7555. let willBeVisible = false;
  7556.  
  7557. if (itemType == "ammo") { //ammo
  7558. const regime = extract("ammoESPRegime");
  7559. if (regime == "whendepleted" && ammo.store == 0) {
  7560. willBeVisible = true;
  7561. } else if (regime == "whenlow" && ammo.store <= ammo[H.capacity]) {
  7562. willBeVisible = true;
  7563. } else if (regime == "belowmax" && ammo.store < ammo[H.storeMax]) {
  7564. willBeVisible = true;
  7565. } else if (regime == "alwayson") {
  7566. willBeVisible = true;
  7567. };
  7568. } else { //grenades
  7569. const regime = extract("grenadeESPRegime");
  7570. if (regime == "whendepleted" && ss.MYPLAYER[H.grenadeCount] == 0) {
  7571. willBeVisible = true;
  7572. } else if (regime == "whenlow" && ss.MYPLAYER[H.grenadeCount] <= 1) {
  7573. willBeVisible = true;
  7574. } else if (regime == "belowmax" && ss.MYPLAYER[H.grenadeCount] < ss.MYPLAYER[H.grenadeCapacity]) {
  7575. willBeVisible = true;
  7576. } else if (regime == "alwayson") {
  7577. willBeVisible = true;
  7578. };
  7579. };
  7580.  
  7581. item.box.visibility = willBeVisible && (itemType == "ammo" && extract("ammoESP") || extract("grenadeESP"));
  7582. item.tracerLines.visibility = willBeVisible && (itemType == "ammo" && extract("ammoTracers") || extract("grenadeTracers"));
  7583.  
  7584. item.exists = objExists;
  7585. };
  7586. });
  7587. };
  7588. //trajectories
  7589. if (trajectory) {
  7590. trajectory.dispose();
  7591. trajectory = null;
  7592. };
  7593. if (extract("trajectories") && ss.MYPLAYER[H.grenadeCount] >= 1 && ss.MYPLAYER[H.playing]) {
  7594. if (!trajectoryNade) {
  7595. const clone = ss.cloneMesh('grenadeItem', ss.SCENE, null);
  7596. if (clone) {
  7597. clone.setEnabled(true);
  7598. trajectoryNade = clone;
  7599. trajectoryNade.renderOverlay = true;
  7600. trajectoryNade[H.renderingGroupId] = 1;
  7601. trajectoryNade.scaling.x = 2.5;
  7602. trajectoryNade.scaling.y = 2.5;
  7603. trajectoryNade.scaling.z = 2.5;
  7604. trajectoryNade.color = new L.BABYLON.Color3(0.627, 0.125, 0.941); // https://3dwebgs.github.io/color4bbyln/
  7605. };
  7606. };
  7607.  
  7608. let power = 0;
  7609.  
  7610. if (extract("grenadeMax")) {
  7611. power = extract("grenadePower");
  7612. } else if (document.getElementById("grenadeThrowContainer").style.visibility === "visible") {
  7613. power = ss.grenadeThrowPower;
  7614. }
  7615.  
  7616. const result = newPredictGrenade(ss.MYPLAYER, power);
  7617. const lines = [result.positions.map(e => new L.BABYLON.Vector3(e.x, e.y, e.z))];
  7618. trajectory = L.BABYLON.MeshBuilder.CreateLineSystem("traject", { lines: lines }, ss.SCENE);
  7619. trajectory.color = new L.BABYLON.Color3(0.627, 0.125, 0.941); // https://3dwebgs.github.io/color4bbyln/
  7620. trajectory[H.renderingGroupId] = 1;
  7621.  
  7622. trajectoryNade.position = new L.BABYLON.Vector3(result.finalPos.x, result.finalPos.y, result.finalPos.z);
  7623. } else if (trajectoryNade) {
  7624. trajectoryNade.dispose();
  7625. trajectoryNade = null;
  7626. };
  7627. // log("done updating lines")
  7628. //garbage collection
  7629. for (let i = 0; i < ESPArray.length; i++) {
  7630. if (ESPArray[i][0] && ESPArray[i][0].exists == objExists) { //obj still exists and still relevant
  7631. //do nothing, lol
  7632. } else {
  7633. if (ESPArray[i][0]) { //obj still exists but no longer relevant
  7634. log('%cRemoving tracer line due to irrelevant object', 'color: white; background: red');
  7635. ESPArray[i][0].generatedESP = false;
  7636. } else { //obj no longer exists
  7637. log('%cRemoving tracer line due to no longer exists', 'color: white; background: red');
  7638. };
  7639. ESPArray[i][1].dispose(); //tracer
  7640. ESPArray[i][2].dispose(); //esp box
  7641. if (ESPArray[i][3]) { ESPArray[i][3].dispose() }; //target
  7642. if (ESPArray[i][4]) { ESPArray[i][4].dispose() }; //look linetrace forward line
  7643. ESPArray.splice(i, 1);
  7644. };
  7645. }; newGame = false;
  7646. };
  7647. createAnonFunction("retrieveFunctions", function (vars, doStateFarm) {
  7648. ss = vars;
  7649.  
  7650. // unsafeWindow.vueApp._showGenericPopup = unsafeWindow.vueApp.showGenericPopup; //this just doesnt work
  7651.  
  7652. // unsafeWindow.vueApp.showGenericPopup = (...args) => {
  7653. // if (args[0] === 'session_expired') return;
  7654. // return unsafeWindow.vueApp._showGenericPopup(...args);
  7655. // };
  7656.  
  7657. if (doStateFarm) {
  7658. didStateFarm = true;
  7659. return F.STATEFARM();
  7660. } else {
  7661. log("StateFarm: creating silence audio");
  7662. unsafeWindow.BAWK.sounds.silence = Object.assign({}, unsafeWindow.BAWK.sounds.ammo);
  7663. unsafeWindow.BAWK.sounds.silence.end = 0.001;
  7664. };
  7665. });
  7666.  
  7667. createAnonFunction("register", async () => {
  7668. let wait = (ms) => new Promise((res) => setTimeout(res, ms));
  7669.  
  7670. document.body.insertAdjacentHTML('beforeend', `
  7671. <style>
  7672. .factoryOverlay {
  7673. position: fixed;
  7674. top: 0;
  7675. left: 0;
  7676. width: 100%;
  7677. height: 100%;
  7678. background-color: rgba(0, 0, 0);
  7679. z-index: 9999999;
  7680. display: flex;
  7681. flex-direction: column;
  7682. justify-content: center;
  7683. align-items: center;
  7684. }
  7685.  
  7686. .factoryText {
  7687. color: white;
  7688. font-weight: bold;
  7689. font-family: 'Nunito';
  7690. font-size: 20px;
  7691. }
  7692.  
  7693. .factoryStatus {
  7694. color: white;
  7695. font-weight: bold;
  7696. font-family: 'Nunito';
  7697. font-size: 36px;
  7698. }
  7699. </style>
  7700.  
  7701. <div class="factoryOverlay">
  7702. <span class="factoryText">Factory</span>
  7703. <span class="factoryStatus"></span>
  7704. </div>
  7705. `);
  7706.  
  7707. const factory = {
  7708. write: (p) => document.querySelector('.factoryStatus').innerHTML = p, // eslint-disable-line
  7709.  
  7710. remove: () => {
  7711. let style = (s, t) => document.querySelector('.factoryOverlay').style[s] = t; // eslint-disable-line
  7712. style('visibility', 'hidden');
  7713. style('opacity', 0);
  7714. style('transition', 'visibility 0s 1s, opacity 1s linear');
  7715. setTimeout(() => document.querySelector('.factoryOverlay').remove(), 1001);
  7716. }
  7717. };
  7718.  
  7719. factory.write('Fetching Account...');
  7720.  
  7721. let account;
  7722.  
  7723. try {
  7724. account = await (await fetch(factoryURL + extract('factoryKey'), {
  7725. method: 'POST'
  7726. })).json();
  7727. } catch {};
  7728.  
  7729. if (!account) {
  7730. factory.write('Factory is currently offline.');
  7731. setTimeout(() => factory.remove(), 2000);
  7732. return;
  7733. } else if (!account.success) {
  7734. factory.write(account.error || 'Unknown error.');
  7735. setTimeout(() => factory.remove(), 2000);
  7736. return;
  7737. };
  7738.  
  7739. factory.write('Fetched Account! 🎉 Signing in....');
  7740.  
  7741. let signIn = async () => {
  7742. try {
  7743. await unsafeWindow.firebase.auth().signInWithEmailAndPassword(account.email, account.password);
  7744. } catch {
  7745. await signIn();
  7746. };
  7747. };
  7748.  
  7749. await signIn();
  7750.  
  7751. factory.write('Fully signed in! 🎉');
  7752. await wait(1000);
  7753. factory.remove();
  7754. });
  7755.  
  7756. const applySkybox = () => {
  7757. //check if we should switch
  7758. const delta2 = Date.now() - lastRandomSkyBoxChangeTime;
  7759. const desire = extract("randomSkyBoxInterval") ? extract("randomSkyBoxInterval") * 60 * 1000 : -1; //stored in minutes, so *60 -> seconds *1000 -> milliseconds.
  7760. if (
  7761. extract("randomSkyBox") &&
  7762. delta2 != -1 &&
  7763. delta2 > desire
  7764. ) {
  7765. const newIdx = randomInt(0, loadedSkyboxes.length - 1);
  7766. log("skybox change overdue for " + (delta2 - desire) + "ms. New skybox index chosen: " + newIdx);
  7767. change("skybox", newIdx); //maybe not the best to overwrite the actual module setting, but eh, don't want to rewrite the entire thing....
  7768. lastRandomSkyBoxChangeTime = Date.now();
  7769. };
  7770. if (!unsafeWindow[skyboxName]) return;
  7771. if (!(extract('skybox') === 'default' || extract('skybox') === true || ss.SCENE.skyboxTextureThing == extract('skybox'))) {
  7772. let url = `${atob(extract("skybox"))}/skybox`;
  7773. unsafeWindow[skyboxName].material.reflectionTexture = new L.BABYLON.CubeTexture(url, ss.SCENE);
  7774. unsafeWindow[skyboxName].material.reflectionTexture.coordinatesMode = 5; //L.BABYLON.Texture.SKYBOX_MODE
  7775. ss.SCENE.skyboxTextureThing = extract('skybox');
  7776. };
  7777. };
  7778.  
  7779. createAnonFunction("STATEFARM", function () {
  7780. ss.PLAYERS.forEach((PLAYER) => (PLAYER.hasOwnProperty("ws")) ? (ss.MYPLAYER = PLAYER) : null);
  7781.  
  7782. if (!verification.checkVerification()) return true;
  7783.  
  7784. if (!ranOneTime) {
  7785. oneTime();
  7786. } else if (typeof (L.BABYLON) !== 'undefined') {
  7787. initVars();
  7788. updateLinesESP();
  7789. // mapStuff();
  7790. applySkybox();
  7791.  
  7792. let isVisible;
  7793. const player = currentlyTargeting || playerLookingAt || undefined;
  7794. if (player && player[H.playing]) {
  7795. isVisible = getLineOfSight(player);
  7796. };
  7797. highlightCrossHairReticleDot(extract("showLOS") ? isVisible : null);
  7798.  
  7799. if (extract("radar")) {
  7800. myPlayerDot.style.display = 'block';
  7801. ss.PLAYERS.forEach(player => { updateRadar(player, ss.MYPLAYER) });
  7802. } else {
  7803. ss.PLAYERS.forEach(player => {
  7804. if (playerDotsMap.has(player[H.uniqueId])) {
  7805. const playerDotToRemove = playerDotsMap.get(player[H.uniqueId]);
  7806. mapEl.removeChild(playerDotToRemove);
  7807. playerDotsMap.delete(player[H.uniqueId]);
  7808. }
  7809. });
  7810. myPlayerDot.style.display = 'none';
  7811. };
  7812.  
  7813. //credit to helloworld for the idea (worked it out on my own tho :P)
  7814. if (ss.MYPLAYER[H.playing]) {
  7815. //camera adjustments
  7816. ss.CAMERA.position.y = extract("perspective") !== "firstPerson" ? extract("perspectiveY") || 0 : 0;
  7817. ss.CAMERA.position.z = extract("perspective") !== "firstPerson" ? extract("perspective") == "thirdPerson" ? (extract("perspectiveZ") || 0) : (-extract("perspectiveZ")) || 0 : 0;
  7818. ss.CAMERA.rotation.x = extract("perspective") == "thirdPersonAlt" ? Math.PI : 0;
  7819.  
  7820. //adjust for scoping
  7821. if (ss.MYPLAYER.scope) {
  7822. let finalFov = 0.4;
  7823. let ourFov = (extract("fov") * (Math.PI / 180));
  7824. let currentFov = ss.CAMERA.fov;
  7825. let percentage = (currentFov - finalFov) / ourFov;
  7826.  
  7827. // log(percentage, finalFov, ourFov, currentFov);
  7828.  
  7829. ss.CAMERA.position.y = ss.CAMERA.position.y * percentage; //i thought this would make a sick transition but it actually wasnt that cool
  7830. ss.CAMERA.position.z = ss.CAMERA.position.z * percentage;
  7831. ss.CAMERA.rotation.x = ss.CAMERA.rotation.x * percentage;
  7832. };
  7833.  
  7834. //rendering
  7835. ss.MYPLAYER[H.actor][H.gunContainer]._children[0][H.renderingGroupId] = extract("perspective") !== "firstPerson" ? 0 : 2;
  7836. ss.MYPLAYER[H.actor][H.gunContainer]._children[2][H.renderingGroupId] = extract("perspective") !== "firstPerson" ? 0 : 2;
  7837. if (!ss.MYPLAYER.stampApplied) ss.MYPLAYER[H.actor].applyStamp(ss.MYPLAYER.stampItem); ss.MYPLAYER.stampApplied = true;
  7838. if (!ss.MYPLAYER[H.actor].hat) {
  7839. ss.MYPLAYER[H.actor].wearHat(ss.MYPLAYER.hatItem);
  7840. } else {
  7841. ss.MYPLAYER[H.actor].hat.visibility = extract("perspective") !== "firstPerson" ? 1 : 0;
  7842. };
  7843. //alpha effect, it sucks and doesnt work the way i wanted it to
  7844. /*
  7845. ss.MYPLAYER[H.actor].hands.material.alphaMode = 5;
  7846. ss.MYPLAYER[H.actor][H.bodyMesh].material.alphaMode = 5;
  7847. ss.MYPLAYER[H.actor].hands.material.alpha = ((extract("perspective") !== "firstPerson") && extract("perspectiveAlpha")) ? .5 : 1;
  7848. ss.MYPLAYER[H.actor][H.bodyMesh].material.alpha = ((extract("perspective") !== "firstPerson") && extract("perspectiveAlpha")) ? .5 : 1;
  7849. */
  7850. };
  7851.  
  7852. let filter = typeof(extract("filter")) == 'number' ? extract("filter") : 2;
  7853. if (ss.SCENE && ss.SCENE.appliedFilter !== filter) {
  7854. ss.SCENE.materials.forEach(material => {
  7855. material.alphaMode = filter;
  7856. }); ss.SCENE.appliedFilter = filter;
  7857. };
  7858.  
  7859. if (ss.MYPLAYER && ss.MYPLAYER[H.actor] && ss.MYPLAYER[H.actor][H.mesh]) {
  7860. ss.MYPLAYER[H.actor][H.mesh].scaling._y = extract("worldFlattening"); //this used to be left side gun but for some reason it just affects the world IDK
  7861.  
  7862. ss.MYPLAYER[H.actor][H.gunContainer].scaling._x = extract("gunPosition") == "hidden" ? 0 : 1;
  7863. ss.MYPLAYER[H.actor][H.gunContainer].scaling._y = extract("gunPosition") == "hidden" ? 0 : 1;
  7864. ss.MYPLAYER[H.actor][H.gunContainer].scaling._x = extract("gunPosition") == "hidden" ? 0 : 1;
  7865. };
  7866.  
  7867. if (extract("spamChat")) {
  7868. if (document.getElementById("chatIn").style.visibility == 'visible') {
  7869. if (spamDelay < Date.now()) {
  7870. if (Date.now() > (lastSpamMessage[0] + extract("spamChatDelay"))) {
  7871. let possibleMessages = extract("spamChatText").split("|");
  7872. let chosenMessage = possibleMessages[spamMessageCount % possibleMessages.length];
  7873. if (chosenMessage == lastSpamMessage[1]) { chosenMessage += String.fromCharCode(97 + Math.floor(Math.random() * 26)) };
  7874. sendChatMessage(chosenMessage);
  7875. lastSpamMessage = [Date.now(), chosenMessage];
  7876. spamMessageCount += 1;
  7877. };
  7878. } else if (spamDelay < Date.now() - 250) {
  7879. spamDelay = Date.now() + 250;
  7880. };
  7881. };
  7882. };
  7883. if (extract("chatHighlight")) {
  7884. document.getElementById("chatOut").style.userSelect = "text"
  7885. };
  7886. if (extract("autoRefill")) {
  7887. //log(ss.MYPLAYER[H.weapon]);
  7888. if (ammo[H.rounds] == 0) {
  7889. ss.MYPLAYER.reload();
  7890. } else if (extract("smartRefill")) {
  7891. let smartRefillMinAmmo = {
  7892. eggk47: 1,
  7893. dozenGauge: 0,
  7894. csg1: 1,
  7895. rpegg: 0,
  7896. smg: 1,
  7897. m24: 0,
  7898. aug: 3,
  7899. cluck9mm: 1
  7900. };
  7901. if (ammo[H.rounds] <= smartRefillMinAmmo[ss.MYPLAYER[H.weapon].constructor.standardMeshName]) {
  7902. ss.MYPLAYER.reload();
  7903. };
  7904. };
  7905. };
  7906. if (extract("autoGrenade") && isVisible && (ss.MYPLAYER[H.grenadeCount] > 0)) {
  7907. ss.MYPLAYER.throwGrenade();
  7908. };
  7909. if ((extract("autoWeapon") !== "disabled") && (!ss.MYPLAYER[H.playing])) {
  7910. weaponArray.random = randomInt(0, 6);
  7911. document.querySelectorAll('.weapon_img')[weaponArray[extract("autoWeapon")]].parentNode.click();
  7912. };
  7913. if (extract("revealBloom") || extract("showMinAngle")) {
  7914. const distCenterToOuter = 2 * (200 / ss.CAMERA.fov);
  7915. const bloomValues = predictBloom(ss.MYPLAYER[H.yaw], ss.MYPLAYER[H.pitch]);
  7916. // Set the new position of the circle
  7917. const centerX = (unsafeWindow.innerWidth / 2);
  7918. const centerY = (unsafeWindow.innerHeight / 2);
  7919. const offsettedX = centerX - (2 * distCenterToOuter * bloomValues[0]);
  7920. const offsettedY = centerY - (2 * distCenterToOuter * bloomValues[1]);
  7921. if (extract("revealBloom")) {
  7922. redCircle.style.display = '';
  7923. redCircle.style.bottom = offsettedY + 'px';
  7924. redCircle.style.right = offsettedX + 'px';
  7925. } else {
  7926. redCircle.style.display = 'none';
  7927. };
  7928. if (extract("showMinAngle")) {
  7929. minangleCircle.style.display = '';
  7930. let idkWhatThisIs = 25 * (1.25 / ss.CAMERA.fov);
  7931. minangleCircle.style.width = extract("aimbotMinAngle") * idkWhatThisIs + 'px';
  7932. minangleCircle.style.height = extract("aimbotMinAngle") * idkWhatThisIs + 'px';
  7933. minangleCircle.style.bottom = centerY + 'px';
  7934. minangleCircle.style.right = centerX + 'px';
  7935. };
  7936. };
  7937. if (!extract("showMinAngle")) {
  7938. minangleCircle.style.display = 'none';
  7939. };
  7940. const playerSlots = document.querySelectorAll('#playerList .playerSlot');
  7941. playerSlots.forEach(slot => {
  7942. const usernameElement = slot.querySelector('.playerSlot--name');
  7943. let username = usernameElement ? usernameElement.textContent.trim() : "";
  7944. const badgeURLs = Array.from(findBadgesForUsername(username)).reverse();
  7945. const existingBadges = slot.querySelectorAll('.badge-image');
  7946.  
  7947. if ((!extract("customBadges")) || (badgeURLs && badgeURLs.length < 1)) {
  7948. existingBadges.forEach(badge => badge.remove());
  7949. } else if (extract("customBadges") && username && badgeURLs && badgeURLs.length > 0 && existingBadges && existingBadges.length < 1) {
  7950. existingBadges.forEach(badge => badge.remove());
  7951. const eggIcon = !!(slot.querySelector('.playerSlot--icons .fas.fa-egg:not(.hidden)') || slot.querySelector('.playerSlot--icons .fab.fa-twitch:not(.hidden)'));
  7952. log(eggIcon, username)
  7953. badgeURLs.forEach((badgeURL, index) => {
  7954. const badgeImage = document.createElement('img');
  7955. badgeImage.src = badgeListURL + badgeURL;
  7956. badgeImage.className = 'badge-image';
  7957. badgeImage.style.position = 'absolute';
  7958. badgeImage.style.height = 'auto';
  7959. badgeImage.style.width = 'auto';
  7960. badgeImage.style.maxHeight = '100%';
  7961. badgeImage.style.maxWidth = '100%';
  7962. badgeImage.style.right = `${-13 - index * 8 - (eggIcon ? 10 : 0)}%`;
  7963. badgeImage.style.top = '50%';
  7964. badgeImage.style.transform = 'translateY(-50%)';
  7965. slot.style.position = 'relative';
  7966. slot.appendChild(badgeImage);
  7967. });
  7968. };
  7969. });
  7970.  
  7971. let partyLightsIntensity = extract("partyLightsIntensity") || 0;
  7972.  
  7973. if (extract("partyLightsEnabled") && partyLightsIntensity > 0 && !ss.SCENE.lights.find(light => light.name === "light")) {
  7974. log("Lets party :joe_cool:");
  7975. partyLight = new L.BABYLON.PointLight("light", new L.BABYLON.Vector3(0, 10, 0), ss.SCENE);
  7976. partyLight.diffuse = new L.BABYLON.Color3(1, 0, 0);
  7977. partyLight.specular = new L.BABYLON.Color3(1, 1, 1);
  7978. };
  7979. if (partyLight) {
  7980. partyLight.intensity = partyLightsIntensity;
  7981. var hue = (Date.now() / 1000) % 1;
  7982. partyLight.diffuse = hslToRgb(hue, 1, 0.5);
  7983. };
  7984.  
  7985. try {
  7986. let minAccuracy = ss.MYPLAYER[H.weapon][H.accuracyMin] + ss.MYPLAYER[H.weapon][H.accuracyLoss];
  7987. accuracyPercentage = (ss.MYPLAYER[H.weapon].accuracy - minAccuracy) / (ss.MYPLAYER[H.weapon][H.accuracyMax] - minAccuracy);
  7988. accuracyPercentage = Math.max(0, accuracyPercentage);
  7989. } catch (error) {
  7990. accuracyPercentage = 1;
  7991. };
  7992.  
  7993. // playerNearest=undefined; //currently unused and not defined
  7994. // enemyLookingAt=undefined; //currently unused and not defined
  7995.  
  7996. let playerLookingAtMinimum = 999999;
  7997. playerLookingAt = undefined; //used for player info
  7998.  
  7999. let enemyMinimumDistance = 999999;
  8000. enemyNearest = undefined; //used for antisneak
  8001.  
  8002. let previousTarget = currentlyTargeting;
  8003.  
  8004. let selectNewTarget = (!extract("antiSwitch") || !currentlyTargeting);
  8005. if (selectNewTarget) currentlyTargeting = false;
  8006. let isDoingAimbot = (extract("aimbot") && (extract("aimbotRightClick") ? isRightButtonDown : true) && ss.MYPLAYER[H.playing]);
  8007. // log(targetingComplete);
  8008.  
  8009. const targetType = extract("aimbotTargetMode");
  8010. const visibilityMode = extract("aimbotVisibilityMode");
  8011.  
  8012. let enemyMinimumValue = ((targetType == "pointingat") && (extract("silentAimbot"))) ? deg2rad(extract("aimbotMinAngle")) : 10000; //used for selecting target (either pointingat or nearest)
  8013.  
  8014. let enemyMinimumAimDistance = 999999;
  8015. enemyAimNearest = undefined;
  8016.  
  8017. let didAimbot
  8018. const candidates = [];
  8019. amountVisible = 0;
  8020.  
  8021. ss.PLAYERS.forEach(player => { //iterate over all players to filter out players that we definitely wont target, and also calc some stats for later use
  8022. if (player && (player !== ss.MYPLAYER) && player[H.playing] && (player[H.hp] > 0)) {
  8023. const whitelisted = (extract("enableWhenNoneVisible") || !extract("enableWhitelistAimbot") || extract("enableWhitelistAimbot") && playerMatchesList(whitelistPlayers, player));
  8024. const blacklisted = (extract("enableBlacklistAimbot") && playerMatchesList(blacklistPlayers, player));
  8025. const passedLists = (whitelisted) && (!blacklisted);
  8026. player.distance = distancePlayers(player);
  8027. player.adjustedDistance = distancePlayers(player, 2);
  8028. const directionVector = getDirectionVectorFacingTarget(player);
  8029.  
  8030. player.angleDiff = getAngularDifference(ss.MYPLAYER, { yawReal: calculateYaw(directionVector), pitchReal: calculatePitch(directionVector) });
  8031. player.isVisible = getLineOfSight(player, extract("prediction"));
  8032.  
  8033. if (player.angleDiff < playerLookingAtMinimum) {
  8034. playerLookingAtMinimum = player.angleDiff;
  8035. playerLookingAt = player;
  8036. };
  8037.  
  8038. if (passedLists) { //is possibly an an enemy
  8039. if (isDoingAimbot) { //is doing aimbot and we care about getting a new target
  8040. if (player.adjustedDistance < enemyMinimumValue) { //for antisneak, not targeting
  8041. enemyMinimumDistance = player.adjustedDistance;
  8042. enemyNearest = player;
  8043. };
  8044. if (player.aimdistance < enemyMinimumAimDistance) {
  8045. enemyMinimumAimDistance = player.aimdistance;
  8046. enemyAimNearest = player;
  8047. };
  8048. if (selectNewTarget) {
  8049. candidates.push(player);
  8050. if ( player.isVisible ) { amountVisible += 1 };
  8051. };
  8052. };
  8053. };
  8054. };
  8055. });
  8056.  
  8057. candidates.forEach(player => {
  8058. const valueToUse = (
  8059. (targetType == "nearest" && (
  8060. player.adjustedDistance
  8061. )) ||
  8062. (targetType == "pointingat" && (
  8063. player.angleDiff
  8064. )) ||
  8065. (targetType == "lowestHp" && (
  8066. player[H.hp]
  8067. )) ||
  8068. (targetType == "mostKills" && (
  8069. -player.score
  8070. )) ||
  8071. (targetType == "aimingAt" && (
  8072. player.aimdistance
  8073. ))
  8074. );
  8075. let visibleValue = ((!ss.MYPLAYER.team) || (player.team !== ss.MYPLAYER.team));
  8076. if (visibilityMode == "disabled") { //we dont care about that shit
  8077. //go ahead
  8078. } else if (amountVisible < 1) { //none of candidates are visible
  8079. const whitelisted = (!extract("enableWhitelistAimbot") || extract("enableWhitelistAimbot") && playerMatchesList(whitelistPlayers, player));
  8080. //log(player.name, whitelisted, visibleValue) //grrrr no console spam
  8081. visibleValue = (whitelisted && extract("enableWhenNoneVisible")) || (visibilityMode == "onlyvisible" ? false : visibleValue); //there are no visible candidates, so either select none if "onlyvisible" or ignore this altogether
  8082. } else { //some are visible
  8083. visibleValue = visibleValue && player.isVisible; //assuming now that either "prioritise" or "onlyvisible" are enabled, as "onlyvisible"'s use case fulfilled in previous statement
  8084. };
  8085. if (visibleValue && extract("aimbotTargetMode") !== "aimingAt") {
  8086. if (valueToUse < enemyMinimumValue) {
  8087. enemyMinimumValue = valueToUse;
  8088. currentlyTargeting = player;
  8089. };
  8090. };
  8091. if(extract("aimbotTargetMode") === "aimingAt"){
  8092. currentlyTargeting = enemyAimNearest;
  8093. };
  8094. });
  8095.  
  8096. const deltaTime = performance.now() - nowOld;
  8097. nowOld += deltaTime;
  8098.  
  8099. if (isDoingAimbot) {
  8100. if (currentlyTargeting && currentlyTargeting[H.playing] && currentlyTargeting[H.actor]) { //found a target
  8101. didAimbot = true;
  8102. currentAimTime += deltaTime;
  8103. if (currentlyTargeting.generatedESP) {
  8104. if (extract("tracers")) {
  8105. currentlyTargeting.tracerLines.color = new L.BABYLON.Color3(...hexToRgb(getColor("aimbotColor", "aimbotRainbow")));
  8106. };
  8107. if (extract("playerESP")) {
  8108. currentlyTargeting.box.color = new L.BABYLON.Color3(...hexToRgb(getColor("aimbotColor", "aimbotRainbow")));
  8109. };
  8110. };
  8111. if ((!extract("silentAimbot")) && (!extract("noWallTrack") || getLineOfSight(player, true)) && (targetingComplete || (deg2rad(extract("aimbotMinAngle")) > currentlyTargeting?.angleDiff))) {
  8112. const aimbot = getAimbot(currentlyTargeting);
  8113.  
  8114. let antiSnap = (1 - (extract("aimbotAntiSnap") || 0));
  8115.  
  8116. //new method: neuublue / https://github.com/AimTuxOfficial/AimTux/blob/master/src/Hacks/aimbot.cpp
  8117.  
  8118. const yawDiff = Math.radDifference(aimbot.yawReal, ss.MYPLAYER[H.yaw]);
  8119. const pitchDiff = Math.radDifference(aimbot.pitchReal, ss.MYPLAYER[H.pitch]);
  8120.  
  8121. if (extract("aimbotAntiSnapRegime") != "slowEnd") { // not slow end
  8122. antiSnap /= ((yawDiff ** 2 + pitchDiff ** 2) ** 0.5) * 4; // constant
  8123. if (extract("aimbotAntiSnapRegime") == "fastEnd") antiSnap *= antiSnap * 10; // fast end
  8124. else if (extract("aimbotAntiSnapRegime") == "timeBased") antiSnap *= currentAimTime / extract("maxAimTime"); // time based
  8125. antiSnap = Math.min(1, antiSnap);
  8126. };
  8127.  
  8128. ss.MYPLAYER[H.yaw] = setPrecision(ss.MYPLAYER[H.yaw] + yawDiff * antiSnap);
  8129. ss.MYPLAYER[H.pitch] = setPrecision(ss.MYPLAYER[H.pitch] + pitchDiff * antiSnap);
  8130.  
  8131. if (previousTarget !== currentlyTargeting) { targetingComplete = false };
  8132.  
  8133. //old method for antisnap
  8134. /*
  8135. const distanceBetweenPlayers = distancePlayers(currentlyTargeting);
  8136. const lerp = function (start, end, alpha) {
  8137. let value = (1 - alpha) * start + alpha * end;
  8138. if ((Math.abs(end - start) < (0.2 / (distanceBetweenPlayers))) || (targetingComplete)) {
  8139. value = end; targetingComplete = true;
  8140. };
  8141. return value;
  8142. };
  8143.  
  8144. ss.MYPLAYER[H.yaw] = setPrecision(lerp(ss.MYPLAYER[H.yaw], aimbot.yawReal, antiSnap));
  8145. ss.MYPLAYER[H.pitch] = setPrecision(lerp(ss.MYPLAYER[H.pitch], aimbot.pitchReal, antiSnap));
  8146. */
  8147. };
  8148. if (enemyMinimumDistance < extract("antiSneak")) {
  8149. currentlyTargeting = enemyNearest;
  8150. if (ammo[H.rounds] === 0) { //basically after MAGDUMP, switch to pistol, if that is empty reload and keep shootin'
  8151. if (ss.MYPLAYER[H.weaponIdx] === 0) { ss.MYPLAYER.swapWeapon(1); }
  8152. else { ss.MYPLAYER.reload(); }
  8153. };
  8154. ss.MYPLAYER.pullTrigger();
  8155. // log("ANTISNEAK---->", enemyNearest?.name, enemyMinimumDistance);
  8156. };
  8157. } else {
  8158. currentAimTime -= deltaTime;
  8159. if (extract("oneKill")) {
  8160. currentlyTargeting = "dead";
  8161. } else {
  8162. currentlyTargeting = false;
  8163. };
  8164. };
  8165. } else {
  8166. currentAimTime -= deltaTime;
  8167. currentlyTargeting = false;
  8168. targetingComplete = false;
  8169. if (extract("enableSeizureX")) {
  8170. ss.MYPLAYER[H.yaw] += extract("amountSeizureX")
  8171. };
  8172. if (extract("enableSeizureY")) {
  8173. ss.MYPLAYER[H.pitch] += extract("amountSeizureY")
  8174. };
  8175. };
  8176. currentAimTime = Math.clamp(currentAimTime, 0, extract("maxAimTime"));
  8177. highlightTargetOnLeaderboard(currentlyTargeting, (extract("highlightLeaderboard")) ? didAimbot : false);
  8178. if (extract("upsideDown")) { //sorta useless
  8179. if (ss.MYPLAYER[H.pitch] < 1.5 && ss.MYPLAYER[H.pitch] > -1.5) {
  8180. ss.MYPLAYER[H.pitch] = Math.PI;
  8181. };
  8182. };
  8183. if (extract("silentRoll")) {
  8184. ss.MYPLAYER[H.pitch] += 2 * Math.PI;
  8185. };
  8186. if (extract("enableAutoFire")) {
  8187. let autoFireType = extract("autoFireType");
  8188. let doAutoFire = false
  8189. if (autoFireType == "always") {
  8190. doAutoFire = true;
  8191. } else if (autoFireType == "whileAimbot" && didAimbot) {
  8192. doAutoFire = true;
  8193. } else if (autoFireType == "whileVisible" && isVisible) {
  8194. doAutoFire = true;
  8195. } else if (autoFireType == "whileVisAimbot" && isVisible && didAimbot) {
  8196. doAutoFire = true;
  8197. };
  8198. if (doAutoFire) {
  8199. if ((ammo[H.rounds] > 0) || (ammo.store > 0)) { //i fucking hate tweakpane. "errrm actually when a slider is 0 it becomes undefined" go fuck yourself.
  8200. ((accuracyPercentage >= (extract("autoFireAccuracy") || 0))) && ss.MYPLAYER.pullTrigger();
  8201. } else {
  8202. ss.MYPLAYER.melee();
  8203. };
  8204. };
  8205. };
  8206. //method by de_Neuublue
  8207. if (extract("enableAutomatic")) {
  8208. if (ss.MYPLAYER[H.weapon].constructor.originallySemi == null) {
  8209. ss.MYPLAYER[H.weapon].constructor.originallySemi = !ss.MYPLAYER[H.weapon].constructor.automatic;
  8210. };
  8211. ss.MYPLAYER[H.weapon].constructor.automatic = true;
  8212. } else if (ss.MYPLAYER[H.weapon].constructor.originallySemi) {
  8213. ss.MYPLAYER[H.weapon].constructor.originallySemi = null;
  8214. ss.MYPLAYER[H.weapon].constructor.automatic = false;
  8215. };
  8216.  
  8217. if (updateMenu) {
  8218. updateMenu = false; initMenu(false);
  8219. tp.mainPanel.hidden = extract("hideAtStartup");
  8220. };
  8221.  
  8222. //nobob
  8223. if (extract("bobModifierEnabled")) {
  8224. let modifier = extract("bobModifier") || 0;
  8225. if (!(extract("bobModifierWhenStill") && ss.CONTROLKEYS !== 0))
  8226. ss.MYPLAYER[H.actor].bobbleIntensity = modifier;
  8227. // log(ss.MYPLAYER[H.actor].bobbleIntensity, modifier);
  8228. };
  8229.  
  8230. let doRender = true;
  8231.  
  8232. if ((extract("renderDelay") > 10) && (Date.now() < (previousFrame + extract("renderDelay")))) { //because bots lmao
  8233. doRender = false;
  8234. } else {
  8235. previousFrame = Date.now();
  8236. };
  8237.  
  8238. framesPassed++;
  8239.  
  8240. return (!doRender);
  8241. };
  8242. });
  8243. };
  8244.  
  8245. //start init thingamajigs
  8246. log("StateFarm: startUp()", attemptedInjection);
  8247. startUp();
  8248. log("StateFarm: after startUp()", attemptedInjection);
  8249.  
  8250. if (typeof GM_info !== 'undefined' && GM_info?.scriptHandler == "Tampermonkey") {
  8251. let count = GM_getValue("StateFarm_TampermonkeyWarnings") || 0;
  8252. count++;
  8253. if (count <= 3) {
  8254. let userConfirmed = confirm("StateFarm Client: Tampermonkey detected! StateFarm Client does not support this manager, use Violentmonkey instead. Press OK to be redirected to the Violentmonkey website. You can continue to use Tampermonkey, but expect unreliable results. For more information, visit our Discord server: "+discordURL);
  8255. if (userConfirmed) {
  8256. GM_openInTab(violentmonkeyURL, { active: true });
  8257. };
  8258. alert(`This alert will show three times in total. Please install Violentmonkey before reporting issues. ${3-count} more warnings.`);
  8259. };
  8260. GM_setValue("StateFarm_TampermonkeyWarnings", count); //continue counting for the lulz
  8261. };
  8262.  
  8263. setTimeout(() => {
  8264. if (unsafeWindow.location.pathname == "/" && !attemptedInjection) {
  8265. log("Injection didn't work for whatever reason, let's try again.");
  8266. reloadPage();
  8267. };
  8268. }, 30000);
  8269. })();
  8270. // log("StateFarm: after function", attemptedInjection);

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址