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

11 KiB
Raw Blame History

ui.hud_target_minimap_status —— 角色状态、目标框、小地图、文本尾标和快捷栏

状态:PARTIAL

本合同检查 HUD 的数据源、UI 实例注册、刷新顺序、目标类型分派、HP/EXP/等级、名字尾标、聊天气泡、小地图标记/缩放、快捷栏和死亡/删除/换图清理。静态模块测试通过,只能证明局部 helper;正式 GameScene 中实际创建了哪些控件、信号是否接通、旧控件是否重复显示,必须单独核对。

40250 参考调用链

  • UserInterface/PythonApplication.cpp / PythonApplication.h
    • 每帧按应用渲染顺序更新 PythonPlayer、TextTail、Effect 和 UITextTail 先刷新全部尾标,再显示目标/拾取/全显尾标,最后更新显示和排布。
  • UserInterface/PythonPlayer.cpp / PythonPlayer.h
    • SetStatus 写入带保护的点数组;等级变化同步 CInstanceBase::SetLevel 和等级尾标,战斗点变化触发派生战斗状态重算。
    • SetQuickPageQUICKSLOT_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.0SetScale 范围 [0.5,4.0]ScaleUp/Down 分别乘 2/0.5;以 terrain cell/cm 坐标计算玩家、PC、怪物、NPC/warp、observer、guild area、waypoint/target mark 和玩家朝向。
    • __SetPositionRender、地图中心及点击拾取都使用同一 scale/terrain-cell 单位,并按边缘半径处理超出地图的 waypoint。
  • UserInterface/PythonPlayer.cppPythonApplication.cppuitaskbar.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 已接入 NetPlayNetPlay 将 HP/SP/ST/EXP/等级写入 HUDQuickbar 自己也订阅 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 resethud.gd 另有一套基于 minimap.dds 的旧地图贴图与玩家点。
    • 正式 GameScene 同时调用 hud.setup()(创建旧 minimap)和 minimap.setup()(创建新雷达),没有销毁/隐藏其中一套,存在重复小地图;新雷达 scale 默认 0.25、范围 0.101.25、按钮步进 ±0.05/滚轮 1.15,与 40250 默认 2.0、范围 0.54.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 都可接收 pointsQuickbar 绘制主要仪表 部分等价;HUD 状态 owner 分散,_build_status() 空实现,等级/旧 setter 的可见链没有统一快照
QuickSlot 全局槽位、页切换、inventory/skill/emotion 分派 _state 36 槽、4×8 页、服务端恢复和激活分支存在 基础路径通过;最后 4 个服务端槽、物品引用失效、死亡/变身门控和资源图标完整时序仍需 live packet 证据
RecvTargetPacket 按 PC/building/stone/enemy/NPC/死亡分派 target_board.gdnet_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.gd13 passed、0 failed;覆盖 TargetBoard 尺寸、HP、关闭回调和手工注入 target_ui 的 NetPlay 分派。
  • project/target_board_test.gd:通过;覆盖目标分类、死亡、异阵营和 LCONTROL 私聊分支。
  • project/test_minimap_radar_parity.gd6 passed、0 failedproject/p9_test.gd 通过;只证明新雷达坐标、按钮、Atlas 信号和基础 world/observer 路径,不检测 GameScene 同时存在两套 minimap,也没有校验 40250 scale 常量。
  • project/text_tail_test.gdproject/text_tail_arrange_test.gdproject/chat_tail_test.gdproject/chat_test.gdproject/name_show_test.gd:均通过;这些是 helper/路由测试,未证明完整 native 渲染帧顺序和 CanPickInstance 等价。
  • project/char_status_ui_test.gd:通过;覆盖布局、状态刷新、加点和分页。
  • project/test_taskbar_quickslot_parity.gd34 passed、0 failedQuickbar/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.gdtest_minimap_radar_parity.gd 6/6、p9_test.gdtext_tail_test.gdtext_tail_arrange_test.gdchat_tail_test.gdchat_test.gdname_show_test.gdchar_status_ui_test.gdtaskbar_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.54.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