Files
2026-10-15 23:11:31 +09:00

75 lines
6.2 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# AVA2 自动洗练适配进度(v1 + 属性锁定)
2026-10-15。修改了 metin2-client 和 metin2-server,AVA2 代码只作参考。服务端规则和协议见 `metin2-server/docs/FEATURE-SWITCHBOT.md`。
## 与 AVA2 的差异
| 项目 | AVA2 | 本实现 |
| --- | --- | --- |
| 窗口 | 新增 SWITCHBOT 物品窗口,5 个物品槽加 1 个道具槽 | 不新增窗口类型,物品留在背包,按物品 ID 绑定;每个角色同一时间只洗 1 件 |
| 洗练执行 | 自己实现消耗和 ChangeAttribute,绕过手动检查和 ItemLog | 每次都调用原 `UseItem`,检查、概率、日志、扣道具都和手动洗练一样;71151/76023 仍只能洗等级上限 ≤40 的武器和衣服 |
| 速度 | 0.1 秒一次 | 0.25 秒一次(约 4 次/秒) |
| 物品被移动 | 拦截移动、交易、出售等路径 | 每次洗练前重新检查:物品不在背包、已装备、易主时停止(item_gone);交易、商店、仓库、合成界面打开时停止(busy) |
| 换线 / 下线 | 通过 P2P 转移,继续洗 | 直接停止,不离线洗练 |
匹配规则和 AVA2 相同:最多 2 套方案,每套 1–5 条“属性 ≥ 阈值”;任意一套全部达标就停止,只看前 5 条普通属性。
## 客户端
- 模块 `mt_switchbot`(`src/platform/ScriptLib/SwitchbotScript.inc`),在 `PythonBoot.cpp` 中安装。入口是小地图旁“百科”按钮下方的“洗练”按钮。
- 物品:扫描背包里至少有一条属性的武器和防具,用 `<` `>` 切换。洗练道具:扫描子类型为 USE_CHANGE_ATTRIBUTE 的道具,显示数量。次数上限可选 10、50、100、200、500、1000。
- 可选属性和最大值由服务端 `attrs` 下发,客户端不自己推算。添加属性时分页点选;阈值用 -/+ 调整,步长为最大值的 1/5,默认取最大值。
- 运行时锁定所有设置,实时显示次数、剩余道具、停止原因和当前 5 条属性。停止时在聊天框提示;达标时如果窗口已关闭,会自动打开。
- 命令间隔至少 0.3 秒,同一时间只有一个请求在等待回复。4 秒没有回复就显示“服务器尚未启用自动洗练”。`attrs` 只接受完整、连续的回复,不完整的整批丢弃。
- 文字都用 GBK 可编码的字符(不用 ◀/▶/⚠)。
## 属性锁定(2026-10-15)
- 服务端规则、存储和协议见 `metin2-server/docs/FEATURE-ATTR-LOCK.md`。锁定的槽位在所有洗练方式下都保持不变:手动用道具、自动洗练、GM 命令。
- 窗口底部“开始/停止”右边有 5 个按钮,每条有属性的普通槽一个:`锁N` 表示未锁,`【锁N】` 表示已锁。点击切换。选属性时和洗练中不能点。
- 当前属性行里,已锁的属性前面加 `[锁]`。状态行提示“已锁定的属性在每次洗练中保持不变”。
- 服务端在 `attrs_end` 之后下发 `MTSB1 lock CELL VNUM MASK`。旧服务端不发这一行,所以不显示按钮。
- 错误提示:`slot`(该条属性不能锁定),`max`(最多锁定 2 条,且至少留 1 条可洗),`db`(保存失败)。
- 与 AVA2 的差异:
- 锁定免费。AVA2 每次锁定或解锁消耗 50348/50349,203 的 item_proto 里没有这两个道具。
- 锁定状态存在服务端独立表里,不占属性槽。
- 不要求物品正好有 5 条属性,但至少要留 1 条不锁。
- 联机测试(channel5 13040,盔甲 11209,背包 19 格):
- 锁第 2、4 条后,自动洗 10 次,这两条每次都不变,其余 3 条每次都变;
- 锁第 3 组时提示 max;
- 重新登录后锁定状态仍在;
- 解锁后表里的行被删除。
## 证据
- `tests/wiki/test_switchbot.py`(CTest:`port.switchbot`)共 7 项通过(第 7 项是锁定协议和按钮),覆盖:
- 请求节流和合并;
- 不完整的 attrs 回复被拒绝;
- start 命令的拼装和校验;
- state/error 解析和超时;
- 和服务端的原因码、错误码、上限一致;
- 窗口流程:扫描 → 读取属性 → 选属性 → 开始 → 达标提示。
- 脚本能在 Python 2.7 下编译。`tests/wiki/test_service.py` 仍然通过。
- 2026-10-15 联机测试(203 额外开的测试核心 channel5/first,端口 13040,使用隔离编译的 game;macOS 原生客户端,账号 admin,物品为背包 33 格的剑 279,道具 71084):
- 上限 10 次:洗满 10 次后停止(limit),约 4 次/秒。
- 两套方案、阈值 1:第 18 次达标(matched)。
- 已经达标的物品:0 次就停止,不扣道具。
- 洗练中把物品从 33 格移到 90 格:继续洗,窗口跟到 90 格;点停止后显示 stopped。
- 洗练中退出客户端:服务端立即停止。
- log.log 中 CHANGE_ATTRIBUTE 共 72 行,和总次数一致。
- busy:洗练中摆摊(先给 50200 摊位包袱;没有它 `OpenMyShop` 会提前返回、摊位不会开,第一次测试就是这样误判的),摊位开出约 1 秒后停止(busy),共洗 6 次。
- no_scroll:用 76014(共 6 张)、上限 10,洗 6 次后停止(no_scroll),道具剩 0。
- rejected:对 90 级剑用 71151(原路径只允许等级 <= 40):0 次就停止(rejected),道具未扣。
- 截图里窗口布局正常。仓库自带的 `Client` 是英文 cp1252 locale,所以中文显示为 `????`;需要 zh locale 客户端才能看到中文。
- 联机测试发现并修复了两个窗口问题,`test_switchbot.py` 已加回归用例:
- 洗练中移动物品后,选中项会跳到别的物品:现在按服务端报告的格子跟随。
- 空闲时移动物品后选中项丢失:现在退而按相同 vnum 匹配。
- 服务端 `tests/features/test_switchbot.py` 和 `test_queries.py` 通过。203 的隔离目录 `/root/metin2-features-dev` 完整编译通过。
## 未完成
- Android 真机测试。
- macOS 构建需要 `-DMT_40250_SOURCE=<含 EterPack/EterPack.cpp 的源码目录>` 来生成 pack 密钥,否则 system.py 读不出来(RunMain Error)。本机没有 40250 源码,这次用的是 AVA2 的 `TEST/3. Source BIN/Client`,两者密钥相同。
- 服务端还没有部署到 203 正式环境。
- 属性锁定已完成(见上),2026-10-15 16:08 已部署到 203 正式环境(服务端 dc71593),CH1 联机验收通过。