Cookie Clicker Mod Menu

Mod menu for Cookie Clicker

  1. // ==UserScript==
  2. // @name Cookie Clicker Mod Menu
  3. // @namespace https://github.com/qba210/cookie-clicker-mod-menu
  4. // @version 1.1
  5. // @description Mod menu for Cookie Clicker
  6. // @author qba210
  7. // @license MIT
  8. // @match *://orteil.dashnet.org/cookieclicker/*
  9. // @icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAqCAMAAAD26OlUAAAAolBMVEU0DAIKBQhqIg8A3v9DLSpuV1URLT9FARDDkzh+ernp1nP///+QgHeMAACpdiE0FRfBqIyov5EAhZXwFwC7XzaDQBTUwbxBTn1NKiPg4OAXPiCaMxaauDTdtGaVXjnKEwr/fgAAWZ5Sb03Fh1D/ieeWABzUQQ3/zC86gSvtEG/cQWKgANXMs6z67bnhwJalQh9g/1B+WkBJDQPKa0G9jnkAAADDKDlIAAAANnRSTlP//////////////////////////////////////////////////////////////////////wChj04xAAAACXBIWXMAAAsTAAALEwEAmpwYAAAGx2lUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNi4wLWMwMDIgNzkuMTY0NDg4LCAyMDIwLzA3LzEwLTIyOjA2OjUzICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIiB4bWxuczpwaG90b3Nob3A9Imh0dHA6Ly9ucy5hZG9iZS5jb20vcGhvdG9zaG9wLzEuMC8iIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIDIxLjAgKFdpbmRvd3MpIiB4bXA6Q3JlYXRlRGF0ZT0iMjAyMi0wOC0wN1QyMDo1NToxNCswMjowMCIgeG1wOk1vZGlmeURhdGU9IjIwMjItMDgtMDdUMjE6MDA6MjgrMDI6MDAiIHhtcDpNZXRhZGF0YURhdGU9IjIwMjItMDgtMDdUMjE6MDA6MjgrMDI6MDAiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6OWRkM2RiMTEtNWViZS01MzQzLWEyOGEtYzAwZDE2MDY3MWFhIiB4bXBNTTpEb2N1bWVudElEPSJhZG9iZTpkb2NpZDpwaG90b3Nob3A6MGUxNzYxNGUtOTkxNy1hMzRmLTllYWYtYzM4ZTdlYjY2MWIwIiB4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ9InhtcC5kaWQ6RjVDMTE2MERDQ0NDMTFFQzlBOThCQzEzREI1QkEzRjUiIGRjOmZvcm1hdD0iaW1hZ2UvcG5nIiBwaG90b3Nob3A6Q29sb3JNb2RlPSIyIiBwaG90b3Nob3A6SUNDUHJvZmlsZT0ic1JHQiBJRUM2MTk2Ni0yLjEiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpGNUMxMTYwQUNDQ0MxMUVDOUE5OEJDMTNEQjVCQTNGNSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpGNUMxMTYwQkNDQ0MxMUVDOUE5OEJDMTNEQjVCQTNGNSIvPiA8eG1wTU06SGlzdG9yeT4gPHJkZjpTZXE+IDxyZGY6bGkgc3RFdnQ6YWN0aW9uPSJzYXZlZCIgc3RFdnQ6aW5zdGFuY2VJRD0ieG1wLmlpZDpiNWRkNTg4NS1jNjA4LWEwNGEtYTYyMi04OTM4NjNlYjcwNGEiIHN0RXZ0OndoZW49IjIwMjItMDgtMDdUMjE6MDA6MjgrMDI6MDAiIHN0RXZ0OnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCAyMi4wIChXaW5kb3dzKSIgc3RFdnQ6Y2hhbmdlZD0iLyIvPiA8cmRmOmxpIHN0RXZ0OmFjdGlvbj0ic2F2ZWQiIHN0RXZ0Omluc3RhbmNlSUQ9InhtcC5paWQ6OWRkM2RiMTEtNWViZS01MzQzLWEyOGEtYzAwZDE2MDY3MWFhIiBzdEV2dDp3aGVuPSIyMDIyLTA4LTA3VDIxOjAwOjI4KzAyOjAwIiBzdEV2dDpzb2Z0d2FyZUFnZW50PSJBZG9iZSBQaG90b3Nob3AgMjIuMCAoV2luZG93cykiIHN0RXZ0OmNoYW5nZWQ9Ii8iLz4gPC9yZGY6U2VxPiA8L3htcE1NOkhpc3Rvcnk+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+nkWItQAAANxJREFUOMut1MEOgjAQBFDaY016bbJfsMde+P9fk3GyLg2obHESPcgjw2LbZd0isv7MEoKq/4Qiqr2rWn16Zxbuq3EZN5aCG0ccg6wFqlWVEAGOQ6+1UtWUVB9b9vQ6dAZEiG9Cp3HIy3glPgw4fotDGwSo95TKEJbPQlB8PPegDTPCWu9AG8AWBZf0DGyNfyGTEgAfRKS1OLRFa7U+ksjJ6rkIUT4uNnmFxXHotFY8hCVnMGyXOCRtDdBKWcvNPAN5pOSMSiKOwQ09B4/Hnh+K8/CYD9U34Mnr+QafGozjyeDrtEIAAAAASUVORK5CYII=
  10. // @grant none
  11. // ==/UserScript==
  12.  
  13. (async function() {
  14. 'use strict';
  15.  
  16. class Logger {
  17. /**
  18. *
  19. * @param {object} msg
  20. */
  21. static LogInfo(msg) {
  22. console.log("\n[Mod Menu] ", msg);
  23. }
  24.  
  25. /**
  26. *
  27. * @param {object} msg
  28. */
  29. static LogDebug(msg) {
  30. Logger.LogInfo(msg);
  31. }
  32. }
  33.  
  34. Logger.LogInfo("Waiting for Game...")
  35. let gamePromise = new Promise((res) => {var int = setInterval(() => {if (Game.Achievements) {clearInterval(int); res(Game);}}, 10)});
  36. await gamePromise;
  37. Logger.LogInfo("Game loaded!")
  38.  
  39.  
  40. let cheatMenu = document.createElement("div");
  41.  
  42. const translations = [
  43. {
  44. lang: "pl",
  45. langName: "Polski",
  46. hacks: {
  47. "silent-mode": {
  48. name: "Tryb cichy",
  49. desc: "Unika wykrycia przez grę hackowania (np. osiągnięcie 'Oszukane ciastka smakują najgorzej')"
  50. },
  51. "cookie-spam": {
  52. name: "Spamowanie ciastka",
  53. desc: "Po przyciśnięciu ciastka samoczynnie zaczyna na nie klikać (kończy po odciśnięciu)"
  54. },
  55. "autoclicker": {
  56. name: "Autokliker",
  57. desc: "Auttomatycznie klika w ciastko"
  58. },
  59. "dev-tools": {
  60. name: "Menu dewelop.",
  61. desc: "Otwiera menu deweloperskie"
  62. },
  63. "set-cookies": {
  64. name: "Ustaw ilość ciastek",
  65. desc: "Pozwala na zmianę ilości ciastek"
  66. },
  67. "delete-save": {
  68. name: "Usuń zapis"
  69. },
  70. "earn-achievement": {
  71. name: "Odblokuj osiągnięcie",
  72. desc: "Wybierz osiągnięcie z listy i kliknij przycisk aby je zdobyć!"
  73. },
  74. "revoke-achievement": {
  75. name: "Usuń osiągnięcie",
  76. desc: "Wybierz osiągnięcie z listy i kliknij przycisk aby je usunąć!"
  77. },
  78. "finish-game": {
  79. name: "Ukończ grę",
  80. desc: "Kończy grę i odblokowywuje wszystko"
  81. }
  82. },
  83. strings: {
  84. "dev-tools-confirm": "Jesteś pewien? Tryb cichy nie uchroni Cię od hacków które włączycz w menu deweloperskim.",
  85. "changes-as-you-type": "Wartość zmienia się jak piszesz",
  86. "confirm-save-delete": "Jesteś pewien?",
  87. "set-object-amount": "Ustaw ilość %s"
  88. }
  89. },
  90. {
  91. lang: "en",
  92. langName: "English",
  93. hacks: {
  94. "silent-mode": {
  95. name: "Silent mode",
  96. desc: "Avoids detecting hacks by game (ex.: achievement 'Cheated cookies tastes awful')"
  97. },
  98. "cookie-spam": {
  99. name: "Cookie spam",
  100. desc: "After holding the cookie, starts to click it automatically (ends after releasing)"
  101. },
  102. "autoclicker": {
  103. name: "Autoclicker",
  104. desc: "Automatically clicks cookie"
  105. },
  106. "dev-tools": {
  107. name: "Dev menu",
  108. desc: "Opens developer menu"
  109. },
  110. "set-cookies": {
  111. name: "Set cookie count",
  112. desc: "Allows you to change cookie count"
  113. },
  114. "delete-save": {
  115. name: "Delete save"
  116. },
  117. "earn-achievement": {
  118. name: "Earn achievement",
  119. desc: "Select achievement from list, then click button to get it!"
  120. },
  121. "revoke-achievement": {
  122. name: "Remove achievement",
  123. desc: "Select achievement from list, then click button to remove it!"
  124. },
  125. "finish-game": {
  126. name: "Finish game",
  127. desc: "Finishes game and unlocks everything"
  128. }
  129. },
  130. strings: {
  131. "dev-tools-confirm": "Are you sure? Silent mode cannot prevent detecting cheats you activate in developer menu.",
  132. "changes-as-you-type": "Changes as you type",
  133. "confirm-save-delete": "Are you sure?",
  134. "set-object-amount": "Set %s amount"
  135. }
  136. }
  137. ]
  138.  
  139. let lang = translations.find((lng) => lng.lang === (localStorage.getItem("cheats_lang") ?? "en"));
  140.  
  141. document.body.append(cheatMenu);
  142.  
  143. cheatMenu.outerHTML = `
  144. <div id="hack-menu" style="left: 50%; top: 35px;">
  145. <div id="hack-popup">Hack</div>
  146. <br>
  147. <div id="hacks" style="display: none;">
  148. <div class="hack-list" id="main-hacks">
  149. <select id="hack-lang-select"></select>
  150. <div class="hack hack-bool" id="hack-silent-mode"></div>
  151. <div class="hack hack-bool" id="hack-cookie-spam"></div>
  152. <div class="hack hack-bool" id="hack-autoclicker"></div>
  153. <div class="hack hack-btn" id="hack-dev-tools"></div>
  154. <div class="hack hack-btn" id="hack-set-cookies"></div>
  155. <div class="hack hack-btn" id="hack-delete-save"></div>
  156. <div class="hack hack-btn" id="hack-finish-game"></div>
  157. <div class="hack hack-select" id="hack-earn-achievement"></div>
  158. <div class="hack hack-select" id="hack-revoke-achievement"></div>
  159. </div>
  160. <div class="hack-list" id="objects-hacks">
  161. </div>
  162. </div>
  163. </div>
  164. <div id="hack-tooltip" style="opacity: 0;left:0;top:0"></div>
  165. <div id="hack-alert-input" style="opacity: 0;display: none;">
  166. <div id="hack-alert-input-popup">
  167. <h1 id="hack-alert-input-popup-title"></h1>
  168. <div id="hack-alert-input-popup-desc"></div><br>
  169. <input type="number" id="hack-alert-input-popup-input"/><br>
  170. <input type="button" id="hack-alert-input-popup-ok" value="OK"/>
  171. </div>
  172. </div>
  173. `;
  174. let styles = document.createElement("style");
  175. styles.innerText = `
  176. #hack-menu, #hack-tooltip {
  177. z-index: 9000000000;
  178. position: absolute;
  179. box-sizing: border-box;
  180. }
  181. #hack-menu, #hack-menu *:not(#hacks){
  182. box-sizing: border-box;
  183. }
  184. #hack-menu {
  185. display: flex;
  186. flex-direction: column;
  187. align-items: center;
  188. width: clamp(150px, 225px, 25vw);
  189. }
  190. #hacks {
  191. backdrop-filter: blur(5px);
  192. display: flex;
  193. flex-direction: row;
  194. gap: 10px;
  195. padding: 10px;
  196. background-color: rgba(0, 0, 0, .5);
  197. border-radius: 13px;
  198. width: 200%;
  199. box-sizing: content-box;
  200. }
  201.  
  202. .hack-list {
  203. display: flex;
  204. flex-direction: column;
  205. gap: 10px;
  206. padding: 10px;
  207. width: 100%;
  208. box-sizing: content-box;
  209. overflow-y: auto;
  210. overflow-x: hidden;
  211. max-height: 70vh;
  212. }
  213. .hack-list::-webkit-scrollbar-thumb {
  214. border: 4px solid rgb(10, 87, 242);
  215. background-color: rgba(10, 87, 242, .2);
  216. border-radius: 5px;
  217. backdrop-filter: blur(3px);
  218. box-shadow: none;
  219. transition: background-color .3s linear, border .3s linear
  220. }
  221. .hack-list::-webkit-scrollbar-thumb:hover {
  222. border: 4px solid #00a2ff;
  223. background-color: rgba(0, 162, 255, .4);
  224. }
  225. .hack-list::-webkit-scrollbar-track {
  226. border: 4px solid black;
  227. background-color: transparent;
  228. border-radius: 5px;
  229. }
  230.  
  231. #hack-popup, .hack {
  232. padding: 10px;
  233. font-size: 20px;
  234. background-color: #00a2ff;
  235. border: 7px solid black;
  236. text-align: center;
  237. width: 100%;
  238. }
  239. .hack {
  240. cursor: pointer;
  241. }
  242. .hack:active {
  243. filter: brightness(0.85);
  244. }
  245.  
  246. .hack-bool {
  247. transition: background-color .3s ease-in;
  248. background-color: red;
  249. }
  250. .hack-bool[on] {
  251. background-color: green;
  252. }
  253. #hack-tooltip {
  254. position: absolute;
  255. backdrop-filter: blur(7px);
  256. filter: blur(0px);
  257. transition: all .3s ease-out, left 0s ease, top 0s ease;
  258. background-color: rgba(0, 0, 0, .5);
  259. color: white;
  260. transform: translate(15px, 9.5px);
  261. width: 200px;
  262. padding: 10px;
  263. border-radius: 13px;
  264. pointer-events: none;
  265. }
  266. #hack-lang-select {
  267. z-index: 90000000001;
  268. background-color: black;
  269. color: white;
  270. border-color: white;
  271. width: 100%
  272. }
  273. #hack-lang-select > option {
  274. color: white;
  275. }
  276.  
  277. #hack-popup {
  278. transition: opacity .35s ease-out;
  279. }
  280. #hack-popup:hover, #hack-popup[open] {
  281. opacity: 1;
  282. }
  283. #hack-popup:not(:hover):not([open]) {
  284. opacity: .8;
  285. }
  286.  
  287. #hack-alert-input {
  288. z-index: 9500000000;
  289. background-color: rgba(0, 0, 0, .5);
  290. transition: opacity .3s ease-out;
  291. position: absolute;
  292. left: 0;
  293. top: 0;
  294. right: 0;
  295. bottom: 0;
  296. backdrop-filter: blur(5px);
  297. }
  298. #hack-alert-input-popup {
  299. position: absolute;
  300. left: 50%;
  301. top: 50%;
  302. transform: translate(-50%, -50%);
  303. width: 60%;
  304. height: 50%;
  305. background-color: black;
  306. color: white;
  307. display: flex;
  308. flex-direction: column;
  309. justify-content: center;
  310. font-family: verdana;
  311. text-align: center;
  312. padding: 20px;
  313. border: 3px solid white;
  314. border-radius: 10px;
  315. }
  316. #hack-alert-input-popup-title {
  317. font-size: 2.5em;
  318. }
  319. #hack-alert-input-popup-desc {
  320. font-size: 1.5em;
  321. }
  322. #hack-alert-input-popup-ok {
  323. background-color: #00a2ff;
  324. border: 4px solid white;
  325. text-align: center;
  326. width: 100%;
  327. height: 50px;
  328. font-weight: bold;
  329. cursor: pointer;
  330. }
  331. #hack-alert-input-popup-input {
  332. background-color: black;
  333. color: white;
  334. border-color: white;
  335. }
  336. .select-in-hack {
  337. width: 100%;
  338. border-color: black;
  339. color: white;
  340. background-color: black;
  341. }
  342.  
  343. `;
  344. document.head.append(styles);
  345.  
  346. if (!localStorage.getItem("cheats_lang")) {
  347. localStorage.setItem("cheats_lang", "en");
  348. }
  349. let $hackmenu = document.getElementById("hack-menu");
  350. let $hacks = document.getElementById("hacks");
  351. let $popup = document.getElementById("hack-popup");
  352. let $tooltip = document.getElementById("hack-tooltip");
  353. /**@type {HTMLSelectElement} */
  354. let $langselect = document.getElementById("hack-lang-select");
  355. let $hack_earnachievement = document.getElementById("hack-earn-achievement")
  356. let $hack_revokeachievement = document.getElementById("hack-revoke-achievement")
  357.  
  358. let $inputalert = {
  359. alert: document.getElementById("hack-alert-input"),
  360. popup: document.getElementById("hack-alert-input-popup"),
  361. title: document.getElementById("hack-alert-input-popup-title"),
  362. desc: document.getElementById("hack-alert-input-popup-desc"),
  363. input: document.getElementById("hack-alert-input-popup-input"),
  364. ok: document.getElementById("hack-alert-input-popup-ok")
  365. }
  366.  
  367. let $objecthacks = document.getElementById("objects-hacks")
  368.  
  369. let $cookie = document.getElementById("bigCookie");
  370.  
  371. dragElement($hackmenu, $popup);
  372.  
  373. //boolean hack manager
  374. $hacks.querySelectorAll(".hack-bool").forEach(node => {
  375. node.addEventListener("click", (e) => {
  376. if (node.hasAttribute("on")) {
  377. node.removeAttribute("on");
  378. } else {
  379. node.setAttribute("on", "");
  380. }
  381. })
  382. })
  383.  
  384. //populate object hacks
  385. gamePromise.then(() => {
  386. Object.entries(Game.Objects).forEach(entry => {
  387. let [key, value] = entry;
  388. let hack = document.createElement("div");
  389. hack.className = "hack hack-btn";
  390. hack.id = `hack-object-amount-${value.bsingle}`;
  391. hack.setAttribute("lang-string", "set-object-amount");
  392. hack.setAttribute("supply-val", value.dname);
  393. hack.setAttribute("key", key);
  394.  
  395. hack.onclick = (e) => {
  396. showInputAlert(hack.innerText, lang.strings["changes-as-you-type"], "number", value.amount, (val) => {
  397. value.getFree(+val - value.amount)
  398. value.free = 0;
  399. })
  400. }
  401.  
  402. $objecthacks.append(hack);
  403. })
  404. // update language after
  405. reloadLangs();
  406. })
  407.  
  408. reloadLangs();
  409.  
  410. //class loop
  411. $hackmenu.querySelectorAll(".hack").forEach(_node => {
  412. /**@type {HTMLElement} */
  413. let node = _node;
  414.  
  415. //tooltip
  416. node.addEventListener("mousemove", function (e) {
  417. if (e.target === this) {
  418. showTooltip(node.id, e.pageX, e.pageY);
  419. } else if (e.target instanceof HTMLSelectElement) {
  420. if (e.target.value && e.target.value !== "") {
  421. showTooltip(Array.from(this.querySelectorAll("option")).find(opt => opt.value === e.target.value).innerHTML, e.pageX, e.pageY, false);
  422. }
  423. } else {
  424. hideTooltip();
  425. }
  426. })
  427. node.addEventListener("mouseleave", (e) => {
  428. hideTooltip();
  429. })
  430. })
  431.  
  432. //menu hide/show
  433. $popup.addEventListener("click", (e) => {
  434. if ($hacks.style.display === "none") {
  435. $hacks.style.display = "";
  436. $popup.setAttribute("open", "");
  437. } else {
  438. $hacks.style.display = "none";
  439. $popup.removeAttribute("open");
  440. }
  441. })
  442.  
  443. //add event listener to language select
  444. $langselect.addEventListener("change", (e) => {
  445. setLang($langselect.value);
  446. })
  447.  
  448. //select language
  449. translations.forEach((translation) => {
  450. let option = document.createElement("option");
  451. option.value = translation.lang;
  452. option.innerText = translation.langName;
  453. $langselect.append(option);
  454. Logger.LogInfo(`Loaded language ${translation.lang}: ${translation.langName}`);
  455. })
  456.  
  457. //set current language
  458. $langselect.value = lang.lang;
  459.  
  460. // Debug menu hack
  461. document.getElementById("hack-dev-tools").addEventListener("click", (e) => {
  462. if (isSilentMode()) {
  463. if (confirm(lang.strings["dev-tools-confirm"])) {
  464. Game.OpenSesame();
  465. }
  466. } else {
  467. Game.OpenSesame();
  468. }
  469. })
  470.  
  471. // Cookie spam hack
  472. let cookieSpamWorker;
  473.  
  474. $cookie.addEventListener("mousedown", (e) =>
  475. {
  476. if (document.getElementById("hack-cookie-spam").hasAttribute("on"))
  477. cookieSpamWorker = setInterval(() => $cookie.dispatchEvent(new Event("click")));
  478. })
  479.  
  480. $cookie.addEventListener("mouseup", (e) => {
  481. clearInterval(cookieSpamWorker);
  482. })
  483.  
  484. // Autoclicker hack
  485. let autoclickerWorker;
  486.  
  487. document.getElementById("hack-autoclicker").addEventListener("click", (e) =>
  488. {
  489. let cookrect = $cookie.getBoundingClientRect();
  490. if (document.getElementById("hack-autoclicker").hasAttribute("on"))
  491. autoclickerWorker = setInterval(() => $cookie.dispatchEvent(new Event("click")), 0);
  492. else
  493. clearInterval(autoclickerWorker);
  494. })
  495.  
  496. // Set cookies hack
  497. document.getElementById("hack-set-cookies").addEventListener("click", (e) => {
  498. //show input to user
  499. showInputAlert(lang.hacks["set-cookies"].name, lang.strings["changes-as-you-type"], "number", Game.cookies.toString(), (val) => {
  500. //earn mode decided by silent mode
  501. if (isSilentMode()) {
  502. Game.Earn(-Game.cookies + +val);
  503. } else {
  504. Game.cookies = +val;
  505. }
  506. })
  507. });
  508.  
  509. // Delete save hack
  510. document.getElementById("hack-delete-save").addEventListener("click", (e) => {
  511. //ask user to confirm
  512. if (confirm(lang.strings["confirm-save-delete"])) {
  513. //delete save from localstorage
  514. localStorage.removeItem("CookieClickerGame");
  515. //after this reload to confirm
  516. window.location.reload();
  517. }
  518. });
  519. //earn achievement hack
  520. $hack_earnachievement.addEventListener("click", function (e) {
  521. //if clicked on select dont gain achevement
  522. if (e.target !== this) return;
  523. //gain selected achievement
  524. Game.Win($hack_earnachievement.querySelector("select").value)
  525. })
  526. //revoke achievement hack (simillar to earn)
  527. $hack_revokeachievement.addEventListener("click", function (e) {
  528. if (e.target !== this) return;
  529. Game.RemoveAchiev($hack_revokeachievement.querySelector("select").value)
  530. })
  531.  
  532. gamePromise.then(() => {
  533. document.getElementById("hack-finish-game").addEventListener("click", (e) => {
  534. Game.RuinTheFun(true);
  535. })
  536. })
  537.  
  538. /**
  539. * @param {string} lang
  540. */
  541.  
  542. function setLang(lang) {
  543. localStorage.setItem("cheats_lang", lang);
  544. reloadLangs();
  545. }
  546.  
  547. function reloadLangs() {
  548. lang = translations.find((lng) => lng.lang === (localStorage.getItem("cheats_lang") ?? "en"))
  549.  
  550. //for every hack
  551. $hackmenu.querySelectorAll(".hack").forEach(node => {
  552. //add value
  553. /**@type {string} */
  554. let transval = (lang.hacks[node.id.replace("hack-", "")] ?? {name: node.id} ).name;
  555. if (node.hasAttribute("lang-string")) {
  556. transval = lang.strings[node.getAttribute("lang-string")];
  557. }
  558. if (node.hasAttribute("supply-val")) {
  559. transval = transval.replace("%s", node.getAttribute("supply-val"));
  560. }
  561. node.innerText = (transval ?? node.id ) ?? node.id
  562. })
  563.  
  564. //support for select class
  565. $hackmenu.querySelectorAll(".hack-select").forEach(node => {
  566. let select = document.createElement("select");
  567. select.className = "select-in-hack";
  568. node.append(select);
  569. })
  570.  
  571. // Earn achevement hack
  572.  
  573. //when Game is avaible do
  574. gamePromise.then(() => {
  575. // foreach achevement ingame
  576. Object.entries(Game.Achievements).forEach((entry) => {
  577. const [key, value] = entry;
  578. //create option with achievement
  579. let option = document.createElement("option");
  580. option.value = key;
  581. option.innerHTML = value.dname;
  582. //add it to hack
  583. $hack_earnachievement.querySelector("select").append(option);
  584. $hack_revokeachievement.querySelector("select").append(option.cloneNode(true));
  585. });
  586. })
  587.  
  588. //set current language
  589. $langselect.value = lang.lang;
  590. }
  591.  
  592. function isSilentMode() {
  593. return document.getElementById("hack-silent-mode").hasAttribute("on");
  594. }
  595.  
  596.  
  597. /**
  598. *
  599. * @param {string} id
  600. * @param {number} x
  601. * @param {number} y
  602. */
  603. function showTooltip(id, x, y, translatable = true) {
  604. //show only if id have description
  605. if (translatable) {
  606. if (!lang.hacks[id.replace("hack-", "")]) return;
  607. if (!lang.hacks[id.replace("hack-", "")].desc) return;
  608. }
  609.  
  610. $tooltip.innerText = translatable ? lang.hacks[id.replace("hack-", "")].desc ?? "" : id;
  611. $tooltip.style.left = x.toString() + "px";
  612. $tooltip.style.top = y.toString() + "px";
  613. $tooltip.style.opacity = 1;
  614. }
  615.  
  616. function hideTooltip() {
  617. //$tooltip.innerText = ""; //its needed to be comented because transistion
  618. $tooltip.style.opacity = 0;
  619. }
  620.  
  621. /**
  622. * Shows input alert.
  623. *
  624. * @param {string} title
  625. * @param {string} desc
  626. * @param {string} type
  627. * @param {string} value
  628. * @param {(value: string) => void} setter
  629. */
  630.  
  631. function showInputAlert(title, desc, type, value, setter) {
  632. $inputalert.ok.onclick = () => {
  633. setTimeout(() => $inputalert.alert.style.display = "none", 301);
  634. setter($inputalert.input.value);
  635. $inputalert.alert.style.opacity = "0";
  636. }
  637.  
  638. $inputalert.title.innerText = title;
  639. $inputalert.desc.innerText = desc;
  640.  
  641. $inputalert.input.type = type;
  642. $inputalert.input.value = value.toString();
  643. $inputalert.input.onchange = (e) => setter($inputalert.input.value);
  644.  
  645. $inputalert.alert.style.display = "";
  646. $inputalert.alert.style.opacity = "1";
  647. }
  648.  
  649. /**
  650. *
  651. * @param {HTMLElement} elmnt element to drag
  652. * @param {HTMLElement?} dragger element dragging elmnt
  653. */
  654. function dragElement(elmnt, dragger) {
  655. var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
  656. if (document.getElementById(elmnt.id + "header") || dragger) {
  657. // if present, the header is where you move the DIV from:
  658. (document.getElementById(elmnt.id + "header") ?? dragger).onmousedown = dragMouseDown;
  659. } else {
  660. // otherwise, move the DIV from anywhere inside the DIV:
  661. elmnt.onmousedown = dragMouseDown;
  662. }
  663. function dragMouseDown(e) {
  664. e = e || window.event;
  665. e.preventDefault();
  666. // get the mouse cursor position at startup:
  667. pos3 = e.clientX;
  668. pos4 = e.clientY;
  669. document.onmouseup = closeDragElement;
  670. // call a function whenever the cursor moves:
  671. document.onmousemove = elementDrag;
  672. if (document.getElementById(elmnt.id + "header") || dragger) {
  673. (document.getElementById(elmnt.id + "header") ?? dragger).setAttribute("dragging", "");
  674. }else {
  675. elmnt.setAttribute("dragging", "");
  676. }
  677. }
  678. function elementDrag(e) {
  679. e = e || window.event;
  680. e.preventDefault();
  681. // calculate the new cursor position:
  682. pos1 = pos3 - e.clientX;
  683. pos2 = pos4 - e.clientY;
  684. pos3 = e.clientX;
  685. pos4 = e.clientY;
  686. // set the element's new position:
  687. elmnt.style.top = (elmnt.offsetTop - pos2) + "px";
  688. elmnt.style.left = (elmnt.offsetLeft - pos1) + "px";
  689. }
  690. function closeDragElement() {
  691. // stop moving when mouse button is released:
  692. document.onmouseup = null;
  693. document.onmousemove = null;
  694.  
  695. if (document.getElementById(elmnt.id + "header") || dragger) {
  696. (document.getElementById(elmnt.id + "header") ?? dragger).removeAttribute("dragging");
  697. }else {
  698. elmnt.removeAttribute("dragging");
  699. }
  700. }
  701. }
  702. })();