From 8383fd9ce24186202695fe9e840b2aa24b239a08 Mon Sep 17 00:00:00 2001 From: kaedelcb <57870068+kaedelcb@users.noreply.github.com> Date: Wed, 2 Jul 2025 19:12:00 +0800 Subject: [PATCH] =?UTF-8?q?v.1.6=E7=89=88=E6=9C=AC=20=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E5=B9=BD=E5=A2=83=E5=8D=B1=E6=88=98=2020250702=20(#1259)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### v.1.6版本:20250702 - **优化**: 1. 优化没找到地脉花领奖的超时退出处理。 2. 优化树脂识别OCR区域。 3. 优化LOG和代码写法和整理。 --- repo/js/AutoStygianOnslaught/README.md | 7 + repo/js/AutoStygianOnslaught/main.js | 229 +++++++++++---------- repo/js/AutoStygianOnslaught/manifest.json | 2 +- 3 files changed, 128 insertions(+), 110 deletions(-) diff --git a/repo/js/AutoStygianOnslaught/README.md b/repo/js/AutoStygianOnslaught/README.md index c60357c1..baef81a2 100644 --- a/repo/js/AutoStygianOnslaught/README.md +++ b/repo/js/AutoStygianOnslaught/README.md @@ -94,5 +94,12 @@ 4. 优化各种`异常状态`的退出处理方法。 5. 优化当有须臾树脂时,脆弱树脂不显示时的处理。 + ### v.1.6版本:20250702 + +- **优化**: +1. 优化没找到地脉花领奖的超时退出处理。 +2. 优化树脂识别OCR区域。 +3. 优化LOG和代码写法和整理。 + diff --git a/repo/js/AutoStygianOnslaught/main.js b/repo/js/AutoStygianOnslaught/main.js index 241dc788..61ed8c84 100644 --- a/repo/js/AutoStygianOnslaught/main.js +++ b/repo/js/AutoStygianOnslaught/main.js @@ -1,18 +1,16 @@ (async function () { let challengeNum = settings.challengeNum;//挑战次数 - if (challengeNum === undefined || challengeNum === ""){challengeNum = 15; } + if (challengeNum === undefined || challengeNum === ""){challengeNum = 15; }//挑战次数 let challengeName = settings.challengeName;//挑战BOSS - if (challengeName === undefined || challengeName === ""){throw new Error("挑战Boss未配置,请在JS配置中选择...")} - let Startforward = settings.Startforward*1000 ? settings.Startforward*1000 : 1000; + if (challengeName === undefined || challengeName === ""){throw new Error("挑战Boss未配置,请在JS配置中选择...")}//初始化处理 + let Startforward = settings.Startforward*1000 ? settings.Startforward*1000 : 1000;//开始战斗的前进时间 var Fighttimeout = settings.timeout * 1000 ? settings.timeout * 1000 : 240000;//战斗超时时间,默认为240秒 const ocrRegion1 = { x: 643, y: 58, width: 800, height: 800 }; // 上方挑战成功区域 const ocrRegion2 = { x: 780, y: 406, width: 370, height: 135 }; // 中间挑战失败区域 - // const ocrRegion3 = { x: 1782, y: 1023, width: 64, height: 29 }; // 右下角space区域 - const ocrRo1 = RecognitionObject.ocr(ocrRegion1.x, ocrRegion1.y, ocrRegion1.width, ocrRegion1.height); - const ocrRo2 = RecognitionObject.ocr(ocrRegion2.x, ocrRegion2.y, ocrRegion2.width, ocrRegion2.height); - // const ocrRo3 = RecognitionObject.ocr(ocrRegion3.x, ocrRegion3.y, ocrRegion3.width, ocrRegion3.height); - var Rewardsuse = settings.Rewardsuse ? settings.Rewardsuse : "1/2"; + const ocrRo1 = RecognitionObject.ocr(ocrRegion1.x, ocrRegion1.y, ocrRegion1.width, ocrRegion1.height);//上方挑战成功区域OCR对象 + const ocrRo2 = RecognitionObject.ocr(ocrRegion2.x, ocrRegion2.y, ocrRegion2.width, ocrRegion2.height);//中间挑战失败区域OCR对象 + var Rewardsuse = settings.Rewardsuse ? settings.Rewardsuse : "1/2";//树脂使用类型,默认为1/2,即浓缩树脂和原粹树脂 var resinTypes = Rewardsuse.split("/"); var rewards = []; var onerewards, secendrewards, threendrewards, fourdrewards; @@ -23,22 +21,22 @@ } rewards.push(resinType); } - const resinTypeMap = ["","使用1个浓缩树脂,获取2倍产出", "使用20个原粹树脂", "使用1个脆弱树脂,获取3倍产出", "使用1个须臾树脂,获取3倍产出"]; - const golbalRewards = ["","浓缩树脂","原粹树脂","脆弱树脂","须臾树脂"]; // 表示四个奖励的选项 + const resinTypeMap = ["","使用1个浓缩树脂,获取2倍产出", "使用20个原粹树脂", "使用1个脆弱树脂,获取3倍产出", "使用1个须臾树脂,获取3倍产出"];//识别树脂领奖文字 + const golbalRewards = ["","浓缩树脂","原粹树脂","脆弱树脂","须臾树脂"]; // 对应四种树脂 // 根据 rewards 数组长度,依次赋值给对应的变量 if (rewards.length > 0) onerewards = golbalRewards[rewards[0]]; if (rewards.length > 1) secendrewards = golbalRewards[rewards[1]]; if (rewards.length > 2) threendrewards = golbalRewards[rewards[2]]; if (rewards.length > 3) fourdrewards = golbalRewards[rewards[3]]; - const golbalRewardText = [onerewards, secendrewards, threendrewards, fourdrewards].filter(Boolean);// + const golbalRewardText = [onerewards, secendrewards, threendrewards, fourdrewards].filter(Boolean);//过滤树脂使用类型 - var advanceNum = 0;//前进次数 - var verticalNum = 0; - var resinAgain = false; + var advanceNum = 0;//前进寻找地脉之花次数 + var verticalNum = 0;//重试寻找地脉之花次数 + var resinAgain = false;//是否重试标志 var Artifacts = settings.Artifacts ? settings.Artifacts : "保持圣遗物奖励不变"; - //建立一个数值映射所有圣遗物对应需要识别的图片 + //映射所有圣遗物对应需要识别的图片 var artifactImageMap = { "长夜之誓 / 深廊终曲": "assets/Artifacts/artifact_1.bmp", "黑曜秘典 / 烬城勇者绘卷": "assets/Artifacts/artifact_2.bmp", @@ -60,6 +58,14 @@ "如雷的盛怒 / 平息鸣雷的尊者": "assets/Artifacts/artifact_18.bmp" }; + //树脂识别图片 + var condensedResin = "assets/condensed_resin_count.png"; + var originalResin = "assets/original_resin_count.png"; + var fragileResin = "assets/fragile_resin_count.png"; + var momentResin = "assets/moment_resin_count.png"; + var oneResin = "assets/one.png"; + + //文字识别封装函数 async function Textocr(wenzi="空参数",chaotime=10,clickocr=0,debugcode=0,x=0,y=0,w=1920,h=1080) { const startTime = new Date(); for (let ii = 0; ii < 10; ii++) @@ -92,6 +98,7 @@ } } + // 图片识别封装函数 async function imageRecognition(imagefilePath="空参数",timeout=10,afterBehavior=0,debugmodel=0,xa=0,ya=0,wa=1920,ha=1080) { const startTime = new Date(); const Imagidentify = RecognitionObject.TemplateMatch(file.ReadImageMatSync(imagefilePath)); @@ -114,12 +121,7 @@ await sleep(1200); } - var condensedResin = "assets/condensed_resin_count.png"; - var originalResin = "assets/original_resin_count.png"; - var fragileResin = "assets/fragile_resin_count.png"; - var momentResin = "assets/moment_resin_count.png"; - var oneResin = "assets/one.png"; - + //树脂数量获取函数 async function getRemainResinStatus() { var condensedResinCount = 0; // 浓缩树脂 var originalResinCount = 0; // 原粹树脂 @@ -170,13 +172,13 @@ var momentResinCountRa = await imageRecognition(momentResin,0.1, 0, 1,1170,0,350,100); if (momentResinCountRa.found) { // await moveMouseTo(momentResinCountRa.x+momentResinCountRa.w+15+momentResinCountRa.w+50,momentResinCountRa.y-15+momentResinCountRa.h+25); - let countArea = await Textocr("",0.5, 0, 2,momentResinCountRa.x+momentResinCountRa.w+15,momentResinCountRa.y-15,momentResinCountRa.w+50,momentResinCountRa.h+25);// + let countArea = await Textocr("",0.5, 0, 2,momentResinCountRa.x+momentResinCountRa.w+20,momentResinCountRa.y-15,60,40);// if (countArea.found){ //log.info("须臾树脂识别数量结果:"+ countArea.text); momentResinCount = countArea.text } else{ - var oneRa = await imageRecognition(oneResin,0.1, 0, 1,momentResinCountRa.x+momentResinCountRa.w+15,momentResinCountRa.y-15,momentResinCountRa.w+50,momentResinCountRa.h+25); + var oneRa = await imageRecognition(oneResin,0.1, 0, 1,momentResinCountRa.x+momentResinCountRa.w+20,momentResinCountRa.y-15,60,40); if (oneRa.found){ momentResinCount = "1"; }else{ @@ -190,14 +192,14 @@ { var fragileResinCountRa = await imageRecognition(fragileResin,0.1, 0, 1,1170,0,350,100); if (fragileResinCountRa.found) { - // await moveMouseTo(fragileResinCountRa.x,fragileResinCountRa.y); - let countArea = await Textocr("",0.5, 0, 2,fragileResinCountRa.x+fragileResinCountRa.w+15,fragileResinCountRa.y-15,fragileResinCountRa.w+50,fragileResinCountRa.h+25);// + // await moveMouseTo(fragileResinCountRa.x+fragileResinCountRa.w+20,fragileResinCountRa.y-15); + let countArea = await Textocr("",0.5, 0, 2,fragileResinCountRa.x+fragileResinCountRa.w+20,fragileResinCountRa.y-15,60,40);// if (countArea.found){ // log.info("脆弱树脂识别数量结果:"+ countArea.text); fragileResinCount = countArea.text } else{ - var oneRa = await imageRecognition(oneResin,0.1, 0, 1,fragileResinCountRa.x+fragileResinCountRa.w+15,fragileResinCountRa.y-15,fragileResinCountRa.w+50,fragileResinCountRa.h+25); + var oneRa = await imageRecognition(oneResin,0.1, 0, 1,fragileResinCountRa.x+fragileResinCountRa.w+20,fragileResinCountRa.y-15,60,40); if (oneRa.found){ fragileResinCount = "1"; }else{ @@ -215,53 +217,58 @@ return {condensedResinCount,originalResinCount,fragileResinCount,momentResinCount} } - //征讨之花领奖 + //征讨之花领奖寻找函数 const autoNavigateToReward = async () => { - // 定义识别对象 - const boxIconRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync("assets/box.png")); - - advanceNum = 0;//前进次数 - //调整为俯视视野 - middleButtonClick(); - await sleep(800); - moveMouseBy(0, 1030); - await sleep(400); - moveMouseBy(0, 920); - await sleep(400); - moveMouseBy(0, 710); - log.info("开始领奖"); + // 定义识别对象 + const boxIconRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync("assets/box.png")); + + advanceNum = 0;//前进次数 + //调整为俯视视野 + middleButtonClick(); + await sleep(800); + moveMouseBy(0, 1030); + await sleep(400); + moveMouseBy(0, 920); + await sleep(400); + moveMouseBy(0, 710); + log.info("开始领奖"); - while (true) { - // 1. 优先检查是否已到达领奖点 - let captureRegion = captureGameRegion(); - let rewardTextArea = captureRegion.DeriveCrop(1210, 515, 200, 50); - let rewardResult = rewardTextArea.find(RecognitionObject.ocrThis); - // 检测到特点文字则结束!!! - if (rewardResult.text == "激活地脉之花") { - log.info("已到达领奖点,检测到文字: " + rewardResult.text); - return true; - } - else if(advanceNum > 80){ + while (true) { + // 1. 优先检查是否已到达领奖点 + let captureRegion = captureGameRegion(); + let rewardTextArea = captureRegion.DeriveCrop(1210, 515, 200, 50); + let rewardResult = rewardTextArea.find(RecognitionObject.ocrThis); + // 检测到特点文字则结束!!! + if (rewardResult.text == "激活地脉之花") { + log.info("已到达领奖点,检测到文字: " + rewardResult.text); + return true; + } + else if(advanceNum > 40){ + await getOut(); + await await genshin.returnMainUi(); throw new Error('前进时间超时'); - } - // 2. 未到达领奖点,则调整视野 - for(let i = 0; i < 100; i++){ + } + // 2. 未到达领奖点,则调整视野 + for(let i = 0; i < 100; i++){ captureRegion = captureGameRegion(); let iconRes = captureRegion.Find(boxIconRo); let climbTextArea = captureRegion.DeriveCrop(1808, 1030, 25, 25); let climbResult = climbTextArea.find(RecognitionObject.ocrThis); // 检查是否处于攀爬状态 - if (climbResult.isEmpty()){ - log.info("检侧到页面错误,尝试脱离"); - let SHU = Textocr("地脉之花", 0.3, 1, 0, 840,225, 230, 125); - if (SHU.found){return true;} - await keyDown("w"); - await keyPress("VK_ESCAPE"); - await sleep(500); - await keyDown("w"); - await sleep(5000); - await keyUp("w"); + if (climbResult.isEmpty()){ + let SHU = Textocr("地脉之花", 0.3, 1, 0, 840,225, 230, 125); + if (SHU.found){ + return true; + } + log.info("检侧到页面错误,尝试脱离"); + await keyDown("w"); + await keyPress("VK_ESCAPE"); + await sleep(500); + await keyDown("w"); + await sleep(5000); + await keyUp("w"); } + if (iconRes.x >= 920 && iconRes.x <= 980 && iconRes.y <= 540) { advanceNum++; log.info(`视野已调正,前进第${advanceNum}次`); @@ -276,14 +283,16 @@ moveMouseBy(adjustAmount * adjustAmount2, 0); await sleep(100); } - + if(i > 97) { if (verticalNum >= 2) { verticalNum = 0; + await getOut(); + await await genshin.returnMainUi(); throw new Error('领取超时'); } log.info("领取超时,重新尝试1次"); - await genshin.returnMainUi(); await sleep(1000);//退出待写 + await sleep(1000); return false; } } @@ -299,6 +308,7 @@ } } + //向前寻找钥匙函数 async function readyFightIn(){ var startTime = new Date(); await sleep(500); @@ -320,7 +330,7 @@ return false } - //异步检测战斗,来自D捣蛋&秋云佬的全自动地脉花的代码 + //异步检测战斗执行函数,来自D捣蛋&秋云佬的全自动地脉花的代码 async function autoFight(timeout) { const cts = new CancellationTokenSource(); log.info("开始战斗"); @@ -332,6 +342,7 @@ return fightResult; } + //异步检测战斗结果函数 async function recognizeTextInRegion(timeout) { return new Promise((resolve, reject) => { (async () => { @@ -383,7 +394,7 @@ }); } - // 领取奖励更换 + //圣遗物奖励更换函数 async function selectionHolyRelics() { let artifactImagePath = artifactImageMap[Artifacts]; @@ -445,8 +456,9 @@ return true; } + // 领取奖励函数 async function claimRewards() { - log.info(`尝试领取奖励,优先${onerewards}'`); + // log.info(`尝试领取奖励,优先${onerewards}'`); let SHUN01 = await Textocr("激活地脉之花",0.6,2,0,1188,358,200,400); let SHUN02 = await Textocr("地脉之花", 0.2, 1, 0, 840,225, 230, 125); if (SHUN01.found || SHUN02.found) { @@ -456,7 +468,8 @@ { log.warn("未找到地脉之花,尝试向前寻找...") await keyDown("W");await sleep(300);await keyUp("W"); - await keyPress("F"); + await keyPress("F"); + await sleep(1000); } await sleep(300); @@ -476,7 +489,7 @@ await sleep(100); await click(SHU.x+550,SHU.y) await sleep(300); - log.info(` ${resinTypeMap[rewards[i]]} 获取奖励...`); + log.info(`${resinTypeMap[rewards[i]]} 获取奖励...`); await Textocr("锁定辅助",10,0,0,1768,0,115,90); let { condensedResinCount, originalResinCount, fragileResinCount , momentResinCount} = await getRemainResinStatus(); @@ -501,7 +514,6 @@ if (shouldExit) { - log.warn("树脂耗尽,停止执行..."); await sleep(1000); await keyPress("VK_ESCAPE"); await sleep(1000); @@ -520,6 +532,7 @@ return false; } + // 进入秘境入口函数 async function VeinEntrance() { for (let i = 0;i < 2;i++) { let JIECHU = await Textocr("F",2,2,0,1098,519,35,32); @@ -544,6 +557,7 @@ } } + //秘境内退出函数 async function getOut() { for (let i = 0;i < 2;i++){ @@ -564,7 +578,7 @@ } - log.warn("自动幽境危战版本:v1.5"); + log.warn("自动幽境危战版本:v1.6"); log.warn("请保证队伍战斗实力,战斗失败或执行错误,会重试两次..."); log.warn("使用前请在 <<幽境危战>> 中配置好战斗队伍..."); log.info("使用树脂类型数量:{0} ", rewards.length) @@ -577,18 +591,22 @@ resinAgain = false; //重试标志 try{ + //1.导航进入页面 await genshin.returnMainUi(); await pathingScript.runFile(`assets/全自动幽境危战.json`); await VeinEntrance(); - // 进入-选择难道 + //2.难度确认和选择 let intoAction = await Textocr("单人挑战",10,0,0,1554,970,360, 105); - if (!intoAction.found) {await genshin.returnMainUi();throw new Error("未进入挑战页面,停止执行...")} + if (!intoAction.found){ + await genshin.returnMainUi(); + throw new Error("未进入挑战页面,停止执行...") + } let adjustmentType = await Textocr("至危挑战", 1, 0, 0,797,144,223,84); if (adjustmentType.found) { log.warn("找到至危挑战,尝试切换...") await sleep(500); - await click(890,191) + await click(adjustmentType.x,adjustmentType.y) await sleep(500); } let hardMode = await Textocr("困难", 0.3, 0, 0,1049,157,72,47); @@ -604,7 +622,7 @@ await click(1093,399); } - //圣遗物奖励选择 + //3.圣遗物奖励选择 if (Artifacts != "保持圣遗物奖励不变"){ let artifact = await imageRecognition(artifactImageMap[Artifacts],0.2,0,0,186,972,71,71); if (!artifact.found) { @@ -616,54 +634,44 @@ } } - //多点击一次,保证进入挑战页面 + //4.进入秘境 await sleep(500); await click(intoAction.x,intoAction.y) await sleep(1000); await click(intoAction.x,intoAction.y) + let enter = await Textocr("Enter",15,0,0,18,990,156,71,71); + if (!enter.found){ + await genshin.returnMainUi(); + throw new Error("未进入秘境,停止执行...") + } - //进入秘境 - let enter = await Textocr("Enter",10,0,0,18,990,156,71,71); - if (!enter.found){await genshin.returnMainUi();throw new Error("未进入秘境,停止执行...")}//退出待写 - - //向前走进入挑战 + //5.向前走进入挑战 if (!(await readyFightIn())){ await getOut(); await genshin.returnMainUi(); throw new Error("未进入准备战斗,停止执行...") - }//退出待写 + } await sleep(1000); - //选择挑战怪兽 + //6.选择挑战boss log.info("选择挑战Boss:'{0}' 挑战次数:'{1}'", challengeName,challengeNum) log.info(`期间树脂耗尽会自动退出秘境...`); + const clickCoordinates = [ { x: 207, y: 349 }, { x: 239, y: 531 }, { x: 227, y: 713 } ]; // Boss坐标1~3 + await click(clickCoordinates[challengeName - 1].x, clickCoordinates[challengeName - 1].y); + + //6.5选择队员-苏婷老师-待写 + //log.warn("队伍选择功能等伟大的苏苏老师考完试做...") - switch (challengeName) { - case "1": - await click(207,349); - break; - case "2": - await click(239,531); - break; - case "3": - await click(227,713); - break; - default: - throw new Error("未知的挑战Boss类型"); - } - - //选择队员-苏婷老师-待写 - // log.warn("队伍选择功能等伟大的苏苏老师考完试做...") - + //7.开始挑战 await Textocr("开始挑战",1,1,0,1554,970,360, 105); - var resinexhaustion = false; // 条件1:树脂耗尽 - //开始战斗循环 + //8.战斗循环 for (let i = 0;i < challengeNum; i++) { - //进入秘境 - log.info("进入战斗环境,开始第 {0} 次战斗", i+1) + log.info("进入战斗环境,开始第 {0} 次战斗", i+1) + + //8.1自动战斗 for (let fightCount = 0; fightCount < 3; fightCount++) { let battleBegins = await Textocr("战斗开始",20,0,0,877,235,164,50); @@ -707,6 +715,7 @@ } } + //8.2领取奖励 if (resinAgain != true) { await sleep(1000); @@ -758,7 +767,7 @@ } } - //是否继续 + //8.3判断继续或退出 if (challengeNum == i+1 || resinexhaustion == true || resinAgain == true ){ log.info(resinAgain ? "累计战斗失败 3 次,退出秘境..." : (challengeNum == i+1) ? `完成 ${i+1}/${challengeNum} 次战斗,退出挑战...`: `树脂耗尽,退出挑战...`); @@ -790,12 +799,14 @@ await sleep(500); } } - catch (error) { + catch (error) { + //9.执行错误,重试处理 log.error(`执行过程中发生错误:${error.message}`); resinAgain = true; await genshin.returnMainUi(); continue; - }finally{ + }finally{ + //10.结束脚本 await genshin.returnMainUi(); if (resinAgain == false) log.info(`Auto自动幽境危战结束...`); } diff --git a/repo/js/AutoStygianOnslaught/manifest.json b/repo/js/AutoStygianOnslaught/manifest.json index 112b135d..ba4fe049 100644 --- a/repo/js/AutoStygianOnslaught/manifest.json +++ b/repo/js/AutoStygianOnslaught/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 1, "name": "自动幽境危战", - "version": "1.5", + "version": "1.6", "tags": ["幽境危战"], "bgi_version": "0.44.8", "description": "请先配置好秘境内的队伍,幽境危战战斗失败或执行错误会重试一次,请保证队伍实力",