Melvor Idle - AutoSlayer

Automatically reroll and extend slayer tasks for specific monsters

  1. // ==UserScript==
  2. // @name Melvor Idle - AutoSlayer
  3. // @description Automatically reroll and extend slayer tasks for specific monsters
  4. // @version 1.0
  5. // @namespace Visua
  6. // @match https://melvoridle.com/*
  7. // @match https://www.melvoridle.com/*
  8. // @grant none
  9. // ==/UserScript==
  10. /* jshint esversion: 6 */
  11.  
  12. ((main) => {
  13. var script = document.createElement('script');
  14. script.textContent = `try { (${main})(); } catch (e) { console.log(e); }`;
  15. document.body.appendChild(script).parentNode.removeChild(script);
  16. })(() => {
  17. 'use strict';
  18.  
  19. const id = 'AutoSlayer';
  20.  
  21. function loadAutoSlayer() {
  22. // Load settings
  23. let settings = {
  24. monsters: MONSTERS.map((m, i) => i).filter(id => MONSTERS[id].canSlayer),
  25. monstersToExtend: [],
  26. };
  27. const savedSettings = JSON.parse(localStorage.getItem(`${id}-${currentCharacter}`));
  28. if (savedSettings) {
  29. settings = savedSettings;
  30. }
  31.  
  32. // Validate and save settings on change
  33. const settingsHandler = {
  34. set: function (obj, prop, value) {
  35. if (prop === 'monsters') {
  36. if (!Array.isArray(value) || value.some(e => !Number.isInteger(e))) {
  37. throw new TypeError('monsters should be an array of integers');
  38. }
  39. } else if (prop === 'monstersToExtend') {
  40. if (!Array.isArray(value) || value.some(e => !Number.isInteger(e))) {
  41. throw new TypeError('monstersToExtend should be an array of integers');
  42. }
  43. }
  44.  
  45. obj[prop] = value;
  46. localStorage.setItem(`${id}-${currentCharacter}`, JSON.stringify(AUTOSLAYER.settings));
  47. console.log('Settings saved');
  48. return true;
  49. },
  50. };
  51.  
  52. window.AUTOSLAYER = {
  53. settings: new Proxy(settings, settingsHandler),
  54. };
  55.  
  56. const _autoSlayer = autoSlayer;
  57. const _getSlayerTask = getSlayerTask;
  58.  
  59. function getAutoSlayerTask(monster, tier = 0) {
  60. _getSlayerTask(monster, tier);
  61.  
  62. try {
  63. if (AUTOSLAYER.settings.monsters.includes(slayerTask[0].monsterID)) {
  64. console.log(`AutoSlayer: Fighting ${MONSTERS[slayerTask[0].monsterID].name} x${slayerTask[0].count}`);
  65. if (isInCombat && enemyInCombat !== slayerTask[0].monsterID) {
  66. jumpToEnemy(slayerTask[0].monsterID);
  67. }
  68. if (AUTOSLAYER.settings.monstersToExtend.includes(slayerTask[0].monsterID)) {
  69. extendSlayerTask();
  70. console.log(`AutoSlayer: Extended to ${slayerTask[0].count}`);
  71. }
  72. } else {
  73. console.log(`AutoSlayer: Rerolling ${MONSTERS[slayerTask[0].monsterID].name}`);
  74. // Temporarily set autoSlayer to true so we don't roll for monsters we can't fight
  75. autoSlayer = true;
  76. selectNewSlayerTask(tier);
  77. // Set it to false again so we don't automatically jump to the new monster
  78. autoSlayer = false;
  79. }
  80. } catch (e) {
  81. console.error(e);
  82. }
  83. };
  84.  
  85. AUTOSLAYER.start = function () {
  86. console.log('AutoSlayer: Starting');
  87. getSlayerTask = getAutoSlayerTask;
  88. // This is just to indicate that we're making use of this setting to only roll for monsters we can fight
  89. autoSlayer = true;
  90. $('#setting-autoslayermonster').prop('checked', true);
  91. };
  92.  
  93. AUTOSLAYER.stop = function () {
  94. console.log('AutoSlayer: Stopping');
  95. getSlayerTask = _getSlayerTask;
  96. // Restore the original setting
  97. autoSlayer = _autoSlayer;
  98. $('#setting-autoslayermonster').prop('checked', autoSlayer);
  99. };
  100.  
  101. AUTOSLAYER.start();
  102. }
  103.  
  104. function loadScript() {
  105. if (typeof confirmedLoaded !== 'undefined' && confirmedLoaded && !currentlyCatchingUp) {
  106. clearInterval(interval);
  107. console.log(`Loading ${id}`);
  108. loadAutoSlayer();
  109. }
  110. }
  111.  
  112. const interval = setInterval(loadScript, 500);
  113. });