js:锄地,批发,团购优化;新增清除爆仓材料 (#2803)
* js:锄地一条龙2.0.6 移除7103 * js:清理爆仓材料 识别达到一定数量的材料,将其删除到指定数量 * js:狗粮批发2.03 1.优化高铁模式 2.调高数字识别最低阈值 * js:锄地一条龙 优化吃药流程 * js:狗粮批发 优化背包界面流程 * js:狗粮团购 优化界面操作 增加在背包界面遮挡时重试 * 605注释修改 * Update manifest.json * js:锄地一条龙 修正深海龙蜥相关信息 * js:锄地一条龙 裁剪6985 * 使用bgi原版拾取时不启用js内的交互或拾取进程
|
Before Width: | Height: | Size: 3.9 KiB |
|
Before Width: | Height: | Size: 6.0 KiB |
|
Before Width: | Height: | Size: 9.1 KiB |
|
Before Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 4.4 KiB |
|
Before Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 6.7 KiB |
|
Before Width: | Height: | Size: 6.0 KiB |
|
Before Width: | Height: | Size: 2.9 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 259 B After Width: | Height: | Size: 446 B |
@@ -1,7 +1,9 @@
|
||||
// 初始化自定义配置并赋予默认值
|
||||
let artifactPartyName = settings.artifactPartyName || "狗粮";//狗粮队伍名称
|
||||
let combatPartyName = settings.combatPartyName;//清怪队伍名称
|
||||
let minIntervalTime = settings.minIntervalTime || 1;//最短间隔时间(分钟)
|
||||
let minIntervalTime = settings.fastMode
|
||||
? 10
|
||||
: Number(settings.minIntervalTime || 1);
|
||||
let maxWaitingTime = settings.maxWaitingTime || 0;//最大额外等待时间(分钟)
|
||||
let forceAlternate = settings.forceAlternate;//强制交替
|
||||
let onlyActivate = settings.onlyActivate;//只运行激活额外和收尾
|
||||
@@ -13,7 +15,6 @@ let accountName = settings.accountName || "默认账户";//账户名
|
||||
let TMthreshold = +settings.TMthreshold || 0.9;//拾取阈值
|
||||
|
||||
//文件路径
|
||||
const ArtifactsButtonRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync("assets/RecognitionObject/ArtifactsButton.png"));
|
||||
const DeleteButtonRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync("assets/RecognitionObject/DeleteButton.png"));
|
||||
const AutoAddButtonRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync("assets/RecognitionObject/AutoAddButton.png"));
|
||||
const ConfirmButtonRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync("assets/RecognitionObject/ConfirmButton.png"));
|
||||
@@ -28,9 +29,9 @@ const doDecompose2Ro = RecognitionObject.TemplateMatch(file.ReadImageMatSync("as
|
||||
|
||||
const outDatedRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync("assets/RecognitionObject/ConfirmButton.png"), 760, 700, 100, 100);
|
||||
|
||||
const normalPathA = "assets/ArtifactsPath/普通98点1号线";
|
||||
const normalPathB = "assets/ArtifactsPath/普通98点2号线";
|
||||
const extraPath = "assets/ArtifactsPath/额外";
|
||||
const normalPathA = settings.fastMode ? "" : "assets/ArtifactsPath/普通98点1号线";
|
||||
const normalPathB = settings.fastMode ? "" : "assets/ArtifactsPath/普通98点2号线";
|
||||
const extraPath = settings.fastMode ? "" : "assets/ArtifactsPath/额外";
|
||||
|
||||
//初始化变量
|
||||
let artifactExperienceDiff = 0;
|
||||
@@ -103,22 +104,21 @@ let gameRegion;
|
||||
}
|
||||
|
||||
moraDiff -= await mora();
|
||||
if (!settings.fastMode) {
|
||||
//执行普通路线,直到预定激活开始时间
|
||||
log.info("开始执行普通路线");
|
||||
await runNormalPath(true);
|
||||
if (state.cancel) return;
|
||||
|
||||
//执行激活路线
|
||||
log.info("开始执行激活路线");
|
||||
await runActivatePath();
|
||||
if (state.cancel) return;
|
||||
//执行普通路线,直到预定激活开始时间
|
||||
log.info("开始执行普通路线");
|
||||
await runNormalPath(true);
|
||||
if (state.cancel) return;
|
||||
|
||||
//执行剩余普通路线
|
||||
log.info("开始执行剩余普通路线");
|
||||
await runNormalPath(false);
|
||||
if (state.cancel) return;
|
||||
}
|
||||
//执行激活路线
|
||||
log.info("开始执行激活路线");
|
||||
await runActivatePath();
|
||||
if (state.cancel) return;
|
||||
|
||||
//执行剩余普通路线
|
||||
log.info("开始执行剩余普通路线");
|
||||
await runNormalPath(false);
|
||||
if (state.cancel) return;
|
||||
|
||||
if (!onlyActivate || state.runningEndingAndExtraRoute != "收尾额外A") {
|
||||
//执行收尾和额外路线
|
||||
@@ -386,12 +386,12 @@ async function processArtifacts(times = 1) {
|
||||
|
||||
async function decomposeArtifacts() {
|
||||
keyPress("B");
|
||||
if (await findAndClick(outDatedRo, 5)) {
|
||||
if (await findAndClick(outDatedRo, true, 1500)) {
|
||||
log.info("检测到过期物品弹窗,处理");
|
||||
await sleep(1000);
|
||||
}
|
||||
await sleep(1000);
|
||||
await click(670, 45);
|
||||
let type = "圣遗物";
|
||||
await findAndClick([`assets/RecognitionObject/背包界面/${type}1.png`, `assets/RecognitionObject/背包界面/${type}2.png`])
|
||||
await sleep(500);
|
||||
if (!await findAndClick(decomposeRo)) {
|
||||
await genshin.returnMainUi();
|
||||
@@ -538,8 +538,8 @@ async function processArtifacts(times = 1) {
|
||||
log.info("检测到过期物品弹窗,处理");
|
||||
await sleep(1000);
|
||||
}
|
||||
await sleep(500);
|
||||
await findAndClick(ArtifactsButtonRo, 5)
|
||||
let type = "圣遗物";
|
||||
await findAndClick([`assets/RecognitionObject/背包界面/${type}1.png`, `assets/RecognitionObject/背包界面/${type}2.png`])
|
||||
try {
|
||||
for (let i = 0; i < times; i++) {
|
||||
// 点击摧毁
|
||||
@@ -603,27 +603,8 @@ async function mora() {
|
||||
log.info("开始尝试识别摩拉");
|
||||
keyPress("B");
|
||||
await sleep(1500);
|
||||
//切换到任务或养成道具
|
||||
let startTime = Date.now();
|
||||
while (Date.now() - startTime < 5000) {
|
||||
// 尝试识别“任务”图标
|
||||
const renwuRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync("assets/RecognitionObject/renwu.png"));
|
||||
let res = await findAndClick(renwuRo);
|
||||
if (res) {
|
||||
recognized = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// 尝试识别“养成道具”文字
|
||||
const yangchengdaojuRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync("assets/RecognitionObject/yangchengdaoju.png"));
|
||||
res = await findAndClick(yangchengdaojuRo);
|
||||
if (res) {
|
||||
recognized = true;
|
||||
break;
|
||||
}
|
||||
|
||||
await sleep(500); // 短暂延迟,避免过快循环
|
||||
}
|
||||
let type = "养成道具";
|
||||
await findAndClick([`assets/RecognitionObject/背包界面/${type}1.png`, `assets/RecognitionObject/背包界面/${type}2.png`])
|
||||
|
||||
let moraRes = 0;
|
||||
await sleep(1000);
|
||||
@@ -646,7 +627,7 @@ async function mora() {
|
||||
gameRegion.dispose();
|
||||
}
|
||||
|
||||
moraRes = await numberTemplateMatch("assets/背包摩拉数字", moraX, moraY, 300, 40);
|
||||
moraRes = await numberTemplateMatch("assets/背包摩拉数字", moraX, moraY, 300, 40, 0.95, 0.85, 10);
|
||||
|
||||
if (moraRes >= 0) {
|
||||
log.info(`成功识别到摩拉数值: ${moraRes}`);
|
||||
@@ -791,7 +772,6 @@ async function runNormalPath(doStop) {
|
||||
state.activatePickUp = true;
|
||||
await runPaths(normalExecutePath, artifactPartyName, doStop, "white");
|
||||
state.activatePickUp = false;
|
||||
|
||||
}
|
||||
|
||||
async function runActivatePath() {
|
||||
@@ -841,18 +821,20 @@ async function runActivatePath() {
|
||||
const extraActivatePath = extraPath + "/激活";
|
||||
const extraCombatPath = extraPath + "/清怪";
|
||||
const extraPreparePath = extraPath + "/准备";
|
||||
if (!forceAlternate && state.runningEndingAndExtraRoute === "收尾额外A") {
|
||||
await runPaths(endingActivatePath, "", false);
|
||||
}
|
||||
await runPaths(extraActivatePath, "", false);
|
||||
if (!settings.fastMode) {
|
||||
if (!forceAlternate && state.runningEndingAndExtraRoute === "收尾额外A") {
|
||||
await runPaths(endingActivatePath, "", false);
|
||||
}
|
||||
await runPaths(extraActivatePath, "", false);
|
||||
|
||||
await runPaths(endingPreparePath, "", false);
|
||||
await runPaths(extraPreparePath, "", false);
|
||||
await runPaths(endingPreparePath, "", false);
|
||||
await runPaths(extraPreparePath, "", false);
|
||||
|
||||
if (combatPartyName) {
|
||||
log.info("填写了清怪队伍,执行清怪路线");
|
||||
await runPaths(extraCombatPath, combatPartyName, false, "black");
|
||||
await runPaths(endingCombatPath, combatPartyName, false, "black");
|
||||
if (combatPartyName) {
|
||||
log.info("填写了清怪队伍,执行清怪路线");
|
||||
await runPaths(extraCombatPath, combatPartyName, false, "black");
|
||||
await runPaths(endingCombatPath, combatPartyName, false, "black");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1176,8 +1158,8 @@ async function runPath(fullPath, targetItemPath = null) {
|
||||
if (errorCheckCount > 50) {
|
||||
errorCheckCount = 0;
|
||||
//log.info("尝试识别并点击复苏按钮");
|
||||
if (await findAndClick(revivalRo1, 2)) {
|
||||
//log.info("识别到复苏按钮,点击复苏");
|
||||
if (await findAndClick(revivalRo1, true, 2, 3)) {
|
||||
log.info("识别到复苏按钮,点击复苏");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1435,25 +1417,70 @@ async function numberTemplateMatch(
|
||||
return adopted.reduce((num, item) => num * 10 + item.digit, 0);
|
||||
}
|
||||
|
||||
async function findAndClick(target, maxAttempts = 20) {
|
||||
for (let attempts = 0; attempts < maxAttempts; attempts++) {
|
||||
const gameRegion = captureGameRegion();
|
||||
try {
|
||||
const result = gameRegion.find(target);
|
||||
if (result.isExist) {
|
||||
await sleep(50);
|
||||
result.click();
|
||||
await sleep(50);
|
||||
return true; // 成功立刻返回
|
||||
/**
|
||||
* 通用找图/找RO并可选点击(支持单图片文件路径、单RO、图片文件路径数组、RO数组)
|
||||
* @param {string|string[]|RecognitionObject|RecognitionObject[]} target
|
||||
* @param {boolean} [doClick=true] 是否点击
|
||||
* @param {number} [timeout=3000] 识别时间上限(ms)
|
||||
* @param {number} [interval=50] 识别间隔(ms)
|
||||
* @param {number} [retType=0] 0-返回布尔;1-返回 Region 结果
|
||||
* @param {number} [preClickDelay=50] 点击前等待
|
||||
* @param {number} [postClickDelay=50] 点击后等待
|
||||
* @returns {boolean|Region} 根据 retType 返回是否成功或最终 Region
|
||||
*/
|
||||
async function findAndClick(target,
|
||||
doClick = true,
|
||||
timeout = 3000,
|
||||
interval = 50,
|
||||
retType = 0,
|
||||
preClickDelay = 50,
|
||||
postClickDelay = 50) {
|
||||
try {
|
||||
// 1. 统一转成 RecognitionObject 数组
|
||||
let ros = [];
|
||||
if (Array.isArray(target)) {
|
||||
ros = target.map(t =>
|
||||
(typeof t === 'string')
|
||||
? RecognitionObject.TemplateMatch(file.ReadImageMatSync(t))
|
||||
: t
|
||||
);
|
||||
} else {
|
||||
ros = [(typeof target === 'string')
|
||||
? RecognitionObject.TemplateMatch(file.ReadImageMatSync(target))
|
||||
: target];
|
||||
}
|
||||
|
||||
const start = Date.now();
|
||||
let found = null;
|
||||
|
||||
while (Date.now() - start <= timeout) {
|
||||
const gameRegion = captureGameRegion();
|
||||
try {
|
||||
// 依次尝试每一个 ro
|
||||
for (const ro of ros) {
|
||||
const res = gameRegion.find(ro);
|
||||
if (!res.isEmpty()) { // 找到
|
||||
found = res;
|
||||
if (doClick) {
|
||||
await sleep(preClickDelay);
|
||||
res.click();
|
||||
await sleep(postClickDelay);
|
||||
}
|
||||
break; // 成功即跳出 for
|
||||
}
|
||||
}
|
||||
if (found) break; // 成功即跳出 while
|
||||
} finally {
|
||||
gameRegion.dispose();
|
||||
}
|
||||
log.warn(`识别失败,第 ${attempts + 1} 次重试`);
|
||||
} catch (err) {
|
||||
} finally {
|
||||
gameRegion.dispose();
|
||||
}
|
||||
if (attempts < maxAttempts - 1) { // 最后一次不再 sleep
|
||||
await sleep(250);
|
||||
await sleep(interval); // 没找到时等待
|
||||
}
|
||||
|
||||
// 3. 按需返回
|
||||
return retType === 0 ? !!found : (found || null);
|
||||
|
||||
} catch (error) {
|
||||
log.error(`执行通用识图时出现错误:${error.message}`);
|
||||
return retType === 0 ? false : null;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"manifest_version": 1,
|
||||
"name": "AAA狗粮批发",
|
||||
"version": "2.0.2",
|
||||
"version": "2.0.3",
|
||||
"tags": [
|
||||
"狗粮"
|
||||
],
|
||||
|
||||
|
Before Width: | Height: | Size: 3.9 KiB |
|
Before Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 2.9 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 259 B After Width: | Height: | Size: 446 B |
@@ -228,7 +228,6 @@ async function runGroupPurchasing(runExtra) {
|
||||
groupNumBer = forceGroupNumber;
|
||||
log.info(`将自己在队伍中的编号强制指定为${groupNumBer}`);
|
||||
}
|
||||
|
||||
if (groupNumBer === 1) {
|
||||
log.info("是1p,检测当前总人数");
|
||||
const totalNumber = await findTotalNumber();
|
||||
@@ -365,8 +364,8 @@ async function runGroupPurchasing(runExtra) {
|
||||
}
|
||||
|
||||
const template = file.ReadImageMatSync(tplPath);
|
||||
const recognitionObj = RecognitionObject.TemplateMatch(template, 0, 0, 1920, 1080); // 全屏查找,可自行改区域
|
||||
if (await findAndClick(recognitionObj, 5)) await sleep(1000);
|
||||
const recognitionObj = RecognitionObject.TemplateMatch(template, 0, 0, 1920, 1080);
|
||||
if (await findAndClick(recognitionObj, false, 2000)) await sleep(1000);
|
||||
|
||||
await genshin.moveMapTo(Math.round(point.x), Math.round(point.y));
|
||||
|
||||
@@ -521,7 +520,7 @@ async function runGroupPurchasing(runExtra) {
|
||||
}
|
||||
|
||||
const folderPath = `assets/ArtifactsPath/${folderName}/执行`;
|
||||
const files = await readFolder(folderPath, true);
|
||||
const files = await readFolder(folderPath, ".json");
|
||||
|
||||
if (files.length === 0) {
|
||||
log.warn(`文件夹 ${folderPath} 下未找到任何 JSON 路线文件`);
|
||||
@@ -544,7 +543,7 @@ async function runGroupPurchasing(runExtra) {
|
||||
async function runExtraPath() {
|
||||
|
||||
const folderPath = `assets/ArtifactsPath/额外/执行`;
|
||||
const files = await readFolder(folderPath, true);
|
||||
const files = await readFolder(folderPath, ".json");
|
||||
|
||||
if (files.length === 0) {
|
||||
log.warn(`文件夹 ${folderPath} 下未找到任何 JSON 路线文件`);
|
||||
@@ -588,7 +587,7 @@ async function runGroupPurchasing(runExtra) {
|
||||
}
|
||||
|
||||
const folderPath = `assets/ArtifactsPath/${folderName}/占位`;
|
||||
const files = await readFolder(folderPath, true);
|
||||
const files = await readFolder(folderPath, ".json");
|
||||
|
||||
if (files.length === 0) {
|
||||
log.warn(`文件夹 ${folderPath} 下未找到任何 JSON 路线文件`);
|
||||
@@ -656,7 +655,7 @@ async function autoEnter(autoEnterSettings) {
|
||||
log.info(`当前模式为:${enterMode}`);
|
||||
|
||||
// 加载目标 PNG
|
||||
const targetPngs = await readFolder(targetsPath, false);
|
||||
const targetPngs = await readFolder(targetsPath, ".png");
|
||||
for (const f of targetPngs) {
|
||||
if (!f.fullPath.endsWith('.png')) continue;
|
||||
const mat = file.ReadImageMatSync(f.fullPath);
|
||||
@@ -837,27 +836,72 @@ async function switchPartyIfNeeded(partyName) {
|
||||
}
|
||||
}
|
||||
|
||||
async function findAndClick(target, maxAttempts = 20) {
|
||||
for (let attempts = 0; attempts < maxAttempts; attempts++) {
|
||||
const gameRegion = captureGameRegion();
|
||||
try {
|
||||
const result = gameRegion.find(target);
|
||||
if (result.isExist()) {
|
||||
await sleep(250);
|
||||
result.click();
|
||||
await sleep(50);
|
||||
return true; // 成功立刻返回
|
||||
/**
|
||||
* 通用找图/找RO并可选点击(支持单图片文件路径、单RO、图片文件路径数组、RO数组)
|
||||
* @param {string|string[]|RecognitionObject|RecognitionObject[]} target
|
||||
* @param {boolean} [doClick=true] 是否点击
|
||||
* @param {number} [timeout=3000] 识别时间上限(ms)
|
||||
* @param {number} [interval=50] 识别间隔(ms)
|
||||
* @param {number} [retType=0] 0-返回布尔;1-返回 Region 结果
|
||||
* @param {number} [preClickDelay=50] 点击前等待
|
||||
* @param {number} [postClickDelay=50] 点击后等待
|
||||
* @returns {boolean|Region} 根据 retType 返回是否成功或最终 Region
|
||||
*/
|
||||
async function findAndClick(target,
|
||||
doClick = true,
|
||||
timeout = 3000,
|
||||
interval = 50,
|
||||
retType = 0,
|
||||
preClickDelay = 50,
|
||||
postClickDelay = 50) {
|
||||
try {
|
||||
// 1. 统一转成 RecognitionObject 数组
|
||||
let ros = [];
|
||||
if (Array.isArray(target)) {
|
||||
ros = target.map(t =>
|
||||
(typeof t === 'string')
|
||||
? RecognitionObject.TemplateMatch(file.ReadImageMatSync(t))
|
||||
: t
|
||||
);
|
||||
} else {
|
||||
ros = [(typeof target === 'string')
|
||||
? RecognitionObject.TemplateMatch(file.ReadImageMatSync(target))
|
||||
: target];
|
||||
}
|
||||
|
||||
const start = Date.now();
|
||||
let found = null;
|
||||
|
||||
while (Date.now() - start <= timeout) {
|
||||
const gameRegion = captureGameRegion();
|
||||
try {
|
||||
// 依次尝试每一个 ro
|
||||
for (const ro of ros) {
|
||||
const res = gameRegion.find(ro);
|
||||
if (!res.isEmpty()) { // 找到
|
||||
found = res;
|
||||
if (doClick) {
|
||||
await sleep(preClickDelay);
|
||||
res.click();
|
||||
await sleep(postClickDelay);
|
||||
}
|
||||
break; // 成功即跳出 for
|
||||
}
|
||||
}
|
||||
if (found) break; // 成功即跳出 while
|
||||
} finally {
|
||||
gameRegion.dispose();
|
||||
}
|
||||
} catch (err) {
|
||||
} finally {
|
||||
gameRegion.dispose();
|
||||
}
|
||||
if (attempts < maxAttempts - 1) { // 最后一次不再 sleep
|
||||
await sleep(250);
|
||||
await sleep(interval); // 没找到时等待
|
||||
}
|
||||
|
||||
// 3. 按需返回
|
||||
return retType === 0 ? !!found : (found || null);
|
||||
|
||||
} catch (error) {
|
||||
log.error(`执行通用识图时出现错误:${error.message}`);
|
||||
return retType === 0 ? false : null;
|
||||
}
|
||||
//log.error("已达到重试次数上限,仍未找到目标");
|
||||
return false;
|
||||
}
|
||||
|
||||
//等待主界面状态
|
||||
@@ -1180,43 +1224,22 @@ async function runPath(fullPath, targetItemPath) {
|
||||
if (errorCheckCount > 50) {
|
||||
errorCheckCount = 0;
|
||||
|
||||
if (await findAndClick(revivalRo, 1)) {
|
||||
if (await findAndClick(revivalRo, true, 2, 3)) {
|
||||
log.info("识别到复苏按钮,点击复苏");
|
||||
errorCheckCount = 50;
|
||||
}
|
||||
|
||||
if (await findRo(readingRo, 1)) {
|
||||
if (await findAndClick(readingRo, false, 2, 3)) {
|
||||
log.info("识别到阅读界面,esc脱离");
|
||||
await genshin.returnMainUi();
|
||||
errorCheckCount = 50;
|
||||
}
|
||||
|
||||
if (await findRo(dialogueRo, 1)) {
|
||||
if (await findAndClick(dialogueRo, false, 2, 3)) {
|
||||
log.info("识别到对话界面,点击进行对话");
|
||||
click(960, 540);
|
||||
errorCheckCount = 50;
|
||||
}
|
||||
|
||||
async function findRo(target, maxAttempts = 20) {
|
||||
for (let attempts = 0; attempts < maxAttempts; attempts++) {
|
||||
const gameRegion = captureGameRegion();
|
||||
try {
|
||||
const result = gameRegion.find(target);
|
||||
if (result.isExist()) {
|
||||
await sleep(250);
|
||||
log.info("找到图标");
|
||||
return true;
|
||||
}
|
||||
} catch (err) {
|
||||
} finally {
|
||||
gameRegion.dispose();
|
||||
}
|
||||
if (attempts < maxAttempts - 1) { // 最后一次不再 sleep
|
||||
await sleep(250);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
})();
|
||||
@@ -1228,7 +1251,7 @@ async function runPath(fullPath, targetItemPath) {
|
||||
//加载拾取物图片
|
||||
async function loadTargetItems() {
|
||||
const targetItemPath = 'assets/targetItems'; // 固定目录
|
||||
const items = await readFolder(targetItemPath, false);
|
||||
const items = await readFolder(targetItemPath, ".png");
|
||||
// 统一预加载模板
|
||||
for (const it of items) {
|
||||
it.template = file.ReadImageMatSync(it.fullPath);
|
||||
@@ -1392,13 +1415,31 @@ async function processArtifacts() {
|
||||
|
||||
async function decomposeArtifacts() {
|
||||
keyPress("B");
|
||||
if (await findAndClick(outDatedRo, 5)) {
|
||||
if (await findAndClick(outDatedRo, true, 1500)) {
|
||||
log.info("检测到过期物品弹窗,处理");
|
||||
await sleep(1000);
|
||||
}
|
||||
await sleep(1000);
|
||||
await click(670, 45);
|
||||
let enterAttempts = 0;
|
||||
await sleep(500);
|
||||
while (enterAttempts < 10) {
|
||||
const type = "圣遗物";
|
||||
const clicked = await findAndClick([
|
||||
`assets/RecognitionObject/背包界面/${type}1.png`,
|
||||
`assets/RecognitionObject/背包界面/${type}2.png`
|
||||
]);
|
||||
if (clicked) break; // 找到并点击成功就退出循环
|
||||
await sleep(750);
|
||||
enterAttempts++;
|
||||
await genshin.returnMainUi();
|
||||
await sleep(100);
|
||||
keyPress("B");
|
||||
}
|
||||
if (enterAttempts >= 10) {
|
||||
log.warn("尝试十次未能成功进入背包界面");
|
||||
notification.Send("尝试十次未能成功进入背包界面");
|
||||
await genshin.returnMainUi();
|
||||
return 0;
|
||||
}
|
||||
if (!await findAndClick(decomposeRo)) {
|
||||
await genshin.returnMainUi();
|
||||
return 0;
|
||||
@@ -1453,28 +1494,6 @@ async function processArtifacts() {
|
||||
await genshin.returnMainUi();
|
||||
return result;
|
||||
}
|
||||
|
||||
async function findAndClick(target, maxAttempts = 20) {
|
||||
for (let attempts = 0; attempts < maxAttempts; attempts++) {
|
||||
const gameRegion = captureGameRegion();
|
||||
try {
|
||||
const result = gameRegion.find(target);
|
||||
if (result.isExist()) {
|
||||
await sleep(250);
|
||||
result.click();
|
||||
await sleep(50);
|
||||
return true; // 成功立刻返回
|
||||
}
|
||||
} catch (err) {
|
||||
} finally {
|
||||
gameRegion.dispose();
|
||||
}
|
||||
if (attempts < maxAttempts - 1) { // 最后一次不再 sleep
|
||||
await sleep(250);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
async function mora() {
|
||||
@@ -1482,31 +1501,30 @@ async function mora() {
|
||||
let result = 0;
|
||||
let tryTimes = 0;
|
||||
while (result === 0 && tryTimes < 3) {
|
||||
log.info("开始尝试识别摩拉");
|
||||
let enterAttempts = 0;
|
||||
await genshin.returnMainUi();
|
||||
await sleep(100);
|
||||
log.info("开始尝试识别摩拉");
|
||||
keyPress("B");
|
||||
await sleep(1500);
|
||||
//切换到任务或养成道具
|
||||
let startTime = Date.now();
|
||||
while (Date.now() - startTime < 5000) {
|
||||
// 尝试识别“任务”图标
|
||||
const renwuRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync("assets/RecognitionObject/renwu.png"));
|
||||
let res = await findAndClick(renwuRo);
|
||||
if (res) {
|
||||
recognized = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// 尝试识别“养成道具”文字
|
||||
const yangchengdaojuRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync("assets/RecognitionObject/yangchengdaoju.png"));
|
||||
res = await findAndClick(yangchengdaojuRo);
|
||||
if (res) {
|
||||
recognized = true;
|
||||
break;
|
||||
}
|
||||
|
||||
await sleep(500); // 短暂延迟,避免过快循环
|
||||
await sleep(500);
|
||||
while (enterAttempts < 10) {
|
||||
const type = "养成道具";
|
||||
const clicked = await findAndClick([
|
||||
`assets/RecognitionObject/背包界面/${type}1.png`,
|
||||
`assets/RecognitionObject/背包界面/${type}2.png`
|
||||
]);
|
||||
if (clicked) break; // 找到并点击成功就退出循环
|
||||
await sleep(750);
|
||||
enterAttempts++;
|
||||
await genshin.returnMainUi();
|
||||
await sleep(100);
|
||||
keyPress("B");
|
||||
}
|
||||
if (enterAttempts >= 10) {
|
||||
log.warn("尝试十次未能成功进入背包界面");
|
||||
notification.Send("尝试十次未能成功进入背包界面");
|
||||
await genshin.returnMainUi();
|
||||
return 0;
|
||||
}
|
||||
|
||||
let moraRes = 0;
|
||||
@@ -1530,7 +1548,7 @@ async function mora() {
|
||||
gameRegion.dispose();
|
||||
}
|
||||
|
||||
moraRes = await numberTemplateMatch("assets/背包摩拉数字", moraX, moraY, 300, 40);
|
||||
moraRes = await numberTemplateMatch("assets/背包摩拉数字", moraX, moraY, 300, 40, 0.95, 0.85, 10);
|
||||
|
||||
if (moraRes >= 0) {
|
||||
log.info(`成功识别到摩拉数值: ${moraRes}`);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"manifest_version": 1,
|
||||
"name": "AAA狗粮联机团购",
|
||||
"version": "1.12.0",
|
||||
"version": "1.13.0",
|
||||
"tags": [
|
||||
"狗粮"
|
||||
],
|
||||
|
||||
3
repo/js/AutoBackpackCleaner/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
1. 适配1080p分辨率,其他分辨率不能使用属于正常现象,能够使用纯属巧合
|
||||
2. 目前只支持删除养成道具页的1-2星材料
|
||||
3. 注意当你的流浪者的经验(绿色经验书)数量大于你设置的起删数量时,也会删除
|
||||
BIN
repo/js/AutoBackpackCleaner/assets/RecognitionObject/一星.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
repo/js/AutoBackpackCleaner/assets/RecognitionObject/不可摧毁.png
Normal file
|
After Width: | Height: | Size: 6.1 KiB |
BIN
repo/js/AutoBackpackCleaner/assets/RecognitionObject/二星.png
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
BIN
repo/js/AutoBackpackCleaner/assets/RecognitionObject/到底了.png
Normal file
|
After Width: | Height: | Size: 281 B |
BIN
repo/js/AutoBackpackCleaner/assets/RecognitionObject/摧毁图标1.png
Normal file
|
After Width: | Height: | Size: 836 B |
BIN
repo/js/AutoBackpackCleaner/assets/RecognitionObject/摧毁图标2.png
Normal file
|
After Width: | Height: | Size: 3.5 KiB |
BIN
repo/js/AutoBackpackCleaner/assets/RecognitionObject/摧毁图标3.png
Normal file
|
After Width: | Height: | Size: 4.2 KiB |
BIN
repo/js/AutoBackpackCleaner/assets/RecognitionObject/最大.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
BIN
repo/js/AutoBackpackCleaner/assets/RecognitionObject/返回.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
repo/js/AutoBackpackCleaner/assets/摧毁物品数字/0.png
Normal file
|
After Width: | Height: | Size: 936 B |
BIN
repo/js/AutoBackpackCleaner/assets/摧毁物品数字/1.png
Normal file
|
After Width: | Height: | Size: 382 B |
BIN
repo/js/AutoBackpackCleaner/assets/摧毁物品数字/2.png
Normal file
|
After Width: | Height: | Size: 789 B |
BIN
repo/js/AutoBackpackCleaner/assets/摧毁物品数字/3.png
Normal file
|
After Width: | Height: | Size: 869 B |
BIN
repo/js/AutoBackpackCleaner/assets/摧毁物品数字/4.png
Normal file
|
After Width: | Height: | Size: 743 B |
BIN
repo/js/AutoBackpackCleaner/assets/摧毁物品数字/5.png
Normal file
|
After Width: | Height: | Size: 829 B |
BIN
repo/js/AutoBackpackCleaner/assets/摧毁物品数字/6.png
Normal file
|
After Width: | Height: | Size: 862 B |
BIN
repo/js/AutoBackpackCleaner/assets/摧毁物品数字/7.png
Normal file
|
After Width: | Height: | Size: 665 B |
BIN
repo/js/AutoBackpackCleaner/assets/摧毁物品数字/8.png
Normal file
|
After Width: | Height: | Size: 964 B |
BIN
repo/js/AutoBackpackCleaner/assets/摧毁物品数字/9.png
Normal file
|
After Width: | Height: | Size: 728 B |
25
repo/js/AutoBackpackCleaner/assets/滚轮下翻.json
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"macroEvents": [
|
||||
{
|
||||
"type": 6,
|
||||
"mouseX": 0,
|
||||
"mouseY": -300,
|
||||
"time": 0
|
||||
},
|
||||
{
|
||||
"type": 6,
|
||||
"mouseX": 0,
|
||||
"mouseY": 0,
|
||||
"time": 1
|
||||
}
|
||||
],
|
||||
"info": {
|
||||
"name": "",
|
||||
"description": "模拟鼠标滚轮向上滚动300单位",
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"width": 1920,
|
||||
"height": 1080,
|
||||
"recordDpi": 1
|
||||
}
|
||||
}
|
||||
BIN
repo/js/AutoBackpackCleaner/assets/背包物品数字/0.png
Normal file
|
After Width: | Height: | Size: 478 B |
BIN
repo/js/AutoBackpackCleaner/assets/背包物品数字/1.png
Normal file
|
After Width: | Height: | Size: 227 B |
BIN
repo/js/AutoBackpackCleaner/assets/背包物品数字/2.png
Normal file
|
After Width: | Height: | Size: 528 B |
BIN
repo/js/AutoBackpackCleaner/assets/背包物品数字/3.png
Normal file
|
After Width: | Height: | Size: 545 B |
BIN
repo/js/AutoBackpackCleaner/assets/背包物品数字/4.png
Normal file
|
After Width: | Height: | Size: 463 B |
BIN
repo/js/AutoBackpackCleaner/assets/背包物品数字/5.png
Normal file
|
After Width: | Height: | Size: 457 B |
BIN
repo/js/AutoBackpackCleaner/assets/背包物品数字/6.png
Normal file
|
After Width: | Height: | Size: 441 B |
BIN
repo/js/AutoBackpackCleaner/assets/背包物品数字/7.png
Normal file
|
After Width: | Height: | Size: 380 B |
BIN
repo/js/AutoBackpackCleaner/assets/背包物品数字/8.png
Normal file
|
After Width: | Height: | Size: 502 B |
BIN
repo/js/AutoBackpackCleaner/assets/背包物品数字/9.png
Normal file
|
After Width: | Height: | Size: 515 B |
430
repo/js/AutoBackpackCleaner/main.js
Normal file
@@ -0,0 +1,430 @@
|
||||
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;
|
||||
star1Ro.InitTemplate();
|
||||
const star2Ro = RecognitionObject.TemplateMatch(file.ReadImageMatSync("assets/RecognitionObject/二星.png"), 107, 214, 1169, 706);
|
||||
star2Ro.Threshold = 0.9;
|
||||
star2Ro.InitTemplate();
|
||||
const delete1Ro = RecognitionObject.TemplateMatch(file.ReadImageMatSync("assets/RecognitionObject/摧毁图标1.png"), 31, 969, 93, 101);
|
||||
delete1Ro.Threshold = 0.9;
|
||||
delete1Ro.Use3Channels = true;
|
||||
delete1Ro.InitTemplate();
|
||||
const delete2Ro = RecognitionObject.TemplateMatch(file.ReadImageMatSync("assets/RecognitionObject/摧毁图标2.png"), 1568, 977, 1920 - 1568, 1080 - 977);
|
||||
delete2Ro.Threshold = 0.9;
|
||||
delete2Ro.Use3Channels = true;
|
||||
delete2Ro.InitTemplate();
|
||||
const delete3Ro = RecognitionObject.TemplateMatch(file.ReadImageMatSync("assets/RecognitionObject/摧毁图标3.png"), 959, 704, 417, 109);
|
||||
delete3Ro.Threshold = 0.9;
|
||||
delete3Ro.Use3Channels = true;
|
||||
delete3Ro.InitTemplate();
|
||||
let itemCount = 0;
|
||||
let itemDeleteCount = 0;
|
||||
|
||||
let delayScale = Number(settings.delayScale) || 1;
|
||||
let delay1 = 50 * delayScale;
|
||||
let delay2 = 150 * delayScale;
|
||||
let scrollScale = Number(settings.scrollScale) || 10;
|
||||
|
||||
(async function () {
|
||||
//进入养成道具界面
|
||||
await genshin.returnMainUi();
|
||||
await genshin.tpToStatueOfTheSeven();
|
||||
await genshin.returnMainUi();
|
||||
keyPress("B");
|
||||
let type = "养成道具";
|
||||
const targetNumber = Number(settings.targetNumber) || 9000;
|
||||
const startNumber = Number(settings.startNumber) || 9900;
|
||||
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");
|
||||
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;
|
||||
}
|
||||
}
|
||||
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) {
|
||||
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)) {
|
||||
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) {
|
||||
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}个`);
|
||||
})();
|
||||
|
||||
/**
|
||||
* 通用找图/找RO并可选点击(支持单图片文件路径、单RO、图片文件路径数组、RO数组)
|
||||
* @param {string|string[]|RecognitionObject|RecognitionObject[]} target
|
||||
* @param {boolean} [doClick=true] 是否点击
|
||||
* @param {number} [timeout=3000] 识别时间上限(ms)
|
||||
* @param {number} [interval=50] 识别间隔(ms)
|
||||
* @param {number} [retType=0] 0-返回布尔;1-返回 Region 结果
|
||||
* @param {number} [preClickDelay=50] 点击前等待
|
||||
* @param {number} [postClickDelay=50] 点击后等待
|
||||
* @returns {boolean|Region} 根据 retType 返回是否成功或最终 Region
|
||||
*/
|
||||
async function findAndClick(target,
|
||||
doClick = true,
|
||||
timeout = 3000,
|
||||
interval = delay1,
|
||||
retType = 0,
|
||||
preClickDelay = delay1,
|
||||
postClickDelay = delay1) {
|
||||
try {
|
||||
// 1. 统一转成 RecognitionObject 数组
|
||||
let ros = [];
|
||||
if (Array.isArray(target)) {
|
||||
ros = target.map(t =>
|
||||
(typeof t === 'string')
|
||||
? RecognitionObject.TemplateMatch(file.ReadImageMatSync(t))
|
||||
: t
|
||||
);
|
||||
} else {
|
||||
ros = [(typeof target === 'string')
|
||||
? RecognitionObject.TemplateMatch(file.ReadImageMatSync(target))
|
||||
: target];
|
||||
}
|
||||
|
||||
const start = Date.now();
|
||||
let found = null;
|
||||
|
||||
while (Date.now() - start <= timeout) {
|
||||
const gameRegion = captureGameRegion();
|
||||
try {
|
||||
// 依次尝试每一个 ro
|
||||
for (const ro of ros) {
|
||||
const res = gameRegion.find(ro);
|
||||
if (!res.isEmpty()) { // 找到
|
||||
found = res;
|
||||
if (doClick) {
|
||||
await sleep(preClickDelay);
|
||||
res.click();
|
||||
await sleep(postClickDelay);
|
||||
}
|
||||
break; // 成功即跳出 for
|
||||
}
|
||||
}
|
||||
if (found) break; // 成功即跳出 while
|
||||
} finally {
|
||||
gameRegion.dispose();
|
||||
}
|
||||
await sleep(interval); // 没找到时等待
|
||||
}
|
||||
|
||||
// 3. 按需返回
|
||||
return retType === 0 ? !!found : (found || null);
|
||||
|
||||
} catch (error) {
|
||||
log.error(`执行通用识图时出现错误:${error.message}`);
|
||||
return retType === 0 ? false : null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 向下滚动lines行(调用一次滚轮下翻脚本)
|
||||
* @param {number} [lines=1] 需要滚动的行数,默认 1 行
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function scrollDown(lines = 1) {
|
||||
lines = lines * scrollScale;
|
||||
for (let i = 0; i < lines; i++) {
|
||||
await keyMouseScript.runFile(`assets/滚轮下翻.json`);
|
||||
}
|
||||
await sleep(delay1);
|
||||
}
|
||||
|
||||
/**
|
||||
* 数字模板匹配
|
||||
*
|
||||
* @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 之间做几次等间隔阈值递减,默认 5
|
||||
* @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 = 4,
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
let gameRegion;
|
||||
const allCandidates = [];
|
||||
|
||||
try {
|
||||
gameRegion = captureGameRegion();
|
||||
|
||||
/* 1. splitCount 次等间隔阈值递减 */
|
||||
for (let k = 0; k < splitCount; k++) {
|
||||
const curThr = maxThreshold - (maxThreshold - minThreshold) * k / Math.max(splitCount - 1, 1);
|
||||
setThreshold(ros, curThr);
|
||||
|
||||
/* 2. 9-0 每个模板跑一遍,所有框都收 */
|
||||
for (let digit = 9; digit >= 0; digit--) {
|
||||
try {
|
||||
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
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
log.error(`识别数字 ${digit} 时出错:${e.message}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
log.error(`识别数字过程中出现错误:${error.message}`);
|
||||
} finally {
|
||||
if (gameRegion) 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将“已选摧毁数量”调节到目标值
|
||||
*
|
||||
* @param {number} delta - 还需再摧毁的件数(fullNum - targetNumber)
|
||||
* 若 ≤0 则直接返回
|
||||
*
|
||||
* 逻辑:
|
||||
* 1. 循环读取当前已选数量 res
|
||||
* 2. res === delta → 松开按键并立即返回
|
||||
* 3. res < delta → 缺多少补多少
|
||||
* 差距 >20 长按“+”按钮(342,923)快速累加
|
||||
* 差距 ≤20 单点 click 精确补齐
|
||||
* 4. res > delta → 多多少减多少
|
||||
* 差距 >20 长按“-”按钮(168,923)快速递减
|
||||
* 差距 ≤20 单点 click 精确减少
|
||||
* 5. state 变量记录当前是否正在长按(1 加 / -1 减 / 0 空闲),
|
||||
* 切换方向时先 leftButtonUp() 防止事件粘连
|
||||
*
|
||||
* @returns {Promise<boolean>} 成功调到目标值返回 true;若 delta≤0 直接返回 false
|
||||
*
|
||||
* @example
|
||||
* await deleteToTargetNumber(147); // 把已选数量调到 147
|
||||
*/
|
||||
async function deleteToTargetNumber(delta) {
|
||||
let state = 0;
|
||||
if (delta <= 0) {
|
||||
return false;
|
||||
}
|
||||
if (await findAndClick("assets/RecognitionObject/不可摧毁.png", false, 250)) {
|
||||
return false;
|
||||
}
|
||||
if (delta >= 4950) {
|
||||
await findAndClick("assets/RecognitionObject/最大.png");
|
||||
}
|
||||
let lastRes = 1;
|
||||
click(342, 923);
|
||||
await sleep(delay1);
|
||||
while (true) {
|
||||
let res = await numberTemplateMatch("assets/摧毁物品数字", 192, 901, 116, 56);
|
||||
//log.info(`调试-识别结果为${res}`);
|
||||
if (res === -1 || Math.abs(res - lastRes) > 100) {
|
||||
state = 0;
|
||||
await sleep(1000);
|
||||
leftButtonUp();
|
||||
for (let i = 0; i < 5; i++) {
|
||||
click(342, 923);
|
||||
await sleep(10);
|
||||
}
|
||||
await sleep(delay2);
|
||||
let res1 = await numberTemplateMatch("assets/摧毁物品数字", 192, 901, 116, 56);
|
||||
if (res1 === -1) {
|
||||
continue;
|
||||
} else {
|
||||
lastRes = res1;
|
||||
res = res1;
|
||||
}
|
||||
} else {
|
||||
lastRes = res;
|
||||
}
|
||||
if (res === delta) {
|
||||
leftButtonUp();
|
||||
return true;
|
||||
}
|
||||
if (res < delta) {
|
||||
if (delta - res > 20) {
|
||||
if (state != 1) {
|
||||
leftButtonUp();
|
||||
await sleep(delay1);
|
||||
moveMouseTo(342, 923);
|
||||
leftButtonDown();
|
||||
state = 1;
|
||||
}
|
||||
} else {
|
||||
if (state != 0) {
|
||||
leftButtonUp();
|
||||
await sleep(delay1);
|
||||
state = 0;
|
||||
}
|
||||
for (let i = 0; i < delta - res; i++) {
|
||||
click(342, 923);
|
||||
await sleep(10);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (res - delta > 20) {
|
||||
if (state != -1) {
|
||||
leftButtonUp();
|
||||
await sleep(delay1);
|
||||
moveMouseTo(168, 923);
|
||||
leftButtonDown();
|
||||
state = -1;
|
||||
}
|
||||
} else {
|
||||
if (state != 0) {
|
||||
leftButtonUp();
|
||||
await sleep(delay1);
|
||||
state = 0;
|
||||
}
|
||||
for (let i = 0; i < res - delta; i++) {
|
||||
click(168, 923);
|
||||
await sleep(10);
|
||||
}
|
||||
}
|
||||
}
|
||||
await sleep(delay1);
|
||||
try { await sleep(1) } catch (e) { break; }
|
||||
}
|
||||
return true;
|
||||
}
|
||||
14
repo/js/AutoBackpackCleaner/manifest.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"manifest_version": 1,
|
||||
"name": "清理爆仓材料",
|
||||
"version": "1.0",
|
||||
"description": "识别达到一定数量的材料,将其删除到指定数量",
|
||||
"authors": [
|
||||
{
|
||||
"name": "mno",
|
||||
"links": "https://github.com/Bedrockx"
|
||||
}
|
||||
],
|
||||
"settings_ui": "settings.json",
|
||||
"main": "main.js"
|
||||
}
|
||||
26
repo/js/AutoBackpackCleaner/settings.json
Normal file
@@ -0,0 +1,26 @@
|
||||
[
|
||||
{
|
||||
"name": "targetNumber",
|
||||
"type": "input-text",
|
||||
"label": "删除后的目标数量",
|
||||
"default": "9000"
|
||||
},
|
||||
{
|
||||
"name": "startNumber",
|
||||
"type": "input-text",
|
||||
"label": "起删数量,大于这个数量的材料才删",
|
||||
"default": "9900"
|
||||
},
|
||||
{
|
||||
"name": "delayScale",
|
||||
"type": "input-text",
|
||||
"label": "延迟系数,设备较差反应不过来时适当调大",
|
||||
"default": "1"
|
||||
},
|
||||
{
|
||||
"name": "scrollScale",
|
||||
"type": "input-text",
|
||||
"label": "翻页距离,调整为一次滑动约三行最佳",
|
||||
"default": "10"
|
||||
}
|
||||
]
|
||||
@@ -1491,6 +1491,12 @@
|
||||
},
|
||||
{
|
||||
"name": "深海龙蜥·原种",
|
||||
"moraRate": 1,
|
||||
"type": "精英",
|
||||
"tags": []
|
||||
},
|
||||
{
|
||||
"name": "深海龙蜥·原种_600",
|
||||
"moraRate": 3,
|
||||
"type": "精英",
|
||||
"tags": []
|
||||
|
||||
|
Before Width: | Height: | Size: 2.4 KiB |
BIN
repo/js/AutoHoeingOneDragon/assets/背包界面/食物1.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
repo/js/AutoHoeingOneDragon/assets/背包界面/食物2.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
@@ -954,9 +954,13 @@ async function runPath(fullPath, map_name, pm, pe) {
|
||||
lastEatBuff = new Date();
|
||||
await genshin.returnMainUi();
|
||||
keyPress("B");
|
||||
await findAndClick("assets/料理界面.png");
|
||||
await sleep(300);
|
||||
let type = "食物"
|
||||
await findAndClick([`assets/RecognitionObject/背包界面/${type}1.png`, `assets/RecognitionObject/背包界面/${type}2.png`]);
|
||||
await sleep(300);
|
||||
// 2. 遍历数组,逐项执行
|
||||
for (const item of res) {
|
||||
await sleep(300);
|
||||
await findAndClick(['assets/筛选1.png', 'assets/筛选2.png']);
|
||||
await findAndClick("assets/重置.png");
|
||||
await sleep(500);
|
||||
@@ -1043,7 +1047,7 @@ async function runPath(fullPath, map_name, pm, pe) {
|
||||
|
||||
/* ---------- 伴随任务 ---------- */
|
||||
const pickupTask = (async () => {
|
||||
if (pickup_Mode != "不拾取任何物品") {
|
||||
if (pickup_Mode.includes("模板匹配")) {
|
||||
await recognizeAndInteract();
|
||||
}
|
||||
})();
|
||||
@@ -1131,7 +1135,7 @@ async function runPath(fullPath, map_name, pm, pe) {
|
||||
return maxMatch / len;
|
||||
}
|
||||
|
||||
if (pickup_Mode === "模板匹配拾取,拾取狗粮和怪物材料" || pickup_Mode === "模板匹配拾取,只拾取狗粮") {
|
||||
if (pickup_Mode.includes("模板匹配")) {
|
||||
while (state.running) {
|
||||
await sleep(1500);
|
||||
if (await checkItemFull()) {
|
||||
@@ -1237,7 +1241,7 @@ async function recognizeAndInteract() {
|
||||
}
|
||||
|
||||
let foundTarget = false;
|
||||
if (pickup_Mode === "模板匹配拾取,拾取狗粮和怪物材料" || pickup_Mode === "模板匹配拾取,只拾取狗粮") {
|
||||
if (pickup_Mode.includes("模板匹配")) {
|
||||
let time1 = new Date();
|
||||
itemName = await performTemplateMatch(centerYF);
|
||||
let time2 = new Date();
|
||||
@@ -1607,7 +1611,6 @@ async function processPathingsByGroup(pathings, accountName) {
|
||||
// 更新坐标
|
||||
lastX = miniMapPosition.X;
|
||||
lastY = miniMapPosition.Y;
|
||||
//log.info(`当前位于${pathing.map_name}地图的(${miniMapPosition.X},${miniMapPosition.Y},距离上次距离${(diffX + diffY)}`);
|
||||
} catch (error) {
|
||||
log.error(`获取坐标时发生错误:${error.message}`);
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
}
|
||||
],
|
||||
"bgi_version": "0.45.0",
|
||||
"description": " 路线信息:该路线预计用时170.9秒,包含以下怪物:3只打手丘丘人、1只冲锋丘丘人、1只木盾丘丘人、2只火斧丘丘暴徒、1只雷斧丘丘暴徒、1只水丘丘萨满、1只遗迹守卫、3只遗迹歼击者、1只遗迹防卫者、1只深海龙蜥·啮冰。",
|
||||
"description": " 路线信息:该路线预计用时170.9秒,包含以下怪物:3只打手丘丘人、1只冲锋丘丘人、1只木盾丘丘人、2只火斧丘丘暴徒、1只雷斧丘丘暴徒、1只水丘丘萨满、1只遗迹守卫、3只遗迹歼击者、1只遗迹防卫者、1只深海龙蜥·原种。",
|
||||
"hash_res": "65684637",
|
||||
"enable_monster_loot_split": false,
|
||||
"last_modified_time": 1763194152729,
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
}
|
||||
],
|
||||
"bgi_version": "0.45.0",
|
||||
"description": " 路线信息:该路线预计用时131.17秒,包含以下怪物:1只丘丘人、1只打手丘丘人、1只丘丘雷兜王、3只深海龙蜥·原种。",
|
||||
"description": " 路线信息:该路线预计用时131.17秒,包含以下怪物:1只丘丘人、1只打手丘丘人、1只丘丘雷兜王、2只深海龙蜥·原种、1只深海龙蜥·原种_600。",
|
||||
"hash_res": "61562744",
|
||||
"enable_monster_loot_split": false,
|
||||
"last_modified_time": 1763453290081,
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"type": "collect",
|
||||
"author": "汐",
|
||||
"version": "1.0",
|
||||
"description": " 路线信息:该路线预计用时124.99秒,包含以下怪物:2只打手丘丘人、1只冰箭丘丘人、1只火深渊法师、3只深海龙蜥·原种。",
|
||||
"description": " 路线信息:该路线预计用时124.99秒,包含以下怪物:2只打手丘丘人、1只冰箭丘丘人、1只火深渊法师、2只深海龙蜥·原种、1只深海龙蜥·原种_600。",
|
||||
"hash_res": "43434511",
|
||||
"map_name": "Enkanomiya",
|
||||
"bgi_version": "0.45.0",
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
}
|
||||
],
|
||||
"bgi_version": "0.45.0",
|
||||
"description": " 路线信息:该路线预计用时149.06秒,包含以下怪物:3只嗜岩·兽境幼兽、2只遗迹守卫、1只遗迹重机、3只深海龙蜥·原种。",
|
||||
"description": " 路线信息:该路线预计用时149.06秒,包含以下怪物:3只嗜岩·兽境幼兽、2只遗迹守卫、1只遗迹重机、2只深海龙蜥·原种、1只深海龙蜥·原种_600。",
|
||||
"hash_res": "07204760",
|
||||
"enable_monster_loot_split": false,
|
||||
"last_modified_time": 1760122348657,
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
}
|
||||
],
|
||||
"bgi_version": "0.45.0",
|
||||
"description": " 路线信息:该路线预计用时133.19秒,包含以下怪物:1只岩史莱姆、1只丘丘雷兜王、3只深海龙蜥·原种。",
|
||||
"description": " 路线信息:该路线预计用时133.19秒,包含以下怪物:1只岩史莱姆、1只丘丘雷兜王、2只深海龙蜥·原种、1只深海龙蜥·原种_600。",
|
||||
"hash_res": "26834014",
|
||||
"enable_monster_loot_split": false,
|
||||
"last_modified_time": 1762112629546,
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
}
|
||||
],
|
||||
"bgi_version": "0.45.0",
|
||||
"description": " 路线信息:该路线预计用时282.38秒,包含以下怪物:4只丘丘人、1只打手丘丘人、3只冲锋丘丘人、1只木盾丘丘人、1只射手丘丘人、2只火斧丘丘暴徒、8只深邃拟覆叶。",
|
||||
"description": " 路线信息:该路线预计用时282.38秒,包含以下怪物:4只丘丘人、1只打手丘丘人、3只冲锋丘丘人、1只木盾丘丘人、1只射手丘丘人、2只火斧丘丘暴徒、3只深邃拟覆叶_400、5只深邃拟覆叶_200。",
|
||||
"enable_monster_loot_split": false,
|
||||
"hash_res": "15821678",
|
||||
"last_modified_time": 1769075224716,
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
}
|
||||
],
|
||||
"bgi_version": "0.45.0",
|
||||
"description": " 路线信息:该路线预计用时216.86秒,包含以下怪物:1只深邃拟覆叶_200、1只秘源机兵·寻捕械、2只幼匿叶龙、2只匿叶龙、2只绒翼龙。",
|
||||
"description": " 路线信息:该路线预计用时106.42秒,包含以下怪物:1只秘源机兵·寻捕械、2只幼匿叶龙、2只匿叶龙。",
|
||||
"enable_monster_loot_split": false,
|
||||
"last_modified_time": 1767735787236,
|
||||
"map_match_method": "",
|
||||
@@ -119,84 +119,12 @@
|
||||
},
|
||||
{
|
||||
"action": "combat_script",
|
||||
"action_params": "click(middle),keypress(T),moveby(1200,0),wait(0.5),keypress(T),moveby(1200,0),wait(0.5),keypress(T),moveby(1200,0),wait(0.5),keypress(T),moveby(1200,0),wait(0.5),keypress(T),moveby(1200,0),wait(0.5),keypress(T)",
|
||||
"action_params": "wait(1)",
|
||||
"id": 12,
|
||||
"move_mode": "dash",
|
||||
"type": "target",
|
||||
"type": "orientation",
|
||||
"x": 312.4649658203125,
|
||||
"y": 176.3822021484375
|
||||
},
|
||||
{
|
||||
"action": "",
|
||||
"action_params": "",
|
||||
"id": 13,
|
||||
"move_mode": "walk",
|
||||
"type": "path",
|
||||
"x": 299.9208984375,
|
||||
"y": 185.8914794921875
|
||||
},
|
||||
{
|
||||
"action": "",
|
||||
"action_params": "",
|
||||
"id": 14,
|
||||
"move_mode": "walk",
|
||||
"type": "path",
|
||||
"x": 280.5816650390625,
|
||||
"y": 191.3587646484375
|
||||
},
|
||||
{
|
||||
"action": "",
|
||||
"action_params": "",
|
||||
"id": 15,
|
||||
"move_mode": "walk",
|
||||
"type": "target",
|
||||
"x": 277.4586181640625,
|
||||
"y": 192.7681884765625
|
||||
},
|
||||
{
|
||||
"action": "combat_script",
|
||||
"action_params": "keydown(e),wait(1.5),keyup(e),wait(0.5),j,keypress(e)",
|
||||
"id": 16,
|
||||
"move_mode": "walk",
|
||||
"type": "orientation",
|
||||
"x": 266.3702392578125,
|
||||
"y": 196.78173828125
|
||||
},
|
||||
{
|
||||
"action": "",
|
||||
"action_params": "",
|
||||
"id": 17,
|
||||
"move_mode": "walk",
|
||||
"type": "path",
|
||||
"x": 266.18896484375,
|
||||
"y": 196.630126953125
|
||||
},
|
||||
{
|
||||
"action": "combat_script",
|
||||
"action_params": "keydown(Q),wait(1.5),keyup(Q),wait(0.1)",
|
||||
"id": 18,
|
||||
"move_mode": "dash",
|
||||
"type": "path",
|
||||
"x": 253.0037841796875,
|
||||
"y": 200.71044921875
|
||||
},
|
||||
{
|
||||
"action": "fight",
|
||||
"action_params": "",
|
||||
"id": 19,
|
||||
"move_mode": "dash",
|
||||
"type": "path",
|
||||
"x": 248.2806396484375,
|
||||
"y": 218.8236083984375
|
||||
},
|
||||
{
|
||||
"action": "combat_script",
|
||||
"action_params": "wait(1)",
|
||||
"id": 20,
|
||||
"move_mode": "dash",
|
||||
"type": "orientation",
|
||||
"x": 248.2806396484375,
|
||||
"y": 218.8236083984375
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
{
|
||||
"info": {
|
||||
"authors": [
|
||||
{
|
||||
"links": "",
|
||||
"name": "mno"
|
||||
}
|
||||
],
|
||||
"bgi_version": "0.45.0",
|
||||
"description": " 路线信息:该路线预计用时99.36秒,包含以下怪物:3只丘丘风行游侠。",
|
||||
"hash_res": "47404325",
|
||||
"enable_monster_loot_split": false,
|
||||
"last_modified_time": 1757850938960,
|
||||
"map_match_method": "",
|
||||
"map_name": "Teyvat",
|
||||
"name": "7103挪德卡莱希汐岛北2",
|
||||
"tags": [
|
||||
"挪德卡莱"
|
||||
],
|
||||
"type": "collect",
|
||||
"version": "1.0"
|
||||
},
|
||||
"positions": [
|
||||
{
|
||||
"action": "",
|
||||
"action_params": "",
|
||||
"id": 1,
|
||||
"move_mode": "walk",
|
||||
"type": "teleport",
|
||||
"x": 10789.009765625,
|
||||
"y": 2277.678466796875
|
||||
},
|
||||
{
|
||||
"action": "",
|
||||
"action_params": "",
|
||||
"id": 2,
|
||||
"move_mode": "dash",
|
||||
"type": "path",
|
||||
"x": 10751.10546875,
|
||||
"y": 2277.8349609375
|
||||
},
|
||||
{
|
||||
"action": "",
|
||||
"action_params": "",
|
||||
"id": 3,
|
||||
"move_mode": "dash",
|
||||
"type": "path",
|
||||
"x": 10754.814453125,
|
||||
"y": 2233.7265625
|
||||
},
|
||||
{
|
||||
"action": "",
|
||||
"action_params": "",
|
||||
"id": 4,
|
||||
"move_mode": "jump",
|
||||
"type": "path",
|
||||
"x": 10754.66796875,
|
||||
"y": 2223.5322265625
|
||||
},
|
||||
{
|
||||
"action": "fight",
|
||||
"action_params": "",
|
||||
"id": 5,
|
||||
"move_mode": "walk",
|
||||
"type": "path",
|
||||
"x": 10763.3896484375,
|
||||
"y": 2206.59228515625
|
||||
},
|
||||
{
|
||||
"action": "combat_script",
|
||||
"action_params": "wait(0.1)",
|
||||
"id": 6,
|
||||
"move_mode": "walk",
|
||||
"type": "path",
|
||||
"x": 10763.3896484375,
|
||||
"y": 2206.59228515625
|
||||
},
|
||||
{
|
||||
"action": "combat_script",
|
||||
"action_params": "wait(1)",
|
||||
"id": 7,
|
||||
"move_mode": "walk",
|
||||
"type": "orientation",
|
||||
"x": 10763.3896484375,
|
||||
"y": 2206.59228515625
|
||||
}
|
||||
]
|
||||
}
|
||||
|
Before Width: | Height: | Size: 259 B After Width: | Height: | Size: 446 B |
@@ -46,7 +46,7 @@ async function canCanNeed() {
|
||||
let attempts = 0;
|
||||
while (moraRes < 0 && attempts < 5) {
|
||||
attempts++;
|
||||
moraRes = await numberTemplateMatch("assets/背包摩拉数字", moraX, moraY, 300, 40, 0.95, 0.8, 5);
|
||||
moraRes = await numberTemplateMatch("assets/背包摩拉数字", moraX, moraY, 300, 40, 0.95, 0.85, 10);
|
||||
}
|
||||
if (moraRes >= 0) {
|
||||
log.info(`成功识别到摩拉数值: ${moraRes}`);
|
||||
@@ -84,7 +84,7 @@ async function canCanNeed() {
|
||||
let attempts = 0;
|
||||
while (primogemRes < 0 && attempts < 5) {
|
||||
attempts++;
|
||||
primogemRes = await numberTemplateMatch("assets/背包摩拉数字", primogemX + 28, primogemY, plusX - primogemX, 40, 0.95, 0.8, 5);
|
||||
primogemRes = await numberTemplateMatch("assets/背包摩拉数字", primogemX + 28, primogemY, plusX - primogemX, 40, 0.95, 0.85, 10);
|
||||
}
|
||||
if (primogemRes >= 0) {
|
||||
log.info(`成功识别到原石数值: ${primogemRes}`);
|
||||
@@ -203,8 +203,8 @@ async function numberTemplateMatch(
|
||||
numberPngFilePath,
|
||||
x = 0, y = 0, w = 1920, h = 1080,
|
||||
maxThreshold = 0.95,
|
||||
minThreshold = 0.8,
|
||||
splitCount = 3,
|
||||
minThreshold = 0.87,
|
||||
splitCount = 10,
|
||||
maxOverlap = 2
|
||||
) {
|
||||
let ros = [];
|
||||
@@ -300,4 +300,4 @@ async function findAndClick(target, maxAttempts = 20) {
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"manifest_version": 1,
|
||||
"name": "摩拉&原石识别",
|
||||
"version": "1.1",
|
||||
"version": "1.2",
|
||||
"tags": [],
|
||||
"description": "更准确、更低性能开销的摩拉和原石等贵重物品识别",
|
||||
"saved_files": [],
|
||||
|
||||