// ==UserScript==
// @name [银河奶牛]食用工具
// @namespace http://tampermonkey.net/
// @version 0.468
// @description 开箱记录、箱子期望、离线统计、公会钉钉、食物警察、掉落追踪、强化统计
// @author Truth_Light
// @license Truth_Light
// @match https://www.milkywayidle.com/*
// @match https://test.milkywayidle.com/*
// @icon https://www.milkywayidle.com/favicon.svg
// @connect raw.githubusercontent.com
// @grant GM.xmlHttpRequest
// @grant GM_registerMenuCommand
// @grant GM_openInTab
// @grant GM_setValue
// @grant GM_getValue
// @downloadURL none
// ==/UserScript==
(async function() {
'use strict';
const isCN = !['en'].some(lang =>localStorage.getItem("i18nextLng")?.toLowerCase()?.startsWith(lang));
const itemSelector = '.ItemDictionary_drop__24I5f';
const iconSelector = '.Icon_icon__2LtL_ use';
const chestNameSelector = '#root > div > div > div.Modal_modalContainer__3B80m > div.Modal_modal__1Jiep > div.ItemDictionary_modalContent__WvEBY > div.ItemDictionary_itemAndDescription__28_he > div.Item_itemContainer__x7kH1 > div > div > div > svg > use';
const MARKET_API_URL = "https://raw.githubusercontent.com/holychikenz/MWIApi/main/medianmarket.json";
let timer = null;
let formattedChestDropData = {};
let battlePlayerFood = {};
let battlePlayerLoot = {};
let battlePlayerData = {};
let battlePlayerFoodConsumable = {};
let battleDuration;
let battleRunCount;
let now_battle_map;
let enhancementLevel;
let currentEnhancingIndex = 1;
let enhancementData = {
[currentEnhancingIndex]: { "强化数据": {}, "其他数据": {} }
};
let currentPlayerID = null;
let currentPlayerName = null;
let item_icon_url
let processCombatConsumablesRunCount = 0;
let marketData = JSON.parse(localStorage.getItem('MWITools_marketAPI_json'));
const init_Client_Data = localStorage.getItem('initClientData');
if (!init_Client_Data) return;
let init_Client_Data_;
try {
init_Client_Data_ = JSON.parse(init_Client_Data);
} catch (error) {
console.error('数据解析失败:', error);
return;
}
if (init_Client_Data_.type !== 'init_client_data') return;
const item_hrid_to_name = {};
for (const key in init_Client_Data_.itemDetailMap) {
const item = init_Client_Data_.itemDetailMap[key];
if (item && typeof item === 'object' && item.name) {
item_hrid_to_name[key] = item.name;
}
}
const item_name_to_hrid = Object.fromEntries(
Object.entries(item_hrid_to_name).map(([key, value]) => [value, key])
);
const e2c = {
"Coin": "金币",
"Task Token": "任务代币",
"Chimerical Token": "奇幻代币",
"Sinister Token": "阴森代币",
"Enchanted Token": "秘法代币",
"Pirate Token": "海盗代币",
"Cowbell": "牛铃",
"Bag Of 10 Cowbells": "牛铃袋 (10个)",
"Purple's Gift": "小紫牛的礼物",
"Small Meteorite Cache": "小陨石舱",
"Medium Meteorite Cache": "中陨石舱",
"Large Meteorite Cache": "大陨石舱",
"Small Artisan's Crate": "小工匠匣",
"Medium Artisan's Crate": "中工匠匣",
"Large Artisan's Crate": "大工匠匣",
"Small Treasure Chest": "小宝箱",
"Medium Treasure Chest": "中宝箱",
"Large Treasure Chest": "大宝箱",
"Chimerical Chest": "奇幻宝箱",
"Sinister Chest": "阴森宝箱",
"Enchanted Chest": "秘法宝箱",
"Pirate Chest": "海盗宝箱",
"Blue Key Fragment": "蓝色钥匙碎片",
"Green Key Fragment": "绿色钥匙碎片",
"Purple Key Fragment": "紫色钥匙碎片",
"White Key Fragment": "白色钥匙碎片",
"Orange Key Fragment": "橙色钥匙碎片",
"Brown Key Fragment": "棕色钥匙碎片",
"Stone Key Fragment": "石头钥匙碎片",
"Dark Key Fragment": "黑暗钥匙碎片",
"Burning Key Fragment": "燃烧钥匙碎片",
"Chimerical Entry Key": "奇幻钥匙",
"Chimerical Chest Key": "奇幻宝箱钥匙",
"Sinister Entry Key": "阴森钥匙",
"Sinister Chest Key": "阴森宝箱钥匙",
"Enchanted Entry Key": "秘法钥匙",
"Enchanted Chest Key": "秘法宝箱钥匙",
"Pirate Entry Key": "海盗钥匙",
"Pirate Chest Key": "海盗宝箱钥匙",
"Donut": "甜甜圈",
"Blueberry Donut": "蓝莓甜甜圈",
"Blackberry Donut": "黑莓甜甜圈",
"Strawberry Donut": "草莓甜甜圈",
"Mooberry Donut": "哞莓甜甜圈",
"Marsberry Donut": "火星莓甜甜圈",
"Spaceberry Donut": "太空莓甜甜圈",
"Cupcake": "纸杯蛋糕",
"Blueberry Cake": "蓝莓蛋糕",
"Blackberry Cake": "黑莓蛋糕",
"Strawberry Cake": "草莓蛋糕",
"Mooberry Cake": "哞莓蛋糕",
"Marsberry Cake": "火星莓蛋糕",
"Spaceberry Cake": "太空莓蛋糕",
"Gummy": "软糖",
"Apple Gummy": "苹果软糖",
"Orange Gummy": "橙子软糖",
"Plum Gummy": "李子软糖",
"Peach Gummy": "桃子软糖",
"Dragon Fruit Gummy": "火龙果软糖",
"Star Fruit Gummy": "杨桃软糖",
"Yogurt": "酸奶",
"Apple Yogurt": "苹果酸奶",
"Orange Yogurt": "橙子酸奶",
"Plum Yogurt": "李子酸奶",
"Peach Yogurt": "桃子酸奶",
"Dragon Fruit Yogurt": "火龙果酸奶",
"Star Fruit Yogurt": "杨桃酸奶",
"Milking Tea": "挤奶茶",
"Foraging Tea": "采摘茶",
"Woodcutting Tea": "伐木茶",
"Cooking Tea": "烹饪茶",
"Brewing Tea": "冲泡茶",
"Alchemy Tea": "炼金茶",
"Enhancing Tea": "强化茶",
"Cheesesmithing Tea": "奶酪锻造茶",
"Crafting Tea": "制作茶",
"Tailoring Tea": "缝纫茶",
"Super Milking Tea": "超级挤奶茶",
"Super Foraging Tea": "超级采摘茶",
"Super Woodcutting Tea": "超级伐木茶",
"Super Cooking Tea": "超级烹饪茶",
"Super Brewing Tea": "超级冲泡茶",
"Super Alchemy Tea": "超级炼金茶",
"Super Enhancing Tea": "超级强化茶",
"Super Cheesesmithing Tea": "超级奶酪锻造茶",
"Super Crafting Tea": "超级制作茶",
"Super Tailoring Tea": "超级缝纫茶",
"Ultra Milking Tea": "究极挤奶茶",
"Ultra Foraging Tea": "究极采摘茶",
"Ultra Woodcutting Tea": "究极伐木茶",
"Ultra Cooking Tea": "究极烹饪茶",
"Ultra Brewing Tea": "究极冲泡茶",
"Ultra Alchemy Tea": "究极炼金茶",
"Ultra Enhancing Tea": "究极强化茶",
"Ultra Cheesesmithing Tea": "究极奶酪锻造茶",
"Ultra Crafting Tea": "究极制作茶",
"Ultra Tailoring Tea": "究极缝纫茶",
"Gathering Tea": "采集茶",
"Gourmet Tea": "美食茶",
"Wisdom Tea": "经验茶",
"Processing Tea": "加工茶",
"Efficiency Tea": "效率茶",
"Artisan Tea": "工匠茶",
"Catalytic Tea": "催化茶",
"Blessed Tea": "福气茶",
"Stamina Coffee": "耐力咖啡",
"Intelligence Coffee": "智力咖啡",
"Defense Coffee": "防御咖啡",
"Attack Coffee": "攻击咖啡",
"Power Coffee": "力量咖啡",
"Ranged Coffee": "远程咖啡",
"Magic Coffee": "魔法咖啡",
"Super Stamina Coffee": "超级耐力咖啡",
"Super Intelligence Coffee": "超级智力咖啡",
"Super Defense Coffee": "超级防御咖啡",
"Super Attack Coffee": "超级攻击咖啡",
"Super Power Coffee": "超级力量咖啡",
"Super Ranged Coffee": "超级远程咖啡",
"Super Magic Coffee": "超级魔法咖啡",
"Ultra Stamina Coffee": "究极耐力咖啡",
"Ultra Intelligence Coffee": "究极智力咖啡",
"Ultra Defense Coffee": "究极防御咖啡",
"Ultra Attack Coffee": "究极攻击咖啡",
"Ultra Power Coffee": "究极力量咖啡",
"Ultra Ranged Coffee": "究极远程咖啡",
"Ultra Magic Coffee": "究极魔法咖啡",
"Wisdom Coffee": "经验咖啡",
"Lucky Coffee": "幸运咖啡",
"Swiftness Coffee": "迅捷咖啡",
"Channeling Coffee": "吟唱咖啡",
"Critical Coffee": "暴击咖啡",
"Poke": "破胆之刺",
"Impale": "透骨之刺",
"Puncture": "破甲之刺",
"Penetrating Strike": "贯心之刺",
"Scratch": "爪影斩",
"Cleave": "分裂斩",
"Maim": "血刃斩",
"Crippling Slash": "致残斩",
"Smack": "重碾",
"Sweep": "重扫",
"Stunning Blow": "重锤",
"Fracturing Impact": "碎裂冲击",
"Shield Bash": "盾击",
"Quick Shot": "快速射击",
"Aqua Arrow": "流水箭",
"Flame Arrow": "烈焰箭",
"Rain Of Arrows": "箭雨",
"Silencing Shot": "沉默之箭",
"Steady Shot": "稳定射击",
"Pestilent Shot": "疫病射击",
"Penetrating Shot": "贯穿射击",
"Water Strike": "流水冲击",
"Ice Spear": "冰枪术",
"Frost Surge": "冰霜爆裂",
"Mana Spring": "法力喷泉",
"Entangle": "缠绕",
"Toxic Pollen": "剧毒粉尘",
"Nature's Veil": "自然菌幕",
"Life Drain": "生命吸取",
"Fireball": "火球",
"Flame Blast": "熔岩爆裂",
"Firestorm": "火焰风暴",
"Smoke Burst": "烟爆灭影",
"Minor Heal": "初级自愈术",
"Heal": "自愈术",
"Quick Aid": "快速治疗术",
"Rejuvenate": "群体治疗术",
"Taunt": "嘲讽",
"Provoke": "挑衅",
"Toughness": "坚韧",
"Elusiveness": "闪避",
"Precision": "精确",
"Berserk": "狂暴",
"Elemental Affinity": "元素增幅",
"Frenzy": "狂速",
"Spike Shell": "尖刺防护",
"Arcane Reflection": "奥术反射",
"Vampirism": "吸血",
"Revive": "复活",
"Insanity": "疯狂",
"Invincible": "无敌",
"Fierce Aura": "物理光环",
"Aqua Aura": "流水光环",
"Sylvan Aura": "自然光环",
"Flame Aura": "火焰光环",
"Speed Aura": "速度光环",
"Critical Aura": "暴击光环",
"Gobo Stabber": "哥布林长剑",
"Gobo Slasher": "哥布林关刀",
"Gobo Smasher": "哥布林狼牙棒",
"Spiked Bulwark": "尖刺重盾",
"Werewolf Slasher": "狼人关刀",
"Griffin Bulwark": "狮鹫重盾",
"Gobo Shooter": "哥布林弹弓",
"Vampiric Bow": "吸血弓",
"Cursed Bow": "咒怨之弓",
"Gobo Boomstick": "哥布林火棍",
"Cheese Bulwark": "奶酪重盾",
"Verdant Bulwark": "翠绿重盾",
"Azure Bulwark": "蔚蓝重盾",
"Burble Bulwark": "深紫重盾",
"Crimson Bulwark": "绛红重盾",
"Rainbow Bulwark": "彩虹重盾",
"Holy Bulwark": "神圣重盾",
"Wooden Bow": "木弓",
"Birch Bow": "桦木弓",
"Cedar Bow": "雪松弓",
"Purpleheart Bow": "紫心弓",
"Ginkgo Bow": "银杏弓",
"Redwood Bow": "红杉弓",
"Arcane Bow": "神秘弓",
"Stalactite Spear": "石钟长枪",
"Granite Bludgeon": "花岗岩大棒",
"Furious Spear": "狂怒长枪",
"Regal Sword": "君王之剑",
"Chaotic Flail": "混沌连枷",
"Soul Hunter Crossbow": "灵魂猎手弩",
"Sundering Crossbow": "裂空之弩",
"Frost Staff": "冰霜法杖",
"Infernal Battlestaff": "炼狱法杖",
"Jackalope Staff": "鹿角兔之杖",
"Rippling Trident": "涟漪三叉戟",
"Blooming Trident": "绽放三叉戟",
"Blazing Trident": "炽焰三叉戟",
"Cheese Sword": "奶酪剑",
"Verdant Sword": "翠绿剑",
"Azure Sword": "蔚蓝剑",
"Burble Sword": "深紫剑",
"Crimson Sword": "绛红剑",
"Rainbow Sword": "彩虹剑",
"Holy Sword": "神圣剑",
"Cheese Spear": "奶酪长枪",
"Verdant Spear": "翠绿长枪",
"Azure Spear": "蔚蓝长枪",
"Burble Spear": "深紫长枪",
"Crimson Spear": "绛红长枪",
"Rainbow Spear": "彩虹长枪",
"Holy Spear": "神圣长枪",
"Cheese Mace": "奶酪钉头锤",
"Verdant Mace": "翠绿钉头锤",
"Azure Mace": "蔚蓝钉头锤",
"Burble Mace": "深紫钉头锤",
"Crimson Mace": "绛红钉头锤",
"Rainbow Mace": "彩虹钉头锤",
"Holy Mace": "神圣钉头锤",
"Wooden Crossbow": "木弩",
"Birch Crossbow": "桦木弩",
"Cedar Crossbow": "雪松弩",
"Purpleheart Crossbow": "紫心弩",
"Ginkgo Crossbow": "银杏弩",
"Redwood Crossbow": "红杉弩",
"Arcane Crossbow": "神秘弩",
"Wooden Water Staff": "木制水法杖",
"Birch Water Staff": "桦木水法杖",
"Cedar Water Staff": "雪松水法杖",
"Purpleheart Water Staff": "紫心水法杖",
"Ginkgo Water Staff": "银杏水法杖",
"Redwood Water Staff": "红杉水法杖",
"Arcane Water Staff": "神秘水法杖",
"Wooden Nature Staff": "木制自然法杖",
"Birch Nature Staff": "桦木自然法杖",
"Cedar Nature Staff": "雪松自然法杖",
"Purpleheart Nature Staff": "紫心自然法杖",
"Ginkgo Nature Staff": "银杏自然法杖",
"Redwood Nature Staff": "红杉自然法杖",
"Arcane Nature Staff": "神秘自然法杖",
"Wooden Fire Staff": "木制火法杖",
"Birch Fire Staff": "桦木火法杖",
"Cedar Fire Staff": "雪松火法杖",
"Purpleheart Fire Staff": "紫心火法杖",
"Ginkgo Fire Staff": "银杏火法杖",
"Redwood Fire Staff": "红杉火法杖",
"Arcane Fire Staff": "神秘火法杖",
"Eye Watch": "掌上监工",
"Snake Fang Dirk": "蛇牙短剑",
"Vision Shield": "视觉盾",
"Gobo Defender": "哥布林防御者",
"Vampire Fang Dirk": "吸血鬼短剑",
"Knight's Aegis": "骑士盾",
"Treant Shield": "树人盾",
"Manticore Shield": "蝎狮盾",
"Tome Of Healing": "治疗之书",
"Tome Of The Elements": "元素之书",
"Watchful Relic": "警戒遗物",
"Bishop's Codex": "主教法典",
"Cheese Buckler": "奶酪圆盾",
"Verdant Buckler": "翠绿圆盾",
"Azure Buckler": "蔚蓝圆盾",
"Burble Buckler": "深紫圆盾",
"Crimson Buckler": "绛红圆盾",
"Rainbow Buckler": "彩虹圆盾",
"Holy Buckler": "神圣圆盾",
"Wooden Shield": "木盾",
"Birch Shield": "桦木盾",
"Cedar Shield": "雪松盾",
"Purpleheart Shield": "紫心盾",
"Ginkgo Shield": "银杏盾",
"Redwood Shield": "红杉盾",
"Arcane Shield": "神秘盾",
"Sinister Cape": "阴森斗篷",
"Chimerical Quiver": "奇幻箭袋",
"Enchanted Cloak": "秘法披风",
"Red Culinary Hat": "红色厨师帽",
"Snail Shell Helmet": "蜗牛壳头盔",
"Vision Helmet": "视觉头盔",
"Fluffy Red Hat": "蓬松红帽子",
"Corsair Helmet": "掠夺者头盔",
"Acrobatic Hood": "杂技师兜帽",
"Magician's Hat": "魔术师帽",
"Cheese Helmet": "奶酪头盔",
"Verdant Helmet": "翠绿头盔",
"Azure Helmet": "蔚蓝头盔",
"Burble Helmet": "深紫头盔",
"Crimson Helmet": "绛红头盔",
"Rainbow Helmet": "彩虹头盔",
"Holy Helmet": "神圣头盔",
"Rough Hood": "粗糙兜帽",
"Reptile Hood": "爬行动物兜帽",
"Gobo Hood": "哥布林兜帽",
"Beast Hood": "野兽兜帽",
"Umbral Hood": "暗影兜帽",
"Cotton Hat": "棉帽",
"Linen Hat": "亚麻帽",
"Bamboo Hat": "竹帽",
"Silk Hat": "丝帽",
"Radiant Hat": "光辉帽",
"Dairyhand's Top": "挤奶工上衣",
"Forager's Top": "采摘者上衣",
"Lumberjack's Top": "伐木工上衣",
"Cheesemaker's Top": "奶酪师上衣",
"Crafter's Top": "工匠上衣",
"Tailor's Top": "裁缝上衣",
"Chef's Top": "厨师上衣",
"Brewer's Top": "饮品师上衣",
"Alchemist's Top": "炼金师上衣",
"Enhancer's Top": "强化师上衣",
"Gator Vest": "鳄鱼马甲",
"Turtle Shell Body": "龟壳胸甲",
"Colossus Plate Body": "巨像胸甲",
"Demonic Plate Body": "恶魔胸甲",
"Anchorbound Plate Body": "锚定胸甲",
"Maelstrom Plate Body": "怒涛胸甲",
"Marine Tunic": "海洋皮衣",
"Revenant Tunic": "亡灵皮衣",
"Griffin Tunic": "狮鹫皮衣",
"Kraken Tunic": "克拉肯皮衣",
"Icy Robe Top": "冰霜袍服",
"Flaming Robe Top": "烈焰袍服",
"Luna Robe Top": "月神袍服",
"Royal Water Robe Top": "皇家水系袍服",
"Royal Nature Robe Top": "皇家自然系袍服",
"Royal Fire Robe Top": "皇家火系袍服",
"Cheese Plate Body": "奶酪胸甲",
"Verdant Plate Body": "翠绿胸甲",
"Azure Plate Body": "蔚蓝胸甲",
"Burble Plate Body": "深紫胸甲",
"Crimson Plate Body": "绛红胸甲",
"Rainbow Plate Body": "彩虹胸甲",
"Holy Plate Body": "神圣胸甲",
"Rough Tunic": "粗糙皮衣",
"Reptile Tunic": "爬行动物皮衣",
"Gobo Tunic": "哥布林皮衣",
"Beast Tunic": "野兽皮衣",
"Umbral Tunic": "暗影皮衣",
"Cotton Robe Top": "棉布袍服",
"Linen Robe Top": "亚麻袍服",
"Bamboo Robe Top": "竹袍服",
"Silk Robe Top": "丝绸袍服",
"Radiant Robe Top": "光辉袍服",
"Dairyhand's Bottoms": "挤奶工下装",
"Forager's Bottoms": "采摘者下装",
"Lumberjack's Bottoms": "伐木工下装",
"Cheesemaker's Bottoms": "奶酪师下装",
"Crafter's Bottoms": "工匠下装",
"Tailor's Bottoms": "裁缝下装",
"Chef's Bottoms": "厨师下装",
"Brewer's Bottoms": "饮品师下装",
"Alchemist's Bottoms": "炼金师下装",
"Enhancer's Bottoms": "强化师下装",
"Turtle Shell Legs": "龟壳腿甲",
"Colossus Plate Legs": "巨像腿甲",
"Demonic Plate Legs": "恶魔腿甲",
"Anchorbound Plate Legs": "锚定腿甲",
"Maelstrom Plate Legs": "怒涛腿甲",
"Marine Chaps": "航海皮裤",
"Revenant Chaps": "亡灵皮裤",
"Griffin Chaps": "狮鹫皮裤",
"Kraken Chaps": "克拉肯皮裤",
"Icy Robe Bottoms": "冰霜袍裙",
"Flaming Robe Bottoms": "烈焰袍裙",
"Luna Robe Bottoms": "月神袍裙",
"Royal Water Robe Bottoms": "皇家水系袍裙",
"Royal Nature Robe Bottoms": "皇家自然系袍裙",
"Royal Fire Robe Bottoms": "皇家火系袍裙",
"Cheese Plate Legs": "奶酪腿甲",
"Verdant Plate Legs": "翠绿腿甲",
"Azure Plate Legs": "蔚蓝腿甲",
"Burble Plate Legs": "深紫腿甲",
"Crimson Plate Legs": "绛红腿甲",
"Rainbow Plate Legs": "彩虹腿甲",
"Holy Plate Legs": "神圣腿甲",
"Rough Chaps": "粗糙皮裤",
"Reptile Chaps": "爬行动物皮裤",
"Gobo Chaps": "哥布林皮裤",
"Beast Chaps": "野兽皮裤",
"Umbral Chaps": "暗影皮裤",
"Cotton Robe Bottoms": "棉袍裙",
"Linen Robe Bottoms": "亚麻袍裙",
"Bamboo Robe Bottoms": "竹袍裙",
"Silk Robe Bottoms": "丝绸袍裙",
"Radiant Robe Bottoms": "光辉袍裙",
"Enchanted Gloves": "附魔手套",
"Pincer Gloves": "蟹钳手套",
"Panda Gloves": "熊猫手套",
"Magnetic Gloves": "磁力手套",
"Dodocamel Gauntlets": "渡渡驼护手",
"Sighted Bracers": "瞄准护腕",
"Marksman Bracers": "神射护腕",
"Chrono Gloves": "时空手套",
"Cheese Gauntlets": "奶酪护手",
"Verdant Gauntlets": "翠绿护手",
"Azure Gauntlets": "蔚蓝护手",
"Burble Gauntlets": "深紫护手",
"Crimson Gauntlets": "绛红护手",
"Rainbow Gauntlets": "彩虹护手",
"Holy Gauntlets": "神圣护手",
"Rough Bracers": "粗糙护腕",
"Reptile Bracers": "爬行动物护腕",
"Gobo Bracers": "哥布林护腕",
"Beast Bracers": "野兽护腕",
"Umbral Bracers": "暗影护腕",
"Cotton Gloves": "棉手套",
"Linen Gloves": "亚麻手套",
"Bamboo Gloves": "竹手套",
"Silk Gloves": "丝手套",
"Radiant Gloves": "光辉手套",
"Collector's Boots": "收藏家靴",
"Shoebill Shoes": "鲸头鹳鞋",
"Black Bear Shoes": "黑熊鞋",
"Grizzly Bear Shoes": "棕熊鞋",
"Polar Bear Shoes": "北极熊鞋",
"Centaur Boots": "半人马靴",
"Sorcerer Boots": "巫师靴",
"Cheese Boots": "奶酪靴",
"Verdant Boots": "翠绿靴",
"Azure Boots": "蔚蓝靴",
"Burble Boots": "深紫靴",
"Crimson Boots": "绛红靴",
"Rainbow Boots": "彩虹靴",
"Holy Boots": "神圣靴",
"Rough Boots": "粗糙靴",
"Reptile Boots": "爬行动物靴",
"Gobo Boots": "哥布林靴",
"Beast Boots": "野兽靴",
"Umbral Boots": "暗影靴",
"Cotton Boots": "棉靴",
"Linen Boots": "亚麻靴",
"Bamboo Boots": "竹靴",
"Silk Boots": "丝靴",
"Radiant Boots": "光辉靴",
"Small Pouch": "小袋子",
"Medium Pouch": "中袋子",
"Large Pouch": "大袋子",
"Giant Pouch": "巨大袋子",
"Gluttonous Pouch": "贪食之袋",
"Guzzling Pouch": "暴饮之囊",
"Necklace Of Efficiency": "效率项链",
"Fighter Necklace": "战士项链",
"Ranger Necklace": "射手项链",
"Wizard Necklace": "巫师项链",
"Necklace Of Wisdom": "经验项链",
"Necklace Of Speed": "速度项链",
"Philosopher's Necklace": "贤者项链",
"Earrings Of Gathering": "采集耳环",
"Earrings Of Essence Find": "精华发现耳环",
"Earrings Of Armor": "护甲耳环",
"Earrings Of Regeneration": "恢复耳环",
"Earrings Of Resistance": "抗性耳环",
"Earrings Of Rare Find": "稀有发现耳环",
"Earrings Of Critical Strike": "暴击耳环",
"Philosopher's Earrings": "贤者耳环",
"Ring Of Gathering": "采集戒指",
"Ring Of Essence Find": "精华发现戒指",
"Ring Of Armor": "护甲戒指",
"Ring Of Regeneration": "恢复戒指",
"Ring Of Resistance": "抗性戒指",
"Ring Of Rare Find": "稀有发现戒指",
"Ring Of Critical Strike": "暴击戒指",
"Philosopher's Ring": "贤者戒指",
"Basic Task Badge": "基础任务徽章",
"Advanced Task Badge": "高级任务徽章",
"Expert Task Badge": "专家任务徽章",
"Celestial Brush": "星空刷子",
"Cheese Brush": "奶酪刷子",
"Verdant Brush": "翠绿刷子",
"Azure Brush": "蔚蓝刷子",
"Burble Brush": "深紫刷子",
"Crimson Brush": "绛红刷子",
"Rainbow Brush": "彩虹刷子",
"Holy Brush": "神圣刷子",
"Celestial Shears": "星空剪刀",
"Cheese Shears": "奶酪剪刀",
"Verdant Shears": "翠绿剪刀",
"Azure Shears": "蔚蓝剪刀",
"Burble Shears": "深紫剪刀",
"Crimson Shears": "绛红剪刀",
"Rainbow Shears": "彩虹剪刀",
"Holy Shears": "神圣剪刀",
"Celestial Hatchet": "星空斧头",
"Cheese Hatchet": "奶酪斧头",
"Verdant Hatchet": "翠绿斧头",
"Azure Hatchet": "蔚蓝斧头",
"Burble Hatchet": "深紫斧头",
"Crimson Hatchet": "绛红斧头",
"Rainbow Hatchet": "彩虹斧头",
"Holy Hatchet": "神圣斧头",
"Celestial Hammer": "星空锤子",
"Cheese Hammer": "奶酪锤子",
"Verdant Hammer": "翠绿锤子",
"Azure Hammer": "蔚蓝锤子",
"Burble Hammer": "深紫锤子",
"Crimson Hammer": "绛红锤子",
"Rainbow Hammer": "彩虹锤子",
"Holy Hammer": "神圣锤子",
"Celestial Chisel": "星空凿子",
"Cheese Chisel": "奶酪凿子",
"Verdant Chisel": "翠绿凿子",
"Azure Chisel": "蔚蓝凿子",
"Burble Chisel": "深紫凿子",
"Crimson Chisel": "绛红凿子",
"Rainbow Chisel": "彩虹凿子",
"Holy Chisel": "神圣凿子",
"Celestial Needle": "星空针",
"Cheese Needle": "奶酪针",
"Verdant Needle": "翠绿针",
"Azure Needle": "蔚蓝针",
"Burble Needle": "深紫针",
"Crimson Needle": "绛红针",
"Rainbow Needle": "彩虹针",
"Holy Needle": "神圣针",
"Celestial Spatula": "星空锅铲",
"Cheese Spatula": "奶酪锅铲",
"Verdant Spatula": "翠绿锅铲",
"Azure Spatula": "蔚蓝锅铲",
"Burble Spatula": "深紫锅铲",
"Crimson Spatula": "绛红锅铲",
"Rainbow Spatula": "彩虹锅铲",
"Holy Spatula": "神圣锅铲",
"Celestial Pot": "星空壶",
"Cheese Pot": "奶酪壶",
"Verdant Pot": "翠绿壶",
"Azure Pot": "蔚蓝壶",
"Burble Pot": "深紫壶",
"Crimson Pot": "绛红壶",
"Rainbow Pot": "彩虹壶",
"Holy Pot": "神圣壶",
"Celestial Alembic": "星空蒸馏器",
"Cheese Alembic": "奶酪蒸馏器",
"Verdant Alembic": "翠绿蒸馏器",
"Azure Alembic": "蔚蓝蒸馏器",
"Burble Alembic": "深紫蒸馏器",
"Crimson Alembic": "绛红蒸馏器",
"Rainbow Alembic": "彩虹蒸馏器",
"Holy Alembic": "神圣蒸馏器",
"Celestial Enhancer": "星空强化器",
"Cheese Enhancer": "奶酪强化器",
"Verdant Enhancer": "翠绿强化器",
"Azure Enhancer": "蔚蓝强化器",
"Burble Enhancer": "深紫强化器",
"Crimson Enhancer": "绛红强化器",
"Rainbow Enhancer": "彩虹强化器",
"Holy Enhancer": "神圣强化器",
"Milk": "牛奶",
"Verdant Milk": "翠绿牛奶",
"Azure Milk": "蔚蓝牛奶",
"Burble Milk": "深紫牛奶",
"Crimson Milk": "绛红牛奶",
"Rainbow Milk": "彩虹牛奶",
"Holy Milk": "神圣牛奶",
"Cheese": "奶酪",
"Verdant Cheese": "翠绿奶酪",
"Azure Cheese": "蔚蓝奶酪",
"Burble Cheese": "深紫奶酪",
"Crimson Cheese": "绛红奶酪",
"Rainbow Cheese": "彩虹奶酪",
"Holy Cheese": "神圣奶酪",
"Log": "原木",
"Birch Log": "白桦原木",
"Cedar Log": "雪松原木",
"Purpleheart Log": "紫心原木",
"Ginkgo Log": "银杏原木",
"Redwood Log": "红杉原木",
"Arcane Log": "神秘原木",
"Lumber": "木板",
"Birch Lumber": "白桦木板",
"Cedar Lumber": "雪松木板",
"Purpleheart Lumber": "紫心木板",
"Ginkgo Lumber": "银杏木板",
"Redwood Lumber": "红杉木板",
"Arcane Lumber": "神秘木板",
"Rough Hide": "粗糙兽皮",
"Reptile Hide": "爬行动物皮",
"Gobo Hide": "哥布林皮",
"Beast Hide": "野兽皮",
"Umbral Hide": "暗影皮",
"Rough Leather": "粗糙皮革",
"Reptile Leather": "爬行动物皮革",
"Gobo Leather": "哥布林皮革",
"Beast Leather": "野兽皮革",
"Umbral Leather": "暗影皮革",
"Cotton": "棉花",
"Flax": "亚麻",
"Bamboo Branch": "竹子",
"Cocoon": "蚕茧",
"Radiant Fiber": "光辉纤维",
"Cotton Fabric": "棉花布料",
"Linen Fabric": "亚麻布料",
"Bamboo Fabric": "竹子布料",
"Silk Fabric": "丝绸",
"Radiant Fabric": "光辉布料",
"Egg": "鸡蛋",
"Wheat": "小麦",
"Sugar": "糖",
"Blueberry": "蓝莓",
"Blackberry": "黑莓",
"Strawberry": "草莓",
"Mooberry": "哞莓",
"Marsberry": "火星莓",
"Spaceberry": "太空莓",
"Apple": "苹果",
"Orange": "橙子",
"Plum": "李子",
"Peach": "桃子",
"Dragon Fruit": "火龙果",
"Star Fruit": "杨桃",
"Arabica Coffee Bean": "低级咖啡豆",
"Robusta Coffee Bean": "中级咖啡豆",
"Liberica Coffee Bean": "高级咖啡豆",
"Excelsa Coffee Bean": "特级咖啡豆",
"Fieriosa Coffee Bean": "火山咖啡豆",
"Spacia Coffee Bean": "太空咖啡豆",
"Green Tea Leaf": "绿茶叶",
"Black Tea Leaf": "黑茶叶",
"Burble Tea Leaf": "紫茶叶",
"Moolong Tea Leaf": "哞龙茶叶",
"Red Tea Leaf": "红茶叶",
"Emp Tea Leaf": "虚空茶叶",
"Catalyst Of Coinification": "点金催化剂",
"Catalyst Of Decomposition": "分解催化剂",
"Catalyst Of Transmutation": "转化催化剂",
"Prime Catalyst": "至高催化剂",
"Snake Fang": "蛇牙",
"Shoebill Feather": "鲸头鹳羽毛",
"Snail Shell": "蜗牛壳",
"Crab Pincer": "蟹钳",
"Turtle Shell": "乌龟壳",
"Marine Scale": "海洋鳞片",
"Treant Bark": "树皮",
"Centaur Hoof": "半人马蹄",
"Luna Wing": "月神翼",
"Gobo Rag": "哥布林抹布",
"Goggles": "护目镜",
"Magnifying Glass": "放大镜",
"Eye Of The Watcher": "观察者之眼",
"Icy Cloth": "冰霜织物",
"Flaming Cloth": "烈焰织物",
"Sorcerer's Sole": "魔法师鞋底",
"Chrono Sphere": "时空球",
"Frost Sphere": "冰霜球",
"Panda Fluff": "熊猫绒",
"Black Bear Fluff": "黑熊绒",
"Grizzly Bear Fluff": "棕熊绒",
"Polar Bear Fluff": "北极熊绒",
"Red Panda Fluff": "小熊猫绒",
"Magnet": "磁铁",
"Stalactite Shard": "钟乳石碎片",
"Living Granite": "花岗岩",
"Colossus Core": "巨像核心",
"Vampire Fang": "吸血鬼之牙",
"Werewolf Claw": "狼人之爪",
"Revenant Anima": "亡者之魂",
"Soul Fragment": "灵魂碎片",
"Infernal Ember": "地狱余烬",
"Demonic Core": "恶魔核心",
"Griffin Leather": "狮鹫之皮",
"Manticore Sting": "蝎狮之刺",
"Jackalope Antler": "鹿角兔之角",
"Dodocamel Plume": "渡渡驼之翎",
"Griffin Talon": "狮鹫之爪",
"Acrobat's Ribbon": "杂技师彩带",
"Magician's Cloth": "魔术师织物",
"Chaotic Chain": "混沌锁链",
"Cursed Ball": "诅咒之球",
"Royal Cloth": "皇家织物",
"Knight's Ingot": "骑士之锭",
"Bishop's Scroll": "主教卷轴",
"Regal Jewel": "君王宝石",
"Sundering Jewel": "裂空宝石",
"Marksman Brooch": "神射胸针",
"Corsair Crest": "掠夺者徽章",
"Damaged Anchor": "破损船锚",
"Maelstrom Plating": "怒涛甲片",
"Kraken Leather": "克拉肯皮革",
"Kraken Fang": "克拉肯之牙",
"Butter Of Proficiency": "精通之油",
"Thread Of Expertise": "专精之线",
"Branch Of Insight": "洞察之枝",
"Gluttonous Energy": "贪食能量",
"Guzzling Energy": "暴饮能量",
"Milking Essence": "挤奶精华",
"Foraging Essence": "采摘精华",
"Woodcutting Essence": "伐木精华",
"Cheesesmithing Essence": "奶酪锻造精华",
"Crafting Essence": "制作精华",
"Tailoring Essence": "缝纫精华",
"Cooking Essence": "烹饪精华",
"Brewing Essence": "冲泡精华",
"Alchemy Essence": "炼金精华",
"Enhancing Essence": "强化精华",
"Swamp Essence": "沼泽精华",
"Aqua Essence": "海洋精华",
"Jungle Essence": "丛林精华",
"Gobo Essence": "哥布林精华",
"Eyessence": "眼精华",
"Sorcerer Essence": "法师精华",
"Bear Essence": "熊熊精华",
"Golem Essence": "魔像精华",
"Twilight Essence": "暮光精华",
"Abyssal Essence": "地狱精华",
"Chimerical Essence": "奇幻精华",
"Sinister Essence": "阴森精华",
"Enchanted Essence": "秘法精华",
"Pirate Essence": "海盗精华",
"Task Crystal": "任务水晶",
"Star Fragment": "星光碎片",
"Pearl": "珍珠",
"Amber": "琥珀",
"Garnet": "石榴石",
"Jade": "翡翠",
"Amethyst": "紫水晶",
"Moonstone": "月亮石",
"Sunstone": "太阳石",
"Philosopher's Stone": "贤者之石",
"Crushed Pearl": "珍珠碎片",
"Crushed Amber": "琥珀碎片",
"Crushed Garnet": "石榴石碎片",
"Crushed Jade": "翡翠碎片",
"Crushed Amethyst": "紫水晶碎片",
"Crushed Moonstone": "月亮石碎片",
"Crushed Sunstone": "太阳石碎片",
"Crushed Philosopher's Stone": "贤者之石碎片",
"Shard Of Protection": "保护碎片",
"Mirror Of Protection": "保护之镜"
}
let specialItemPrices = {
'Coin': { ask: 1, bid: 1 }, // 默认的特殊物品价值,包括 ask 和 bid 价值
'Cowbell': {
ask: getSpecialItemPrice('Bag Of 10 Cowbells', 'ask') / 10 || 21000,
bid: getSpecialItemPrice('Bag Of 10 Cowbells', 'bid') / 10 || 20500
},
'Chimerical Token': {
ask: getSpecialItemPrice('Chimerical Essence', 'ask') || 600,
bid: getSpecialItemPrice('Chimerical Essence', 'bid') || 600
},
'Sinister Token': {
ask: getSpecialItemPrice('Sinister Essence', 'ask') || 900,
bid: getSpecialItemPrice('Sinister Essence', 'bid') || 900
},
'Enchanted Token': {
ask: getSpecialItemPrice('Enchanted Essence', 'ask') || 2000,
bid: getSpecialItemPrice('Enchanted Essence', 'bid') || 2000
},
'Pirate Token': {
ask: getSpecialItemPrice('Pirate Essence', 'ask') || 4000,
bid: getSpecialItemPrice('Pirate Essence', 'bid') || 4000
},
'Chimerical Quiver': {
ask: 1440*getSpecialItemPrice('Chimerical Essence', 'ask') || 1440*600,
bid: 1440*getSpecialItemPrice('Chimerical Essence', 'bid') || 1440*600
},
'Sinister Cape': {
ask: 1440*getSpecialItemPrice('Sinister Essence', 'ask') || 1440*900,
bid: 1440*getSpecialItemPrice('Sinister Essence', 'bid') || 1440*900
},
'Enchanted Cloak': {
ask: 1440*getSpecialItemPrice('Enchanted Essence', 'ask') || 1440*2000,
bid: 1440*getSpecialItemPrice('Enchanted Essence', 'bid') || 1440*2000
},
};
const chestCosts = {
"Chimerical Chest": {
keyAsk: getSpecialItemPrice('Chimerical Chest Key', 'ask') || 3000e3,
keyBid: getSpecialItemPrice('Chimerical Chest Key', 'bid') || 3000e3,
entryAsk: getSpecialItemPrice('Chimerical Entry Key', 'ask') || 280e3,
entryBid: getSpecialItemPrice('Chimerical Entry Key', 'bid') || 280e3
},
"Sinister Chest": {
keyAsk: getSpecialItemPrice('Sinister Chest Key', 'ask') || 5600e3,
keyBid: getSpecialItemPrice('Sinister Chest Key', 'bid') || 5400e3,
entryAsk: getSpecialItemPrice('Sinister Entry Key', 'ask') || 300e3,
entryBid: getSpecialItemPrice('Sinister Entry Key', 'bid') || 280e3
},
"Enchanted Chest": {
keyAsk: getSpecialItemPrice('Enchanted Chest Key', 'ask') || 7600e3,
keyBid: getSpecialItemPrice('Enchanted Chest Key', 'bid') || 7200e3,
entryAsk: getSpecialItemPrice('Enchanted Entry Key', 'ask') || 360e3,
entryBid: getSpecialItemPrice('Enchanted Entry Key', 'bid') || 360e3
},
"Pirate Chest": {
keyAsk: getSpecialItemPrice('Pirate Chest Key', 'ask') || 9400e3,
keyBid: getSpecialItemPrice('Pirate Chest Key', 'bid') || 92000e3,
entryAsk: getSpecialItemPrice('Pirate Entry Key', 'ask') || 460e3,
entryBid: getSpecialItemPrice('Pirate Entry Key', 'bid') || 440e3
}
};
const auraAbilities = new Set([
'revive',
'insanity',
'invincible',
'fierce_aura',
'aqua_aura',
'sylvan_aura',
'flame_aura',
'speed_aura',
'critical_aura'
]);
//公会部分代码
const updataDealy = 24*60*60*1000; //数据更新时限
let rateXPDayMap = {};
async function fetchMarketData() {
return new Promise((resolve, reject) => {
GM.xmlHttpRequest({
method: 'GET',
url: MARKET_API_URL,
responseType: 'json',
timeout: 5000,
onload: function(response) {
if (response.status === 200) {
const data = JSON.parse(response.responseText);
console.log('从API获取到的数据:', data);
resolve(data);
} else {
console.error('获取数据失败。状态码:', response.status);
reject(new Error('数据获取失败'));
}
},
ontimeout: function() {
console.error('请求超时:超过5秒未能获取到数据');
reject(new Error('请求超时'));
},
onerror: function(error) {
console.error('获取数据时发生错误:', error);
reject(error);
}
});
});
}
hookWS();
initObserver();
try {
// 尝试从 API 获取数据
marketData = await fetchMarketData();
marketData.market.Coin.ask = 1;
marketData.market.Coin.bid = 1;
} catch (error) {
console.error('从 API 获取数据失败,尝试从本地存储获取数据。', error);
// 从本地存储获取数据
const marketDataStr = localStorage.getItem('MWITools_marketAPI_json');
marketData = JSON.parse(marketDataStr);
if (!marketData) {
alert('无法获取 market 数据');
} else {
console.log('从本地存储获取到的数据:', marketData);
}
}
function getSpecialItemPrice(itemName, priceType) {
if (marketData?.market?.[itemName]) {
const itemPrice = marketData.market[itemName][priceType];
if (itemPrice !== undefined && itemPrice !== -1) {
return itemPrice;
}
} else if (specialItemPrices?.[itemName]) {
const itemPrice = specialItemPrices[itemName][priceType];
if (itemPrice !== undefined && itemPrice !== -1) {
return itemPrice;
}
}
console.error(`未找到物品 ${itemName} 的 ${priceType} 价格信息`);
return null;
}
function getItemNameFromElement(element) {
const itemNameRaw = element.getAttribute('href').split('#').pop();
return formatItemName(itemNameRaw);
}
function formatItemName(itemNameRaw) {
return item_hrid_to_name[`/items/${itemNameRaw}`]
}
function formatPrice(value,n = 1) {
const isNegative = value < 0;
value = Math.abs(value);
if (value >= 1e13 / n) {
return (isNegative ? '-' : '') + (value / 1e12).toFixed(1) + 'T';
} else if (value >= 1e10 / n) {
return (isNegative ? '-' : '') + (value / 1e9).toFixed(1) + 'B';
} else if (value >= 1e7 / n) {
return (isNegative ? '-' : '') + (value / 1e6).toFixed(1) + 'M';
} else if (value >= 1e4 / n) {
return (isNegative ? '-' : '') + (value / 1e3).toFixed(1) + 'K';
} else {
return (isNegative ? '-' : '') + value.toFixed(0);
}
}
function parseQuantityString(quantityStr) {
const suffix = quantityStr.slice(-1);
const base = parseFloat(quantityStr.slice(0, -1));
if (suffix === 'K') {
return base * 1000;
} else if (suffix === 'M') {
return base * 1000000;
} else if (suffix === 'B') {
return base * 1000000000;
} else {
return parseFloat(quantityStr);
}
}
function recordChestOpening(modalElement) {
if (document.querySelector('.ChestStatistics')) {
return;
}
// 从本地存储读取数据
let edibleTools = JSON.parse(localStorage.getItem('Edible_Tools')) || {};
edibleTools.Chest_Open_Data = edibleTools.Chest_Open_Data || {};
// 确保当前玩家的开箱数据结构存在
if (!currentPlayerID || !currentPlayerName) {
console.error("无法获取当前玩家的 ID 或昵称");
return;
}
edibleTools.Chest_Open_Data[currentPlayerID] = edibleTools.Chest_Open_Data[currentPlayerID] || {
玩家昵称: currentPlayerName,
开箱数据: {}
};
let chestOpenData = edibleTools.Chest_Open_Data[currentPlayerID].开箱数据;
const chestDropData = edibleTools.Chest_Drop_Data;
const chestNameElement = modalElement.querySelector("div.Modal_modal__1Jiep > div.Inventory_modalContent__3ObSx > div.Item_itemContainer__x7kH1 > div > div > div.Item_iconContainer__5z7j4 > svg > use");
const chestCountElement = modalElement.querySelector("div.Modal_modal__1Jiep > div.Inventory_modalContent__3ObSx > div.Item_itemContainer__x7kH1 > div > div > div.Item_count__1HVvv");
if (chestNameElement && chestCountElement) {
const chestName = getItemNameFromElement(chestNameElement);
chestOpenData[chestName] = chestOpenData[chestName] || {};
let chestData = chestOpenData[chestName];
const chestCount = parseQuantityString(chestCountElement.textContent.trim());
chestData["总计开箱数量"] = (chestData["总计开箱数量"] || 0) + chestCount;
chestData["获得物品"] = chestData["获得物品"] || {};
const itemsContainer = modalElement.querySelector('.Inventory_gainedItems___e9t9');
const itemElements = itemsContainer.querySelectorAll('.Item_itemContainer__x7kH1');
let totalAskValue = 0;
let totalBidValue = 0;
itemElements.forEach(itemElement => {
const itemNameElement = itemElement.querySelector('.Item_iconContainer__5z7j4 use');
const itemQuantityElement = itemElement.querySelector('.Item_count__1HVvv');
if (itemNameElement && itemQuantityElement) {
const itemName = getItemNameFromElement(itemNameElement);
const itemQuantity = parseQuantityString(itemQuantityElement.textContent.trim());
const itemData = chestDropData[chestName].item[itemName] || {};
const itemAskValue = itemData["出售单价"] || 0;
const itemBidValue = itemData["收购单价"] || 0;
const color = itemData.Color || '';
itemQuantityElement.style.color = color;
const itemOpenTotalAskValue = itemAskValue * itemQuantity;
const itemOpenTotalBidValue = itemBidValue * itemQuantity;
chestData["获得物品"][itemName] = chestData["获得物品"][itemName] || {};
chestData["获得物品"][itemName]["数量"] = (chestData["获得物品"][itemName]["数量"] || 0) + itemQuantity;
chestData["获得物品"][itemName]["总计Ask价值"] = (chestData["获得物品"][itemName]["总计Ask价值"] || 0) + itemOpenTotalAskValue;
chestData["获得物品"][itemName]["总计Bid价值"] = (chestData["获得物品"][itemName]["总计Bid价值"] || 0) + itemOpenTotalBidValue;
totalAskValue += itemOpenTotalAskValue;
totalBidValue += itemOpenTotalBidValue;
}
});
chestData["总计开箱Ask"] = (chestData["总计开箱Ask"] || 0) + totalAskValue;
chestData["总计开箱Bid"] = (chestData["总计开箱Bid"] || 0) + totalBidValue;
// 计算本次开箱的偏差值
const differenceValue = totalBidValue - chestDropData[chestName]["期望产出Bid"] * chestCount;
// 更新累计偏差值
chestData["累计偏差值"] = (chestData["累计偏差值"] || 0) + differenceValue;
// 地牢开箱
let profitRange = null;
let profitColor = 'lime'; // 默认颜色
if (chestCosts[chestName]) {
const { keyAsk, keyBid, entryAsk, entryBid } = chestCosts[chestName];
const minProfit = totalBidValue - (keyAsk + entryAsk) * chestCount;
const maxProfit = totalAskValue - (keyBid + entryBid) * chestCount;
profitRange = `${formatPrice(minProfit)}~${formatPrice(maxProfit)}`;
chestData["总计最高利润"] = (chestData["总计最高利润"] || 0) + maxProfit;
chestData["总计最低利润"] = (chestData["总计最低利润"] || 0) + minProfit;
if (minProfit > 0 && maxProfit > 0) {
profitColor = 'lime';
} else if (minProfit < 0 && maxProfit < 0) {
profitColor = 'red';
} else {
profitColor = 'orange';
}
}
// 显示
const openChestElement = document.querySelector('.Inventory_modalContent__3ObSx');
const displayElement = document.createElement('div');
displayElement.classList.add('ChestStatistics');
displayElement.style.position = 'absolute';
displayElement.style.left = `${openChestElement.offsetLeft}px`;
displayElement.style.top = `${openChestElement.offsetTop}px`;
displayElement.style.fontSize = '12px';
displayElement.innerHTML = `
总计开箱次数:
${chestData["总计开箱数量"]}
本次开箱价值:
${formatPrice(totalAskValue)}/${formatPrice(totalBidValue)}
总计开箱价值:
${formatPrice(chestData["总计开箱Ask"])}/${formatPrice(chestData["总计开箱Bid"])}
`;
const expectedOutputElement = document.createElement('div');
expectedOutputElement.classList.add('ExpectedOutput');
expectedOutputElement.style.position = 'absolute';
expectedOutputElement.style.left = `${openChestElement.offsetLeft}px`;
expectedOutputElement.style.bottom = `${openChestElement.offsetTop}px`;
expectedOutputElement.style.fontSize = '12px';
expectedOutputElement.innerHTML = `
预计产出价值:
${formatPrice(chestDropData[chestName]["期望产出Ask"]*chestCount)}/${formatPrice(chestDropData[chestName]["期望产出Bid"]*chestCount)}
`;
const differenceOutputElement = document.createElement('div');
differenceOutputElement.classList.add('DifferenceOutput');
differenceOutputElement.style.position = 'absolute';
differenceOutputElement.style.right = `${openChestElement.offsetLeft}px`;
differenceOutputElement.style.bottom = `${openChestElement.offsetTop}px`;
differenceOutputElement.style.fontSize = '12px';
differenceOutputElement.style.color = differenceValue > 0 ? 'lime' : 'red';
differenceOutputElement.innerHTML = `
${differenceValue > 0 ? '高于期望价值:' : '低于期望价值:'}
${formatPrice(Math.abs(differenceValue))}
`;
// 创建并显示累计偏差值的元素
const cumulativeDifferenceElement = document.createElement('div');
cumulativeDifferenceElement.classList.add('CumulativeDifference');
cumulativeDifferenceElement.style.position = 'absolute';
cumulativeDifferenceElement.style.right = `${openChestElement.offsetLeft}px`;
cumulativeDifferenceElement.style.top = `${openChestElement.offsetTop}px`;
cumulativeDifferenceElement.style.fontSize = '12px';
cumulativeDifferenceElement.style.color = chestData["累计偏差值"] > 0 ? 'lime' : 'red';
cumulativeDifferenceElement.innerHTML = `
本次开箱利润
${profitRange ? `${profitRange}` : `${formatPrice(totalAskValue)}/${formatPrice(totalBidValue)}`}
累计${chestData["累计偏差值"] > 0 ? '高于期望:' : '低于期望:'}
${formatPrice(Math.abs(chestData["累计偏差值"]))}
`;
openChestElement.appendChild(displayElement);
openChestElement.appendChild(expectedOutputElement);
openChestElement.appendChild(differenceOutputElement);
openChestElement.appendChild(cumulativeDifferenceElement);
// 保存更新的数据到本地存储
localStorage.setItem('Edible_Tools', JSON.stringify(edibleTools));
}
}
function calculateTotalValues(itemElements) {
let totalAskValue = 0;
let totalBidValue = 0;
itemElements.forEach(itemElement => {
const itemNameElement = itemElement.querySelector('.Item_iconContainer__5z7j4 use');
const itemQuantityElement = itemElement.querySelector('.Item_count__1HVvv');
if (itemNameElement && itemQuantityElement) {
const itemName = getItemNameFromElement(itemNameElement);
const itemQuantity = parseQuantityString(itemQuantityElement.textContent.trim());
let askPrice = 0;
let bidPrice = 0;
let priceColor = '';
// 获取价格
if (specialItemPrices[itemName] && specialItemPrices[itemName].ask) {
askPrice = parseFloat(specialItemPrices[itemName].ask);
bidPrice = parseFloat(specialItemPrices[itemName].bid);
priceColor = '';
} else if (marketData?.market?.[itemName]) {
bidPrice = marketData.market[itemName].bid;
askPrice = marketData.market[itemName].ask;
} else {
console.log(`${itemName} 的价格未找到`);
}
const itemTotalAskValue = askPrice * itemQuantity;
const itemTotalBidValue = bidPrice * itemQuantity;
totalAskValue += itemTotalAskValue;
totalBidValue += itemTotalBidValue;
}
});
//console.log(totalAskValue);
return { totalAskValue, totalBidValue };
}
//更详细的战斗等级显示
const updateCombatLevel = () => {
const elements = document.querySelectorAll(".NavigationBar_currentExperience__3GDeX");
if (elements.length === 17) {
const levels = Array.from(elements).slice(10, 17).map(el => {
const levelText = parseInt(el.parentNode.parentNode.querySelector(".NavigationBar_textContainer__7TdaI .NavigationBar_level__3C7eR").textContent);
const decimalPart = parseFloat(el.style.width) / 100;
return { integerPart: levelText, decimalPart: decimalPart };
});
let [endurance, intelligence, attack, strength, defense, ranged, magic] = levels;
let combatTypeMax = Math.max(
0.5 * (attack.integerPart + strength.integerPart),
ranged.integerPart,
magic.integerPart
);
if (combatTypeMax !== 0.5 * (attack.integerPart + strength.integerPart)) {
attack.decimalPart = 0;
strength.decimalPart = 0;
}
if (combatTypeMax !== ranged.integerPart) ranged.decimalPart = 0;
if (combatTypeMax !== magic.integerPart) magic.decimalPart = 0;
let combatLevel = 0.2 * (endurance.integerPart + intelligence.integerPart + defense.integerPart) + 0.4 * combatTypeMax;
combatLevel = parseFloat(combatLevel.toFixed(2));
//console.log("combatLevel",combatLevel)
const integerPart = Math.floor(combatLevel);
const decimalPart = combatLevel - integerPart;
//console.log("integerPart",integerPart)
const list1 = [
endurance.decimalPart * 0.2,
intelligence.decimalPart * 0.2,
attack.decimalPart * 0.2,
strength.decimalPart * 0.2,
defense.decimalPart * 0.2,
ranged.decimalPart * 0.2,
magic.decimalPart * 0.2
];
const list2 = [
endurance.decimalPart * 0.2,
intelligence.decimalPart * 0.2,
attack.decimalPart * 0.2,
strength.decimalPart * 0.2,
defense.decimalPart * 0.2,
ranged.decimalPart * 0.2,
magic.decimalPart * 0.2,
ranged.decimalPart * 0.2,
magic.decimalPart * 0.2
];
//console.log("list1",list1,"\nlist2",list2)
list1.sort((a, b) => b - a);
list2.sort((a, b) => b - a);
if (decimalPart === 0.8) {
combatLevel += list1[0];
} else {
let total = 0;
const maxIterations = Math.floor((1 - decimalPart) / 0.2);
let iterations = 0;
for (const i of list2) {
if (iterations >= maxIterations) break;
if ((decimalPart + total + i) < 1) {
total += i;
} else {
break;
}
iterations++;
}
combatLevel = decimalPart + integerPart + total;
}
elements[15].parentNode.parentNode.parentNode.parentNode.parentNode.querySelector(".NavigationBar_nav__3uuUl .NavigationBar_level__3C7eR").textContent = combatLevel.toFixed(2);
}
};
window.setInterval(updateCombatLevel, 10000);
function OfflineStatistics(modalElement) {
const itemsContainer = modalElement.querySelectorAll(".OfflineProgressModal_itemList__26h-Y");
let timeContainer = null;
let getItemContainer = null;
let spendItemContainer = null;
itemsContainer.forEach(container => {
const labelElement = container.querySelector('.OfflineProgressModal_label__2HwFG');
if (labelElement) {
const textContent = labelElement.textContent.trim();
if (textContent.startsWith("Offline duration") || textContent.startsWith("你离线了") || textContent.startsWith("离线时间")) {
timeContainer = container;
} else if (textContent.startsWith("Items gained") || textContent.startsWith("获得物品:") || textContent.startsWith("获得物品")) {
getItemContainer = container;
} else if (textContent.startsWith("Items consumed") || textContent.startsWith("你消耗了:") || textContent.startsWith("消耗物品")) {
spendItemContainer = container;
}
}
});
let TotalSec = null;
if (timeContainer) {
const textContent = timeContainer.textContent;
const match = textContent.match(/(?:(\d+)d\s*)?(?:(\d+)h\s*)?(?:(\d+)m\s*)?(?:(\d+)s)/);
if (match) {
let days = parseInt(match[1], 10) || 0;
let hours = parseInt(match[2], 10) || 0;
let minutes = parseInt(match[3], 10) || 0;
let seconds = parseInt(match[4], 10) || 0;
TotalSec = days * 86400 + hours * 3600 + minutes * 60 + seconds;
}
}
let getitemtotalAskValue = 0;
let getitemtotalBidValue = 0;
if (getItemContainer) {
const getitemElements = getItemContainer.querySelectorAll('.Item_itemContainer__x7kH1');
const { totalAskValue, totalBidValue } = calculateTotalValues(getitemElements);
getitemtotalAskValue = totalAskValue;
getitemtotalBidValue = totalBidValue;
}
let spenditemtotalAskValue = 0;
let spenditemtotalBidValue = 0;
if (spendItemContainer) {
const spenditemElements = spendItemContainer.querySelectorAll('.Item_itemContainer__x7kH1');
const { totalAskValue, totalBidValue } = calculateTotalValues(spenditemElements);
spenditemtotalAskValue = totalAskValue;
spenditemtotalBidValue = totalBidValue;
}
if (timeContainer) {
const newElement = document.createElement('span');
newElement.textContent = `利润: ${formatPrice(getitemtotalBidValue - spenditemtotalAskValue,10)} [${formatPrice((getitemtotalBidValue - spenditemtotalAskValue) / (TotalSec / 3600) * 24,10)}/天]`;
newElement.style.color = 'gold';
newElement.style.whiteSpace = 'nowrap';
newElement.style.marginLeft = 'auto';
timeContainer.querySelector(':first-child').appendChild(newElement);
}
if (getItemContainer) {
const newElement = document.createElement('span');
newElement.textContent = `产出:[${formatPrice(getitemtotalAskValue)}/${formatPrice(getitemtotalBidValue)}]`;
newElement.style.float = 'right';
newElement.style.color = 'gold';
newElement.style.whiteSpace = 'nowrap';
getItemContainer.querySelector(':first-child').appendChild(newElement);
}
if (spendItemContainer) {
const newElement = document.createElement('span');
newElement.textContent = `成本:[${formatPrice(spenditemtotalAskValue)}/${formatPrice(spenditemtotalBidValue)}]`;
newElement.style.float = 'right';
newElement.style.color = 'gold';
newElement.style.whiteSpace = 'nowrap';
spendItemContainer.querySelector(':first-child').appendChild(newElement);
}
}
function initObserver() {
// 选择要观察的目标节点
const targetNode = document.body;
// 观察器的配置(需要观察子节点的变化)
const config = { childList: true, subtree: true };
// 创建一个观察器实例并传入回调函数
const observer = new MutationObserver(mutationsList => {
for (let mutation of mutationsList) {
if (mutation.type === 'childList') {
// 监听到子节点变化
mutation.addedNodes.forEach(addedNode => {
// 检查是否是我们关注的 Modal_modalContainer__3B80m 元素被添加
if (addedNode.classList && addedNode.classList.contains('Modal_modalContainer__3B80m')) {
// Modal_modalContainer__3B80m 元素被添加,执行处理函数
//console.log("箱子被打开")
ShowChestPrice();
recordChestOpening(addedNode);
// 开始监听箱子图标的变化
startIconObserver();
}
if (addedNode.classList && addedNode.classList.contains('OfflineProgressModal_modalContainer__knnk7')) {
OfflineStatistics(addedNode);
console.log("离线报告已创建!")
}
if (addedNode.classList && addedNode.classList.contains('MainPanel_subPanelContainer__1i-H9')) {
if (addedNode.querySelector(".CombatPanel_combatPanel__QylPo")) {
addBattlePlayerFoodButton();
addBattlePlayerLootButton();
} else if (addedNode.querySelector('.EnhancingPanel_enhancingPanel__ysWpV')) {
updateEnhancementUI();
}
}
});
mutation.removedNodes.forEach(removedNode => {
// 检查是否是 Modal_modalContainer__3B80m 元素被移除
if (removedNode.classList && removedNode.classList.contains('Modal_modalContainer__3B80m')) {
// Modal_modalContainer__3B80m 元素被移除,停止监听箱子图标的变化
stopIconObserver();
}
});
}
}
});
// 以上述配置开始观察目标节点
observer.observe(targetNode, config);
// 定义箱子图标变化的观察器
let iconObserver = null;
// 开始监听箱子图标的变化
function startIconObserver() {
const chestNameElem = document.querySelector(chestNameSelector);
if (!chestNameElem) return;
// 创建一个观察器实例来监听图标的变化
iconObserver = new MutationObserver(() => {
// 当箱子图标变化时,执行处理函数
ShowChestPrice();
});
// 配置观察器的选项
const iconConfig = { attributes: true, attributeFilter: ['href'] };
// 以上述配置开始观察箱子图标节点
iconObserver.observe(chestNameElem, iconConfig);
}
// 停止监听箱子图标的变化
function stopIconObserver() {
if (iconObserver) {
iconObserver.disconnect();
iconObserver = null;
}
}
}
function hookWS() {
const dataProperty = Object.getOwnPropertyDescriptor(MessageEvent.prototype, "data");
const oriGet = dataProperty.get;
dataProperty.get = hookedGet;
Object.defineProperty(MessageEvent.prototype, "data", dataProperty);
function hookedGet() {
const socket = this.currentTarget;
if (!(socket instanceof WebSocket)) {
return oriGet.call(this);
}
if (socket.url.indexOf("api.milkywayidle.com/ws") <= -1 && socket.url.indexOf("api-test.milkywayidle.com/ws") <= -1) {
return oriGet.call(this);
}
const message = oriGet.call(this);
Object.defineProperty(this, "data", { value: message }); // Anti-loop
return handleMessage(message);
}
}
function addStatisticsButton() {
const waitForNavi = () => {
const targetNode = document.querySelector("div.NavigationBar_minorNavigationLinks__dbxh7");
if (targetNode) {
// 创建统计窗口按钮
let statsButton = document.createElement("div");
statsButton.setAttribute("class", "NavigationBar_minorNavigationLink__31K7Y");
statsButton.style.color = "gold";
statsButton.innerHTML = isCN ? "开箱统计" : "Chest Statistics";
statsButton.addEventListener("click", () => {
const edibleTools = JSON.parse(localStorage.getItem('Edible_Tools')) || {};
const openChestData = edibleTools.Chest_Open_Data || {};
createVisualizationWindow(openChestData);
});
// 创建食用工具按钮
let edibleToolsButton = document.createElement("div");
edibleToolsButton.setAttribute("class", "NavigationBar_minorNavigationLink__31K7Y");
edibleToolsButton.style.color = "gold";
edibleToolsButton.innerHTML = isCN ? "食用工具" : "Edible Tools";
edibleToolsButton.addEventListener("click", () => {
openSettings();
});
// 将按钮添加到目标节点
targetNode.insertAdjacentElement("afterbegin", statsButton);
targetNode.insertAdjacentElement("afterbegin", edibleToolsButton);
//获取图标url格式模板
item_icon_url = document.querySelector("div[class^='Item_itemContainer'] use")?.getAttribute("href")?.split("#")[0];
addBattlePlayerFoodButton();
addBattlePlayerLootButton();
} else {
setTimeout(waitForNavi, 200);
}
};
waitForNavi(); // 开始等待目标节点出现
}
//奶牛钉钉
function handleMessage(message) {
try {
let obj = JSON.parse(message);
if (obj && obj.type === "new_battle") {
processCombatConsumables(obj);
} else if (obj && obj.type === "init_character_data") {
now_battle_map = undefined;
processCharacterData(obj);
addStatisticsButton();
update_market_list(obj);
} else if (obj && obj.type === "action_completed" && obj.endCharacterAction) {
const actionHrid = obj.endCharacterAction.actionHrid;
if (actionHrid === "/actions/enhancing/enhance") {
processEnhancementData(obj);
} else if (actionHrid.startsWith("/actions/combat/")) {
now_battle_map = actionHrid;
}
} else if (obj && obj.type === "guild_updated") {
const Guild_ID = obj.guild.id;
const edibleTools = JSON.parse(localStorage.getItem('Edible_Tools')) || {};
edibleTools.Guild_Data = edibleTools.Guild_Data || {};
let storedData = edibleTools.Guild_Data || {};
// 判断是否已经存在旧数据
if (storedData[Guild_ID] && storedData[Guild_ID].guild_updated && storedData[Guild_ID].guild_updated.old.updatedAt) {
const oldUpdatedAt = new Date(storedData[Guild_ID].guild_updated.new.updatedAt);
const newUpdatedAt = new Date(obj.guild.updatedAt);
// 计算时间差(单位:毫秒)
const timeDifference = newUpdatedAt - oldUpdatedAt;
if (timeDifference >= updataDealy) {
// 更新老数据为新数据
storedData[Guild_ID].guild_updated.old = storedData[Guild_ID].guild_updated.new;
// 更新新数据为当前数据
storedData[Guild_ID].guild_updated.new = {
experience: obj.guild.experience,
level: obj.guild.level,
updatedAt: obj.guild.updatedAt
};
} else {
// 仅更新新数据
storedData[Guild_ID].guild_updated.new = {
experience: obj.guild.experience,
level: obj.guild.level,
updatedAt: obj.guild.updatedAt
};
}
//计算Δ
const Delta = {
Delta_Xp: storedData[Guild_ID].guild_updated.new.experience - storedData[Guild_ID].guild_updated.old.experience,
Delta_Level: storedData[Guild_ID].guild_updated.new.level - storedData[Guild_ID].guild_updated.old.level,
Delta_Time: (newUpdatedAt - new Date(storedData[Guild_ID].guild_updated.old.updatedAt)) / 1000, // 转换为秒
Rate_XP_Hours: (3600*(obj.guild.experience - storedData[Guild_ID].guild_updated.old.experience)/((newUpdatedAt - new Date(storedData[Guild_ID].guild_updated.old.updatedAt)) / 1000)).toFixed(2)
};
storedData[Guild_ID].guild_updated.Delta = Delta;
const Guild_TotalXp_div = document.querySelectorAll(".GuildPanel_value__Hm2I9")[1];
if (Guild_TotalXp_div) {
const xpText = isCN ? "经验值 / 小时" : "XP / Hour";
Guild_TotalXp_div.insertAdjacentHTML(
"afterend",
`
${isCN ? "剩余时间" : "Duration"}: ${timeDisplay}
${isCN ? "每分回血" : "HP Regen/min"}: ${isNaN(HpRegen) ? (isCN ? "等待数据稳定" : "Waiting for stable data") : `${HpRegen.toFixed(0)}(${HpRegenMax})`}
${isCN ? "每分回蓝" : "MP Regen/min"}: ${isNaN(MpRegen) ? (isCN ? "等待数据稳定" : "Waiting for stable data") : `${MpRegen.toFixed(0)}(${MpRegenMax})`}
${isCN ? "光环" : "Aura"}: ${transferAuraName}
${item}: ${lootItems[item].数量}
`; } } if (totalPrice > 0) { dataHtml += `总计价格: ${formatPrice(totalPrice)}
`; } dataHtml += '订单ID | 角色ID | 状态 | 类型 | 物品 | 数量 | 已交易数量 | 单价 | 贸易额 | 更新时间 | 操作 |
---|