您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Greasy Fork is available in English.
Auto-manage game queue(自动9战)
当前为
// ==UserScript== // @name MWI-AutoCombat // @name:zh-CN MWI自动战斗助手 // @namespace https://github.com/CYR2077 // @version 1.0 // @description Auto-manage game queue(自动9战) // @author CYR2077 // @license GPL3 // @match https://www.milkywayidle.com/* // @icon https://www.google.com/s2/favicons?sz=64&domain=milkywayidle.com // @grant GM_setValue // @grant GM_getValue // ==/UserScript== /** * 关于使用本插件可能存在的脚本行为说明: * * 《游戏规则》 * * 4.机器人、脚本和扩展 * * 4.1禁止机器人: 请勿使用任何自动化程序代替你操作游戏。 * 4.2脚本和扩展: 任何脚本或扩展程序都不得为玩家执行任何操作(向服务器发送任何请求), 仅限使用于显示信息或改进用户界面 (例如: 显示战斗摘要、跟踪掉落、将按钮移动到不同位置)。 * * 请仔细阅读游戏规则条款后,再选择是否安装使用本插件,谢谢! */ (function (workerScript) { if (!/MSIE 10/i.test (navigator.userAgent)) { try { var blob = new Blob (["\ var fakeIdToId = {};\ onmessage = function (event) {\ var data = event.data,\ name = data.name,\ fakeId = data.fakeId,\ time;\ if(data.hasOwnProperty('time')) {\ time = data.time;\ }\ switch (name) {\ case 'setInterval':\ fakeIdToId[fakeId] = setInterval(function () {\ postMessage({fakeId: fakeId});\ }, time);\ break;\ case 'clearInterval':\ if (fakeIdToId.hasOwnProperty (fakeId)) {\ clearInterval(fakeIdToId[fakeId]);\ delete fakeIdToId[fakeId];\ }\ break;\ case 'setTimeout':\ fakeIdToId[fakeId] = setTimeout(function () {\ postMessage({fakeId: fakeId});\ if (fakeIdToId.hasOwnProperty (fakeId)) {\ delete fakeIdToId[fakeId];\ }\ }, time);\ break;\ case 'clearTimeout':\ if (fakeIdToId.hasOwnProperty (fakeId)) {\ clearTimeout(fakeIdToId[fakeId]);\ delete fakeIdToId[fakeId];\ }\ break;\ }\ }\ "]); // Obtain a blob URL reference to our worker 'file'. workerScript = window.URL.createObjectURL(blob); } catch (error) { /* Blob is not supported, use external script instead */ } } var worker, fakeIdToCallback = {}, lastFakeId = 0, maxFakeId = 0x7FFFFFFF, // 2 ^ 31 - 1, 31 bit, positive values of signed 32 bit integer logPrefix = 'HackTimer.js by turuslan: '; if (typeof (Worker) !== 'undefined') { function getFakeId () { do { if (lastFakeId == maxFakeId) { lastFakeId = 0; } else { lastFakeId ++; } } while (fakeIdToCallback.hasOwnProperty (lastFakeId)); return lastFakeId; } try { worker = new Worker (workerScript); window.setInterval = function (callback, time /* , parameters */) { var fakeId = getFakeId (); fakeIdToCallback[fakeId] = { callback: callback, parameters: Array.prototype.slice.call(arguments, 2) }; worker.postMessage ({ name: 'setInterval', fakeId: fakeId, time: time }); return fakeId; }; window.clearInterval = function (fakeId) { if (fakeIdToCallback.hasOwnProperty(fakeId)) { delete fakeIdToCallback[fakeId]; worker.postMessage ({ name: 'clearInterval', fakeId: fakeId }); } }; window.setTimeout = function (callback, time /* , parameters */) { var fakeId = getFakeId (); fakeIdToCallback[fakeId] = { callback: callback, parameters: Array.prototype.slice.call(arguments, 2), isTimeout: true }; worker.postMessage ({ name: 'setTimeout', fakeId: fakeId, time: time }); return fakeId; }; window.clearTimeout = function (fakeId) { if (fakeIdToCallback.hasOwnProperty(fakeId)) { delete fakeIdToCallback[fakeId]; worker.postMessage ({ name: 'clearTimeout', fakeId: fakeId }); } }; worker.onmessage = function (event) { var data = event.data, fakeId = data.fakeId, request, parameters, callback; if (fakeIdToCallback.hasOwnProperty(fakeId)) { request = fakeIdToCallback[fakeId]; callback = request.callback; parameters = request.parameters; if (request.hasOwnProperty ('isTimeout') && request.isTimeout) { delete fakeIdToCallback[fakeId]; } } if (typeof (callback) === 'string') { try { callback = new Function (callback); } catch (error) { console.log (logPrefix + 'Error parsing callback code string: ', error); } } if (typeof (callback) === 'function') { callback.apply (window, parameters); } }; worker.onerror = function (event) { console.log (event); }; } catch (error) { console.log (logPrefix + 'Initialisation failed'); console.error (error); } } else { console.log (logPrefix + 'Initialisation failed - HTML5 Web Worker is not supported'); } }) ('HackTimerWorker.js'); (function () { 'use strict'; // Language detection and internationalization const isChineseUser = () => { const lang = navigator.language.toLowerCase(); return lang.startsWith('zh'); }; const translations = { zh: { title: '自动战斗助手', selectTask: '选择任务:', executionCount: '执行次数:', startAuto: '开始挂机', stopAuto: '停止挂机', noTasksFound: '未找到任务 (请初始化)', initializeTasks: '初始化战斗任务列表', status: { waitingToStart: '状态: 等待开始', invalidNumber: '请输入1-9999999999之间的整数!', invalidCountSet: '执行次数无效,已设置为1次', startingAuto: '开始挂机', times: '次', stopped: '已停止挂机', addedToQueue: '已添加到队列', addToQueueFailed: '添加到队列失败', queueNotFull: '队列未满,添加新任务', queueStatus: '队列状态', queueFull: '队列已满,等待队列消化', executionError: '执行出错', timeout: '超时,停止执行' } }, en: { title: 'MWI-AutoCombat', selectTask: 'Select Task:', executionCount: 'Execution Count:', startAuto: 'Start Auto', stopAuto: 'Stop Auto', noTasksFound: 'No tasks found (Please initialize)', initializeTasks: 'Initialize Battle Task List', status: { waitingToStart: 'Status: Waiting to start', invalidNumber: 'Please enter an integer between 1-9999999999!', invalidCountSet: 'Invalid execution count, set to 1', startingAuto: 'Starting automation', times: 'times', stopped: 'Automation stopped', addedToQueue: 'Added to queue', addToQueueFailed: 'Failed to add to queue', queueNotFull: 'Queue not full, adding new task', queueStatus: 'Queue status', queueFull: 'Queue is full, waiting for queue to process', executionError: 'Execution error', timeout: 'Timeout, stopping execution' } } }; const t = translations[isChineseUser() ? 'zh' : 'en']; let isRunning = false; let retryCount = 0; let currentConfig = { planetIndex: 0, battleCount: 5, retryDelay: 30000, maxRetries: 30 }; // Drag-related variables let isDragging = false; let dragOffset = { x: 0, y: 0 }; // Storage keys const STORAGE_KEYS = { PLANET_INDEX: 'automation_planet_index', BATTLE_COUNT: 'automation_battle_count' }; // Save settings to storage function saveSettings() { const planetSelect = document.getElementById('planet-select'); const battleInput = document.getElementById('battle-count'); if (planetSelect && battleInput) { GM_setValue(STORAGE_KEYS.PLANET_INDEX, planetSelect.value); GM_setValue(STORAGE_KEYS.BATTLE_COUNT, battleInput.value); } } // Load settings from storage function loadSettings() { const savedPlanetIndex = GM_getValue(STORAGE_KEYS.PLANET_INDEX, '0'); const savedBattleCount = GM_getValue(STORAGE_KEYS.BATTLE_COUNT, '9'); return { planetIndex: savedPlanetIndex, battleCount: savedBattleCount }; } // Apply saved settings to UI function applySettings() { const settings = loadSettings(); const planetSelect = document.getElementById('planet-select'); const battleInput = document.getElementById('battle-count'); if (planetSelect && battleInput) { // Restore execution count battleInput.value = settings.battleCount; // Restore planet selection (need to wait for options to load) if (planetSelect.options.length > 0) { const planetIndex = parseInt(settings.planetIndex); if (planetIndex < planetSelect.options.length) { planetSelect.value = settings.planetIndex; } } } } function createUI() { const container = document.createElement('div'); container.id = 'queue-automation-panel'; container.style.cssText = ` position: fixed; top: 20px; right: 20px; width: 300px; background: rgba(44, 62, 80, 0.95); color: white; border-radius: 10px; padding: 20px; box-shadow: 0 4px 20px rgba(0,0,0,0.3); z-index: 10000; font-family: Arial, sans-serif; font-size: 14px; backdrop-filter: blur(5px); transition: opacity 0.3s ease; `; const titleBar = document.createElement('div'); titleBar.id = 'title-bar'; titleBar.style.cssText = ` display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px; cursor: move; user-select: none; `; const title = document.createElement('h3'); title.id = 'panel-title'; title.textContent = t.title; title.style.cssText = ` margin: 0; color: #3498db; border-bottom: 2px solid #3498db; padding-bottom: 10px; flex: 1; text-align: center; cursor: move; `; const toggleButton = document.createElement('button'); toggleButton.id = 'toggle-button'; toggleButton.textContent = '−'; toggleButton.style.cssText = ` width: 25px; height: 25px; border: none; border-radius: 50%; background: #e74c3c; color: white; cursor: pointer; font-size: 16px; line-height: 1; margin-left: 10px; flex-shrink: 0; transition: filter 0.3s ease; `; toggleButton.addEventListener('mouseenter', () => { toggleButton.style.filter = 'brightness(110%)'; }); toggleButton.addEventListener('mouseleave', () => { toggleButton.style.filter = 'brightness(100%)'; }); titleBar.appendChild(title); titleBar.appendChild(toggleButton); const content = document.createElement('div'); content.id = 'panel-content'; const planetLabel = document.createElement('label'); planetLabel.textContent = t.selectTask; planetLabel.style.cssText = 'display: block; margin-bottom: 5px; font-weight: bold;'; const planetSelect = document.createElement('select'); planetSelect.id = 'planet-select'; planetSelect.style.cssText = ` width: 100%; padding: 8px; margin-bottom: 15px; border: none; border-radius: 5px; background: rgba(52, 73, 94, 0.8); color: white; font-size: 14px; `; const battleLabel = document.createElement('label'); battleLabel.textContent = t.executionCount; battleLabel.style.cssText = 'display: block; margin-bottom: 5px; font-weight: bold;'; const battleInput = document.createElement('input'); battleInput.id = 'battle-count'; battleInput.type = 'number'; battleInput.value = '9'; battleInput.min = '1'; battleInput.max = '9999999999'; battleInput.step = '1'; battleInput.style.cssText = ` width: 100%; padding: 8px; margin-bottom: 15px; border: none; border-radius: 5px; background: rgba(52, 73, 94, 0.8); color: white; font-size: 14px; box-sizing: border-box; `; // Prevent decimal input battleInput.addEventListener('keydown', function(e) { if (e.key === '.' || e.key === 'e' || e.key === '-') { e.preventDefault(); } }); const buttonContainer = document.createElement('div'); buttonContainer.style.cssText = 'display: flex; gap: 10px; margin-bottom: 15px;'; const startButton = document.createElement('button'); startButton.id = 'start-button'; startButton.textContent = t.startAuto; startButton.style.cssText = ` flex: 1; padding: 10px; border: none; border-radius: 5px; background: #27ae60; color: white; font-size: 14px; font-weight: bold; cursor: pointer; transition: filter 0.3s ease, opacity 0.3s ease; `; const stopButton = document.createElement('button'); stopButton.id = 'stop-button'; stopButton.textContent = t.stopAuto; stopButton.disabled = true; stopButton.style.cssText = ` flex: 1; padding: 10px; border: none; border-radius: 5px; background: #e74c3c; color: white; font-size: 14px; font-weight: bold; cursor: pointer; transition: filter 0.3s ease, opacity 0.3s ease; opacity: 0.5; `; // Add hover effects [startButton, stopButton].forEach(button => { button.addEventListener('mouseenter', () => { if (!button.disabled) { button.style.filter = 'brightness(110%)'; } }); button.addEventListener('mouseleave', () => { button.style.filter = 'brightness(100%)'; }); }); const statusDiv = document.createElement('div'); statusDiv.id = 'status-display'; statusDiv.style.cssText = ` background: rgba(52, 73, 94, 0.8); padding: 10px; border-radius: 5px; margin-bottom: 10px; height: 120px; font-size: 12px; line-height: 1.4; overflow-y: auto; `; statusDiv.innerHTML = `<div>${t.status.waitingToStart}</div>`; const refreshButton = document.createElement('button'); refreshButton.textContent = t.initializeTasks; refreshButton.style.cssText = ` width: 100%; padding: 5px; margin-top: 10px; border: none; border-radius: 5px; background: #9b59b6; color: white; font-size: 12px; cursor: pointer; transition: filter 0.3s ease; `; refreshButton.addEventListener('mouseenter', () => { refreshButton.style.filter = 'brightness(110%)'; }); refreshButton.addEventListener('mouseleave', () => { refreshButton.style.filter = 'brightness(100%)'; }); refreshButton.addEventListener('click', ()=>{ document.getElementsByClassName("NavigationBar_nav__3uuUl")[13].click(); document.getElementsByClassName("MuiBadge-root TabsComponent_badge__1Du26 css-1rzb3uu")[0].click(); initializePlanetOptions(); }); content.appendChild(planetLabel); content.appendChild(planetSelect); content.appendChild(battleLabel); content.appendChild(battleInput); content.appendChild(buttonContainer); buttonContainer.appendChild(startButton); buttonContainer.appendChild(stopButton); content.appendChild(statusDiv); content.appendChild(refreshButton); container.appendChild(titleBar); container.appendChild(content); document.body.appendChild(container); initializePlanetOptions(); bindEvents(); setupDragFunctionality(); } function setupDragFunctionality() { const container = document.getElementById('queue-automation-panel'); const titleBar = document.getElementById('title-bar'); const title = document.getElementById('panel-title'); // Add drag cursor for draggable areas function addDragCursor(element) { element.addEventListener('mouseenter', (e) => { if (e.target.id !== 'toggle-button') { element.style.cursor = 'move'; } }); } addDragCursor(titleBar); addDragCursor(title); function startDrag(e) { if (e.target.id === 'toggle-button') return; isDragging = true; const rect = container.getBoundingClientRect(); dragOffset.x = e.clientX - rect.left; dragOffset.y = e.clientY - rect.top; container.style.transition = 'none'; container.style.opacity = '0.8'; e.preventDefault(); } titleBar.addEventListener('mousedown', startDrag); title.addEventListener('mousedown', startDrag); document.addEventListener('mousemove', (e) => { if (!isDragging) return; const x = e.clientX - dragOffset.x; const y = e.clientY - dragOffset.y; const maxX = window.innerWidth - container.offsetWidth; const maxY = window.innerHeight - container.offsetHeight; container.style.left = Math.max(0, Math.min(x, maxX)) + 'px'; container.style.top = Math.max(0, Math.min(y, maxY)) + 'px'; container.style.right = 'auto'; e.preventDefault(); }); document.addEventListener('mouseup', () => { if (isDragging) { isDragging = false; container.style.transition = 'opacity 0.3s ease'; container.style.opacity = '0.95'; } }); container.addEventListener('mouseenter', () => { if (!isDragging) { container.style.opacity = '1'; } }); container.addEventListener('mouseleave', () => { if (!isDragging) { container.style.opacity = '0.95'; } }); } function bindEvents() { const battleInput = document.getElementById('battle-count'); const planetSelect = document.getElementById('planet-select'); battleInput.addEventListener('input', function(e) { let value = this.value; value = value.replace(/[^\d]/g, ''); if (value === '') { value = '1'; } else { const num = parseInt(value); if (num < 1) value = '1'; if (num > 9999999999) value = '9999999999'; } this.value = value; // Save settings in real time saveSettings(); }); battleInput.addEventListener('blur', function() { if (this.value === '') { this.value = '1'; } saveSettings(); }); // Listen for planet selection changes planetSelect.addEventListener('change', function() { saveSettings(); }); document.getElementById('start-button').addEventListener('click', () => { const battleCount = parseInt(document.getElementById('battle-count').value); if (!Number.isInteger(battleCount) || battleCount < 1 || battleCount > 9999999999) { updateStatus(t.status.invalidNumber, 'error'); return; } if (!isRunning) { updateConfig(); startAutomation(); } }); document.getElementById('stop-button').addEventListener('click', stopAutomation); const toggleButton = document.getElementById('toggle-button'); const container = document.getElementById('queue-automation-panel'); const content = document.getElementById('panel-content'); const title = document.getElementById('panel-title'); let isMinimized = false; toggleButton.addEventListener('click', (e) => { e.stopPropagation(); if (isMinimized) { // Expand content.style.display = 'block'; container.style.width = '300px'; container.style.padding = '20px'; title.style.borderBottom = '2px solid #3498db'; title.style.paddingBottom = '10px'; toggleButton.textContent = '−'; } else { // Collapse content.style.display = 'none'; container.style.width = '160px'; container.style.padding = '10px 15px'; title.style.borderBottom = 'none'; title.style.paddingBottom = '0'; title.style.fontSize = '14px'; toggleButton.textContent = '+'; } isMinimized = !isMinimized; }); } function initializePlanetOptions() { const planetSelect = document.getElementById('planet-select'); const planetElements = document.getElementsByClassName("SkillAction_name__2VPXa"); planetSelect.innerHTML = ''; if (planetElements.length === 0) { const option = document.createElement('option'); option.value = '0'; option.textContent = t.noTasksFound; planetSelect.appendChild(option); return; } for (let i = 0; i < planetElements.length; i++) { const option = document.createElement('option'); option.value = i; option.textContent = `${planetElements[i].textContent || 'Unknown'}`; planetSelect.appendChild(option); } // Apply saved settings after initialization setTimeout(() => { applySettings(); }, 100); } function updateConfig() { currentConfig.planetIndex = parseInt(document.getElementById('planet-select').value) || 0; const battleCount = parseInt(document.getElementById('battle-count').value); if (Number.isInteger(battleCount) && battleCount >= 1 && battleCount <= 9999999999) { currentConfig.battleCount = battleCount; } else { currentConfig.battleCount = 1; document.getElementById('battle-count').value = '1'; updateStatus(t.status.invalidCountSet, 'warning'); } // Save settings when starting saveSettings(); } function updateStatus(message, type = 'info') { const statusDiv = document.getElementById('status-display'); const timestamp = new Date().toLocaleTimeString(); const colorMap = { 'info': '#3498db', 'success': '#27ae60', 'warning': '#f39c12', 'error': '#e74c3c' }; const newMessage = document.createElement('div'); newMessage.style.color = colorMap[type]; newMessage.textContent = `[${timestamp}] ${message}`; // Add new message to bottom statusDiv.appendChild(newMessage); // Limit message count, keep latest 30 while (statusDiv.children.length > 30) { statusDiv.removeChild(statusDiv.firstChild); } // Auto scroll to bottom to show latest message statusDiv.scrollTop = statusDiv.scrollHeight; } function startAutomation() { isRunning = true; retryCount = 0; document.getElementById('start-button').disabled = true; document.getElementById('start-button').style.opacity = '0.5'; document.getElementById('stop-button').disabled = false; document.getElementById('stop-button').style.opacity = '1'; const planetSelect = document.getElementById('planet-select').options[currentConfig.planetIndex].text; updateStatus(`${t.status.startingAuto} - ${planetSelect}, ${currentConfig.battleCount}${t.status.times}`, 'success'); ExecuteQueueCheck(); } function stopAutomation() { isRunning = false; document.getElementById('start-button').disabled = false; document.getElementById('start-button').style.opacity = '1'; document.getElementById('stop-button').disabled = true; document.getElementById('stop-button').style.opacity = '0.5'; updateStatus(t.status.stopped, 'warning'); } function setInputValue(el, value) { const lastValue = el.value; el.value = value; const event = new Event('input', { bubbles: true }); const tracker = el._valueTracker; if (tracker) { tracker.setValue(lastValue); } el.dispatchEvent(event); } function addTaskToQueue(i, j) { if (!isRunning) return; try { document.getElementsByClassName("NavigationBar_nav__3uuUl")[13].click(); document.getElementsByClassName("MuiBadge-root TabsComponent_badge__1Du26 css-1rzb3uu")[0].click(); const planetElement = document.getElementsByClassName("SkillAction_name__2VPXa")[i]; if (!planetElement) throw new Error(`Task element with index ${i} not found`); planetElement.click(); setTimeout(() => { if (!isRunning) return; const inputElement = document.getElementsByClassName("Input_input__2-t98")[0]; if (!inputElement) throw new Error("Input element not found"); setInputValue(inputElement, j); const addButton = document.getElementsByClassName("Button_button__1Fe9z Button_fullWidth__17pVU Button_large__yIDVZ")[0]; if (!addButton) throw new Error("Add button not found"); addButton.click(); updateStatus(t.status.addedToQueue, 'success'); retryCount = 0; }, 300); } catch (error) { updateStatus(`${t.status.addToQueueFailed}: ${error.message}`, 'error'); } } function isQueueExpanded() { return !!document.getElementsByClassName("QueuedActions_label__1lTOW")[0]; } function waitAndRetryQueueCheck() { if (!isRunning) return; retryCount++; if (retryCount >= currentConfig.maxRetries) { updateStatus(t.status.timeout, 'error'); stopAutomation(); return; } setTimeout(() => { if (isRunning) ExecuteQueueCheck(); }, currentConfig.retryDelay); } function ExecuteQueueCheck() { if (!isRunning) return; try { const queueElement = document.getElementsByClassName("QueuedActions_queuedActions__2xerL")[0]; if (!queueElement){ updateStatus(t.status.queueNotFull, 'success'); addTaskToQueue(currentConfig.planetIndex, currentConfig.battleCount); setTimeout(() => isRunning && ExecuteQueueCheck(), 2000); return; } if (!isQueueExpanded()) { queueElement.click(); return setTimeout(() => isRunning && ExecuteQueueCheck(), 500); } const labelElement = document.getElementsByClassName("QueuedActions_label__1lTOW")[0]; const match = labelElement.textContent.match(/\((\d+)\/(\d+)\)/); if (!match) throw new Error("Matching number format not found"); const numerator = parseInt(match[1]); const denominator = parseInt(match[2]); updateStatus(`${t.status.queueStatus}: ${numerator}/${denominator}`, 'info'); if (numerator < denominator) { updateStatus(t.status.queueNotFull, 'success'); addTaskToQueue(currentConfig.planetIndex, currentConfig.battleCount); setTimeout(() => isRunning && ExecuteQueueCheck(), 2000); } else { updateStatus(t.status.queueFull, 'warning'); waitAndRetryQueueCheck(); } } catch (error) { updateStatus(t.status.executionError`: ${error.message}`, 'error'); retryCount < 5 ? waitAndRetryQueueCheck() : stopAutomation(); } } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', createUI); } else { createUI(); } })();