您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
在製作配方彈窗中,為缺少的材料(包含升級道具)右側添加一個快捷購買按鈕,並在購買後自動刷新狀態。
// ==UserScript== // @name 銀河奶牛放置-任務製作材料快捷購買 // @name:en Milky way idle Quest Materials Instant buy // @namespace http://tampermonkey.net/ // @version 4.0 // @description 在製作配方彈窗中,為缺少的材料(包含升級道具)右側添加一個快捷購買按鈕,並在購買後自動刷新狀態。 // @description:en Adds a quick-buy button with the missing quantity for required materials in any crafting/upgrading window. // @author YourName // @match https://www.milkywayidle.com/game* // @icon https://www.google.com/s2/favicons?sz=64&domain=milkywayidle.com // @grant none // @license MIT // ==/UserScript== (function() { 'use strict'; // ================================================================================= // ========== 設定區:你可以根據需要修改下面的值 ========== // ================================================================================= const MAX_PRICE_MULTIPLIER = 10; // 願意用高於市價 15% 的價格購買 (可自行調整) const REFRESH_DELAY_MS = 200; // 購買後等待多少毫秒刷新UI (2.5秒),如果伺服器回應慢可以適當加長 // ================================================================================= /** * 購買單一物品的函式 * @param {string} itemName - 物品的中文名稱 * @param {number} quantity - 要購買的數量 */ async function buyItem(itemName, quantity) { if (quantity <= 0) return; if (!window.mwi?.MWICoreInitialized) { alert('錯誤:遊戲核心物件 (mwi) 未就緒!'); return; } const itemHrid = window.mwi.itemNameToHridDict[itemName]; if (!itemHrid) { alert(`錯誤:找不到物品 "${itemName}" 的內部ID!`); return; } const priceInfo = window.mwi.coreMarket.getItemPrice(itemHrid, 0, true); const askPrice = priceInfo?.ask; if (!askPrice || askPrice <= 0) { alert(`錯誤:查不到 "${itemName}" 的市場價格,無法自動下單。`); return; } const maxPrice = Math.ceil(askPrice * MAX_PRICE_MULTIPLIER); const totalCost = (quantity * maxPrice).toLocaleString(); const confirmationMessage = `確認購買?\n\n物品:${itemName}\n數量:${quantity}\n最高單價:${maxPrice.toLocaleString()}\n\n預計最高花費:${totalCost} 金幣`; // const isConfirmed = confirm(confirmationMessage); const isConfirmed = true; if (isConfirmed) { console.log(`下單購買: ${itemName}, Hrid: ${itemHrid}, 數量: ${quantity}, 最高單價: ${maxPrice}`); try { window.mwi.game.handlePostMarketOrder(false, itemHrid, 0, quantity, maxPrice, true); // *** 新增功能:購買後延遲刷新UI *** setTimeout(() => { const activeModal = document.querySelector('.Modal_modal__1Jiep'); if (activeModal) { console.log('刷新按鈕狀態...'); refreshButtons(activeModal); } }, REFRESH_DELAY_MS); } catch (e) { console.error("呼叫購買函式時出錯!", e); alert("執行購買操作時發生錯誤,請按 F12 查看主控台以獲取詳細資訊。"); } } } /** * 核心函式:刷新指定視窗內的所有購買按鈕 * @param {Node} modalNode - 彈出視窗的 DOM 節點 */ function refreshButtons(modalNode) { // 先移除所有由本腳本添加的舊按鈕和數量提示 modalNode.querySelectorAll('.quick-buy-wrapper').forEach(el => el.remove()); const productionCountInput = modalNode.querySelector('.SkillActionDetail_maxActionCountInput__1C0Pw .Input_input__2-t98'); if (!productionCountInput) return; const productionCount = parseInt(productionCountInput.value, 10) || 1; // --- 1. 處理普通材料 --- const requirementsContainer = modalNode.querySelector('.SkillActionDetail_itemRequirements__3SPnA'); if (requirementsContainer) { const childNodes = requirementsContainer.childNodes; for (let i = 0; i < childNodes.length; i += 3) { const itemContainerDiv = childNodes[i + 2]; if (!itemContainerDiv || itemContainerDiv.nodeName !== 'DIV') continue; const baseRequiredAmount = parseInt((childNodes[i + 1]).textContent.replace(/[^0-9]/g, ''), 10); const currentAmount = parseInt((childNodes[i]).textContent, 10); const itemName = itemContainerDiv.querySelector('.Item_name__2C42x')?.textContent; if (isNaN(currentAmount) || isNaN(baseRequiredAmount) || !itemName) continue; const missingAmount = (baseRequiredAmount * productionCount) - currentAmount; if (missingAmount > 0) { const wrapper = document.createElement('div'); wrapper.className = 'quick-buy-wrapper'; wrapper.style.cssText = 'display: flex; align-items: center;'; const button = document.createElement('button'); button.innerHTML = '🛒'; button.title = `總需求: ${baseRequiredAmount * productionCount}\n缺少: ${missingAmount}\n點擊購買`; button.className = 'quick-buy-button Button_button__1Fe9z Button_small__3fqC7'; button.style.cssText = 'padding: 0px 6px; flex-shrink: 0;'; button.onclick = (e) => { e.stopPropagation(); buyItem(itemName, missingAmount); }; const missingSpan = document.createElement('span'); missingSpan.textContent = `-${missingAmount.toLocaleString()}`; missingSpan.style.cssText = 'color: red; margin-left: 5px; font-weight: bold;'; wrapper.appendChild(button); wrapper.appendChild(missingSpan); itemContainerDiv.style.cssText = 'display: flex; align-items: center; justify-content: space-between; width: 100%;'; itemContainerDiv.appendChild(wrapper); } } } // --- 2. 處理需要升級的道具 --- const upgradeSection = modalNode.querySelector('.SkillActionDetail_upgradeItemSelectorInput__2mnS0'); if (upgradeSection) { const itemNameElement = upgradeSection.querySelector('svg[aria-label]'); const itemName = itemNameElement ? itemNameElement.getAttribute('aria-label') : null; const ownedAmountText = upgradeSection.querySelector('.Item_count__1HVvv')?.textContent || '0'; const ownedAmount = parseInt(ownedAmountText.replace(/,/g, ''), 10); if (!itemName || isNaN(ownedAmount)) return; const missingAmount = productionCount - ownedAmount; if (missingAmount > 0) { const wrapper = document.createElement('div'); wrapper.className = 'quick-buy-wrapper'; wrapper.style.cssText = 'display: flex; align-items: center; margin-left: 8px;'; const button = document.createElement('button'); button.innerHTML = '🛒'; button.title = `總需求: ${productionCount}\n缺少: ${missingAmount}\n點擊購買`; button.className = 'quick-buy-button Button_button__1Fe9z Button_small__3fqC7'; button.style.cssText = 'padding: 0px 6px; flex-shrink: 0;'; button.onclick = (e) => { e.stopPropagation(); buyItem(itemName, missingAmount); }; const missingSpan = document.createElement('span'); missingSpan.textContent = `-${missingAmount.toLocaleString()}`; missingSpan.style.cssText = 'color: red; margin-left: 5px; font-weight: bold;'; wrapper.appendChild(button); wrapper.appendChild(missingSpan); const itemSelector = upgradeSection.querySelector('.ItemSelector_itemSelector__2eTV6'); if (itemSelector) { itemSelector.parentElement.style.display = 'flex'; itemSelector.parentElement.style.alignItems = 'center'; itemSelector.parentElement.appendChild(wrapper); } } } } function observeAndInject() { const observer = new MutationObserver((mutationsList) => { for (const mutation of mutationsList) { if (mutation.addedNodes.length > 0) { mutation.addedNodes.forEach(node => { if (node.nodeType === 1) { const modal = node.matches('.Modal_modal__1Jiep') ? node : node.querySelector('.Modal_modal__1Jiep'); if (modal) { const reprocess = () => { setTimeout(() => refreshButtons(modal), 100); }; setTimeout(reprocess, 200); const input = modal.querySelector('.SkillActionDetail_maxActionCountInput__1C0Pw .Input_input__2-t98'); if (input) { input.addEventListener('change', reprocess); input.addEventListener('keyup', reprocess); } } } }); } } }); observer.observe(document.body, { childList: true, subtree: true }); } new Promise(resolve => { let count = 0; const interval = setInterval(() => { count++; if (count > 30) { clearInterval(interval); } if (window.mwi?.MWICoreInitialized) { clearInterval(interval); resolve(); } }, 1000); }).then(() => { console.log("銀河放置-配方材料快捷購買腳本已啟動。"); observeAndInject(); }); })();