diff --git a/repo/js/AutoBackpackCleaner/README.md b/repo/js/AutoBackpackCleaner/README.md index 9d3a6acf1..9a2305d3b 100644 --- a/repo/js/AutoBackpackCleaner/README.md +++ b/repo/js/AutoBackpackCleaner/README.md @@ -1,3 +1,5 @@ 1. 适配1080p分辨率,其他分辨率不能使用属于正常现象,能够使用纯属巧合 -2. 目前只支持删除养成道具页的1-2星材料 -3. 注意当你的流浪者的经验(绿色经验书)数量大于你设置的起删数量时,也会删除 \ No newline at end of file +2. 目前只支持删除材料和养成道具页的0-2星材料 +3. 注意当你的流浪者的经验(绿色经验书)数量大于你设置的起删数量并小于设置的终止数量,且不等于指定的白名单数量时,也会删除 +4. 务必仔细自行关注各个物品的数量,如有误删,后果自负 +5. 将js添加至配置组中,在配置组界面右键点击js以修改自定义配置 \ No newline at end of file diff --git a/repo/js/AutoBackpackCleaner/assets/RecognitionObject/0星.png b/repo/js/AutoBackpackCleaner/assets/RecognitionObject/0星.png new file mode 100644 index 000000000..19f4498bf Binary files /dev/null and b/repo/js/AutoBackpackCleaner/assets/RecognitionObject/0星.png differ diff --git a/repo/js/AutoBackpackCleaner/assets/RecognitionObject/1星.png b/repo/js/AutoBackpackCleaner/assets/RecognitionObject/1星.png new file mode 100644 index 000000000..d733c4fde Binary files /dev/null and b/repo/js/AutoBackpackCleaner/assets/RecognitionObject/1星.png differ diff --git a/repo/js/AutoBackpackCleaner/assets/RecognitionObject/2星.png b/repo/js/AutoBackpackCleaner/assets/RecognitionObject/2星.png new file mode 100644 index 000000000..928ff0bb3 Binary files /dev/null and b/repo/js/AutoBackpackCleaner/assets/RecognitionObject/2星.png differ diff --git a/repo/js/AutoBackpackCleaner/assets/RecognitionObject/一星.png b/repo/js/AutoBackpackCleaner/assets/RecognitionObject/一星.png deleted file mode 100644 index 9d9707d02..000000000 Binary files a/repo/js/AutoBackpackCleaner/assets/RecognitionObject/一星.png and /dev/null differ diff --git a/repo/js/AutoBackpackCleaner/assets/RecognitionObject/二星.png b/repo/js/AutoBackpackCleaner/assets/RecognitionObject/二星.png deleted file mode 100644 index c1336d688..000000000 Binary files a/repo/js/AutoBackpackCleaner/assets/RecognitionObject/二星.png and /dev/null differ diff --git a/repo/js/AutoBackpackCleaner/assets/RecognitionObject/背包界面/材料1.png b/repo/js/AutoBackpackCleaner/assets/RecognitionObject/背包界面/材料1.png new file mode 100644 index 000000000..05aa05be9 Binary files /dev/null and b/repo/js/AutoBackpackCleaner/assets/RecognitionObject/背包界面/材料1.png differ diff --git a/repo/js/AutoBackpackCleaner/assets/RecognitionObject/背包界面/材料2.png b/repo/js/AutoBackpackCleaner/assets/RecognitionObject/背包界面/材料2.png new file mode 100644 index 000000000..83b8064ff Binary files /dev/null and b/repo/js/AutoBackpackCleaner/assets/RecognitionObject/背包界面/材料2.png differ diff --git a/repo/js/AutoBackpackCleaner/main.js b/repo/js/AutoBackpackCleaner/main.js index 0ec0577b2..63eb50ad4 100644 --- a/repo/js/AutoBackpackCleaner/main.js +++ b/repo/js/AutoBackpackCleaner/main.js @@ -1,11 +1,14 @@ const bottomRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync("assets/RecognitionObject/到底了.png"), 1282, 934, 1296 - 1282, 945 - 934); bottomRo.Threshold = 0.9; bottomRo.InitTemplate(); -const star1Ro = RecognitionObject.TemplateMatch(file.ReadImageMatSync("assets/RecognitionObject/一星.png"), 107, 214, 1169, 706); -star1Ro.Threshold = 0.9; +const star0Ro = RecognitionObject.TemplateMatch(file.ReadImageMatSync("assets/RecognitionObject/0星.png"), 107, 214, 1169, 706); +star0Ro.Threshold = 0.93; +star0Ro.InitTemplate(); +const star1Ro = RecognitionObject.TemplateMatch(file.ReadImageMatSync("assets/RecognitionObject/1星.png"), 107, 214, 1169, 706); +star1Ro.Threshold = 0.85; star1Ro.InitTemplate(); -const star2Ro = RecognitionObject.TemplateMatch(file.ReadImageMatSync("assets/RecognitionObject/二星.png"), 107, 214, 1169, 706); -star2Ro.Threshold = 0.9; +const star2Ro = RecognitionObject.TemplateMatch(file.ReadImageMatSync("assets/RecognitionObject/2星.png"), 107, 214, 1169, 706); +star2Ro.Threshold = 0.85; star2Ro.InitTemplate(); const delete1Ro = RecognitionObject.TemplateMatch(file.ReadImageMatSync("assets/RecognitionObject/摧毁图标1.png"), 31, 969, 93, 101); delete1Ro.Threshold = 0.9; @@ -29,102 +32,140 @@ let scrollScale = Number(settings.scrollScale) || 10; (async function () { //进入养成道具界面 + if (!settings.delayScale) { + log.error("延迟系数异常,你从来没打开过自定义配置"); + log.error("去阅读README后再使用"); + return; + } + log.warn("务必仔细自行关注各个物品的数量,如有误删,后果自负"); await genshin.returnMainUi(); + log.warn("务必仔细自行关注各个物品的数量,如有误删,后果自负"); await genshin.tpToStatueOfTheSeven(); + log.warn("务必仔细自行关注各个物品的数量,如有误删,后果自负"); await genshin.returnMainUi(); keyPress("B"); - let type = "养成道具"; + let types = Array.from(settings.executingTypes); const targetNumber = Number(settings.targetNumber) || 9000; const startNumber = Number(settings.startNumber) || 9900; + const endNumber = Number(settings.endNumber) || 9999; + const whiteNumbers = settings.whiteNumbers || ""; + + // 按中文逗号分隔,去除空项 + const numberArray = whiteNumbers + .split(',') + .map(s => s.trim()) + .filter(s => s !== ''); + + const validWhiteNumbers = []; + + // 校验每一项是否为有效数字 + for (const item of numberArray) { + const num = Number(item); + + // 校验:必须是有效数字(不是NaN,不是Infinity) + if (!Number.isFinite(num)) { + log.error(`${item} 不是有效数字`); + throw new Error('存在非法数字格式'); + } + + validWhiteNumbers.push(num); + } + + // 此时 validWhiteNumbers 存储的是数字类型数组,如 [1, 2, 3] + log.info(`白名单数字列表:${validWhiteNumbers.join(', ')}`); + if (targetNumber >= startNumber) { log.error("目标数量必须小于起删数量"); return; } - if (await findAndClick([`assets/RecognitionObject/背包界面/${type}1.png`, `assets/RecognitionObject/背包界面/${type}2.png`])) { - log.info(`成功进入${type}界面,开始执行`); - } else { - await genshin.returnMainUi(); - keyPress("B"); + for (let type of types) { + try { await sleep(1) } catch (e) { break; } if (await findAndClick([`assets/RecognitionObject/背包界面/${type}1.png`, `assets/RecognitionObject/背包界面/${type}2.png`])) { log.info(`成功进入${type}界面,开始执行`); } else { - log.info(`进入${type}界面失败`); - return; - } - } - let scrolls = 0 - while (scrolls < 200) { - try { await sleep(1) } catch (e) { break; } - if (await findAndClick(delete2Ro, false, 100, 16)) { - await findAndClick("assets/RecognitionObject/返回.png"); - await sleep(delay2); - } - let findFullRes = null; - let time4 = new Date(); - const gameRegion = captureGameRegion(); - const allRes1 = gameRegion.findMulti(star2Ro); - - let time5 = new Date(); - log.info(`调试-找出所有2星用时${time5 - time4}`); - for (let i = 0; i < allRes1.count; i++) { - const res = allRes1[i]; - const num = await numberTemplateMatch("assets/背包物品数字", res.x + 34, res.y + 16, 59, 30); - if (num >= startNumber) { - findFullRes = { x: res.x, y: res.y }; - break; + await genshin.returnMainUi(); + keyPress("B"); + if (await findAndClick([`assets/RecognitionObject/背包界面/${type}1.png`, `assets/RecognitionObject/背包界面/${type}2.png`])) { + log.info(`成功进入${type}界面,开始执行`); + } else { + log.info(`进入${type}界面失败`); + return; } } - let time6 = new Date(); - log.info(`调试-依次核对数量${time6 - time5}`); - if (!findFullRes) { - let time1 = new Date(); - const allRes2 = gameRegion.findMulti(star1Ro); - let time2 = new Date(); - log.info(`调试-找出所有1星用时${time2 - time1}`); - for (let i = 0; i < allRes2.count; i++) { - const res = allRes2[i]; - const num = await numberTemplateMatch("assets/背包物品数字", res.x + 34, res.y + 16, 59, 30); - if (num >= startNumber) { + await sleep(500); + let scrolls = 0 + while (scrolls < 200) { + try { await sleep(1) } catch (e) { break; } + if (await findAndClick(delete2Ro, false, 100, 16)) { + await findAndClick("assets/RecognitionObject/返回.png"); + await sleep(delay2); + } + let findFullRes = null; + const gameRegion = captureGameRegion(); + const allRes1 = gameRegion.findMulti(star2Ro); + for (let i = 0; i < allRes1.count; i++) { + const res = allRes1[i]; + const num = await numberTemplateMatch("assets/背包物品数字", res.x + 20, res.y + 14, 80, 30); + if (num >= startNumber && num <= endNumber && !validWhiteNumbers.includes(num)) { findFullRes = { x: res.x, y: res.y }; break; } } - let time3 = new Date(); - log.info(`调试-依次核对数量${time3 - time2}`); - } - gameRegion.dispose(); - if (findFullRes) { - //二次确认 - let fullNum = await numberTemplateMatch("assets/背包物品数字", findFullRes.x + 34, findFullRes.y + 16, 59, 30); - log.info(`找到一个爆仓材料,位置(${findFullRes.x},${findFullRes.y}),数量 ${fullNum} 个`); - await findAndClick(delete1Ro, true, 200, 16); - await sleep(delay2); - click(findFullRes.x + 20, findFullRes.y - 60); - await sleep(delay2); - if (!await deleteToTargetNumber(fullNum - targetNumber)) { + if (!findFullRes) { + const allRes2 = gameRegion.findMulti(star1Ro); + for (let i = 0; i < allRes2.count; i++) { + const res = allRes2[i]; + const num = await numberTemplateMatch("assets/背包物品数字", res.x + 20, res.y + 14, 80, 30); + if (num >= startNumber && num <= endNumber && !validWhiteNumbers.includes(num)) { + findFullRes = { x: res.x, y: res.y }; + break; + } + } + } + if (!findFullRes) { + const allRes3 = gameRegion.findMulti(star0Ro); + for (let i = 0; i < allRes3.count; i++) { + const res = allRes3[i]; + const num = await numberTemplateMatch("assets/背包物品数字", res.x + 20, res.y + 14, 80, 30); + if (num >= startNumber && num <= endNumber && !validWhiteNumbers.includes(num)) { + findFullRes = { x: res.x, y: res.y }; + break; + } + } + } + gameRegion.dispose(); + if (findFullRes) { + let fullNum = await numberTemplateMatch("assets/背包物品数字", findFullRes.x + 20, findFullRes.y + 14, 80, 30); + log.info(`找到一个爆仓材料,位置(${findFullRes.x},${findFullRes.y}),数量 ${fullNum} 个`); + await findAndClick(delete1Ro, true, 200, 16); + await sleep(delay2); + click(findFullRes.x + 20, findFullRes.y - 60); + await sleep(delay2); + if (!await deleteToTargetNumber(fullNum - targetNumber)) { + continue; + } + await sleep(delay2); + await findAndClick(delete2Ro); + await sleep(delay2); + await findAndClick(delete3Ro); + itemCount++; + itemDeleteCount += fullNum - targetNumber; continue; } - await sleep(delay2); - await findAndClick(delete2Ro); - await sleep(delay2); - await findAndClick(delete3Ro); - itemCount++; - itemDeleteCount += fullNum - targetNumber; - continue; - } - scrolls++; - let bottomres = await findAndClick(bottomRo, false, 2, 3, 1); - if (bottomres) { + scrolls++; + let bottomres = await findAndClick(bottomRo, false, 2, 3, 1); + if (bottomres) { + moveMouseTo(139, 910); + await scrollDown(3); + bottomres = await findAndClick(bottomRo, false, 2, 3, 1); + if (bottomres) { + log.info(`到底了,${type}类型处理完毕`); + break; + } + } moveMouseTo(139, 910); await scrollDown(3); - bottomres = await findAndClick(bottomRo, false, 2, 3, 1); - if (bottomres) { - log.info(`到底了,${type}类型处理完毕`); - break; - } } - moveMouseTo(139, 910); - await scrollDown(3); } log.info(`删除了${itemCount}种爆仓材料共${itemDeleteCount}个`); })(); @@ -205,6 +246,7 @@ async function findAndClick(target, async function scrollDown(lines = 1) { lines = lines * scrollScale; for (let i = 0; i < lines; i++) { + try { await sleep(1) } catch (e) { break; } await keyMouseScript.runFile(`assets/滚轮下翻.json`); } await sleep(delay1); @@ -357,6 +399,7 @@ async function deleteToTargetNumber(delta) { click(342, 923); await sleep(delay1); while (true) { + try { await sleep(1) } catch (e) { break; } let res = await numberTemplateMatch("assets/摧毁物品数字", 192, 901, 116, 56); //log.info(`调试-识别结果为${res}`); if (res === -1 || Math.abs(res - lastRes) > 100) { @@ -390,6 +433,9 @@ async function deleteToTargetNumber(delta) { moveMouseTo(342, 923); leftButtonDown(); state = 1; + } else { + moveMouseTo(342, 923); + leftButtonDown(); } } else { if (state != 0) { @@ -410,6 +456,9 @@ async function deleteToTargetNumber(delta) { moveMouseTo(168, 923); leftButtonDown(); state = -1; + } else { + moveMouseTo(168, 923); + leftButtonDown(); } } else { if (state != 0) { diff --git a/repo/js/AutoBackpackCleaner/manifest.json b/repo/js/AutoBackpackCleaner/manifest.json index ccba42d24..a947416b6 100644 --- a/repo/js/AutoBackpackCleaner/manifest.json +++ b/repo/js/AutoBackpackCleaner/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 1, "name": "清理爆仓材料", - "version": "1.0", + "version": "1.1", "description": "识别达到一定数量的材料,将其删除到指定数量", "authors": [ { diff --git a/repo/js/AutoBackpackCleaner/settings.json b/repo/js/AutoBackpackCleaner/settings.json index 5f986502b..7fb6909b1 100644 --- a/repo/js/AutoBackpackCleaner/settings.json +++ b/repo/js/AutoBackpackCleaner/settings.json @@ -3,13 +3,36 @@ "name": "targetNumber", "type": "input-text", "label": "删除后的目标数量", - "default": "9000" + "default": "9900" }, { "name": "startNumber", "type": "input-text", - "label": "起删数量,大于这个数量的材料才删", - "default": "9900" + "label": "起删数量,大于等于这个数量的材料才删", + "default": "9901" + }, + { + "name": "endNumber", + "type": "input-text", + "label": "终止数量,大于这个数量的材料不删(以防把矿删了)", + "default": "9999" + }, + { + "name": "whiteNumbers", + "type": "input-text", + "label": "白名单数量,数量恰好等于该值的物品不会被删除,如有多个,使用【中文逗号】分隔\n用于保留特定物品" + }, + { + "name": "executingTypes", + "type": "multi-checkbox", + "label": "要执行的物品种类", + "default": [ + "养成道具" + ], + "options": [ + "养成道具", + "材料" + ] }, { "name": "delayScale", diff --git a/repo/js/AutoHoeingOneDragon/main.js b/repo/js/AutoHoeingOneDragon/main.js index 1dcdcb205..3dc4c714a 100644 --- a/repo/js/AutoHoeingOneDragon/main.js +++ b/repo/js/AutoHoeingOneDragon/main.js @@ -628,7 +628,7 @@ async function findBestRouteGroups(pathings, k1, k2, targetEliteNum, targetMonst pathings.sort((a, b) => { const aHigh = a.tags.includes("高收益") ? 1 : 0; const bHigh = b.tags.includes("高收益") ? 1 : 0; - return bHigh - aHigh || a.index - b.index; // 有标签的在前,同标签按原顺序 + return bHigh - aHigh || a.fileName.localeCompare(b.fileName); // 有标签的在前,同标签按文件名排序 }); break; diff --git a/repo/js/AutoHoeingOneDragon/manifest.json b/repo/js/AutoHoeingOneDragon/manifest.json index b05a50133..8609db5a7 100644 --- a/repo/js/AutoHoeingOneDragon/manifest.json +++ b/repo/js/AutoHoeingOneDragon/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 1, "name": "锄地一条龙", - "version": "2.2.7", + "version": "2.2.8", "description": "一站式解决自动化锄地,支持只拾取狗粮,请仔细阅读README.md后使用", "authors": [ {