diff --git a/repo/js/背包材料统计/README.md b/repo/js/背包材料统计/README.md index e8a58af18..24f12dbc1 100644 --- a/repo/js/背包材料统计/README.md +++ b/repo/js/背包材料统计/README.md @@ -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:如何排除不想要的路径? +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:![](assets/Pic/Pic12.png) + - 截图2:![](assets/Pic/Pic10.png) + +### 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:![](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收获记录 | \ No newline at end of file diff --git a/repo/js/背包材料统计/assets/Pic/Pic01.png b/repo/js/背包材料统计/assets/Pic/Pic01.png new file mode 100644 index 000000000..5da22ed6b Binary files /dev/null and b/repo/js/背包材料统计/assets/Pic/Pic01.png differ diff --git a/repo/js/背包材料统计/assets/Pic/Pic02.png b/repo/js/背包材料统计/assets/Pic/Pic02.png new file mode 100644 index 000000000..577d37399 Binary files /dev/null and b/repo/js/背包材料统计/assets/Pic/Pic02.png differ diff --git a/repo/js/背包材料统计/assets/Pic/Pic03.png b/repo/js/背包材料统计/assets/Pic/Pic03.png new file mode 100644 index 000000000..2f0da0290 Binary files /dev/null and b/repo/js/背包材料统计/assets/Pic/Pic03.png differ diff --git a/repo/js/背包材料统计/assets/Pic/Pic04.png b/repo/js/背包材料统计/assets/Pic/Pic04.png new file mode 100644 index 000000000..77f36940a Binary files /dev/null and b/repo/js/背包材料统计/assets/Pic/Pic04.png differ diff --git a/repo/js/背包材料统计/assets/Pic/Pic05.png b/repo/js/背包材料统计/assets/Pic/Pic05.png new file mode 100644 index 000000000..e3eba03c6 Binary files /dev/null and b/repo/js/背包材料统计/assets/Pic/Pic05.png differ diff --git a/repo/js/背包材料统计/assets/Pic/Pic06.png b/repo/js/背包材料统计/assets/Pic/Pic06.png new file mode 100644 index 000000000..4fb09bb1f Binary files /dev/null and b/repo/js/背包材料统计/assets/Pic/Pic06.png differ diff --git a/repo/js/背包材料统计/assets/Pic/Pic07.png b/repo/js/背包材料统计/assets/Pic/Pic07.png new file mode 100644 index 000000000..7112a7d6a Binary files /dev/null and b/repo/js/背包材料统计/assets/Pic/Pic07.png differ diff --git a/repo/js/背包材料统计/assets/Pic/Pic08.png b/repo/js/背包材料统计/assets/Pic/Pic08.png new file mode 100644 index 000000000..9a7d7589f Binary files /dev/null and b/repo/js/背包材料统计/assets/Pic/Pic08.png differ diff --git a/repo/js/背包材料统计/assets/Pic/Pic09.png b/repo/js/背包材料统计/assets/Pic/Pic09.png new file mode 100644 index 000000000..56f68ff47 Binary files /dev/null and b/repo/js/背包材料统计/assets/Pic/Pic09.png differ diff --git a/repo/js/背包材料统计/assets/Pic/Pic10.png b/repo/js/背包材料统计/assets/Pic/Pic10.png new file mode 100644 index 000000000..a03654234 Binary files /dev/null and b/repo/js/背包材料统计/assets/Pic/Pic10.png differ diff --git a/repo/js/背包材料统计/assets/Pic/Pic11.png b/repo/js/背包材料统计/assets/Pic/Pic11.png new file mode 100644 index 000000000..4deaa4574 Binary files /dev/null and b/repo/js/背包材料统计/assets/Pic/Pic11.png differ diff --git a/repo/js/背包材料统计/assets/Pic/Pic12.png b/repo/js/背包材料统计/assets/Pic/Pic12.png new file mode 100644 index 000000000..a4af8f4e5 Binary files /dev/null and b/repo/js/背包材料统计/assets/Pic/Pic12.png differ diff --git a/repo/js/背包材料统计/assets/Pic/Pic13.png b/repo/js/背包材料统计/assets/Pic/Pic13.png new file mode 100644 index 000000000..9d5f51b31 Binary files /dev/null and b/repo/js/背包材料统计/assets/Pic/Pic13.png differ diff --git a/repo/js/背包材料统计/lib/backStats.js b/repo/js/背包材料统计/lib/backStats.js index ed28cd14b..d991a8d02 100644 --- a/repo/js/背包材料统计/lib/backStats.js +++ b/repo/js/背包材料统计/lib/backStats.js @@ -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) { diff --git a/repo/js/背包材料统计/main.js b/repo/js/背包材料统计/main.js index 0e82ec419..a96f2eb4d 100644 --- a/repo/js/背包材料统计/main.js +++ b/repo/js/背包材料统计/main.js @@ -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); })(); diff --git a/repo/js/背包材料统计/manifest.json b/repo/js/背包材料统计/manifest.json index c528fa380..5668777cd 100644 --- a/repo/js/背包材料统计/manifest.json +++ b/repo/js/背包材料统计/manifest.json @@ -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": [ diff --git a/repo/js/背包材料统计/settings.json b/repo/js/背包材料统计/settings.json index 46bb98572..10b129e01 100644 --- a/repo/js/背包材料统计/settings.json +++ b/repo/js/背包材料统计/settings.json @@ -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像素点)" } ] \ No newline at end of file