Files
2025-07-07 00:54:42 +08:00

308 lines
10 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

(async function () {
// 脚本配置参数
// const ACTIVITY_LOCATION = { x: "1200.0", y: "1500.0" }; // 活动坐标
const PATH_FILE_START = "assets/pathing/start.json"; // 地图追踪路径文件
const PATH_FILE_CONTINUE = "assets/pathing/continue.json"; // 地图追踪路径文件
await sleep(1000);
log.info("自动吃金币活动, 启动!")
// 1. 脚本开始前确保在主界面
log.info("确保游戏在主界面状态");
await genshin.returnMainUi();
await sleep(1000);
// 在循环前添加游戏次数限制
// const MAX_GAMES = 2;
const MAX_GAMES = typeof (settings.max_games) === 'undefined' ? 20 : parseInt(settings.max_games, 10);
let gameCount = 0;
log.info("最大游戏次数设定: {MAX_GAMES}次", MAX_GAMES)
// 只要积分未满且游戏次数未达上限,就循环进行匹配和游戏
while (gameCount < MAX_GAMES) {
gameCount++; // 增加游戏计数
log.info("开始第{count}场游戏", gameCount);
// 2. 使用地图追踪走到活动入口
log.info("正在使用地图追踪前往活动入口");
try {
// 运行路径追踪脚本
if (gameCount == 1) {
await pathingScript.runFile(PATH_FILE_START);
} else {
await pathingScript.runFile(PATH_FILE_CONTINUE);
}
log.info("已到达活动入口");
} catch (error) {
log.error("地图追踪失败: {error}", error);
return;
}
// 3. 检测F键交互窗口 - 使用正确的OCR方法
let foundActivity = false;
for (let i = 0; i < 10; i++) { // 最多尝试10次
// 获取游戏截图
const screenshot = captureGameRegion();
// 对整个区域进行OCR - 使用ocrThis
const activityTextRegions = screenshot.findMulti(RecognitionObject.ocrThis);
// 遍历所有OCR结果
for (let j = 0; j < activityTextRegions.count; j++) {
const region = activityTextRegions[j];
if (region.text.includes("跨界挑战")) {
log.info("检测到活动入口");
foundActivity = true;
break;
}
}
if (foundActivity) break;
keyPress('W');
moveMouseBy(0, 100); // 轻微移动视角帮助识别
await sleep(1000);
}
// 4. 按F进入活动界面
log.info("进入活动界面");
keyPress("F");
await sleep(2000); // 等待界面加载
// 5. 精确识别积分信息
const scoreRegion = captureGameRegion().deriveCrop(
1248, // x
360, // y
150, // width
30 // height
);
// 对积分区域进行OCR
const scoreResults = scoreRegion.findMulti(RecognitionObject.ocrThis);
let currentScore = 0;
let maxScore = 0;
let scoreFound = false;
// 遍历所有识别结果
for (let i = 0; i < scoreResults.count; i++) {
const res = scoreResults[i];
// 使用正则表达式匹配积分格式
const match = res.text.match(/(\d+)\s*\/\s*(\d+)/);
if (match && match.length >= 3) {
currentScore = parseInt(match[1]);
maxScore = parseInt(match[2]);
scoreFound = true;
break;
}
}
if (!scoreFound) {
log.error("未识别到积分信息");
// await genshin.returnMainUi();
return;
}
log.info("积分状态: {current}/{max}", currentScore, maxScore);
if (currentScore >= maxScore) {
log.info("PVP活动已完成");
// notification.send("PVP活动已完成");
await genshin.returnMainUi();
await sleep(1000);
return;
}
// 6. 点击开始匹配
log.info("匹配挑战");
// 假设开始按钮在屏幕中间下方位置
click(1560, 1012);
await sleep(1000);
// 7. 等待并确认匹配
let matchFound = false,matchFound_1st = false; //matchFound_1st确认按钮是否点击过
let matchTimeout = 0; //联机确认按钮超时等待(单位:秒)
let beRefusedCount = 0; //被拒绝次数
for (let i = 0; i < 60; i++) { // 最多等待60秒
const confirmRegion = captureGameRegion().deriveCrop(
1037,
706,
280,
64
);
// 执行OCR识别
const confirmResults = confirmRegion.findMulti(RecognitionObject.ocrThis);
log.info("匹配确认区域OCR识别结果数量: {count}", confirmResults.count);
/*处理联机确认按钮
执行逻辑:(如有报错,自己改 或者 反馈naralan0502@gmail.com
如果OCR识别结果数量等于0判断是否已经点击过确认按钮通过变量matchFound_1st确认
超时等待时长matchTimeout++,若超时等待时长==13设置matchFound为true跳出循环
否:继续循环
如果OCR识别结果数量大于0遍历所有识别结果
如果存在确认按钮设置变量matchFound_1st = true超时等待t=0
*/
if(confirmResults.count){
// 遍历所有识别结果
for (let j = 0; j < confirmResults.count; j++) {
const region = confirmResults[j];
// log.info("匹配确认区域OCR结果:位置({x},{y},{w},{h}), 文本: {text}",
// region.x, region.y, region.width, region.height, region.text);
if (region.text.includes("接受")) {
click(1182, 737); // 点击确认按钮
if(matchFound_1st && (++beRefusedCount >= 3)) log.info("兄啊有点点背,被拒绝了{count}次诶", beRefusedCount);
matchFound_1st = true;
log.info("匹配成功, 点击接受");
matchTimeout = 0;
break;
}
}
}
else{
if(matchFound_1st && (++matchTimeout == 13)) { //超时等待13s游戏内联机确认超时时长10s+冷却CD3s
matchFound = true;
log.info("点击确认成功");
break;
}
}
await sleep(1000);
}
if (!matchFound) {
notification.error("匹配超时");
return;
}
// 7 等待进入游戏(直到出现"第1回合"提示)
let roundStarted = false;
const roundStartTime = Date.now();
const ROUND_TIMEOUT = 90 * 1000; // 90秒超时
while (!roundStarted && Date.now() - roundStartTime < ROUND_TIMEOUT) {
const roundRegion = captureGameRegion().deriveCrop(
770,
246,
373,
60
);
const roundText = roundRegion.find(RecognitionObject.ocrThis);
if (roundText && roundText.text && roundText.text.includes("第1回合")) {
log.info("游戏开始");
roundStarted = true;
break;
}
await sleep(1000);
}
if (!roundStarted) {
log.error("未检测到回合开始提示");
notification.error("进入游戏失败");
return;
}
// 8. 进入游戏后模拟操作
log.info("开始模拟操作");
// 随机选择操作
const actions = [
// Shift+W 冲刺前进1秒
async () => {
keyDown("SHIFT");
keyDown("W");
await sleep(1000);
keyUp("W");
keyUp("SHIFT");
},
// Shift+A 冲刺左移1秒
async () => {
keyDown("SHIFT");
keyDown("A");
await sleep(1000);
keyUp("A");
keyUp("SHIFT");
},
// Shift+S 冲刺后退1秒
async () => {
keyDown("SHIFT");
keyDown("S");
await sleep(1000);
keyUp("S");
keyUp("SHIFT");
},
// Shift+D 冲刺右移1秒
async () => {
keyDown("SHIFT");
keyDown("D");
await sleep(1000);
keyUp("D");
keyUp("SHIFT");
},
// 空格跳跃1秒
async () => {
keyDown("SPACE");
await sleep(1000);
keyUp("SPACE");
},
// 1秒内按两下E元素战技
async () => {
// 第一次按E
keyPress("E");
await sleep(700); // 短暂间隔
// 第二次按E
keyPress("E");
await sleep(300); // 总时间1秒
}
];
const startTime = Date.now();
const MAX_GAME_DURATION = 300 * 1000;
while (Date.now() - startTime < MAX_GAME_DURATION) {
// 在屏幕顶部中央检测"挑战完成"文本
const completionRegion = captureGameRegion().deriveCrop(
800, 180, 320, 100
);
const completionResults = completionRegion.findMulti(RecognitionObject.ocrThis);
let challengeCompleted = false;
// 遍历识别结果
for (let i = 0; i < completionResults.count; i++) {
const region = completionResults[i];
if (region.text.includes("挑战完成")) {
challengeCompleted = true;
break;
}
}
if (challengeCompleted) {
log.info("挑战完成");
break;
}
// 随机执行一个操作
const action = actions[Math.floor(Math.random() * actions.length)];
await action();
}
await sleep(20000);
await genshin.returnMainUi();
await sleep(1000);
await genshin.returnMainUi();
}
log.info("已达到最大游戏次数{max}次", MAX_GAMES);
return;
})();