v.2.1版本 自动幽境危战 20250918 (#1939)

### v.2.1版本:20250918

- **优化**:
1. 改用普通模板匹配浓缩树脂。
2. 适配6.0奖励领取页面,,添加原石使用选项,添加新圣遗物的选择。
3. 添加选择队伍功能。
This commit is contained in:
kaedelcb
2025-09-18 12:04:00 +08:00
committed by GitHub
parent 5960db58dd
commit c0ed55ad8e
12 changed files with 258 additions and 50 deletions

View File

@@ -40,6 +40,12 @@
## 三、更新说明
### v.2.1版本20250918
- **优化**
1. 改用普通模板匹配浓缩树脂。
2. 适配6.0奖励领取页面,,添加原石使用选项,添加新圣遗物的选择。
3. 添加选择队伍功能。
### v.2.0版本20250830

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@@ -3,6 +3,11 @@
var Threshold = genshin.width > 2560 ? 0.65
: genshin.width > 1920 ? 0.7
: 0.8;
var Thresholdr = genshin.width > 2560 ? 0.8
: genshin.width > 1920 ? 0.8
: 0.9;
log.warn(`屏幕分辨率${genshin.width},识别阈值调整为${Threshold}...`);
let challengeNum = settings.challengeNum;//挑战次数
@@ -18,22 +23,42 @@
var Rewardsuse = settings.Rewardsuse ? settings.Rewardsuse : "1/2";//树脂使用类型默认为1/2即浓缩树脂和原粹树脂
var resinTypes = Rewardsuse.split("/");
var rewards = [];
var onerewards, secendrewards, threendrewards, fourdrewards;
var onerewards, secendrewards, threendrewards, fourdrewards,fiverewards;
for (var i = 0; i < resinTypes.length; i++) {
var resinType = parseInt(resinTypes[i]);
if (isNaN(resinType) || resinType < 1 || resinType > 4) {
if (isNaN(resinType) || resinType < 1 || resinType > 5) {
throw new Error("设定的树脂类型无效或缺失,请重新配置");
}
rewards.push(resinType);
}
const resinTypeMap = ["","使用1个浓缩树脂获取2倍产出", "使用20个原粹树脂", "使用1个脆弱树脂获取3产出", "使用1个须臾树脂获取3产出"];//识别树脂领奖文字
const golbalRewards = ["","浓缩树脂","原粹树脂","脆弱树脂","须臾树脂"]; // 对应四种树脂
const resinTypeMap = ["","使用1个浓缩树脂获取3次产出", "使用40个原粹树脂获取2次产出", "使用1个脆弱树脂获取3产出", "使用1个须臾树脂获取3产出","使用20个原粹树脂"];
const resinTypeMap2 = ["使用50原石获取3次产出", "使用100原石获取3次产出", "使用150原石获取3次产出", "使用200原石获取3次产出"];
//原石使用
var primogemUseCount = settings.primogemUseCount ? settings.primogemUseCount : 0;
if (primogemUseCount === undefined || primogemUseCount === null) {
throw new Error("原石使用 参数无效请设置0到6之间的整数值");
}
primogemUseCount = parseInt(primogemUseCount);
if (isNaN(primogemUseCount) || !Number.isInteger(primogemUseCount) || primogemUseCount < 0 || primogemUseCount > 6) {
throw new Error("原石使用 数量设置无效请设置0到6之间的整数值");
}
primogemUseCount = (isNaN(primogemUseCount)) ? 0 : primogemUseCount;
var primogemUseDone = 0;
var resinDone = false;
const golbalRewards = ["","浓缩树脂","原粹树脂40","脆弱树脂","须臾树脂","原粹树脂20"]; // 对应四种树脂
// 根据 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);//过滤树脂使用类型
if (rewards.length > 4) fiverewards = golbalRewards[rewards[4]];
const golbalRewardText = [onerewards, secendrewards, threendrewards, fourdrewards,fiverewards].filter(Boolean);//过滤树脂使用类型
if(primogemUseCount>0){golbalRewardText.push("原石")}
// 根据 rewards 数组长度,依次赋值给对应的变量
var firstawards = false;
var advanceNum = 0;//前进寻找地脉之花次数
var verticalNum = 0;//重试寻找地脉之花次数
@@ -42,7 +67,8 @@
var Artifacts = settings.Artifacts ? settings.Artifacts : "保持圣遗物奖励不变";
//映射所有圣遗物对应需要识别的图片
var artifactImageMap = {
var artifactImageMap = {
"穹境示现之夜 / 纺月的夜歌": "assets/Artifacts/artifact_0.bmp",
"长夜之誓 / 深廊终曲": "assets/Artifacts/artifact_1.bmp",
"黑曜秘典 / 烬城勇者绘卷": "assets/Artifacts/artifact_2.bmp",
"谐律异想断章 / 未竟的遐思": "assets/Artifacts/artifact_3.bmp",
@@ -72,13 +98,16 @@
var rewardsButton = "assets/rewards.png";
var resinImages = [
"assets/model/one.png",
"assets/model/two.png",
"assets/model/three.png",
"assets/model/four.png",
"assets/model/five.png"
"assets/zero.png",
"assets/one.png",
"assets/two.png",
"assets/three.png",
"assets/four.png",
"assets/five.png"
];
FightTeam = settings.FightTeam;
//文字识别封装函数
async function Textocr(wenzi="空参数",chaotime=10,clickocr=0,debugcode=0,x=0,y=0,w=1920,h=1080) {
const startTime = new Date();
@@ -128,6 +157,11 @@
Imagidentify.InitTemplate();
}
// Imagidentify.Name = "测试";
// Imagidentify.DrawOnWindow=true;
// Imagidentify.InitTemplate();
for (let ii = 0; ii < 10; ii++) {
captureRegion = captureGameRegion(); // 获取一张截图
res = captureRegion.DeriveCrop(xa, ya, wa, ha).Find(Imagidentify);
@@ -156,27 +190,47 @@
var fragileResinCount = 0; // 脆弱树脂
var momentResinCount = 0; //须臾树脂
// var shuz = []
// 浓缩树脂
var condensedResinCountRa = await imageRecognition(condensedResin,0.2, 0, 0,800,15,700,70,Threshold);
if (condensedResinCountRa.found) {
if (condensedResinCountRa.found) {
//测试用
// log.info("检测到浓缩树脂图标");
// await moveMouseTo(condensedResinCountRa.x+condensedResinCountRa.w,condensedResinCountRa.y);
// log.warn("X{0} Y{1} W{2} H{3}",condensedResinCountRa.x,condensedResinCountRa.y,condensedResinCountRa.w,condensedResinCountRa.h,);
// if (Math.abs(condensedResinCountRa.x - 1256) > 5 || condensedResinCountRa.y != 33){
// throw new Error("浓缩图标错误");
// }
// log.warn("T{0}",Thresholdr);
// log.warn("L{0}",resinImages.length);
for (let i = 0; i < resinImages.length; i++) {
if(i==0){await sleep(1000);}
let countArea = await imageRecognition(resinImages[i],0.2, 0, 0,condensedResinCountRa.x+condensedResinCountRa.w*0.9,condensedResinCountRa.y,condensedResinCountRa.w*2,condensedResinCountRa.h,Threshold);
if (countArea.found){
condensedResinCount =i+1;
if(i==0){await sleep(500);}
// log.warn("i{0}",i);
let countArea = await imageRecognition(resinImages[i],0, 0, 0,condensedResinCountRa.x+condensedResinCountRa.w+15,condensedResinCountRa.y,30,32,Thresholdr);
if (countArea.found){
// await moveMouseTo(countArea.x,countArea.y);
condensedResinCount =i;
// shuz.push(i);
break;
}
if (i==4){log.info("未检测到浓缩数量强制为1"); condensedResinCount=1;}
if (i==5){log.info("未检测到浓缩数量强制为1"); condensedResinCount=1;}
}
//测试用
// log.warn("{0}",shuz);
// if (shuz.length != 1 || shuz[0] != 0){
// // log.warn("错误");
// // await sleep(2000);
// throw new Error("错误");
// }
}else{
log.info("未检测到浓缩树脂图标");
}
}
var originalResinCountRa = await imageRecognition(originalResin,0.1, 0, 0,1555,0,100,100,Threshold);
//脆弱树脂
var originalResinCountRa = await imageRecognition(originalResin,0.1, 0, 0,1325,0,400,500,Threshold);
if (originalResinCountRa.found) {
// await moveMouseTo(originalResinCountRa.x,originalResinCountRa.y);
let countArea = await Textocr("",0.5, 0, 2,originalResinCountRa.x+originalResinCountRa.w,originalResinCountRa.y,originalResinCountRa.w*3,originalResinCountRa.h,Threshold);//
let countArea = await Textocr("",0.5, 0, 2,originalResinCountRa.x+originalResinCountRa.w,originalResinCountRa.y,originalResinCountRa.w*4,originalResinCountRa.h);//
if (countArea.found){
log.info("原粹树脂识别数量结果:"+ countArea.text);
let match = countArea.text.match(/(\d+)\s*[/17]\s*(2|20|200)/);
@@ -198,16 +252,17 @@
log.info("未检测到原粹树脂图标");
}
var momentResinCountRa = await imageRecognition(momentResin,0.2, 0, 1,1170,0,500,100,0.7,Threshold);
// 须臾树脂
var momentResinCountRa = await imageRecognition(momentResin,0.1, 0, 1,960,0,500,100,Threshold);
if (momentResinCountRa.found) {
for (let i = 0; i < resinImages.length; i++) {
let countArea = await imageRecognition(resinImages[i],0.2, 0, 0,momentResinCountRa.x+momentResinCountRa.w,momentResinCountRa.y,momentResinCountRa.w*2,momentResinCountRa.h,Threshold);
let countArea = await imageRecognition(resinImages[i],0, 0, 0,momentResinCountRa.x+momentResinCountRa.w+10,momentResinCountRa.y,30,35,Thresholdr);
if (countArea.found){
momentResinCount =i+1;
momentResinCount =i;
break;
}
if (i==4){log.info("未检测到须臾图标强制为1"); momentResinCount=1;}
if (i==5){log.info("未检测到须臾数量强制为1"); momentResinCount=1;}
}
fragileResinCount = "1";
@@ -217,20 +272,23 @@
{
log.info("未检测到须臾树脂图标");
var fragileResinCountRa = await imageRecognition(fragileResin,0.1, 0, 1,1170,0,300,100,Threshold);
// 脆弱树脂
var fragileResinCountRa = await imageRecognition(fragileResin,0.1, 0, 1,960,0,500,100,Threshold);
if (fragileResinCountRa.found) {
// await moveMouseTo(fragileResinCountRa.x+fragileResinCountRa.w+20,fragileResinCountRa.y-15);
let countArea = await Textocr("",0.5, 0, 2,fragileResinCountRa.x+fragileResinCountRa.w,fragileResinCountRa.y,fragileResinCountRa.w*2,fragileResinCountRa.h,Threshold);//
// await moveMouseTo(fragileResinCountRa.x+fragileResinCountRa.w+20,fragileResinCountRa.y-15);
let countArea = await Textocr("",0.1, 0, 2,fragileResinCountRa.x+fragileResinCountRa.w,fragileResinCountRa.y,fragileResinCountRa.w*2,fragileResinCountRa.h);//
if (countArea.found){
// log.info("脆弱树脂识别数量结果:"+ countArea.text);
fragileResinCount = countArea.text
}
else{
var oneRa = await imageRecognition(resinImages[0],0.1, 0, 1,fragileResinCountRa.x+fragileResinCountRa.w,fragileResinCountRa.y,60,40,Threshold);
var oneRa = await imageRecognition(resinImages[1],0.1, 0, 1,fragileResinCountRa.x+fragileResinCountRa.w,fragileResinCountRa.y,60,40,Threshold);
if (oneRa.found){
fragileResinCount = "1";
}else{
fragileResinCount = "1";
log.info("2未检测到脆弱树脂图标,脆弱树脂识别强制为 1 ");//有图标说明至少为1
}
}
}
@@ -242,7 +300,7 @@
log.info("树脂状态:浓缩{0} 原粹{1} 脆弱{2} 须臾{3}", condensedResinCount, originalResinCount, fragileResinCount,momentResinCount)
return {condensedResinCount,originalResinCount,fragileResinCount,momentResinCount}
}
}
//征讨之花领奖寻找函数
@@ -461,7 +519,7 @@
retries++; // 重试次数加1
//滚轮操作
YOffset += 100;
if (retries === maxRetries || retries+YOffset > 1080) {
if (retries === maxRetries || 155+YOffset > 1080) {
await leftButtonUp();
await sleep(100);
await keyPress("VK_ESCAPE");
@@ -492,11 +550,30 @@
await sleep(1000);
}
await sleep(300);
await sleep(300);
//确保转换按键根据数字2和5的顺序判断是否要点
if(!firstawards){
let index2 = resinTypes.indexOf("2");
let index5 = resinTypes.indexOf("5");
if (index2 !== -1 && (index5 === -1 || index2 < index5)) {
let SHU = await Textocr(resinTypeMap[5], 0.1, 0, 0, 510, 380, 640, 600);
if (SHU.found) {
await click(SHU.x + 480, SHU.y + 15);
}
}else{
let SHU = await Textocr(resinTypeMap[2], 0.1, 0, 0, 510, 380, 640, 600);
if (SHU.found) {
await click(SHU.x + 480, SHU.y + 15);
}
}
firstawards = true;
}
for (let j = 0;j < 2;j++) {
for (let i = 0;i < rewards.length;i++) {
for (let i = 0;i < rewards.length && !resinDone;i++) {
let SHU = await Textocr(resinTypeMap[rewards[i]],0.3,0,0,510,380,640,600);
if (SHU.found){
if (resinTypeMap[rewards[i]] == "使用20个原粹树脂")
@@ -513,7 +590,7 @@
await Textocr("锁定辅助",10,0,0,1768,0,115,90);
await sleep(500);
await sleep(1000);
let { condensedResinCount, originalResinCount, fragileResinCount , momentResinCount} = await getRemainResinStatus();
let shouldExit = true;
@@ -522,7 +599,7 @@
{
shouldExit &= (parseInt(condensedResinCount, 10) == 0);
}
if (resinTypes.includes("2"))
if (resinTypes.includes("2") || resinTypes.includes("5"))
{
shouldExit &= (parseInt(originalResinCount, 10) < 20);
}
@@ -536,11 +613,17 @@
}
if (shouldExit)
{
await sleep(1000);
await keyPress("VK_ESCAPE");
await sleep(1000);
return false;
{
if(primogemUseCount <= 0){
await sleep(1000);
await keyPress("VK_ESCAPE");
await sleep(1000);
return false;
}
else{
log.warn("树脂耗尽,后续尝试使用原石 {0} 次...", primogemUseCount);
resinDone = true;
}
}
log.warn("还有树脂...");
return true;
@@ -548,6 +631,46 @@
}
await sleep(500);
}
resinDone = true;
if(primogemUseCount > 0 && resinDone){
log.warn("树脂耗尽,尝试使用原石 {0}/{1} ...", primogemUseDone+1, primogemUseCount);
let SHU = await Textocr("兑换",0,0,0,510,380,800,600);
if (SHU.found) {
resinTypeMap2.length = 0;
log.warn("{t}","原石不足,执行结束...");
}
for (let k = 0; k < resinTypeMap2.length; k++) {
let SHU = await Textocr(resinTypeMap2[k],0.1,0,0,510,380,640,600);
if (SHU.found){
log.warn("{t}","原石使用啦!!!!!!!!!...");
await click(SHU.x+550,SHU.y)
let dimai2 = await Textocr("确认",0.5, 0, 0, 960,720, 400, 80);
if (dimai2.found) {
await click(865,630)//不再提示
await sleep(1000);
// await moveMouseTo(dimai2.x,dimai2.y+10);
await click(dimai2.x,dimai2.y+10)
}
primogemUseDone ++;
primogemUseCount--;
if (primogemUseCount <= 0) {
log.warn("原石使用次数耗尽,停止执行...");
break;
}
return true;
}else{
log.warn("未找到原石使用选项,停止执行...");
break;
}
}
}
log.warn("未找到树脂,结束领取奖励...");
await sleep(1000);
await keyPress("VK_ESCAPE");
@@ -601,12 +724,66 @@
}
log.warn("自动幽境危战版本v2.0");
//更换战斗队伍
async function Switchteams() {
for (let i = 0;i < 2;i++){
let teams = await Textocr("预设队伍",5,1,0,1360,985,200, 70);
let teams2 = await Textocr("预设队伍",5,0,0,1,0,160, 80);
if (teams.found) {break}
else if (!teams2.found && i == 1){log.warn("未找到预设队伍按钮,不执行切换操作...");return false;}
}
await click(936,150);
await sleep(100);
let YOffset = 0; // Y轴偏移量根据需要调整
//滚轮预操作
await click(936,150);
await sleep(100);
await leftButtonDown();
await sleep(100);
await click(936,140);
const maxRetries = 30; // 最大重试次数
let retries = 0; // 当前重试次数
while (retries < maxRetries) {
let result1 = await Textocr(FightTeam,0.2,1,0,50,108,350, 900);
if (result1.found) {
await leftButtonUp();
await sleep(300);
await click(result.x,result.y);
await sleep(500);
return true
}
retries++; // 重试次数加1
//滚轮操作
YOffset += 100;
if (retries === maxRetries || 130+YOffset > 1080) {
await leftButtonUp();
await sleep(100);
log.warn("未找到预设战斗队伍名称,保持原有队伍...");
await keyPress("VK_ESCAPE");
await sleep(500);
return false;
}
await click(936,130+YOffset);
await sleep(200);
}
return true;
}
log.warn("自动幽境危战版本v2.1");
log.warn("请保证队伍战斗实力,战斗失败或执行错误,会重试两次...");
log.warn("使用前请在 <<幽境危战>> 中配置好战斗队伍...");
log.info("使用树脂类型数量{0} ", rewards.length)
log.info(`使用树脂顺序:${golbalRewardText.join(" ->")}`);
log.info("圣遗物奖励选择{0} ", Artifacts)
log.info("使用树脂顺序{0} ", golbalRewardText.join(" ->"))
log.info("圣遗物奖励选择:{0} ", Artifacts)
if (!(FightTeam === undefined || FightTeam === "")){log.info("配置战斗队伍为{0}", FightTeam)}
//重试两次
for (let j = 0;j < 2;j++) {
@@ -690,8 +867,12 @@
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("队伍选择功能等伟大的苏苏老师考完试做...")
//6.5 更换队伍
if (FightTeam === undefined || FightTeam === ""){log.info("不更换战斗队伍...");}
else{
log.info("配置战斗队伍为:{0}", FightTeam)
await Switchteams();
}
//7.开始挑战
await Textocr("开始挑战",1,1,0,1554,970,360, 105);

View File

@@ -1,7 +1,7 @@
{
"manifest_version": 1,
"name": "自动幽境危战",
"version": "2.0",
"version": "2.1",
"tags": [
"幽境危战"
],

View File

@@ -1,10 +1,16 @@
[
[
{
"name": "FightTeam",
"type": "input-text",
"label": "默认:不填则不更换队伍,队伍不要有生僻字或特殊符号"
},
{
"name": "Artifacts",
"type": "select",
"label": "圣遗物奖励,默认不修改圣遗物奖励",
"options": [
"保持圣遗物奖励不变",
"穹境示现之夜 / 纺月的夜歌",
"长夜之誓 / 深廊终曲",
"黑曜秘典 / 烬城勇者绘卷",
"谐律异想断章 / 未竟的遐思" ,
@@ -47,6 +53,21 @@
"type": "input-text",
"label": "树脂顺序1=浓缩树脂/2=原粹树脂/3=脆弱树脂/4=须臾树脂\n用`/`隔开填写对应的树脂数字即可默认1/2\n表示先使用浓缩树脂再使用原粹树脂不填的不使用",
"default": "1/2"
},
{
"name": "primogemUseCount",
"type": "select",
"label": "原石购买体力次数(0~6次),上面设置的树脂用完后才会使用 ↓↓",
"options": [
"0",
"1",
"2",
"3",
"4",
"5",
"6"
],
"default": "0"
},
{
"name": "Fighttimeout",