moPsEk - CSGO MTSL 2 MOD MENU

moPsEk for CSGO MTSL Version 2

  1. // ==UserScript==
  2. // @name moPsEk - CSGO MTSL 2 MOD MENU
  3. // @namespace https://github.com/mopsfl/moPsEk
  4. // @description moPsEk for CSGO MTSL Version 2
  5. // @author mopsfl
  6. // @version 0.0.9
  7. // @license MIT
  8. // @match *://csgo.mtsl.dk/
  9. // @match *://csgo.mtsl.dk/esr/
  10. // @icon https://github.com/mopsfl/moPsEk/raw/main/assets/bulldog--v2.png%202x.png
  11. // @run-at document-start
  12. // @grant GM_setValue
  13. // @grant GM_getValue
  14. // @grant GM_setClipboard
  15. // @grant GM_download
  16. // @grant window.onurlchange
  17. // ==/UserScript==
  18.  
  19. (function () {
  20. 'use strict';
  21.  
  22. let user = {
  23. money: 240,
  24. tickets: 0,
  25. tokens: 0,
  26. xp: 0,
  27. stats: { creation: new Date().getTime() },
  28. inventory: [],
  29. upgrades: {},
  30. achievements: {},
  31. achievements_collected: {},
  32. luckyWheelWins: [],
  33. upgrades: {
  34. maxClick: null,
  35. minClick: null,
  36. passiveIncome: null,
  37. offlineIncome: null,
  38. offlineBank: null,
  39. missionGeneration: null
  40. },
  41. },
  42. temp_inventory = []
  43.  
  44. //DATA MANAGMENT
  45. let S = { "=": "0", "!": "1", "?": "2", $: "3", "%": "4", "&": "5", "/": "6", "\\": "7", "-": "8", "+": "9" },
  46. w = Object.keys(S).join(""),
  47. v = { 0: "=", 1: "!", 2: "?", 3: "$", 4: "%", 5: "&", 6: "/", 7: "\\", 8: "-", 9: "+" },
  48. achievements = {}
  49.  
  50. function getUser() { return JSON.parse(y(localStorage.localsave)) }
  51.  
  52. function f(e) { return decodeURIComponent(e.split("").map((function (e) { return "%" + ("00" + e.charCodeAt(0).toString(16)).slice(-2) })).join("")) }
  53.  
  54. function y(e) {
  55. let t = [],
  56. o = "";
  57. for (let n = 0; n < e.length; n++) {
  58. let i = e[n];
  59. i.match(/[A-Z]/) || w.includes(i) ? (o += w.includes(i) ? S[i] : i.toLowerCase(), t.push(parseInt(o, 36)), o = "") : o += i
  60. }
  61. let n, i = {},
  62. r = String.fromCharCode(t[0]),
  63. s = r,
  64. a = [r],
  65. m = 256;
  66. for (let e = 1; e < t.length; e++) {
  67. let o = t[e];
  68. n = o < 256 ? String.fromCharCode(t[e]) : i[o] ? i[o] : s + r, a.push(n), r = n[0], i[m] = s + r, m++, s = n
  69. }
  70. return f(a.join(""))
  71. }
  72.  
  73. function m(e) { return encodeURIComponent(e).replace(/%([0-9A-F]{2})/g, (function (e, t) { return String.fromCharCode("0x" + t) })) }
  74.  
  75. function h(e) {
  76. let t, o = {},
  77. n = ((e = m(e)) + "").split(""),
  78. i = [],
  79. r = n[0],
  80. s = 256;
  81. for (let e = 1; e < n.length; e++) t = n[e], null != o[r + t] ? r += t : (i.push(r.length > 1 ? o[r] : r.charCodeAt(0)), o[r + t] = s, s++, r = t);
  82. return i.push(r.length > 1 ? o[r] : r.charCodeAt(0)), i.map((e => { let t = e.toString(36); return t.substring(0, t.length - 1) + (t[t.length - 1].match(/[0-9]/) ? v[t[t.length - 1]] : t[t.length - 1].toUpperCase()) })).join("")
  83. }
  84.  
  85. function c_mmid(e) { for (var t = "", o = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", n = o.length, i = 0; i < e; i++) t += o.charAt(Math.floor(Math.random() * n)); return t }
  86. let ic = 0,
  87. liit = 0;
  88. var itemNames = ["bravo", "breakout", "brokenfang", "cs20", "csgoweapon", "csgoweapon2", "csgoweapon3", "falchion", "fracture", "gamma", "horizon", "huntsman", "phoenix", "prisma", "prisma2", "spectrum", "spectrum2", "winteroffensive", "snakebite", "gamma2", "clutch", "chroma", "chroma2", "chroma3", "shadow", "collections/assault", "collections/aztec", "collections/dust", "collections/inferno", "collections/militia", "collections/nuke", "collections/office", "collections/vertigo", "vanguard", "revolver", "wildfire", "glove", "hydra", "dangerzone", "shatteredweb", "collections/risingsun", "collections/stmarc", "collections/overpass", "collections/norse", "collections/mirage", "collections/cobblestone", "collections/havoc", "collections/godsandmonsters", "collections/alpha", "collections/ancient", "collections/baggage", "collections/bank", "collections/cache", "collections/canals", "collections/chopshop", "collections/control", "collections/dust2", "collections/dust22021", "collections/inferno2018", "collections/italy", "collections/lake", "collections/mirage2021", "collections/nuke2018", "collections/safehouse", "collections/train", "collections/train2021", "collections/vertigo2021", "riptide", "doppler-phases/phases", "esports2013", "esports2013winter", "esports2014summer", "dreamsandnightmares"];
  89.  
  90. function uuidv4() { return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, (e => (e ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> e / 4).toString(16))) }
  91. let loadedAchievements = 0;
  92.  
  93. //FUNCTIONS
  94. function getSaveDataString() {
  95. const a = h(JSON.stringify(user));
  96. return a;
  97. }
  98.  
  99. function save(r) {
  100. localStorage['moPsEk_' + localStorage._moPsEk_uuid] = getSaveDataString();
  101. localStorage['moPsEk_' + localStorage._moPsEk_uuid + "_tempInv"] = JSON.stringify(temp_inventory);
  102. if (r) return location.reload();
  103. }
  104.  
  105. function log(message, color) {
  106. console.info(`%c${message}`, `background-color:black;padding:5px;border-left:solid 4px ${color};color:white`);
  107. }
  108.  
  109. function loadAchievements() {
  110. fetch("https://raw.githubusercontent.com/mopsfl/moPsEk/main/games/csgo.mtsl.dk/achievements.json").then(response => response.json())
  111. .then(data => {
  112. achievements = data;
  113. log(`Fetched ${Object.keys(achievements).length} achievements.`, "green");
  114. }).catch(error => {
  115. log(error);
  116. nf("Unable to load achievements.", "red")
  117. })
  118. }
  119.  
  120. function dlFile(e, t, n) {
  121. if (!(e || t || n)) return log('Could not create file. (Missing attr)', 'red');
  122. var d = document.createElement('a');
  123. d.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(n)), d.setAttribute('download', `${e}.${t}`), d.style.display = 'none', document.body.appendChild(d), d.click(), document.body.removeChild(d);
  124. }
  125.  
  126. function byteToSize(e) {
  127. var t = e;
  128. return t < 1024 ? t + 'B' : t < 1048576 ? (t / 1024).toFixed(2) + 'KB' : t < 1073741824 ? (t / 1024 * 1024).toFixed(2) + 'MB' : t < 1099511627776 ? (t / 1024 * 1024 * 1024).toFixed(2) + 'GB' : (t / 1024 * 1024 * 1024 * 1024).toFixed(2) + 'TB';
  129. }
  130.  
  131. function wipeData() {
  132. localStorage.clear()
  133. return save(true)
  134. }
  135.  
  136. function nf(msg, t, c) {
  137. if (msg == null) return;
  138. let notif = document.createElement("div")
  139. let notifs = document.querySelector(".notifications")
  140. if (!(notif || notifs)) return log("Unable to create notification", "red")
  141. notifs.classList.remove("hide")
  142.  
  143. notif.classList.add("notification")
  144. notif.innerHTML = `<div class="notification-message"><span style="${c ? 'color:' + c || 'inherit' : ''}">${!t ? "moPsEk: " : ""}${msg}</span></div><div class="notification-close"></div>`
  145.  
  146. notif.querySelector(".notification-close").onclick = () => { notif.remove() }
  147.  
  148. notifs.appendChild(notif)
  149. }
  150.  
  151. const injectCSS = css => {
  152. let el = document.createElement('style');
  153. el.type = 'text/css';
  154. el.innerText = css;
  155. document.head.appendChild(el);
  156. return el;
  157. };
  158.  
  159. function parseNumbers(string) {
  160. string = string.toString()
  161. return string.replace(/\D/gm, "")
  162. }
  163.  
  164. function setData(d) {
  165. if (!d || d == null) return;
  166.  
  167. const a = {
  168. money: d.money,
  169. xp: d.xp,
  170. tokens: d.tokens,
  171. tickets: d.tickets,
  172. achievements: d.achievements,
  173. upgrades: d.upgrades,
  174. },
  175. inv = JSON.parse(localStorage['moPsEk_' + localStorage._moPsEk_uuid + "_tempInv"])
  176.  
  177. temp_inventory = inv
  178. temp_inventory.forEach(item => {
  179. user.inventory.push(item)
  180. });
  181. localStorage['moPsEk_' + localStorage._moPsEk_uuid + "_tempInv"] = JSON.stringify([])
  182. temp_inventory = []
  183.  
  184. Object.keys(a.achievements).forEach(achievement => {
  185. user.achievements[achievement] = true
  186. })
  187.  
  188. Object.keys(a.upgrades).forEach(upgrade => {
  189. user.upgrades[upgrade] = a.upgrades[upgrade]
  190. })
  191.  
  192. Object.keys(a).forEach(k => {
  193. if (!['money', 'xp', 'tokens', 'tickets'].includes(k)) return;
  194. user[k] = a[k]
  195. log(`Set ${k} to ${a[k]}`, "green")
  196. })
  197.  
  198. console.log(user, a)
  199.  
  200. /*Object.keys(a).forEach(b => {
  201. console.log(`${b} : ${a[b]}`)
  202. if(!a[b]||a[b]==null) return;
  203. user[b]=a[b]
  204. localStorage.localsave = getSaveDataString(user)
  205. })*/
  206.  
  207. localStorage.localsave = getSaveDataString(user)
  208. }
  209.  
  210. //MAIN
  211.  
  212. user = getUser();
  213. loadAchievements()
  214.  
  215. function initMenu() {
  216. const btnClone = document.querySelector('#nav>button').cloneNode(true);
  217. const pageClone = document.querySelector('.page').cloneNode(true);
  218.  
  219. let n = document.createElement('span');
  220. n.classList.add('_tooltip')
  221. n.style = 'position: absolute;z-index: 9999;background-color: #333;border: 2px solid #555;min-width: 15px;padding: 4px;border-radius: 3px;max-width: 250px;word-break: break-word;font-family: "Roboto", sans-serif;'
  222. injectCSS(`
  223. .upgrade-mph:hover{transform:scale(1)}
  224. `)
  225. document.onmousemove = t => {
  226. n.style.left = t.clientX - n.offsetWidth + 'px'
  227. n.style.top = t.clientY - n.offsetHeight + 'px'
  228. }
  229.  
  230. document.querySelector('#nav').style.overflow = "scroll"
  231. document.querySelector('#nav').style.scrollbarWidth = "none"
  232.  
  233. pageClone.classList.add('mm');
  234. pageClone.innerHTML = `
  235. <h1><img src="https://github.com/mopsfl/moPsEk/raw/main/assets/bulldog--v2.png%202x.png" style="width: 45px;height: auto;" loading="lazy"></img> moPsEk</h1>
  236. <h1 style="font-size:20px;border-bottom:solid 1px gray"><img src="https://github.com/mopsfl/moPsEk/raw/main/assets/icons8-wrench-100.png" style="width: 17px;height: auto;" loading="lazy"></img> General <span style="font-size:10px; color: #888">Too high values can result in a bugged display. (But still counts)</span></h1>
  237. <div class="upgrade upgrade-mph" style="width:95%; position: static; height: 25px; background: none; ">
  238. <div class="upgrade-title">Set Money<span data-info='Will refresh your page!' style="position: absolute;height: 15px;width: 15px;background: #333;border-radius: 1ex;margin-left: 5px;padding: 1px;"><img style="width: 100%;height: auto;/*! text-align: center;" src='https://raw.githubusercontent.com/mopsfl/moPsEk/main/assets/icons8-exclamation-mark-90.png' alt='!'></img></span></div>
  239. <div class="upgrade-desc">Changes your current money.</div>
  240. <div style="position: absolute;top: 14px;right: 0;">
  241. <button class="button" style="float: right;position: static;" data-mm_sm>Set</button><input class="input" placeholder="Money" style="float: right;" data-mm_smi>
  242. </div>
  243. </div>
  244. <div class="upgrade upgrade-mph" style="width:95%; position: static; height: 25px; background: none; ">
  245. <div class="upgrade-title">Set XP<span data-info='Will refresh your page!' style="position: absolute;height: 15px;width: 15px;background: #333;border-radius: 1ex;margin-left: 5px;padding: 1px;"><img style="width: 100%;height: auto;/*! text-align: center;" src='https://raw.githubusercontent.com/mopsfl/moPsEk/main/assets/icons8-exclamation-mark-90.png' alt='!'></img></span></div>
  246. <div class="upgrade-desc">Changes your current XP.</div>
  247. <div style="position: absolute;top: 14px;right: 0;">
  248. <button class="button" style="float: right;position: static;" data-mm_sxp>Set</button><input class="input" placeholder="XP" style="float: right;" data-mm_sxpi>
  249. </div>
  250. </div>
  251. <div class="upgrade upgrade-mph" style="width:95%; position: static; height: 25px; background: none; ">
  252. <div class="upgrade-title">Set Tokens<span data-info='Will refresh your page!' style="position: absolute;height: 15px;width: 15px;background: #333;border-radius: 1ex;margin-left: 5px;padding: 1px;"><img style="width: 100%;height: auto;/*! text-align: center;" src='https://raw.githubusercontent.com/mopsfl/moPsEk/main/assets/icons8-exclamation-mark-90.png' alt='!'></img></span></div>
  253. <div class="upgrade-desc">Changes your current tokens.</div>
  254. <div style="position: absolute;top: 14px;right: 0;">
  255. <button class="button" style="float: right;position: static;" data-mm_stks>Set</button><input class="input" placeholder="Tokens" style="float: right;" data-mm_stksi>
  256. </div>
  257. </div>
  258. <div class="upgrade upgrade-mph" style="width:95%; position: static; height: 25px; background: none; ">
  259. <div class="upgrade-title">Set Tickets<span data-info='Will refresh your page!' style="position: absolute;height: 15px;width: 15px;background: #333;border-radius: 1ex;margin-left: 5px;padding: 1px;"><img style="width: 100%;height: auto;/*! text-align: center;" src='https://raw.githubusercontent.com/mopsfl/moPsEk/main/assets/icons8-exclamation-mark-90.png' alt='!'></img></span></div>
  260. <div class="upgrade-desc">Changes your tickets.</div>
  261. <div style="position: absolute;top: 14px;right: 0;">
  262. <button class="button" style="float: right;position: static;" data-mm_stk>Set</button><input class="input" placeholder="Tickets" style="float: right;" data-mm_stki>
  263. </div>
  264. </div>
  265. <div class="upgrade upgrade-mph" style="width:95%; position: static; height: 25px; background: none; ">
  266. <div class="upgrade-title">Set Money per Click<span data-info='Will refresh your page!' style="position: absolute;height: 15px;width: 15px;background: #333;border-radius: 1ex;margin-left: 5px;padding: 1px;"><img style="width: 100%;height: auto;/*! text-align: center;" src='https://raw.githubusercontent.com/mopsfl/moPsEk/main/assets/icons8-exclamation-mark-90.png' alt='!'></img></span></div>
  267. <div class="upgrade-desc">Changes the amount of money you get per click.</div>
  268. <div style="position: absolute;top: 14px;right: 0;">
  269. <button class="button" style="float: right;position: static;" data-mm_mpc>Set</button><input class="input" placeholder="Min" style="float: right;" data-mm_mpcmi><input class="input" placeholder="Max" style="float: right;" data-mm_mpcxi>
  270. </div>
  271. </div>
  272. <div class="upgrade upgrade-mph" style="width:95%; position: static; height: 25px; background: none; ">
  273. <div class="upgrade-title">Set Passive income <span data-info='Will refresh your page!' style="position: absolute;height: 15px;width: 15px;background: #333;border-radius: 1ex;margin-left: 5px;padding: 1px;"><img style="width: 100%;height: auto;/*! text-align: center;" src='https://raw.githubusercontent.com/mopsfl/moPsEk/main/assets/icons8-exclamation-mark-90.png' alt='!'></img></span></div>
  274. <div class="upgrade-desc">Unlocks and finishes all achievements.</div>
  275. <div style="position: absolute;top: 14px;right: 0;">
  276. <button class="button" style="float: right;position: static;" data-mm_spin>Set</button><input class="input" placeholder="Passive Income" style="float: right;" data-mm_pini>
  277. </div>
  278. </div>
  279. <div class="upgrade upgrade-mph" style="width:95%; position: static; height: 25px; background: none; ">
  280. <div class="upgrade-title">Set Offline income <span data-info='Will refresh your page!' style="position: absolute;height: 15px;width: 15px;background: #333;border-radius: 1ex;margin-left: 5px;padding: 1px;"><img style="width: 100%;height: auto;/*! text-align: center;" src='https://raw.githubusercontent.com/mopsfl/moPsEk/main/assets/icons8-exclamation-mark-90.png' alt='!'></img></span></div>
  281. <div class="upgrade-desc">Changes the amount of the offline income.</div>
  282. <div style="position: absolute;top: 14px;right: 0;">
  283. <button class="button" style="float: right;position: static;" data-mm_soin>Set</button><input class="input" placeholder="Offline Income" style="float: right;" data-mm_oini>
  284. </div>
  285. </div>
  286. <div class="upgrade upgrade-mph" style="width:95%; position: static; height: 25px; background: none; ">
  287. <div class="upgrade-title">Give all items<span data-info='Will refresh your page & might cause lags or slow down the page.' style="position: absolute;height: 15px;width: 15px;background: #333;border-radius: 1ex;margin-left: 5px;padding: 1px;"><img style="width: 100%;height: auto;/*! text-align: center;" src='https://raw.githubusercontent.com/mopsfl/moPsEk/main/assets/icons8-exclamation-mark-90.png' alt='!'></img></span></div>
  288. <div class="upgrade-desc">Gives you every item (Knives, Skins, Cases, ...).</div>
  289. <div style="position: absolute;top: 14px;right: 0;">
  290. <button class="button" style="float: right;position: static;" data-mm_gait>Give</button>
  291. </div>
  292. </div>
  293. <div class="upgrade upgrade-mph" style="width:95%; position: static; height: 25px; background: none; ">
  294. <div class="upgrade-title">Give all achievements <span data-info='Will refresh your page!' style="position: absolute;height: 15px;width: 15px;background: #333;border-radius: 1ex;margin-left: 5px;padding: 1px;"><img style="width: 100%;height: auto;/*! text-align: center;" src='https://raw.githubusercontent.com/mopsfl/moPsEk/main/assets/icons8-exclamation-mark-90.png' alt='!'></img></span></div>
  295. <div class="upgrade-desc">Unlocks and finishes all achievements.</div>
  296. <div style="position: absolute;top: 14px;right: 0;">
  297. <button class="button" style="float: right;position: static;" data-mm_gaac>Give</button>
  298. </div>
  299. </div>
  300. <h1 style="font-size:20px;border-bottom:solid 1px gray"><img src="https://github.com/mopsfl/moPsEk/raw/main/assets/icons8-cloud-folder-90.png" style="width: 17px;height: auto;" loading="lazy"></img> Data Managment</h1>
  301. <div class="upgrade upgrade-mph" style="width:95%; position: static; height: 25px; background: none; ">
  302. <div class="upgrade-title">Export Data</div>
  303. <div class="upgrade-desc">Export your current client data.</div>
  304. <div style="position: absolute;top: 14px;right: 0;">
  305. <button class="button" style="float: right;position: static;" data-mm_excd_en>Encoded</button>
  306. <button class="button" style="float: right;position: static;" data-mm_excd_rw>Raw</button>
  307. </div>
  308. </div>
  309. <div class="upgrade upgrade-mph" style="width:95%; position: static; height: 25px; background: none; ">
  310. <div class="upgrade-title">Import Data</div>
  311. <div class="upgrade-desc">Import your saved client data.</div>
  312. <div style="position: absolute;top: 14px;right: 0;">
  313. <button class="button" style="float: right;position: static;" data-mm_imd_en>Import</button>
  314. </div>
  315. </div>
  316. <div class="upgrade upgrade-mph" style="width:95%; position: static; height: 25px; background: none; ">
  317. <div class="upgrade-title">Create backup</div>
  318. <div class="upgrade-desc">Creates a backup of your current data.</div>
  319. <div style="position: absolute;top: 14px;right: 0;">
  320. <button class="button" style="float: right;position: static;" data-mm_cbup>Create</button>
  321. </div>
  322. </div>
  323. <div class="upgrade upgrade-mph" style="width:95%; position: static; height: 25px; background: none; ">
  324. <div class="upgrade-title">Load backup</div>
  325. <div class="upgrade-desc">Loads your recent created backup.</div>
  326. <div style="position: absolute;top: 14px;right: 0;">
  327. <button class="button" style="float: right;position: static;" data-mm_delbup>Load</button>
  328. </div>
  329. </div>
  330. <div class="upgrade upgrade-mph" style="width:95%; position: static; height: 25px; background: none; ">
  331. <div class="upgrade-title">Wipe Data <span data-info='Will open/close seperate tabs! Be sure popups are allowed. If it doesnt work, do it again.' style="position: absolute;height: 15px;width: 15px;background: #333;border-radius: 1ex;margin-left: 5px;padding: 1px;"><img style="width: 100%;height: auto;/*! text-align: center;" src='https://raw.githubusercontent.com/mopsfl/moPsEk/main/assets/icons8-exclamation-mark-90.png' alt='!'></img></span></div>
  332. <div class="upgrade-desc">Wipes all your game data.</div>
  333. <div style="position: absolute;top: 14px;right: 0;">
  334. <button class="button red" style="float: right;position: static;" data-mm_wipd>Wipe</button>
  335. </div>
  336. </div>
  337. <h1 style="font-size:20px;border-bottom:solid 1px gray"><img src="https://github.com/mopsfl/moPsEk/raw/main/assets/bulldog--v2.png%202x.png" style="width: 17px;height: auto;" loading="lazy"></img> moPsEk</h1>
  338. <div class="upgrade upgrade-mph" style="width:95%; position: static; height: 25px; background: none; ">
  339. <p class="upgrade-desc">Script Version<span style="float:right">v.${GM_info.script.version}</span></p>
  340. </div>
  341. <div class="upgrade upgrade-mph" style="width:95%; position: static; height: 25px; background: none; ">
  342. <p class="upgrade-desc">Author <span style="float:right; user-select:text">${GM_info.script.author}</span></p>
  343. </div>
  344. <div class="upgrade upgrade-mph" style="width:95%; position: static; height: 25px; background: none; ">
  345. <p class="upgrade-desc">Automatic Update<span style="float:right; user-select:text">${GM_info.script.options.check_for_updates == true ? "Yes" : "No"}</span></p>
  346. </div>
  347. <div class="upgrade upgrade-mph" style="width:95%; position: static; height: 25px; background: none; ">
  348. <p class="upgrade-desc">Client UUID <span style="float:right; user-select:text">${localStorage._moPsEk_uuid}</span></p>
  349. </div>
  350. `;
  351.  
  352. document.querySelector('#nav').appendChild(btnClone);
  353. document.querySelector('#pages').appendChild(pageClone)
  354. btnClone.innerHTML = '<img src="https://github.com/mopsfl/moPsEk/raw/main/assets/bulldog--v2.png%202x.png"></img> moPsEk';
  355. btnClone.onclick = () => {
  356. document.querySelectorAll('.page').forEach(e => e.classList.remove('show'));
  357. pageClone.classList.add('show');
  358. document.querySelector('#pages').appendChild(pageClone)
  359. };
  360.  
  361. pageClone.querySelectorAll('[data-info]').forEach(t => {
  362. const e = t.attributes['data-info'].nodeValue;
  363. t.onmouseenter = t => {
  364. document.body.appendChild(n)
  365. n.innerText = e;
  366. }
  367. t.onmouseleave = t => {
  368. document.body.removeChild(n)
  369. n.innerText = '';
  370. };
  371. });
  372.  
  373.  
  374. //OPTIONS
  375. const options = {
  376. setMoney: {
  377. input: document.querySelector('[data-mm_smi]'),
  378. btn: document.querySelector('[data-mm_sm]')
  379. },
  380. setXP: {
  381. input: document.querySelector('[data-mm_sxpi]'),
  382. btn: document.querySelector('[data-mm_sxp]')
  383. },
  384. setTokens: {
  385. input: document.querySelector('[data-mm_stksi]'),
  386. btn: document.querySelector('[data-mm_stks]')
  387. },
  388. setTickets: {
  389. input: document.querySelector('[data-mm_stki]'),
  390. btn: document.querySelector('[data-mm_stk]')
  391. },
  392. giveAllItems: {
  393. btn: document.querySelector('[data-mm_gait]')
  394. },
  395. exportData: {
  396. btn: document.querySelector('[data-mm_excd_en]'),
  397. btn2: document.querySelector('[data-mm_excd_rw]'),
  398. },
  399. importData: {
  400. btn: document.querySelector('[data-mm_imd_en]'),
  401. },
  402. wipeData: {
  403. btn: document.querySelector('[data-mm_wipd]'),
  404. },
  405. createBackup: {
  406. btn: document.querySelector('[data-mm_cbup]'),
  407. },
  408. loadBackup: {
  409. btn: document.querySelector('[data-mm_delbup]'),
  410. },
  411. giveAllAchievements: {
  412. btn: document.querySelector('[data-mm_gaac]')
  413. },
  414. setMoneyPerClick: {
  415. btn: document.querySelector('[data-mm_mpc]'),
  416. min: document.querySelector('[data-mm_mpcmi]'),
  417. max: document.querySelector('[data-mm_mpcxi]'),
  418. },
  419. setPassiveIncome: {
  420. btn: document.querySelector('[data-mm_spin]'),
  421. input: document.querySelector('[data-mm_pini]'),
  422. },
  423. setOfflineIncome: {
  424. btn: document.querySelector('[data-mm_soin]'),
  425. input: document.querySelector('[data-mm_oini]'),
  426. }
  427. };
  428.  
  429. //SET MONEY
  430. options.setMoney.btn.onclick = () => {
  431. if (!isNaN(options.setMoney.input) || options.setMoney.input == '') return;
  432. const value = parseInt(options.setMoney.input.value) * 100;
  433. const valid = parseNumbers(value) != '' ? true : false
  434. if (!valid) {
  435. log("Unable to parse numbers for min|max", "red")
  436. nf("This input is invalid.", null, "red")
  437. return
  438. };
  439. user.money = value;
  440. log(`Set money to ${value}.`, 'green');
  441. return save(true);
  442. };
  443.  
  444. //SET XP
  445. options.setXP.btn.onclick = () => {
  446. const value = parseInt(options.setXP.input.value.replace(/\D/g, ''));
  447. const valid = parseNumbers(value) != '' ? true : false
  448. if (!valid) {
  449. log("Unable to parse numbers for min|max", "red")
  450. nf("This input is invalid.", null, "red")
  451. return
  452. };
  453. user.xp = value;
  454. log(`Set xp to ${value}.`, 'green');
  455. return save(true);
  456. };
  457.  
  458. //SET TOKENS
  459. options.setTokens.btn.onclick = () => {
  460. const value = parseInt(options.setTokens.input.value.replace(/\D/g, ''));
  461. const valid = parseNumbers(value) != '' ? true : false
  462. if (!valid) {
  463. log("Unable to parse numbers for min|max", "red")
  464. nf("This input is invalid.", null, "red")
  465. return
  466. };
  467. user.tokens = value;
  468. log(`Set tokens to ${value}.`, 'green');
  469. return save(true);
  470. };
  471.  
  472. //SET TICKETS
  473. options.setTickets.btn.onclick = () => {
  474. const value = parseInt(options.setTickets.input.value.replace(/\D/g, ''));
  475. const valid = parseNumbers(value) != '' ? true : false
  476. if (!valid) {
  477. log("Unable to parse numbers for min|max", "red")
  478. nf("This input is invalid.", null, "red")
  479. return
  480. };
  481. user.tickets = value;
  482. log(`Set tickets to ${value}.`, 'green');
  483. return save(true);
  484. };
  485.  
  486. //GIVE ALL ITEMS
  487. options.giveAllItems.btn.onclick = () => {
  488. ic = 0
  489. liit = 0;
  490. nf("Fetching all packages. This may take a few seconds. (Page will refresh after It's finished)")
  491. itemNames.forEach(name => {
  492. ++ic;
  493. fetch(`https://csgo.mtsl.dk/data/items/${name}.json?v=15`).then(res => res.json()).then(data => {
  494. ++liit;
  495. Object.keys(data).forEach(async item => {
  496. await temp_inventory.push(item)
  497. })
  498. log(`Fetching package : '${name}'.`, "yellow")
  499. if (liit == itemNames.length) {
  500. log(`Successfully fetched all packages.`, "green")
  501. nf("Successfully fetched all packages.")
  502. save(true)
  503. }
  504. })
  505. })
  506.  
  507. log(`Fetching ${ic} packages.`, "yellow")
  508. };
  509.  
  510. //EXPORT DATA
  511. options.exportData.btn.onclick = () => {
  512. const data = getSaveDataString(getUser())
  513. if (!data) return log("Unable to encode current client data", "red");
  514.  
  515. return dlFile(`mtslData_${localStorage._moPsEk_uuid}.encoded`, "txt", data)
  516. };
  517. options.exportData.btn2.onclick = () => {
  518. const data = getUser()
  519. if (!data) {
  520. log("Unable to get current client data", "red");
  521. nf(`Unable to get current client data.`, null, "red")
  522. return
  523. }
  524.  
  525. return dlFile(`mtslData_${localStorage._moPsEk_uuid}.raw`, "txt", JSON.stringify(data, null, 2))
  526. };
  527.  
  528. //IMPORT DATA
  529. options.importData.btn.onclick = () => {
  530. var input = document.createElement('input');
  531. input.type = 'file';
  532. input.click();
  533.  
  534. input.onchange = (e) => {
  535. var reader = new FileReader();
  536. var file = input.files[0]
  537.  
  538. reader.onload = function () {
  539. var text = reader.result
  540. if (!text) return log(`Unable to get file text from '${file.name}'`, "red")
  541. console.log(text)
  542. console.log(file)
  543. log(`Loaded file '${input.files[0].name}' with an size of ${byteToSize(file.size)}`, "green")
  544.  
  545. try {
  546. let json = JSON.parse(text);
  547. user = json
  548. log("Imported raw data.", "green")
  549. nf(`Data imported sucessfully!`)
  550. save(true)
  551. } catch (e) {
  552. try {
  553. let json = JSON.parse(y(text))
  554. user = json
  555. log("Imported encoded data.", "green")
  556. nf(`Data imported sucessfully!`)
  557. save(true)
  558. } catch (e) {
  559. log("Unable to decode data file.", "red")
  560. nf(`Unable to decode data file!`, null, "red")
  561. }
  562. }
  563. };
  564. reader.readAsText(file);
  565. }
  566. };
  567.  
  568. //WIPE DATA
  569. options.wipeData.btn.onclick = () => {
  570. window.open("/esr")
  571. window.close()
  572. GM_setValue(`moPsEk.wipeData`, true)
  573. }
  574.  
  575. //CREATE BACKUP
  576. options.createBackup.btn.onclick = () => {
  577. const data = getSaveDataString(getUser())
  578. if (!data) return log("Unable to get current local data", "red")
  579.  
  580. GM_setValue(`moPsEk_${localStorage._moPsEk_uuid}.backup`, data)
  581. nf(`Sucessfully created local backup.`)
  582. return log("Sucessfully created local backup.", "green")
  583. }
  584.  
  585. //LOAD BACKUP
  586. options.loadBackup.btn.onclick = () => {
  587. const data = GM_getValue(`moPsEk_${localStorage._moPsEk_uuid}.backup`)
  588. if (!data) return log("Unable to get current backup data", "red")
  589.  
  590. localStorage['moPsEk_' + localStorage._moPsEk_uuid] = data;
  591.  
  592. nf(`Sucessfully loaded local backup!`)
  593. log("Sucessfully loaded local backup.", "green")
  594. return save(true)
  595. }
  596.  
  597. //GIVE ALL ACHIEVMENTS
  598. options.giveAllAchievements.btn.onclick = () => {
  599. loadedAchievements = 0;
  600. const data = getSaveDataString(getUser())
  601. if (!data) return log("Unable to get current local data", "red")
  602.  
  603. nf("Loading all achievements. (Page will refresh after It's finished)")
  604. log(`Loading ${Object.keys(achievements).length} achievements.`, "yellow")
  605. console.log(Object.keys(achievements))
  606.  
  607. Object.keys(achievements).forEach(achievement => {
  608. ++loadedAchievements;
  609. log(achievement, "yellow")
  610. user.achievements[achievement] = true
  611. if (loadedAchievements == Object.keys(achievements).length) {
  612. nf("All achievements given successfully.")
  613. log("All achievements loaded successfully.", "green")
  614. console.log(user)
  615. save(true)
  616. }
  617. })
  618. }
  619.  
  620. //MONEY PER CLICK
  621. options.setMoneyPerClick.btn.onclick = () => {
  622. const data = getSaveDataString(getUser())
  623. if (!data) return log("Unable to get current local data", "red")
  624. let min = options.setMoneyPerClick.min.value.replace(/\D/g, '')
  625. let max = options.setMoneyPerClick.max.value.replace(/\D/g, '')
  626. //const valid = parseInt(Number(min)??Number(max)) ? true : false
  627. const valid = (parseNumbers(min) || parseNumbers(max)) != '' ? true : false
  628. if (!valid) {
  629. log("Unable to parse numbers for min|max", "red")
  630. nf("This input is invalid.", null, "red")
  631. return
  632. };
  633. log(`Set clicks per second to [${min} - ${min}]`, "green")
  634.  
  635. user.upgrades.minClick = parseInt(min) * 100
  636. user.upgrades.maxClick = parseInt(max) * 100
  637. return save(true)
  638. }
  639.  
  640. //SET PASSIVE INCOME
  641. options.setPassiveIncome.btn.onclick = () => {
  642. const data = getSaveDataString(getUser())
  643. if (!data) return log("Unable to get current local data", "red")
  644. let value = options.setPassiveIncome.input.value.replace(/\D/g, '')
  645. const valid = parseNumbers(value) != '' ? true : false
  646. if (!valid) {
  647. log("Unable to parse numbers for min|max", "red")
  648. nf("This input is invalid.", null, "red")
  649. return
  650. };
  651. log(`Set passive income to [${value}]`, "green")
  652.  
  653. user.upgrades.passiveIncome = parseInt(value) * 100
  654. return save(true)
  655. }
  656.  
  657. //SET OFFLINE INCOME
  658. options.setOfflineIncome.btn.onclick = (e) => {
  659. const data = getSaveDataString(getUser())
  660. if (!data) return log("Unable to get current local data", "red")
  661. let value = options.setOfflineIncome.input.value.replace(/\D/g, '')
  662. const valid = parseNumbers(value) != '' ? true : false
  663. if (!valid) {
  664. log("Unable to parse numbers for offlineIncome", "red")
  665. nf("This input is invalid.", null, "red")
  666. return
  667. };
  668. log(`Set offline income to [${value}]`, "green")
  669.  
  670. user.upgrades.offlineIncome = parseInt(value) * 100
  671. return save(true)
  672. }
  673.  
  674.  
  675. //
  676.  
  677. //OTHER
  678. log(`moPsEk v.${GM_info.script.version} initalized sucessfully! Client UUID : ${localStorage._moPsEk_uuid}`, 'green');
  679. nf(`moPsEk v.${GM_info.script.version} initalized sucessfully!`, true)
  680. }
  681.  
  682. if (GM_getValue(`moPsEk.wipeData`) == true) {
  683. localStorage.clear()
  684. window.open("https://csgo.mtsl.dk/")
  685. GM_setValue(`moPsEk.wipeData`, false)
  686. window.close()
  687. }
  688.  
  689. //SETUP
  690. try {
  691. log(`Initalizing moPsEk v.${GM_info.script.version}`, 'yellow');
  692. if (!localStorage.getItem('_moPsEk_uuid')) {
  693. localStorage.setItem('_moPsEk_uuid', uuidv4());
  694. log('moPsEk client uuid created sucessfully!', 'green');
  695. }
  696. if (!localStorage.getItem('moPsEk_' + localStorage._moPsEk_uuid)) {
  697. localStorage.setItem('moPsEk_' + localStorage._moPsEk_uuid, getSaveDataString(getUser()));
  698. log('moPsEk client savedata created sucessfully!', 'green');
  699. }
  700. if (!localStorage['moPsEk_' + localStorage._moPsEk_uuid + "_tempInv"]) {
  701. localStorage['moPsEk_' + localStorage._moPsEk_uuid + "_tempInv"] = JSON.stringify([])
  702. }
  703. //localStorage.localsave = localStorage['moPsEk_' + localStorage._moPsEk_uuid];
  704. setData(JSON.parse(y(localStorage['moPsEk_' + localStorage._moPsEk_uuid])))
  705.  
  706. window.onload = () => {
  707. initMenu()
  708. fetch("https://raw.githubusercontent.com/mopsfl/moPsEk/main/games/csgo.mtsl.dk/compatible_versions.json")
  709. .then(res => res.json())
  710. .then(data => {
  711. let game_version = document.querySelector("#version-version").innerText
  712.  
  713. if (!data.compatible_versions.includes(game_version)) {
  714. log("This game version might not be fully compatible with moPsEk.", "red")
  715. alert("moPsEk Info\n\nThis game version might not be fully compatible with moPsEk.\nBe sure it's up to date!")
  716. } else log(`Game Version '${game_version}' compatible!`, 'green');
  717.  
  718. if (GM_info.script.options.run_at != "document-start") {
  719. GM_setClipboard("// @run-at document-start")
  720. alert("moPsEk Info\n\n@run-at is not set to 'document-start'\nThis might cause the mod menu to not work correctly.\n\nAdd the string in your clipboard to the script.")
  721. }
  722. })
  723. };
  724. } catch (e) {
  725. log("Unable to load moPsEk", "red")
  726. log(e, "red")
  727. }
  728. }());