
新内容,新点数
对于已经完成之前内容的玩家,可以直接加载新的操作表,并运行脚本;
对于未完成之前内容的玩家,新的操作表会加载到之前操作表的后面,可以连续运行两部分的操作模拟。
注意事项: 模拟拖拽时不要使用鼠标滚轮移动页面否则物品会乱飞
// ==================== 操作表更新 ====================
(function() {
'use strict';
// 定义新增的操作阶段
const NEW_MANUALS = [
// ========== Manual 15: 点树液桶 ==========
{name: "树液桶", actions: [
{type: 'click', page: 1, panel: 3, x: 40, y: 77, wait: 5000}
]},
// ========== Manual 16: 浆果丛 ==========
{name: "浆果丛", actions: [
{type: 'click', page: 1, panel: 11, x: 69, y: 57, wait: 1000},
{type: 'click', page: 1, panel: 11, x: 77, y: 76, wait: 1000},
{type: 'click', page: 1, panel: 11, x: 94, y: 76, wait: 1000},
{type: 'click', page: 1, panel: 11, x: 86, y: 56, wait: 1000},
{type: 'click', page: 1, panel: 11, x: 55, y: 76, wait: 1000}
]},
// ========== Manual 17: 找蟋蟀 ==========
{name: "点灌木丛找蟋蟀", actions: [
{type: 'click', page: 1, panel: 7, x: 9, y: 70, wait: 5000}
]},
// ========== Manual 18: 蟋蟀和蘑菇 ==========
{name: "蟋蟀和蘑菇", actions: [
{type: 'click', page: 1, panel: 6, x: 26, y: 77, wait: 800},
{type: 'click', page: 1, panel: 6, x: 83, y: 84, wait: 800}
]},
// ========== Manual 19: 收集各种材料 ==========
{name: "收集各种材料", actions: [
{type: 'click', page: 1, panel: 4, x: 51, y: 52, wait: 1000},
{type: 'click', page: 1, panel: 5, x: 7, y: 16, wait: 1000},
{type: 'click', page: 1, panel: 5, x: 37, y: 89, wait: 1000},
{type: 'click', page: 1, panel: 7, x: 20, y: 80, wait: 1000},
{type: 'click', page: 1, panel: 7, x: 80, y: 81, wait: 1000},
{type: 'click', page: 1, panel: 8, x: 13, y: 82, wait: 1000},
{type: 'click', page: 1, panel: 8, x: 36, y: 82, wait: 1000},
{type: 'click', page: 1, panel: 10, x: 32, y: 85, wait: 1000},
{type: 'click', page: 1, panel: 10, x: 65, y: 63, wait: 1000},
{type: 'click', page: 1, panel: 12, x: 92, y: 12, wait: 4000}
]},
// ========== Manual 20: 打开井盖 ==========
{name: "打开井盖", actions: [
{type: 'click', page: 1, panel: 12, x: 63, y: 70, wait: 800},
{type: 'click', page: 1, panel: 12, x: 63, y: 70, wait: 800},
{type: 'click', page: 1, panel: 12, x: 58, y: 81, wait: 800},
{type: 'click', page: 1, panel: 12, x: 63, y: 70, wait: 800},
{type: 'click', page: 1, panel: 12, x: 70, y: 81, wait: 800},
{type: 'click', page: 1, panel: 12, x: 58, y: 78, wait: 800},
{type: 'click', page: 1, panel: 12, x: 58, y: 78, wait: 800},
{type: 'click', page: 1, panel: 12, x: 63, y: 70, wait: 800},
{type: 'click', page: 1, panel: 12, x: 71, y: 79, wait: 4000}
]},
// ========== Manual 21: 入井 ==========
{name: "入井", actions: [
{type: 'click', page: 1, panel: 13, x: 42, y: 70, wait: 2000}
]},
// ========== Manual 22: 药罐 ==========
{name: "入井", actions: [
{type: 'click', page: 1, panel: 16, x: 85, y: 62, wait: 5000}
]},
// ========== Manual 23: 勺子舀树液 ==========
{name: "勺子舀树液", actions: [
{type: 'drag', sliderId: 'page1panel20-477', startCoord: {x: 71, y: 80}, endCoord: {x: 92, y: 67}, valueChange: {from: 0, to: 1}, wait: 1500},
{type: 'drag', sliderId: 'page1panel20-765', startCoord: {x: 71, y: 80}, endCoord: {x: 47, y: 43}, valueChange: {from: 0, to: 1}, wait: 5000}
]},
// ========== Manual 24: 第一个配方 ==========
{name: "第一个配方", actions: [
{type: 'drag',sliderId: 'page1panel20-948',startCoord: {x: 4, y: 69},endCoord: {x: 47, y: 38},valueChange: {from: 0, to: 1},wait: 1000},
{type: 'drag',sliderId: 'page1panel20-908',startCoord: {x: 29, y: 48},endCoord: {x: 51, y: 39},valueChange: {from: 0, to: 1},wait: 1000},
{type: 'drag',sliderId: 'page1panel20-712',startCoord: {x: 19, y: 44},endCoord: {x: 45, y: 36},valueChange: {from: 0, to: 1},wait: 1000},
{type: 'drag',sliderId: 'page1panel20-908',startCoord: {x: 46, y: 65},endCoord: {x: 50, y: 41},valueChange: {from: 0, to: 1},wait: 1000},
{type: 'drag',sliderId: 'page1panel20-271',startCoord: {x: 60, y: 56},endCoord: {x: 50, y: 36},valueChange: {from: 0, to: 1},wait: 4000}
]},
// ========== Manual 25: 第二个配方 ==========
{name: "第二个配方",actions: [
{type: 'drag',sliderId: 'page1panel20-712',startCoord: {x: 44, y:41},endCoord: {x: 19, y: 44},valueChange: {from: 0, to: 1},wait: 1000},
{type: 'drag',sliderId: 'page1panel20-948',startCoord: {x: 47, y: 38},endCoord: {x: 4, y: 69},valueChange: {from: 0, to: 1},wait: 1000},
{type: 'drag',sliderId: 'page1panel20-712',startCoord: {x: 19, y: 44},endCoord: {x: 44, y:41},valueChange: {from: 0, to: 1},wait: 1000},
{type: 'drag',sliderId: 'page1panel20-378',startCoord: {x: 84, y: 63},endCoord: {x: 46, y: 26},valueChange: {from: 0, to: 1},wait: 1000},
{type: 'drag',sliderId: 'page1panel20-271', startCoord: {x: 62, y: 51},endCoord: {x: 51, y: 34},valueChange: {from: 0, to: 1},wait: 4000}
]},
// ========== Manual 26: 第三个配方 ==========
{name: "第三个配方", actions: [
{type: 'drag', sliderId: 'page1panel20-378', startCoord: {x: 46, y: 28}, endCoord: {x: 84, y: 63}, valueChange: {from: 0, to: 1}, wait: 1000},
{type: 'drag', sliderId: 'page1panel20-876', startCoord: {x: 69, y: 63}, endCoord: {x: 45, y: 34}, valueChange: {from: 0, to: 1}, wait: 1000},
{type: 'drag', sliderId: 'page1panel20-271', startCoord: {x: 62, y: 52}, endCoord: {x: 54, y: 34}, valueChange: {from: 0, to: 1}, wait: 4000}
]},
// ========== Manual 27: 第四个配方 ==========
{name: "第四个配方", actions: [
{type: 'drag', sliderId: 'page1panel20-432', startCoord: {x: 48, y: 42}, endCoord: {x: 45, y: 67}, valueChange: {from: 0, to: 1}, wait: 1000},
{type: 'drag', sliderId: 'page1panel20-908', startCoord: {x: 51, y: 40}, endCoord: {x: 29, y: 50}, valueChange: {from: 0, to: 1}, wait: 1000},
{type: 'drag', sliderId: 'page1panel20-602', startCoord: {x: 76, y: 36}, endCoord: {x: 50, y: 40}, valueChange: {from: 0, to: 1}, wait: 1000},
{type: 'drag', sliderId: 'page1panel20-547', startCoord: {x: 25, y: 61}, endCoord: {x: 51, y: 36 }, valueChange: {from: 0, to: 1}, wait: 1000},
{type: 'drag', sliderId: 'page1panel20-948', startCoord: {x: 4, y: 69}, endCoord: {x: 44, y: 36}, valueChange: {from: 0, to: 1}, wait: 1000},
{type: 'drag', sliderId: 'page1panel20-271', startCoord: {x: 60, y: 49}, endCoord: {x: 52, y:34}, valueChange: {from: 0, to: 1}, wait: 4000}
]},
// ========== Manual 28: 第五个配方 ==========
{name: "第五个配方", actions: [
{type: 'drag', sliderId: 'page1panel20-876', startCoord: {x: 45, y: 34}, endCoord: {x: 69, y: 63}, valueChange: {from: 0, to: 1}, wait: 1000},
{type: 'drag', sliderId: 'page1panel20-712', startCoord: {x: 44, y: 41}, endCoord: {x: 71, y: 42}, valueChange: {from: 0, to: 1}, wait: 1000},
{type: 'drag', sliderId: 'page1panel20-948', startCoord: {x: 44, y: 36}, endCoord: {x: 8, y: 58}, valueChange: {from: 0, to: 1}, wait: 1000},
{type: 'drag', sliderId: 'page1panel20-602', startCoord: {x: 50, y: 40}, endCoord: {x: 60, y: 69}, valueChange: {from: 0, to: 1}, wait: 1000},
{type: 'drag', sliderId: 'page1panel20-908', startCoord: {x: 29, y: 51}, endCoord: {x: 52, y: 40}, valueChange: {from: 0, to: 1}, wait: 1000},
{type: 'drag', sliderId: 'page1panel20-432', startCoord: {x: 46, y: 68}, endCoord: {x: 47, y: 41}, valueChange: {from: 0, to: 1}, wait: 1000},
{type: 'drag', sliderId: 'page1panel20-496', startCoord: {x: 7, y: 85}, endCoord: {x: 48, y: 38}, valueChange: {from: 0, to: 1}, wait: 1000},
{type: 'drag', sliderId: 'page1panel20-271', startCoord: {x: 61, y: 51}, endCoord: {x: 54, y: 35}, valueChange: {from: 0, to: 1}, wait: 4000}
]},
// ========== Manual 29: 点瓦 ==========
{name: "点瓦", actions: [
{type: 'click', page: 1, panel: 21, x: 73, y: 34, wait: 500}
]}
];
// ==================== MANUAL合并 ====================
if (window.MANUAL && Array.isArray(window.MANUAL)) {
// 已存在旧版 MANUAL,追加新内容
const oldCount = window.MANUAL.length;
window.MANUAL.push(...NEW_MANUALS);
console.log(`新内容已合并
`);
} else {
// 不存在旧版 MANUAL,直接加载新内容
window.MANUAL = NEW_MANUALS;
console.log(`新内容已加载`);
}
})();
// ==================== 主逻辑 ====================
(function() {
'use strict';
// ==================== 工具函数 ====================
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function waitForElement(selector, timeout) {
if (timeout === undefined) {
// #page1panel6 需要 3 分钟超时
if (selector === '#page1panel6') {
timeout = 180000;
console.log(`等待蟋蟀两分钟`);
} else {
timeout = 8000; // 默认 8 秒
}
const start = Date.now();
while (Date.now() - start < timeout) {
// 1. 先找到面板容器
const panelContainer = document.querySelector(selector);
if (panelContainer) {
// 2. 查找内层的 .panel-background(绑定监听器的元素)
const clickTarget = panelContainer.querySelector('.panel-background');
if (clickTarget) {
// 返回可点击的内层元素
return clickTarget;
} else {
// 如果没有,继续等待直到达到超时上限
}
}
await sleep(500);
}
throw new Error(`元素未找到: ${selector} (等待了 ${timeout / 1000} 秒)`);
}
}
async function waitForReady(timeout = 10000) {
const start = Date.now();
while (Date.now() - start < timeout) {
if (!document.body.classList.contains('loading')) {
await sleep(200);
return true;
}
await sleep(100);
}
console.warn('等待超时,继续执行');
return false;
}
// ==================== 视觉反馈 ====================
function highlightClick(x, y) {
const dot = document.createElement('div');
dot.style.cssText = `
position: fixed;
left: ${x}px;
top: ${y}px;
width: 20px;
height: 20px;
margin: -10px 0 0 -10px;
border-radius: 50%;
background: rgba(255, 0, 0, 0.5);
border: 2px solid red;
pointer-events: none;
z-index: 999999;
animation: pulse 0.5s ease-out;
`;
document.body.appendChild(dot);
setTimeout(() => dot.remove(), 500);
}
function highlightDrag(startX, startY, endX, endY) {
const line = document.createElement('div');
const length = Math.sqrt(Math.pow(endX - startX, 2) + Math.pow(endY - startY, 2));
const angle = Math.atan2(endY - startY, endX - startX) * 180 / Math.PI;
line.style.cssText = `
position: fixed;
left: ${startX}px;
top: ${startY}px;
width: ${length}px;
height: 3px;
background: linear-gradient(to right, rgba(0, 100, 255, 0.8), rgba(0, 200, 255, 0.8));
transform-origin: 0 50%;
transform: rotate(${angle}deg);
pointer-events: none;
z-index: 999999;
animation: dragFade 1s ease-out;
`;
document.body.appendChild(line);
// 起点标记
const startDot = document.createElement('div');
startDot.style.cssText = `
position: fixed;
left: ${startX}px;
top: ${startY}px;
width: 12px;
height: 12px;
margin: -6px 0 0 -6px;
border-radius: 50%;
background: rgba(0, 100, 255, 0.6);
border: 2px solid blue;
pointer-events: none;
z-index: 999999;
animation: dragFade 1s ease-out;
`;
document.body.appendChild(startDot);
// 终点标记
const endDot = document.createElement('div');
endDot.style.cssText = `
position: fixed;
left: ${endX}px;
top: ${endY}px;
width: 12px;
height: 12px;
margin: -6px 0 0 -6px;
border-radius: 50%;
background: rgba(0, 200, 255, 0.6);
border: 2px solid cyan;
pointer-events: none;
z-index: 999999;
animation: dragFade 1s ease-out;
`;
document.body.appendChild(endDot);
setTimeout(() => {
line.remove();
startDot.remove();
endDot.remove();
}, 1000);
}
const style = document.createElement('style');
style.textContent = `
@keyframes pulse {
0% { transform: scale(0.5); opacity: 1; }
100% { transform: scale(2); opacity: 0; }
}
@keyframes dragFade {
0% { opacity: 1; }
70% { opacity: 1; }
100% { opacity: 0; }
}
`;
document.head.appendChild(style);
// ==================== 操作执行 ====================
async function simulateClick({page, panel, x, y, wait = 1000, desc = ''}) {
const selector = `#page${page}panel${panel}`;
const element = await waitForElement(selector);
const rect = element.getBoundingClientRect();
const clientX = rect.left + rect.width * x / 100;
const clientY = rect.top + rect.height * y / 100;
highlightClick(clientX, clientY);
const clickEvent = new MouseEvent('click', {
bubbles: true,
cancelable: true,
clientX: clientX,
clientY: clientY,
view: window
});
element.dispatchEvent(clickEvent);
const descText = desc ? ` (${desc})` : '';
console.log(` ✓ Panel ${panel} (${x}%, ${y}%)${descText}`);
await waitForReady();
await sleep(wait);
}
async function simulateDrag({sliderId, startCoord, endCoord, valueChange, wait = 1500}) {
const element = document.getElementById(sliderId);
if (!element) {
console.error(` ✗ 元素未找到: ${sliderId}`);
return;
}
// 检测元素类型:滑块 vs 可拖拽面板
const isDraggablePanel = element.hasAttribute('candrag') && element.getAttribute('candrag') === 'true';
if (isDraggablePanel) {
// ========== 可拖拽面板模式 ==========
console.log(` 🔄 拖拽面板 ${sliderId}`);
// 获取父容器(通常是页面容器)
const parentElement = element.parentElement;
const parentRect = parentElement.getBoundingClientRect();
// 关键修正:startCoord 和 endCoord 是相对于父容器的百分比位置
// 需要转换为绝对屏幕坐标
const startX = parentRect.left + parentRect.width * startCoord.x / 100;
const startY = parentRect.top + parentRect.height * startCoord.y / 100;
const endX = parentRect.left + parentRect.width * endCoord.x / 100;
const endY = parentRect.top + parentRect.height * endCoord.y / 100;
// 显示拖拽轨迹
highlightDrag(startX, startY, endX, endY);
// pointerdown + mousedown
element.dispatchEvent(new PointerEvent('pointerdown', {
bubbles: true, cancelable: true, view: window,
clientX: startX, clientY: startY,
button: 0, buttons: 1, pointerId: 1, pointerType: 'mouse', isPrimary: true
}));
element.dispatchEvent(new MouseEvent('mousedown', {
bubbles: true, cancelable: true, view: window,
clientX: startX, clientY: startY, button: 0, buttons: 1
}));
await sleep(50);
// pointermove + mousemove (2次插值)
for (let i = 0; i < 2; i++) {
const currentX = startX + (endX - startX) * (i + 1) / 2;
const currentY = startY + (endY - startY) * (i + 1) / 2;
element.dispatchEvent(new PointerEvent('pointermove', {
bubbles: true, cancelable: true, view: window,
clientX: currentX, clientY: currentY,
button: 0, buttons: 1, pointerId: 1, pointerType: 'mouse', isPrimary: true
}));
element.dispatchEvent(new MouseEvent('mousemove', {
bubbles: true, cancelable: true, view: window,
clientX: currentX, clientY: currentY, button: 0, buttons: 1
}));
await sleep(30);
}
await sleep(100);
// pointerup + mouseup
element.dispatchEvent(new PointerEvent('pointerup', {
bubbles: true, cancelable: true, view: window,
clientX: endX, clientY: endY,
button: 0, buttons: 0, pointerId: 1, pointerType: 'mouse', isPrimary: true
}));
element.dispatchEvent(new MouseEvent('mouseup', {
bubbles: true, cancelable: true, view: window,
clientX: endX, clientY: endY, button: 0, buttons: 0
}));
} else {
// ========== 滑块模式 (原有逻辑保持不变) ==========
console.log(` 🔄 ${sliderId}: ${valueChange.from.toFixed(2)}% → ${valueChange.to.toFixed(2)}%`);
const back = element.querySelector('.rangeslider-back');
const knob = element.querySelector('.rangeslider-knob');
if (!back || !knob) {
console.error(` ✗ 滑块组件未找到`);
return;
}
const sliderRect = element.getBoundingClientRect();
const backRect = back.getBoundingClientRect();
const startY = sliderRect.top + sliderRect.height * startCoord.y / 100;
const endY = sliderRect.top + sliderRect.height * endCoord.y / 100;
const centerX = backRect.left + backRect.width / 2;
// 显示拖拽轨迹
highlightDrag(centerX, startY, centerX, endY);
// pointerdown + mousedown
back.dispatchEvent(new PointerEvent('pointerdown', {
bubbles: true, cancelable: true, view: window,
clientX: centerX, clientY: startY,
button: 0, buttons: 1, pointerId: 1, pointerType: 'mouse', isPrimary: true
}));
back.dispatchEvent(new MouseEvent('mousedown', {
bubbles: true, cancelable: true, view: window,
clientX: centerX, clientY: startY, button: 0, buttons: 1
}));
await sleep(50);
// 2次 pointermove + mousemove
for (let i = 0; i < 2; i++) {
const currentY = startY + (endY - startY) * (i + 1) / 2;
back.dispatchEvent(new PointerEvent('pointermove', {
bubbles: true, cancelable: true, view: window,
clientX: centerX, clientY: currentY,
button: 0, buttons: 1, pointerId: 1, pointerType: 'mouse', isPrimary: true
}));
back.dispatchEvent(new MouseEvent('mousemove', {
bubbles: true, cancelable: true, view: window,
clientX: centerX, clientY: currentY, button: 0, buttons: 1
}));
await sleep(30);
}
await sleep(100);
// pointerup + mouseup
back.dispatchEvent(new PointerEvent('pointerup', {
bubbles: true, cancelable: true, view: window,
clientX: centerX, clientY: endY,
button: 0, buttons: 0, pointerId: 1, pointerType: 'mouse', isPrimary: true
}));
back.dispatchEvent(new MouseEvent('mouseup', {
bubbles: true, cancelable: true, view: window,
clientX: centerX, clientY: endY, button: 0, buttons: 0
}));
await sleep(100);
const finalValue = parseFloat(knob.style.bottom) || 0;
console.log(` ✓ 完成 (${finalValue.toFixed(2)}%)`);
}
await waitForReady();
await sleep(wait);
}
// ==================== 初始化函数 ====================
async function initialize(operationName) {
console.log(`\n🔍 检测到操作: ${operationName}`);
console.log('开始执行初始化...');
const bodyElement = document.body;
const currentPage = bodyElement.getAttribute('page');
switch(operationName) {
case "窗户、沙漏":
if (currentPage === "1") {
try {
await simulateClick({page: 1, panel: 0, x: 17, y: 13, wait: 3000,desc: '切换回白天'});
console.log('✅ 已切换到 Page 0');
} catch (error) {
console.warn('页面切换失败');
}
}
break;
case "树液桶":
if (currentPage === "1") {
break;
}
try {
if (currentPage === "0") {
await simulateClick({page: 0, panel: 0, x: 17, y: 16, wait: 3000, desc: '切换到夜晚'});
} else if (currentPage === "78") {
await simulateClick({page: 78, panel: 0, x: 41, y: 90, wait: 3000, desc: '返回夜晚'});
} else {
console.warn(`⚠️ 未知的起始页面: Page ${currentPage}`);
}
} catch (error) {
console.warn('⚠️ 页面切换失败:', error);
}
break;
default:
break;
}
console.log('✅ 初始化完成\n');
return true;
}
// ==================== 初始化和复位 ====================
const OPERATIONS_REQUIRING_INIT = [
"窗户、沙漏",
"树液桶"
];
// ==================== 控制器 ====================
const Controller = {
config: null,
currentStage: 0,
isRunning: false,
autoMode: false,
isInitialized: false,
async executeStage(index) {
if (!this.config) {
console.error('错误: 未找到 MANUAL 配置,请先加载 Complete Manual.js');
return false;
}
if (index < 0 || index >= this.config.length) {
console.error('阶段索引超出范围');
return false;
}
this.isRunning = true;
const stage = this.config[index];
console.log(`\n${'='.repeat(50)}`);
console.log(`执行阶段 ${index + 1}/${this.config.length}: ${stage.name}`);
console.log(`${'='.repeat(50)}`);
try {
for (let i = 0; i < stage.actions.length; i++) {
if (!this.isRunning) {
console.log('执行已停止');
return false;
}
const action = stage.actions[i];
console.log(`[${i + 1}/${stage.actions.length}]`);
if (action.type === 'click') {
await simulateClick(action);
} else if (action.type === 'drag') {
await simulateDrag(action);
}
}
console.log(`阶段 ${index + 1} 完成`);
this.isRunning = false;
return true;
} catch (error) {
console.error(`执行出错:`, error);
this.isRunning = false;
return false;
}
},
async next() {
// 1. 检查配置是否加载
if (!this.config) {
this.config = window.MANUAL;
if (!this.config) {
console.error('❌ 错误: 未找到 MANUAL 配置,请先加载 Complete Manual.js');
return;
}
}
// 2. 检查是否正在执行
if (this.isRunning) {
console.warn('⚠️ 正在执行中,请等待完成');
return;
}
// 3. 检查是否已完成所有阶段
if (this.currentStage >= this.config.length) {
console.log('\n🎉 所有阶段已完成!');
return;
}
// 4. 获取当前阶段信息
const currentOperation = this.config[this.currentStage];
const operationName = currentOperation.name;
// 5. 检查当前操作是否需要初始化
if (OPERATIONS_REQUIRING_INIT.includes(operationName)) {
console.log(`\n${'━'.repeat(50)}`);
console.log(`⚙️ 检测到需要初始化的操作: ${operationName}`);
console.log(`${'━'.repeat(50)}`);
try {
await initialize(operationName);
} catch (error) {
console.error('❌ 初始化失败:', error);
console.log('尝试继续执行...\n');
}
}
// 6. 执行当前阶段
const success = await this.executeStage(this.currentStage);
// 7. 处理执行结果
if (success) {
this.currentStage++;
if (this.currentStage < this.config.length) {
console.log(`\n💡 输入 next() 继续下一阶段`);
// 自动模式下继续执行
if (this.autoMode) {
await sleep(1000);
await this.next();
}
} else {
console.log('\n🎊 所有阶段已完成!');
}
} else {
console.error('❌ 当前阶段执行失败');
}
},
async auto() {
if (!this.config) {
this.config = window.MANUAL;
if (!this.config) {
console.error('❌ 错误: 未找到 MANUAL 配置,请先加载 Complete Manual.js');
return;
}
}
console.log('\n🚀 启动自动模式');
console.log(`共 ${this.config.length} 个阶段,将自动执行所有步骤\n`);
this.autoMode = true;
await this.next();
},
jumpTo(stageNumber) {
// 1. 检查配置是否加载
if (!this.config) {
this.config = window.MANUAL;
if (!this.config) {
console.error('❌ 错误: 未找到 MANUAL 配置,请先加载 Complete Manual.js');
return;
}
}
// 2. 验证阶段编号
const index = stageNumber - 1;
if (index < 0 || index >= this.config.length) {
console.error(`❌ 阶段编号无效,请输入 1-${this.config.length} 之间的数字`);
return;
}
// 3. 设置当前阶段
this.currentStage = index;
const operationName = this.config[index].name;
// 4. ⭐ 增强的用户提示
console.log(`\n${'━'.repeat(50)}`);
console.log(`📍 已跳转到阶段 ${stageNumber}/${this.config.length}`);
console.log(`📋 操作名称: ${operationName}`);
// 5. 提示是否需要初始化
if (OPERATIONS_REQUIRING_INIT.includes(operationName)) {
console.log(`⚙️ 此操作需要初始化,执行时将自动进行`);
}
console.log(`\n💡 输入 next() 开始执行此阶段`);
console.log(`${'━'.repeat(50)}\n`);
},
stop() {
this.isRunning = false;
this.autoMode = false;
console.log('已停止执行');
}
};
// ==================== 全局接口 ====================
window.next = () => Controller.next();
window.auto = () => Controller.auto();
window.jumpTo = (n) => Controller.jumpTo(n);
window.stop = () => Controller.stop();
// ==================== 初始化提示 ====================
console.log(`
${'━'.repeat(60)}
🎮 饥荒解谜自动化脚本
${'━'.repeat(60)}
脚本已就绪
命令说明:
auto() - 自动执行所有阶段
next() - 执行下一阶段
jumpTo(n) - 跳转到第 n 阶段
stop() - 停止执行
注意:执行期间请勿刷新页面
${'━'.repeat(60)}
`);
// 检查 MANUAL 是否已加载
if (window.MANUAL) {
Controller.config = window.MANUAL;
console.log(`✓ 已加载 ${window.MANUAL.length} 个操作阶段\n`);
} else {
console.log('⚠ 请先加载 Complete Manual.js\n');
}
})();