fix(地脉花): 4.1.1 重构部分代码

This commit is contained in:
秋云
2025-08-23 18:54:55 +08:00
parent ae4224e72b
commit 9e04710060
8 changed files with 45 additions and 180 deletions

View File

@@ -12,9 +12,8 @@
右键脚本选择修改js脚本自定义配置根据你的需要对脚本进行配置。
![](assets/image/image5.png)
### 配置地图追踪策略和战斗策略
点击配置组设置,打开地图追踪设置,**开启允许在js中使用**和**覆盖js中的自动战斗策略**,并开启战斗策略配置,**关闭自动检测战斗结束**,其他的根据你的队伍进行配置。
点击配置组设置,开启战斗策略配置,**关闭自动检测战斗结束**,其他的根据你的队伍进行配置。
> 脚本不通过按L检查战斗是否结束不关闭**自动检测战斗结束**可能导致提前结束战斗!
> 战斗超时时间一定要大于或与脚本配置内的时间一样,太短会原地罚站!
![](assets/image/image6.png)

View File

@@ -9,7 +9,6 @@ let leyLineX = 0; // 地脉花X坐标
let leyLineY = 0; // 地脉花Y坐标
let currentFlower = null; // 当前花的引用
let strategyName = ""; // 任务策略名称
let retryCount = 0; // 重试次数
let marksStatus = true; // 自定义标记状态
let currentRunTimes = 0; // 当前运行次数
let isNotification = false; // 是否发送通知
@@ -31,17 +30,21 @@ const ocrRoThis = RecognitionObject.ocrThis;
* 主函数 - 脚本入口点
*/
(async function () {
dispatcher.addTimer(new RealtimeTimer("AutoPick"));
try {
await runLeyLineOutcropScript();
} catch (error) {
log.error("出错了! {error}", error.message);
}
catch (error) {
// 全局错误捕获,记录并发送错误日志
log.error("出错了: {error}", error.message);
if (isNotification) {
notification.error("出错了 {error}", error.message);
notification.error("出错了: {error}", error.message);
}
}
finally {
if (!marksStatus) {
await openCustomMarks();
}
log.info("全自动地脉花运行结束");
}
})();
@@ -51,29 +54,19 @@ const ocrRoThis = RecognitionObject.ocrThis;
*/
async function runLeyLineOutcropScript() {
// 初始化加载配置和设置并校验
await initialize();
await loadConfig();
loadSettings();
retryCount = 0;
initialize();
await prepareForLeyLineRun();
// 执行地脉花挑战
await runLeyLineChallenges();
// 完成后恢复自定义标记
if (!marksStatus) {
await openCustomMarks();
}
}
/**
* 初始化
* @returns {Promise<void>}
*/
async function initialize() {
await genshin.returnMainUi();
setGameMetrics(1920, 1080, 1);
function initialize() {
// 预定义工具函数
try {
const utils = [
"attemptReward.js",
@@ -85,30 +78,49 @@ async function initialize() {
"locateLeyLineOutcrop.js",
"processLeyLineOutcrop.js",
"recognizeTextInRegion.js"
];
];
for (const fileName of utils) {
eval(file.readTextSync(`utils/${fileName}`));
log.debug(`utils/${fileName} 加载成功`);
}
} catch (error) {
throw new Error(`JS文件缺失,请重新安装脚本! ${error.message}`);
throw new Error(`JS文件缺失: ${error.message}`);
}
// 2. 加载配置文件
try {
config = JSON.parse(file.readTextSync("config.json"));
loadSettings();
} catch (error) {
throw new Error("配置文件加载失败请检查config.json文件是否存在");
}
}
/**
* 执行地脉花挑战前的准备工作
* 1. 传送七天神像和切换战斗队伍
* 2. 关闭自定义标记
* 3. 添加自动拾取实时任务
* 注意:该函数运行结束之后位于大地图界面
* @returns {Promise<void>}
*/
async function prepareForLeyLineRun() {
// 开局传送到七天神像
await genshin.tpToStatueOfTheSeven();
// 0. 回到主界面
await genshin.returnMainUi(); // 回到主界面
setGameMetrics(1920, 1080, 1); // 看起来没什么用
// 1. 开局传送到七天神像
// TODO考虑添加选项禁用这个特性看起来有点浪费时间需要提示风险
await genshin.tpToStatueOfTheSeven();
// 切换战斗队伍
// 2. 切换战斗队伍
if (settings.team) {
log.info(`切换至队伍 ${settings.team}`);
await genshin.switchParty(settings.team);
}
// 3. 关闭自定义标记
await closeCustomMarks();
// 4. 添加自动拾取实时任务
// TODO: 个性化拾取策略
dispatcher.addTimer(new RealtimeTimer("AutoPick"));
}
/**
@@ -435,19 +447,6 @@ async function handleNoStrategyFound() {
}
}
/**
* 加载配置文件
* @returns {Promise<void>}
*/
async function loadConfig() {
try {
const configData = JSON.parse(await file.readText("config.json"));
config = configData; // 直接赋值给全局变量
} catch (error) {
log.error(`加载配置文件失败: ${error.message}`);
throw new Error("配置文件加载失败请检查config.json文件是否存在");
}
}
/**
* 地脉花寻找和定位相关函数
@@ -818,12 +817,11 @@ async function openCustomMarks() {
let b = button[i];
if (b.y > 280 && b.y < 350) {
log.info("打开自定义标记");
marksStatus = true;
click(Math.round(b.x + b.width / 2), Math.round(b.y + b.height / 2));
}
}
} else {
log.error("未找到开关按钮");
keyPress("ESCAPE");
genshin.returnMainUi();
}
}

View File

@@ -1,7 +1,7 @@
{
"manifest_version": 1,
"name": "全自动地脉花",
"version": "4.1",
"version": "4.1.1",
"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如果遇到问题请先参照手册中的方法进行解决。",

View File

@@ -58,7 +58,7 @@
{
"name": "useAdventurerHandbook",
"type": "checkbox",
"label": "是否使用冒险之证寻找地脉花\n开发中请勿使用",
"label": "是否使用冒险之证寻找地脉花\n开发中请勿使用"
},
{
"name": "isNotification",

View File

@@ -29,7 +29,6 @@ this.clickWithVerification = async function(x, y, targetText, maxRetries = 20) {
if (!textFound) {
return true;
}
}
log.warn(`经过${maxRetries}次点击,文字"${targetText}"仍未消失`);
@@ -40,13 +39,9 @@ this.clickWithVerification = async function(x, y, targetText, maxRetries = 20) {
* 尝试领取地脉花奖励
* @returns {Promise<void>}
*/
this.attemptReward =
async function () {
const MAX_RETRY = 5;
// 超时处理
this.attemptReward = async function (retryCount = 0) {
const MAX_RETRY = 3;
if (retryCount >= MAX_RETRY) {
retryCount = 0;
throw new Error("超过最大重试次数,领取奖励失败");
}
@@ -129,8 +124,7 @@ async function () {
log.info("当前界面不是地脉之花界面,重试");
await genshin.returnMainUi();
await sleep(1000);
retryCount++;
await autoNavigateToReward();
await attemptReward();
await attemptReward(++retryCount);
}
}

View File

@@ -1,124 +0,0 @@
/**
* 带验证的单击函数
* @param {number} x - X坐标
* @param {number} y - Y坐标
* @param {string} targetText - 需要验证消失的目标文字
* @param {number} maxRetries - 最大重试次数默认为10
* @returns {Promise<boolean>} 是否成功
*/
this.clickWithVerification = async function(x, y, targetText, maxRetries = 20) {
for (let i = 0; i < maxRetries; i++) {
click(x, y);
await sleep(400);
// 验证目标文字是否消失
let resList = captureGameRegion().findMulti(ocrRoThis);
let textFound = false;
if (resList && resList.count > 0) {
for (let j = 0; j < resList.count; j++) {
if (resList[j].text.includes(targetText)) {
textFound = true;
break;
}
}
}
// 如果文字消失了,说明点击成功
if (!textFound) {
return true;
}
}
log.warn(`经过${maxRetries}次点击,文字"${targetText}"仍未消失`);
return false;
}
/**
* 尝试领取地脉花奖励
* @returns {Promise<void>}
*/
this.attemptReward =
async function () {
const MAX_RETRY = 5;
// 超时处理
if (retryCount >= MAX_RETRY) {
retryCount = 0;
throw new Error("超过最大重试次数,领取奖励失败");
}
log.info("开始领取地脉奖励");
keyPress("F");
await sleep(500);
// 识别是否为地脉之花界面
let resList = captureGameRegion().findMulti(ocrRoThis); // 使用预定义的ocrRoThis对象
let isValid = false;
let condensedResin = null;
let originalResin = null;
let isResinEmpty = false;
let dobuleReward = false;
if (resList && resList.count > 0) {
// 分析识别到的文本
for (let i = 0; i < resList.count; i++) {
let res = resList[i];
if (res.text.includes("使用浓缩树脂")) {
isValid = true;
condensedResin = res;
} else if (res.text.includes("使用原粹树脂")) {
isValid = true;
originalResin = res;
} else if (res.text.includes("补充原粹树脂")) {
isValid = true;
isResinEmpty = true;
} else if (res.text.includes("产出")) {
isValid = true;
dobuleReward = true;
}
} // 处理不同的树脂情况
if (originalResin && dobuleReward == true) {
log.info("选择使用原粹树脂,获得双倍产出");
await clickWithVerification(
Math.round(originalResin.x + originalResin.width / 2),
Math.round(originalResin.y + originalResin.height / 2),
"树脂"
);
} else if (condensedResin) {
log.info("选择使用浓缩树脂");
await clickWithVerification(
Math.round(condensedResin.x + condensedResin.width / 2),
Math.round(condensedResin.y + condensedResin.height / 2),
"树脂"
);
} else if (originalResin) {
log.info("选择使用原粹树脂");
await clickWithVerification(
Math.round(originalResin.x + originalResin.width / 2),
Math.round(originalResin.y + originalResin.height / 2),
"树脂"
);
} else if (isResinEmpty) {
log.error("识别到补充原粹树脂,看来树脂用完了呢");
keyPress("VK_ESCAPE");
throw new Error("树脂已用完");
}
if (settings.friendshipTeam) {
log.info("切换回战斗队伍");
await sleep(500);
const switchSuccess = await switchTeam(settings.team);
}
}
// 界面不正确,尝试重试
if (!isValid) {
log.info("当前界面不是地脉之花界面,重试");
await genshin.returnMainUi();
await sleep(1000);
retryCount++;
await autoNavigateToReward();
await attemptReward();
}
}

View File

@@ -3,8 +3,7 @@
* @param {Object} position - 位置对象
* @returns {Promise<void>}
*/
this.executePathsUsingNodeData =
async function (position) {
this.executePathsUsingNodeData = async function (position) {
try {
const nodeData = await loadNodeData();
let currentNodePosition = position;

View File

@@ -6,8 +6,7 @@
*/
this.findLeyLineOutcrop =
async function (country, type) {
currentFlower = null;
await closeCustomMarks();
currentFlower = null;
await sleep(1000);
log.info("开始寻找地脉花");
if (!config.mapPositions[country] || config.mapPositions[country].length === 0) {