Melvor Corruption Roller

Bloop Bleep. I roll for corruptions.

Bu betiği kurabilmeniz için Tampermonkey, Greasemonkey ya da Violentmonkey gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

Bu betiği yüklemek için Tampermonkey gibi bir uzantı yüklemeniz gerekir.

Bu betiği kurabilmeniz için Tampermonkey ya da Violentmonkey gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

Bu betiği kurabilmeniz için Tampermonkey ya da Userscripts gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

Bu betiği indirebilmeniz için ayrıca Tampermonkey gibi bir eklenti kurmanız gerekmektedir.

Bu komut dosyasını yüklemek için bir kullanıcı komut dosyası yöneticisi uzantısı yüklemeniz gerekecek.

(Zaten bir kullanıcı komut dosyası yöneticim var, kurmama izin verin!)

Bu stili yüklemek için Stylus gibi bir uzantı yüklemeniz gerekir.

Bu stili yüklemek için Stylus gibi bir uzantı kurmanız gerekir.

Bu stili yükleyebilmek için Stylus gibi bir uzantı yüklemeniz gerekir.

Bu stili yüklemek için bir kullanıcı stili yöneticisi uzantısı yüklemeniz gerekir.

Bu stili yüklemek için bir kullanıcı stili yöneticisi uzantısı kurmanız gerekir.

Bu stili yükleyebilmek için bir kullanıcı stili yöneticisi uzantısı yüklemeniz gerekir.

(Zateb bir user-style yöneticim var, yükleyeyim!)

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