您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Bloop Bleep. I roll for corruptions.
// ==UserScript== // @name Melvor Corruption Roller // @namespace http://tampermonkey.net/ // @version 0.0.5 // @description Bloop Bleep. I roll for corruptions. // @author NotCorgan#1234 // @match https://melvoridle.com/* // @match https://www.melvoridle.com/* // @match https://test.melvoridle.com/* // @exclude https://melvoridle.com/update/* // @exclude https://www.melvoridle.com/update/* // @exclude https://test.melvoridle.com/update/* // @grant none // @noframes // ==/UserScript== // Made for version 0.19.2 (function() { function injectScript(main) { var script = document.createElement('script'); script.textContent = `try {(${main})();} catch (e) {console.log(e);}`; document.body.appendChild(script).parentNode.removeChild(script); } function script() { if (currentGamemode === 3) { items.forEach((item, i) => item.itemID = i); let __notifyPlayer = notifyPlayer; notifyPlayer = function() { let [skill, message, type = "success"] = [...arguments]; if (skill == CONSTANTS.skill.Attack && message == 'Your item was destroyed :(' && type == "danger") return; __notifyPlayer.apply(window, arguments); } let bannedModifiers = ["golbinRaidWaveSkipCostReduction", "golbinRaidIncreasedMinimumFood", "golbinRaidIncreasedMaximumAmmo", "golbinRaidIncreasedMaximumRunes", "golbinRaidPrayerUnlocked", "golbinRaidIncreasedPrayerLevel", "golbinRaidIncreasedPrayerPointsStart", "golbinRaidIncreasedPrayerPointsWave", "golbinRaidPassiveSlotUnlocked", "golbinRaidIncreasedStartingRuneCount", "golbinRaidStartingWeapon", "freeBonfires", "autoSlayerUnlocked", "increasedEquipmentSets", "dungeonEquipmentSwapping", "increasedTreeCutLimit", "increasedAttackRolls", "decreasedAttackRolls", "increasedBankSpaceShop", "decreasedBankSpaceShop", "increasedGPFromSales", "decreasedGPFromSales", ]; let activeModifiers = Object.fromEntries(Object.entries(playerModifiersTemplate).filter(([mod, val]) => !bannedModifiers.includes(mod))); corruptionRollerSettings = new Proxy(JSON.parse(localStorage.getItem(`corruptionRoller-${currentCharacter}`) || JSON.stringify(Array.from(Array(11)).map((_, i) => []))), { get: function(target, id) { return target[id]; }, set: function(target, id, value) { target[id] = value localStorage.setItem(`corruptionRoller-${currentCharacter}`, JSON.stringify(target)) } }); corruptionRollerCount = new Proxy(JSON.parse(localStorage.getItem(`corruptionRollerCount-${currentCharacter}`) || JSON.stringify(Array.from(Array(11)).fill(0))), { get: function(target, id) { return target[id]; }, set: function(target, id, value) { target[id] = value localStorage.setItem(`corruptionRollerCount-${currentCharacter}`, JSON.stringify(target)) } }); let levelRequired = (item) => Math.max(item.attackLevelRequired || 0, item.defenceLevelRequired || 0, item.rangedLevelRequired || 0, item.magicLevelRequired || 0, item.slayerLevelRequired || 0) let itemSub = (item) => [ ['Attack', 'attackLevelRequired'], ['Defence', 'defenceLevelRequired'], ['Ranged', 'rangedLevelRequired'], ['Magic', 'magicLevelRequired'], ['Slayer', 'slayerLevelRequired'] ].map(([name, stat]) => item[stat] != undefined && `<br>Requires ${name} <small class='text-warning'>${item[stat]}</small>`).filter(Boolean) class CorruptionModal { constructor() { this.modal = document.createElement('div'); this.modal.id = 'modal-corruption-items'; this.modal.className = 'modal'; this.modalDialog = document.createElement('div'); this.modalDialog.className = 'modal-dialog modal-xl'; this.modal.appendChild(this.modalDialog); this.modalContent = document.createElement('div'); this.modalContent.className = 'modal-content'; this.modalDialog.appendChild(this.modalContent); this.modalHeader = $(`<div class="block block-themed block-transparent mb-0"><div class="block-header bg-primary-dark"><h3 class="block-title">Corruption Items</h3><div class="block-options"><button type="button" class="btn-block-option" data-dismiss="modal" aria-label="Close"><i class="fa fa-fw fa-times"></i></button></div></div></div>`); $(this.modalContent).append(this.modalHeader); this.modalBody = $(`<div class="row"></div>`); this.modalWrap = $(`<div class="block-content"></div`); $(this.modalWrap).append(this.modalBody); $(this.modalContent).append(this.modalWrap); this.tts = []; document.getElementById('page-container').appendChild(this.modal); } show = (i) => { $(this.modalBody).html(""); if (this.tts.length > 0) this.tts.forEach(tt => tt.destroy()); this.tts = []; items.filter(item => item.equipmentSlot !== undefined && item.sellsFor >= [0, 200, 10000, 400000, Infinity][i] && item.sellsFor < [0, 200, 10000, 400000, Infinity][i + 1]).sort((a, b) => (a.equipmentSlot == b.equipmentSlot ? levelRequired(a) - levelRequired(b) : a.equipmentSlot - b.equipmentSlot)).forEach(item => { $(this.modalBody).append('<img class="skill-icon-sm" id="corruption-item-img-' + item.itemID + '" src="' + getItemMedia(item.itemID) + '">'); let tt = "<div class='text-center'>" + item.name + "<small class='text-info'>" + itemSub(item) + "</small></div>"; this.tts = this.tts.concat(tippy("#corruption-item-img-" + item.itemID, { content: tt, placement: "bottom", allowHTML: true, interactive: false, animation: false, })); }); $(this.modal).modal("show"); }; } class AutoComplete { constructor(parent, db, [inputValue, valueValue] = []) { this.parent = parent; this.db = db; this.inputElement = document.createElement('input'); this.valueElement = document.createElement('input'); this.skillElement = document.createElement('select'); this.removeElement = document.createElement('div'); let anyOpt = document.createElement('option'); anyOpt.value = -1; anyOpt.innerHTML = "Any"; this.skillElement.appendChild(anyOpt); Object.entries(SKILLS).forEach(([id, skill]) => { let opt = document.createElement('option'); opt.value = parseInt(id); opt.innerHTML = skill.name; this.skillElement.appendChild(opt); }); if (inputValue != undefined) this.inputElement.value = inputValue; if (valueValue != undefined) { if (Array.isArray(valueValue)) { this.skillElement.style.setProperty('display', 'inline-block'); this.skillElement.value = valueValue[0]; this.valueElement.value = valueValue[1]; } else { this.skillElement.style.setProperty('display', 'none'); this.valueElement.value = valueValue; } } else { this.skillElement.style.setProperty('display', 'none'); } this.resultsElement = document.createElement('div'); this.parent.style.setProperty('text-align', 'left'); this.removeElement.style.setProperty('height', '30px'); this.removeElement.style.setProperty('display', 'inline-block'); this.removeElement.style.setProperty('padding', '5px'); this.removeElement.appendChild(document.createTextNode('X')); this.inputElement.style.setProperty('height', '30px'); this.inputElement.style.setProperty('width', '350px'); this.skillElement.style.setProperty('height', '30px'); this.valueElement.style.setProperty('width', '40px'); this.valueElement.style.setProperty('height', '30px'); this.resultsElement.style.setProperty('position', 'relative'); this.resultsElement.style.setProperty('top', '30px;'); this.resultsElement.style.setProperty('min-height', '0px'); this.resultsElement.style.setProperty('max-height', '100px'); this.resultsElement.style.setProperty('transition', 'height 350ms ease'); this.resultsElement.style.setProperty('overflow-y', 'hidden'); this.resultsElement.style.setProperty('z-index', '99'); this.resultsElement.style.setProperty('background-color', '#222'); this.resultsElement.style.setProperty('border-radius', '5px'); this.parent.appendChild(this.inputElement); this.parent.appendChild(this.valueElement); this.parent.appendChild(this.skillElement); this.parent.appendChild(this.removeElement); this.parent.appendChild(this.resultsElement); this.inputElement.addEventListener("keyup", this.updateAutoComplete); this.inputElement.addEventListener("change", this.updateAutoComplete); this.inputElement.addEventListener("focusin", this.updateAutoComplete); this.inputElement.addEventListener("blur", (e) => { if (e.relatedTarget != null && this.db.findIndex(mod => this.inputElement.value.toLowerCase() == mod.toLowerCase()) == -1) { this.inputElement.value = ''; } this.updateAutoComplete(); }); this.removeElement.addEventListener("mousedown", (e) => this.parent.parentNode.removeChild(this.parent)); } getConfig = () => { let idx = this.db.findIndex(mod => this.inputElement.value.toLowerCase() == mod.toLowerCase()); let mod = this.db[idx]; if (activeModifiers[mod] !== undefined && this.parent.parentNode != null) { if (Array.isArray(activeModifiers[mod])) { return [mod, [parseInt(this.skillElement.value) || 0, parseInt(this.valueElement.value) || 0]]; } else { return [mod, parseInt(this.valueElement.value) || 0]; } } } updateSkill = () => { let idx = this.db.findIndex(mod => this.inputElement.value.toLowerCase() == mod.toLowerCase()); let mod = this.db[idx]; if (mod) { if (activeModifiers[mod] !== undefined) { if (Array.isArray(activeModifiers[mod])) { this.skillElement.style.setProperty('display', 'inline-block'); } else { this.skillElement.style.setProperty('display', 'none'); } } } } updateAutoComplete = e => { this.updateSkill(); this.resultsElement.innerHTML = ''; this.resultsElement.style.height = '0px'; if (!this.inputElement.value || this.db.findIndex(mod => this.inputElement.value == mod) != -1) return; var search = new RegExp(this.inputElement.value, "i"); let frag = document.createDocumentFragment(); this.db.forEach(mod => { if (search.test(mod)) { var div = document.createElement('div'); div.style.setProperty('height', '20px'); div.style.setProperty('width', '100%'); div.style.setProperty('text-align', 'left'); div.appendChild(document.createTextNode(mod)); div.addEventListener('mousedown', (e) => (this.inputElement.value = mod, this.resultsElement.innerHTML = '', this.resultsElement.style.height = '0px', this.inputElement.dispatchEvent(new Event('change')))); frag.appendChild(div); } }); if (frag.children.length > 1 || frag.children.length == 1 && frag.firstElementChild.innerText != this.inputElement.value) (this.resultsElement.style.height = '100px', this.resultsElement.appendChild(frag)) } } Object.entries(corruptionRollerSettings).forEach(([slot, settings]) => { let el = $(`#corruption-equipment-slot-${slot}`)[0]; if (!el) return; let btn = document.createElement('button'); btn.className = 'btn btn-sm btn-dual text-combat-smoke'; btn.id = `corruption-equipment-slot-${slot}-mods` /* */ tippy(btn, { allowHTML: true, onShow: (instance) => { let count = Math.min(corruptionRollerCount[slot] || 0, corruptionRollerSettings[slot].length); let html = `<h5 class="font-w600 font-size-sm mb-2">Corrupting for ${count} Modifier${count!=1?'s':''}</h5>`; html += corruptionRollerSettings[slot].map(([modifier, value]) => printPlayerModifier(modifier, value)) .map(mod => `<h5 class="font-w400 font-size-sm mb-1 ${mod[1]}">${mod[0]}</h5>`).join(''); instance.setContent(html); } }) btn.addEventListener('click', (e) => { e.preventDefault() e.stopPropagation(); let mods = []; let html = '' + '<div class="corruption-mods">' + ('<div class="corruption-mod-selector"></div>'.repeat(corruptionRollerSettings[slot].length)) + '</div>' + '<div class="corruption-mods-add">Add New</div>'; Swal.fire({ html: html, width: 700, onBeforeOpen: () => { mods = [...$('.corruption-mod-selector')].map((el, i) => new AutoComplete(el, Object.keys(activeModifiers), corruptionRollerSettings[slot][i])); $('.corruption-mods-add')[0].addEventListener('click', (e) => { let el = document.createElement('div'); el.className = 'corruption-mod-selector'; $('.corruption-mods')[0].appendChild(el); mods.push(new AutoComplete(el, Object.keys(activeModifiers))) }); }, preConfirm: () => { if (mods) return mods; } }).then(data => { if (data.isConfirmed) { corruptionRollerSettings[slot] = data.value.map(value => value.getConfig()).filter(v => v != null) } }); }); let img = document.createElement('img'); img.className = 'skill-icon-xxs'; img.src = 'assets/media/main/corruption.svg'; btn.appendChild(img); let count = document.createElement('select'); Array.from(Array(5)).map(count => document.createElement('option')).map((el, i) => (el.value = i, el.innerHTML = i, el)).forEach(el => count.appendChild(el)); count.value = corruptionRollerCount[slot]; count.addEventListener('click', (e) => (e.preventDefault(), e.stopPropagation())) count.addEventListener('change', (e) => corruptionRollerCount[slot] = parseInt(e.target.value)) btn.appendChild(count); //el.parentNode.firstElementChild.insertBefore(count, el.parentNode.firstElementChild.firstElementChild); el.parentNode.appendChild(btn) el.parentNode.appendChild(count); }); let hasMod = (slot, mod, value = 0) => Object.entries(randomModifiers.equipment[slot]).reduce((acc, [rMod, val]) => { let modCount = getRandomModifierMaxValue(Object.keys(randomModifiers.equipment[slot]).length) - 1; // Guess the tier from number of mods on the item? if (rMod != mod) return acc; if (Array.isArray(value) && Array.isArray(val) && value[0] != val[0][0] && value[0] != -1) // Wrong skill return acc; if (Math.min(modCount, (Array.isArray(value) ? value[1] : value)) > (Array.isArray(val) ? val[0][1] : val)) // Rolled value is too low return acc; return true; }, false); let hasQty = (slot) => equippedItems[slot] > 0 && getItemQtyRandomModifier(equippedItems[slot])[0] > 1; let hasGP = (slot) => gp >= getRandomModifierCost(slot) && equippedItems[slot] > 0 let corruptEquipment = () => { equippedItems.forEach((item, slot) => { if (randomModifiers.equipment[slot] == undefined || corruptionRollerSettings[slot] == undefined || corruptionRollerSettings[slot].length == 0 || corruptionRollerCount[slot] == 0) return; let modCount = corruptionRollerSettings[slot].map(([mod, val]) => hasMod(slot, mod, val)).filter(Boolean).length; if (modCount >= Math.min(corruptionRollerCount[slot] || 0, corruptionRollerSettings[slot].length)) return; if (hasQty(slot) && hasGP(slot)) getEquipmentCorruption(slot) }) }; setInterval(corruptEquipment, 100); let modal = new CorruptionModal(); [...$('#aprilfools2021-container .block-content > div.row > .col-12')].forEach((el, i) => el.addEventListener('click', () => modal.show(i))) } } function loadScript() { if ((window.isLoaded && !window.currentlyCatchingUp) || (typeof unsafeWindow !== 'undefined' && unsafeWindow.isLoaded && !unsafeWindow.currentlyCatchingUp)) { // Only load script after game has opened clearInterval(scriptLoader); injectScript(script); } } const scriptLoader = setInterval(loadScript, 200); })();