docs(D.5.3a): spec + plan — selected-object meter (Stream A)

Brainstormed design for the action bar's bottom strip: name + Health meter
on selection (mana deferred #140). Decisions: SelectionChanged via property
setter; send QueryHealth(0x01BF) on select. Grounded in retail
gmToolbarUI::HandleSelectionChanged (acclient_2013_pseudo_c.txt:198635) —
clear-then-populate, overlay state 0x1000000b, health gate
IsPlayer||pet||attackable. Render-bug fix is BuildMeter-only (single-image
back+fill meter; UiMeter already renders it).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Erik 2026-06-18 22:19:14 +02:00
parent d400bc6105
commit e8562fc4e2
2 changed files with 335 additions and 0 deletions

View file

@ -0,0 +1,46 @@
# D.5.3a — Selected-object meter — implementation plan
Spec: `docs/superpowers/specs/2026-06-18-d53a-selected-object-meter-design.md`.
Pre-approved by user 2026-06-18; subagent-driven, sequential (build-safe in one worktree).
Mandatory per task: cite named-retail anchors in comments; `dotnet build` + the relevant
`dotnet test` green; match surrounding code style. No commits by subagents — the lead commits the
coherent set after the full build+test passes.
## Task order (each builds on the accumulated working tree)
### T1 — `WorldSession.SendQueryHealth` (+ net test) · project: `AcDream.Core.Net`
- Add `SendQueryHealth(uint targetGuid)` mirroring `SendChangeCombatMode` (`WorldSession.cs:1134`):
`NextGameActionSequence()``SocialActions.BuildQueryHealth(seq, guid)``SendGameAction(body)`.
- Test in `tests/AcDream.Core.Net.Tests/`: drive it through the existing send-capture seam used by the
other `WorldSession.Send*` tests; assert captured bytes == `BuildQueryHealth(seq, guid)`.
- Accept: `dotnet test` for `AcDream.Core.Net.Tests` green.
### T2 — `DatWidgetFactory.BuildMeter` single-image shape (+ test) · project: `AcDream.App`
- Handle `containers.Count == 1`: `BackLeft = info.StateMedia[""].File`,
`FrontLeft = containers[0].StateMedia[""].File`, tile/right = 0. Keep `>= 2` (vitals) path unchanged.
Warn only on `Count == 0` / `Count > 2`.
- Extend `tests/AcDream.App.Tests/UI/Layout/DatWidgetFactoryTests.cs`: 1-container synthetic meter
asserts Back/Front populated + others 0; 2-container case asserts vitals path unchanged.
- Accept: `dotnet test` for `AcDream.App.Tests` green.
### T3 — `SelectedObjectController` (+ test) · project: `AcDream.App`
- New `src/AcDream.App/UI/Layout/SelectedObjectController.cs` per spec §3 (Bind signature, bind-time
setup, `OnSelectionChanged` clear-then-populate). Cite `HandleSelectionChanged:198635`.
- New `tests/AcDream.App.Tests/UI/Layout/SelectedObjectControllerTests.cs` per spec §Testing item 2
(mirror `ToolbarControllerTests` for building a minimal `ImportedLayout` + recording delegates).
- Accept: `dotnet test` for `AcDream.App.Tests` green.
### T4 — GameWindow integration + register rows · project: `AcDream.App` (depends on T1, T3)
- Convert `_selectedGuid` field → `SelectedGuid` property + `SelectionChanged` event (spec §1); replace
the 3 write sites; leave read sites on the field.
- Remove `0x100001A1` + `0x100001A2` from `ToolbarController.HiddenIds` (keep `0x100001A4`).
- Wire `SelectedObjectController.Bind(...)` after `ToolbarController.Bind` (spec §5).
- Add the 2 divergence rows (spec §Divergence) to
`docs/architecture/retail-divergence-register.md`.
- Accept: full `dotnet build` + `dotnet test` green.
## Then (lead)
- Adversarial Opus review of the full diff vs spec + decomp.
- Commit the coherent set to the branch; update roadmap/ISSUES if applicable; memory if a durable lesson.
- Stop for the user's visual gate (the acceptance test for this stream).