自动黑名单,增加拖动距离,增加月卡弹窗识别 (#2129)

* Add files via upload

* Add files via upload

* Add files via upload

* 背包统计2.51增加自动黑名单、月卡弹窗识别、自定义划页距离

+ v2.51 自定义设置增加划页距离、拖动点,增加月卡弹窗识别,增加路径材料9999自动黑名单,修复怪物0收获记录

* Add files via upload

* Add files via upload
This commit is contained in:
吉吉喵
2025-10-13 08:14:57 +08:00
committed by GitHub
parent 028a712514
commit fc39b8307d
18 changed files with 296 additions and 98 deletions

View File

@@ -1,76 +1,160 @@
# 背包材料统计 v2.5
# 背包材料统计 v2.5
作者:吉吉喵
## 简介:
可统计背包养成道具、部分食物、素材的数量根据设定数量、根据材料刷新CD执行挖矿、采集、刷怪等的路径。优势
+ 1. 自动判断材料CD不需要管材料CD有没有好
+ 2. 可以随意添加路径,能自动排除低效、无效路径;
+ 3. 有独立名单识别不会交互路边的npc或是神像可自定义识别名单具体方法看【问题解答】增减识别名单
+ 4. 有实时的弹窗模块,提供了常见的几种:路边信件、过期物品、月卡、调查
## 用前须知要有一点的动手能力该JS不提供路径文件需要文件夹操作
## 一、简介
可统计背包内养成道具、部分食物、素材的数量并根据「设定目标数量」「材料刷新CD」自动执行挖矿、采集、刷怪等路径。
## 使用方法
### 核心优势
1. **自动CD判断**无需手动关注材料刷新状态脚本自动识别CD是否就绪
2. **灵活路径管理**:支持自定义添加路径,自动排除低效/无效路径;
3. **独立名单识别**不与路边NPC、神像交互可自定义识别名单操作见「四、问题解答」
4. **实时弹窗保护**:内置弹窗模块(覆盖路边信件、过期物品、月卡、调查等场景),运行时全程保护路径不被弹窗干扰。
## 基础教程
+ 1. 仓库 订阅 所需路径文件;
+ 2. 打开路径所在文件夹BetterGI\Repos\bettergi-scripts-list-git\repo\pathing
把地方特产、敌人与魔物、矿物、食材与炼金四个文件夹复制到背包材料统计JS目录BetterGI\User\JsScript\背包材料统计\pathing中最好手动去除重复多余路径pathing下只能读取3层文件夹如pathing文件夹下有4层或以上子文件夹请削减到3层
+ 3. 推荐根据队伍来把路径分组放置。比如
背包统计采集组,生存队:迪希雅 芭芭拉 瑶瑶 草神。适合一般情况下的采集;
背包统计刷怪组,适合挂机输出的队:火神 奶奶 钟离 万叶,能够胜任需要刷怪的路径;
背包统计附魔材料组,附魔队:钟离 芭芭拉 久岐忍 砂糖或班尼特,适合附魔采集;
+ 4. 找到背包材料统计js右键 背包材料统计选择JS修改脚本自定义设置
## JS的自定义设置
+ 1. 目标数量,是扫描背包中材料数量,只有低于目标的材料,其路径才会被纳入执行序列;
+ 2. 优先级材料,是最高优先级,直接无视上述目标数量,纳入执行序列最顶层;
+ 3. 时间成本在一个路径存在3到5次记录时会计算时间成本单个材料获取时间超过默认30秒的则跳过
+ 4. 发送通知每类材料跑完会通知一次全部材料跑完会汇总通知一次。需在BGI通知里开启接收端企业微信的使用自行寻找
+ 5. 取消扫描,是取消每个路径执行完的扫描;当大部分需要的路径都有足够多记录,就可以不需要新增运行记录,可以不扫描了,以节约时间;但全部材料执行始末会各扫一次,以汇总材料信息。
+ 6. 仅pathing材料是平衡背包材料统计和路径CD管理的选项选择仅pathing材料则直接无视下方勾选的材料分类只扫描pathing文件夹已有的路径材料没有的就不扫以缩短扫描时间
+ 7. 弹窗名不填默认assets\imageClick文件夹下所有弹窗循环执行弹窗模块会在背包统计运行时全程保护路径防止弹窗影响路径执行
+ 8. 采用的CD分类不在materialsCD文件夹的不执行这个文件夹可以按格式新增材料CD分类txt只要背包材料统计的图库里有路径所在的文件夹名正确就能按CD执行
+ 9. targetText文件夹里的是独立名单识别的名单可以按随意新增txt内容按格式英文冒号前的名字也随便写冒号后的文字会被当成目标来识别不在targetText文件夹下不识别
## 注意事项
+ 1. 联机请求会遮挡背包菜单导致识别不到类别建议在背包统计JS前加一个权限设置JS以禁止联机
+ 2. pathing下只能读取3层文件夹如pathing文件夹下有4层或以上的子文件夹请削减到3层
+ 3. 推荐根据功能需求来把路径分组放置。复制多份背包材料统计,分别加上采集、刷怪、附魔材料后缀,用于管理一般情况下的采集路径、能够胜任需要战斗的路径、需求附魔采集的路径;
+ 4. 因食物部分图片未补足,为适配快速滑页,背包食物界面,苹果、日落果、星蕈、活化的星蕈、枯焦的星蕈、泡泡桔、烛伞蘑菇、美味的宝石闪闪,这八个食物必须有,且在第一行。不然这几个食物会无法识别;
## 二、用前须知
1. 需具备基础电脑操作能力(如文件夹复制、路径查找);
2. 脚本不自带路径文件,需手动对目标文件夹进行操作(步骤见「三、使用方法」)。
## 问题解答
+ 1. 如果不想要某些路径怎么排除直接进pathing文件夹把该材料名或者该怪物名路径文件夹移走或者删除切记不要把路径文件放入targetText和materialsCD这两个文件夹
+ 2. 如果想要增减识别名单怎么做直接进targetText文件夹选择或者新建一份txt名字随意内容按格式英文冒号前的名字可随便写冒号后的文字会被当成目标来识别用英文逗号分割如果想刷某类怪但不想要拾取其怪物材料可以找到掉落.txt删除不要的材料名
+ 3. 如果想要识别不规范命名的路径文件夹怎么做?比如纳塔食材一条龙或者果园.json。方法把纳塔食材一条龙文件夹或者果园.json丢进一个适配的材料文件夹里CD要符合因为CD选择是由所在的材料名文件夹决定果园.json可以丢到苹果文件夹里
+ 4. 如果想要识别自带CD文件中没有的材料怎么做比如新材料新木头打开materialsCD文件夹选择或者新建一份txt名字随意内容按格式中文冒号前的名字也要按格式具体参考自带的CD文件如几点几小时几次0点冒号后的文字会被当成目标来识别用中文逗号分割注意这个文字就是作为JS里的标准名路径所在文件夹名和材料图片名都必须和它一致多层套叠的文件夹会默认选择符合标准名的那个如有同名套叠会选最外层那个
+ 5. 如果不想要每次路径都扫描背包怎么做具体方法看【JS的自定义设置】取消扫描
## 后言
本脚本目前处于测试阶段,欢迎反馈问题至 QQ频道号: bettergiv1。
## 三、使用方法
### 3.1 基础教程(路径配置)
#### 步骤1订阅路径文件
在仓库中订阅所需的路径文件,参考以下截图操作:
- 截图1![](assets/Pic/Pic06.png)
- 截图2![](assets/Pic/Pic09.png)
- 截图3![](assets/Pic/Pic11.png)
- 截图4![](assets/Pic/Pic04.png)
## 更新日志
+ v0.1 OCR名单 输出图片名和材料名
+ v1.0 图包(素材)
+ v1.1 图包(素材+养成道具)
+ v1.2 识图分类
+ v1.3 加速寻找(前位材料识别)
+ v1.31 本地保存调整
+ v1.32 新增后位材料识别
+ v2.0 多组材料多个分类 开发版
- v2.0 前、后位材料识别
+ v2.1 CD管理版
+ v2.2 路径顺序 材料数量优化
+ v2.21 储存路径修改
+ v2.22 精简log
+ v2.23 优化部分函数
+ v2.24 修复不能空路径使用背包统计功能等bug
+ v2.25 当前、后位材料识别(加速扫描),新增只扫描路径材料名选项(内存占用更小)
+ v2.26 修复读取材料时间错误等bug新增路径材料时间成本计算
+ v2.27 修复计算材料数错误、目标数量临界值、"3"识别成"三"等bug
+ v2.28 材料更变时初始数量更新正常记录排除0位移和0数量的路径记录(可能是卡路径需手动根据0记录去甄别)新增材料名0后缀本地记录新增背包弹窗识别
+ v2.29 新增排除提示;调整平均时间成本计算;过滤掉差异较大的记录;
+ v2.30 更改路径专注模式默认值加log提示去除注释掉的调试log
+ v2.40 优化背包识别时占用的内存;增加通知;
+ v2.41 修复勾选分类的本地记录bug新增仅背包统计选项如果本地记录已经遭到破坏。比如每条路径都产生大量材料名-0.txt就只能手动清理或者删除本地记录pathing_record重新跑
+ v2.42 增加无路径间的扫描、无数量记录的noRecord模式适合路径记录已经炼成的玩家。新增怪物材料CD文件以支持轻度刷怪需求。
+ v2.5 增加独立名单拾取增加弹窗模块这个2个是背包材料统计JS运行时实时运行。增加对怪物名的支持。
#### 步骤2复制路径到目标文件夹
1. 打开**路径源文件夹**(存放订阅的路径文件):
```
BetterGI\Repos\bettergi-scripts-list-git\repo\pathing
```
2. 根据需求,复制以下类型的路径文件夹(按需选择):
- 地方特产
- 敌人与魔物
- 矿物
- 食材与炼金
3. 粘贴到**脚本目标文件夹**(背包材料统计的路径读取目录):
```
BetterGI\User\JsScript\背包材料统计\pathing
```
#### 步骤2关键注意点
- 手动删除重复路径(例如“萃凝晶”可能存在多个重复路径,需手动清理),参考截图:![](assets/Pic/Pic01.png)
- `pathing` 文件夹仅支持**3层子文件夹**若超过3层需手动削减否则无法读取
- 推荐优先配置「枫丹水下」路径:无队伍要求,但需提前开启水下锚点。
#### 步骤3按队伍分组管理路径
建议复制多份「背包材料统计」脚本,按队伍功能分组存放适配路径,避免路径混乱。示例如下:
| 分组名称 | 适配队伍组合 | 适用场景 | 特殊说明 |
|------------------------|-----------------------------------|---------------------------|-----------------------------------|
| 背包统计采集组(生存队) | 迪希雅 + 芭芭拉 + 瑶瑶 + 草神 | 常规材料采集 | 无草神时需批量搜索路径中“nahida_collect”并排除 |
| 背包统计刷怪组 | 火神 + 奶奶 + 钟离 + 万叶 | 挂机刷怪(获取怪物材料) | 确保队伍输出足够,能高效清理怪物 |
| 背包统计附魔材料组 | 钟离 + 芭芭拉 + 久岐忍 + 砂糖/班尼特 | 附魔类采集(需特定附魔) | 适配需附魔才能获取的材料路径 |
分组示例参考截图:![](assets/Pic/Pic03.png)
无草神时排除路径操作参考截图:![](assets/Pic/Pic05.png)
#### 步骤4打开脚本自定义设置
1. 找到「背包材料统计.js」文件
2. 右键点击该文件选择「JS 修改脚本自定义设置」;
3. 操作参考截图:![](assets/Pic/Pic02.png)
### 3.2 JS 自定义设置(核心配置项)
| 配置项 | 功能说明 | 操作建议 |
|----------------------|--------------------------------------------------------------------------|--------------------------------------------------------------------------|
| 1. 目标数量 | 仅当背包材料数量**低于此值**时,该材料的路径才会被纳入执行序列 | 这是个统一值,管理路径下全部材料的目标数量 |
| 2. 优先级材料 | 无视“目标数量”限制,直接纳入执行序列顶层(最高优先级) | 填写当前急需材料(例:“虹滴晶”“巡陆艇”) |
| 3. 时间成本 | 当一个路径有3-5次运行记录后自动计算“单材料获取时间”超过30秒则跳过该路径 | 保持默认30秒即可无需频繁修改可过滤低效路径 |
| 4. 发送通知 | ① 每类材料跑完通知一次;② 全部材料跑完汇总通知一次需开启BGI通知 | 建议开启,方便实时了解进度(接收端如企业微信需自行配置) |
| 5. 取消扫描 | 取消“每个路径执行后”的背包扫描,仅保留“全部执行前/后”2次扫描 | 路径记录足够多时开启,可节约运行时间 |
| 6. 仅 pathing 材料 | 仅扫描 `pathing` 文件夹内的材料,跳过其他分类,大幅缩短扫描时间 | 路径配置完成后开启,提升脚本运行效率 |
| 7. 弹窗名 | 不填则默认循环执行 `assets\imageClick` 文件夹下所有弹窗;填写则仅执行指定弹窗 | 推荐默认,需单独适配某类弹窗时填写(例:仅处理月卡弹窗则填:月卡) |
| 8. 采用的 CD 分类 | 仅执行 `materialsCD` 文件夹内配置的材料路径支持新增CD分类txt | 新增材料时需在该文件夹同步配置CD规则操作见「四、问题解答4」 |
| 9. 拖动距离 | 解决非1080p分辨率下“划页过头”问题需调整到“一次划页≤4行” | 拖动点建议选“第五行材料附近”大于1080p屏可适当减小数值 |
## 四、注意事项
1. **禁止联机请求**联机请求会遮挡背包菜单导致材料识别失败。建议在本脚本前添加「AutoPermission」权限设置JS仓库可查自动禁止联机
2. **文件夹层级限制**`pathing` 文件夹仅支持3层子文件夹超过需手动削减否则路径无法读取
3. **食物识别强制要求**:背包食物界面**第一行必须包含8种食物**(苹果、日落果、星蕈、活化的星蕈、枯焦的星蕈、泡泡桔、烛伞蘑菇、美味的宝石闪闪),缺少则这些食物无法识别;
4. **关键文件备份**:定期备份 `pathing` 文件夹(路径文件)和 `pathing_record` 文件夹(路径运行记录),丢失后需重新配置/统计。
## 五、问题解答
### Q1如何排除不想要的路径
A1. 打开 `pathing` 文件夹(脚本路径:`BetterGI\User\JsScript\背包材料统计\pathing`
2. 直接删除/移走目标材料/怪物的路径文件夹;
3. **注意**:不要将路径文件放入 `targetText` 或 `materialsCD` 文件夹(这两个文件夹默认全部读取,也会被更新覆盖)。
### Q2如何增减识别名单
A1. 打开 `targetText` 文件夹(脚本路径:`BetterGI\User\JsScript\背包材料统计\targetText`
2. 新建/编辑txt文件按格式填写`自定义名称:目标1,目标2`(英文冒号+英文逗号,例:“新材料:霜盏花,便携轴承”);
3. 若需排除怪物掉落材料:找到“掉落.txt”删除对应材料名即可
4. 操作参考截图:
- 截图1![](assets/Pic/Pic12.png)
- 截图2![](assets/Pic/Pic10.png)
### Q3如何识别不规范命名的路径文件夹如“纳塔食材一条龙”“果园.json”
A将不规范的文件夹/文件,放入**适配的材料文件夹**中即可路径CD由“所在材料文件夹”决定
例:“果园.json”放入“苹果”文件夹将按“苹果”的CD规则执行。
### Q4如何识别自带CD文件中没有的材料如新材料、新木头
A1. 打开 `materialsCD` 文件夹(脚本路径:`BetterGI\User\JsScript\背包材料统计\materialsCD`
2. 新建/编辑txt文件按格式填写`CD规则材料1材料2`(中文冒号+中文逗号CD规则参考自带文件“1次0点月落银宿影花”
3. **关键要求**路径文件夹名、材料图片名必须与“材料1/2”完全一致多层文件夹默认读取最外层同名文件夹
4. 操作参考截图:
- 截图1![](assets/Pic/Pic07.png)
- 截图2![](assets/Pic/Pic08.png)
### Q5如何避免每次路径执行后都扫描背包
A在「JS自定义设置」中勾选“取消扫描”仅保留“全部材料执行始/末”的2次扫描节约时间
### Q6扫描背包少一行、拖动距离异常怎么办
A在「JS自定义设置」中调整“拖动距离”直到“一次划页仅显示≤4行材料”拖动点建议选第5行材料附近
### Q7本地记录保存在哪里
A记录文件夹位于 `BetterGI\User\JsScript\背包材料统计\` 下,各文件功能如下:
- `overwrite_record`:所有历史记录(按材料分类储存);
- `history_record`:勾选“材料分类”后的专属记录;
- `latest_record.txt`:最近几种材料的记录(有上限,仅存最新数据);
- `pathing_record`:单个路径的完整记录(含运行时间、收获量,需重点备份);
操作参考截图:![](assets/Pic/Pic13.png)
## 六、后言
本脚本目前处于测试阶段,欢迎反馈问题至 QQ 频道号bettergiv1。
## 七、更新日志
| 版本号 | 更新内容 |
|---------|--------------------------------------------------------------------------|
| v0.1 | 新增OCR名单功能输出图片名与材料名 |
| v1.0 | 新增图包(仅含素材) |
| v1.1 | 图包扩展(素材+养成道具) |
| v1.2 | 新增识图分类功能 |
| v1.3 | 优化:加速材料寻找(新增前位材料识别) |
| v1.31 | 调整本地记录存储逻辑 |
| v1.32 | 新增后位材料识别功能 |
| v2.0 | 开发版:支持多组材料、多个分类;移除前/后位材料识别 |
| v2.1 | 新增CD管理功能 |
| v2.2 | 优化路径顺序、材料数量判断逻辑 |
| v2.21 | 修改路径储存路径 |
| v2.22 | 精简日志输出内容 |
| v2.23 | 优化部分函数性能 |
| v2.24 | 修复“空路径无法使用背包统计”等bug |
| v2.25 | 恢复前/后位材料识别(加速扫描);新增“仅扫描路径材料”选项(降低内存占用) |
| v2.26 | 修复材料时间读取错误;新增路径材料时间成本计算功能 |
| v2.27 | 修复“材料数计算错误”“目标数量临界值异常”“3识别成三”等bug |
| v2.28 | 材料变更时自动更新初始数量排除0位移/0数量路径记录新增材料名0后缀本地记录新增背包弹窗识别 |
| v2.29 | 新增排除提示;调整平均时间成本计算逻辑;过滤异常值记录 |
| v2.30 | 更改路径专注模式默认值;增加日志提示;移除调试日志 |
| v2.40 | 优化背包识别时的内存占用;新增通知功能 |
| v2.41 | 修复“勾选分类的本地记录”bug新增“仅背包统计”选项补充记录损坏处理说明 |
| v2.42 | 新增“无路径间扫描”“noRecord模式”适合成熟路径新增怪物材料CD文件 |
| v2.50 | 新增独立名单拾取、弹窗模块;支持怪物名识别 |
| v2.51 | 自定义设置新增“拖动距离/拖动点”新增月卡弹窗识别路径材料9999自动黑名单修复怪物0收获记录 |

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

View File

@@ -383,7 +383,7 @@ async function scanMaterials(materialsCategory, materialCategoryMap) {
width: 66 + 2 * tolerance,
height: 22 + 2 * tolerance
};
const ocrResult = await recognizeText(ocrRegion, 1000, 10, 10, 3, ra);
const ocrResult = await recognizeText(ocrRegion, 1000, 10, 5, 2, ra);
materialInfo.push({ name, count: ocrResult || "?" });
if (!hasFoundFirstMaterial) {
@@ -509,31 +509,43 @@ const CultivationItemsRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync
const FoodRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync("assets/Food.png"), 845, 31, 38, 38);
const specialMaterials = [
"水晶块", "魔晶块", "星银矿石", "紫晶块", "萃凝晶", "铁块", "白铁块",
"水晶块", "魔晶块", "星银矿石", "紫晶块", "萃凝晶", "虹滴晶", "铁块", "白铁块",
"精锻用魔矿", "精锻用良矿", "精锻用杂矿"
];
function filterLowCountMaterials(pathingMaterialCounts, materialCategoryMap) {
// 将 materialCategoryMap 中的所有材料名提取出来
// 新增超量阈值普通材料9999矿石处理后也是9999
const EXCESS_THRESHOLD = 9999;
// 新增:临时存储本次超量材料
const tempExcess = [];
// 原逻辑:提取所有需要扫描的材料
const allMaterials = Object.values(materialCategoryMap).flat();
// 筛选 pathingMaterialCounts 中的材料,只保留 materialCategoryMap 中定义的材料,并且数量低于 targetCount 或 count 为 "?" 或 name 在 specialMaterials 中
return pathingMaterialCounts
const filteredMaterials = pathingMaterialCounts
.filter(item =>
allMaterials.includes(item.name) &&
(item.count < targetCount || item.count === "?")
)
.map(item => {
// 如果 name 在 specialMaterials 数组中
if (specialMaterials.includes(item.name)) {
// 如果 count 是 "?",直接保留
if (item.count === "?") {
return item;
}
// 否则,将 count 除以 10 并向下取整
item.count = Math.floor(item.count / 10);
// 原逻辑矿石数量÷10
let processedCount = item.count;
if (specialMaterials.includes(item.name) && item.count !== "?") {
processedCount = Math.floor(Number(item.count) / 10);
}
return item;
// 新增:判断是否超量(用处理后数量对比阈值)
if (item.count !== "?" && processedCount >= EXCESS_THRESHOLD) {
tempExcess.push(item.name); // 记录超量材料名
}
return { ...item, count: processedCount };
});
// 新增:更新全局超量名单(去重)
excessMaterialNames = [...new Set(tempExcess)];
log.info(`【超量材料更新】共${excessMaterialNames.length}种:${excessMaterialNames.join("、")}`);
return filteredMaterials; // 原返回值不变
}
function dynamicMaterialGrouping(materialCategoryMap) {

View File

@@ -65,7 +65,7 @@ if (allowedCDCategories.length > 0) {
}
// ==============================================
// 材料与怪物映射管理"XP": "祝圣精华"
// 材料与怪物映射管理
// ==============================================
// 材料分类映射
const material_mapping = {
@@ -384,7 +384,7 @@ function checkPathNameFrequency(resourceName, pathName, recordDir) {
/**
* 记录路径运行时间与材料变化
* @param {string} resourceName - 资源名
* @param {string} resourceName - 资源名(普通材料名/怪物名)
* @param {string} pathName - 路径名
* @param {string} startTime - 开始时间
* @param {string} endTime - 结束时间
@@ -398,8 +398,31 @@ function recordRunTime(resourceName, pathName, startTime, endTime, runTime, reco
const normalContent = `路径名: ${pathName}\n开始时间: ${startTime}\n结束时间: ${endTime}\n运行时间: ${runTime}\n数量变化: ${JSON.stringify(materialCountDifferences)}\n\n`;
try {
if (runTime >= 3) {
// 处理0数量记录
if (runTime >= 3) { // 运行时间≥3秒才处理记录
// ==============================================
// 新增怪物路径专用逻辑判断对应材料总数量是否为0
// ==============================================
const isMonsterPath = monsterToMaterials.hasOwnProperty(resourceName); // 是否为怪物路径
if (isMonsterPath) {
// 1. 获取当前怪物对应的所有目标材料(从已有映射中取)
const monsterTargetMaterials = monsterToMaterials[resourceName] || [];
// 2. 计算这些材料的总数量变化(只累加目标材料,忽略其他无关材料)
let monsterMaterialsTotal = 0;
monsterTargetMaterials.forEach(targetMat => {
monsterMaterialsTotal += (materialCountDifferences[targetMat] || 0);
});
// 3. 若总数量为0生成怪物专用0记录文件文件名含“总0”标识避免混淆
if (monsterMaterialsTotal === 0) {
const zeroMonsterPath = `${recordDir}/${resourceName}${CONSTANTS.ZERO_COUNT_SUFFIX}`;
const zeroMonsterContent = `路径名: ${pathName}\n开始时间: ${startTime}\n结束时间: ${endTime}\n运行时间: ${runTime}\n数量变化: ${JSON.stringify(materialCountDifferences)}\n\n`;
writeContentToFile(zeroMonsterPath, zeroMonsterContent);
log.warn(`${CONSTANTS.LOG_MODULES.RECORD}怪物【${resourceName}】对应材料总数量为0已写入单独文件: ${zeroMonsterPath}`);
}
}
// ==============================================
// 原有普通材料0记录逻辑完全保留不做修改
// ==============================================
for (const [material, count] of Object.entries(materialCountDifferences)) {
if (material === resourceName && count === 0) {
const zeroMaterialPath = `${recordDir}/${material}${CONSTANTS.ZERO_COUNT_SUFFIX}`;
@@ -409,6 +432,9 @@ function recordRunTime(resourceName, pathName, startTime, endTime, runTime, reco
}
}
// ==============================================
// 原有:正常记录生成逻辑(完全保留,不做修改)
// ==============================================
const hasZeroMaterial = Object.values(materialCountDifferences).includes(0);
const isFinalCumulativeDistanceZero = finalCumulativeDistance === 0;
@@ -469,10 +495,10 @@ function getLastRunEndTime(resourceName, pathName, recordDir, noRecordDir) {
/**
* 计算单次时间成本(平均耗时/材料数量)
* @param {string} resourceName - 资源名
* @param {string} resourceName - 资源名(普通材料名/怪物名)
* @param {string} pathName - 路径名
* @param {string} recordDir - 记录目录
* @returns {number|null} 时间成本(秒/null=无法计算
* @returns {number|null} 时间成本(秒/中级单位null=无法计算
*/
function calculatePerTime(resourceName, pathName, recordDir) {
const recordPath = `${recordDir}/${resourceName}.txt`;
@@ -481,22 +507,73 @@ function calculatePerTime(resourceName, pathName, recordDir) {
const lines = content.split('\n');
const completeRecords = [];
for (let i = 0; i < lines.length; i++) {
if (lines[i].startsWith('路径名: ') && lines[i].split('路径名: ')[1] === pathName) {
const runTimeLine = lines[i + 3];
const quantityChangeLine = lines[i + 4];
// ==============================================
// 怪物路径改为以中级材料为基准最低级÷3
// ==============================================
if (monsterToMaterials.hasOwnProperty(resourceName)) {
const monsterMaterials = monsterToMaterials[resourceName]; // 映射顺序:[最高级, 中级, 最低级]
// 新比例最高级×31最高级=3中级中级×1本身最低级×1/33最低级=1中级 → 最低级÷3
const gradeRatios = [3, 1, 1/3];
if (runTimeLine?.startsWith('运行时间: ') && quantityChangeLine?.startsWith('数量变化: ')) {
const runTime = parseInt(runTimeLine.split('运行时间: ')[1].split('')[0], 10);
const quantityChange = JSON.parse(quantityChangeLine.split('数量变化: ')[1]);
for (let i = 0; i < lines.length; i++) {
if (lines[i].startsWith('路径名: ') && lines[i].split('路径名: ')[1] === pathName) {
const runTimeLine = lines[i + 3];
const quantityChangeLine = lines[i + 4];
if (quantityChange[resourceName] !== undefined && quantityChange[resourceName] !== 0) {
completeRecords.push(parseFloat((runTime / quantityChange[resourceName]).toFixed(2)));
if (runTimeLine?.startsWith('运行时间: ') && quantityChangeLine?.startsWith('数量变化: ')) {
// 1. 提取运行时间
const runTime = parseInt(runTimeLine.split('运行时间: ')[1].split('秒')[0], 10);
if (isNaN(runTime) || runTime <= 0) continue;
// 2. 提取数量变化
const quantityChange = JSON.parse(quantityChangeLine.split('数量变化: ')[1]);
// 3. 按新比例计算“总中级单位数量”最低级÷3
let totalMiddleCount = 0; // 变量名改为中级单位
monsterMaterials.forEach((mat, index) => {
const count = quantityChange[mat] || 0;
const ratio = gradeRatios[index] || 1;
totalMiddleCount += count * ratio; // 最低级此处等价于 count ÷ 3
});
// 保留两位小数处理1/3导致的无限小数
totalMiddleCount = parseFloat(totalMiddleCount.toFixed(2));
// 4. 过滤无效数据
if (totalMiddleCount <= 0) continue;
// 5. 计算时间成本(秒/中级单位)
const perTime = parseFloat((runTime / totalMiddleCount).toFixed(2));
completeRecords.push(perTime);
// 日志更新为中级单位
log.debug(`${CONSTANTS.LOG_MODULES.RECORD}怪物【${resourceName}】路径${pathName}${runTime}秒/${totalMiddleCount}中级单位 → ${perTime}秒/单位`);
}
}
}
}
// ==============================================
// 普通材料:完全保留原有逻辑
// ==============================================
else {
for (let i = 0; i < lines.length; i++) {
if (lines[i].startsWith('路径名: ') && lines[i].split('路径名: ')[1] === pathName) {
const runTimeLine = lines[i + 3];
const quantityChangeLine = lines[i + 4];
if (runTimeLine?.startsWith('运行时间: ') && quantityChangeLine?.startsWith('数量变化: ')) {
const runTime = parseInt(runTimeLine.split('运行时间: ')[1].split('秒')[0], 10);
const quantityChange = JSON.parse(quantityChangeLine.split('数量变化: ')[1]);
if (quantityChange[resourceName] !== undefined && quantityChange[resourceName] !== 0) {
completeRecords.push(parseFloat((runTime / quantityChange[resourceName]).toFixed(2)));
}
}
}
}
}
// ==============================================
// 统一的异常值过滤和平均值计算(不变)
// ==============================================
if (completeRecords.length < 3) {
log.warn(`${CONSTANTS.LOG_MODULES.RECORD}路径${pathName}有效记录不足3条无法计算时间成本`);
return null;
@@ -1308,6 +1385,16 @@ ${Object.entries(totalDifferences).map(([name, diff]) => ` ${name}: +${diff}个
const targetTexts = targetTextCategories[categoryName];
allTargetTexts = allTargetTexts.concat(Object.values(targetTexts).flat());
}
// 关键补充等待超量名单生成由filterLowCountMaterials更新
let waitTimes = 0;
while (excessMaterialNames.length === 0 && waitTimes < 300) {
await sleep(1000); // 每1秒查一次
waitTimes++;
}
// 现在过滤才有效确保excessMaterialNames已生成
allTargetTexts = allTargetTexts.filter(name => !excessMaterialNames.includes(name));
log.info(`OCR最终目标文本已过滤超量${allTargetTexts.join('、')}`);
await alignAndInteractTarget(allTargetTexts, fDialogueRo, textxRange, texttolerance);
})();

View File

@@ -1,7 +1,7 @@
{
"manifest_version": 1,
"name": "背包统计采集系统",
"version": "2.5",
"version": "2.51",
"bgi_version": "0.44.8",
"description": "可统计背包养成道具、部分食物、素材的数量根据设定数量、根据材料刷新CD执行挖矿、采集、刷怪等的路径。优势\n+ 1. 自动判断材料CD不需要管材料CD有没有好\n+ 2. 可以随意添加路径,能自动排除低效、无效路径;\n+ 3. 有独立名单识别不会交互路边的npc或是神像可自定义识别名单具体方法看【问题解答】增减识别名单\n+ 4. 有实时的弹窗模块,提供了常见的几种:路边信件、过期物品、月卡、调查;更多详细内容查看reeadme.md",
"saved_files": [

View File

@@ -108,5 +108,20 @@
"name": "CDCategories",
"type": "input-text",
"label": "----------------------------------\n\n采用的CD分类默认:全部)"
},
{
"name": "HoldX",
"type": "input-text",
"label": "------------------------\n(0,0)———> X 增加\n |\n |\n V Y 增加\n\n翻页拖动点X坐标0~1920(默认1050)"
},
{
"name": "HoldY",
"type": "input-text",
"label": "------------------------\n翻页拖动点Y坐标0~1080(默认750)"
},
{
"name": "PageScrollDistance",
"type": "input-text",
"label": "------------------------\n拖动距离(默认711像素点)"
}
]