mirror of
https://github.com/babalae/bettergi-scripts-list.git
synced 2026-04-04 06:46:19 +08:00
F1找花优化,修复部分bug (#1711)
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
**仅支持BetterGI 0.44.7 及以上版本!**
|
||||
**仅支持Bitblt截图方式!**
|
||||
目前脚本仍在更新,开发阶段会有很多bug,详见下方已知问题,如果遇到没有提到的bug请反馈给我们,非常感谢!
|
||||
[TOC]
|
||||
## 配置
|
||||
使用前需要对脚本以及战斗策略进行配置
|
||||
在调度器新建一个配置组,将脚本添加进来,脚本只能在配置组内使用
|
||||
@@ -47,13 +48,9 @@ wgc的bug,请使用bitblt截图方式,脚本只支持这个
|
||||
打开大地图,点击左下角设置,开启自定义标记。
|
||||
脚本非正常结束运行时会出现该问题。
|
||||
## 更新日志
|
||||
### 4.1.4
|
||||
修复取消自动任务报错
|
||||
### 4.1.3
|
||||
修复v8报错
|
||||
|
||||
### 4.1
|
||||
通过冒险之证找花 - 测试
|
||||
- 新增通过冒险之证寻找地脉花
|
||||
- 修复部分报错
|
||||
### 4.0
|
||||
- 适配原神5.7版本更新
|
||||
- 修复打开自定义标记的bug
|
||||
|
||||
@@ -38,7 +38,7 @@ const ocrRoThis = RecognitionObject.ocrThis;
|
||||
// 全局错误捕获,记录并发送错误日志
|
||||
log.error("出错了: {error}", error.message);
|
||||
if (isNotification) {
|
||||
notification.error("出错了: ${error.message}");
|
||||
notification.error(`出错了: ${error.message}`);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"manifest_version": 1,
|
||||
"name": "全自动地脉花",
|
||||
"version": "4.1.4",
|
||||
"version": "4.1.5",
|
||||
"tags": ["地脉花"],
|
||||
"bgi_version": "0.44.7",
|
||||
"description": "基于OCR图像识别的全自动刷取地脉花。\n💡更多信息请查看在线手册:https://hcnsvf0s8d0s.feishu.cn/wiki/Tb1twpThLi7UlykqcYOcuccTnjJ \n\n----------注意事项----------\n●仅支持BetterGI 0.44.7 及以上版本!\n●部分地脉花因特殊原因不支持全自动,具体的点位请在手册中查看。\n●树脂使用的优先级:2倍原粹树脂 > 浓缩树脂 > 原粹树脂。\n●运行时会传送到七天神像设置中设置的七天神像,需要关闭七天神像设置中的“是否就近七天神像恢复血量”,并指定七天神像。\n●战斗策略注意调度器设置中地图追踪行走配置里的“允许在JsSpript中使用”和“覆盖JS中的自动战斗配置”,只有在都打开的情况下脚本才会使用下面的战斗配置,否则会使用独立任务中的战斗策略。战斗超时时间不能大于脚本自定义配置中的时间。\n\n如果遇到问题,请先参照手册中的方法进行解决。",
|
||||
|
||||
@@ -25,8 +25,7 @@ this.findLeyLineOutcropByBook = async function (country, type) {
|
||||
await sleep(1000);
|
||||
click(1300, 800); //点击推荐
|
||||
await sleep(1000);
|
||||
let captureRegion = captureGameRegion();
|
||||
let resList = captureRegion.findMulti(RecognitionObject.ocrThis);
|
||||
let resList = captureGameRegion().findMulti(ocrRoThis);
|
||||
for (let i = 0; i < resList.count; i++) {
|
||||
let res = resList[i];
|
||||
if (res.text.includes(country)) {
|
||||
@@ -34,6 +33,14 @@ this.findLeyLineOutcropByBook = async function (country, type) {
|
||||
}
|
||||
}
|
||||
await sleep(1000);
|
||||
let resList2 = captureGameRegion().findMulti(ocrRoThis);
|
||||
for (let i = 0; i < resList2.count; i++) {
|
||||
let res = resList2[i];
|
||||
if (res.text.includes("停止追踪")) {
|
||||
res.click();
|
||||
await sleep(1000);
|
||||
}
|
||||
}
|
||||
click(1500, 850);
|
||||
click(1500, 850); //点击追踪,连点两次防止点不到
|
||||
await sleep(1000);
|
||||
@@ -41,6 +48,27 @@ this.findLeyLineOutcropByBook = async function (country, type) {
|
||||
const center = genshin.getPositionFromBigMap();
|
||||
leyLineX = center.x;
|
||||
leyLineY = center.y;
|
||||
log.info(`找到地脉花的坐标:(${center.x}, ${center.y})`);
|
||||
log.info(`找到地脉花的坐标:(${leyLineX}, ${leyLineY})`);
|
||||
|
||||
// 取消追踪
|
||||
click(960, 540);
|
||||
await sleep(1000);
|
||||
let zhuizong = captureGameRegion().findMulti(ocrRoThis);
|
||||
if (zhuizong && zhuizong.count > 0) {
|
||||
for (let i = 0; i < zhuizong.count; i++) {
|
||||
if (zhuizong[i].text.includes("停止追踪")) {
|
||||
zhuizong[i].click();
|
||||
log.debug("点击取消追踪");
|
||||
await sleep(1000);
|
||||
return;
|
||||
} else if (zhuizong[i].text.includes("地脉") || zhuizong[i].text.includes("衍出")) {
|
||||
zhuizong[i].click();
|
||||
await sleep(1000);
|
||||
click(1700, 1010);
|
||||
log.debug("点击取消追踪");
|
||||
await sleep(1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
return center;
|
||||
}
|
||||
@@ -1,74 +1,74 @@
|
||||
/**
|
||||
* 加载、验证、输出用户设置
|
||||
* @returns {Object} 处理过的设置对象
|
||||
*/
|
||||
this.loadSettings =
|
||||
function () {
|
||||
try {
|
||||
// 直接使用全局settings对象而不是重新创建
|
||||
// 这样能保留原始设置内容
|
||||
|
||||
// 验证必要的设置
|
||||
if (!settings.start) {
|
||||
throw new Error("请仔细阅读脚本介绍和手册,并在调度器内进行配置,如果你是直接运行的脚本,请将脚本加入调度器内运行!");
|
||||
}
|
||||
|
||||
if (!settings.leyLineOutcropType) {
|
||||
throw new Error("请选择你要刷取的地脉花类型(经验书/摩拉)");
|
||||
}
|
||||
|
||||
if (!settings.country) {
|
||||
throw new Error("请在游戏中确认地脉花的第一个点的位置,然后在js设置中选择地脉花所在的国家。");
|
||||
}
|
||||
|
||||
if (settings.friendshipTeam && !settings.team) {
|
||||
throw new Error("未配置战斗队伍!当配置了好感队时必须配置战斗队伍!");
|
||||
}
|
||||
|
||||
// 为了向后兼容,确保某些设置有默认值
|
||||
settings.timeout = settings.timeout * 1000 || 120000;
|
||||
|
||||
// 处理刷取次数
|
||||
if (!settings.count || !/^-?\d+\.?\d*$/.test(settings.count)) {
|
||||
log.warn(`刷取次数 ${settings.count} 不是数字,使用默认次数6次`);
|
||||
settings.timesValue = 6;
|
||||
} else {
|
||||
// 转换为数字
|
||||
const num = parseFloat(settings.count);
|
||||
|
||||
// 范围检查
|
||||
if (num < 1) {
|
||||
settings.timesValue = 1;
|
||||
log.info(`⚠️ 次数 ${num} 小于1,已调整为1`);
|
||||
} else {
|
||||
// 处理小数
|
||||
if (!Number.isInteger(num)) {
|
||||
settings.timesValue = Math.floor(num);
|
||||
log.info(`⚠️ 次数 ${num} 不是整数,已向下取整为 ${settings.timesValue}`);
|
||||
} else {
|
||||
settings.timesValue = num;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 记录使用的设置
|
||||
log.info(`地脉花类型:${settings.leyLineOutcropType}`);
|
||||
log.info(`国家:${settings.country}`);
|
||||
|
||||
if (settings.friendshipTeam) {
|
||||
log.info(`好感队:${settings.friendshipTeam}`);
|
||||
}
|
||||
|
||||
log.info(`刷取次数:${settings.timesValue}`);
|
||||
|
||||
// 设置通知状态
|
||||
isNotification = settings.isNotification;
|
||||
|
||||
if (isNotification) {
|
||||
notification.send(`全自动地脉花开始运行,以下是本次运行的配置:\n\n地脉花类型:${settings.leyLineOutcropType}\n国家:${settings.country}\n刷取次数:${settings.timesValue}`);
|
||||
}
|
||||
} catch (error) {
|
||||
log.error(`加载设置失败: ${error.message}`);
|
||||
throw error;
|
||||
}
|
||||
/**
|
||||
* 加载、验证、输出用户设置
|
||||
* @returns {Object} 处理过的设置对象
|
||||
*/
|
||||
this.loadSettings =
|
||||
function () {
|
||||
try {
|
||||
// 直接使用全局settings对象而不是重新创建
|
||||
// 这样能保留原始设置内容
|
||||
|
||||
// 验证必要的设置
|
||||
if (!settings.start) {
|
||||
throw new Error("请仔细阅读脚本介绍和手册,并在调度器内进行配置,如果你是直接运行的脚本,请将脚本加入调度器内运行!");
|
||||
}
|
||||
|
||||
if (!settings.leyLineOutcropType) {
|
||||
throw new Error("请选择你要刷取的地脉花类型(经验书/摩拉)");
|
||||
}
|
||||
|
||||
if (!settings.country) {
|
||||
throw new Error("请在游戏中确认地脉花的第一个点的位置,然后在js设置中选择地脉花所在的国家。");
|
||||
}
|
||||
|
||||
if (settings.friendshipTeam && !settings.team) {
|
||||
throw new Error("未配置战斗队伍!当配置了好感队时必须配置战斗队伍!");
|
||||
}
|
||||
|
||||
// 为了向后兼容,确保某些设置有默认值
|
||||
//settings.timeout = settings.timeout * 1000 || 120000;
|
||||
|
||||
// 处理刷取次数
|
||||
if (!settings.count || !/^-?\d+\.?\d*$/.test(settings.count)) {
|
||||
log.warn(`刷取次数 ${settings.count} 不是数字,使用默认次数6次`);
|
||||
settings.timesValue = 6;
|
||||
} else {
|
||||
// 转换为数字
|
||||
const num = parseFloat(settings.count);
|
||||
|
||||
// 范围检查
|
||||
if (num < 1) {
|
||||
settings.timesValue = 1;
|
||||
log.info(`⚠️ 次数 ${num} 小于1,已调整为1`);
|
||||
} else {
|
||||
// 处理小数
|
||||
if (!Number.isInteger(num)) {
|
||||
settings.timesValue = Math.floor(num);
|
||||
log.info(`⚠️ 次数 ${num} 不是整数,已向下取整为 ${settings.timesValue}`);
|
||||
} else {
|
||||
settings.timesValue = num;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 记录使用的设置
|
||||
log.info(`地脉花类型:${settings.leyLineOutcropType}`);
|
||||
log.info(`国家:${settings.country}`);
|
||||
|
||||
if (settings.friendshipTeam) {
|
||||
log.info(`好感队:${settings.friendshipTeam}`);
|
||||
}
|
||||
|
||||
log.info(`刷取次数:${settings.timesValue}`);
|
||||
|
||||
// 设置通知状态
|
||||
isNotification = settings.isNotification;
|
||||
|
||||
if (isNotification) {
|
||||
notification.send(`全自动地脉花开始运行,以下是本次运行的配置:\n\n地脉花类型:${settings.leyLineOutcropType}\n国家:${settings.country}\n刷取次数:${settings.timesValue}`);
|
||||
}
|
||||
} catch (error) {
|
||||
log.error(`加载设置失败: ${error.message}`);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@@ -1,74 +1,75 @@
|
||||
/**
|
||||
* 判断是否为地脉花并处理
|
||||
* @param {number} timeout - 超时时间
|
||||
* @param {string} targetPath - 目标路径
|
||||
* @param {number} [retries=0] - 当前函数内重试次数
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
this.processLeyLineOutcrop =
|
||||
async function (timeout, targetPath, retries = 0) {
|
||||
const MAX_RETRIES = 3;
|
||||
let captureRegion = null;
|
||||
|
||||
try {
|
||||
// 检查重试次数,避免死循环
|
||||
if (retries >= MAX_RETRIES) {
|
||||
const errorMsg = `开启地脉花失败,已重试${MAX_RETRIES}次,终止处理`;
|
||||
log.error("我辣么大一个地脉花哪去了?");
|
||||
throw new Error(errorMsg);
|
||||
}
|
||||
|
||||
// 截图并识别
|
||||
captureRegion = captureGameRegion();
|
||||
const result = captureRegion.find(ocrRo2);
|
||||
const result2 = captureRegion.find(ocrRo3);
|
||||
|
||||
// 检查地脉之花状态 - 已完成状态,准备领取奖励
|
||||
if (result2.text.includes("地脉之花")) {
|
||||
log.info("识别到地脉之花,准备领取奖励");
|
||||
await switchToFriendshipTeamIfNeeded();
|
||||
return;
|
||||
}
|
||||
|
||||
// 处理地脉溢口
|
||||
if (result2.text.includes("地脉溢口")) {
|
||||
log.info("识别到地脉溢口");
|
||||
keyPress("F");
|
||||
await sleep(300);
|
||||
keyPress("F");
|
||||
await sleep(500);
|
||||
} else if (result.text.includes("打倒所有敌人")) {
|
||||
log.info("地脉花已经打开,直接战斗");
|
||||
} else {
|
||||
// 未识别到目标,需要重新导航
|
||||
log.warn("未识别到地脉花文本,尝试重新导航");
|
||||
await pathingScript.runFile(targetPath);
|
||||
return await this.processLeyLineOutcrop(timeout, targetPath, retries + 1);
|
||||
}
|
||||
|
||||
// 执行战斗
|
||||
const fightResult = await autoFight(timeout);
|
||||
if (!fightResult) {
|
||||
throw new Error("战斗失败");
|
||||
}
|
||||
|
||||
// 完成后续操作
|
||||
await switchToFriendshipTeamIfNeeded();
|
||||
await autoNavigateToReward();
|
||||
|
||||
} catch (error) {
|
||||
// 保留原始错误信息
|
||||
const errorMsg = `地脉花处理失败 (重试${retries}/${MAX_RETRIES}): ${error.message}`;
|
||||
log.error(errorMsg);
|
||||
throw error;
|
||||
} finally {
|
||||
// 确保资源释放
|
||||
if (captureRegion) {
|
||||
try {
|
||||
captureRegion.dispose();
|
||||
} catch (disposeError) {
|
||||
log.warn(`截图资源释放失败: ${disposeError.message}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 判断是否为地脉花并处理
|
||||
* @param {number} timeout - 超时时间
|
||||
* @param {string} targetPath - 目标路径
|
||||
* @param {number} [retries=0] - 当前函数内重试次数
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
this.processLeyLineOutcrop =
|
||||
async function (timeout, targetPath, retries = 0) {
|
||||
const MAX_RETRIES = 3;
|
||||
let captureRegion = null;
|
||||
timeout = timeout * 1000;
|
||||
|
||||
try {
|
||||
// 检查重试次数,避免死循环
|
||||
if (retries >= MAX_RETRIES) {
|
||||
const errorMsg = `开启地脉花失败,已重试${MAX_RETRIES}次,终止处理`;
|
||||
log.error("我辣么大一个地脉花哪去了?");
|
||||
throw new Error(errorMsg);
|
||||
}
|
||||
|
||||
// 截图并识别
|
||||
captureRegion = captureGameRegion();
|
||||
const result = captureRegion.find(ocrRo2);
|
||||
const result2 = captureRegion.find(ocrRo3);
|
||||
|
||||
// 检查地脉之花状态 - 已完成状态,准备领取奖励
|
||||
if (result2.text.includes("地脉之花")) {
|
||||
log.info("识别到地脉之花,准备领取奖励");
|
||||
await switchToFriendshipTeamIfNeeded();
|
||||
return;
|
||||
}
|
||||
|
||||
// 处理地脉溢口
|
||||
if (result2.text.includes("地脉溢口")) {
|
||||
log.info("识别到地脉溢口");
|
||||
keyPress("F");
|
||||
await sleep(300);
|
||||
keyPress("F");
|
||||
await sleep(500);
|
||||
} else if (result.text.includes("打倒所有敌人")) {
|
||||
log.info("地脉花已经打开,直接战斗");
|
||||
} else {
|
||||
// 未识别到目标,需要重新导航
|
||||
log.warn("未识别到地脉花文本,尝试重新导航");
|
||||
await pathingScript.runFile(targetPath);
|
||||
return await this.processLeyLineOutcrop(timeout, targetPath, retries + 1);
|
||||
}
|
||||
|
||||
// 执行战斗
|
||||
const fightResult = await autoFight(timeout);
|
||||
if (!fightResult) {
|
||||
throw new Error("战斗失败");
|
||||
}
|
||||
|
||||
// 完成后续操作
|
||||
await switchToFriendshipTeamIfNeeded();
|
||||
await autoNavigateToReward();
|
||||
|
||||
} catch (error) {
|
||||
// 保留原始错误信息
|
||||
const errorMsg = `地脉花处理失败 (重试${retries}/${MAX_RETRIES}): ${error.message}`;
|
||||
log.error(errorMsg);
|
||||
throw error;
|
||||
} finally {
|
||||
// 确保资源释放
|
||||
if (captureRegion) {
|
||||
try {
|
||||
captureRegion.dispose();
|
||||
} catch (disposeError) {
|
||||
log.warn(`截图资源释放失败: ${disposeError.message}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user