Melvor Corruption Roller

Bloop Bleep. I roll for corruptions.

Du musst eine Erweiterung wie Tampermonkey, Greasemonkey oder Violentmonkey installieren, um dieses Skript zu installieren.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

Sie müssten eine Skript Manager Erweiterung installieren damit sie dieses Skript installieren können

(Ich habe schon ein Skript Manager, Lass mich es installieren!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==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);
})();