Melvor Idle - AutoMastery

Automatically spends mastery when a pool is about to fill up

目前為 2020-12-03 提交的版本,檢視 最新版本

// ==UserScript==
// @name        Melvor Idle - AutoMastery
// @description Automatically spends mastery when a pool is about to fill up
// @version     2.2
// @namespace   Visua
// @match       https://melvoridle.com/*
// @match       https://www.melvoridle.com/*
// @grant       none
// ==/UserScript==
/* jshint esversion: 6 */

((main) => {
    var script = document.createElement('script');
    script.textContent = `try { (${main})(); } catch (e) { console.log(e); }`;
    document.body.appendChild(script).parentNode.removeChild(script);
})(() => {
    'use strict';

    function autoSpendMasteryPool(skill, xpToBeAdded) {
        const poolXp = MASTERY[skill].pool;
        const poolMax = getMasteryPoolTotalXP(skill);
        if (poolXp + xpToBeAdded >= poolMax) {
            const _masteryPoolLevelUp = masteryPoolLevelUp;
            masteryPoolLevelUp = 1;

            const xpOverCheckpoint = poolXp + xpToBeAdded - (poolMax * window.autoMasterySettings[skill].threshold) / 100;

            let masteryToLevel = -1;
            let reason = '';
            let masteries = [];

            if (Array.isArray(window.autoMasterySettings[skill].selectedMasteries)) {
                masteries = window.autoMasterySettings[skill].selectedMasteries.map(id => ({ id, xp: MASTERY[skill].xp[id] })).filter(m => m.xp < 13034432);
            }
            if (!masteries.length) {
                masteries = MASTERY[skill].xp.map((xp, id) => ({ id, xp }));
                masteryToLevel = window.autoMasterySelectedMasteries[skill];
                if (Number.isInteger(masteryToLevel) && masteryToLevel !== -1) {
                    if (getMasteryLevel(skill, masteryToLevel) >= 99 || getMasteryXpForNextLevel(skill, masteryToLevel) > poolXp) {
                        masteryToLevel = -1;
                    } else {
                        reason = 'was manually selected';
                    }
                } else {
                    masteryToLevel = -1;
                }
            }

            if (masteryToLevel === -1) {
                masteryToLevel = masteries
                    .reduce(
                        (best, m) => {
                            const toNext = getMasteryXpForNextLevel(skill, m.id);
                            if (toNext > 0 && toNext <= xpOverCheckpoint && (best.id === -1 || (window.autoMasterySettings[skill].selectLowest ? m.xp <= best.xp : m.xp >= best.xp))) {
                                return m;
                            } else {
                                return best;
                            }
                        },
                        { id: -1, xp: 0 }
                    ).id;
                reason = `was the ${window.autoMasterySettings[skill].selectLowest ? 'lowest' : 'highest'} that could be leveled without dropping below ${window.autoMasterySettings[skill].threshold}%`;
            }

            if (masteryToLevel === -1) {
                const min = masteries
                    .map(m => ({ id: m.id, toNext: getMasteryXpForNextLevel(skill, m.id) }))
                    .reduce((min, m) => ((m.toNext > 0 && m.toNext <= min.toNext) || min.toNext === 0 ? m : min));
                if (min.toNext > 0 && min.toNext < poolXp) {
                    masteryToLevel = min.id;
                    reason = `was the cheapest to level and we are forced to drop below ${window.autoMasterySettings[skill].threshold}%`;
                }
            }

            if (masteryToLevel !== -1) {
                const message = `AutoMastery: Leveled up ${getMasteryName(skill, masteryToLevel)} to ${getMasteryLevel(skill, masteryToLevel) + 1}`;
                const cost = getMasteryXpForNextLevel(skill, masteryToLevel);
                const details = `Earned ${numberWithCommas(xpToBeAdded.toFixed(3))} XP. Pool before: ${((poolXp / poolMax) * 100).toFixed(3)}%. Pool after: ${(((poolXp + xpToBeAdded - cost) / poolMax) * 100).toFixed(3)}%`;
                console.log(`${message} for ${numberWithCommas(Math.round(cost))} XP because it ${reason} (${details})`);
                autoMasteryNotify(message);
                const _showSpendMasteryXP = showSpendMasteryXP;
                showSpendMasteryXP = () => {};
                try {
                    levelUpMasteryWithPool(skill, masteryToLevel);
                } catch (e) {
                    console.error(e);
                } finally {
                    masteryPoolLevelUp = _masteryPoolLevelUp;
                    showSpendMasteryXP = _showSpendMasteryXP;
                }
                autoSpendMasteryPool(skill, xpToBeAdded);
            }
        }
    }

    function autoMasteryNotify(message) {
        Toastify({
            text: `<div class="text-center"><img class="notification-img" src="assets/media/main/mastery_pool.svg"><span class="badge badge-success">${message}</span></div>`,
            duration: 5000,
            gravity: 'bottom',
            position: 'center',
            backgroundColor: 'transparent',
            stopOnFocus: false,
        }).showToast();
    }

    function autoMastery() {
        window.autoMasterySettings = Object.keys(SKILLS).map(s => ({ threshold: 95, selectLowest: false, selectedMasteries: [] }));
        window.autoMasterySelectedMasteries = Array(Object.keys(SKILLS).length).fill(-1);

        const _addMasteryXPToPool = addMasteryXPToPool;
        addMasteryXPToPool = (...args) => {
            try {
                const skill = args[0];
                let xpToBeAdded = args[1];
                const token = args[3];
                if (xpToBeAdded > 0) {
                    if (skillLevel[skill] >= 99 && !token) {
                        xpToBeAdded /= 2;
                    } else if (!token) {
                        xpToBeAdded /= 4;
                    }
                    autoSpendMasteryPool(skill, xpToBeAdded);
                }
            } catch (e) {
                console.error(e);
            } finally {
                _addMasteryXPToPool(...args);
            }
        };
    }

    function loadScript() {
        if (typeof confirmedLoaded !== 'undefined' && confirmedLoaded && !currentlyCatchingUp) {
            clearInterval(interval);
            console.log('Loading AutoMastery');
            autoMastery();
        }
    }

    const interval = setInterval(loadScript, 500);
});

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址