diff --git a/repo/js/采集cd管理/main.js b/repo/js/采集cd管理/main.js index 2ec1b21e5..9f83d7bfe 100644 --- a/repo/js/采集cd管理/main.js +++ b/repo/js/采集cd管理/main.js @@ -1762,7 +1762,6 @@ async function isTimeRestricted(timeRule, threshold = 5) { return false; } - /** * 食材加工主函数,用于自动前往指定地点进行食材的加工 * @@ -1772,8 +1771,20 @@ async function isTimeRestricted(timeRule, threshold = 5) { * @returns {Promise} 无返回值,执行完所有加工流程后退出 */ async function ingredientProcessing() { - if (Foods.length == 0) { log.error("未选择要加工的料理/食材"); return; } - if (Foods.length != foodCount.length) { log.error("请检查料理与对应的数量是否一致!"); return; } + const targetFoods = [ + "面粉", "兽肉", "鱼肉", "神秘的肉", "黑麦粉", "奶油", "熏禽肉", + "黄油", "火腿", "糖", "香辛料", "酸奶油", "蟹黄", "果酱", + "奶酪", "培根", "香肠" + ]; + if (Foods.length == 0) { log.error("未选择要加工的食材"); return; } + if (Foods.length != foodCount.length) { log.error("请检查食材与对应的数量是否一致!"); return; } + const taskList = Foods.map((name, i) => `${name}*${foodCount[i]}`).join(","); + const tasks = Foods.map((name, idx) => ({ + name, + count: Number(foodCount[idx]) || 0, + done: false + })); + log.info(`本次加工食材:${taskList}`); const stove = "蒙德炉子"; log.info(`正在前往${stove}进行食材加工`); @@ -1813,13 +1824,6 @@ async function ingredientProcessing() { } await clickPNG("食材加工"); - // 固定列表只定义一次 - const targetFoods = new Set([ - "面粉", "兽肉", "鱼肉", "神秘的肉", "黑麦粉", "奶油", "熏禽肉", - "黄油", "火腿", "糖", "香辛料", "酸奶油", "蟹黄", "果酱", - "奶酪", "培根", "香肠" - ]); - /* ===== 1. 公共加工流程 ===== */ async function doCraft(i) { await clickPNG("制作"); @@ -1827,9 +1831,9 @@ async function ingredientProcessing() { /* ---------- 1. 队列已满 ---------- */ if (await findPNG("队列已满", 1)) { - log.warn(`检测到${Foods[i]}队列已满,等待图标消失`); + log.warn(`检测到${tasks[i].name}队列已满,等待图标消失`); while (await findPNG("队列已满", 1)) { - log.warn(`检测到${Foods[i]}队列已满,等待图标消失`); + log.warn(`检测到${tasks[i].name}队列已满,等待图标消失`); await sleep(300); } if (await clickPNG("全部领取", 3)) { @@ -1842,9 +1846,9 @@ async function ingredientProcessing() { /* ---------- 2. 材料不足 ---------- */ if (await findPNG("材料不足", 1)) { - log.warn(`检测到${Foods[i]}材料不足,等待图标消失`); + log.warn(`检测到${tasks[i].name}材料不足,等待图标消失`); while (await findPNG("材料不足", 1)) { - log.warn(`检测到${Foods[i]}材料不足,等待图标消失`); + log.warn(`检测到${tasks[i].name}材料不足,等待图标消失`); await sleep(300); } if (await clickPNG("全部领取", 3)) { @@ -1854,6 +1858,7 @@ async function ingredientProcessing() { } Foods.splice(i, 1); foodCount.splice(i, 1); + return false; } @@ -1861,16 +1866,17 @@ async function ingredientProcessing() { await findPNG("选择加工数量"); click(960, 460); await sleep(800); - inputText(foodCount[i]); - log.info(`尝试制作${Foods[i]} ${foodCount[i]}个`); + inputText(String(tasks[i].count)); + + log.info(`尝试制作${tasks[i].name} ${tasks[i].count}个`); await clickPNG("确认加工"); await sleep(500); /* ---------- 4. 已不能持有更多 ---------- */ if (await findPNG("已不能持有更多", 1)) { - log.warn(`检测到${Foods[i]}已满,等待图标消失`); + log.warn(`检测到${tasks[i].name}已满,等待图标消失`); while (await findPNG("已不能持有更多", 1)) { - log.warn(`检测到${Foods[i]}已满,等待图标消失`); + log.warn(`检测到${tasks[i].name}已满,等待图标消失`); await sleep(300); } if (await clickPNG("全部领取", 3)) { @@ -1880,6 +1886,7 @@ async function ingredientProcessing() { } Foods.splice(i, 1); foodCount.splice(i, 1); + return false; } @@ -1893,8 +1900,6 @@ async function ingredientProcessing() { } /* ===== 2. 两轮扫描 ===== */ - const done = new Array(Foods.length).fill(false); - // 进入界面先领取一次 if (await clickPNG("全部领取", 3)) { await clickPNG("点击空白区域继续"); @@ -1902,17 +1907,30 @@ async function ingredientProcessing() { await sleep(100); } - /* ---------- 第一轮:直接找 Foods[i]+"1" ---------- */ - for (let i = 0; i < Foods.length; i++) { - if (!targetFoods.has(Foods[i])) continue; - if (await clickPNG(Foods[i] + "1", 5)) { - log.info(`${Foods[i]}已找到`); + let lastSuccess = true; + for (let i = 0; i < tasks.length; i++) { + if (!targetFoods.includes(tasks[i].name)) continue; + + const retry = lastSuccess ? 5 : 1; + if (await clickPNG(`${tasks[i].name}1`, retry)) { + log.info(`${tasks[i].name}已找到`); await doCraft(i); - done[i] = true; + tasks[i].done = true; + lastSuccess = true; // 记录成功 + } else { + lastSuccess = false; // 记录失败 } } - /* ---------- 第二轮:先点 item,再轮询 5 次识别 ---------- */ + const remain1 = tasks.filter(t => !t.done).map(t => `${t.name}*${t.count}`).join(",") || "无"; + log.info(`剩余待加工食材:${remain1}`); + + if (remain1 === "无") { + log.info("所有食材均已加工完毕,跳过第二轮扫描"); + await genshin.returnMainUi(); + return; + } + const rg = captureGameRegion(); const foodItems = []; try { @@ -1926,50 +1944,57 @@ async function ingredientProcessing() { } } finally { rg.dispose(); } - for (const item of foodItems) { - click(item.x, item.y); await sleep(200); - click(item.x, item.y); await sleep(200); + log.info(`识别到${foodItems.length}个加工中食材`); - const foodROs = []; - for (let i = 0; i < Foods.length; i++) { - if (!targetFoods.has(Foods[i])) continue; // 只处理目标食材 - const ro = RecognitionObject.TemplateMatch( - file.ReadImageMatSync(`assets/RecognitionObject/${Foods[i]}2.png`) - ); - ro.Threshold = 0.95; - ro.InitTemplate(); - foodROs.push({ idx: i, name: Foods[i], ro }); // 记住原数组下标 - } + for (const item of foodItems) { + click(item.x, item.y); await sleep(1 * checkInterval); + click(item.x, item.y); await sleep(6 * checkInterval); for (let round = 0; round < 5; round++) { const rg = captureGameRegion(); try { let hit = false; - /* 2. 在同一帧里用建好的模板依次匹配 */ - for (const it of foodROs) { - if (done[it.idx]) continue; // 已完成的跳过 + /* 直接扫 tasks,模板已挂在 task.ro */ + for (const task of tasks) { + if (task.done) continue; + if (!targetFoods.includes(task.name)) continue; - const res = rg.find(it.ro); + /* 首次使用再加载,避免重复 IO */ + if (!task.ro) { + task.ro = RecognitionObject.TemplateMatch( + file.ReadImageMatSync(`assets/RecognitionObject/${task.name}2.png`) + ); + task.ro.Threshold = 0.9; + task.ro.InitTemplate(); + } + + if (!task.ro) { + log.warn(`${task.name}2.png 不存在,跳过识别`); + continue; + } + const res = rg.find(task.ro); if (res.isExist()) { - log.info(`${it.name}已找到`); - res.click(); - rg.dispose(); // 提前释放 - await doCraft(it.idx); - done[it.idx] = true; + log.info(`${task.name}已找到`); + await doCraft(tasks.indexOf(task)); + task.done = true; hit = true; - break; // 一轮只处理一个 + break; // 一轮只处理一个 } } - if (hit) break; // 本轮已处理,跳出 round + if (hit) break; // 本轮已命中,跳出 round } finally { - rg.dispose(); // 确保释放截图 + rg.dispose(); } } - } + const remain = tasks.filter(t => !t.done).map(t => `${t.name}*${t.count}`).join(",") || "无"; + log.info(`剩余待加工食材:${remain}`); + + + await genshin.returnMainUi(); } diff --git a/repo/js/采集cd管理/manifest.json b/repo/js/采集cd管理/manifest.json index 6f33d7c55..33ca89e4a 100644 --- a/repo/js/采集cd管理/manifest.json +++ b/repo/js/采集cd管理/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 1, "name": "采集cd管理", - "version": "2.8.1", + "version": "2.8.2", "bgi_version": "0.44.8", "description": "仅面对会操作文件和读readme的用户,基于文件夹操作自动管理采集路线的cd,会按照路径组的顺序依次运行,直到指定的时间,并会按照给定的cd类型,自动跳过未刷新的路线", "saved_files": [ diff --git a/repo/js/食材加工极速版/README.md b/repo/js/食材加工极速版/README.md new file mode 100644 index 000000000..81867f1b3 --- /dev/null +++ b/repo/js/食材加工极速版/README.md @@ -0,0 +1,2 @@ +原则上仅用于1080p分辨率,其他分辨率能够使用纯属巧合,出现问题后果自负 +当某种食材原料恰好在本次加工中耗尽时会引起食材位置改变,默认状态下会在未完成加工时尝试重试,可通过自定义配置禁用 \ No newline at end of file diff --git a/repo/js/食材加工极速版/assets/RecognitionObject/交互烹饪锅.png b/repo/js/食材加工极速版/assets/RecognitionObject/交互烹饪锅.png new file mode 100644 index 000000000..a95141c19 Binary files /dev/null and b/repo/js/食材加工极速版/assets/RecognitionObject/交互烹饪锅.png differ diff --git a/repo/js/食材加工极速版/assets/RecognitionObject/全部领取.png b/repo/js/食材加工极速版/assets/RecognitionObject/全部领取.png new file mode 100644 index 000000000..c22f6757a Binary files /dev/null and b/repo/js/食材加工极速版/assets/RecognitionObject/全部领取.png differ diff --git a/repo/js/食材加工极速版/assets/RecognitionObject/兽肉1.png b/repo/js/食材加工极速版/assets/RecognitionObject/兽肉1.png new file mode 100644 index 000000000..16ffa542a Binary files /dev/null and b/repo/js/食材加工极速版/assets/RecognitionObject/兽肉1.png differ diff --git a/repo/js/食材加工极速版/assets/RecognitionObject/兽肉2.png b/repo/js/食材加工极速版/assets/RecognitionObject/兽肉2.png new file mode 100644 index 000000000..083057c32 Binary files /dev/null and b/repo/js/食材加工极速版/assets/RecognitionObject/兽肉2.png differ diff --git a/repo/js/食材加工极速版/assets/RecognitionObject/制作.png b/repo/js/食材加工极速版/assets/RecognitionObject/制作.png new file mode 100644 index 000000000..1ba1bb7de Binary files /dev/null and b/repo/js/食材加工极速版/assets/RecognitionObject/制作.png differ diff --git a/repo/js/食材加工极速版/assets/RecognitionObject/培根1.png b/repo/js/食材加工极速版/assets/RecognitionObject/培根1.png new file mode 100644 index 000000000..ad911cdb5 Binary files /dev/null and b/repo/js/食材加工极速版/assets/RecognitionObject/培根1.png differ diff --git a/repo/js/食材加工极速版/assets/RecognitionObject/培根2.png b/repo/js/食材加工极速版/assets/RecognitionObject/培根2.png new file mode 100644 index 000000000..34bd259d8 Binary files /dev/null and b/repo/js/食材加工极速版/assets/RecognitionObject/培根2.png differ diff --git a/repo/js/食材加工极速版/assets/RecognitionObject/奶油1.png b/repo/js/食材加工极速版/assets/RecognitionObject/奶油1.png new file mode 100644 index 000000000..f226b1dda Binary files /dev/null and b/repo/js/食材加工极速版/assets/RecognitionObject/奶油1.png differ diff --git a/repo/js/食材加工极速版/assets/RecognitionObject/奶油2.png b/repo/js/食材加工极速版/assets/RecognitionObject/奶油2.png new file mode 100644 index 000000000..264e6d5e7 Binary files /dev/null and b/repo/js/食材加工极速版/assets/RecognitionObject/奶油2.png differ diff --git a/repo/js/食材加工极速版/assets/RecognitionObject/奶酪1.png b/repo/js/食材加工极速版/assets/RecognitionObject/奶酪1.png new file mode 100644 index 000000000..2f2b10db8 Binary files /dev/null and b/repo/js/食材加工极速版/assets/RecognitionObject/奶酪1.png differ diff --git a/repo/js/食材加工极速版/assets/RecognitionObject/奶酪2.png b/repo/js/食材加工极速版/assets/RecognitionObject/奶酪2.png new file mode 100644 index 000000000..70853bfad Binary files /dev/null and b/repo/js/食材加工极速版/assets/RecognitionObject/奶酪2.png differ diff --git a/repo/js/食材加工极速版/assets/RecognitionObject/已不能持有更多.png b/repo/js/食材加工极速版/assets/RecognitionObject/已不能持有更多.png new file mode 100644 index 000000000..002abc62b Binary files /dev/null and b/repo/js/食材加工极速版/assets/RecognitionObject/已不能持有更多.png differ diff --git a/repo/js/食材加工极速版/assets/RecognitionObject/已加工0个.png b/repo/js/食材加工极速版/assets/RecognitionObject/已加工0个.png new file mode 100644 index 000000000..6438ede76 Binary files /dev/null and b/repo/js/食材加工极速版/assets/RecognitionObject/已加工0个.png differ diff --git a/repo/js/食材加工极速版/assets/RecognitionObject/已加工1个.png b/repo/js/食材加工极速版/assets/RecognitionObject/已加工1个.png new file mode 100644 index 000000000..f273136d9 Binary files /dev/null and b/repo/js/食材加工极速版/assets/RecognitionObject/已加工1个.png differ diff --git a/repo/js/食材加工极速版/assets/RecognitionObject/材料不足.png b/repo/js/食材加工极速版/assets/RecognitionObject/材料不足.png new file mode 100644 index 000000000..644874215 Binary files /dev/null and b/repo/js/食材加工极速版/assets/RecognitionObject/材料不足.png differ diff --git a/repo/js/食材加工极速版/assets/RecognitionObject/果酱1.png b/repo/js/食材加工极速版/assets/RecognitionObject/果酱1.png new file mode 100644 index 000000000..bf260eda2 Binary files /dev/null and b/repo/js/食材加工极速版/assets/RecognitionObject/果酱1.png differ diff --git a/repo/js/食材加工极速版/assets/RecognitionObject/果酱2.png b/repo/js/食材加工极速版/assets/RecognitionObject/果酱2.png new file mode 100644 index 000000000..269ca86cb Binary files /dev/null and b/repo/js/食材加工极速版/assets/RecognitionObject/果酱2.png differ diff --git a/repo/js/食材加工极速版/assets/RecognitionObject/火腿1.png b/repo/js/食材加工极速版/assets/RecognitionObject/火腿1.png new file mode 100644 index 000000000..34b962057 Binary files /dev/null and b/repo/js/食材加工极速版/assets/RecognitionObject/火腿1.png differ diff --git a/repo/js/食材加工极速版/assets/RecognitionObject/火腿2.png b/repo/js/食材加工极速版/assets/RecognitionObject/火腿2.png new file mode 100644 index 000000000..bd65cb450 Binary files /dev/null and b/repo/js/食材加工极速版/assets/RecognitionObject/火腿2.png differ diff --git a/repo/js/食材加工极速版/assets/RecognitionObject/点击空白区域继续.png b/repo/js/食材加工极速版/assets/RecognitionObject/点击空白区域继续.png new file mode 100644 index 000000000..32f4b1a9a Binary files /dev/null and b/repo/js/食材加工极速版/assets/RecognitionObject/点击空白区域继续.png differ diff --git a/repo/js/食材加工极速版/assets/RecognitionObject/熏禽肉1.png b/repo/js/食材加工极速版/assets/RecognitionObject/熏禽肉1.png new file mode 100644 index 000000000..1bbefbc31 Binary files /dev/null and b/repo/js/食材加工极速版/assets/RecognitionObject/熏禽肉1.png differ diff --git a/repo/js/食材加工极速版/assets/RecognitionObject/熏禽肉2.png b/repo/js/食材加工极速版/assets/RecognitionObject/熏禽肉2.png new file mode 100644 index 000000000..57f19359a Binary files /dev/null and b/repo/js/食材加工极速版/assets/RecognitionObject/熏禽肉2.png differ diff --git a/repo/js/食材加工极速版/assets/RecognitionObject/确认加工.png b/repo/js/食材加工极速版/assets/RecognitionObject/确认加工.png new file mode 100644 index 000000000..a46f7c596 Binary files /dev/null and b/repo/js/食材加工极速版/assets/RecognitionObject/确认加工.png differ diff --git a/repo/js/食材加工极速版/assets/RecognitionObject/神秘的肉1.png b/repo/js/食材加工极速版/assets/RecognitionObject/神秘的肉1.png new file mode 100644 index 000000000..85640efd2 Binary files /dev/null and b/repo/js/食材加工极速版/assets/RecognitionObject/神秘的肉1.png differ diff --git a/repo/js/食材加工极速版/assets/RecognitionObject/神秘的肉2.png b/repo/js/食材加工极速版/assets/RecognitionObject/神秘的肉2.png new file mode 100644 index 000000000..aa0025d29 Binary files /dev/null and b/repo/js/食材加工极速版/assets/RecognitionObject/神秘的肉2.png differ diff --git a/repo/js/食材加工极速版/assets/RecognitionObject/糖1.png b/repo/js/食材加工极速版/assets/RecognitionObject/糖1.png new file mode 100644 index 000000000..ce35ac202 Binary files /dev/null and b/repo/js/食材加工极速版/assets/RecognitionObject/糖1.png differ diff --git a/repo/js/食材加工极速版/assets/RecognitionObject/糖2.png b/repo/js/食材加工极速版/assets/RecognitionObject/糖2.png new file mode 100644 index 000000000..3f6dd3765 Binary files /dev/null and b/repo/js/食材加工极速版/assets/RecognitionObject/糖2.png differ diff --git a/repo/js/食材加工极速版/assets/RecognitionObject/蟹黄1.png b/repo/js/食材加工极速版/assets/RecognitionObject/蟹黄1.png new file mode 100644 index 000000000..47e28b9a3 Binary files /dev/null and b/repo/js/食材加工极速版/assets/RecognitionObject/蟹黄1.png differ diff --git a/repo/js/食材加工极速版/assets/RecognitionObject/蟹黄2.png b/repo/js/食材加工极速版/assets/RecognitionObject/蟹黄2.png new file mode 100644 index 000000000..dc7facf2d Binary files /dev/null and b/repo/js/食材加工极速版/assets/RecognitionObject/蟹黄2.png differ diff --git a/repo/js/食材加工极速版/assets/RecognitionObject/选择加工数量.png b/repo/js/食材加工极速版/assets/RecognitionObject/选择加工数量.png new file mode 100644 index 000000000..02c3de00e Binary files /dev/null and b/repo/js/食材加工极速版/assets/RecognitionObject/选择加工数量.png differ diff --git a/repo/js/食材加工极速版/assets/RecognitionObject/酸奶油1.png b/repo/js/食材加工极速版/assets/RecognitionObject/酸奶油1.png new file mode 100644 index 000000000..f16173f56 Binary files /dev/null and b/repo/js/食材加工极速版/assets/RecognitionObject/酸奶油1.png differ diff --git a/repo/js/食材加工极速版/assets/RecognitionObject/酸奶油2.png b/repo/js/食材加工极速版/assets/RecognitionObject/酸奶油2.png new file mode 100644 index 000000000..9c417a154 Binary files /dev/null and b/repo/js/食材加工极速版/assets/RecognitionObject/酸奶油2.png differ diff --git a/repo/js/食材加工极速版/assets/RecognitionObject/队列已满.png b/repo/js/食材加工极速版/assets/RecognitionObject/队列已满.png new file mode 100644 index 000000000..a5b425694 Binary files /dev/null and b/repo/js/食材加工极速版/assets/RecognitionObject/队列已满.png differ diff --git a/repo/js/食材加工极速版/assets/RecognitionObject/面粉1.png b/repo/js/食材加工极速版/assets/RecognitionObject/面粉1.png new file mode 100644 index 000000000..a217fafbc Binary files /dev/null and b/repo/js/食材加工极速版/assets/RecognitionObject/面粉1.png differ diff --git a/repo/js/食材加工极速版/assets/RecognitionObject/面粉2.png b/repo/js/食材加工极速版/assets/RecognitionObject/面粉2.png new file mode 100644 index 000000000..e47126602 Binary files /dev/null and b/repo/js/食材加工极速版/assets/RecognitionObject/面粉2.png differ diff --git a/repo/js/食材加工极速版/assets/RecognitionObject/食材加工.png b/repo/js/食材加工极速版/assets/RecognitionObject/食材加工.png new file mode 100644 index 000000000..1014b73f8 Binary files /dev/null and b/repo/js/食材加工极速版/assets/RecognitionObject/食材加工.png differ diff --git a/repo/js/食材加工极速版/assets/RecognitionObject/食材加工2.png b/repo/js/食材加工极速版/assets/RecognitionObject/食材加工2.png new file mode 100644 index 000000000..09f1c04ab Binary files /dev/null and b/repo/js/食材加工极速版/assets/RecognitionObject/食材加工2.png differ diff --git a/repo/js/食材加工极速版/assets/RecognitionObject/香肠1.png b/repo/js/食材加工极速版/assets/RecognitionObject/香肠1.png new file mode 100644 index 000000000..9c2b53476 Binary files /dev/null and b/repo/js/食材加工极速版/assets/RecognitionObject/香肠1.png differ diff --git a/repo/js/食材加工极速版/assets/RecognitionObject/香肠2.png b/repo/js/食材加工极速版/assets/RecognitionObject/香肠2.png new file mode 100644 index 000000000..0575cf19a Binary files /dev/null and b/repo/js/食材加工极速版/assets/RecognitionObject/香肠2.png differ diff --git a/repo/js/食材加工极速版/assets/RecognitionObject/香辛料1.png b/repo/js/食材加工极速版/assets/RecognitionObject/香辛料1.png new file mode 100644 index 000000000..adf4c438c Binary files /dev/null and b/repo/js/食材加工极速版/assets/RecognitionObject/香辛料1.png differ diff --git a/repo/js/食材加工极速版/assets/RecognitionObject/香辛料2.png b/repo/js/食材加工极速版/assets/RecognitionObject/香辛料2.png new file mode 100644 index 000000000..a0c57fe1e Binary files /dev/null and b/repo/js/食材加工极速版/assets/RecognitionObject/香辛料2.png differ diff --git a/repo/js/食材加工极速版/assets/RecognitionObject/鱼肉1.png b/repo/js/食材加工极速版/assets/RecognitionObject/鱼肉1.png new file mode 100644 index 000000000..a846d17b8 Binary files /dev/null and b/repo/js/食材加工极速版/assets/RecognitionObject/鱼肉1.png differ diff --git a/repo/js/食材加工极速版/assets/RecognitionObject/鱼肉2.png b/repo/js/食材加工极速版/assets/RecognitionObject/鱼肉2.png new file mode 100644 index 000000000..5832091ed Binary files /dev/null and b/repo/js/食材加工极速版/assets/RecognitionObject/鱼肉2.png differ diff --git a/repo/js/食材加工极速版/assets/RecognitionObject/黄油1.png b/repo/js/食材加工极速版/assets/RecognitionObject/黄油1.png new file mode 100644 index 000000000..50732ff2b Binary files /dev/null and b/repo/js/食材加工极速版/assets/RecognitionObject/黄油1.png differ diff --git a/repo/js/食材加工极速版/assets/RecognitionObject/黄油2.png b/repo/js/食材加工极速版/assets/RecognitionObject/黄油2.png new file mode 100644 index 000000000..21edd5afa Binary files /dev/null and b/repo/js/食材加工极速版/assets/RecognitionObject/黄油2.png differ diff --git a/repo/js/食材加工极速版/assets/RecognitionObject/黑麦粉1.png b/repo/js/食材加工极速版/assets/RecognitionObject/黑麦粉1.png new file mode 100644 index 000000000..3d860ff80 Binary files /dev/null and b/repo/js/食材加工极速版/assets/RecognitionObject/黑麦粉1.png differ diff --git a/repo/js/食材加工极速版/assets/RecognitionObject/黑麦粉2.png b/repo/js/食材加工极速版/assets/RecognitionObject/黑麦粉2.png new file mode 100644 index 000000000..a370c293b Binary files /dev/null and b/repo/js/食材加工极速版/assets/RecognitionObject/黑麦粉2.png differ diff --git a/repo/js/食材加工极速版/assets/蒙德炉子.json b/repo/js/食材加工极速版/assets/蒙德炉子.json new file mode 100644 index 000000000..52850589b --- /dev/null +++ b/repo/js/食材加工极速版/assets/蒙德炉子.json @@ -0,0 +1,115 @@ +{ + "config": { + "realtime_triggers": { + "AutoPick": true + } + }, + "farming_info": { + "allow_farming_count": false, + "duration_seconds": 0, + "elite_details": "", + "elite_mob_count": 0, + "normal_mob_count": 0, + "primary_target": "", + "total_mora": 0 + }, + "info": { + "authors": [ + { + "links": "https://github.com/jiangziyanowo", + "name": "江紫烟owo" + } + ], + "bgi_version": "0.45.0", + "description": "蒙德做菜炉子", + "enable_monster_loot_split": false, + "items": [], + "last_modified_time": 1758891203475, + "map_match_method": "", + "map_name": "Teyvat", + "name": "每周做菜", + "order": 0, + "tags": [], + "type": "collect", + "version": "1.0" + }, + "positions": [ + { + "action": "", + "id": 1, + "move_mode": "run", + "point_ext_params": { + "description": "", + "enable_monster_loot_split": false, + "misidentification": { + "arrival_time": 0, + "handling_mode": "previousDetectedPoint", + "type": [ + "unrecognized" + ] + } + }, + "type": "teleport", + "x": -874.724609375, + "y": 2276.950439453125 + }, + { + "action": "", + "id": 2, + "move_mode": "run", + "point_ext_params": { + "description": "", + "enable_monster_loot_split": false, + "misidentification": { + "arrival_time": 0, + "handling_mode": "previousDetectedPoint", + "type": [ + "unrecognized" + ] + } + }, + "type": "path", + "x": -881.150390625, + "y": 2268.43115234375 + }, + { + "action": "", + "id": 3, + "move_mode": "run", + "point_ext_params": { + "description": "", + "enable_monster_loot_split": false, + "misidentification": { + "arrival_time": 0, + "handling_mode": "previousDetectedPoint", + "type": [ + "unrecognized" + ] + } + }, + "type": "path", + "x": -887.611328125, + "y": 2256.250244140625 + }, + { + "action": "", + "action_params": "", + "id": 4, + "move_mode": "run", + "point_ext_params": { + "description": "", + "enable_monster_loot_split": false, + "misidentification": { + "arrival_time": 0, + "handling_mode": "previousDetectedPoint", + "type": [ + "unrecognized" + ] + } + }, + "type": "target", + "x": -883.83203125, + "y": 2242.46826171875 + } + ] +} \ No newline at end of file diff --git a/repo/js/食材加工极速版/main.js b/repo/js/食材加工极速版/main.js new file mode 100644 index 000000000..7745ea2e7 --- /dev/null +++ b/repo/js/食材加工极速版/main.js @@ -0,0 +1,311 @@ + + +let ingredientProcessingFood = settings.ingredientProcessingFood; +let foodCounts = settings.foodCount; + +let checkInterval = +settings.checkInterval || 50; + +let Foods = []; +let foodCount = []; + +(async function () { + if (typeof ingredientProcessingFood === 'string' && ingredientProcessingFood.trim()) { + Foods = ingredientProcessingFood + .split(/[,,;;\s]+/) // 支持中英文逗号、分号、空格 + .map(word => word.trim()) + .filter(word => word.length > 0); + } + + if (typeof foodCounts === 'string' && foodCounts.trim()) { + foodCount = foodCounts + .split(/[,,;;\s]+/) + .map(word => word.trim()) + .filter(word => word.length > 0); + } + await ingredientProcessing(); +})(); + + +/** +* 食材加工主函数,用于自动前往指定地点进行食材的加工 +* +* 该函数会根据 Foods 和 foodCount 数组中的食材名称和数量,依次查找并制作对应的料食材 +* 支持调味品类食材(直接在“食材加工”界面查找) +* +* @returns {Promise} 无返回值,执行完所有加工流程后退出 +*/ +async function ingredientProcessing() { + const targetFoods = [ + "面粉", "兽肉", "鱼肉", "神秘的肉", "黑麦粉", "奶油", "熏禽肉", + "黄油", "火腿", "糖", "香辛料", "酸奶油", "蟹黄", "果酱", + "奶酪", "培根", "香肠" + ]; + if (Foods.length == 0) { log.error("未选择要加工的食材"); return; } + if (Foods.length != foodCount.length) { log.error("请检查食材与对应的数量是否一致!"); return; } + const taskList = Foods.map((name, i) => `${name}*${foodCount[i]}`).join(","); + const tasks = Foods.map((name, idx) => ({ + name, + count: Number(foodCount[idx]) || 0, + done: false + })); + log.info(`本次加工食材:${taskList}`); + const stove = "蒙德炉子"; + log.info(`正在前往${stove}进行食材加工`); + + try { + let filePath = `assets/${stove}.json`; + await pathingScript.runFile(filePath); + } catch (error) { + log.error(`执行 ${stove} 路径时发生错误`); + return; + } + + const res1 = await findPNG("交互烹饪锅"); + if (res1) { + keyPress("F"); + } else { + log.warn("烹饪按钮未找到,正在寻找……"); + let attempts = 0; + const maxAttempts = 3; + let foundInRetry = false; + while (attempts < maxAttempts) { + log.info(`第${attempts + 1}次尝试寻找烹饪按钮`); + keyPress("W"); + const res2 = await findPNG("交互烹饪锅"); + if (res2) { + keyPress("F"); + foundInRetry = true; + break; + } else { + attempts++; + await sleep(500); + } + } + if (!foundInRetry) { + log.error("多次未找到烹饪按钮,放弃"); + return; + } + } + await clickPNG("食材加工"); + + /* ===== 1. 公共加工流程 ===== */ + async function doCraft(i) { + await clickPNG("制作"); + await sleep(300); + + /* ---------- 1. 队列已满 ---------- */ + if (await findPNG("队列已满", 1)) { + log.warn(`检测到${tasks[i].name}队列已满,等待图标消失`); + while (await findPNG("队列已满", 1)) { + log.warn(`检测到${tasks[i].name}队列已满,等待图标消失`); + await sleep(300); + } + if (await clickPNG("全部领取", 3)) { + await clickPNG("点击空白区域继续"); + await findPNG("食材加工2"); + await sleep(100); + } + return false; + } + + /* ---------- 2. 材料不足 ---------- */ + if (await findPNG("材料不足", 1)) { + log.warn(`检测到${tasks[i].name}材料不足,等待图标消失`); + while (await findPNG("材料不足", 1)) { + log.warn(`检测到${tasks[i].name}材料不足,等待图标消失`); + await sleep(300); + } + if (await clickPNG("全部领取", 3)) { + await clickPNG("点击空白区域继续"); + await findPNG("食材加工2"); + await sleep(100); + } + Foods.splice(i, 1); + foodCount.splice(i, 1); + + return false; + } + + /* ---------- 3. 正常加工流程 ---------- */ + await findPNG("选择加工数量"); + click(960, 460); + await sleep(800); + inputText(String(tasks[i].count)); + + log.info(`尝试制作${tasks[i].name} ${tasks[i].count}个`); + await clickPNG("确认加工"); + await sleep(500); + + /* ---------- 4. 已不能持有更多 ---------- */ + if (await findPNG("已不能持有更多", 1)) { + log.warn(`检测到${tasks[i].name}已满,等待图标消失`); + while (await findPNG("已不能持有更多", 1)) { + log.warn(`检测到${tasks[i].name}已满,等待图标消失`); + await sleep(300); + } + if (await clickPNG("全部领取", 3)) { + await clickPNG("点击空白区域继续"); + await findPNG("食材加工2"); + await sleep(100); + } + Foods.splice(i, 1); + foodCount.splice(i, 1); + + return false; + } + + await sleep(200); + /* 正常完成:仅领取,不移除 */ + if (await clickPNG("全部领取", 3)) { + await clickPNG("点击空白区域继续"); + await findPNG("食材加工2"); + await sleep(100); + } + } + + /* ===== 2. 两轮扫描 ===== */ + // 进入界面先领取一次 + if (await clickPNG("全部领取", 3)) { + await clickPNG("点击空白区域继续"); + await findPNG("食材加工2"); + await sleep(100); + } + + let lastSuccess = true; + for (let i = 0; i < tasks.length; i++) { + if (!targetFoods.includes(tasks[i].name)) continue; + + const retry = lastSuccess ? 5 : 1; + if (await clickPNG(`${tasks[i].name}1`, retry)) { + log.info(`${tasks[i].name}已找到`); + await doCraft(i); + tasks[i].done = true; + lastSuccess = true; // 记录成功 + } else { + lastSuccess = false; // 记录失败 + } + } + + const remain1 = tasks.filter(t => !t.done).map(t => `${t.name}*${t.count}`).join(",") || "无"; + log.info(`剩余待加工食材:${remain1}`); + + if (remain1 === "无") { + log.info("所有食材均已加工完毕,跳过第二轮扫描"); + await genshin.returnMainUi(); + return; + } + + /* ---------- 第二轮:无限轮询,直到全部完成或本轮零进展 ---------- */ + let allDone; // 本轮是否全部完成 + let progress; // 本轮是否至少完成 1 个 + + while (true) { + allDone = tasks.every(t => t.done); + if (allDone) break; // 条件 1 + + progress = false; // 先假设本轮零进展 + + const rg = captureGameRegion(); + const foodItems = []; + try { + for (const flag of ['已加工0个', '已加工1个']) { + const mat = file.ReadImageMatSync(`assets/RecognitionObject/${flag}.png`); + const res = rg.findMulti(RecognitionObject.TemplateMatch(mat)); + for (let k = 0; k < res.count; ++k) { + foodItems.push({ x: res[k].x, y: res[k].y }); + } + mat.dispose(); + } + } finally { rg.dispose(); } + + log.info(`识别到${foodItems.length}个加工中食材`); + + for (const item of foodItems) { + click(item.x, item.y); await sleep(1 * checkInterval); + click(item.x, item.y); await sleep(6 * checkInterval); + + for (let round = 0; round < 5; round++) { + const rg = captureGameRegion(); + try { + let hit = false; + + /* 直接扫 tasks,模板已挂在 task.ro */ + for (const task of tasks) { + if (task.done) continue; + if (!targetFoods.includes(task.name)) continue; + + /* 首次使用再加载,避免重复 IO */ + if (!task.ro) { + task.ro = RecognitionObject.TemplateMatch( + file.ReadImageMatSync(`assets/RecognitionObject/${task.name}2.png`) + ); + task.ro.Threshold = 0.9; + task.ro.InitTemplate(); + } + + if (!task.ro) { + log.warn(`${task.name}2.png 不存在,跳过识别`); + continue; + } + const res = rg.find(task.ro); + if (res.isExist()) { + log.info(`${task.name}已找到`); + await doCraft(tasks.indexOf(task)); + task.done = true; + hit = true; + progress = true; // 本轮有进展 + break; // 一轮只处理一个 + } + } + + if (hit) break; // 本轮已命中,跳出 round + } finally { + rg.dispose(); + } + } + } + + const remain = tasks.filter(t => !t.done).map(t => `${t.name}*${t.count}`).join(",") || "无"; + log.info(`剩余待加工食材:${remain}`); + + if (!progress) { // 条件 2:本轮零进展 + log.info("本轮未再完成任何食材,结束第二轮"); + break; + } + + if (settings.disableRetry) { + break; + } + } + + await genshin.returnMainUi(); +} + + +async function clickPNG(png, maxAttempts = 20) { + //log.info(`调试-点击目标${png},重试次数${maxAttempts}`); + const pngRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync(`assets/RecognitionObject/${png}.png`)); + pngRo.Threshold = 0.9; + pngRo.InitTemplate(); + return await findAndClick(pngRo, true, maxAttempts); +} + +async function findPNG(png, maxAttempts = 20) { + //log.info(`调试-识别目标${png},重试次数${maxAttempts}`); + const pngRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync(`assets/RecognitionObject/${png}.png`)); + pngRo.Threshold = 0.9; + pngRo.InitTemplate(); + return await findAndClick(pngRo, false, maxAttempts); +} + +async function findAndClick(target, doClick = true, maxAttempts = 60) { + for (let i = 0; i < maxAttempts; i++) { + const rg = captureGameRegion(); + try { + const res = rg.find(target); + if (res.isExist()) { await sleep(checkInterval * 2 + 50); if (doClick) { res.click(); } return true; } + } finally { rg.dispose(); } + if (i < maxAttempts - 1) await sleep(checkInterval); + } + return false; +} \ No newline at end of file diff --git a/repo/js/食材加工极速版/manifest.json b/repo/js/食材加工极速版/manifest.json new file mode 100644 index 000000000..5cb874cc7 --- /dev/null +++ b/repo/js/食材加工极速版/manifest.json @@ -0,0 +1,16 @@ +{ + "manifest_version": 1, + "name": "食材加工极速版", + "version": "1.0", + "bgi_version": "0.44.8", + "description": "目前最快最稳的食材加工(原则上仅用于1080p分辨率,其他分辨率能够使用纯属巧合,出现问题后果自负", + "saved_files": [], + "authors": [ + { + "name": "mno", + "links": "https://github.com/Bedrockx" + } + ], + "settings_ui": "settings.json", + "main": "main.js" +} \ No newline at end of file diff --git a/repo/js/食材加工极速版/settings.json b/repo/js/食材加工极速版/settings.json new file mode 100644 index 000000000..3a9df2e0d --- /dev/null +++ b/repo/js/食材加工极速版/settings.json @@ -0,0 +1,23 @@ +[ + { + "name": "ingredientProcessingFood", + "type": "input-text", + "label": "食材名称\n用中文逗号,分隔" + }, + { + "name": "foodCount", + "type": "input-text", + "label": "食材数量\n数量对应上方的食材\n用中文逗号,分隔" + }, + { + "name": "checkInterval", + "type": "input-text", + "label": "食材加工中的识别间隔(毫秒),仅建议在设备反应较慢出现识别错误时适当调大", + "default": "50" + }, + { + "name": "disableRetry", + "type": "checkbox", + "label": "勾选后禁用第二轮加工重试" + } +] \ No newline at end of file