// ==UserScript== // @name 赛尔号启航 手动加速器(开关可控) // @namespace http://tampermonkey.net/ // @version 1.0 // @description 手动开启/关闭全局加速,战斗时开启,日常活动时关闭 // @match https://*.61.com/* // @match https://seer.61.com/* // @match https://s.61.com/* // @run-at document-start // @grant GM_getValue // @grant GM_setValue // @grant GM_addStyle // ==/UserScript== (function() { 'use strict'; // 配置 const defaultSpeed = 3.0; // 默认加速倍数 const minSpeed = 1.0; const maxSpeed = 10.0; const storageKey = 'manual_speed'; const enabledKey = 'manual_enabled'; let speed = GM_getValue(storageKey, defaultSpeed); let enabled = GM_getValue(enabledKey, false); // 默认关闭 console.log('🕹️ 赛尔号启航手动加速器启动,当前状态:' + (enabled ? '开启' : '关闭') + ',速度:' + speed + 'x'); // ---------- 注入时间劫持代码(始终注入,但受开关控制)---------- function injectTimeHijack() { const script = document.createElement('script'); script.textContent = ` (function() { console.log('⏱️ 时间劫持模块注入'); // 保存原始函数 const originalDateNow = Date.now.bind(Date); const originalPerformanceNow = performance.now.bind(performance); const originalRequestAnimationFrame = requestAnimationFrame.bind(window); const originalSetInterval = setInterval.bind(window); const originalSetTimeout = setTimeout.bind(window); const originalGetTime = Date.prototype.getTime; // 状态变量 let enabled = ${enabled}; let speed = ${speed}; let timeScale = enabled ? speed : 1; // 时间基准 let startTime = originalDateNow(); let baseTime = startTime; // 劫持 Date.now Date.now = function() { const realNow = originalDateNow(); if (!enabled) return realNow; return baseTime + (realNow - startTime) * timeScale; }.bind(Date); // 劫持 performance.now performance.now = function() { const realNow = originalPerformanceNow(); if (!enabled) return realNow; return realNow * timeScale; }.bind(performance); // 劫持 Date.prototype.getTime Date.prototype.getTime = function() { const realTime = originalGetTime.call(this); if (!enabled || this === window || this === undefined) return realTime; return baseTime + (realTime - startTime) * timeScale; }; // 劫持 requestAnimationFrame window.requestAnimationFrame = function(callback) { if (!enabled) return originalRequestAnimationFrame(callback); const wrappedCallback = function(timestamp) { const twistedTimestamp = timestamp * timeScale; callback(twistedTimestamp); }; return originalRequestAnimationFrame(wrappedCallback); }.bind(window); // 劫持 setInterval window.setInterval = function(callback, interval, ...args) { if (!enabled) return originalSetInterval(callback, interval, ...args); const realInterval = Math.max(4, interval / timeScale); return originalSetInterval(callback, realInterval, ...args); }.bind(window); // 劫持 setTimeout window.setTimeout = function(callback, delay, ...args) { if (!enabled) return originalSetTimeout(callback, delay, ...args); const realDelay = Math.max(0, delay / timeScale); return originalSetTimeout(callback, realDelay, ...args); }.bind(window); // 控制接口 window.setAcceleratorState = function(enable, newSpeed) { if (enable !== undefined) enabled = enable; if (newSpeed !== undefined) { speed = newSpeed; timeScale = enabled ? speed : 1; } else { timeScale = enabled ? speed : 1; } // 重置时间基准,避免跳跃 startTime = originalDateNow(); baseTime = startTime; console.log('加速器状态:' + (enabled ? '开启' : '关闭') + ',速度:' + speed + 'x'); }; console.log('✅ 时间劫持完成,初始状态:' + (enabled ? '开启' : '关闭') + ',速度:' + speed + 'x'); })(); `; if (document.documentElement) { document.documentElement.appendChild(script); script.remove(); } } // ---------- 创建手动开关面板 ---------- function createControlPanel() { GM_addStyle(` .manual-control { position: fixed; bottom: 20px; left: 20px; background: rgba(0, 0, 0, 0.85); border: 2px solid #ffaa00; border-radius: 10px; color: white; padding: 12px; z-index: 999999; font-family: 'Microsoft YaHei', sans-serif; box-shadow: 0 0 15px rgba(255,170,0,0.5); min-width: 200px; backdrop-filter: blur(5px); } .manual-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; padding-bottom: 5px; border-bottom: 1px solid #444; } .manual-title { font-weight: bold; color: #ffaa00; } .manual-toggle { display: flex; align-items: center; gap: 8px; } .toggle-switch { width: 50px; height: 24px; background: #444; border-radius: 12px; position: relative; cursor: pointer; transition: background 0.2s; } .toggle-switch.on { background: #ffaa00; } .toggle-switch::after { content: ''; position: absolute; width: 20px; height: 20px; background: white; border-radius: 50%; top: 2px; left: 2px; transition: transform 0.2s; } .toggle-switch.on::after { transform: translateX(26px); } .toggle-label { font-size: 14px; color: ${enabled ? '#ffaa00' : '#aaa'}; font-weight: bold; } .speed-row { margin: 10px 0; display: flex; align-items: center; justify-content: space-between; } .speed-value { font-size: 24px; font-weight: bold; color: #ffaa00; } .slider { width: 100%; margin: 10px 0; height: 6px; background: #333; border-radius: 3px; -webkit-appearance: none; } .slider::-webkit-slider-thumb { -webkit-appearance: none; width: 18px; height: 18px; background: #ffaa00; border-radius: 50%; cursor: pointer; border: 2px solid white; } .presets { display: grid; grid-template-columns: repeat(4, 1fr); gap: 5px; margin: 10px 0; } .presets button { background: #333; border: 1px solid #555; color: white; padding: 5px; border-radius: 4px; cursor: pointer; font-size: 12px; transition: all 0.2s; } .presets button:hover { background: #444; border-color: #ffaa00; } .note { font-size: 11px; color: #888; text-align: center; margin-top: 8px; border-top: 1px solid #333; padding-top: 5px; } .note span { color: #ffaa00; } `); const panel = document.createElement('div'); panel.className = 'manual-control'; panel.innerHTML = `
⚡ 手动加速器
${enabled ? '开启' : '关闭'}
当前速度 ${speed.toFixed(1)}x
⏺️ 手动开关,战斗时开启,日常关闭 ⏺️
`; document.body.appendChild(panel); // 拖动功能 let isDragging = false; let offsetX, offsetY; panel.addEventListener('mousedown', (e) => { if (e.target.closest('.presets') || e.target.closest('.slider') || e.target.closest('.toggle-switch')) return; isDragging = true; offsetX = e.clientX - panel.offsetLeft; offsetY = e.clientY - panel.offsetTop; }); document.addEventListener('mousemove', (e) => { if (!isDragging) return; panel.style.left = (e.clientX - offsetX) + 'px'; panel.style.top = (e.clientY - offsetY) + 'px'; panel.style.right = 'auto'; panel.style.bottom = 'auto'; }); document.addEventListener('mouseup', () => isDragging = false); // 开关逻辑 const toggleSwitch = document.getElementById('toggleSwitch'); const toggleLabel = document.getElementById('toggleLabel'); function setEnabled(newEnabled) { enabled = newEnabled; GM_setValue(enabledKey, enabled); toggleSwitch.className = 'toggle-switch ' + (enabled ? 'on' : ''); toggleLabel.textContent = enabled ? '开启' : '关闭'; toggleLabel.style.color = enabled ? '#ffaa00' : '#aaa'; // 调用内部函数更新状态 const script = document.createElement('script'); script.textContent = `if (window.setAcceleratorState) window.setAcceleratorState(${enabled});`; document.documentElement.appendChild(script); script.remove(); console.log('加速器手动切换为:' + (enabled ? '开启' : '关闭')); } toggleSwitch.addEventListener('click', () => { setEnabled(!enabled); }); // 速度控制 const slider = document.getElementById('speedSlider'); const speedDisplay = document.getElementById('speedDisplay'); slider.addEventListener('input', (e) => { speedDisplay.textContent = parseFloat(e.target.value).toFixed(1) + 'x'; }); slider.addEventListener('change', (e) => { const newSpeed = parseFloat(e.target.value); speed = newSpeed; GM_setValue(storageKey, speed); // 更新内部状态 const script = document.createElement('script'); script.textContent = `if (window.setAcceleratorState) window.setAcceleratorState(${enabled}, ${speed});`; document.documentElement.appendChild(script); script.remove(); speedDisplay.textContent = speed.toFixed(1) + 'x'; }); // 预设按钮 panel.querySelectorAll('.presets button').forEach(btn => { btn.addEventListener('click', () => { const newSpeed = parseFloat(btn.dataset.speed); slider.value = newSpeed; speedDisplay.textContent = newSpeed.toFixed(1) + 'x'; // 触发change事件 slider.dispatchEvent(new Event('change')); }); }); } // ---------- 启动 ---------- injectTimeHijack(); if (document.readyState === 'complete') { setTimeout(createControlPanel, 2000); } else { window.addEventListener('load', () => setTimeout(createControlPanel, 2000)); } })();