// ==UserScript== // @name MWI TaskManager // @namespace http://tampermonkey.net/ // @version 0.10 // @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 // @downloadURL none // ==/UserScript== (function () { 'use strict'; //configs const isShowIcon = true; const isShowDungeon = false; 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": "深渊小鬼", "zone": "/actions/combat/infernal_abyss", "dungeon": [ "/actions/combat/enchanted_fortress" ], "sortIndex": 11 }, "/monsters/aquahorse": { "en": "Aquahorse", "cn": "水马", "zone": "/actions/combat/aqua_planet", "dungeon": [ "/actions/combat/chimerical_den" ], "sortIndex": 3 }, "/monsters/black_bear": { "en": "Black Bear", "cn": "黑熊", "zone": "/actions/combat/bear_with_it", "dungeon": [ "/actions/combat/sinister_circus" ], "sortIndex": 8 }, "/monsters/gobo_boomy": { "en": "Boomy", "cn": "轰轰", "zone": "/actions/combat/gobo_planet", "dungeon": [ "/actions/combat/sinister_circus" ], "sortIndex": 5 }, "/monsters/butterjerry": { "en": "Butterjerry", "cn": "蝶鼠", "zone": "", "dungeon": [ "/actions/combat/chimerical_den" ], "sortIndex": -1 }, "/monsters/centaur_archer": { "en": "Centaur Archer", "cn": "半人马弓箭手", "zone": "/actions/combat/jungle_planet", "dungeon": [ "/actions/combat/chimerical_den" ], "sortIndex": 4 }, "/monsters/chronofrost_sorcerer": { "en": "Chronofrost Sorcerer", "cn": "霜时巫师", "zone": "/actions/combat/sorcerers_tower", "sortIndex": 7 }, "/monsters/crystal_colossus": { "en": "Crystal Colossus", "cn": "水晶巨像", "zone": "/actions/combat/golem_cave", "sortIndex": 9 }, "/monsters/demonic_overlord": { "en": "Demonic Overlord", "cn": "恶魔霸主", "zone": "/actions/combat/infernal_abyss", "sortIndex": 11 }, "/monsters/dusk_revenant": { "en": "Dusk Revenant", "cn": "黄昏亡灵", "zone": "/actions/combat/twilight_zone", "sortIndex": 10 }, "/monsters/elementalist": { "en": "Elementalist", "cn": "元素法师", "zone": "/actions/combat/sorcerers_tower", "dungeon": [ "/actions/combat/sinister_circus" ], "sortIndex": 7 }, "/monsters/enchanted_pawn": { "en": "Enchanted Pawn", "cn": "秘法之兵", "zone": "", "dungeon": [ "/actions/combat/enchanted_fortress" ], "sortIndex": -1 }, "/monsters/eye": { "en": "Eye", "cn": "独眼", "zone": "/actions/combat/planet_of_the_eyes", "dungeon": [ "/actions/combat/enchanted_fortress" ], "sortIndex": 6 }, "/monsters/eyes": { "en": "Eyes", "cn": "叠眼", "zone": "/actions/combat/planet_of_the_eyes", "dungeon": [ "/actions/combat/enchanted_fortress" ], "sortIndex": 6 }, "/monsters/flame_sorcerer": { "en": "Flame Sorcerer", "cn": "火焰巫师", "zone": "/actions/combat/sorcerers_tower", "dungeon": [ "/actions/combat/enchanted_fortress", "/actions/combat/sinister_circus" ], "sortIndex": 7 }, "/monsters/fly": { "en": "Fly", "cn": "苍蝇", "zone": "/actions/combat/smelly_planet", "sortIndex": 1 }, "/monsters/frog": { "en": "Frogger", "cn": "青蛙", "zone": "/actions/combat/swamp_planet", "dungeon": [ "/actions/combat/chimerical_den" ], "sortIndex": 2 }, "/monsters/sea_snail": { "en": "Gary", "cn": "蜗牛", "zone": "/actions/combat/aqua_planet", "sortIndex": 3 }, "/monsters/giant_shoebill": { "en": "Giant Shoebill", "cn": "鲸头鹳", "zone": "/actions/combat/swamp_planet", "sortIndex": 2 }, "/monsters/gobo_chieftain": { "en": "Gobo Chieftain", "cn": "哥布林酋长", "zone": "/actions/combat/gobo_planet", "sortIndex": 5 }, "/monsters/granite_golem": { "en": "Granite Golem", "cn": "花岗魔像", "zone": "/actions/combat/golem_cave", "sortIndex": 9 }, "/monsters/grizzly_bear": { "en": "Grizzly Bear", "cn": "棕熊", "zone": "/actions/combat/bear_with_it", "dungeon": [ "/actions/combat/sinister_circus" ], "sortIndex": 8 }, "/monsters/gummy_bear": { "en": "Gummy Bear", "cn": "软糖熊", "zone": "/actions/combat/bear_with_it", "dungeon": [ "/actions/combat/sinister_circus", "/actions/combat/chimerical_den" ], "sortIndex": 8 }, "/monsters/crab": { "en": "I Pinch", "cn": "螃蟹", "zone": "/actions/combat/aqua_planet", "sortIndex": 3 }, "/monsters/ice_sorcerer": { "en": "Ice Sorcerer", "cn": "冰霜巫师", "zone": "/actions/combat/sorcerers_tower", "dungeon": [ "/actions/combat/enchanted_fortress", "/actions/combat/sinister_circus" ], "sortIndex": 7 }, "/monsters/infernal_warlock": { "en": "Infernal Warlock", "cn": "地狱术士", "zone": "/actions/combat/infernal_abyss", "sortIndex": 11 }, "/monsters/jackalope": { "en": "Jackalope", "cn": "鹿角兔", "zone": "", "dungeon": [ "/actions/combat/chimerical_den" ], "sortIndex": -1 }, "/monsters/rat": { "en": "Jerry", "cn": "杰瑞", "zone": "/actions/combat/smelly_planet", "dungeon": [ "/actions/combat/chimerical_den" ], "sortIndex": 1 }, "/monsters/jungle_sprite": { "en": "Jungle Sprite", "cn": "丛林精灵", "zone": "/actions/combat/jungle_planet", "dungeon": [ "/actions/combat/chimerical_den" ], "sortIndex": 4 }, "/monsters/luna_empress": { "en": "Luna Empress", "cn": "月神之蝶", "zone": "/actions/combat/jungle_planet", "sortIndex": 4 }, "/monsters/magnetic_golem": { "en": "Magnetic Golem", "cn": "磁力魔像", "zone": "/actions/combat/golem_cave", "dungeon": [ "/actions/combat/enchanted_fortress" ], "sortIndex": 9 }, "/monsters/marine_huntress": { "en": "Marine Huntress", "cn": "海洋猎手", "zone": "/actions/combat/aqua_planet", "sortIndex": 3 }, "/monsters/myconid": { "en": "Myconid", "cn": "蘑菇人", "zone": "/actions/combat/jungle_planet", "sortIndex": 4 }, "/monsters/nom_nom": { "en": "Nom Nom", "cn": "咬咬鱼", "zone": "/actions/combat/aqua_planet", "sortIndex": 3 }, "/monsters/novice_sorcerer": { "en": "Novice Sorcerer", "cn": "新手巫师", "zone": "/actions/combat/sorcerers_tower", "dungeon": [ "/actions/combat/enchanted_fortress", "/actions/combat/sinister_circus" ], "sortIndex": 7 }, "/monsters/panda": { "en": "Panda", "cn": "熊猫", "zone": "/actions/combat/bear_with_it", "dungeon": [ "/actions/combat/sinister_circus" ], "sortIndex": 8 }, "/monsters/polar_bear": { "en": "Polar Bear", "cn": "北极熊", "zone": "/actions/combat/bear_with_it", "dungeon": [ "/actions/combat/sinister_circus" ], "sortIndex": 8 }, "/monsters/porcupine": { "en": "Porcupine", "cn": "豪猪", "zone": "/actions/combat/smelly_planet", "dungeon": [ "/actions/combat/chimerical_den" ], "sortIndex": 1 }, "/monsters/rabid_rabbit": { "en": "Rabid Rabbit", "cn": "疯魔兔", "zone": "", "dungeon": [ "/actions/combat/sinister_circus" ], "sortIndex": -1 }, "/monsters/red_panda": { "en": "Red Panda", "cn": "小熊猫", "zone": "/actions/combat/bear_with_it", "sortIndex": 8 }, "/monsters/alligator": { "en": "Sherlock", "cn": "夏洛克", "zone": "/actions/combat/swamp_planet", "sortIndex": 2 }, "/monsters/gobo_shooty": { "en": "Shooty", "cn": "射射", "zone": "/actions/combat/gobo_planet", "dungeon": [ "/actions/combat/sinister_circus" ], "sortIndex": 5 }, "/monsters/skunk": { "en": "Skunk", "cn": "臭鼬", "zone": "/actions/combat/smelly_planet", "sortIndex": 1 }, "/monsters/gobo_slashy": { "en": "Slashy", "cn": "割割", "zone": "/actions/combat/gobo_planet", "dungeon": [ "/actions/combat/sinister_circus" ], "sortIndex": 5 }, "/monsters/slimy": { "en": "Slimy", "cn": "史莱姆", "zone": "/actions/combat/smelly_planet", "sortIndex": 1 }, "/monsters/gobo_smashy": { "en": "Smashy", "cn": "锤锤", "zone": "/actions/combat/gobo_planet", "dungeon": [ "/actions/combat/sinister_circus" ], "sortIndex": 5 }, "/monsters/soul_hunter": { "en": "Soul Hunter", "cn": "灵魂猎手", "zone": "/actions/combat/infernal_abyss", "dungeon": [ "/actions/combat/enchanted_fortress" ], "sortIndex": 11 }, "/monsters/gobo_stabby": { "en": "Stabby", "cn": "刺刺", "zone": "/actions/combat/gobo_planet", "dungeon": [ "/actions/combat/sinister_circus" ], "sortIndex": 5 }, "/monsters/stalactite_golem": { "en": "Stalactite Golem", "cn": "钟乳石魔像", "zone": "/actions/combat/golem_cave", "dungeon": [ "/actions/combat/enchanted_fortress" ], "sortIndex": 9 }, "/monsters/swampy": { "en": "Swampy", "cn": "沼泽虫", "zone": "/actions/combat/swamp_planet", "dungeon": [ "/actions/combat/chimerical_den" ], "sortIndex": 2 }, "/monsters/the_watcher": { "en": "The Watcher", "cn": "观察者", "zone": "/actions/combat/planet_of_the_eyes", "sortIndex": 6 }, "/monsters/snake": { "en": "Thnake", "cn": "蛇", "zone": "/actions/combat/swamp_planet", "sortIndex": 2 }, "/monsters/treant": { "en": "Treant", "cn": "树人", "zone": "/actions/combat/jungle_planet", "sortIndex": 4 }, "/monsters/turtle": { "en": "Turuto", "cn": "忍者龟", "zone": "/actions/combat/aqua_planet", "sortIndex": 3 }, "/monsters/vampire": { "en": "Vampire", "cn": "吸血鬼", "zone": "/actions/combat/twilight_zone", "dungeon": [ "/actions/combat/sinister_circus" ], "sortIndex": 10 }, "/monsters/veyes": { "en": "Veyes", "cn": "复眼", "zone": "/actions/combat/planet_of_the_eyes", "dungeon": [ "/actions/combat/enchanted_fortress" ], "sortIndex": 6 }, "/monsters/werewolf": { "en": "Werewolf", "cn": "狼人", "zone": "/actions/combat/twilight_zone", "dungeon": [ "/actions/combat/sinister_circus" ], "sortIndex": 10 }, "/monsters/zombie": { "en": "Zombie", "cn": "僵尸", "zone": "/actions/combat/twilight_zone", "dungeon": [ "/actions/combat/sinister_circus" ], "sortIndex": 10 }, "/monsters/zombie_bear": { "en": "Zombie Bear", "cn": "僵尸熊", "zone": "", "dungeon": [ "/actions/combat/sinister_circus" ], "sortIndex": -1 } }; function getTaskDetailFromTaskName(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 getTaskDetailFromElement(ele) { const div = ele.querySelector("div.RandomTask_name__1hl1b"); const translatedfrom = div.getAttribute("script_translatedfrom"); //adapt old CN Script if (translatedfrom) { return getTaskDetailFromTaskName(translatedfrom); } const fullTaskName = Array.from(div.childNodes).find(node => node.nodeType === Node.TEXT_NODE).textContent.trim(); return getTaskDetailFromTaskName(fullTaskName); } function compareFn(a, b) { var { taskType: a_TypeIndex, taskName: a_taskName } = getTaskDetailFromElement(a); var { taskType: b_TypeIndex, taskName: b_TaskName } = getTaskDetailFromElement(b); 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(div); if (taskType != taskBattleIndex) { return; } const monsterHrid = getHridFromMonsterName(taskName); var offset = 5; // 5% from left and each 30% width if (!isShowDungeon) offset = 50; const backgroundDiv = document.createElement('div'); backgroundDiv.id = "MonsterIcon"; backgroundDiv.style.position = 'absolute'; backgroundDiv.style.left = `${offset}%`; offset += 30; backgroundDiv.style.width = '30%'; backgroundDiv.style.height = '100%'; backgroundDiv.style.opacity = '0.3'; const monsterName = monsterHrid.split("/").pop(); const svgContent = ``; backgroundDiv.innerHTML = svgContent; div.appendChild(backgroundDiv); const dungeonMap = allMonster[monsterHrid]?.dungeon; if (isShowDungeon && dungeonMap) { ["/actions/combat/chimerical_den", "/actions/combat/sinister_circus", "/actions/combat/enchanted_fortress"].forEach(dungeon => { if (dungeonMap.includes(dungeon)) { const dungeonDiv = document.createElement('div'); dungeonDiv.id = "DungeonIcon"; dungeonDiv.style.position = 'absolute'; dungeonDiv.style.left = `${offset}%`; offset += 30; dungeonDiv.style.width = '30%'; dungeonDiv.style.height = '100%'; dungeonDiv.style.opacity = '0.3'; const dungeonName = dungeon.split("/").pop(); const svgContent = ``; dungeonDiv.innerHTML = svgContent; div.appendChild(dungeonDiv); } }) } // fix button style div.style.position = 'relative'; 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); if (isShowIcon) 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); })();