js,购买食材修复bug+优化 (#816) (#648)

* js,购买食材优化

修复循环套叠,优化F未识别后的尝试方案

* Add files via upload
This commit is contained in:
JJMdzh
2025-05-14 21:37:05 +08:00
committed by GitHub
parent beb7084359
commit 1a4381a6cf
2 changed files with 91 additions and 50 deletions

View File

@@ -92,7 +92,7 @@ const replacementMap = {
const npcNames = { const npcNames = {
[mondstadtGroceryFilePath]: ["布兰琪"], [mondstadtGroceryFilePath]: ["布兰琪"],
[liyueGroceryFilePath]: ["东升"], [liyueGroceryFilePath]: ["东升"],
[liyueWanminFilePath]: ["卯师傅"],// ["卯师傅", "卵师傅"] [liyueWanminFilePath]: ["卯师傅", "师傅"],// ["卯师傅", "卵师傅"]
[groceryFilePath]: ["葵"], [groceryFilePath]: ["葵"],
[charcoalFilePath]: ["志村勘"], [charcoalFilePath]: ["志村勘"],
[fengdanGroceryFilePath]: ["布希柯"], [fengdanGroceryFilePath]: ["布希柯"],
@@ -210,6 +210,7 @@ function performOcr(targetText, xRange, yRange, tolerance, timeout = 2000) {
// 遍历识别结果,检查是否找到目标文本 // 遍历识别结果,检查是否找到目标文本
for (let i = 0; i < resList.count; i++) { for (let i = 0; i < resList.count; i++) {
let res = resList[i]; let res = resList[i];
// log.info("0CR结果-"+ res.text);
// 后处理:根据替换映射表检查和替换错误识别的字符 // 后处理:根据替换映射表检查和替换错误识别的字符
let correctedText = res.text; let correctedText = res.text;
for (let [wrongChar, correctChar] of Object.entries(replacementMap)) { for (let [wrongChar, correctChar] of Object.entries(replacementMap)) {
@@ -297,56 +298,71 @@ async function clickSelectedIngredients(selectedIngredients, filePath, npcNames)
} }
} }
// 检查 F 图标和右边水平对齐的文字 // 检查 F 图标和右边水平对齐的文字
async function checkNpcAndFAlignment(npcName, fDialogueRo) { async function checkNpcAndFAlignment(npcName, fDialogueRo) {
let ra = captureGameRegion(); let ra = captureGameRegion();
let fRes = ra.find(fDialogueRo); let fRes = ra.find(fDialogueRo);
if (!fRes.isExist()) { if (!fRes.isExist()) {
let f_attempts = 0; // 初始化尝试次数 let f_attempts = null; // 初始化尝试次数
while (f_attempts < 3) { // 最多尝试 3 while (f_attempts < 5) { // 最多尝试 4
f_attempts++; f_attempts++;
log.info(`当前尝试次数:${f_attempts}`); log.info(`当前尝试次数:${f_attempts}`);
if (f_attempts === 1) { if (f_attempts <= 3) {
// 第一次未找到 F 图标 // 第 1-3 次尝试
await simulateKeyOperations("S", 200); // 后退 200 毫秒 await simulateKeyOperations("S", 200); // 后退 200 毫秒
await sleep(200); await sleep(200);
await simulateKeyOperations("W", 800); // 前进 800 毫秒 await simulateKeyOperations("W", 400); // 前进 400 毫秒
} else if (f_attempts === 2) { await sleep(500);
// 第二次未找到 F 图标 } else if (f_attempts === 4) {
log.info("重新加载路径文件"); // 第 4 次尝试
await pathingScript.runFile(filePath); log.info("重新加载路径文件");
await sleep(500); await pathingScript.runFile(filePath);
} else { await sleep(500);
// 第三次未找到 F 图标 } else {
log.warn("尝试次数已达上限"); // 第 5 次尝试,尝试次数已达上限
return false; log.warn("尝试次数已达上限");
} break; // 找到后退出循环
log.warn(`尝试 ${f_attempts + 1}:寻找 F 图标`);
} }
}
// 获取 F 图标的中心点 Y 坐标
let centerYF = fRes.y + fRes.height / 2;
// 在 F 图标右侧水平方向上识别 NPC 名称 // 检查是否找到 F 图标
let ocrResult = await performOcr(npcName, npcxRange, { min: fRes.y, max: fRes.y + fRes.height }, tolerance); fRes = ra.find(fDialogueRo); // 重新查找 F 图标
if (!ocrResult.success) { if (fRes.isExist()) {
log.warn(`OCR 识别未找到 NPC: ${npcName},尝试滚动`); log.info("找到 F 图标");
return false; break; // 找到后退出循环
}
log.warn(`尝试 ${f_attempts}:寻找 F 图标`);
} }
// 获取 NPC 名称的中心点 Y 坐标 // 如果尝试次数用完仍未找到 F 图标,返回 false
let centerYnpcName = ocrResult.y + ocrResult.height / 2; if (!fRes.isExist()) {
log.warn("经过多次尝试后仍未找到 F 图标");
// 检查 NPC 名称和 F 图标的中心点 Y 坐标是否在容错范围内
if (Math.abs(centerYnpcName - centerYF) <= npctolerance) {
return true;
} else {
log.info(`NPC '${npcName}' 和 F 图标未水平对齐, NPC: ${centerYnpcName}, F 图标: ${centerYF}`);
return false; return false;
} }
} }
// 获取 F 图标的中心点 Y 坐标
let centerYF = fRes.y + fRes.height / 2;
// 在 F 图标右侧水平方向上识别 NPC 名称
let ocrResult = await performOcr(npcName, npcxRange, { min: fRes.y, max: fRes.y + fRes.height }, tolerance);
if (!ocrResult.success) {
log.warn(`OCR 识别未找到 NPC: ${npcName},尝试滚动`);
return false;
}
// 获取 NPC 名称的中心点 Y 坐标
let centerYnpcName = ocrResult.y + ocrResult.height / 2;
// 检查 NPC 名称和 F 图标的中心点 Y 坐标是否在容错范围内
if (Math.abs(centerYnpcName - centerYF) <= npctolerance) {
return true;
} else {
log.info(`NPC '${npcName}' 和 F 图标未水平对齐NPC: ${centerYnpcName}, F 图标: ${centerYF}`);
return false;
}
}
// 新增变量用于记录滚轮操作次数 // 新增变量用于记录滚轮操作次数
let scrollAttempts = 0; let scrollAttempts = 0;
const maxScrollAttempts = 5; // 最大滚轮操作次数限制 const maxScrollAttempts = 5; // 最大滚轮操作次数限制
@@ -354,7 +370,6 @@ async function clickSelectedIngredients(selectedIngredients, filePath, npcNames)
for (const npcName of npcNames) { for (const npcName of npcNames) {
log.info(`尝试识别 NPC: ${npcName}`); log.info(`尝试识别 NPC: ${npcName}`);
let isAligned = await checkNpcAndFAlignment(npcName, fDialogueRo); let isAligned = await checkNpcAndFAlignment(npcName, fDialogueRo);
while (!isAligned && scrollAttempts < maxScrollAttempts) { while (!isAligned && scrollAttempts < maxScrollAttempts) {
// 如果未水平对齐,执行滚轮操作 // 如果未水平对齐,执行滚轮操作
await keyMouseScript.runFile(`assets/滚轮下翻.json`); await keyMouseScript.runFile(`assets/滚轮下翻.json`);
@@ -368,13 +383,39 @@ async function clickSelectedIngredients(selectedIngredients, filePath, npcNames)
} }
// 重新检查 F 图标和 NPC 名称是否对齐 // 重新检查 F 图标和 NPC 名称是否对齐
isAligned = await checkNpcAndFAlignment(npcName, fDialogueRo); let ra = captureGameRegion();
let fRes = ra.find(fDialogueRo);
if (!fRes.isExist()) {
log.warn("未找到 F 图标");
continue; // 如果未找到 F 图标,继续下一次循环
}
// 获取 F 图标的中心点 Y 坐标
let centerYF = fRes.y + fRes.height / 2;
// 在 F 图标右侧水平方向上识别 NPC 名称
let ocrResult = await performOcr(npcName, npcxRange, { min: fRes.y, max: fRes.y + fRes.height }, tolerance);
if (!ocrResult.success) {
log.warn(`OCR 识别未找到 NPC: ${npcName}`);
continue; // 如果未找到 NPC 名称,继续下一次循环
}
// 获取 NPC 名称的中心点 Y 坐标
let centerYnpcName = ocrResult.y + ocrResult.height / 2;
// 检查 NPC 名称和 F 图标的中心点 Y 坐标是否在容错范围内
if (Math.abs(centerYnpcName - centerYF) <= npctolerance) {
isAligned = true;
log.info(`NPC '${npcName}' 和 F 图标水平对齐NPC: ${centerYnpcName}, F 图标: ${centerYF}`);
} else {
log.info(`NPC '${npcName}' 和 F 图标未水平对齐NPC: ${centerYnpcName}, F 图标: ${centerYF}`);
}
} }
// 如果水平对齐,执行交互操作 // 如果水平对齐,执行交互操作
if (isAligned) { if (isAligned) {
keyPress("F"); keyPress("F");
await sleep(2500); await sleep(2500);
// 首次执行点击操作 // 首次执行点击操作
await performClickOperations(filePath); await performClickOperations(filePath);

View File

@@ -1,8 +1,8 @@
{ {
"manifest_version": 1, "manifest_version": 1,
"name": "选择购买食材OCR", "name": "选择购买食材OCR",
"version": "1.30420", "version": "1.30513",
"description": "至少需要0.44版本bgi对NPC和材料进行文字、图像识别。\n一般食材杂货在蒙德、璃月、稻妻、枫丹杂货商购买。\n10鱼肉、10螃蟹在卯师傅、珀姆、布特罗斯、阿扎莱和志村勘兵卫购买。\n咖啡豆在须弥、枫丹咖啡馆购买。\n增加对话F图像识别增加个别字识别容错增加香辛料在阿扎莱处购买", "description": "至少需要0.44版本bgi对NPC和材料进行文字、图像识别。\n一般食材杂货在蒙德、璃月、稻妻、枫丹杂货商购买。\n10鱼肉、10螃蟹在卯师傅、珀姆、布特罗斯、阿扎莱和志村勘兵卫购买。\n咖啡豆在须弥、枫丹咖啡馆购买。\n增加对话F图像识别增加个别字识别容错增加香辛料在阿扎莱处购买。\nv1.30513修复循环套叠优化F未识别后的尝试方案。",
"authors": [ "authors": [
{ {
"name": "吉吉喵" "name": "吉吉喵"