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内的交互或拾取进程
This commit is contained in:
mno
2026-01-28 15:49:23 +08:00
committed by GitHub
parent 4416a6cd74
commit 16a95a2465
79 changed files with 749 additions and 357 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 259 B

After

Width:  |  Height:  |  Size: 446 B

View File

@@ -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;
}

View File

@@ -1,7 +1,7 @@
{
"manifest_version": 1,
"name": "AAA狗粮批发",
"version": "2.0.2",
"version": "2.0.3",
"tags": [
"狗粮"
],

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 259 B

After

Width:  |  Height:  |  Size: 446 B

View File

@@ -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}`);

View File

@@ -1,7 +1,7 @@
{
"manifest_version": 1,
"name": "AAA狗粮联机团购",
"version": "1.12.0",
"version": "1.13.0",
"tags": [
"狗粮"
],

View File

@@ -0,0 +1,3 @@
1. 适配1080p分辨率其他分辨率不能使用属于正常现象能够使用纯属巧合
2. 目前只支持删除养成道具页的1-2星材料
3. 注意当你的流浪者的经验(绿色经验书)数量大于你设置的起删数量时,也会删除

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 836 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 936 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 382 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 789 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 869 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 743 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 829 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 862 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 665 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 964 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 728 B

View 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
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 478 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 227 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 528 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 545 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 463 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 457 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 441 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 380 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 502 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 515 B

View 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;
}

View 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"
}

View 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"
}
]

View File

@@ -1491,6 +1491,12 @@
},
{
"name": "深海龙蜥·原种",
"moraRate": 1,
"type": "精英",
"tags": []
},
{
"name": "深海龙蜥·原种_600",
"moraRate": 3,
"type": "精英",
"tags": []

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@@ -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}`);
}

View File

@@ -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,

View File

@@ -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,

View File

@@ -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",

View File

@@ -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,

View File

@@ -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,

View File

@@ -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,

View File

@@ -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
}
]
}

View File

@@ -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
}
]
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 259 B

After

Width:  |  Height:  |  Size: 446 B

View File

@@ -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;
}
}

View File

@@ -1,7 +1,7 @@
{
"manifest_version": 1,
"name": "摩拉&原石识别",
"version": "1.1",
"version": "1.2",
"tags": [],
"description": "更准确、更低性能开销的摩拉和原石等贵重物品识别",
"saved_files": [],