v.1.2自动幽境秘境 版本(20250627) (#1218)
* v1.2自动幽境危战 v.1.2版本:20250627 1、添加圣遗物奖励选择功能。 2、添加自动选择难度功能。 3、优化逻辑处理。 4、加大战斗完成识别区域。 * Delete repo/js/Auto自动幽境危战 directory * v.1.2自动幽境秘境 版本(20250627) ### v.1.2版本(20250627) - **新增功能**: 1. 添加圣遗物奖励选择功能。 2. 添加自动选择难度功能。 - **优化**: 1. 优化逻辑处理。 2. 加大战斗完成识别区域。 * 文件版本修改 文件版本修改 * 优化前进到准备战斗的方式 优化前进到准备战斗的方式
66
repo/js/AutoStygianOnslaught/README.md
Normal file
@@ -0,0 +1,66 @@
|
||||
# 幽境危战注意事项
|
||||
|
||||
## 零、前言
|
||||
|
||||
- 当前文档处于测试阶段,注意事项可能尚不完善,敬请谅解。
|
||||
- 如发现BUG,请通过QQ:119996800联系我们,您的反馈将非常受欢迎。
|
||||
- 本脚本基于地脉花和首领一条龙脚本进行改造。
|
||||
- 脚本仅供娱乐使用,请在下载后24小时内删除。
|
||||
|
||||
## 一、省流注意事项
|
||||
|
||||
1. **使用前准备**:
|
||||
- 请在`<<幽境危战>>`中配置好战斗队伍。
|
||||
2. **黑名单建议**:
|
||||
- 根目录下有建议加入自动拾取黑名单的名称,请检查并添加。
|
||||
3. **战斗实力**:
|
||||
- 请确保队伍具备足够的战斗实力,当前版本在战斗失败时会自动退出秘境。
|
||||
4. **自动拾取功能**:
|
||||
- 为避免不必要的干扰,建议关闭自动拾取功能。
|
||||
|
||||
## 二、配置简介
|
||||
|
||||
1. **圣遗物奖励**:
|
||||
- 默认设置下,脚本不会修改圣遗物奖励。
|
||||
|
||||
2. **Boss挑战关卡选择**:
|
||||
- 必填项:请从上往下选择第几个Boss挑战关卡(1至3),否则脚本将退出执行。
|
||||
|
||||
3. **挑战次数**:
|
||||
- 默认设置为15次,期间若树脂耗尽,脚本将自动结束。
|
||||
|
||||
4. **树脂顺序设定**:
|
||||
- 使用`/`隔开数字来设定树脂使用顺序,如`1/2`表示先使用浓缩树脂,再使用原粹树脂。
|
||||
- 树脂类型对应关系:
|
||||
- 1 = 浓缩树脂
|
||||
- 2 = 原粹树脂
|
||||
- 3 = 脆弱树脂
|
||||
- 4 = 须臾树脂
|
||||
- 默认设置:`1/2`
|
||||
|
||||
5. **最长战斗超时时间**:
|
||||
- 默认设置为240秒,一般情况下无需修改。
|
||||
|
||||
6. **开始战斗后的移动时间**:
|
||||
- 默认设置为1秒(注意单位为秒)。由于开始位置离Boss较远,请根据实际情况设定,一般情况下默认设置即可。
|
||||
|
||||
## 三、更新说明
|
||||
|
||||
### v.1.0版本(20250627)
|
||||
|
||||
- **功能**:脚本发布。
|
||||
|
||||
### v.1.1版本
|
||||
|
||||
- **备注**:此版本信息被省略。
|
||||
|
||||
### v.1.2版本(20250627)
|
||||
|
||||
- **新增功能**:
|
||||
1. 添加圣遗物奖励选择功能。
|
||||
2. 添加自动选择难度功能。
|
||||
- **优化**:
|
||||
1. 优化逻辑处理。
|
||||
2. 加大战斗完成识别区域。
|
||||
|
||||
请将以上内容保存为`README.md`文件,以便在GitHub或其他支持Markdown的平台上正确显示和使用。
|
||||
BIN
repo/js/AutoStygianOnslaught/assets/Artifacts/artifact_1.bmp
Normal file
|
After Width: | Height: | Size: 5.6 KiB |
BIN
repo/js/AutoStygianOnslaught/assets/Artifacts/artifact_10.bmp
Normal file
|
After Width: | Height: | Size: 6.3 KiB |
BIN
repo/js/AutoStygianOnslaught/assets/Artifacts/artifact_10in.bmp
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
repo/js/AutoStygianOnslaught/assets/Artifacts/artifact_11.bmp
Normal file
|
After Width: | Height: | Size: 6.2 KiB |
BIN
repo/js/AutoStygianOnslaught/assets/Artifacts/artifact_11in.bmp
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
repo/js/AutoStygianOnslaught/assets/Artifacts/artifact_12.bmp
Normal file
|
After Width: | Height: | Size: 6.6 KiB |
BIN
repo/js/AutoStygianOnslaught/assets/Artifacts/artifact_12in.bmp
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
repo/js/AutoStygianOnslaught/assets/Artifacts/artifact_13.bmp
Normal file
|
After Width: | Height: | Size: 6.1 KiB |
BIN
repo/js/AutoStygianOnslaught/assets/Artifacts/artifact_13in.bmp
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
repo/js/AutoStygianOnslaught/assets/Artifacts/artifact_14.bmp
Normal file
|
After Width: | Height: | Size: 6.1 KiB |
BIN
repo/js/AutoStygianOnslaught/assets/Artifacts/artifact_14in.bmp
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
repo/js/AutoStygianOnslaught/assets/Artifacts/artifact_15.bmp
Normal file
|
After Width: | Height: | Size: 6.3 KiB |
BIN
repo/js/AutoStygianOnslaught/assets/Artifacts/artifact_15in.bmp
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
repo/js/AutoStygianOnslaught/assets/Artifacts/artifact_16.bmp
Normal file
|
After Width: | Height: | Size: 6.2 KiB |
BIN
repo/js/AutoStygianOnslaught/assets/Artifacts/artifact_16in.bmp
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
repo/js/AutoStygianOnslaught/assets/Artifacts/artifact_17.bmp
Normal file
|
After Width: | Height: | Size: 6.9 KiB |
BIN
repo/js/AutoStygianOnslaught/assets/Artifacts/artifact_17in.bmp
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
repo/js/AutoStygianOnslaught/assets/Artifacts/artifact_18.bmp
Normal file
|
After Width: | Height: | Size: 6.8 KiB |
BIN
repo/js/AutoStygianOnslaught/assets/Artifacts/artifact_18in.bmp
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
repo/js/AutoStygianOnslaught/assets/Artifacts/artifact_1in.bmp
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
repo/js/AutoStygianOnslaught/assets/Artifacts/artifact_2.bmp
Normal file
|
After Width: | Height: | Size: 6.2 KiB |
BIN
repo/js/AutoStygianOnslaught/assets/Artifacts/artifact_2in.bmp
Normal file
|
After Width: | Height: | Size: 9.6 KiB |
BIN
repo/js/AutoStygianOnslaught/assets/Artifacts/artifact_3.bmp
Normal file
|
After Width: | Height: | Size: 6.9 KiB |
BIN
repo/js/AutoStygianOnslaught/assets/Artifacts/artifact_3in.bmp
Normal file
|
After Width: | Height: | Size: 9.9 KiB |
BIN
repo/js/AutoStygianOnslaught/assets/Artifacts/artifact_4.bmp
Normal file
|
After Width: | Height: | Size: 6.1 KiB |
BIN
repo/js/AutoStygianOnslaught/assets/Artifacts/artifact_4in.bmp
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
repo/js/AutoStygianOnslaught/assets/Artifacts/artifact_5.bmp
Normal file
|
After Width: | Height: | Size: 6.6 KiB |
BIN
repo/js/AutoStygianOnslaught/assets/Artifacts/artifact_5in.bmp
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
repo/js/AutoStygianOnslaught/assets/Artifacts/artifact_6.bmp
Normal file
|
After Width: | Height: | Size: 7.1 KiB |
BIN
repo/js/AutoStygianOnslaught/assets/Artifacts/artifact_6in.bmp
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
repo/js/AutoStygianOnslaught/assets/Artifacts/artifact_7.bmp
Normal file
|
After Width: | Height: | Size: 6.9 KiB |
BIN
repo/js/AutoStygianOnslaught/assets/Artifacts/artifact_7in.bmp
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
repo/js/AutoStygianOnslaught/assets/Artifacts/artifact_8.bmp
Normal file
|
After Width: | Height: | Size: 6.1 KiB |
BIN
repo/js/AutoStygianOnslaught/assets/Artifacts/artifact_8in.bmp
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
repo/js/AutoStygianOnslaught/assets/Artifacts/artifact_9.bmp
Normal file
|
After Width: | Height: | Size: 6.2 KiB |
BIN
repo/js/AutoStygianOnslaught/assets/Artifacts/artifact_9in.bmp
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
repo/js/AutoStygianOnslaught/assets/box.png
Normal file
|
After Width: | Height: | Size: 1018 B |
26
repo/js/AutoStygianOnslaught/assets/全自动幽境危战.json
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"info": {
|
||||
"name": "全自动幽境危战",
|
||||
"type": "collect",
|
||||
"author": "LCB-茶包",
|
||||
"version": "1.0",
|
||||
"description": "",
|
||||
"bgi_version": "0.44.8"
|
||||
},
|
||||
"positions": [
|
||||
{
|
||||
"id": 1,
|
||||
"x": -194.198,
|
||||
"y": 984.095,
|
||||
"move_mode": "walk",
|
||||
"type": "teleport"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"x": -194.25293,
|
||||
"y": 980.6616,
|
||||
"move_mode": "walk",
|
||||
"type": "target"
|
||||
}
|
||||
]
|
||||
}
|
||||
607
repo/js/AutoStygianOnslaught/main.js
Normal file
@@ -0,0 +1,607 @@
|
||||
(async function () {
|
||||
|
||||
let challengeNum = settings.challengeNum;//挑战次数
|
||||
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;
|
||||
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 ocrRo1 = RecognitionObject.ocr(ocrRegion1.x, ocrRegion1.y, ocrRegion1.width, ocrRegion1.height);
|
||||
const ocrRo2 = RecognitionObject.ocr(ocrRegion2.x, ocrRegion2.y, ocrRegion2.width, ocrRegion2.height);
|
||||
var Rewardsuse = settings.Rewardsuse ? settings.Rewardsuse : "1/2";
|
||||
var resinTypes = Rewardsuse.split("/");
|
||||
var rewards = [];
|
||||
var onerewards, secendrewards, threendrewards, fourdrewards;
|
||||
for (var i = 0; i < resinTypes.length; i++) {
|
||||
var resinType = parseInt(resinTypes[i]);
|
||||
if (isNaN(resinType) || resinType < 1 || resinType > 4) {
|
||||
throw new Error("设定的树脂类型无效或缺失,请重新配置");
|
||||
}
|
||||
rewards.push(resinType);
|
||||
}
|
||||
const resinTypeMap = ["","使用1个浓缩树脂,获取2倍产出", "使用20个原粹树脂", "使用1个脆弱树脂,获取3倍产出", "使用1个须臾树脂,获取3倍产出"];
|
||||
// 根据 rewards 数组长度,依次赋值给对应的变量
|
||||
if (rewards.length > 0) onerewards = resinTypeMap[rewards[0]];
|
||||
if (rewards.length > 1) secendrewards = resinTypeMap[rewards[1]];
|
||||
if (rewards.length > 2) threendrewards = resinTypeMap[rewards[2]];
|
||||
if (rewards.length > 3) fourdrewards = resinTypeMap[rewards[3]];
|
||||
|
||||
log.info(`使用树脂类型数量:${rewards.length}`);
|
||||
log.info(`优先使用的树脂类型:${onerewards} --> ${secendrewards??"无"} --> ${threendrewards??"无"} --> ${fourdrewards??"无"}`);
|
||||
|
||||
const rewardTextRo = RecognitionObject.Ocr(1210, 515, 200, 50);//领奖区域检测
|
||||
var advanceNum = 0;//前进次数
|
||||
var verticalNum = 0;
|
||||
|
||||
var Artifacts = settings.Artifacts ? settings.Artifacts : "长夜之誓 / 深廊终曲";
|
||||
|
||||
//建立一个数值映射所有圣遗物对应需要识别的图片
|
||||
var artifactImageMap = {
|
||||
"长夜之誓 / 深廊终曲": "assets/Artifacts/artifact_1.bmp",
|
||||
"黑曜秘典 / 烬城勇者绘卷": "assets/Artifacts/artifact_2.bmp",
|
||||
"谐律异想断章 / 未竟的遐思": "assets/Artifacts/artifact_3.bmp",
|
||||
"回声之林夜话 / 昔时之歌": "assets/Artifacts/artifact_4.bmp",
|
||||
"逐影猎人 / 黄金剧团": "assets/Artifacts/artifact_5.bmp",
|
||||
"水仙之梦 / 花海甘露之光": "assets/Artifacts/artifact_6.bmp",
|
||||
"乐园遗落之花 / 沙上楼阁史话": "assets/Artifacts/artifact_7.bmp",
|
||||
"深林的记忆 / 饰金之梦": "assets/Artifacts/artifact_8.bmp",
|
||||
"来歆余响 / 辰砂往生录": "assets/Artifacts/artifact_9.bmp",
|
||||
"华馆梦醒形骸记 / 海染砗磲": "assets/Artifacts/artifact_10.bmp",
|
||||
"绝缘之旗印 / 追忆之注连": "assets/Artifacts/artifact_11.bmp",
|
||||
"昔日宗室之仪 / 染血的骑士道": "assets/Artifacts/artifact_12.bmp",
|
||||
"渡过烈火的贤人 / 炽烈的炎之魔女": "assets/Artifacts/artifact_13.bmp",
|
||||
"悠古的磐岩 / 逆飞的流星": "assets/Artifacts/artifact_14.bmp",
|
||||
"千岩牢固 / 苍白之火": "assets/Artifacts/artifact_15.bmp",
|
||||
"冰风迷途的勇士 / 沉沦之心": "assets/Artifacts/artifact_16.bmp",
|
||||
"翠绿之影 / 被怜爱的少女": "assets/Artifacts/artifact_17.bmp",
|
||||
"如雷的盛怒 / 平息鸣雷的尊者": "assets/Artifacts/artifact_18.bmp"
|
||||
};
|
||||
|
||||
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++)
|
||||
{
|
||||
// 获取一张截图
|
||||
let captureRegion = captureGameRegion();
|
||||
let res1
|
||||
// 对整个区域进行 OCR
|
||||
let resList = captureRegion.findMulti(RecognitionObject.ocr(x,y,w,h));
|
||||
//log.info("OCR 全区域识别结果数量 {len}", resList.count);
|
||||
for (let i = 0; i < resList.count; i++)
|
||||
{ // 遍历的是 C# 的 List 对象,所以要用 count,而不是 length
|
||||
let res = resList[i];
|
||||
res1=res.text
|
||||
if (res.text===wenzi) {
|
||||
log.info(`识别到 ·${res1}·`);
|
||||
if (debugcode===1){if (x===0 & y===0){log.info("全图代码位置:({x},{y},{h},{w})", res.x-10, res.y-10, res.width+10, res.Height+10);return result = { text: res.text, x: res.x, y: res.y, found: true }}}else{if (x===0 & y===0){log.info("文本OCR完成'{text}'", res.text);}}
|
||||
if (clickocr===1){await sleep(1000);click(res.x, res.y);}else{}
|
||||
if (clickocr===2){await sleep(100);keyPress("F");}else{}
|
||||
return result = { text: res.text, x: res.x, y: res.y, found: true }
|
||||
}
|
||||
}
|
||||
const NowTime = new Date();
|
||||
if (Math.abs(NowTime - startTime)>chaotime*1000){if (x===0 & y===0){log.info(`${chaotime}秒超时退出,"${wenzi}"未找到`);}return result = {found: false };}else{ii=8;if (x !== 861){if(debugcode!==3){await keyPress("VK_W");}};}
|
||||
await sleep(100);
|
||||
}
|
||||
}
|
||||
|
||||
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));
|
||||
for (let ii = 0; ii < 10; ii++) {
|
||||
captureRegion = captureGameRegion(); // 获取一张截图
|
||||
res = captureRegion.DeriveCrop(xa, ya, wa, ha).Find(Imagidentify);
|
||||
if (res.isEmpty()) {
|
||||
if (debugmodel===1 & xa===0 & ya===0){log.info("识别页面元素")};
|
||||
} else {
|
||||
if (afterBehavior===1){if (xa===0 & ya===0){log.info("点击模式:开");}await sleep(1000);click(res.x+xa, res.y+ya);}else{if (debugmodel===1 & xa===0 & ya===0){log.info("点击模式:关")}}
|
||||
if (afterBehavior===2){if (xa===0 & ya===0){log.info("F模式:开");}await sleep(1000);keyPress("F");}else{if (debugmodel===1 & xa===0 & ya===0){log.info("F模式:关")}}
|
||||
if (debugmodel===1 & xa===0 & ya===0){log.info("全图代码位置:({x},{y},{h},{w})", res.x+xa, res.y+ya, res.width+wa, res.Height+ha);}else{ log.info("识别到图片");}
|
||||
return result = { x: res.x+xa, y: res.y+ya, w:res.width+wa,h:res.Height+ha,found: true }
|
||||
}
|
||||
const NowTime = new Date();
|
||||
if ((NowTime - startTime)>timeout*1000){if (debugmodel===1 & xa===0 & ya===0){log.info(`${timeout}秒超时退出,未找到图片`);}return result = {found: false };}else{ii=8}
|
||||
await sleep(200);
|
||||
}
|
||||
await sleep(1200);
|
||||
}
|
||||
|
||||
//征讨之花领奖
|
||||
const autoNavigateToReward = async () => {
|
||||
// 定义识别对象
|
||||
const boxIconRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync("assets/box.png"));
|
||||
const rewardTextRo = RecognitionObject.Ocr(1210, 515, 200, 50);//领奖区域检测
|
||||
|
||||
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){
|
||||
throw new Error('前进时间超时');
|
||||
}
|
||||
// 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, 861,265, 194, 265);
|
||||
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 (iconRes.x >= 920 && iconRes.x <= 980 && iconRes.y <= 540) {
|
||||
advanceNum++;
|
||||
log.info(`视野已调正,前进第${advanceNum}次`);
|
||||
break;
|
||||
} else {
|
||||
// 小幅度调整
|
||||
if(iconRes.y >= 520) moveMouseBy(0, 920);
|
||||
let adjustAmount = iconRes.x < 920 ? -20 : 20;
|
||||
let distanceToCenter = Math.abs(iconRes.x - 920); // 计算与920的距离
|
||||
let scaleFactor = Math.max(1, Math.floor(distanceToCenter / 50)); // 根据距离缩放,最小为1
|
||||
let adjustAmount2 = iconRes.y < 540 ? scaleFactor : 10;
|
||||
moveMouseBy(adjustAmount * adjustAmount2, 0);
|
||||
await sleep(100);
|
||||
}
|
||||
|
||||
if(i > 97) {
|
||||
if (verticalNum >= 2) {
|
||||
verticalNum = 0;
|
||||
throw new Error('领取超时');
|
||||
}
|
||||
log.info("领取超时,重新尝试1次");
|
||||
await genshin.returnMainUi(); await sleep(1000);//退出待写
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// 3. 前进一小步
|
||||
keyDown("w");
|
||||
await sleep(600);
|
||||
keyUp("w");
|
||||
await sleep(100); // 等待角色移动稳定
|
||||
let earthlyVeins = await Textocr("地脉之花", 0.1, 0, 0, 861,265, 194, 265)
|
||||
if (earthlyVeins.found) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function readyFightIn(){
|
||||
var startTime = new Date();
|
||||
await sleep(500);
|
||||
var NowTime = new Date();
|
||||
keyDown("w");
|
||||
while ((NowTime - startTime)<10*1000){
|
||||
const result = await Textocr("战斗准备",0.1,0,3,1198,492,150,80);
|
||||
const result2 = await Textocr("开始挑战",0.1,0,3,1554,970,360, 105);
|
||||
if (result.found || result2.found) {
|
||||
await keyUp("w");
|
||||
await keyPress("F");await sleep(200); await keyPress("F");
|
||||
return true;
|
||||
}
|
||||
keyDown("w");
|
||||
keyPress("F");
|
||||
NowTime = new Date();
|
||||
}
|
||||
await keyUp("w");
|
||||
await genshin.returnMainUi();
|
||||
return false
|
||||
}
|
||||
|
||||
//异步检测战斗,来自D捣蛋&秋云佬的全自动地脉花的代码
|
||||
async function autoFight(timeout) {
|
||||
const cts = new CancellationTokenSource();
|
||||
log.info("开始战斗");
|
||||
dispatcher.RunTask(new SoloTask("AutoFight"), cts);
|
||||
let fightResult = await recognizeTextInRegion(timeout);
|
||||
logFightResult = fightResult ? "成功" : "失败";
|
||||
log.info(`战斗结束,战斗结果:${logFightResult}`);
|
||||
cts.cancel();
|
||||
return fightResult;}
|
||||
|
||||
|
||||
async function recognizeTextInRegion(timeout) {
|
||||
return new Promise((resolve, reject) => {
|
||||
(async () => {
|
||||
try {
|
||||
let startTime = Date.now();
|
||||
const successKeywords = ["挑战完成","战斗完成"];
|
||||
const failureKeywords = ["战斗失败"];
|
||||
|
||||
// 循环检测直到超时
|
||||
while (Date.now() - startTime < timeout) {
|
||||
try {
|
||||
let captureRegion = captureGameRegion();
|
||||
let result = captureRegion.find(ocrRo1);
|
||||
let result2 = captureRegion.find(ocrRo2);
|
||||
let text = result.text;
|
||||
let text2 = result2.text;
|
||||
|
||||
// 检查成功关键词
|
||||
for (let keyword of successKeywords) {
|
||||
if (text.includes(keyword)) {
|
||||
log.info("检测到战斗成功关键词: {0}", keyword);
|
||||
resolve(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 检查失败关键词--
|
||||
for (let keyword of failureKeywords) {
|
||||
if (text2.includes(keyword)) {
|
||||
log.warn("检测到战斗失败关键词: {0}", keyword);
|
||||
resolve(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
log.error("OCR过程中出错: {0}", error);
|
||||
}
|
||||
|
||||
await sleep(1000); // 检查间隔
|
||||
}
|
||||
|
||||
log.warn("在超时时间内未检测到战斗结果");
|
||||
resolve(false);
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
}
|
||||
})();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 领取奖励更换
|
||||
async function selectionHolyRelics() {
|
||||
|
||||
let artifactImagePath = artifactImageMap[Artifacts];
|
||||
// 检查artifactImagePath是否存在
|
||||
if (!artifactImagePath) {
|
||||
throw new Error(`未找到与Artifacts值'${Artifacts}'对应的图片路径`);
|
||||
}
|
||||
let modifiedPath = artifactImagePath.slice(0, -4);
|
||||
let newImagePath = modifiedPath + "in.bmp";
|
||||
|
||||
await sleep(500);
|
||||
await click(116,980) // 领取奖励切换按钮
|
||||
await sleep(100);
|
||||
await click(116,980) // 领取奖励切换按钮
|
||||
await sleep(100);
|
||||
|
||||
let rewardSettings = await Textocr("奖励设置",15,0,0,882,34,161,52);//这个时候有人申请进入世界会遮住,真是尴尬啊,不过不影响大局。
|
||||
if (!rewardSettings.found) {await genshin.returnMainUi();return false;}
|
||||
await click(1642,159);
|
||||
await sleep(100);
|
||||
await click(1642,159);
|
||||
await sleep(100);
|
||||
|
||||
let YOffset = 0; // Y轴偏移量,根据需要调整
|
||||
|
||||
//滚轮预操作
|
||||
await moveMouseTo(1642,159);
|
||||
await sleep(100);
|
||||
await leftButtonDown();
|
||||
await sleep(100);
|
||||
await moveMouseTo(1642,155);
|
||||
|
||||
const maxRetries = 15; // 最大重试次数
|
||||
let retries = 0; // 当前重试次数
|
||||
while (retries < maxRetries) {
|
||||
let result1 = await imageRecognition(newImagePath, 1, 0, 0,1178,148,87,857);//
|
||||
if (result1.found) {
|
||||
await leftButtonUp();
|
||||
await sleep(500);
|
||||
await click(result.x-200,result.y);
|
||||
await sleep(1000);
|
||||
await keyPress("VK_ESCAPE");
|
||||
return true
|
||||
}
|
||||
retries++; // 重试次数加1
|
||||
//滚轮操作
|
||||
YOffset += 200;
|
||||
if (retries === maxRetries || retries+YOffset > 1920) {
|
||||
await leftButtonUp();
|
||||
await sleep(100);
|
||||
await keyPress("VK_ESCAPE");
|
||||
await genshin.returnMainUi();
|
||||
return false;}
|
||||
await moveMouseTo(1642,155+YOffset);
|
||||
await sleep(500);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
async function claimRewards() {
|
||||
log.info(`尝试领取奖励,优先${onerewards}'`);
|
||||
let SHUN01 = await Textocr("激活地脉之花",0.6,2,0,1188,358,200,400);
|
||||
let SHUN02 = await Textocr("地脉之花", 0.2, 0, 0, 861,265, 194, 265);
|
||||
if (SHUN01.found || SHUN02.found) {
|
||||
log.info("找到地脉之花,开始领取奖励...");
|
||||
}
|
||||
else
|
||||
{
|
||||
log.warn("未找到地脉之花,尝试向前寻找...")
|
||||
await keyDown("W");await sleep(300);await keyUp("W");
|
||||
await keyPress("F");
|
||||
}
|
||||
|
||||
await sleep(300);
|
||||
|
||||
for (let j = 0;j < 2;j++) {
|
||||
|
||||
for (let i = 0;i < rewards.length;i++) {
|
||||
let SHU = await Textocr(resinTypeMap[rewards[i]],0.3,0,0,510,380,640,600);
|
||||
if (SHU.found){
|
||||
if (resinTypeMap[rewards[i]] == "使用20个原粹树脂")
|
||||
{
|
||||
let BUC = await Textocr("补充",0.2,0,0,1150,440,210,130);
|
||||
if (BUC.found) {continue;}
|
||||
}
|
||||
await sleep(100);
|
||||
await click(SHU.x+550,SHU.y)
|
||||
await sleep(100);
|
||||
await click(SHU.x+550,SHU.y)
|
||||
await sleep(300);
|
||||
log.info(` ${resinTypeMap[rewards[i]]} 获取奖励...`);
|
||||
dispatcher.addTimer(new RealtimeTimer("AutoPick", { forceInteraction: true }));
|
||||
dispatcher.addTimer(new RealtimeTimer("AutoPick", { "forceInteraction": false }));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
await sleep(500);
|
||||
}
|
||||
log.warn("未找到树脂,结束地脉花...");
|
||||
dispatcher.addTimer(new RealtimeTimer("AutoPick", { "forceInteraction": false }));
|
||||
await sleep(1000);
|
||||
await keyPress("VK_ESCAPE"); //退出待写
|
||||
await sleep(1000);
|
||||
return false;
|
||||
}
|
||||
|
||||
async function VeinEntrance() {
|
||||
for (let i = 0;i < 2;i++) {
|
||||
let JIECHU = await Textocr("F",2,2,0,1098,519,35,32);
|
||||
if (JIECHU.found)
|
||||
{
|
||||
await keyPress("F");await dispatcher.addTimer(new RealtimeTimer("AutoPick", { "forceInteraction": true }));await keyPress("F");
|
||||
dispatcher.addTimer(new RealtimeTimer("AutoPick", { "forceInteraction": false }));
|
||||
break;
|
||||
}
|
||||
else{
|
||||
if(i == 1)
|
||||
{
|
||||
log.warn("没找入口,尝试强制转圈寻找...");
|
||||
dispatcher.addTimer(new RealtimeTimer("AutoPick", { "forceInteraction": true }));
|
||||
await keyDown("W");await sleep(500);await keyUp("W");
|
||||
await keyDown("D");await sleep(500);await keyUp("D");
|
||||
dispatcher.addTimer(new RealtimeTimer("AutoPick", { "forceInteraction": true }));
|
||||
await keyDown("S");await sleep(500);await keyUp("S");
|
||||
dispatcher.addTimer(new RealtimeTimer("AutoPick", { "forceInteraction": true }));
|
||||
await keyDown("A");await sleep(500);await keyUp("A");
|
||||
dispatcher.addTimer(new RealtimeTimer("AutoPick", { "forceInteraction": true }));
|
||||
await keyDown("W");await sleep(500);await keyUp("W");
|
||||
dispatcher.addTimer(new RealtimeTimer("AutoPick", { "forceInteraction": false }));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
dispatcher.addTimer(new RealtimeTimer("AutoPick", { "forceInteraction": false }));
|
||||
}
|
||||
|
||||
var resinAgain = false;
|
||||
log.warn("根目录下有建议加的黑名单的名称,建议加入自动拾取黑名单...");
|
||||
log.warn("请保证队伍战斗实力,目前战斗失败会自动退出秘境...");
|
||||
log.warn("使用前请在 <<幽境危战>> 中配置好战斗队伍...");
|
||||
log.warn("最好关闭自动拾取功能...");
|
||||
log.info(`圣遗物奖励选择:'${Artifacts}'`);
|
||||
|
||||
// for (let j = 0;j < 2;j++) {
|
||||
|
||||
await genshin.returnMainUi();
|
||||
await pathingScript.runFile(`assets/全自动幽境危战.json`);
|
||||
await VeinEntrance();
|
||||
|
||||
try{
|
||||
// 进入-选择难道
|
||||
let intoAction = await Textocr("单人挑战",10,0,0,1554,970,360, 105);
|
||||
if (!intoAction.found) {await genshin.returnMainUi();throw new Error("未进入挑战页面,停止执行...")}
|
||||
let adjustmentType = await Textocr("常规挑战", 2, 0, 0,797,144,223,84);
|
||||
if (!adjustmentType.found) {
|
||||
log.warn("未找到常规挑战,尝试切换...")
|
||||
await sleep(500);
|
||||
await click(890,191)
|
||||
}
|
||||
let hardMode = await Textocr("困难", 2, 0, 0,1049,157,72,47);
|
||||
if (!hardMode.found) {
|
||||
log.warn("未找到困难模式,尝试切换...")
|
||||
await sleep(500);
|
||||
await click(1096,186);
|
||||
await sleep(500);
|
||||
await click(1093,399);
|
||||
}
|
||||
|
||||
//圣遗物奖励选择
|
||||
|
||||
if (Artifacts != "保持圣遗物奖励不变"){
|
||||
let artifact = await imageRecognition(artifactImageMap[Artifacts],0.2,0,0,186,972,71,71);
|
||||
if (!artifact.found) {
|
||||
log.warn("圣遗物奖励和设定不一致,尝试切换...")
|
||||
if (!await selectionHolyRelics()) {throw new Error("圣遗物奖励设置错误,停止执行...")}
|
||||
}
|
||||
else
|
||||
{
|
||||
log.warn("圣遗物奖励一致,无需切换...")
|
||||
}
|
||||
}
|
||||
|
||||
//多点击一次,保证进入挑战页面
|
||||
await sleep(500);
|
||||
await click(intoAction.x,intoAction.y)
|
||||
await sleep(1000);
|
||||
await click(intoAction.x,intoAction.y)
|
||||
|
||||
//进入秘境
|
||||
let enter = await Textocr("Enter",10,0,0,18,990,156,71,71);
|
||||
if (!enter.found) {await genshin.returnMainUi();throw new Error("未进入秘境,停止执行...")}//退出待写
|
||||
|
||||
//向前走进入挑战
|
||||
if (!(await readyFightIn())){await genshin.returnMainUi();throw new Error("未进入准备战斗,停止执行...")}//退出待写
|
||||
await sleep(1000);
|
||||
|
||||
//选择挑战怪兽
|
||||
log.info(`选择挑战Boss:'${challengeName}' 挑战次数:'${challengeNum}'`);
|
||||
log.info(`期间树脂耗尽会自动退出秘境...`);
|
||||
|
||||
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("队伍选择功能等伟大的苏苏老师考完试做...")
|
||||
|
||||
await Textocr("开始挑战",1,1,0,1554,970,360, 105);
|
||||
|
||||
var resinexhaustion = false; // 条件1:树脂耗尽
|
||||
|
||||
//开始战斗循环
|
||||
for (let i = 0;i < challengeNum; i++) {
|
||||
//进入秘境
|
||||
let battleBegins = await Textocr("战斗开始",20,0,0,877,235,164,50);
|
||||
if (!battleBegins.found){await genshin.returnMainUi();throw new Error("未进入战斗环境,停止执行...")}//退出待写
|
||||
|
||||
log.info(`进入战斗环境,开始第${i+1}次战斗`);
|
||||
|
||||
await keyDown("w");
|
||||
await sleep(Startforward);
|
||||
await keyUp("w");
|
||||
|
||||
try {
|
||||
if(!await autoFight(Fighttimeout)){
|
||||
log.warn("战斗失败,退出秘境...");
|
||||
await sleep(1000);
|
||||
await keyPress("VK_ESCAPE");
|
||||
await sleep(1000);
|
||||
await keyPress("VK_ESCAPE");
|
||||
await sleep(1000);
|
||||
resinAgain = true;//待开发重试
|
||||
let exitChallenge = await Textocr("退出挑战",2,1,0,866,719,274,86);
|
||||
return false;
|
||||
}
|
||||
} catch (error) {
|
||||
log.info(`挑战失败,再来一次`);
|
||||
if(!await autoFight(Fighttimeout)){
|
||||
log.warn("战斗超时失败,尝试寻找地脉花入口");
|
||||
}
|
||||
}
|
||||
|
||||
// if (resinAgain == true)
|
||||
|
||||
await sleep(1000);
|
||||
await keyPress("VK_ESCAPE");
|
||||
await sleep(1000);
|
||||
|
||||
while((await Textocr("Enter",5,0,0,18,990,156,80).found) == false)
|
||||
{
|
||||
await keyPress("VK_ESCAPE");
|
||||
await sleep(1000);
|
||||
}
|
||||
|
||||
log.info(`第${i+1}次领奖`);
|
||||
|
||||
if(!(await autoNavigateToReward())){verticalNum++;continue;}
|
||||
|
||||
await sleep(1000);
|
||||
|
||||
if (!(await claimRewards())) {
|
||||
log.warn("树脂消耗完毕,结束任务");
|
||||
resinexhaustion = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (challengeNum != i+1)
|
||||
{
|
||||
let challengeAgian = await Textocr("再次挑战",10,1,0,1094,958,200,70);
|
||||
}
|
||||
}
|
||||
|
||||
//是否继续
|
||||
if (challengeNum == i+1 || resinexhaustion == true){
|
||||
log.info (`完成 ${i+1} 次战斗或树脂耗尽,退出挑战...`);
|
||||
dispatcher.addTimer(new RealtimeTimer("AutoPick", { forceInteraction: false }));
|
||||
await keyPress("VK_ESCAPE");
|
||||
await sleep(1000);
|
||||
|
||||
var exitTimeout = 0;
|
||||
while(exitTimeout < 20)
|
||||
{
|
||||
let exitChallenge = await Textocr("退出挑战",0.3,0,0,866,719,274,86);
|
||||
if (exitChallenge.found) {
|
||||
await sleep(600);
|
||||
await click(exitChallenge.x, exitChallenge.y);
|
||||
await sleep(500);
|
||||
break;
|
||||
}
|
||||
let exitChallenge2 = await Textocr("退出挑战",0.3,1,0,866,719,274,86);
|
||||
log.info("尝试退出挑战...");
|
||||
await sleep(1000);
|
||||
await keyPress("VK_ESCAPE");
|
||||
await sleep(1000);
|
||||
exitTimeout++;
|
||||
}
|
||||
await genshin.returnMainUi();
|
||||
return false;
|
||||
}
|
||||
|
||||
await sleep(500);
|
||||
}
|
||||
|
||||
}
|
||||
catch (error) {
|
||||
log.error(`执行过程中发生错误:${error.message}`);
|
||||
}finally{
|
||||
await genshin.returnMainUi();
|
||||
log.info(`Auto自动幽境危战结束...`);
|
||||
}
|
||||
// }
|
||||
|
||||
})();
|
||||
15
repo/js/AutoStygianOnslaught/manifest.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"manifest_version": 1,
|
||||
"name": "自动幽境危战",
|
||||
"version": "1.2",
|
||||
"tags": ["幽境危战"],
|
||||
"bgi_version": "0.44.8",
|
||||
"description": "请先配置好秘境内的队伍,幽境危战战斗失败会导致卡死,请保证队伍实力,先配置好秘境内的队伍",
|
||||
"authors": [
|
||||
{
|
||||
"name": "LCB-茶包"
|
||||
}
|
||||
],
|
||||
"settings_ui": "settings.json",
|
||||
"main": "main.js"
|
||||
}
|
||||
58
repo/js/AutoStygianOnslaught/settings.json
Normal file
@@ -0,0 +1,58 @@
|
||||
[
|
||||
{
|
||||
"name": "Artifacts",
|
||||
"type": "select",
|
||||
"label": "圣遗物奖励,默认不修改圣遗物奖励",
|
||||
"options": [
|
||||
"保持圣遗物奖励不变",
|
||||
"长夜之誓 / 深廊终曲",
|
||||
"黑曜秘典 / 烬城勇者绘卷",
|
||||
"谐律异想断章 / 未竟的遐思" ,
|
||||
"回声之林夜话 / 昔时之歌" ,
|
||||
"逐影猎人 / 黄金剧团" ,
|
||||
"水仙之梦 / 花海甘露之光" ,
|
||||
"乐园遗落之花 / 沙上楼阁史话" ,
|
||||
"深林的记忆 / 饰金之梦" ,
|
||||
"来歆余响 / 辰砂往生录" ,
|
||||
"华馆梦醒形骸记 / 海染砗磲" ,
|
||||
"绝缘之旗印 / 追忆之注连" ,
|
||||
"昔日宗室之仪 / 染血的骑士道" ,
|
||||
"渡过烈火的贤人 / 炽烈的炎之魔女" ,
|
||||
"悠古的磐岩 / 逆飞的流星",
|
||||
"千岩牢固 / 苍白之火" ,
|
||||
"冰风迷途的勇士 / 沉沦之心" ,
|
||||
"翠绿之影 / 被怜爱的少女" ,
|
||||
"如雷的盛怒 / 平息鸣雷的尊者"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "challengeName",
|
||||
"type": "select",
|
||||
"label": "必填:请选择第几个Boss挑战关卡",
|
||||
"options": [
|
||||
"1",
|
||||
"2",
|
||||
"3"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "challengeNum",
|
||||
"type": "input-text",
|
||||
"label": "挑战次数,默认15次,期间树脂耗尽会自动结束"
|
||||
},
|
||||
{
|
||||
"name": "Rewardsuse",
|
||||
"type": "input-text",
|
||||
"label": "树脂顺序,1=浓缩树脂/2=原粹树脂/3=脆弱树脂/4=须臾树脂\n用`/`隔开,填写对应的树脂数字即可,默认:1/2\n表示先使用浓缩树脂,再使用原粹树脂,不填的不使用"
|
||||
},
|
||||
{
|
||||
"name": "Fighttimeout",
|
||||
"type": "input-text",
|
||||
"label": "最长战斗超时时间,单位秒,默认240秒"
|
||||
},
|
||||
{
|
||||
"name": "Startforward",
|
||||
"type": "input-text",
|
||||
"label": "开始战斗后,向前移动的时间,默认1秒(注意单位:秒)"
|
||||
}
|
||||
]
|
||||
9
repo/js/AutoStygianOnslaught/建议加入自动拾取黑名单.txt
Normal file
@@ -0,0 +1,9 @@
|
||||
"激活地脉之花",
|
||||
"战斗准备",
|
||||
"退出秘境",
|
||||
"幽境危战",
|
||||
"「幽境危战」",
|
||||
"幽境危战」",
|
||||
"【幽境危战】",
|
||||
"幽境危战】",
|
||||
"幽境危战",
|
||||