js:自动狗粮重制版1.21更新 (#1037)

* js:自动狗粮重制版1.21更新

* js:消耗复活料理更新

现在会从七天神像处下落了,避免因为简易策略脚本失效造成问题

* js:根据patick-ze的pr,修改fakelog中的日志级别
This commit is contained in:
mno
2025-06-09 00:50:21 +08:00
committed by GitHub
parent 24361db4fb
commit 036704504c
8 changed files with 101 additions and 81 deletions

View File

@@ -128,6 +128,10 @@
## 更新日志 ## 更新日志
### 1.212025.06.09
1. 修改盗宝团触发路线,减少摩拉丢失
2.优化ocr模块现在识别失败时会尝试点击中心位置
3.优化流程现在只有当用户勾选了不分解四星时才会两次快速选择可以节约约5秒
### 1.22025.06.08 ### 1.22025.06.08
1. 加入狗粮分解和经验统计功能。 1. 加入狗粮分解和经验统计功能。
2.优化逻辑已经运行完成狗粮路线时仍然可以直接执行本js来完成好感 2.优化逻辑已经运行完成狗粮路线时仍然可以直接执行本js来完成好感

View File

@@ -13,13 +13,23 @@
"id": 1, "id": 1,
"x": -2738.38, "x": -2738.38,
"y": -3414.45, "y": -3414.45,
"action": "", "action": "combat_script",
"move_mode": "walk", "move_mode": "walk",
"action_params": "", "action_params": "wait(1)",
"type": "teleport" "type": "orientation"
}, },
{ {
"id": 2, "id": 2,
"x": -2738.38,
"y": -3414.45,
"action": "",
"move_mode": "walk",
"action_params": "",
"type": "teleport",
"locked": false
},
{
"id": 3,
"x": -2736.6, "x": -2736.6,
"y": -3415.44, "y": -3415.44,
"action": "exit_and_relogin", "action": "exit_and_relogin",

View File

@@ -282,7 +282,7 @@ const DEFAULT_FIGHT_TIMEOUT_SECONDS = 120;
} }
//运行前按自定义配置清理狗粮 //运行前按自定义配置清理狗粮
const result1 = await decomposeArtifacts(settings.keep4Star, false); const result1 = await decomposeArtifacts(settings.keep4Star, settings.doDecompose);
artifacts: { artifacts: {
if (runnedToday) { if (runnedToday) {
@@ -293,11 +293,16 @@ const DEFAULT_FIGHT_TIMEOUT_SECONDS = 120;
await switchPartyIfNeeded(grindPartyName); await switchPartyIfNeeded(grindPartyName);
let runArtifactsResult = true; let runArtifactsResult = true;
runArtifactsResult = await runArtifactsPaths(runRouteA); runArtifactsResult = await runArtifactsPaths(runRouteA);
const result2 = await decomposeArtifacts(settings.keep4Star, settings.doDecompose); const result2 = await decomposeArtifacts(settings.keep4Star, settings.doDecompose);
// 计算 mora 和 artifactExperience 的差值 // 计算 mora 和 artifactExperience 的差值
const moraDiff = Number(result2.mora) - Number(result1.mora); // 将字符串转换为数字后计算差值 const moraDiff = Number(result2.mora) - Number(result1.mora); // 将字符串转换为数字后计算差值
const artifactExperienceDiff = result2.artifactExperience - result1.artifactExperience; let artifactExperienceDiff;
if (!settings.doDecompose) {
artifactExperienceDiff = result2.artifactExperience - result1.artifactExperience;
} else {
artifactExperienceDiff = result2.artifactExperience;
}
log.info(`狗粮路线获取摩拉: ${moraDiff}`); log.info(`狗粮路线获取摩拉: ${moraDiff}`);
log.info(`狗粮路线获取狗粮经验: ${artifactExperienceDiff}`); log.info(`狗粮路线获取狗粮经验: ${artifactExperienceDiff}`);
@@ -536,7 +541,7 @@ async function fakeLog(name, isJs, isStart, duration) {
`------------------------------\n\n` + `------------------------------\n\n` +
`[${formattedTime}] [INF] BetterGenshinImpact.Service.ScriptService\n` + `[${formattedTime}] [INF] BetterGenshinImpact.Service.ScriptService\n` +
`→ 开始执行JS脚本: "${name}"`; `→ 开始执行JS脚本: "${name}"`;
log.info(logMessage); log.debug(logMessage);
} }
if (isJs && !isStart) { if (isJs && !isStart) {
// 处理 isJs = true 且 isStart = false 的情况 // 处理 isJs = true 且 isStart = false 的情况
@@ -545,7 +550,7 @@ async function fakeLog(name, isJs, isStart, duration) {
`→ 脚本执行结束: "${name}", 耗时: ${durationMinutes}${durationSeconds}\n\n` + `→ 脚本执行结束: "${name}", 耗时: ${durationMinutes}${durationSeconds}\n\n` +
`[${formattedTime}] [INF] BetterGenshinImpact.Service.ScriptService\n` + `[${formattedTime}] [INF] BetterGenshinImpact.Service.ScriptService\n` +
`------------------------------`; `------------------------------`;
log.info(logMessage); log.debug(logMessage);
} }
if (!isJs && isStart) { if (!isJs && isStart) {
// 处理 isJs = false 且 isStart = true 的情况 // 处理 isJs = false 且 isStart = true 的情况
@@ -554,7 +559,7 @@ async function fakeLog(name, isJs, isStart, duration) {
`------------------------------\n\n` + `------------------------------\n\n` +
`[${formattedTime}] [INF] BetterGenshinImpact.Service.ScriptService\n` + `[${formattedTime}] [INF] BetterGenshinImpact.Service.ScriptService\n` +
`→ 开始执行地图追踪任务: "${name}"`; `→ 开始执行地图追踪任务: "${name}"`;
log.info(logMessage); log.debug(logMessage);
} }
if (!isJs && !isStart) { if (!isJs && !isStart) {
// 处理 isJs = false 且 isStart = false 的情况 // 处理 isJs = false 且 isStart = false 的情况
@@ -563,7 +568,7 @@ async function fakeLog(name, isJs, isStart, duration) {
`→ 脚本执行结束: "${name}", 耗时: ${durationMinutes}${durationSeconds}\n\n` + `→ 脚本执行结束: "${name}", 耗时: ${durationMinutes}${durationSeconds}\n\n` +
`[${formattedTime}] [INF] BetterGenshinImpact.Service.ScriptService\n` + `[${formattedTime}] [INF] BetterGenshinImpact.Service.ScriptService\n` +
`------------------------------`; `------------------------------`;
log.info(logMessage); log.debug(logMessage);
} }
} }
@@ -893,7 +898,7 @@ async function recognizeImage(recognitionObject, timeout = 5000) {
} }
// 定义一个函数用于识别文字并点击 // 定义一个函数用于识别文字并点击
async function recognizeTextAndClick(targetText, ocrRegion, timeout = 5000) { async function recognizeTextAndClick(targetText, ocrRegion, timeout = 3000) {
let startTime = Date.now(); let startTime = Date.now();
let retryCount = 0; // 重试计数 let retryCount = 0; // 重试计数
while (Date.now() - startTime < timeout) { while (Date.now() - startTime < timeout) {
@@ -910,8 +915,8 @@ async function recognizeTextAndClick(targetText, ocrRegion, timeout = 5000) {
if (correctedText.includes(targetText)) { if (correctedText.includes(targetText)) {
// 如果找到目标文本,计算并点击文字的中心坐标 // 如果找到目标文本,计算并点击文字的中心坐标
let centerX = res.x + res.width / 2; let centerX = Math.round(res.x + res.width / 2);
let centerY = res.y + res.height / 2; let centerY = Math.round(res.y + res.height / 2);
await click(centerX, centerY); await click(centerX, centerY);
await sleep(500); // 确保点击后有足够的时间等待 await sleep(500); // 确保点击后有足够的时间等待
return { success: true, x: centerX, y: centerY }; return { success: true, x: centerX, y: centerY };
@@ -923,7 +928,11 @@ async function recognizeTextAndClick(targetText, ocrRegion, timeout = 5000) {
} }
await sleep(1000); // 短暂延迟,避免过快循环 await sleep(1000); // 短暂延迟,避免过快循环
} }
log.warn(`经过多次尝试,仍然无法识别文字: ${targetText}`); log.warn(`经过多次尝试,仍然无法识别文字: ${targetText},尝试点击默认中心位置`);
let centerX = Math.round(ocrRegion.x + ocrRegion.width / 2);
let centerY = Math.round(ocrRegion.y + ocrRegion.height / 2);
await click(centerX, centerY);
await sleep(1000);
return { success: false }; return { success: false };
} }
@@ -1028,34 +1037,37 @@ async function decomposeArtifacts(keep4Star, doDecompose) {
} else { } else {
log.warn(`在指定区域未识别到有效数字: ${initialValue}`); log.warn(`在指定区域未识别到有效数字: ${initialValue}`);
} }
await recognizeTextAndClick("快速选择", { x: 248, y: 996, width: 121, height: 49 });
moveMouseTo(960, 540);
await sleep(1000);
await click(370, 1020); // 点击“确认选择”按钮
await sleep(1500);
let regionToCheck3 = { x: 100, y: 885, width: 170, height: 50 }; let regionToCheck3 = { x: 100, y: 885, width: 170, height: 50 };
let decomposedNum = await recognizeTextInRegion(regionToCheck3); let decomposedNum = await recognizeTextInRegion(regionToCheck3);
let firstNumber = 0; let firstNumber = 0;
let firstNumber2 = 0; let firstNumber2 = 0;
// 使用正则表达式提取第一个数字 if (keep4Star) {
const match = decomposedNum.match(/已选(\d+)/); await recognizeTextAndClick("快速选择", { x: 248, y: 996, width: 121, height: 49 });
moveMouseTo(960, 540);
await sleep(1000);
// 检查是否匹配成功 await click(370, 1020); // 点击“确认选择”按钮
if (match) { await sleep(1500);
// 将匹配到的第一个数字转换为数字类型并存储在变量中
firstNumber = Number(match[1]);
} else {
log.info("识别失败"); // 使用正则表达式提取第一个数字
const match = decomposedNum.match(/已选(\d+)/);
// 检查是否匹配成功
if (match) {
// 将匹配到的第一个数字转换为数字类型并存储在变量中
firstNumber = Number(match[1]);
} else {
log.info("识别失败");
}
keyPress("VK_ESCAPE");
await recognizeTextAndClick("分解", { x: 635, y: 991, width: 81, height: 57 });
await sleep(1000);
} }
keyPress("VK_ESCAPE");
await recognizeTextAndClick("分解", { x: 635, y: 991, width: 81, height: 57 });
await sleep(1000);
await recognizeTextAndClick("快速选择", { x: 248, y: 996, width: 121, height: 49 }); await recognizeTextAndClick("快速选择", { x: 248, y: 996, width: 121, height: 49 });
moveMouseTo(960, 540); moveMouseTo(960, 540);
await sleep(1000); await sleep(1000);
@@ -1093,20 +1105,24 @@ async function decomposeArtifacts(keep4Star, doDecompose) {
} }
if (doDecompose) { if (doDecompose) {
log.info(`用户选择了分解,执行分解`);
// 根据用户配置,分解狗粮 // 根据用户配置,分解狗粮
await sleep(500); await sleep(1000);
await click(1620, 1020); // 点击分解按钮 await click(1620, 1020); // 点击分解按钮
await sleep(500); await sleep(1000);
// 4. 识别"进行分解"按钮 // 4. 识别"进行分解"按钮
await recognizeTextAndClick("分解", { x: 1120, y: 740, width: 130, height: 40 }); await click(1340, 755); // 点击进行分解按钮
await sleep(1000); await sleep(1000);
// 5. 关闭确认界面 // 5. 关闭确认界面
await click(1620, 1020); await click(1340, 755);
await sleep(1000); await sleep(1000);
} }
else {
log.info(`用户未选择分解,不执行分解`);
}
// 7. 计算分解获得经验=总经验-上次剩余 // 7. 计算分解获得经验=总经验-上次剩余
const resinExperience = Math.max(newValue - initialValue, 0); const resinExperience = Math.max(newValue - initialValue, 0);

View File

@@ -1,7 +1,7 @@
{ {
"manifest_version": 1, "manifest_version": 1,
"name": "自动狗粮重制版", "name": "自动狗粮重制版",
"version": "1.2", "version": "1.21",
"tags": ["好感", "盗宝团", "愚人众", "鳄鱼", "兽肉", "狗粮"], "tags": ["好感", "盗宝团", "愚人众", "鳄鱼", "兽肉", "狗粮"],
"description": "通过不同好感任务卡时间后运行狗粮任务以提高狗粮总收益,需要正确配置好感队伍的战斗策略,并在自定义配置中指定好感和狗粮队伍名称", "description": "通过不同好感任务卡时间后运行狗粮任务以提高狗粮总收益,需要正确配置好感队伍的战斗策略,并在自定义配置中指定好感和狗粮队伍名称",
"authors": [ "authors": [

View File

@@ -1,5 +1,5 @@
上次运行完成日期: 2025/06/07 上次运行完成日期: 2025/05/25
上次结束时间: 2025-06-07T00:05:41.866Z 上次结束时间: 2025-05-24T20:00:00.000Z
上次运行路线: A 上次运行路线: A
历史收益: 历史收益:
日期:2025/05/25运行路线F狗粮经验-1摩拉-1 日期:2025/05/25运行路线F狗粮经验-1摩拉-1
@@ -8,4 +8,4 @@
日期:2025/05/22运行路线F狗粮经验-1摩拉-1 日期:2025/05/22运行路线F狗粮经验-1摩拉-1
日期:2025/05/21运行路线F狗粮经验-1摩拉-1 日期:2025/05/21运行路线F狗粮经验-1摩拉-1
日期:2025/05/20运行路线F狗粮经验-1摩拉-1 日期:2025/05/20运行路线F狗粮经验-1摩拉-1
日期:2025/05/19运行路线F狗粮经验-1摩拉-1 日期:2025/05/19运行路线F狗粮经验-1摩拉-1

View File

@@ -13,20 +13,29 @@
"id": 1, "id": 1,
"x": -2738.38, "x": -2738.38,
"y": -3414.45, "y": -3414.45,
"action": "", "action": "combat_script",
"move_mode": "walk", "move_mode": "walk",
"action_params": "", "action_params": "wait(1)",
"type": "teleport" "type": "orientation"
}, },
{ {
"id": 2, "id": 2,
"x": -2736.60, "x": -2738.38,
"y": -3415.44, "y": -3414.45,
"type": "path", "action": "",
"move_mode": "walk", "move_mode": "walk",
"action": "combat_script", "action_params": "",
"action_params": "wait(0.5)", "type": "teleport",
"locked": false "locked": false
},
{
"id": 3,
"x": -2736.6,
"y": -3415.44,
"action": "exit_and_relogin",
"move_mode": "walk",
"action_params": "",
"type": "path"
} }
] ]
} }

View File

@@ -133,10 +133,10 @@ async function fakeLog(name, isJs, isStart, duration) {
await fakeLog(`${i + 1}次信仰之跃.json`, false, false, 0); await fakeLog(`${i + 1}次信仰之跃.json`, false, false, 0);
//捕获任务结束的信息,同时等待95秒用来卡时间 //捕获任务结束的信息,同时等待115秒用来卡时间
try { try {
log.info('正在等待复活料理cd') log.info('正在等待复活料理cd')
await sleep(95000); await sleep(115000);
} catch (error) { } catch (error) {
log.error(`发生错误: ${error}`); log.error(`发生错误: ${error}`);
break; // 终止循环 break; // 终止循环

View File

@@ -11,40 +11,21 @@
"positions": [ "positions": [
{ {
"id": 1, "id": 1,
"x": 508.03515625, "x": 2297.58984375,
"y": -630.49072265625, "y": -824.51416015625,
"action": "",
"move_mode": "walk",
"action_params": "",
"type": "teleport", "type": "teleport",
"locked": false "move_mode": "walk",
"action": "",
"action_params": ""
}, },
{ {
"id": 2, "id": 2,
"x": 508.03515625, "x": 2313.7578125,
"y": -630.49072265625, "y": -821.52001953125,
"action": "combat_script", "type": "path",
"move_mode": "walk", "move_mode": "walk",
"action_params": "keypress(1)",
"type": "path"
},
{
"id": 3,
"x": 499.87890625,
"y": -686.18310546875,
"action": "stop_flying",
"move_mode": "fly",
"action_params": "10000",
"type": "path"
},
{
"id": 4,
"x": 501.3095703125,
"y": -683.6240234375,
"action": "combat_script", "action": "combat_script",
"move_mode": "walk", "action_params": "wait(1),keypress(z)"
"action_params": "wait(5),keypress(z)",
"type": "path"
} }
] ]
} }