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