自动黑名单,增加拖动距离,增加月卡弹窗识别 (#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
@@ -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:
|
||||
- 截图2:
|
||||
- 截图3:
|
||||
- 截图4:
|
||||
|
||||
## 更新日志
|
||||
+ 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关键注意点
|
||||
- 手动删除重复路径(例如“萃凝晶”可能存在多个重复路径,需手动清理),参考截图:;
|
||||
- `pathing` 文件夹仅支持**3层子文件夹**,若超过3层需手动削减(否则无法读取);
|
||||
- 推荐优先配置「枫丹水下」路径:无队伍要求,但需提前开启水下锚点。
|
||||
|
||||
#### 步骤3:按队伍分组管理路径
|
||||
建议复制多份「背包材料统计」脚本,按队伍功能分组存放适配路径,避免路径混乱。示例如下:
|
||||
|
||||
| 分组名称 | 适配队伍组合 | 适用场景 | 特殊说明 |
|
||||
|------------------------|-----------------------------------|---------------------------|-----------------------------------|
|
||||
| 背包统计采集组(生存队) | 迪希雅 + 芭芭拉 + 瑶瑶 + 草神 | 常规材料采集 | 无草神时,需批量搜索路径中“nahida_collect”并排除 |
|
||||
| 背包统计刷怪组 | 火神 + 奶奶 + 钟离 + 万叶 | 挂机刷怪(获取怪物材料) | 确保队伍输出足够,能高效清理怪物 |
|
||||
| 背包统计附魔材料组 | 钟离 + 芭芭拉 + 久岐忍 + 砂糖/班尼特 | 附魔类采集(需特定附魔) | 适配需附魔才能获取的材料路径 |
|
||||
|
||||
分组示例参考截图:
|
||||
无草神时排除路径操作参考截图:
|
||||
|
||||
#### 步骤4:打开脚本自定义设置
|
||||
1. 找到「背包材料统计.js」文件;
|
||||
2. 右键点击该文件,选择「JS 修改脚本自定义设置」;
|
||||
3. 操作参考截图:
|
||||
|
||||
|
||||
### 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:如何排除不想要的路径?
|
||||
A:1. 打开 `pathing` 文件夹(脚本路径:`BetterGI\User\JsScript\背包材料统计\pathing`);
|
||||
2. 直接删除/移走目标材料/怪物的路径文件夹;
|
||||
3. **注意**:不要将路径文件放入 `targetText` 或 `materialsCD` 文件夹(这两个文件夹默认全部读取,也会被更新覆盖)。
|
||||
|
||||
### Q2:如何增减识别名单?
|
||||
A:1. 打开 `targetText` 文件夹(脚本路径:`BetterGI\User\JsScript\背包材料统计\targetText`);
|
||||
2. 新建/编辑txt文件,按格式填写:`自定义名称:目标1,目标2`(英文冒号+英文逗号,例:“新材料:霜盏花,便携轴承”);
|
||||
3. 若需排除怪物掉落材料:找到“掉落.txt”,删除对应材料名即可;
|
||||
4. 操作参考截图:
|
||||
- 截图1:
|
||||
- 截图2:
|
||||
|
||||
### Q3:如何识别不规范命名的路径文件夹(如“纳塔食材一条龙”“果园.json”)?
|
||||
A:将不规范的文件夹/文件,放入**适配的材料文件夹**中即可(路径CD由“所在材料文件夹”决定)。
|
||||
例:“果园.json”放入“苹果”文件夹,将按“苹果”的CD规则执行。
|
||||
|
||||
### Q4:如何识别自带CD文件中没有的材料(如新材料、新木头)?
|
||||
A:1. 打开 `materialsCD` 文件夹(脚本路径:`BetterGI\User\JsScript\背包材料统计\materialsCD`);
|
||||
2. 新建/编辑txt文件,按格式填写:`CD规则:材料1,材料2`(中文冒号+中文逗号,CD规则参考自带文件,例:“1次0点:月落银,宿影花”);
|
||||
3. **关键要求**:路径文件夹名、材料图片名必须与“材料1/2”完全一致(多层文件夹默认读取最外层同名文件夹);
|
||||
4. 操作参考截图:
|
||||
- 截图1:
|
||||
- 截图2:
|
||||
|
||||
### Q5:如何避免每次路径执行后都扫描背包?
|
||||
A:在「JS自定义设置」中勾选“取消扫描”(仅保留“全部材料执行始/末”的2次扫描,节约时间)。
|
||||
|
||||
### Q6:扫描背包少一行、拖动距离异常怎么办?
|
||||
A:在「JS自定义设置」中调整“拖动距离”,直到“一次划页仅显示≤4行材料”(拖动点建议选第5行材料附近)。
|
||||
|
||||
### Q7:本地记录保存在哪里?
|
||||
A:记录文件夹位于 `BetterGI\User\JsScript\背包材料统计\` 下,各文件功能如下:
|
||||
- `overwrite_record`:所有历史记录(按材料分类储存);
|
||||
- `history_record`:勾选“材料分类”后的专属记录;
|
||||
- `latest_record.txt`:最近几种材料的记录(有上限,仅存最新数据);
|
||||
- `pathing_record`:单个路径的完整记录(含运行时间、收获量,需重点备份);
|
||||
操作参考截图:
|
||||
|
||||
|
||||
## 六、后言
|
||||
本脚本目前处于测试阶段,欢迎反馈问题至 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收获记录 |
|
||||
BIN
repo/js/背包材料统计/assets/Pic/Pic01.png
Normal file
|
After Width: | Height: | Size: 3.6 KiB |
BIN
repo/js/背包材料统计/assets/Pic/Pic02.png
Normal file
|
After Width: | Height: | Size: 7.9 KiB |
BIN
repo/js/背包材料统计/assets/Pic/Pic03.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
repo/js/背包材料统计/assets/Pic/Pic04.png
Normal file
|
After Width: | Height: | Size: 5.9 KiB |
BIN
repo/js/背包材料统计/assets/Pic/Pic05.png
Normal file
|
After Width: | Height: | Size: 9.6 KiB |
BIN
repo/js/背包材料统计/assets/Pic/Pic06.png
Normal file
|
After Width: | Height: | Size: 6.6 KiB |
BIN
repo/js/背包材料统计/assets/Pic/Pic07.png
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
BIN
repo/js/背包材料统计/assets/Pic/Pic08.png
Normal file
|
After Width: | Height: | Size: 6.5 KiB |
BIN
repo/js/背包材料统计/assets/Pic/Pic09.png
Normal file
|
After Width: | Height: | Size: 5.6 KiB |
BIN
repo/js/背包材料统计/assets/Pic/Pic10.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
repo/js/背包材料统计/assets/Pic/Pic11.png
Normal file
|
After Width: | Height: | Size: 4.3 KiB |
BIN
repo/js/背包材料统计/assets/Pic/Pic12.png
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
repo/js/背包材料统计/assets/Pic/Pic13.png
Normal file
|
After Width: | Height: | Size: 5.1 KiB |
@@ -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) {
|
||||
|
||||
@@ -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]; // 映射顺序:[最高级, 中级, 最低级]
|
||||
// 新比例:最高级×3(1最高级=3中级),中级×1(本身),最低级×1/3(3最低级=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);
|
||||
})();
|
||||
|
||||
|
||||
@@ -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": [
|
||||
|
||||
@@ -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像素点)"
|
||||
}
|
||||
]
|
||||