IdlePixel Combat Presets Plus

CombatPresets (5x5) / Don't use with "Slap Chop".

  1. // ==UserScript==
  2. // @name IdlePixel Combat Presets Plus
  3. // @namespace mippo.idle-pixel
  4. // @version 1.0.1
  5. // @description CombatPresets (5x5) / Don't use with "Slap Chop".
  6. // @author mippo
  7. // @license MIT
  8. // @match *://idle-pixel.com/login/play*
  9. // @grant none
  10. // @require https://greasyfork.org/scripts/441206-idlepixel/code/IdlePixel+.js?anticache=20220905
  11. // ==/UserScript==
  12.  
  13. (function () {
  14. "use strict";
  15.  
  16. // Overall Declarations for different variables used throughout the script
  17. let IPP, getVar, getThis;
  18. const IMAGE_URL_BASE = document
  19. .querySelector("itembox[data-item=copper] img")
  20. .src.replace(/\/[^/]+.png$/, "");
  21. let loaded = false;
  22. let onLoginLoaded = false;
  23.  
  24. // Start New Code Base Const/Functions
  25. const misc = function () {
  26. return {
  27. initStyles: function () {
  28. var style = document.createElement("style");
  29. style.id = "styles-slapchop";
  30. style.innerHTML = `
  31. #slapchop-quickpreset > .slapchop-quickpreset-buttons {
  32. display: flex;
  33. flex-direction: row;
  34. justify-content: start;
  35. }
  36.  
  37. #slapchop-quickpreset > .slapchop-quickpreset-buttons > div {
  38. display: flex;
  39. flex-direction: column;
  40. justify-content: start;
  41. }
  42.  
  43. #combat-stats #slapchop-quickpreset > .slapchop-quickpreset-buttons {
  44. display: grid;
  45. grid-template-columns: auto auto;
  46. justify-content: start;
  47. column-gap: 1em;
  48. }
  49.  
  50. #combat-stats #slapchop-quickpreset > .slapchop-quickpreset-buttons > div {
  51. display: flex;
  52. flex-direction: row;
  53. justify-content: flex-start;
  54. }
  55.  
  56. #combat-stats #slapchop-quickpreset > .slapchop-quickpreset-buttons > div > div {
  57. display: flex;
  58. flex-direction: column;
  59. justify-content: flex-start;
  60. }
  61.  
  62. #slapchop-quickpreset-buttons-unlink,
  63. #slapchop-quickpreset-buttons-unlink-lock {
  64. font-size: 0.8em;
  65. }
  66.  
  67. #slapchop-quickpreset-buttons-unlink.current-group-0,
  68. #slapchop-quickpreset-buttons-unlink-lock.current-group-99,
  69. #combat-stats #slapchop-quickpreset-buttons-groups.current-group-6 > .slapchop-quickpreset-buttons-group6 > button,
  70. #combat-stats #slapchop-quickpreset-buttons-groups.current-group-7 > .slapchop-quickpreset-buttons-group7 > button,
  71. #combat-stats #slapchop-quickpreset-buttons-groups.current-group-8 > .slapchop-quickpreset-buttons-group8 > button,
  72. #combat-stats #slapchop-quickpreset-buttons-groups.current-group-9 > .slapchop-quickpreset-buttons-group9 > button,
  73. #combat-stats #slapchop-quickpreset-buttons-groups.current-group-10 > .slapchop-quickpreset-buttons-group10 > button,
  74. #in-combat-presets-icon-6.current,
  75. #in-combat-presets-icon-7.current,
  76. #in-combat-presets-icon-8.current,
  77. #in-combat-presets-icon-9.current,
  78. #in-combat-presets-icon-10.current {
  79. background-color: limegreen;
  80. }
  81.  
  82. #slapchop-quickpreset button {
  83. margin: 0.125em;
  84. }
  85.  
  86. .combat-presets-area,
  87. .combat-potions-area,
  88. .combat-cannon-area {
  89. vertical-align: text-top;
  90. }
  91. `;
  92. document.head.appendChild(style);
  93. },
  94. };
  95. };
  96.  
  97. const combat = function () {
  98. window.SCUSERNAME = getVar("username", "", "string");
  99.  
  100. // Define keys for localStorage in a centralized manner
  101. const COMBAT_PRESETS_KEY = SCUSERNAME + ".combat_presets";
  102. const COMBAT_PRESETS_LINK_KEY = SCUSERNAME + ".combat_presets_link";
  103.  
  104. return {
  105. loadPresetGroups: function (buttonNum) {
  106. // Suppress popup "Combat preset saved"
  107. const openImageModalOriginal = Modals.open_image_modal;
  108. Modals.open_image_modal = (title, image_path, message, primary_button_text, secondary_button_text, command, force_unclosable) => {
  109. if (message === "Successfully saved preset based on what you are currently wearing.") {
  110. return;
  111. }
  112. openImageModalOriginal(title, image_path, message, primary_button_text, secondary_button_text, command, force_unclosable);
  113. }
  114.  
  115. // Set shortcut number presets to 1-5
  116. for (let combatpresetNum = 1; combatpresetNum < 6; combatpresetNum++) {
  117. let presetName = `CombatPreset ${buttonNum * 10 + combatpresetNum}`;
  118.  
  119. // Retrieve all presets from local storage
  120. let allPresets =
  121. JSON.parse(localStorage.getItem(COMBAT_PRESETS_KEY)) ||
  122. {};
  123.  
  124. // Check if the requested preset exists
  125. if (!allPresets[presetName]) {
  126. console.error("Preset not found for button number:", presetName);
  127. return;
  128. }
  129.  
  130. // Load the preset and equip each item
  131. IdlePixelPlus.sendMessage("UNEQUIP_ALL");
  132. allPresets[presetName].forEach((item) => {
  133. if (item) {
  134. IdlePixelPlus.sendMessage("EQUIP=" + item);
  135. }
  136. });
  137. IdlePixelPlus.sendMessage(`PRESET_SAVE=${combatpresetNum}`);
  138. }
  139. IdlePixelPlus.sendMessage('PRESET_LOAD=1~1');
  140.  
  141. sCCombat().saveLinkedPresetNum(buttonNum);
  142. },
  143.  
  144. savePresetGroups: function (buttonNum) {
  145. // Presets 1-5 are saved as shortcut numbers
  146. for (let combatpresetNum = 1; combatpresetNum < 6; combatpresetNum++) {
  147. let presetName = `CombatPreset ${buttonNum * 10 + combatpresetNum}`;
  148.  
  149. // Retrieve all presets from local storage, or initialize a new object if none exist
  150. let allPresets =
  151. JSON.parse(localStorage.getItem(COMBAT_PRESETS_KEY)) ||
  152. {};
  153.  
  154. // Save current equipment settings into the relevant key of the allPresets object
  155. allPresets[presetName] = [
  156. getVar(`preset_head_${combatpresetNum}`, null, "string"),
  157. getVar(`preset_body_${combatpresetNum}`, null, "string"),
  158. getVar(`preset_legs_${combatpresetNum}`, null, "string"),
  159. getVar(`preset_boots_${combatpresetNum}`, null, "string"),
  160. getVar(`preset_gloves_${combatpresetNum}`, null, "string"),
  161. getVar(`preset_amulet_${combatpresetNum}`, null, "string"),
  162. getVar(`preset_weapon_${combatpresetNum}`, null, "string"),
  163. getVar(`preset_shield_${combatpresetNum}`, null, "string"),
  164. getVar(`preset_arrows_${combatpresetNum}`, null, "string"),
  165. ];
  166.  
  167. // Update the single entry in local storage with the modified allPresets object
  168. localStorage.setItem(COMBAT_PRESETS_KEY, JSON.stringify(allPresets));
  169. }
  170.  
  171. sCCombat().saveLinkedPresetNum(buttonNum);
  172. },
  173.  
  174. saveCurrentPresets: function (buttonNum) {
  175. IdlePixelPlus.sendMessage(`PRESET_SAVE=${buttonNum}`)
  176.  
  177. // Get linked preset numbers
  178. const LinkedPresetNum =
  179. JSON.parse(localStorage.getItem(COMBAT_PRESETS_LINK_KEY)) ||
  180. 0;
  181. if (LinkedPresetNum === 0 || LinkedPresetNum === 99) {
  182. return;
  183. }
  184.  
  185. sCCombat().savePresetGroups(LinkedPresetNum);
  186.  
  187. let presetName = `CombatPreset ${LinkedPresetNum * 10 + buttonNum}`;
  188.  
  189. // Retrieve all presets from local storage, or initialize a new object if none exist
  190. let allPresets =
  191. JSON.parse(localStorage.getItem(COMBAT_PRESETS_KEY)) ||
  192. {};
  193.  
  194. // Save current equipment settings into the relevant key of the allPresets object
  195. allPresets[presetName] = [
  196. getVar("head", null, "string"),
  197. getVar("body", null, "string"),
  198. getVar("legs", null, "string"),
  199. getVar("boots", null, "string"),
  200. getVar("gloves", null, "string"),
  201. getVar("amulet", null, "string"),
  202. getVar("weapon", null, "string"),
  203. getVar("shield", null, "string"),
  204. getVar("arrows", null, "string"),
  205. ];
  206.  
  207. // Update the single entry in local storage with the modified allPresets object
  208. localStorage.setItem(COMBAT_PRESETS_KEY, JSON.stringify(allPresets));
  209. },
  210.  
  211. saveLinkedPresetNum: function (buttonNum) {
  212. const LinkedPresetNum =
  213. JSON.parse(localStorage.getItem(COMBAT_PRESETS_LINK_KEY)) ||
  214. 0;
  215.  
  216. // Lock button on/off switching
  217. if (LinkedPresetNum === 99) {
  218. if (buttonNum === 99) {
  219. buttonNum = 0;
  220. } else {
  221. return;
  222. }
  223. }
  224.  
  225. localStorage.setItem(COMBAT_PRESETS_LINK_KEY, buttonNum);
  226.  
  227. sCCombat().removeHighlightPresetButtons();
  228. sCCombat().highlightPresetButtons();
  229. },
  230.  
  231. highlightPresetButtons: function () {
  232. // Retrieve the preset number from localStorage (default to 0 if not found)
  233. const LinkedPresetNum =
  234. JSON.parse(localStorage.getItem(COMBAT_PRESETS_LINK_KEY)) || 0;
  235.  
  236. if (LinkedPresetNum >= 6 && LinkedPresetNum <= 10) {
  237. // For numbers between 6 and 10, apply a highlight to the corresponding group and icon
  238. const groupElem = document.getElementById("slapchop-quickpreset-buttons-groups");
  239. if (groupElem) {
  240. groupElem.className = "current-group-" + LinkedPresetNum;
  241. }
  242. const iconElem = document.getElementById("in-combat-presets-icon-" + LinkedPresetNum);
  243. if (iconElem) {
  244. iconElem.classList.add("current");
  245. }
  246. } else {
  247. const unlinkElem = document.getElementById("slapchop-quickpreset-buttons-unlink");
  248. if (unlinkElem) {
  249. // If LinkedPresetNum is 0, apply highlight to the unlink button
  250. unlinkElem.className = "current-group-0";
  251. }
  252. if (LinkedPresetNum === 99) {
  253. // If LinkedPresetNum is 99, apply highlight to the unlink-lock button
  254. const unlinkLockElem = document.getElementById("slapchop-quickpreset-buttons-unlink-lock");
  255. if (unlinkLockElem) {
  256. unlinkLockElem.className = "current-group-99";
  257. }
  258. }
  259. }
  260. },
  261.  
  262. removeHighlightPresetButtons: function () {
  263. // Remove highlight for the entire preset group container
  264. const groupElem = document.getElementById("slapchop-quickpreset-buttons-groups");
  265. if (groupElem) {
  266. groupElem.className = ""; // Reset the container's class
  267. }
  268.  
  269. // Remove highlights from preset icons for groups 6 to 10
  270. for (let i = 6; i <= 10; i++) {
  271. const iconElem = document.getElementById("in-combat-presets-icon-" + i);
  272. if (iconElem) {
  273. iconElem.classList.remove("current");
  274. }
  275. }
  276.  
  277. // Remove highlights from the unlink and unlink-lock buttons
  278. const unlinkElem = document.getElementById("slapchop-quickpreset-buttons-unlink");
  279. if (unlinkElem) {
  280. unlinkElem.className = "";
  281. }
  282. const unlinkLockElem = document.getElementById("slapchop-quickpreset-buttons-unlink-lock");
  283. if (unlinkLockElem) {
  284. unlinkLockElem.className = "";
  285. }
  286. },
  287.  
  288. initQuickFight: async function () {
  289. let html = `
  290. </div>
  291. <hr>
  292. </div>
  293. <div id="slapchop-quickpreset">
  294. <div class="slapchop-quickpreset-buttons">
  295. <h5>Quick Current Presets:</h5>
  296. <h5>Current Preset Groups:
  297. <button id="slapchop-quickpreset-buttons-unlink" onclick="sCCombat().saveLinkedPresetNum(0)">Unlink Current Gr</button>
  298. <button id="slapchop-quickpreset-buttons-unlink-lock" onclick="sCCombat().saveLinkedPresetNum(99)">Lock</button>
  299. </h5>
  300. <div>
  301. <div>
  302. <button onclick="sCCombat().saveCurrentPresets(1);">Save 1</button>
  303. <button onclick="IdlePixelPlus.sendMessage('PRESET_LOAD=1~1')">Load 1</button>
  304. </div>
  305. <div>
  306. <button onclick="sCCombat().saveCurrentPresets(2);">Save 2</button>
  307. <button onclick="IdlePixelPlus.sendMessage('PRESET_LOAD=2~1')">Load 2</button>
  308. </div>
  309. <div>
  310. <button onclick="sCCombat().saveCurrentPresets(3);">Save 3</button>
  311. <button onclick="IdlePixelPlus.sendMessage('PRESET_LOAD=3~1')">Load 3</button>
  312. </div>
  313. <div>
  314. <button onclick="sCCombat().saveCurrentPresets(4);">Save 4</button>
  315. <button onclick="IdlePixelPlus.sendMessage('PRESET_LOAD=4~1')">Load 4</button>
  316. </div>
  317. <div>
  318. <button onclick="sCCombat().saveCurrentPresets(5);">Save 5</button>
  319. <button onclick="IdlePixelPlus.sendMessage('PRESET_LOAD=5~1')">Load 5</button>
  320. </div>
  321. </div>
  322. <div id="slapchop-quickpreset-buttons-groups" class="">
  323. <div class="slapchop-quickpreset-buttons-group6">
  324. <button onclick="sCCombat().savePresetGroups(6)">Save Gr6</button>
  325. <button onclick="sCCombat().loadPresetGroups(6)">Load Gr6</button>
  326. </div>
  327. <div class="slapchop-quickpreset-buttons-group7">
  328. <button onclick="sCCombat().savePresetGroups(7)">Save Gr7</button>
  329. <button onclick="sCCombat().loadPresetGroups(7)">Load Gr7</button>
  330. </div>
  331. <div class="slapchop-quickpreset-buttons-group8">
  332. <button onclick="sCCombat().savePresetGroups(8)">Save Gr8</button>
  333. <button onclick="sCCombat().loadPresetGroups(8)">Load Gr8</button>
  334. </div>
  335. <div class="slapchop-quickpreset-buttons-group9">
  336. <button onclick="sCCombat().savePresetGroups(9)">Save Gr9</button>
  337. <button onclick="sCCombat().loadPresetGroups(9)">Load Gr9</button>
  338. </div>
  339. <div class="slapchop-quickpreset-buttons-group10">
  340. <button onclick="sCCombat().savePresetGroups(10)">Save Gr10</button>
  341. <button onclick="sCCombat().loadPresetGroups(10)">Load Gr10</button>
  342. </div>
  343. </div>
  344. </div>
  345. </div>
  346. <hr>
  347. `;
  348. const panelCombat = document.getElementById("combat-stats").querySelectorAll("div")[4];
  349. if (panelCombat) {
  350. panelCombat.insertAdjacentHTML("afterend", html);
  351. }
  352. },
  353.  
  354. initPresets: function () {
  355. const combatPresetsHtml = `
  356. <br />
  357. <br />
  358. <img data-tooltip="Presets group 6" id="in-combat-presets-icon-6" onclick="sCCombat().loadPresetGroups(6)" class="combat-presets-combat-icon hover w30" src="${IMAGE_URL_BASE}/melee.png" />
  359. <img data-tooltip="Presets group 7" id="in-combat-presets-icon-7" onclick="sCCombat().loadPresetGroups(7)" class="combat-presets-combat-icon hover w30" src="${IMAGE_URL_BASE}/melee.png" />
  360. <img data-tooltip="Presets group 8" id="in-combat-presets-icon-8" onclick="sCCombat().loadPresetGroups(8)" class="combat-presets-combat-icon hover w30" src="${IMAGE_URL_BASE}/melee.png" />
  361. <img data-tooltip="Presets group 9" id="in-combat-presets-icon-9" onclick="sCCombat().loadPresetGroups(9)" class="combat-presets-combat-icon hover w30" src="${IMAGE_URL_BASE}/melee.png" />
  362. <img data-tooltip="Presets group 10" id="in-combat-presets-icon-10" onclick="sCCombat().loadPresetGroups(10)" class="combat-presets-combat-icon hover w30" src="${IMAGE_URL_BASE}/melee.png" />
  363. `;
  364.  
  365. const combatPresetsArea = document.getElementById(
  366. "combat-presets-area"
  367. );
  368. if (combatPresetsArea) {
  369. combatPresetsArea.insertAdjacentHTML("beforeend", combatPresetsHtml);
  370. }
  371. },
  372.  
  373. initPresetListener: function () {
  374. const KEY_ACTIONS = {
  375. 54: () => sCCombat().loadPresetGroups(6), //key [6]
  376. 55: () => sCCombat().loadPresetGroups(7), //key [7]
  377. 56: () => sCCombat().loadPresetGroups(8), //key [8]
  378. 57: () => sCCombat().loadPresetGroups(9), //key [9]
  379. 48: () => sCCombat().loadPresetGroups(10), //key [0]
  380. };
  381.  
  382. document.addEventListener("keyup", (e) => {
  383. const chatInput = document.getElementById("chat-area-input");
  384. let chatFocused = chatInput && document.activeElement === chatInput;
  385. let isRelevantPanel = [
  386. "panel-combat-canvas",
  387. "panel-combat",
  388. "panel-combat-canvas-raids",
  389. ].includes(Globals.currentPanel);
  390.  
  391. if (chatFocused || !isRelevantPanel) {
  392. return; // Early exit if chat is focused or the panel is not relevant
  393. }
  394.  
  395. const action = KEY_ACTIONS[e.keyCode];
  396. if (action) {
  397. action(); // Execute the action associated with the key code
  398. }
  399. });
  400. },
  401. };
  402. };
  403.  
  404. window.sCMisc = misc;
  405. window.sCCombat = combat;
  406.  
  407. // End New Code Base Const/Functions
  408.  
  409. class SlapChopPlugin extends IdlePixelPlusPlugin {
  410. constructor() {
  411. super("slapchop", {
  412. about: {
  413. name: GM_info.script.name + " (ver: " + GM_info.script.version + ")",
  414. version: GM_info.script.version,
  415. author: GM_info.script.author,
  416. description: GM_info.script.description,
  417. },
  418. });
  419. }
  420.  
  421. onConfigsChanged() {
  422. if (onLoginLoaded) {
  423. const slapchopQuickPreset = document.querySelector(
  424. "#slapchop-quickpreset"
  425. );
  426.  
  427. const presetsUnlocked = IdlePixelPlus.getVar("combat_presets") == "1";
  428. if (presetsUnlocked) {
  429. slapchopQuickPreset.style.display = "block";
  430. } else {
  431. slapchopQuickPreset.style.display = "none";
  432. }
  433. }
  434. }
  435.  
  436. onLogin() {
  437. IPP = IdlePixelPlus;
  438. getVar = IdlePixelPlus.getVarOrDefault;
  439. getThis = IdlePixelPlus.plugins.slapchop;
  440. sCMisc().initStyles();
  441. sCCombat().initQuickFight();
  442. sCCombat().initPresets();
  443. sCCombat().initPresetListener();
  444. sCCombat().highlightPresetButtons();
  445.  
  446. setTimeout(function () {
  447. onLoginLoaded = true;
  448. IdlePixelPlus.plugins.slapchop.onConfigsChanged();
  449. }, 5000);
  450. loaded = true;
  451. }
  452.  
  453. async delay() {
  454. await new Promise((resolve) => {
  455. const checkLoaded = () => {
  456. if (loaded) {
  457. resolve();
  458. } else {
  459. setTimeout(checkLoaded, 2000);
  460. }
  461. };
  462.  
  463. checkLoaded();
  464. });
  465. }
  466. }
  467.  
  468. const plugin = new SlapChopPlugin();
  469. IdlePixelPlus.registerPlugin(plugin);
  470. })();