您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
add-on to Loot Drops Overlay
当前为
// ==UserScript== // @name Milky Way Idle - Loot Drops Value Add-on // @namespace https://milkywayidle.com/ // @version 1.0 // @description add-on to Loot Drops Overlay // @author notawhale // @match https://www.milkywayidle.com/* // @grant none // ==/UserScript== (function () { 'use strict'; const CUSTOM_SORT_KEY = 'lootDropsCustomSortPref'; const SORT_MODES = ['name', 'value', 'quantity']; const SORT_LABELS = { name: 'Name', value: 'Value', quantity: 'Quantity' }; const ENABLE_LOG = true; let marketData = null; const fixedValueChests = new Set([ 'small treasure chest', 'medium treasure chest', 'large treasure chest', 'chimerical chest', 'sinister chest', 'enchanted chest', 'pirate chest' ]); function formatCoins(value) { return `${Math.round(value).toLocaleString()} coin`; } function capitalizeEachWord(str) { return str .split(' ') .map((w) => w.charAt(0).toUpperCase() + w.slice(1)) .join(' '); } async function loadMarketData() { try { const res = await fetch( 'https://raw.githubusercontent.com/holychikenz/MWIApi/main/medianmarket.json' ); const json = await res.json(); marketData = json.market || {}; console.log('[ValueAdd] Market data loaded.'); } catch (e) { console.error('[ValueAdd] Failed to load market data:', e); } } function getUnitValue(name) { const normalized = name.trim().toLowerCase(); if (fixedValueChests.has(normalized)) return 1; if (normalized === 'coin') return 1; const entry = marketData[capitalizeEachWord(name)]; return entry?.ask || 0; } function calculateItemValue(name, count) { return count * getUnitValue(name); } function calculateTotalValue(section, playerName = 'Player') { const itemRows = section.querySelectorAll('.ldt-loot-item-entry'); let total = 0; if (ENABLE_LOG) console.group(`[${playerName}] Value Breakdown`); itemRows.forEach((row) => { const nameEl = row.querySelector('.ldt-item-name'); const countEl = row.querySelector('.ldt-item-count'); if (!nameEl || !countEl) return; const name = nameEl.textContent.trim(); let rawCount = countEl.dataset.count; if (!rawCount) { const parsed = parseInt(countEl.textContent.replace(/[^\d]/g, ''), 10); rawCount = isNaN(parsed) ? '0' : String(parsed); countEl.dataset.count = rawCount; } const count = parseInt(rawCount, 10); const unit = getUnitValue(name); const itemTotal = count * unit; total += itemTotal; if (ENABLE_LOG) { console.log( `• ${name}: count=${count}, unit=${formatCoins(unit)}, total=${formatCoins(itemTotal)}` ); } }); if (ENABLE_LOG) { console.log(`= Total: ${formatCoins(total)}`); console.groupEnd(); } return total; } function injectValuesAndSort() { const sortPref = localStorage.getItem(CUSTOM_SORT_KEY) || 'name'; const playerSections = document.querySelectorAll('.ldt-player-stats-section'); playerSections.forEach((section) => { const header = section.querySelector('.ldt-player-name-header'); const playerName = header?.textContent?.split('(')[0]?.trim() || 'Unknown'; const existingSpan = header.querySelector('span[data-value-injected]'); if (existingSpan) existingSpan.remove(); const totalValue = calculateTotalValue(section, playerName); if (totalValue > 0) { const span = document.createElement('span'); span.style.color = 'gold'; span.style.fontWeight = 'normal'; span.style.fontSize = '0.9em'; span.textContent = ` (${formatCoins(totalValue)})`; span.dataset.valueInjected = 'true'; header.appendChild(span); } const list = section.querySelector('.ldt-loot-list'); if (!list) return; const items = Array.from(list.querySelectorAll('.ldt-loot-item-entry')); const itemData = items.map((row) => { const nameEl = row.querySelector('.ldt-item-name'); const countEl = row.querySelector('.ldt-item-count'); const name = nameEl?.textContent.trim() || ''; let rawCount = countEl.dataset.count; if (!rawCount) { const parsed = parseInt(countEl.textContent.replace(/[^\d]/g, ''), 10); rawCount = isNaN(parsed) ? '0' : String(parsed); countEl.dataset.count = rawCount; } const count = parseInt(rawCount, 10); const value = calculateItemValue(name, count); return { row, name, count, value, nameEl, countEl }; }); itemData.sort((a, b) => { if (sortPref === 'value') { return b.value - a.value || b.count - a.count || a.name.localeCompare(b.name); } if (sortPref === 'quantity') { return b.count - a.count || a.name.localeCompare(b.name); } return a.name.localeCompare(b.name); }); itemData.forEach(({ countEl, count }) => { countEl.textContent = `× ${count}`; }); list.innerHTML = ''; itemData.forEach(({ row }) => list.appendChild(row)); }); } function overrideSortButton() { const btn = document.querySelector('#milt-loot-drops-display-sortbtn'); if (!btn || btn.dataset.customOverrideInjected) return; btn.dataset.customOverrideInjected = 'true'; const updateLabel = () => { const current = localStorage.getItem(CUSTOM_SORT_KEY) || 'name'; btn.textContent = `Sort: ${SORT_LABELS[current]}`; }; btn.addEventListener('click', (e) => { e.stopPropagation(); const current = localStorage.getItem(CUSTOM_SORT_KEY) || 'name'; const next = SORT_MODES[(SORT_MODES.indexOf(current) + 1) % SORT_MODES.length]; localStorage.setItem(CUSTOM_SORT_KEY, next); updateLabel(); injectValuesAndSort(); }); updateLabel(); } async function main() { await loadMarketData(); setInterval(() => { const overlay = document.getElementById('milt-loot-drops-display'); if (!overlay || overlay.classList.contains('is-hidden')) return; overrideSortButton(); injectValuesAndSort(); }, 1000); } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', main); } else { main(); } })();