diff --git a/repo/js/AutoPickLitter/README.md b/repo/js/AutoPickLitter/README.md index 98f6c8128..ec0cbbf33 100644 --- a/repo/js/AutoPickLitter/README.md +++ b/repo/js/AutoPickLitter/README.md @@ -29,10 +29,6 @@ ## 更新 -### 版本:2.1 -1.龙蛋数目由玩家填写,暂时去掉打开背包自动记录龙蛋功能 -2.修改去纳塔悠悠集市的路线(中转一下) -3.添加糖雕添加雅珂达、哥伦比娅选项,以及后退几步,避免用户BGI开启的自动拾取误触调查点 -4.转盘提供多种选择 -5.去掉圣水中转路线,去掉快速调节时间操作 -6.历史更新记录在records文件夹内 +### 版本:2.1.2 +更换识别方式,让龙蛋数量进行准确识别 +回退为打开背包识别龙蛋 diff --git a/repo/js/AutoPickLitter/assets/backpackNumber/0.png b/repo/js/AutoPickLitter/assets/backpackNumber/0.png new file mode 100644 index 000000000..da4d07462 Binary files /dev/null and b/repo/js/AutoPickLitter/assets/backpackNumber/0.png differ diff --git a/repo/js/AutoPickLitter/assets/backpackNumber/1.png b/repo/js/AutoPickLitter/assets/backpackNumber/1.png new file mode 100644 index 000000000..4db8e14c2 Binary files /dev/null and b/repo/js/AutoPickLitter/assets/backpackNumber/1.png differ diff --git a/repo/js/AutoPickLitter/assets/backpackNumber/2.png b/repo/js/AutoPickLitter/assets/backpackNumber/2.png new file mode 100644 index 000000000..1b4ebe363 Binary files /dev/null and b/repo/js/AutoPickLitter/assets/backpackNumber/2.png differ diff --git a/repo/js/AutoPickLitter/assets/backpackNumber/3.png b/repo/js/AutoPickLitter/assets/backpackNumber/3.png new file mode 100644 index 000000000..b37488276 Binary files /dev/null and b/repo/js/AutoPickLitter/assets/backpackNumber/3.png differ diff --git a/repo/js/AutoPickLitter/assets/backpackNumber/4.png b/repo/js/AutoPickLitter/assets/backpackNumber/4.png new file mode 100644 index 000000000..0bf9fcbce Binary files /dev/null and b/repo/js/AutoPickLitter/assets/backpackNumber/4.png differ diff --git a/repo/js/AutoPickLitter/assets/backpackNumber/5.png b/repo/js/AutoPickLitter/assets/backpackNumber/5.png new file mode 100644 index 000000000..6b2b2c92b Binary files /dev/null and b/repo/js/AutoPickLitter/assets/backpackNumber/5.png differ diff --git a/repo/js/AutoPickLitter/assets/backpackNumber/6.png b/repo/js/AutoPickLitter/assets/backpackNumber/6.png new file mode 100644 index 000000000..a9d099f55 Binary files /dev/null and b/repo/js/AutoPickLitter/assets/backpackNumber/6.png differ diff --git a/repo/js/AutoPickLitter/assets/backpackNumber/7.png b/repo/js/AutoPickLitter/assets/backpackNumber/7.png new file mode 100644 index 000000000..17770e559 Binary files /dev/null and b/repo/js/AutoPickLitter/assets/backpackNumber/7.png differ diff --git a/repo/js/AutoPickLitter/assets/backpackNumber/8.png b/repo/js/AutoPickLitter/assets/backpackNumber/8.png new file mode 100644 index 000000000..00e507db7 Binary files /dev/null and b/repo/js/AutoPickLitter/assets/backpackNumber/8.png differ diff --git a/repo/js/AutoPickLitter/assets/backpackNumber/9.png b/repo/js/AutoPickLitter/assets/backpackNumber/9.png new file mode 100644 index 000000000..d9fec1daa Binary files /dev/null and b/repo/js/AutoPickLitter/assets/backpackNumber/9.png differ diff --git a/repo/js/AutoPickLitter/assets/moraNumber/0.png b/repo/js/AutoPickLitter/assets/moraNumber/0.png new file mode 100644 index 000000000..3e08bf713 Binary files /dev/null and b/repo/js/AutoPickLitter/assets/moraNumber/0.png differ diff --git a/repo/js/AutoPickLitter/assets/moraNumber/1.png b/repo/js/AutoPickLitter/assets/moraNumber/1.png new file mode 100644 index 000000000..92f4e86c4 Binary files /dev/null and b/repo/js/AutoPickLitter/assets/moraNumber/1.png differ diff --git a/repo/js/AutoPickLitter/assets/moraNumber/2.png b/repo/js/AutoPickLitter/assets/moraNumber/2.png new file mode 100644 index 000000000..562b3bf89 Binary files /dev/null and b/repo/js/AutoPickLitter/assets/moraNumber/2.png differ diff --git a/repo/js/AutoPickLitter/assets/moraNumber/3.png b/repo/js/AutoPickLitter/assets/moraNumber/3.png new file mode 100644 index 000000000..4857790fe Binary files /dev/null and b/repo/js/AutoPickLitter/assets/moraNumber/3.png differ diff --git a/repo/js/AutoPickLitter/assets/moraNumber/4.png b/repo/js/AutoPickLitter/assets/moraNumber/4.png new file mode 100644 index 000000000..af92f713c Binary files /dev/null and b/repo/js/AutoPickLitter/assets/moraNumber/4.png differ diff --git a/repo/js/AutoPickLitter/assets/moraNumber/5.png b/repo/js/AutoPickLitter/assets/moraNumber/5.png new file mode 100644 index 000000000..ca565e88d Binary files /dev/null and b/repo/js/AutoPickLitter/assets/moraNumber/5.png differ diff --git a/repo/js/AutoPickLitter/assets/moraNumber/6.png b/repo/js/AutoPickLitter/assets/moraNumber/6.png new file mode 100644 index 000000000..1e2dd27ff Binary files /dev/null and b/repo/js/AutoPickLitter/assets/moraNumber/6.png differ diff --git a/repo/js/AutoPickLitter/assets/moraNumber/7.png b/repo/js/AutoPickLitter/assets/moraNumber/7.png new file mode 100644 index 000000000..de222721b Binary files /dev/null and b/repo/js/AutoPickLitter/assets/moraNumber/7.png differ diff --git a/repo/js/AutoPickLitter/assets/moraNumber/8.png b/repo/js/AutoPickLitter/assets/moraNumber/8.png new file mode 100644 index 000000000..aa4608259 Binary files /dev/null and b/repo/js/AutoPickLitter/assets/moraNumber/8.png differ diff --git a/repo/js/AutoPickLitter/assets/moraNumber/9.png b/repo/js/AutoPickLitter/assets/moraNumber/9.png new file mode 100644 index 000000000..8a4cac4d7 Binary files /dev/null and b/repo/js/AutoPickLitter/assets/moraNumber/9.png differ diff --git a/repo/js/AutoPickLitter/main.js b/repo/js/AutoPickLitter/main.js index af18d27eb..d5183d71f 100644 --- a/repo/js/AutoPickLitter/main.js +++ b/repo/js/AutoPickLitter/main.js @@ -6,12 +6,12 @@ let recordsNum = 0; // 写入内容次数 let sticksTime = false; // 判定是否可以上香 //六龙蛋位置 const coordinates = [ - [565, 150], - [568, 723], - [1088, 161], - [874, 335], - [468, 574], - [1339, 358] + [565, 150], // 山 + [568, 723], // 飞 + [1088, 161], // 圣 + [874, 335], // 太 + [468, 574], // 献 + [1339, 358] // 菲 ]; // 通用方法区域 @@ -414,7 +414,8 @@ async function chcekDragonEggs() { await keyPress("B"); await checkExpire(); await sleep(1500); - await click(1250,50); + await click(1250,50); + await sleep(50); let DragonEggs = [0, 0, 0, 0, 0, 0]; let judgeEgg = 0; // 判定是不是只有一页 @@ -423,16 +424,18 @@ async function chcekDragonEggs() { for (let index = 0; index < 6; index++) { let DragonEgg = await findImgIcon(`assets/RecognitionObject/DragonEgg${index}.png`, { min: 99, max: 1295 }, { min: 104, max: 967 }, true, 0.95); if (DragonEgg.success) { - let ocrEggNum = await performOcr("", - { min: DragonEgg.coordinates[0]-46, max: DragonEgg.coordinates[0]+34 }, { min: DragonEgg.coordinates[1]+56, max: DragonEgg.coordinates[1]+83 }, true); - // log.info(`第一次识别到的数字:${ocrEggNum.text}`); - if (ocrEggNum.text == "") { - await sleep(700); - ocrEggNum = await performOcr("", - { min: DragonEgg.coordinates[0]-46, max: DragonEgg.coordinates[0]+34 }, { min: DragonEgg.coordinates[1]+56, max: DragonEgg.coordinates[1]+83 }, true); - // log.info(`第二次识别到的数字:${ocrEggNum.text}`); - }; - DragonEggs[index] = Number(ocrEggNum.text); + // let ocrEggNum = await performOcr("", + // { min: DragonEgg.coordinates[0]-46, max: DragonEgg.coordinates[0]+34 }, { min: DragonEgg.coordinates[1]+56, max: DragonEgg.coordinates[1]+83 }, true); + // // log.info(`第一次识别到的数字:${ocrEggNum.text}`); + // if (ocrEggNum.text == "") { + // await sleep(700); + // ocrEggNum = await performOcr("", + // { min: DragonEgg.coordinates[0]-46, max: DragonEgg.coordinates[0]+34 }, { min: DragonEgg.coordinates[1]+56, max: DragonEgg.coordinates[1]+83 }, true); + // // log.info(`第二次识别到的数字:${ocrEggNum.text}`); + // }; + let eggNum = await numberTemplateMatch('assets/backpackNumber', DragonEgg.coordinates[0]-46, DragonEgg.coordinates[1]+56, 80, 27); + log.info(`识别到的数字:${eggNum}`); + DragonEggs[index] = Number(eggNum); }else{ DragonEggs[index] = 0; }; @@ -443,19 +446,11 @@ async function chcekDragonEggs() { for (let index = 0; index < 6; index++) { let DragonEgg = await findImgIcon(`assets/RecognitionObject/DragonEgg${index}.png`, { min: 99, max: 1295 }, { min: 104, max: 967 }, true, 0.95); if (DragonEgg.success) { - let ocrEggNum = await performOcr("", - { min: DragonEgg.coordinates[0]-46, max: DragonEgg.coordinates[0]+34 }, { min: DragonEgg.coordinates[1]+56, max: DragonEgg.coordinates[1]+83 }, true); - // log.info(`第一次识别到的数字:${ocrEggNum.text}`); - if (ocrEggNum.text == "") { - await sleep(700); - ocrEggNum = await performOcr("", - { min: DragonEgg.coordinates[0]-46, max: DragonEgg.coordinates[0]+34 }, { min: DragonEgg.coordinates[1]+56, max: DragonEgg.coordinates[1]+83 }, true); - // log.info(`第二次识别到的数字:${ocrEggNum.text}`); + let eggNum = await numberTemplateMatch('assets/backpackNumber', DragonEgg.coordinates[0]-46, DragonEgg.coordinates[1]+56, 80, 27); + if (eggNum == "") { + eggNum = 1; }; - if (ocrEggNum.text == "") { - ocrEggNum.text = 1; - }; - DragonEggs[index] = ocrEggNum.text; + DragonEggs[index] = eggNum; }else{ DragonEggs[index] = 0; }; @@ -510,10 +505,112 @@ async function checkExpire() { let ocrExpire = await performOcr("",{ min: 870, max: 1040 }, { min: 280, max: 320 }, true); if (ocrExpire.text == "物品过期") { log.info(`处理中=========`); - await click(980, 750); + await click(980, 750); + await sleep(50); }; }; +// 多文本识别数字 +/** + * 在指定区域内,用 0-9 的 PNG 模板做「多阈值 + 非极大抑制」数字识别, + * 最终把检测到的数字按左右顺序拼成一个整数返回。 + * + * @param {string} numberPngFilePath - 存放 0.png ~ 9.png 的文件夹路径(不含文件名) + * @param {number} x - 待识别区域的左上角 x 坐标,默认 0 + * @param {number} y - 待识别区域的左上角 y 坐标,默认 0 + * @param {number} w - 待识别区域的宽度,默认 1920 + * @param {number} h - 待识别区域的高度,默认 1080 + * @param {number} maxThreshold - 模板匹配起始阈值,默认 0.95(最高可信度) + * @param {number} minThreshold - 模板匹配最低阈值,默认 0.8(最低可信度) + * @param {number} splitCount - 在 maxThreshold 与 minThreshold 之间做几次等间隔阈值递减,默认 3 + * @param {number} maxOverlap - 非极大抑制时允许的最大重叠像素,默认 2;只要 x 或 y 方向重叠大于该值即视为重复框 + * + * @returns {number} 识别出的整数;若没有任何有效数字框则返回 -1 + * + * @example + * const mora = await numberTemplateMatch('摩拉数字', 860, 70, 200, 40); + * if (mora >= 0) console.log(`当前摩拉:${mora}`); + */ +async function numberTemplateMatch( + numberPngFilePath, + x = 0, y = 0, w = 1920, h = 1080, + maxThreshold = 0.95, + minThreshold = 0.8, + splitCount = 3, + maxOverlap = 2 +) { + let ros = []; + for (let i = 0; i <= 9; i++) { + ros[i] = RecognitionObject.TemplateMatch( + file.ReadImageMatSync(`${numberPngFilePath}/${i}.png`), x, y, w, h); + }; + + function setThreshold(roArr, newThreshold) { + for (let i = 0; i < roArr.length; i++) { + roArr[i].Threshold = newThreshold; + roArr[i].InitTemplate(); + }; + }; + + const gameRegion = captureGameRegion(); + const allCandidates = []; + + /* 1. splitCount 次等间隔阈值递减 */ + for (let k = 0; k < splitCount; k++) { + const curThr = maxThreshold - (maxThreshold - minThreshold) * k / Math.max(splitCount - 1, 1); + setThreshold(ros, curThr); + + /* 2. 0-9 每个模板跑一遍,所有框都收 */ + for (let digit = 0; digit <= 9; digit++) { + const res = gameRegion.findMulti(ros[digit]); + if (res.count === 0) continue; + + for (let i = 0; i < res.count; i++) { + const box = res[i]; + allCandidates.push({ + digit: digit, + x: box.x, + y: box.y, + w: box.width, + h: box.height, + thr: curThr + }); + }; + }; + + }; + gameRegion.dispose(); + + /* 3. 无结果提前返回 -1 */ + if (allCandidates.length === 0) { + return -1; + }; + + /* 4. 非极大抑制(必须 x、y 两个方向重叠都 > maxOverlap 才视为重复) */ + const adopted = []; + for (const c of allCandidates) { + let overlap = false; + for (const a of adopted) { + const xOverlap = Math.max(0, Math.min(c.x + c.w, a.x + a.w) - Math.max(c.x, a.x)); + const yOverlap = Math.max(0, Math.min(c.y + c.h, a.y + a.h) - Math.max(c.y, a.y)); + if (xOverlap > maxOverlap && yOverlap > maxOverlap) { + overlap = true; + break; + } + } + if (!overlap) { + adopted.push(c); + //log.info(`在 [${c.x},${c.y},${c.w},${c.h}] 找到数字 ${c.digit},匹配阈值=${c.thr}`); + } + } + + /* 5. 按 x 排序,拼整数;仍无有效框时返回 -1 */ + if (adopted.length === 0) return -1; + adopted.sort((a, b) => a.x - b.x); + + return adopted.reduce((num, item) => num * 10 + item.digit, 0); +}; + // 执行区 (async function() { await fakeLog("AutoPickLitter脚本", true, true, 0); @@ -540,6 +637,7 @@ async function checkExpire() { await genshin.returnMainUi(); await pathingScript.runFile("assets/蒙德清泉镇路线.json"); await genshin.setTime(8,0); + await sleep(700); //识别对话位置,并点击 let ocrResults = await performOcr("神奇的", dialogZone.x, dialogZone.y, false); if (ocrResults.success) { @@ -547,17 +645,12 @@ async function checkExpire() { await performOcr("如何才", dialogZone.x, dialogZone.y, false); await sleep(700); let ocrOver = await performOcr("已",{ min: 1482, max: 1630 }, { min: 912, max: 957 }, false); + await sleep(700); if (ocrOver.success) { log.info("已售罄!!!"); } else { - let ocrMora = await performOcr("", { min: 1600, max: 1780 }, { min: 30, max: 60 }, true); - if (ocrMora == "") { - await sleep(700); - ocrMora = await performOcr("", { min: 1600, max: 1780 }, { min: 30, max: 60 }, true); - }; - // 处理得到的数据 - let onlyNumber = ocrMora.text.replace(/[^0-9]/g, ""); - if (BigInt(onlyNumber) >= 300) { + const mora = await numberTemplateMatch('assets/moraNumber', 1600, 30, 180, 30); + if (BigInt(mora) >= 300) { await sleep(800); await click(1636,1019); await sleep(1000); @@ -806,7 +899,7 @@ async function checkExpire() { await fakeLog("枫丹梅洛彼得堡福利餐", false, true, 0) await genshin.returnMainUi(); await pathingScript.runFile("assets/枫丹梅洛彼得堡路线.json"); - await sleep(1000); + await sleep(1500); let ocrResults = await performOcr("布兰", dialogZone.x, dialogZone.y, false); if (ocrResults.success) { await sleep(700); @@ -902,12 +995,11 @@ async function checkExpire() { if(settings.eggs){ await fakeLog("纳塔悠悠集市龙蛋", false, true, 0) // 保留打开背包识别龙蛋信息 - // let nowDragonEggsNum = record.lastDragonEggsNum; - // if (record.lastDragonEggsNum == "【山之血:0,飞澜鲨鲨:0,圣龙君临:0,太阳的轰鸣:0,献给小酒杯:0,菲耶蒂娜:0】" || settings.updateEggs) { - // nowDragonEggsNum = await chcekDragonEggs(); - // settings.updateEggs = "false"; - // }; - let nowDragonEggsNum = settings.dragonEggsNum; + let nowDragonEggsNum = record.lastDragonEggsNum; + log.info(`上次的龙蛋信息:${nowDragonEggsNum}`); + if (record.lastDragonEggsNum == "【山之血:0,飞澜鲨鲨:0,圣龙君临:0,太阳的轰鸣:0,献给小酒杯:0,菲耶蒂娜:0】" || settings.updateEggs) { + nowDragonEggsNum = await chcekDragonEggs(); + }; let nowDragonEggs = nowDragonEggsNum.match(/\d+/g).map(Number); await genshin.returnMainUi(); await pathingScript.runFile("assets/纳塔悠悠集市路线.json"); @@ -951,15 +1043,15 @@ async function checkExpire() { }else { // 平均模式 const now = new Date(); - const weekNumber = now.getDay() + const weekNumber = now.getDay(); if (nowDragonEggs.every(num => num === nowDragonEggs[0])) { // 所有元素相同时,按星期规则处理 - if (weekNumber === 0) { // 周日:随机一个元素+1 + if (weekNumber == 0) { // 周日:随机一个元素+1 figure = Math.floor(Math.random() * 6); nowDragonEggs[figure]++; } else { // 周一到周六:第n个元素 +n(1-6) - const index = weekNumber - 1; // 周一对应索引0,...,周六对应索引5 - nowDragonEggs[index]++; + figure = weekNumber - 1; // 周一对应索引0,...,周六对应索引5 + nowDragonEggs[figure]++; }; } else { // 元素不同时:给低于平均数且最小的元素+1,直到趋于平均 @@ -1239,6 +1331,7 @@ async function checkExpire() { if (ocrResults1.success) { await sleep(800); await click(1012, 765); + await sleep(50); await click(1012, 765); }; }; @@ -1291,6 +1384,7 @@ async function checkExpire() { if (ocrResults1.success) { await sleep(800); await click(1012, 765); + await sleep(50); await click(1012, 765); }; }; diff --git a/repo/js/AutoPickLitter/manifest.json b/repo/js/AutoPickLitter/manifest.json index 2e28c8838..d909b2d12 100644 --- a/repo/js/AutoPickLitter/manifest.json +++ b/repo/js/AutoPickLitter/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 1, "name": "提瓦特杂事(收集)", - "version": "2.1", + "version": "2.1.2", "tags": [ "玄学", "收集", diff --git a/repo/js/AutoPickLitter/records/历史更新记录.txt b/repo/js/AutoPickLitter/records/历史更新记录.txt index 6d4a744e3..f1136f8f4 100644 --- a/repo/js/AutoPickLitter/records/历史更新记录.txt +++ b/repo/js/AutoPickLitter/records/历史更新记录.txt @@ -1,3 +1,14 @@ +### 版本:2.1.1 +修复龙蛋平均模式 + +### 版本:2.1 +1.龙蛋数目由玩家填写,暂时去掉打开背包自动记录龙蛋功能 +2.修改去纳塔悠悠集市的路线(中转一下) +3.添加糖雕添加雅珂达、哥伦比娅选项,以及后退几步,避免用户BGI开启的自动拾取误触调查点 +4.转盘提供多种选择 +5.去掉圣水中转路线,去掉快速调节时间操作 +6.历史更新记录在records文件夹内 + ### 版本:2.0.4 1.修改多处龙蛋对应位置 2.固定缩放 diff --git a/repo/js/AutoPickLitter/records/默认账户.txt b/repo/js/AutoPickLitter/records/默认账户.txt index 7054586b9..1352daeaf 100644 --- a/repo/js/AutoPickLitter/records/默认账户.txt +++ b/repo/js/AutoPickLitter/records/默认账户.txt @@ -1,6 +1,14 @@ -上次运行日期: 2026/01/18 +上次运行日期: 2026/02/14 上次上香时间: 2026-01-18T11:07:47.147Z -背包龙蛋数目: 【山之血:8,飞澜鲨鲨:3,圣龙君临:4,太阳的轰鸣:3,献给小酒杯:8,菲耶蒂娜:4】 +背包龙蛋数目: 【山之血:1,飞澜鲨鲨:1,圣龙君临:3,太阳的轰鸣:3,献给小酒杯:2,菲耶蒂娜:5】 +>>>>>>>>>> 2026年02月14日 +>>>>>>>>>> 2026年02月14日 +>>>>>>>>>> 2026年02月14日 +>>>>>>>>>> 2026年02月14日 +>>>>>>>>>> 2026年02月14日 +>>>>>>>>>> 2026年02月01日 +>>>>>>>>>> 2026年01月31日 +>>>>>>>>>> 2026年01月31日 >>>>>>>>>> 2026年01月18日 >>>>>>>>>> 2026年01月18日 转盘的运势: 「『旭日瞳瞳,驱散迷雾。』就是遇到困难也没关系,一定会得到帮助的意思!」 diff --git a/repo/js/AutoPickLitter/settings.json b/repo/js/AutoPickLitter/settings.json index d4bcb84a1..531e84066 100644 --- a/repo/js/AutoPickLitter/settings.json +++ b/repo/js/AutoPickLitter/settings.json @@ -55,12 +55,6 @@ ], "default": "随机模式" }, - { - "name": "dragonEggsNum", - "type": "input-text", - "label": "平均模式:自行输入自己背包各龙蛋数目\n顺序为【山-飞-圣-太-献-菲 】\n各龙蛋数目用【-】相连", - "default": "0-0-0-0-0-0" - }, { "name": "pickupDragonEgg", "type": "select", @@ -74,12 +68,12 @@ "闪闪礼蛋·飞澜鲨鲨" ] }, - // { - // "name": "updateEggs", - // "type": "checkbox", - // "label": "是否更新背包各龙蛋数目(默认否)", - // "default": "false" - // }, + { + "name": "updateEggs", + "type": "checkbox", + "label": "是否更新背包各龙蛋数目(默认否),勾选上后,下次运行前记得取消", + "default": "false" + }, { "name": "turntable", "type": "checkbox",