Greasy Fork

Greasy Fork is available in English.

Real Profit Calculator

Calculates real NoRNG profit and exp gain for MWI battle emulator.

目前为 2025-05-18 提交的版本,查看 最新版本

// ==UserScript==
// @name         Real Profit Calculator
// @namespace    http://tampermonkey.net/
// @version      1.2
// @description  Calculates real NoRNG profit and exp gain for MWI battle emulator.
// @author       guch8017
// @match        https://shykai.github.io/MWICombatSimulatorTest/dist/
// @grant        GM_registerMenuCommand
// @grant        GM_setValue
// @grant        GM_getValue
// @license      MIT
// ==/UserScript==

(function () {
    'use strict';

    GM_registerMenuCommand("设置社区掉落增益", async function () {
        const currentRate = await GM_getValue('buffRate', 1.295);
        const input = prompt("Enter new Buff Rate:", currentRate);
        if (input !== null) {
            const parsed = parseFloat(input);
            if (!isNaN(parsed) && parsed > 0) {
                await GM_setValue('buffRate', parsed);
                alert(`Buff rate set to ${parsed}. Reload the page to see changes.`);
            } else {
                alert("Invalid input. Please enter a positive number.");
            }
        }
    });
    GM_registerMenuCommand("设置社区经验增益", async function () {
        const currentRate = await GM_getValue('expBuffRate', 0.295);
        const input = prompt("Enter new Exp Buff Rate:", currentRate);
        if (input !== null) {
            const parsed = parseFloat(input);
            if (!isNaN(parsed) && parsed > 0) {
                await GM_setValue('expBuffRate', parsed);
                alert(`Exp rate set to ${parsed}. Reload the page to see changes.`);
            } else {
                alert("Invalid input. Please enter a positive number.");
            }
        }
    });

    const eliteMapExpBonus = {
        "/actions/combat/smelly_planet_elite": 0.1,
        "/actions/combat/swamp_planet_elite": 0.1,
        "/actions/combat/aqua_planet_elite": 0.1,
        "/actions/combat/jungle_planet_elite": 0.1,
        "/actions/combat/gobo_planet_elite": 0.15,
        "/actions/combat/planet_of_the_eyes_elite": 0.15,
        "/actions/combat/sorcerers_tower_elite": 0.15,
        "/actions/combat/bear_with_it_elite": 0.15,
        "/actions/combat/golem_cave_elite": 0.2,
        "/actions/combat/twilight_zone_elite": 0.2,
        "/actions/combat/infernal_abyss_elite": 0.2,
    }

    const enhancementLevelTotalMultiplierTable = [0, 1, 2.1, 3.3, 4.6, 6, 7.5, 9.1, 10.8, 12.600000000000001, 14.500000000000002, 16.5, 18.6, 20.8, 23.1, 25.5, 28, 30.6, 33.300000000000004, 36.1, 39];

    // function waitForElement(selector, callback) {
    //     const observer = new MutationObserver(() => {
    //         const el = document.querySelector(selector);
    //         if (el) {
    //             observer.disconnect();
    //             callback(el);
    //         }
    //     });
    //     observer.observe(document.body, { childList: true, subtree: true });
    // }

    function parseNumber(text) {
        const numericText = text.replace(/[^\d.,\-]/g, '').replace(/,/g, '');
        return parseFloat(numericText);
    }

    function getDrinkConcentration(level) {
        return 0.1 + 0.002 * (enhancementLevelTotalMultiplierTable[level] || 0);
    }

    function getWisdomNeckBonus(level) {
        return 0.03 + 0.003 * (enhancementLevelTotalMultiplierTable[level] || 0);
    }

    async function calculateProfit() {
        const expenseText = document.getElementById('script_expense')?.textContent || '';
        const noRngProfitText = document.getElementById('noRngProfitPreview')?.textContent || '';

        const expense = parseNumber(expenseText);
        const noRngProfit = parseNumber(noRngProfitText);
        const buffRate = await GM_getValue('buffRate', 1.295);

        if (!isNaN(expense) && !isNaN(noRngProfit)) {
            const realProfit = ((noRngProfit + expense) * 1.295) - expense;
            const formattedProfit = realProfit.toLocaleString(undefined, { maximumFractionDigits: 3 });

            const existingDiv = document.getElementById('realProfitDisplay');
            if (existingDiv) {
                existingDiv.textContent = `实际期望利润: ${formattedProfit}`;
                return;
            }

            const displayDiv = document.createElement('div');
            displayDiv.id = 'realProfitDisplay';
            displayDiv.style.backgroundColor = '#FFD700';
            displayDiv.style.color = 'black';
            displayDiv.style.fontWeight = 'bold';
            displayDiv.style.padding = '4px';
            displayDiv.textContent = `实际期望利润: ${formattedProfit}`;

            const targetDiv = document.getElementById('noRngProfitPreview').parentElement.parentElement;
            targetDiv.parentNode.insertBefore(displayDiv, targetDiv.nextSibling);
        }
    }

    async function calculateExp() {
        let expBonus = 0;
        // 判断精英地图加成
        const mapSelected = document.querySelector("#selectZone").value;
        const isEliteMap = mapSelected.includes("elite");
        if (isEliteMap) {
            let mapBonus = eliteMapExpBonus[mapSelected];
            if (mapBonus === undefined) {
                console.error(`No bonus found for elite map: ${mapSelected}`);
            } else {
                expBonus = mapBonus;
            }
        }
        // 判断咖啡加成,同时计算暴饮带来的额外增益
        let coffeeBonus = 0;
        for (let drinkId = 0; drinkId < 3; drinkId++) {
            const drink = document.querySelector(`#selectDrink_${drinkId}`);
            if (drink && drink.value === "/items/wisdom_coffee") {
                coffeeBonus += 0.12;
            }
        }
        const pouchSel = document.querySelector("#selectEquipment_pouch");
        if (pouchSel && pouchSel.value === "/items/guzzling_pouch") {
            const pouchEnhanceLv = Number.parseInt(document.querySelector("#inputEquipmentEnhancementLevel_pouch").value) || 0;
            const pouchConcentration = getDrinkConcentration(pouchEnhanceLv);
            coffeeBonus *= pouchConcentration;
        }
        expBonus += coffeeBonus;
        // 判断经验项链加成
        if (document.querySelector("#selectEquipment_neck").value === "/items/necklace_of_wisdom") {
            const neckEnhanceLv = Number.parseInt(document.querySelector("#inputEquipmentEnhancementLevel_neck").value) || 0;
            expBonus += getWisdomNeckBonus(neckEnhanceLv);
        }
        // 判断房屋加成
        let houseTotalLv = 0;
        for (const houseLv of document.querySelectorAll('input[data-house-hrid]')) {
            houseTotalLv += Number.parseInt(houseLv.value) || 0;
        }
        expBonus += houseTotalLv * 0.0005;
        // 读取经验值
        const expRateBonus = await GM_getValue('expBuffRate', 0.295);
        for (let node of document.querySelector("#simulationResultExperienceGain").childNodes) {
            node = node.childNodes[1];
            let expCurrent = Number.parseInt(node.innerText);
            let expNew = Math.floor(expCurrent / (1 + expBonus) * (1 + expBonus + 0.295));
            node.innerText = `(${expNew})${expCurrent}`;
        }
    }

    const obConfig = {characterData: true, subtree: true, childList: true};
    const ProfitNode = document.getElementById('noRngProfitPreview');
    const ExpNode = document.getElementById('simulationResultExperienceGain');

    new MutationObserver(() => {calculateProfit();}).observe(ProfitNode, obConfig);
    const expObserver = new MutationObserver(() => {
        expObserver.disconnect();
        calculateExp();
        expObserver.observe(ExpNode, obConfig);
    });
    expObserver.observe(ExpNode, obConfig)
})();