铁匠铺2.0更新 (#905)

* 铁匠铺2.0更新

-   新增矿石未能识别时自动选择备用选矿

* Create 建文件夹用

* Add files via upload

* Delete repo/js/铁匠铺/assets/RecognitionObject/建文件夹用

* Update and rename readme(25.05.21).md to readme(25.05.22).md

* Add files via upload
This commit is contained in:
呱呱z
2025-05-22 10:56:05 +08:00
committed by GitHub
parent 30d7b41639
commit b4a34c9ae7
7 changed files with 152 additions and 54 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@@ -1,3 +1,10 @@
//锻造按钮模板
const ConfirmDeployButtonRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync("Assets/RecognitionObject/Confirm Deploy Button.png"), 0, 870, 1920, 210);
const ForgingInterfaceRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync("Assets/RecognitionObject/ForgingInterface.png"), 0, 0, 140, 100);
const ForgeRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync("Assets/RecognitionObject/Forge.png"), 1260, 300, 600, 600);
(async function () {
// 设置通知状态
let notice = settings.notice ?? false;
@@ -12,8 +19,8 @@
// 读取用户配置
let smithyName = settings.smithyName || "枫丹铁匠铺";
let primaryOre = settings.ore || "水晶块";
let secondaryOre = settings.secondaryOre || "萃凝晶"; // 新增备选矿物2
let tertiaryOre = settings.tertiaryOre || "紫晶块"; // 新增备选矿物3
let secondaryOre = settings.secondaryOre || "萃凝晶";
let tertiaryOre = settings.tertiaryOre || "紫晶块";
// 定义矿物名称和图片文件名的映射表
const ingredientImageMap = {
@@ -38,7 +45,6 @@
// 行列数的排列组合
const rows = [1, 2, 3]; // 行数
const cols = [1, 2, 3, 4, 5]; // 列数
const gridCoordinates = [];
for (const row of rows) {
@@ -122,75 +128,163 @@
log.info(`开始识别矿石: ${OreChineseMap[oreType]}`);
const scanOffset = { x: -35, y: -35 };
// 最大尝试次数
const maxAttempts = 3;
for (let attempt = 0; attempt < maxAttempts; attempt++) {
let found = false;
for (const coordinate of gridCoordinates) {
const scanX = coordinate.x + scanOffset.x;
const scanY = coordinate.y + scanOffset.y;
const imageResult = recognizeImage(imagePath, scanX, scanY, 70, 70);
if (imageResult) {
found = true;
imageResult.click();
await sleep(2000);
await sleep(1000);
if (notice) {
notification.send(`通过图像识别找到矿石: ${OreChineseMap[oreType]}`);
} else {
log.info(`通过图像识别找到矿石: ${OreChineseMap[oreType]}`);
}
determineOre(oreType);
// 点击"开始锻造"3次
for (let i = 0; i < 3; i++) {
await sleep(1000);
click(1645, 1015);
}
return true;
}
}
if (notice) {
notification.error(`未能识别到矿石: ${OreChineseMap[oreType]}`);
// 点击“开始锻造”按钮3次每次点击后进行OCR识别提示
const ocrRegion = { x: 660, y: 495, width: 1250 - 660, height: 550 - 495 };
// 内部点击循环——点击“开始锻造”按钮后进行OCR识别
let clickAttempts = 0;
let forgingTriggered = false;
while (clickAttempts < 3 && !forgingTriggered) {
// 点击“开始锻造”
let ConfirmButton = captureGameRegion().find(ConfirmDeployButtonRo);
if (ConfirmButton.isExist()) {
//log.info("识别到确定按钮:({x},{y},{w},{h})", ConfirmButton.x, ConfirmButton.y, ConfirmButton.Width, ConfirmButton.Height);
ConfirmButton.click();
} else {
log.error(`未能识别到矿石: ${OreChineseMap[oreType]}`);
//log.warn("未能识别到确定按钮");
}
await sleep(1500); // 等待提示出现
// 执行OCR识别提示区域内的文字
let ocrResults = captureGameRegion().find(
RecognitionObject.ocr(ocrRegion.x, ocrRegion.y, ocrRegion.width, ocrRegion.height)
);
if (ocrResults) {
log.info(`${ocrResults.text}`);
if (ocrResults.text.includes("今日已无法锻造")) {
if (notice) {
notification.send("检测到 今日已无法锻造 停止脚本");
} else {
log.info("检测到 今日已无法锻造 停止脚本");
}
return true; // 完全终止锻造流程
} else if (ocrResults.text.includes("材料不足")) {
if (notice) {
notification.send("检测到 材料不足 跳过当前矿物。请检查背包,及时补充矿物。");
} else {
log.info("检测到 材料不足 跳过当前矿物。请检查背包,及时补充矿物。");
}
await click(960, 800); // 点击确定关闭提示
await sleep(1000);
return false; // 直接返回,跳过识别当前矿物
} else {
// 如果OCR识别结果没有检测到错误提示则认为本次锻造指令有效
forgingTriggered = true;
}
} else {
//log.warn("未能识别到任何文字");
}
clickAttempts++;
}
}
}
// 如果本次尝试未识别到矿石,则等待后重试
if (!found) {
if (notice) {
//notification.error(`未能识别到矿石: ${OreChineseMap[oreType]},重试中... (${attempt + 1}/${maxAttempts})`);
}
log.error(`未能识别到矿石: ${OreChineseMap[oreType]},重试中... (${attempt + 1}/${maxAttempts})`);
await sleep(1000);
}
}
if (notice) {
notification.error(`未能识别到矿石: ${OreChineseMap[oreType]},停止尝试`);
} else {
log.error(`未能识别到矿石: ${OreChineseMap[oreType]},停止尝试`);
}
return false;
}
// 锻造矿石操作
const forgeOre = async function (smithyName) {
// 对话
// 对话部分(如果需要可打开注释)
await sleep(1000); keyPress("F");
await sleep(1000); await click(960, 600);
await sleep(1000); await click(960, 600);
await sleep(1000); await click(1375, 500);
await sleep(1000); await click(960, 600); await sleep(1000);
await click(960, 600); await sleep(1000);
await sleep(1000); await click(960, 1042);
await sleep(1000); await click(960, 1042);
let Forge = captureGameRegion().find(ForgeRo);
if (Forge.isExist()) {
//log.info("识别到锻造图标:({x},{y},{w},{h})", Forge.x, Forge.y, Forge.Width, Forge.Height);
await Forge.click();
} else {
log.warn("未能识别到锻造图标");
}
await sleep(1000); await click(960, 1042);
await sleep(1000); await click(960, 1042);
//检测到锻造界面
for (let i = 0; i < 3; i++) {
let ForgingInterface = captureGameRegion().find(ForgingInterfaceRo);
if (ForgingInterface.isExist()) {
log.info("已进入锻造界面,准备锻造");
// 锻造领取
await click(520, 140); await sleep(1000);
await click(170, 1010); await sleep(1000);
await click(960, 900); await sleep(1000);
break;
} else {
await sleep(1000);
}
}
// 锻造领取(如果需要可打开注释)
//领取全部
const ClaimAllRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync("Assets/RecognitionObject/全部领取.png"), 0, 900, 1920, 180);
let ClaimAll = captureGameRegion().find(ClaimAllRo);
if (ClaimAll.isExist()) {
//log.info("识别到全部领取按钮:({x},{y},{w},{h})", ClaimAll.x, ClaimAll.y, ClaimAll.Width, ClaimAll.Height);
ClaimAll.click();
await sleep(1000); // 等待提示出现
//确认领取
let ConfirmButton = captureGameRegion().find(ConfirmDeployButtonRo);
if (ConfirmButton.isExist()) {
//log.info("识别到确定按钮:({x},{y},{w},{h})", ConfirmButton.x, ConfirmButton.y, ConfirmButton.Width, ConfirmButton.Height);
ConfirmButton.click();
} else {
//log.warn("未能识别到确定按钮");
}
} else {
//log.warn("未能识别到全部领取按钮");
}
click(220, 150); await sleep(1000);
// 按优先级尝试识别矿石
let forgeSuccess = false;
// 尝试主选矿石
if (!forgeSuccess) {
forgeSuccess = await tryForgeOre(primaryOre, []);
if (await tryForgeOre(primaryOre, [])) {
forgeSuccess = true;
}
// 如果主选矿石识别失败尝试备选矿石2跳过与主选相同的
if (!forgeSuccess) {
forgeSuccess = await tryForgeOre(secondaryOre, [primaryOre]);
// 如果主选识别失败尝试备选矿石2
else if (await tryForgeOre(secondaryOre, [primaryOre])) {
forgeSuccess = true;
}
// 如果备选矿石2也识别失败尝试备选矿石3跳过与主选和备选2相同的
if (!forgeSuccess) {
forgeSuccess = await tryForgeOre(tertiaryOre, [primaryOre, secondaryOre]);
// 如果备选矿石2也失败尝试备选矿石3
else if (await tryForgeOre(tertiaryOre, [primaryOre, secondaryOre])) {
forgeSuccess = true;
}
// 如果所有矿石都识别失败
if (!forgeSuccess) {
// 所有备选矿石都未能识别,结束锻造
else {
if (notice) {
notification.error("所有备选矿石都未能识别,结束锻造");
} else {
@@ -198,7 +292,7 @@
}
}
// 退出锻造界面
// 退出锻造界面(如果需要可打开注释)
await click(520, 140); await sleep(1000);
if (notice) {
notification.send("锻造结束,退出界面");
@@ -208,6 +302,7 @@
await genshin.returnMainUi();
};
// 执行步骤
await autoSmithy(smithyName);
await forgeOre(smithyName);
await genshin.returnMainUi();

View File

@@ -1,9 +1,9 @@
{
"manifest_version": 1,
"name": "自动锻造魔矿",
"version": "1.40521(2025.05.21版)",
"version": "2.0\n(2025.05.22版)",
"bgi_version": "0.44.0",
"description": "自动选择铁匠铺和使用矿物去锻造精锻矿。\n \n使用前请阅读“readme”文件。 \n---更新说明--- \n- 新增矿石未能识别时自动选择备用选矿",
"description": "自动选择铁匠铺和使用矿物去锻造精锻矿。\n \n使用前请阅读“readme”文件。 \n---更新说明--- \n- 新增矿石不足时自动选择备用选矿",
"tags": ["铁匠铺", "锻造", "精锻用矿"],
"authors": [
{

View File

@@ -55,6 +55,9 @@
## 更新日志
### 2.02025.05.22
- 新增矿石不足时自动选择备用选矿
### 1.405212025.05.21
- 新增矿石未能识别时自动选择备用选矿