mirror of
https://github.com/babalae/bettergi-scripts-list.git
synced 2026-05-09 00:44:17 +08:00
js:采集cd管理2.10.0 (#2865)
* js:采集cd管理2.10.0 1.食材加工固定数量99,并将选择模式改为多选 2.适配旧日之海水下挖矿路线,优化螃蟹技能管理逻辑改为识别技能图标 3.更新了版本号 * Update main.js 修改当前进度的输出格式,优先阶段可以在当前进度直接看到剩余材料
This commit is contained in:
Binary file not shown.
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 3.1 KiB |
76
repo/js/采集cd管理/assets/学习螃蟹技能2.json
Normal file
76
repo/js/采集cd管理/assets/学习螃蟹技能2.json
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
{
|
||||||
|
"info": {
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "芝士贝果",
|
||||||
|
"links": "https://github.com/cheese-bagel"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"bgi_version": "0.54.1-alpha.3",
|
||||||
|
"description": "",
|
||||||
|
"enable_monster_loot_split": false,
|
||||||
|
"last_modified_time": 1765869417061,
|
||||||
|
"map_match_method": "",
|
||||||
|
"map_name": "SeaOfBygoneEras",
|
||||||
|
"name": "E00-卡皮托利姆旧宫(学习螃蟹技能)",
|
||||||
|
"tags": [],
|
||||||
|
"type": "collect",
|
||||||
|
"version": "1.0"
|
||||||
|
},
|
||||||
|
"positions": [
|
||||||
|
{
|
||||||
|
"action": "",
|
||||||
|
"action_params": "",
|
||||||
|
"id": 1,
|
||||||
|
"move_mode": "walk",
|
||||||
|
"type": "teleport",
|
||||||
|
"x": 3543.8477,
|
||||||
|
"y": 1380.2609
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"action": "",
|
||||||
|
"action_params": "",
|
||||||
|
"id": 2,
|
||||||
|
"move_mode": "run",
|
||||||
|
"type": "path",
|
||||||
|
"x": 3556.3594,
|
||||||
|
"y": 1374.9818
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"action": "combat_script",
|
||||||
|
"action_params": "keydown(VK_LCONTROL);wait(3);keyup(VK_LCONTROL);click(middle);wait(0.5);moveby(0,700)",
|
||||||
|
"id": 3,
|
||||||
|
"move_mode": "run",
|
||||||
|
"type": "path",
|
||||||
|
"x": 3569.1558,
|
||||||
|
"y": 1379.5138
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"action": "",
|
||||||
|
"action_params": "",
|
||||||
|
"id": 4,
|
||||||
|
"move_mode": "dash",
|
||||||
|
"type": "path",
|
||||||
|
"x": 3600.522,
|
||||||
|
"y": 1386.7323
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"action": "combat_script",
|
||||||
|
"action_params": "attack",
|
||||||
|
"id": 5,
|
||||||
|
"move_mode": "walk",
|
||||||
|
"type": "orientation",
|
||||||
|
"x": 3613.7422,
|
||||||
|
"y": 1393.2585
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"action": "combat_script",
|
||||||
|
"action_params": "attack",
|
||||||
|
"id": 6,
|
||||||
|
"move_mode": "walk",
|
||||||
|
"type": "orientation",
|
||||||
|
"x": 3614.2134,
|
||||||
|
"y": 1384.8744
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
BIN
repo/js/采集cd管理/assets/螃蟹技能图标.png
Normal file
BIN
repo/js/采集cd管理/assets/螃蟹技能图标.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.9 KiB |
@@ -35,13 +35,13 @@ const userSettings = {
|
|||||||
disableJsons: settings.disableJsons || ""
|
disableJsons: settings.disableJsons || ""
|
||||||
};
|
};
|
||||||
|
|
||||||
let ingredientProcessingFood = settings.ingredientProcessingFood;
|
let processingIngredient = settings.processingIngredient;
|
||||||
let foodCounts = settings.foodCount;
|
|
||||||
|
|
||||||
let firstCook = true;
|
let firstCook = true;
|
||||||
let firstsettime = true;
|
let firstsettime = true;
|
||||||
let lastCookTime = new Date();
|
let lastCookTime = new Date();
|
||||||
let lastsettimeTime = new Date();
|
let lastsettimeTime = new Date();
|
||||||
|
let lastMapName = "";
|
||||||
|
|
||||||
// 解析禁用名单
|
// 解析禁用名单
|
||||||
let disableArray = [];
|
let disableArray = [];
|
||||||
@@ -89,7 +89,6 @@ let lastRoll = new Date();
|
|||||||
let checkDelay = Math.round(findFInterval / 2);
|
let checkDelay = Math.round(findFInterval / 2);
|
||||||
|
|
||||||
let Foods = [];
|
let Foods = [];
|
||||||
let foodCount = [];
|
|
||||||
|
|
||||||
const FiconRo = RecognitionObject.TemplateMatch(fIcontemplate, 1102, 335, 34, 400);
|
const FiconRo = RecognitionObject.TemplateMatch(fIcontemplate, 1102, 335, 34, 400);
|
||||||
FiconRo.Threshold = 0.95;
|
FiconRo.Threshold = 0.95;
|
||||||
@@ -97,8 +96,6 @@ FiconRo.InitTemplate();
|
|||||||
|
|
||||||
const mainUiRo = RecognitionObject.TemplateMatch(mainUITemplate, 0, 0, 150, 150);
|
const mainUiRo = RecognitionObject.TemplateMatch(mainUITemplate, 0, 0, 150, 150);
|
||||||
|
|
||||||
let underWater = false;
|
|
||||||
|
|
||||||
let checkInterval = +settings.checkInterval || 50;
|
let checkInterval = +settings.checkInterval || 50;
|
||||||
|
|
||||||
(async function () {
|
(async function () {
|
||||||
@@ -203,14 +200,29 @@ let checkInterval = +settings.checkInterval || 50;
|
|||||||
"default": "100"
|
"default": "100"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "ingredientProcessingFood",
|
"name": "processingIngredient",
|
||||||
"type": "input-text",
|
"type": "multi-checkbox",
|
||||||
"label": "食材名称\n用中文逗号,分隔"
|
"label": "要加工的食材种类",
|
||||||
},
|
"default": [],
|
||||||
{
|
"options": [
|
||||||
"name": "foodCount",
|
"面粉",
|
||||||
"type": "input-text",
|
"兽肉",
|
||||||
"label": "食材数量\n数量对应上方的食材\n用中文逗号,分隔"
|
"鱼肉",
|
||||||
|
"神秘的肉",
|
||||||
|
"黑麦粉",
|
||||||
|
"奶油",
|
||||||
|
"熏禽肉",
|
||||||
|
"黄油",
|
||||||
|
"火腿",
|
||||||
|
"糖",
|
||||||
|
"香辛料",
|
||||||
|
"酸奶油",
|
||||||
|
"蟹黄",
|
||||||
|
"果酱",
|
||||||
|
"奶酪",
|
||||||
|
"培根",
|
||||||
|
"香肠"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "checkInterval",
|
"name": "checkInterval",
|
||||||
@@ -438,12 +450,9 @@ let checkInterval = +settings.checkInterval || 50;
|
|||||||
log.error(`写入文件失败: ${recordFilePath}`);
|
log.error(`写入文件失败: ${recordFilePath}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof ingredientProcessingFood === 'string' && ingredientProcessingFood.trim()) {
|
try {
|
||||||
Foods = ingredientProcessingFood
|
Foods = Array.from(processingIngredient);
|
||||||
.split(/[,,;;\s]+/) // 支持中英文逗号、分号、空格
|
} catch (e) { Foods = []; }
|
||||||
.map(word => word.trim())
|
|
||||||
.filter(word => word.length > 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof foodCounts === 'string' && foodCounts.trim()) {
|
if (typeof foodCounts === 'string' && foodCounts.trim()) {
|
||||||
foodCount = foodCounts
|
foodCount = foodCounts
|
||||||
@@ -667,8 +676,8 @@ let checkInterval = +settings.checkInterval || 50;
|
|||||||
|
|
||||||
const pickedCounter = {};
|
const pickedCounter = {};
|
||||||
priorityItemSet.forEach(n => pickedCounter[n] = 0);
|
priorityItemSet.forEach(n => pickedCounter[n] = 0);
|
||||||
/* ===== 每轮开始输出剩余物品 ===== */
|
/* ===== 剩余物品 ===== */
|
||||||
log.info(`剩余目标材料 ${priorityList.map(t => `${t.itemName}*${t.count}`).join(', ')} `);
|
let remaining = priorityList.map(t => `${t.itemName}*${t.count}`).join(', ');
|
||||||
/* 4-1 扫描 + 读 record + 前置过滤(禁用/时间/材料相关)+ 计算效率 + CD后置排除 */
|
/* 4-1 扫描 + 读 record + 前置过滤(禁用/时间/材料相关)+ 计算效率 + CD后置排除 */
|
||||||
const allFiles = await readFolder('pathing', true);
|
const allFiles = await readFolder('pathing', true);
|
||||||
const rawRecord = await file.readText(`${recordFolder}/${subFolderName}/record.json`);
|
const rawRecord = await file.readText(`${recordFolder}/${subFolderName}/record.json`);
|
||||||
@@ -783,12 +792,14 @@ let checkInterval = +settings.checkInterval || 50;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.info(`当前进度:执行路线 ${fileName},剩余优先材料:${remaining}`);
|
||||||
|
|
||||||
let timeNow = new Date();
|
let timeNow = new Date();
|
||||||
if (Foods.length != 0 && (((timeNow - lastCookTime) > cookInterval) || firstCook)) {
|
if (Foods.length != 0 && (((timeNow - lastCookTime) > cookInterval) || firstCook)) {
|
||||||
firstCook = false;
|
firstCook = false;
|
||||||
await ingredientProcessing();
|
await ingredientProcessing();
|
||||||
lastCookTime = new Date();
|
lastCookTime = new Date();
|
||||||
underWater = false;
|
lastMapName = "Teyvat";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (settings.setTimeMode && settings.setTimeMode != "不调节时间" && (((timeNow - lastsettimeTime) > settimeInterval) || firstsettime)) {
|
if (settings.setTimeMode && settings.setTimeMode != "不调节时间" && (((timeNow - lastsettimeTime) > settimeInterval) || firstsettime)) {
|
||||||
@@ -804,16 +815,28 @@ let checkInterval = +settings.checkInterval || 50;
|
|||||||
runOnce.push(fileName);
|
runOnce.push(fileName);
|
||||||
|
|
||||||
/* ================================= */
|
/* ================================= */
|
||||||
log.info(`当前进度:执行路线 ${fileName}`);
|
|
||||||
state.running = true;
|
state.running = true;
|
||||||
|
|
||||||
|
const raw = file.readTextSync(filePath);
|
||||||
|
const json = JSON.parse(raw);
|
||||||
|
const mapName = (json.info?.map_name && json.info.map_name.trim()) ? json.info.map_name : 'Teyvat';
|
||||||
|
if (filePath.includes('枫丹水下')) {
|
||||||
|
log.info("当前路线为水下路线,检查螃蟹技能");
|
||||||
|
let skillRes = await findAndClick("assets/螃蟹技能图标.png", false, 1000);
|
||||||
|
if (!skillRes || lastMapName != mapName) {
|
||||||
|
log.info("识别到没有螃蟹技能或上一条路线处于其他地图,前往获取螃蟹技能");
|
||||||
|
|
||||||
|
if (mapName === "SeaOfBygoneEras") {
|
||||||
|
await pathingScript.runFile("assets/学习螃蟹技能2.json");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
"assets/学习螃蟹技能1.json";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lastMapName = mapName;
|
||||||
const pickupTask = recognizeAndInteract();
|
const pickupTask = recognizeAndInteract();
|
||||||
if (!underWater && filePath.includes('枫丹水下')) {
|
|
||||||
await pathingScript.runFile("assets/A00-塞洛海原(学习螃蟹技能).json");
|
|
||||||
underWater = true;
|
|
||||||
}
|
|
||||||
if (underWater && !filePath.includes('枫丹水下')) {
|
|
||||||
underWater = false;
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
await pathingScript.runFile(filePath);
|
await pathingScript.runFile(filePath);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -1116,7 +1139,7 @@ let checkInterval = +settings.checkInterval || 50;
|
|||||||
firstCook = false;
|
firstCook = false;
|
||||||
await ingredientProcessing();
|
await ingredientProcessing();
|
||||||
lastCookTime = new Date();
|
lastCookTime = new Date();
|
||||||
underWater = false;
|
lastMapName = "Teyvat";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (settings.setTimeMode && settings.setTimeMode != "不调节时间" && (((timeNow - lastsettimeTime) > settimeInterval) || firstsettime)) {
|
if (settings.setTimeMode && settings.setTimeMode != "不调节时间" && (((timeNow - lastsettimeTime) > settimeInterval) || firstsettime)) {
|
||||||
@@ -1155,17 +1178,29 @@ let checkInterval = +settings.checkInterval || 50;
|
|||||||
/* ======================================= */
|
/* ======================================= */
|
||||||
|
|
||||||
state.running = true;
|
state.running = true;
|
||||||
|
const raw = file.readTextSync(filePath);
|
||||||
|
const json = JSON.parse(raw);
|
||||||
|
const mapName = (json.info?.map_name && json.info.map_name.trim()) ? json.info.map_name : 'Teyvat';
|
||||||
|
if (filePath.includes('枫丹水下')) {
|
||||||
|
log.info("当前路线为水下路线,检查螃蟹技能");
|
||||||
|
let skillRes = await findAndClick("assets/螃蟹技能图标.png", false);
|
||||||
|
if (!skillRes || lastMapName != mapName) {
|
||||||
|
log.info("识别到没有螃蟹技能或上一条路线处于其他地图,前往获取螃蟹技能");
|
||||||
|
|
||||||
|
if (mapName === "SeaOfBygoneEras") {
|
||||||
|
await pathingScript.runFile("assets/学习螃蟹技能2.json");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
"assets/学习螃蟹技能1.json";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lastMapName = mapName;
|
||||||
const pickupTask = recognizeAndInteract();
|
const pickupTask = recognizeAndInteract();
|
||||||
|
|
||||||
log.info(`当前进度:路径组${i} ${folder} ${fileName} 为第 ${groupFiles.indexOf(filePath) + 1}/${groupFiles.length} 个`);
|
log.info(`当前进度:执行路线 ${fileName},路径组${i} ${folder} 第 ${groupFiles.indexOf(filePath) + 1}/${groupFiles.length} 个`);
|
||||||
log.info(`当前路线分均效率为 ${(filePath._efficiency ?? 0).toFixed(2)}`);
|
log.info(`当前路线分均效率为 ${(filePath._efficiency ?? 0).toFixed(2)}`);
|
||||||
if (!underWater && filePath.fullPath.includes('枫丹水下')) {
|
|
||||||
await pathingScript.runFile("assets/A00-塞洛海原(学习螃蟹技能).json");
|
|
||||||
underWater = true;
|
|
||||||
}
|
|
||||||
if (underWater && !filePath.fullPath.includes('枫丹水下')) {
|
|
||||||
underWater = false;
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
state.runPickupLog = []; // 新路线开始前清空
|
state.runPickupLog = []; // 新路线开始前清空
|
||||||
await pathingScript.runFile(filePath.fullPath);
|
await pathingScript.runFile(filePath.fullPath);
|
||||||
@@ -1797,7 +1832,7 @@ async function isTimeRestricted(timeRule, threshold = 5) {
|
|||||||
/**
|
/**
|
||||||
* 食材加工主函数,用于自动前往指定地点进行食材的加工
|
* 食材加工主函数,用于自动前往指定地点进行食材的加工
|
||||||
*
|
*
|
||||||
* 该函数会根据 Foods 和 foodCount 数组中的食材名称和数量,依次查找并制作对应的料食材
|
* 该函数会根据 Foods 数组中的食材名称,依次查找并制作对应的料食材
|
||||||
* 支持调味品类食材(直接在“食材加工”界面查找)
|
* 支持调味品类食材(直接在“食材加工”界面查找)
|
||||||
*
|
*
|
||||||
* @returns {Promise<void>} 无返回值,执行完所有加工流程后退出
|
* @returns {Promise<void>} 无返回值,执行完所有加工流程后退出
|
||||||
@@ -1809,11 +1844,9 @@ async function ingredientProcessing() {
|
|||||||
"奶酪", "培根", "香肠"
|
"奶酪", "培根", "香肠"
|
||||||
];
|
];
|
||||||
if (Foods.length == 0) { log.error("未选择要加工的食材"); return; }
|
if (Foods.length == 0) { log.error("未选择要加工的食材"); return; }
|
||||||
if (Foods.length != foodCount.length) { log.error("请检查食材与对应的数量是否一致!"); return; }
|
const taskList = Foods.map((name) => `${name}`).join(",");
|
||||||
const taskList = Foods.map((name, i) => `${name}*${foodCount[i]}`).join(",");
|
const tasks = Foods.map((name) => ({
|
||||||
const tasks = Foods.map((name, idx) => ({
|
|
||||||
name,
|
name,
|
||||||
count: Number(foodCount[idx]) || 0,
|
|
||||||
done: false
|
done: false
|
||||||
}));
|
}));
|
||||||
log.info(`本次加工食材:${taskList}`);
|
log.info(`本次加工食材:${taskList}`);
|
||||||
@@ -1889,7 +1922,6 @@ async function ingredientProcessing() {
|
|||||||
await sleep(100);
|
await sleep(100);
|
||||||
}
|
}
|
||||||
Foods.splice(i, 1);
|
Foods.splice(i, 1);
|
||||||
foodCount.splice(i, 1);
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -1898,9 +1930,9 @@ async function ingredientProcessing() {
|
|||||||
await findPNG("选择加工数量");
|
await findPNG("选择加工数量");
|
||||||
click(960, 460);
|
click(960, 460);
|
||||||
await sleep(800);
|
await sleep(800);
|
||||||
inputText(String(tasks[i].count));
|
inputText(String(99));
|
||||||
|
|
||||||
log.info(`尝试制作${tasks[i].name} ${tasks[i].count}个`);
|
log.info(`尝试制作${tasks[i].name} 99个`);
|
||||||
await clickPNG("确认加工");
|
await clickPNG("确认加工");
|
||||||
await sleep(500);
|
await sleep(500);
|
||||||
|
|
||||||
@@ -1917,7 +1949,6 @@ async function ingredientProcessing() {
|
|||||||
await sleep(100);
|
await sleep(100);
|
||||||
}
|
}
|
||||||
Foods.splice(i, 1);
|
Foods.splice(i, 1);
|
||||||
foodCount.splice(i, 1);
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -1954,7 +1985,7 @@ async function ingredientProcessing() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const remain1 = tasks.filter(t => !t.done).map(t => `${t.name}*${t.count}`).join(",") || "无";
|
const remain1 = tasks.filter(t => !t.done).map(t => `${t.name}`).join(",") || "无";
|
||||||
log.info(`剩余待加工食材:${remain1}`);
|
log.info(`剩余待加工食材:${remain1}`);
|
||||||
|
|
||||||
if (remain1 === "无") {
|
if (remain1 === "无") {
|
||||||
@@ -1980,7 +2011,7 @@ async function ingredientProcessing() {
|
|||||||
|
|
||||||
for (const item of foodItems) {
|
for (const item of foodItems) {
|
||||||
click(item.x, item.y); await sleep(1 * checkInterval);
|
click(item.x, item.y); await sleep(1 * checkInterval);
|
||||||
click(item.x, item.y); await sleep(6 * checkInterval);
|
click(item.x, item.y); await sleep(3 * checkInterval);
|
||||||
|
|
||||||
for (let round = 0; round < 5; round++) {
|
for (let round = 0; round < 5; round++) {
|
||||||
const rg = captureGameRegion();
|
const rg = captureGameRegion();
|
||||||
@@ -2022,7 +2053,7 @@ async function ingredientProcessing() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const remain = tasks.filter(t => !t.done).map(t => `${t.name}*${t.count}`).join(",") || "无";
|
const remain = tasks.filter(t => !t.done).map(t => `${t.name}`).join(",") || "无";
|
||||||
log.info(`剩余待加工食材:${remain}`);
|
log.info(`剩余待加工食材:${remain}`);
|
||||||
|
|
||||||
|
|
||||||
@@ -2075,7 +2106,7 @@ async function clickPNG(png, maxAttempts = 20) {
|
|||||||
const pngRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync(`assets/RecognitionObject/${png}.png`));
|
const pngRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync(`assets/RecognitionObject/${png}.png`));
|
||||||
pngRo.Threshold = 0.95;
|
pngRo.Threshold = 0.95;
|
||||||
pngRo.InitTemplate();
|
pngRo.InitTemplate();
|
||||||
return await findAndClick(pngRo, true, maxAttempts);
|
return await findAndClick(pngRo, true, maxAttempts * checkInterval, checkInterval);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function findPNG(png, maxAttempts = 20) {
|
async function findPNG(png, maxAttempts = 20) {
|
||||||
@@ -2083,19 +2114,75 @@ async function findPNG(png, maxAttempts = 20) {
|
|||||||
const pngRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync(`assets/RecognitionObject/${png}.png`));
|
const pngRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync(`assets/RecognitionObject/${png}.png`));
|
||||||
pngRo.Threshold = 0.95;
|
pngRo.Threshold = 0.95;
|
||||||
pngRo.InitTemplate();
|
pngRo.InitTemplate();
|
||||||
return await findAndClick(pngRo, false, maxAttempts);
|
return await findAndClick(pngRo, false, maxAttempts * checkInterval, checkInterval);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function findAndClick(target, doClick = true, maxAttempts = 60) {
|
/**
|
||||||
for (let i = 0; i < maxAttempts; i++) {
|
* 通用找图/找RO并可选点击(支持单图片文件路径、单RO、图片文件路径数组、RO数组)
|
||||||
const rg = captureGameRegion();
|
* @param {string|string[]|RecognitionObject|RecognitionObject[]} target
|
||||||
try {
|
* @param {boolean} [doClick=true] 是否点击
|
||||||
const res = rg.find(target);
|
* @param {number} [timeout=3000] 识别时间上限(ms)
|
||||||
if (res.isExist()) { await sleep(checkInterval * 2 + 50); if (doClick) { res.click(); } await sleep(50); return true; }
|
* @param {number} [interval=50] 识别间隔(ms)
|
||||||
} finally { rg.dispose(); }
|
* @param {number} [retType=0] 0-返回布尔;1-返回 Region 结果
|
||||||
if (i < maxAttempts - 1) await sleep(checkInterval);
|
* @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();
|
||||||
|
}
|
||||||
|
await sleep(interval); // 没找到时等待
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 按需返回
|
||||||
|
return retType === 0 ? !!found : (found || null);
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
log.error(`执行通用识图时出现错误:${error.message}`);
|
||||||
|
return retType === 0 ? false : null;
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2128,6 +2215,7 @@ function isArrivedAtEndPoint(fullPath) {
|
|||||||
if (endX === 0 && endY === 0) return false; // 没找到有效点
|
if (endX === 0 && endY === 0) return false; // 没找到有效点
|
||||||
|
|
||||||
/* 2. 取当前人物坐标 */
|
/* 2. 取当前人物坐标 */
|
||||||
|
|
||||||
const mapName = (json.info?.map_name && json.info.map_name.trim()) ? json.info.map_name : 'Teyvat';
|
const mapName = (json.info?.map_name && json.info.map_name.trim()) ? json.info.map_name : 'Teyvat';
|
||||||
const pos = genshin.getPositionFromMap(mapName, 3000);
|
const pos = genshin.getPositionFromMap(mapName, 3000);
|
||||||
const curX = pos.X;
|
const curX = pos.X;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"manifest_version": 1,
|
"manifest_version": 1,
|
||||||
"name": "采集cd管理",
|
"name": "采集cd管理",
|
||||||
"version": "2.9.5",
|
"version": "2.10.0",
|
||||||
"bgi_version": "0.44.8",
|
"bgi_version": "0.44.8",
|
||||||
"description": "仅面对会操作文件和读readme的用户,基于文件夹操作自动管理采集路线的cd,会按照路径组的顺序依次运行,直到指定的时间,并会按照给定的cd类型,自动跳过未刷新的路线",
|
"description": "仅面对会操作文件和读readme的用户,基于文件夹操作自动管理采集路线的cd,会按照路径组的顺序依次运行,直到指定的时间,并会按照给定的cd类型,自动跳过未刷新的路线",
|
||||||
"saved_files": [
|
"saved_files": [
|
||||||
|
|||||||
Binary file not shown.
Reference in New Issue
Block a user