Files
mtgodot-poc/audit/contracts/ui.hud-target-minimap-status.md
T
shenandshen c93894313a fix: 装备属性面板避让逻辑 + 多项功能更新
- item_tooltip_view.gd: 新增 avoid_rect 属性,tooltip 与装备窗口重叠时自动推到左侧
- inventory_ui.gd: 悬停装备时传入窗口矩形作为避让区域
- 包含其他累积的功能开发和测试文件
2026-09-21 16:38:59 -07:00

99 lines
11 KiB
Markdown
Raw 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.
# ui.hud_target_minimap_status —— 角色状态、目标框、小地图、文本尾标和快捷栏
状态:`PARTIAL`
本合同检查 HUD 的数据源、UI 实例注册、刷新顺序、目标类型分派、HP/EXP/等级、名字尾标、聊天气泡、小地图标记/缩放、快捷栏和死亡/删除/换图清理。静态模块测试通过,只能证明局部 helper;正式 `GameScene` 中实际创建了哪些控件、信号是否接通、旧控件是否重复显示,必须单独核对。
## 40250 参考调用链
- `UserInterface/PythonApplication.cpp` / `PythonApplication.h`
- 每帧按应用渲染顺序更新 PythonPlayer、TextTail、Effect 和 UI;TextTail 先刷新全部尾标,再显示目标/拾取/全显尾标,最后更新显示和排布。
- `UserInterface/PythonPlayer.cpp` / `PythonPlayer.h`
- `SetStatus` 写入带保护的点数组;等级变化同步 `CInstanceBase::SetLevel` 和等级尾标,战斗点变化触发派生战斗状态重算。
- `SetQuickPage` 按 `QUICKSLOT_MAX_LINE` 环绕,快捷栏按全局槽位保存,使用时区分 inventory/skill/emotion 并经网络发送。
- 目标死亡、删除和不可选中时清理目标;`UpdatePartyMemberInfo/Affect` 更新队伍状态和头像/尾标数据。
- `UserInterface/PythonTextTail.cpp` / `.h`
- 维护角色、聊天、信息、掉落尾标的 map/list/pool;角色尾标由 `RegisterCharacterTextTail` 建立,按 guild/title/level 资源更新;聊天尾标 5000ms 到期,`bNameFlag` 会强显名字并把名字上移 17px;物品尾标按屏幕 AABB 互相下推。
- `DeleteCharacterTextTail`、死亡分支和地图清理必须同时删除角色名、公会/称号/等级、聊天和物品 owner 子实例。
- `UserInterface/PythonMiniMap.cpp` / `.h`
- 默认 `m_fScale=2.0`,`SetScale` 范围 `[0.5,4.0]`,ScaleUp/Down 分别乘 2/0.5;以 terrain cell/cm 坐标计算玩家、PC、怪物、NPC/warp、observer、guild area、waypoint/target mark 和玩家朝向。
- `__SetPosition`、`Render`、地图中心及点击拾取都使用同一 scale/terrain-cell 单位,并按边缘半径处理超出地图的 waypoint。
- `UserInterface/PythonPlayer.cpp`、`PythonApplication.cpp`、`uitaskbar.py` / `uicharacter.py` / `uitarget.py`
- TaskBar/CharacterWindow/TargetBoard 由统一 UI 入口创建并接收 points、target、quickslot、party 和 entity 删除事件,不允许只保留“存在但未注入”的独立控件。
## 当前端实现映射
- `project/net_play.gd` / `project/hud.gd` / `project/ui/quickbar.gd`
- native `points_changed`/`vitals_changed`/`target_info` 已接入 NetPlay;NetPlay 将 HP/SP/ST/EXP/等级写入 HUD,Quickbar 自己也订阅 `points_changed` 并绘制 4 段经验珠、HP/SP/ST 和 36 槽服务端快捷栏。
- `hud.gd::_build_status()` 已经是空实现,旧 HUD 的 setters 只有在 Quickbar 存在时才产生可见效果;这是一次“数据链存在但显示 owner 分散”的适配层。
- `project/ui/target_board.gd` / `project/ui/target_ui.gd`
- `target_board.gd` 已镜像 `RecvTargetPacket` 的 CLOSE/CLOSE_IF_DIFFERENT/SET_HP/NONE 判定,`target_ui.gd` 已实现宽度、等级/阶级前缀、HP、PC 操作按钮和关闭回调。
- 但正式 `project/game_scene.gd` 只把 `target_changed` 连接到 `net_world.set_target_vid`,没有创建 `target_ui.gd` 实例,也没有设置 `net_play.target_ui`;实际运行的目标面板退回 `hud.gd` 的简化 200×40 面板,缺少 40250 TargetBoard 的运行链。
- `project/net_world.gd` / `project/text_tail.gd` / `project/text_tail_arrange.gd` / `project/chat_tail.gd`
- 已实现角色名字、guild/title/level、guild mark、聊天/信息尾标、5000ms 生命周期、目标/悬停强显和掉落名条 AABB 排布;测试覆盖了静态颜色、标题、聊天和物品尾标 helper。
- 当前 `CanPickInstance` 仍用存活/墙体近似,尾标强制显示和名字可见性整表刷新约 2Hz,而 40250 在渲染帧内按实例资格和 list 重建;真实字体/Label3D 像素度量也有 fallback 近似。
- `project/ui/minimap.gd` / `project/hud.gd` / `project/game_scene.gd`
- `minimap.gd` 已绘制实体、NPC/warp、observer、guild area、quest signal、target marker、坐标和玩家箭头,并连接 channel/world reset;`hud.gd` 另有一套基于 `minimap.dds` 的旧地图贴图与玩家点。
- 正式 `GameScene` 同时调用 `hud.setup()`(创建旧 minimap)和 `minimap.setup()`(创建新雷达),没有销毁/隐藏其中一套,存在重复小地图;新雷达 scale 默认 0.25、范围 0.10–1.25、按钮步进 ±0.05/滚轮 1.15,与 40250 默认 2.0、范围 0.5–4.0、按钮 ×2/×0.5 的行为和单位不一致。
- `project/ui/char_status_ui.gd`
- 已支持状态/技能/表情/任务页、points 读取、装备/技能资源、加点命令和移动端页;`char_status_ui_test.gd` 证明基础布局/刷新/Tab/加点路径。
## 分支等价矩阵
| 40250 判据/副作用 | 当前实现 | 结论 |
|---|---|---|
| points/status → TaskBar HP/SP/ST/EXP/等级刷新 | NetPlay 和 Quickbar 都可接收 points,Quickbar 绘制主要仪表 | 部分等价;HUD 状态 owner 分散,`_build_status()` 空实现,等级/旧 setter 的可见链没有统一快照 |
| QuickSlot 全局槽位、页切换、inventory/skill/emotion 分派 | `_state` 36 槽、4×8 页、服务端恢复和激活分支存在 | 基础路径通过;最后 4 个服务端槽、物品引用失效、死亡/变身门控和资源图标完整时序仍需 live packet 证据 |
| `RecvTargetPacket` 按 PC/building/stone/enemy/NPC/死亡分派 | `target_board.gd` 和 `net_play._on_target_info` 静态/单测通过 | 判定 helper 基本等价;生产 `target_ui` 未实例化注入,实际 UI 运行链不等价 |
| TargetBoard 宽度、等级/阶级、HP、PC 私聊/交易/装备按钮 | `ui/target_ui.gd` 单测通过 | 代码存在但正式场景未挂载;当前可见 HUD 面板是简化实现 |
| 角色 guild/title/level、聊天/信息尾标、5000ms 回收 | `net_world` + TextTail/ChatTail + 2Hz 可见性刷新 | 部分等价;`CanPickInstance`、逐帧 list 生命周期、字体真实度量和死亡/删除全链仍有近似 |
| 掉落物 owner 名、AABB 去重叠和拾取 | `ground_items` + `text_tail_arrange` | helper 通过;实际投影、字体、删除和鼠标拾取尚未与 native 渲染逐像素对照 |
| 小地图 scale、地形单位、玩家/实体/observer/waypoint/target/guild mark | 新 `minimap.gd` 覆盖大部分标记和 observer 插值 | 不等价;scale 常量/步进/单位不同,且 HUD 与新 Minimap 同时显示两套地图 |
| 场景创建、目标/小地图/尾标的统一 owner | GameScene 分散创建 HUD、Minimap、NetWorld、NetPlay | 不等价;TargetUI 漏接入,MiniMap 重复创建,跨图/退出时 UI 节点清理未形成统一证据 |
| 角色死亡、实体删除、换图清理 | NetWorld 清理 HP bars、尾标、target、实体;NetPlay 清理 target | 部分等价;需补生产场景级删除/换图后无重复 UI、无悬挂 signal 的测试 |
## 已执行测试
- `project/test_target_board_parity.gd`:13 passed、0 failed;覆盖 TargetBoard 尺寸、HP、关闭回调和手工注入 `target_ui` 的 NetPlay 分派。
- `project/target_board_test.gd`:通过;覆盖目标分类、死亡、异阵营和 LCONTROL 私聊分支。
- `project/test_minimap_radar_parity.gd`:6 passed、0 failed;`project/p9_test.gd` 通过;只证明新雷达坐标、按钮、Atlas 信号和基础 world/observer 路径,不检测 GameScene 同时存在两套 minimap,也没有校验 40250 scale 常量。
- `project/text_tail_test.gd`、`project/text_tail_arrange_test.gd`、`project/chat_tail_test.gd`、`project/chat_test.gd`、`project/name_show_test.gd`:均通过;这些是 helper/路由测试,未证明完整 native 渲染帧顺序和 `CanPickInstance` 等价。
- `project/char_status_ui_test.gd`:通过;覆盖布局、状态刷新、加点和分页。
- `project/test_taskbar_quickslot_parity.gd`:34 passed、0 failed;Quickbar/TaskBar 断言通过,但进程报告 221 个 ObjectDB、91 个 CanvasItem RID、3 个资源仍在使用,不能作为稳定清理证据。
- `project/taskbar_dock_test.gd`:通过;覆盖任务栏按钮、角色窗 Tab 和安全箱窗口。
## Deep audit round 2026-09-21
### Fresh regression results
- `test_target_board_parity.gd` 13/13、`target_board_test.gd`、`test_minimap_radar_parity.gd` 6/6、`p9_test.gd`、`text_tail_test.gd`、`text_tail_arrange_test.gd`、`chat_tail_test.gd`、`chat_test.gd`、`name_show_test.gd`、`char_status_ui_test.gd`、`taskbar_dock_test.gd` 均退出码 0。
- `test_taskbar_quickslot_parity.gd` 34/34,但退出时仍有 221 个 ObjectDB、91 个 CanvasItem RID、3 个资源、56 个 shaped-text RID 和 1 个 font RID 泄漏。
### Static parity conclusion
- TargetBoard 单测和手工注入的 `target_ui` 分派通过,但正式 `GameScene` 仍未实例化/注入唯一 TargetUI,实际显示路径仍可能回落到 HUD 简化目标条。
- HUD 与新 minimap 仍是两套生产 owner;新雷达的 scale 默认/范围/步进与 40250 的 2.0、0.5–4.0、×2/×0.5 不一致。
- TextTail、血条、快捷栏和角色状态 helper 可用,但逐帧显示顺序、真实字体度量、删除/死亡/换图清理和统一 points/target/quickslot owner 仍未闭合。
本轮仍为 `PARTIAL`,完成 HUD/目标框/小地图/尾标第二轮证据登记,未修改实现。
## 已确认差异和未验证项
1. 在正式 GameScene 创建并注入唯一的 `TargetUI`,将 `NetPlay.target_ui` 的 open/set_hp/close 与 TargetBoard 分派接通;再移除/隐藏 HUD 简化目标条,避免两个目标面板 owner。
2. 只保留一套生产小地图,统一参考端的 scale/terrain-cell 单位、默认值、上下限、按钮倍率、滚轮和地图/雷达切换行为。
3. 将 points、quickslot、target、party、entity delete、world reset 的 UI 更新集中到可观测 owner,补生产场景级重复创建、换图、死亡、重连和退出清理测试。
4. 逐帧对照 TextTail 的 `UpdateAllTextTail → Show* → UpdateShowingTextTail → ArrangeTextTail`,消除 `CanPickInstance` 近似、2Hz 可见性延迟和 Label3D 字体度量 fallback。
5. 补真实资源/网络包驱动的 HP/EXP/等级/快捷栏/小地图 marker 测试;修复 Quickbar 测试的 ObjectDB/RID/resource cleanup。
## 下一轮验证入口
- 先修复/验证 GameScene 的 TargetUI 单例注入和旧 HUD 目标条去重。
- 再以一个地图、一个远端 PC、一个敌对怪、一个 NPC/warp、一个 observer 和一条 quest waypoint 采集新旧客户端同帧 UI 快照。
- 最后验证 mini-map scale 边界、实体删除/死亡/换图/重连后的尾标、血条、目标框和小地图无残留。
## Active UserInterface minimap and text-tail bridge review
- `PythonMiniMapModule.cpp` 暴露小地图 scale/center/size、创建/销毁/更新/拾取、atlas、waypoint、guild area 和地图 marker;这些状态依赖地图坐标、地形/atlas 资源和实体删除顺序。
- `PythonTextTailModule.cpp` 暴露角色/聊天/信息尾标注册、标题颜色、投影位置、显示/隐藏、排列和 pick;生产更新必须先更新全部尾标,再更新可见集合和排列,不能由单个 Label3D 的定时器替代。
- 当前端 minimap/text-tail 有 helper 和局部布局测试,但生产 owner、marker/waypoint 删除、实体重置、投影失败和资源字体度量未闭合;本轮纳入 active source 证据,合同继续 `PARTIAL`。