【铁匠铺js】2.3.0更新 (#1745)

* 【铁匠铺js】路径优化与新增

修复:枫丹铁匠铺走过头的问题
新增:纳塔铁匠铺

* 【铁匠铺js】整理模板匹配图像

* 【铁匠铺js】2.3.0更新

- **修复**:枫丹铁匠铺跑过头导致失败的问题
- **优化**:仅领取锻造时,先检测大地图左上角是否有【锻造奖励】图标
- **新增**:
  1. 模式选择(默认模式一)
     - 模式一:自动识别背包中数量最多的矿石锻造,失败自动切换到手动优先级(可能存在数量识别错误)
     - 模式二:手动优先级,依次尝试主选及备选矿石
  2. 支持纳塔铁匠铺

---------

Co-authored-by: 起个名字好难的喵 <25520958+MisakaAldrich@users.noreply.github.com>
This commit is contained in:
呱呱z
2025-08-28 21:40:15 +08:00
committed by GitHub
parent 837b019ff1
commit b181b020fc
18 changed files with 617 additions and 167 deletions

View File

@@ -1,97 +1,163 @@
// ==UserScript==
// @name 自动锻造魔矿脚本
// @version 2.2.1
// @description 自动前往铁匠铺并锻造魔矿,通过识图模式自动选择矿石
// @author 呱呱z
// @match 原神版本5.6BGI 版本0.45.1
// ==/UserScript==
/\*\*
- === 重要免责声明 ===
- 1. 使用风险
- - 本脚本为开源学习项目,禁止用于商业用途或违反游戏条款的行为。
- - 滥用可能导致游戏账号封禁,开发者不承担任何直接或间接责任。
-
- 2. 责任限制
- - 本脚本按“现状”提供,不承诺兼容性、安全性或功能完整性。
- - 因使用本脚本导致的账号、数据、设备损失,开发者概不负责。
-
- 3. 禁止条款
- - 严禁逆向工程、恶意篡改或用于外挂等非法用途。
- - 如游戏运营商提出要求,开发者保留随时停止维护的权利。
-
- 使用即表示您已阅读并同意上述条款。
-
- Last Updated: 2025-05-12
\*/
# 自动锻造魔矿脚本
## 简介
## ⚠️ 免责声明
本脚本可自动前往铁匠铺并利用识图模式选择需要的矿石锻造魔矿。
> **重要提示:请在使用前仔细阅读以下内容**
## 文件结构
### 使用风险
本脚本为开源学习项目,仅限个人学习使用,**禁止用于商业用途或任何违反游戏条款的行为**。滥用可能导致游戏账号封禁,开发者不承担任何直接或间接责任。
- **main.js**:负责核心业务逻辑,包括前往铁匠铺和执行锻造任务。
- **manifest.json**:脚本配置文件,记录基本信息和设置
- **settings.json**:用户配置文件,用于选择目标铁匠铺和指定矿石。
### 责任限制
本脚本按"现状"提供,不承诺兼容性、安全性或功能完整性。因使用本脚本导致的账号、数据、设备等任何损失,开发者概不负责。
## 使用方法
### 禁止条款
严禁对本脚本进行逆向工程、恶意篡改或用于外挂等非法用途。如游戏运营商提出要求,开发者保留随时停止维护的权利。
1. 将脚本添加至调度器。
2. 右键点击脚本以修改 JS 自定义配置。
3. 在配置文件中选择目标城市的铁匠铺(默认选择枫丹铁匠铺),并设定所需矿石(默认:水晶矿)。
- 注意:由于地图追踪功能尚不支持室内定位,故纳塔铁匠铺不可用。
- 可选矿石:
- 默认:水晶矿
- 其他:紫晶矿、萃凝晶
- 如需使用“星银矿石”、“白铁块”或“铁块”,请打开 `settings.json`,删除对应矿石前的 `//` 注释后保存配置。
**使用本脚本即表示您已阅读、理解并同意上述所有条款。**
## 后言
## 📞 联系与反馈
本脚本目前处于测试阶段,欢迎反馈问题至 QQ1765137214。
如有任何建议或问题,欢迎通过以下方式联系:
📧 QQ1765137214
## 更新日志
---
### 2.2.12025.08.03
## ✨ 功能介绍
适用于原神 5.6
BGI 0.48.2 版本
本脚本能够自动前往指定铁匠铺,通过智能图像识别技术自动选择或按预设优先级锻造魔矿:
- 加快锻造速度
- 优化通知逻辑,减少通知被吞概率
- 🗺️ **自动寻路** - 智能导航至指定铁匠铺
- 🔍 **矿石识别** - 支持多种矿石的自动识别与选择
- 🎯 **双模式锻造** - 提供自动和手动两种智能模式
- 📊 **状态通知** - 实时桌面通知与详细执行日志
- 🛡️ **异常处理** - 智能应对各种异常情况
## 📁 文件结构
```
自动锻造魔矿脚本/
├── main.js # 核心业务逻辑
├── manifest.json # 脚本元信息与基础配置
└── settings.json # 用户自定义配置文件
```
## 🚀 快速开始
### 1. 安装脚本
将本脚本添加至 BGI 脚本调度器。
### 2. 配置参数
右键点击脚本,选择"编辑 JS 配置"或直接修改 `settings.json` 文件:
```json
{
"smithyName": "枫丹铁匠铺",
"ore": "水晶块",
"secondaryOre": "紫晶块",
"tertiaryOre": "萃凝晶",
"notice": true,
"forgedOrNot": "是",
"model": "模式一"
}
```
### 3. 矿石配置说明
**默认支持矿石**
- 水晶块
- 紫晶块
- 萃凝晶
**扩展矿石配置**
如需使用"星银矿石"、"白铁块"或"铁块",请在 `settings.json` 中取消对应矿石前的注释(`//`),保存后即可生效。
## ⚙️ 功能详解
### 🔧 锻造模式
| 模式 | 描述 |
|------|------|
| **模式一(自动)** | 自动识别背包中数量最多的矿石进行锻造,识别失败时自动切换到手动优先级模式(可能存在数量识别错误) |
| **模式二(手动)** | 按照用户配置的优先级顺序,依次尝试主选及备选矿石 |
### 🎯 特殊功能
- **仅领取锻造**:如选择"否",则仅检测并领取已完成的锻造奖励
- **智能兜底**:自动模式识别失败时,自动切换到手动优先级模式
- **通知与日志**:支持桌面通知和详细日志,便于追踪脚本执行状态
- **异常处理**:多次识别失败、材料不足等情况均有详细提示和自动处理
## 📋 使用注意事项
1. **环境要求**确保游戏分辨率、BGI 版本与脚本要求一致
2. **窗口状态**:运行脚本时请保持游戏窗口处于前台且未被遮挡
3. **权限设置**:确保已授予脚本必要的系统权限
3. **权限设置**:部分模块由于使用了快捷键,请确保快捷键为默认值。例如纳塔铁匠铺以及仅领取锻造前检查,使用地图快捷键"M";模式一矿物识别部分,使用背包快捷键"B"。因为模式一调用了OCR数字识别部分可能出现错误
## ❓ 常见问题
Q脚本运行后无反应
**A**:请按以下步骤排查:
1. 检查游戏分辨率是否符合要求
2. 确认 BGI 版本是否为 0.48.2 或更高
3. 验证脚本配置是否正确
4. 确保游戏窗口处于前台且未被遮挡
5. 确认游戏快捷键设置为默认值(特别是地图"M"和背包"B"键)
QOCR识别矿石数量不准确怎么办
**A**这是OCR技术的固有局限性可尝试
切换到模式二(手动优先级模式)
---
## 📜 更新日志
### 2.3.0`(2025-08-28)`
- **修复**:枫丹铁匠铺跑过头导致失败的问题
- **优化**:仅领取锻造时,先检测大地图左上角是否有【锻造奖励】图标
- **新增**
1. 模式选择(默认模式一)
- 模式一:自动识别背包中数量最多的矿石锻造,失败自动切换到手动优先级(可能存在数量识别错误)
- 模式二:手动优先级,依次尝试主选及备选矿石
2. 支持纳塔铁匠铺
### 2.2.1`(2025-08-03)`
- 加快锻造速度
- 优化通知逻辑,减少通知被吞概率
### 2.1
- 使用新版版本号
- 5.7 提高了锻造上限,锻造次数由 3 改为 4
- 使用新版版本号
- 5.7 提高了锻造上限,因此使用锻造次数从 3 改成了 4
### 2.005232025-05-23
- 新增仅领取锻造
- 优化点击逻辑
- 修复锻造点击次数超过 3 次的 bug
### 2.005232025.05.23
### 2.02025-05-22
- 新增矿石不足时自动选择备用矿石
- 新增仅领取锻造
- 优化点击逻辑
- 修复点击锻造的次数超过 3 次的 bug
### 1.405212025-05-21
- 新增矿石未能识别时自动选择备用矿石
### 2.02025.05.22
### 1.42025-05-20
- 新增通知功能
- 新增矿石不足时自动选择备用选矿
### 1.32025-05-15
- 修复选择"萃凝晶"时无法识别的问题
- 仓库内新增标签
### 1.405212025.05.21
### 1.22025-05-12
- 修复选择"萃凝晶"时无法识别的 bug
- 新增矿石未能识别时自动选择备用选矿
### 1.12025-05-01
- 优化矿石选取方式,改用识图模式
### 1.42025.05.20
---
- 新增通知功能
**最后更新**2025 年 8 月 28 日
**维护者**@呱呱z
### 1.32025.05.15
- 修复选择“萃凝晶”时无法识别的问题
- 仓库内新增标签。
### 1.22025.05.12
- 修复选择“萃凝晶”时无法识别的 bug
### 1.12025.05.01
- 优化矿石选取方式,改用识图模式
> 💡 提示:建议定期检查更新以获取最佳体验和最新功能

View File

@@ -1,48 +1,62 @@
{
{
"info": {
"name": "枫丹铁匠铺",
"type": "collect",
"author": "寒露",
"version": "1.0",
"authors": [
{
"links": "",
"name": "寒露"
},
{
"links": "",
"name": "呱呱z"
}
],
"bgi_version": "0.45.0",
"description": "",
"bgi_version": "0.42.3"
"enable_monster_loot_split": false,
"last_modified_time": 1756367313887,
"map_match_method": "",
"map_name": "Teyvat",
"name": "枫丹铁匠铺",
"tags": [],
"type": "collect",
"version": "1.1"
},
"positions": [
{
"id": 1,
"action": "",
"action_params": "",
"id": 1,
"move_mode": "run",
"type": "teleport",
"x": 4514.0908203125,
"y": 3630.588623046875,
"action_params": ""
"y": 3630.588623046875
},
{
"action": "",
"action_params": "",
"id": 2,
"move_mode": "run",
"type": "path",
"x": 4518.59765625,
"y": 3601.3916015625,
"type": "path",
"move_mode": "run",
"action": "",
"action_params": ""
"y": 3601.3916015625
},
{
"action": "",
"action_params": "",
"id": 3,
"x": 4563.74755859375,
"y": 3593.390869140625,
"type": "path",
"move_mode": "run",
"action": "",
"action_params": ""
"type": "path",
"x": 4563.74755859375,
"y": 3593.390869140625
},
{
"id": 4,
"x": 4580.56640625,
"y": 3603.6337890625,
"type": "path",
"move_mode": "walk",
"action": "",
"action_params": ""
"action_params": "",
"id": 4,
"move_mode": "dash",
"type": "target",
"x": 4580.56640625,
"y": 3603.6337890625
}
]
}
}

View File

@@ -0,0 +1,40 @@
{
"info": {
"authors": [
{
"links": "",
"name": "呱呱z"
}
],
"bgi_version": "0.48.2",
"description": "",
"enable_monster_loot_split": false,
"last_modified_time": 1756367298175,
"map_match_method": "",
"map_name": "Teyvat",
"name": "纳塔铁匠铺",
"tags": [],
"type": "collect",
"version": "1.0"
},
"positions": [
{
"action": "",
"action_params": "",
"id": 1,
"move_mode": "walk",
"type": "path",
"x": 9025.55078125,
"y": -1913.60107421875
},
{
"action": "",
"action_params": "",
"id": 2,
"move_mode": "dash",
"type": "target",
"x": 9036.7490234375,
"y": -1939.0771484375
}
]
}

View File

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

View File

@@ -1,12 +1,13 @@
/*********************** 配置与常量 ***********************/
// 用户配置
let smithyName = settings.smithyName || "蒙德铁匠铺"; // 铁匠铺地区
let smithyName = settings.smithyName || "枫丹铁匠铺"; // 铁匠铺地区
let primaryOre = settings.ore || "水晶块"; // 主选矿石
let secondaryOre = settings.secondaryOre || "萃凝晶"; // 备选矿石1
let tertiaryOre = settings.tertiaryOre || "紫晶块"; // 备选矿石2
let notice = settings.notice ?? false; // 通知状态
let notice = settings.notice ?? false; // 通知状态
let forgedOrNot = (settings.forgedOrNot && settings.forgedOrNot.trim() !== "") ? settings.forgedOrNot : "是"; // 是否锻造
let model = settings.model || "模式一"; // 模式选择
// 矿石图像与中文名称映射
const ingredientImageMap = {
@@ -27,22 +28,88 @@ const OreChineseMap = {
铁块: "铁块",
};
// 模板识别对象
const ConfirmDeployButtonRo = RecognitionObject.TemplateMatch(
file.ReadImageMatSync("Assets/RecognitionObject/Confirm Deploy Button.png"),
0, 870, 1920, 210
); // 确定按钮
const smithyMap = {
"蒙德铁匠铺": { x: -869, y: 2278, country: "蒙德" },
"璃月铁匠铺": { x: 267, y: -665, country: "璃月" },
"稻妻铁匠铺": { x: -4402, y: -3052, country: "稻妻" },
"须弥铁匠铺": { x: 2786, y: -503, country: "须弥" },
"枫丹铁匠铺": { x: 4507, y: 3630, country: "枫丹" },
"纳塔铁匠铺": { x: 9085, y: -1964, country: "纳塔" }
};
const ForgingInterfaceRo = RecognitionObject.TemplateMatch(
file.ReadImageMatSync("Assets/RecognitionObject/ForgingInterface.png"),
// 模板识别对象
//游戏界面
const InventoryInterFaceRo = RecognitionObject.TemplateMatch(
file.ReadImageMatSync("Assets/RecognitionObject/GameInterface/InventoryInterFace.png"),
0, 0, 140, 100
); // 【背包界面】图标
const DisabledMaterialsFaceRo = RecognitionObject.TemplateMatch(
file.ReadImageMatSync("Assets/RecognitionObject/GameInterface/DisabledMaterialsFace.png"),
0, 0, 1920, 100
); // 【材料界面-未处于】图标
const MaterialsFaceRo = RecognitionObject.TemplateMatch(
file.ReadImageMatSync("Assets/RecognitionObject/GameInterface/MaterialsFace.png"),
0, 0, 1920, 100
); // 【材料界面-已处于】图标
const ForgingInterFaceRo = RecognitionObject.TemplateMatch(
file.ReadImageMatSync("Assets/RecognitionObject/GameInterface/ForgingInterFace.png"),
0, 0, 140, 100
); // 锻造界面图标
//锻造界面物品图标-未使用这部分代码
const CondessenceCrystalForgeRo = RecognitionObject.TemplateMatch(
file.ReadImageMatSync("Assets/Picture/CondessenceCrystal.png"),
0, 870, 1920, 210
); // 【萃凝晶】
const AmethystLumpForgeRo = RecognitionObject.TemplateMatch(
file.ReadImageMatSync("Assets/Picture/AmethystLump.png"),
0, 870, 1920, 210
); // 【紫晶块】
const CrystalChunkForgeRo = RecognitionObject.TemplateMatch(
file.ReadImageMatSync("Assets/Picture/CrystalChunk.png"),
0, 870, 1920, 210
); // 【水晶块】
//背包界面物品图标
const CondessenceCrystalRo = RecognitionObject.TemplateMatch(
file.ReadImageMatSync("Assets/RecognitionObject/ItemImage/CondessenceCrystal.png"),
115, 115, 1270, 625
); // 【萃凝晶】
const AmethystLumpRo = RecognitionObject.TemplateMatch(
file.ReadImageMatSync("Assets/RecognitionObject/ItemImage/AmethystLump.png"),
115, 115, 1165, 510
); // 【紫晶块】
const CrystalChunkRo = RecognitionObject.TemplateMatch(
file.ReadImageMatSync("Assets/RecognitionObject/ItemImage/CrystalChunk.png"),
115, 115, 1165, 510
); // 【水晶块】
//对话框图标
const ForgeRo = RecognitionObject.TemplateMatch(
file.ReadImageMatSync("Assets/RecognitionObject/Forge.png"),
file.ReadImageMatSync("Assets/RecognitionObject/DialogueInterface/Forge.png"),
1260, 300, 600, 600
); // 对话框中的锻造图标
//图标
const ConfirmDeployButtonRo = RecognitionObject.TemplateMatch(
file.ReadImageMatSync("Assets/RecognitionObject/Icon/ConfirmDeployButton.png"),
0, 870, 1920, 210
); // 确定按钮
const ClaimAllRo = RecognitionObject.TemplateMatch(
file.ReadImageMatSync("Assets/RecognitionObject/Icon/全部领取.png"),
0, 900, 1920, 180
);
//地图界面图标
const MapRo = RecognitionObject.TemplateMatch(
file.ReadImageMatSync("Assets/RecognitionObject/icon/右上角巨诗.png"),
945, 20, 975, 50
); // 地图右上角【识别用】图标
const MapForgeRo = RecognitionObject.TemplateMatch(
file.ReadImageMatSync("Assets/RecognitionObject/icon/MapForge.png"),
0, 0, 400, 625
); // 地图左上角【锻造】图标
// 计算矿物图标的坐标(行列排列)
const rows = [1, 2, 3];
const cols = [1, 2, 3, 4, 5];
@@ -57,6 +124,131 @@ for (const row of rows) {
/*********************** 工具函数 ***********************/
// 模板匹配与交互
/**
* 图像识别与交互函数(优化版)
* @param {Object} target - 要识别的图像模板对象
* @param {Object} [options={}] - 配置选项
* @param {boolean} [options.useClick=false] - 是否执行点击操作
* @param {number} [options.timeout=5000] - 识别超时时间(毫秒)
* @param {number} [options.interval=500] - 重试间隔(毫秒)
* @param {boolean} [options.clickCenter=true] - 是否点击中心点
* @param {number} [options.postClickDelay=500] - 点击后等待时间(毫秒)
* @param {boolean} [options.singleAttempt=false] - 是否仅尝试一次
* @returns {Promise<Object>} 返回识别结果对象
*/
async function findAndInteract(target, options = {}) {
// 合并默认选项
const {
useClick = false,
timeout = 3000,
interval = 300,
clickCenter = true,
postClickDelay = 300,
singleAttempt = false
} = options || {};
const startTime = Date.now();
let attemptCount = 0;
let lastError = null;
// 结果对象结构
const resultTemplate = {
success: false,
position: null, // {x, y} 原始位置
clickPosition: null, // {x, y} 点击位置
dimensions: null, // {width, height}
attempts: 0,
elapsed: 0,
error: null
};
// 主识别循环
while (true) {
attemptCount++;
let gameRegion = null;
try {
// 1. 捕获游戏区域
gameRegion = captureGameRegion();
// 2. 执行图像识别
const found = gameRegion.find(target);
if (found?.isExist?.() === true) {
// 构建成功结果
const result = {
...resultTemplate,
success: true,
position: { x: found.x, y: found.y },
dimensions: { width: found.width, height: found.height },
attempts: attemptCount,
elapsed: Date.now() - startTime
};
//log.info(`✅ 识别成功 | 位置: (${found.x}, ${found.y}) | 尺寸: ${found.width}x${found.height} | 尝试: ${attemptCount}次`);
// 3. 处理点击交互
if (useClick) {
// 计算点击位置
const clickPos = clickCenter
? {
x: Math.round(found.x + found.width / 2),
y: Math.round(found.y + found.height / 2)
}
: { x: Math.round(found.x), y: Math.round(found.y) };
result.clickPosition = clickPos;
// 兼容同步/异步 click
if (typeof click === 'function') {
const clickResult = click(clickPos.x, clickPos.y);
if (clickResult && typeof clickResult.then === 'function') {
await clickResult;
}
}
//log.info(`🖱️ 已点击位置: (${clickPos.x}, ${clickPos.y})`);
// 点击后延迟
if (postClickDelay > 0) {
await sleep(postClickDelay);
}
}
return result;
}
// 未找到时的日志
if (attemptCount % 3 === 0) {
log.debug(`⏳ 识别尝试中... 次数: ${attemptCount}, 已用时: ${Date.now() - startTime}ms`);
}
} catch (error) {
lastError = error;
log.error(`识别异常,错误: ${error.message}`);
} finally {
// 4. 资源清理
if (gameRegion?.dispose) {
try { gameRegion.dispose(); } catch (e) { }
}
}
// 退出条件
if (singleAttempt || Date.now() - startTime >= timeout) {
log.warn(`识别失败 | 尝试: ${attemptCount}次,未能识别到目标图像`);
return {
...resultTemplate,
attempts: attemptCount,
elapsed: Date.now() - startTime,
error: lastError?.message
},
false;
}
await sleep(interval);
}
}
// 图像识别函数
function recognizeImage(imagePath, x, y, searchWidth, searchHeight) {
try {
@@ -88,12 +280,97 @@ function determineOre(oreType) {
return message;
}
/*********************** 主逻辑函数 ***********************/
// 模式一:自动识别背包中数量最多的矿石
async function getMaxOreType() {
try {
//开启背包
//【背包】界面检测
if (!await findAndInteract(InventoryInterFaceRo, {
singleAttempt: true
})) {
log.info("未检测到背包界面,尝试返回主界面并打开背包");
await genshin.returnMainUi();
keyPress("B"); await sleep(1000);
} else {
log.info("检测到处于背包界面");
}
// 【材料】见面检测
if (!await findAndInteract(MaterialsFaceRo,
{
singleAttempt: true
})) {
log.info("未处于材料界面,准备点击材料界面图标");
await findAndInteract(DisabledMaterialsFaceRo,
{
useClick: true
})
await sleep(600);
} else {
log.info("已经处于材料界面,准备点击料理区域");
}
const oreResults = [
{ name: "萃凝晶", ro: CondessenceCrystalRo },
{ name: "紫晶块", ro: AmethystLumpRo },
{ name: "水晶块", ro: CrystalChunkRo }
];
let maxOre = null;
let maxCount = 0;
for (const ore of oreResults) {
const result = await findAndInteract(ore.ro, {
useClick: true,
timeout: 5000,
interval: 500,
postClickDelay: 500
});
if (!result || !result.success || !result.clickPosition) continue;
let ocrX = result.clickPosition.x - 63;
let ocrY = result.clickPosition.y + 60;
let resList = captureGameRegion().findMulti(RecognitionObject.ocr(ocrX, ocrY, 130, 55));
let oreNum = 0;
if (resList.count > 0) {
let text = resList[0].text.replace(/[^\d]/g, "");
oreNum = parseInt(text, 10) || 0;
log.info(`识别到 ${OreChineseMap[ore.name]} 数量: ${oreNum}`);
}
if (oreNum > maxCount) {
maxCount = oreNum;
maxOre = ore.name;
if (notice) {
notification.info(`当前最多矿石为: ${OreChineseMap[ore.name]} 数量: ${oreNum}`);
} else {
log.info(`当前最多矿石为: ${OreChineseMap[ore.name]} 数量: ${oreNum}`);
}
}
}
return maxOre;
} catch (error) {
if (notice) {
notification.error(`自动识别背包中数量最多的矿石失败,错误: ${error.message}`);
} else {
log.error(`识自动识别背包中数量最多的矿石失败,错误: ${error.message}`);
}
return null;
}
}
// 自动前往铁匠铺
async function autoSmithy(smithyName) {
log.info(`自动前往 ${smithyName}`);
try {
if (smithyName === "纳塔铁匠铺") {
keyPress("M"); await sleep(1000);
click(1845, 1015); await sleep(100);
click(1650, 355); await sleep(100);
await genshin.setBigMapZoomLevel(1.0);
click(845, 615); await sleep(100);
click(1475, 1005); await sleep(100);
}
let filePath = `assets/Pathing/${smithyName}.json`;
await pathingScript.runFile(filePath);
if (notice) {
@@ -220,7 +497,7 @@ async function tryForgeOre(oreType, skipCheckOres = []) {
}
// 对话、领取、锻造操作
async function forgeOre(smithyName) {
async function forgeOre(smithyName, maxOre = null) {
// 对话部分
await sleep(1000);
keyPress("F");
@@ -246,12 +523,13 @@ async function forgeOre(smithyName) {
await click(960, 1042);
}
}
if (dialogFound) break;
if (!dialogFound)
log.error("多次尝试未能识别到对话界面锻造图标");
break;
}
// 检测锻造界面是否出现
if (dialogFound) {
let interfaceFound = false;
let interFaceFound = false;
for (let attempt = 0; attempt < maxAttempts; attempt++) {
const ocrRegion = { x: 185, y: 125, width: 670 - 185, height: 175 - 125 };
let ocrResults = captureGameRegion().find(
@@ -259,8 +537,8 @@ async function forgeOre(smithyName) {
);
let innerFound = false;
for (let i = 0; i < 3; i++) {
let ForgingInterface = captureGameRegion().find(ForgingInterfaceRo);
if (ForgingInterface.isExist()) {
let ForgingInterFace = captureGameRegion().find(ForgingInterFaceRo);
if (ForgingInterFace.isExist()) {
log.info("已进入锻造界面");
innerFound = true;
break;
@@ -270,13 +548,9 @@ async function forgeOre(smithyName) {
}
}
if (innerFound) {
interfaceFound = true;
interFaceFound = true;
// 领取操作:点击全部领取及确认领取
const ClaimAllRo = RecognitionObject.TemplateMatch(
file.ReadImageMatSync("Assets/RecognitionObject/全部领取.png"),
0, 900, 1920, 180
);
let ClaimAll = captureGameRegion().find(ClaimAllRo);
if (ClaimAll.isExist()) {
ClaimAll.click();
@@ -285,26 +559,40 @@ async function forgeOre(smithyName) {
if (ConfirmButton.isExist()) {
ConfirmButton.click();
await sleep(500);
await click(220, 150);
await sleep(1000); // 点击进入锻造界面
if (forgedOrNot === "是") {
await click(220, 150);
await sleep(1000); // 点击进入锻造界面
}
} else {
log.warn("未能识别到确定按钮");
}
}
// 若设置为锻造,则依次尝试主选及备选矿石
if (forgedOrNot === "是") {
let forgeSuccess = false;
if (await tryForgeOre(primaryOre, [])) {
forgeSuccess = true;
} else if (await tryForgeOre(secondaryOre, [primaryOre])) {
forgeSuccess = true;
} else if (await tryForgeOre(tertiaryOre, [primaryOre, secondaryOre])) {
forgeSuccess = true;
} else {
if (notice) {
notification.error("所有备选矿石都未能识别,结束锻造");
// 模式一:自动模式:自动选择数量最多的矿石锻造
if (model === "模式一" && maxOre) {
primaryOre = maxOre;
log.info(`自动选择数量最多的矿石为: ${primaryOre}`);
forgeSuccess = await tryForgeOre(primaryOre, []);
if (!forgeSuccess) {
log.warn("自动模式锻造未成功,切换到手动备选矿石模式");
}
}
// 模式二或模式一失败时,依次尝试主选及备选矿石
if (model === "模式二" || !forgeSuccess) {
if (await tryForgeOre(primaryOre, [])) {
forgeSuccess = true;
} else if (await tryForgeOre(secondaryOre, [primaryOre])) {
forgeSuccess = true;
} else if (await tryForgeOre(tertiaryOre, [primaryOre, secondaryOre])) {
forgeSuccess = true;
} else {
log.error("所有备选矿石都未能识别,结束锻造");
if (notice) {
notification.error("所有备选矿石都未能识别,结束锻造");
} else {
log.error("所有备选矿石都未能识别,结束锻造");
}
}
}
}
@@ -324,7 +612,7 @@ async function forgeOre(smithyName) {
break; // 退出锻造界面检测循环
}
}
if (!interfaceFound) {
if (!interFaceFound) {
log.error("经过多次尝试,未能进入锻造界面");
}
} else {
@@ -352,9 +640,45 @@ async function forgeOre(smithyName) {
log.info("自动锻造矿石脚本开始");
}
let maxOre = null;
if (forgedOrNot === "是") {
if (model === "模式一") {
maxOre = await getMaxOreType();
if (maxOre) {
log.info(`自动选择数量最多的矿石为: ${maxOre}`);
primaryOre = maxOre;
} else {
log.warn("自动识别矿石失败,将使用默认配置");
}
}
await autoSmithy(smithyName);
await forgeOre(smithyName, maxOre);
}
if (forgedOrNot === "否") {
keyPress("M"); await sleep(1000);
if (!await findAndInteract(MapRo,
{
singleAttempt: true
})) {
const smithyInfo = smithyMap[smithyName];
if (smithyInfo) {
await genshin.moveMapTo(smithyInfo.x, smithyInfo.y, smithyInfo.country);
}
}
if (!await findAndInteract(MapForgeRo,
{
})) {
await genshin.returnMainUi();
log.info("未能识别到锻造完成图标,无需前往领取。结束脚本");
return; // 若没有锻造图标则跳出
}
await autoSmithy(smithyName);//路径函数,前往铁匠铺
await forgeOre(smithyName);
}
await autoSmithy(smithyName);
await forgeOre(smithyName);
await genshin.returnMainUi();
//后退两步

View File

@@ -1,28 +1,23 @@
{
"manifest_version": 1,
"name": "自动锻造魔矿(识图版)",
"version": "2.2.1",
"bgi_version": "0.44.0",
"description": "自动选择铁匠铺和使用矿物去锻造精锻矿。\n \n使用前请阅读“readme”文件以获取更多详细信息。 \n---更新说明--- \n- 请查阅readme",
"tags": [
"铁匠铺",
"锻造",
"精锻用魔矿",
"模板匹配"
],
"authors": [
{
"name": "呱呱z",
"links": "https://github.com/jidingcai"
},
{
"name": "寒露"
},
{
"name": "蜜柑魚",
"links": "https://github.com/this-Fish"
}
],
"settings_ui": "settings.json",
"main": "main.js"
}
"manifest_version": 1,
"name": "自动锻造魔矿(识图版)",
"version": "2.3.0",
"bgi_version": "0.48.2",
"description": "自动选择铁匠铺和使用矿物去锻造精锻矿。\n \n使用前请阅读“readme”文件以获取更多详细信息。 \n---更新说明--- \n- 请查阅readme",
"tags": ["铁匠铺", "锻造", "精锻用矿"],
"authors": [
{
"name": "呱呱z",
"links": "https://github.com/jidingcai"
},
{
"name": "寒露"
},
{
"name": "蜜柑魚",
"links": "https://github.com/this-Fish"
}
],
"settings_ui": "settings.json",
"main": "main.js"
}

View File

@@ -4,16 +4,27 @@
"type": "checkbox",
"label": "通过BGI通知系统发送详细通知"
},
{
"name": "model",
"type": "select",
"label": "模式选择(默认:模式一)\n【模式一】自动模式自动选择数量最多的矿石锻造\n【模式二】手动模式依次尝试主选及备选矿石\n注模式一可能会因OCR识别数量不准导致选择错误",
"options": [
"模式一",
"模式二"
],
"default": "模式一"
},
{
"name": "smithyName",
"type": "select",
"label": "选择铁匠铺(默认:蒙德铁匠铺)",
"label": "铁匠铺地区选择(默认:枫丹铁匠铺)",
"options": [
"蒙德铁匠铺",
"璃月铁匠铺",
"稻妻铁匠铺",
"须弥铁匠铺",
"枫丹铁匠铺"
"枫丹铁匠铺",
"纳塔铁匠铺"
]
},
{
@@ -28,11 +39,11 @@
{
"name": "ore",
"type": "select",
"label": "当矿石未能识别时依次使用\n锻造用矿默认水晶块",
"label": "当矿石未能识别/模式二时依次使用\n锻造用矿默认水晶块",
"options": [
"水晶块",
"萃凝晶",
"星银矿石",
//"星银矿石",
//"白铁块",
//"铁块",
"紫晶块"