MWI TaskManager

sort all task in taskpanel

目前为 2025-03-03 提交的版本。查看 最新版本

// ==UserScript==
// @name         MWI TaskManager
// @namespace    http://tampermonkey.net/
// @version      0.8
// @description  sort all task in taskpanel
// @author       shykai
// @match        https://www.milkywayidle.com/*
// @match        https://test.milkywayidle.com/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=milkywayidle.com
// @grant        none
// ==/UserScript==

(function () {
    'use strict';

    const taskBattleIndex = 99; //Battle at bottom
    const taskOrderIndex = {
        Milking: 1,
        Foraging: 2,
        Woodcutting: 3,
        Cheesesmithing: 4,
        Crafting: 5,
        Tailoring: 6,
        Cooking: 7,
        Brewing: 8,
        Alchemy: 9,
        Enhancing: 10,
        Defeat: taskBattleIndex, //Battle at bottom
    };
    const taskOrderIndex_CN = {
        挤奶: 1,
        采摘: 2,
        伐木: 3,
        奶酪锻造: 4,
        制作: 5,
        缝纫: 6,
        烹饪: 7,
        冲泡: 8,
        炼金: 9,
        强化: 10,
        击败: taskBattleIndex, //Battle at bottom
    };

    const allMonster = {
        "/monsters/abyssal_imp": {
            "en": "Abyssal Imp",
            "cn": "深渊小鬼",
            "sortIndex": 11
        },
        "/monsters/aquahorse": {
            "en": "Aquahorse",
            "cn": "水马",
            "sortIndex": 3
        },
        "/monsters/black_bear": {
            "en": "Black Bear",
            "cn": "黑熊",
            "sortIndex": 8
        },
        "/monsters/gobo_boomy": {
            "en": "Boomy",
            "cn": "轰轰",
            "sortIndex": 5
        },
        "/monsters/centaur_archer": {
            "en": "Centaur Archer",
            "cn": "半人马弓箭手",
            "sortIndex": 4
        },
        "/monsters/chronofrost_sorcerer": {
            "en": "Chronofrost Sorcerer",
            "cn": "霜时巫师",
            "sortIndex": 7
        },
        "/monsters/crystal_colossus": {
            "en": "Crystal Colossus",
            "cn": "水晶巨像",
            "sortIndex": 9
        },
        "/monsters/demonic_overlord": {
            "en": "Demonic Overlord",
            "cn": "恶魔霸主",
            "sortIndex": 11
        },
        "/monsters/dusk_revenant": {
            "en": "Dusk Revenant",
            "cn": "黄昏亡灵",
            "sortIndex": 10
        },
        "/monsters/elementalist": {
            "en": "Elementalist",
            "cn": "元素法师",
            "sortIndex": 7
        },
        "/monsters/eye": {
            "en": "Eye",
            "cn": "独眼",
            "sortIndex": 6
        },
        "/monsters/eyes": {
            "en": "Eyes",
            "cn": "叠眼",
            "sortIndex": 6
        },
        "/monsters/flame_sorcerer": {
            "en": "Flame Sorcerer",
            "cn": "火焰巫师",
            "sortIndex": 7
        },
        "/monsters/frog": {
            "en": "Frogger",
            "cn": "青蛙",
            "sortIndex": 2
        },
        "/monsters/sea_snail": {
            "en": "Gary",
            "cn": "蜗牛",
            "sortIndex": 3
        },
        "/monsters/giant_shoebill": {
            "en": "Giant Shoebill",
            "cn": "鲸头鹳",
            "sortIndex": 2
        },
        "/monsters/gobo_chieftain": {
            "en": "Gobo Chieftain",
            "cn": "哥布林酋长",
            "sortIndex": 5
        },
        "/monsters/granite_golem": {
            "en": "Granite Golem",
            "cn": "花岗魔像",
            "sortIndex": 9
        },
        "/monsters/grizzly_bear": {
            "en": "Grizzly Bear",
            "cn": "棕熊",
            "sortIndex": 8
        },
        "/monsters/gummy_bear": {
            "en": "Gummy Bear",
            "cn": "软糖熊",
            "sortIndex": 8
        },
        "/monsters/crab": {
            "en": "I Pinch",
            "cn": "螃蟹",
            "sortIndex": 3
        },
        "/monsters/ice_sorcerer": {
            "en": "Ice Sorcerer",
            "cn": "冰霜巫师",
            "sortIndex": 7
        },
        "/monsters/infernal_warlock": {
            "en": "Infernal Warlock",
            "cn": "地狱术士",
            "sortIndex": 11
        },
        "/monsters/jungle_sprite": {
            "en": "Jungle Sprite",
            "cn": "丛林精灵",
            "sortIndex": 4
        },
        "/monsters/luna_empress": {
            "en": "Luna Empress",
            "cn": "月神之蝶",
            "sortIndex": 4
        },
        "/monsters/magnetic_golem": {
            "en": "Magnetic Golem",
            "cn": "磁力魔像",
            "sortIndex": 9
        },
        "/monsters/marine_huntress": {
            "en": "Marine Huntress",
            "cn": "海洋猎手",
            "sortIndex": 3
        },
        "/monsters/myconid": {
            "en": "Myconid",
            "cn": "蘑菇人",
            "sortIndex": 4
        },
        "/monsters/nom_nom": {
            "en": "Nom Nom",
            "cn": "咬咬鱼",
            "sortIndex": 3
        },
        "/monsters/novice_sorcerer": {
            "en": "Novice Sorcerer",
            "cn": "新手巫师",
            "sortIndex": 7
        },
        "/monsters/panda": {
            "en": "Panda",
            "cn": "熊猫",
            "sortIndex": 8
        },
        "/monsters/polar_bear": {
            "en": "Polar Bear",
            "cn": "北极熊",
            "sortIndex": 8
        },
        "/monsters/red_panda": {
            "en": "Red Panda",
            "cn": "小熊猫",
            "sortIndex": 8
        },
        "/monsters/alligator": {
            "en": "Sherlock",
            "cn": "夏洛克",
            "sortIndex": 2
        },
        "/monsters/gobo_shooty": {
            "en": "Shooty",
            "cn": "射射",
            "sortIndex": 5
        },
        "/monsters/gobo_slashy": {
            "en": "Slashy",
            "cn": "割割",
            "sortIndex": 5
        },
        "/monsters/gobo_smashy": {
            "en": "Smashy",
            "cn": "锤锤",
            "sortIndex": 5
        },
        "/monsters/soul_hunter": {
            "en": "Soul Hunter",
            "cn": "灵魂猎手",
            "sortIndex": 11
        },
        "/monsters/gobo_stabby": {
            "en": "Stabby",
            "cn": "刺刺",
            "sortIndex": 5
        },
        "/monsters/stalactite_golem": {
            "en": "Stalactite Golem",
            "cn": "钟乳石魔像",
            "sortIndex": 9
        },
        "/monsters/swampy": {
            "en": "Swampy",
            "cn": "沼泽虫",
            "sortIndex": 2
        },
        "/monsters/the_watcher": {
            "en": "The Watcher",
            "cn": "观察者",
            "sortIndex": 6
        },
        "/monsters/snake": {
            "en": "Thnake",
            "cn": "蛇",
            "sortIndex": 2
        },
        "/monsters/treant": {
            "en": "Treant",
            "cn": "树人",
            "sortIndex": 4
        },
        "/monsters/turtle": {
            "en": "Turuto",
            "cn": "忍者龟",
            "sortIndex": 3
        },
        "/monsters/vampire": {
            "en": "Vampire",
            "cn": "吸血鬼",
            "sortIndex": 10
        },
        "/monsters/veyes": {
            "en": "Veyes",
            "cn": "复眼",
            "sortIndex": 6
        },
        "/monsters/werewolf": {
            "en": "Werewolf",
            "cn": "狼人",
            "sortIndex": 10
        },
        "/monsters/zombie": {
            "en": "Zombie",
            "cn": "僵尸",
            "sortIndex": 10
        }
    };

    function getTaskDetailFromElement(fullTaskName) {
        var taskType = -1;
        var taskName = "";

        if (/^(.+) - (.+)$/.test(fullTaskName)) {
            let res = /^(.+) - (.+)$/.exec(fullTaskName);
            if (res[1] in taskOrderIndex) {
                taskType = taskOrderIndex[res[1]];
            }
            else if (res[1] in taskOrderIndex_CN) {
                taskType = taskOrderIndex_CN[res[1]];
            }
            taskName = res[2];
        }
        if (taskType == -1) console.log(fullTaskName, taskType);

        return { taskType, taskName };
    }

    function getMapIndexFromTaskName(name) {
        for (let key in allMonster) {
            if (allMonster[key].en === name || allMonster[key].cn === name) {
                return allMonster[key].sortIndex;
            }
        }
        return -1;
    }

    function compareFn(a, b) {
        var { taskType: a_TypeIndex, taskName: a_taskName } = getTaskDetailFromElement(Array.from(a.querySelector("div.RandomTask_name__1hl1b").childNodes).find(node => node.nodeType === Node.TEXT_NODE).textContent.trim());

        var { taskType: b_TypeIndex, taskName: b_TaskName } = getTaskDetailFromElement(Array.from(b.querySelector("div.RandomTask_name__1hl1b").childNodes).find(node => node.nodeType === Node.TEXT_NODE).textContent.trim());

        if (a_TypeIndex === taskBattleIndex && b_TypeIndex === taskBattleIndex) {
            var a_MapIndex = getMapIndexFromTaskName(a_taskName);
            var b_MapIndex = getMapIndexFromTaskName(b_TaskName);

            if (a_MapIndex != b_MapIndex) {
                return (a_MapIndex > b_MapIndex ? 1 : -1);
            }
        }

        if (a_TypeIndex == b_TypeIndex) {
            return a_taskName == b_TaskName ? 0
                : (a_taskName > b_TaskName ? 1 : -1);
        }

        return a_TypeIndex > b_TypeIndex ? 1 : -1;
    }

    function getHridFromMonsterName(name) {
        for (let key in allMonster) {
            if (allMonster[key].en === name || allMonster[key].cn === name) {
                return key;
            }
        }
    }

    function addIconToTask(div) {
        var { taskType, taskName } = getTaskDetailFromElement(Array.from(div.querySelector("div.RandomTask_name__1hl1b").childNodes).find(node => node.nodeType === Node.TEXT_NODE).textContent.trim());

        if (taskType != taskBattleIndex) {
            return;
        }

        const monsterHrid = getHridFromMonsterName(taskName);
        const monsterName = monsterHrid.split("/").pop();

        const backgroundDiv = document.createElement('div');
        backgroundDiv.style.position = 'absolute';
        backgroundDiv.style.left = '5%';
        backgroundDiv.style.width = '30%';
        backgroundDiv.style.height = '100%';
        backgroundDiv.style.opacity = '0.3';

        const svgContent = `<svg width="100%" height="100%"><use href="/static/media/combat_monsters_sprite.395438a8.svg#${monsterName}"></use></svg>`;
        backgroundDiv.innerHTML = svgContent;

        div.style.position = 'relative';
        div.appendChild(backgroundDiv);

        div.querySelector(".RandomTask_content__VVQva").style.zIndex = 1;
        div.querySelectorAll(".Item_item__2De2O").forEach(node => node.style.backgroundColor = "transparent");
    }

    function addButton() {
        const targetNode = document.querySelector("div.TasksPanel_taskSlotCount__nfhgS");
        if (targetNode) {
            let sortButton = targetNode.querySelector("#TaskSort");
            if (!sortButton) {
                sortButton = document.createElement("button");
                sortButton.setAttribute("class", "Button_button__1Fe9z Button_small__3fqC7");
                sortButton.id = "TaskSort";
                sortButton.innerHTML = "TaskSort";
                sortButton.addEventListener("click", function (evt) {
                    const list = document.querySelector("div.TasksPanel_taskList__2xh4k");
                    [...list.querySelectorAll("div.RandomTask_randomTask__3B9fA")]
                        .sort(compareFn)
                        .forEach(node => list.appendChild(node));
                });
                targetNode.appendChild(sortButton);
                document.querySelectorAll("div.TasksPanel_taskList__2xh4k div.RandomTask_randomTask__3B9fA").forEach(node => addIconToTask(node));
            }
        }
    }

    const config = { attributes: true, childList: true, subtree: true };

    const observer = new MutationObserver(function (mutationsList, observer) {
        addButton();
    });

    observer.observe(document, config);

})();

QingJ © 2025

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