fix(ui): complete live targeted healing flow

Route ACE server commands through the existing chat path, bind the retail paperdoll hit mask instead of its obscured viewport, and prefer authoritative private health vitals. Record the user-confirmed live gate and pin the production DAT widget type in tests.
This commit is contained in:
Erik 2026-07-11 07:58:59 +02:00
parent eb6229394a
commit 05f6222865
11 changed files with 181 additions and 24 deletions

View file

@ -484,7 +484,7 @@ behavior. Estimated 1726 days focused work, 35 weeks calendar.
- **D.5 remaining — sub-phase ledger.** D.5.1 (toolbar + the `UiItemSlot`/`UiItemList`/`IconComposer` spine) ✅, D.5.2 (stateful icons) ✅, D.5.4 (client object/item data model) ✅, D.2b-B window manager (`abbd97b`) ✅, D.2b-B B-Grid (inventory sub-window mount + `UiItemList` grid) ✅, D.2b-B B-Controller (inventory population + burden meter + captions, `03fbf44`; **visually confirmed 2026-06-21** — two render bugs fixed at the gate `417b137`: backdrop wash-out [a #145 continuation — mounted sub-window slots must keep their own frame ZLevel, not inherit the base root's 1000] + captions [drive the host UiText directly]) ✅, D.2b-B B-Wire (`EncumbranceVal`/PropertyInt 5 wire delivery, AP-48/49 retired) ✅, inventory window finish Stage 1 (scroll/frame/vertical-resize/102-slot grid) ✅, empty-slot art ✅, container-switching + open/selected indicators + main-pack icon + per-bag capacity bar ✅, B-Drag (inventory drag-drop / item moving) ✅, **Sub-phase C (paperdoll): Slice 1 equip slots ✅ + Slice 2 3-D doll `UiViewport` (Type 0xD via the `IUiViewportRenderer` RTT seam) + Slots toggle ✅ (visually confirmed 2026-06-25, `8fa66c2` — pose/camera/heading all retail-verbatim)** ✅, **UI Studio** (`AcDream.App ui-studio`) ✅, **importer dat-fidelity (Fix A/B/C)** ✅, **Character window** (`LayoutDesc 0x2100002E`, `CharacterStatController`) ✅, **Wave 3.1 unified selection** (Core `SelectionState`; AP-58 retired) ✅, and **Wave 3.2 pure item-use/drop policy** (`ItemInteractionPolicy`; AP-99 retired) ✅ are shipped. Build order from here: **finish Wave 3 activation router/cursors, then D.5.3 selected-object mana + stack entry/slider and the separate favorite-spell bars; ISSUES #146/#147/#197.** Each ☐ below gets its own focused oracle/spec/plan/gate.
- **✓ SHIPPED — UI Studio** (2026-06-26, branch `claude/hopeful-maxwell-214a12`, ~33693c6→HEAD). Standalone `AcDream.App ui-studio <datdir> [--layout 0xNNNN | --dump <slug>] [--screenshot <png>]` Silk tool that previews any panel through the **production renderer** (`RenderBootstrap.cs` + GameWindow untouched). Sources: 26-window retail dump (`docs/research/2026-06-25-retail-ui-layout-dump.json`) via `--dump`, or live dat import + fixtures via `--layout`. Interactive canvas (click-routing to `UiHost`, Interact/Inspect ImGui toggle), headless `--screenshot`. Architecture: `src/AcDream.App/Studio/` (`StudioWindow`, `PanelFbo`, `FixtureProvider`, `LayoutSource`) + `src/AcDream.App/Rendering/RenderBootstrap.cs`. ISSUES #156 (inventory all-black in studio) and #157 (GameWindow font resolver) filed.
- **✓ SHIPPED — Importer dat-fidelity** (Fix A/B/C, 2026-06-26, same branch). **Boundary established: look = importer (font/justification/color from dat); state/behavior = runtime controller logic.** Fix A: justification property `0x14`/`0x15``UiText` Centered/RightAligned/VerticalJustify. Fix B: FontColor property `0x1B``UiText.DefaultColor`; character colors proved RUNTIME (no importer fix). Fix C: FontDid → per-element dat font via a resolver in `DatWidgetFactory`**STUDIO path only**; GameWindow passes `null` (Issue #157). Fix 4 (UIState-group activation): INVESTIGATED — no importer fix exists; the dat has no Visible encoding; runtime `gm*UI` is correct.
- **✓ SHIPPED — Wave 3.3 unified primary-click router.** `ItemInteractionController.OfferPrimaryClick` returns `NotActive` / `ConsumedSuccess` / `ConsumedRejected`; inventory, bags, main pack, paperdoll, toolbar, radar, and world clicks all offer target mode before local fallback. Rejected targets cannot drift selection or open/use the clicked object. Issue #197 and AP-107 retired; retained end-to-end matrix green.
- **✓ SHIPPED — Wave 3.3 unified primary-click router.** `ItemInteractionController.OfferPrimaryClick` returns `NotActive` / `ConsumedSuccess` / `ConsumedRejected`; inventory, bags, main pack, paperdoll, toolbar, radar, and world clicks all offer target mode before local fallback. Rejected targets cannot drift selection or open/use the clicked object. Issue #197 and AP-107 retired; retained matrix and live ACE-provisioned healing gate user-confirmed. The 3-D doll routes through authored hit mask `0x100001D6` (resolved `UiButton` above viewport `0x100001D5`), and local health prefers authoritative private-vital state.
- **✓ SHIPPED — Character window** (`LayoutDesc 0x2100002E`, `CharacterStatController`, 2026-06-26, same branch). **Visually user-confirmed 2026-06-26 — Attributes tab reads as retail.** Three tabs, header (name/heritage/PK), large-gold level number (dat font, `largeDatFont` 18px), "Total Experience (XP):" + "XP for next level:" captions, 9-row attribute list (icons + right-aligned values + Health/Stamina/Mana vitals), click-to-select (top/bottom selection bars + footer State-B "{Attr}: {value}" / "Experience To Raise: Infinity!" + affordability-gated raise triangles), centered footer. User noted "still needs some polish for later" — deferred to Issue #158.
- **✓ SHIPPED — D.5.4 — Client object/item data model (foundation).** Shipped 2026-06-18 (`b506f53`..`a33e897`, 11 commits). Renamed `ItemRepository``ClientObjectTable` / `ItemInstance``ClientObject`; broadened the table to hold EVERY server object (retail `weenie_object_table` shape). `CreateObject` is now the canonical merge-upsert (`ClientObjectTable.Ingest`, retail `SetWeenieDesc` semantics) via a new Core.Net `ObjectTableWiring` (off GameWindow); `DeleteObject` evicts; `PlayerDescription` is a membership manifest (`RecordMembership`); live container-membership index (`GetContents`, retail `object_inventory_table`). `_liveEntityInfoByGuid` retired (selection/describe resolve from the one table). Root fix: the old enrich-existing-only `EnrichItem` dropped `CreateObject`s for items with no `PlayerDescription` stub — live-Coldeve 4/6 hotbar slots blank; items are now created, not dropped. **Crux resolved:** retail is TWO tables (`object_table` + `weenie_object_table`), NOT one — acdream's `WorldEntity` (3D system) + `ClientObjectTable` (data/UI) split was already architecturally faithful; the fix was the ingestion path, not a table unification. 2671 tests green.
- **Roadmap correction (2026-07-10):** the completion order is now the architecture-first campaign in `docs/superpowers/plans/2026-07-10-retail-ui-fidelity-completion.md`. Retail `gmToolbarUI` is object-only: preserve `ShortCutData.index_`, `objectID_`, and `spellID_`, but do not invent spell glyphs on this bar. `PlayerModule::favorite_spells_[8]` feeds separate spell bars.

View file

@ -363,11 +363,11 @@ consume the typed action seam when those surfaces land; until then the policy
refuses unsafe wire sends rather than bypassing their gates.
**Acceptance (2026-07-11):** Non-debug Release live-world gate passed for
ordinary item/container activation, equip/inventory synchronization, and grounded
world drop, with no observed UI regression. A healing kit was not available in
the test character's inventory, so the targeted-heal click was not exercised
live; the compatible/invalid/self target matrix remains pinned by Core and App
controller tests. Full suite green before launch: 4,575 passed, 5 skipped.
ordinary item/container activation, equip/inventory synchronization, grounded
world drop, and targeted healing. ACE command forwarding provisioned WCID 632
with `/ci 632`; `/harmself` then proved the main-pack and paperdoll self-target
paths plus authoritative health-bar drain/recovery. Full suite green at the final
gate: 4,583 passed, 5 skipped.
### 3.3 Add one item primary-click chokepoint
@ -393,6 +393,14 @@ results. The consumed target is retained for retail's 500 ms double-click window
so the second Click/DoubleClick pair cannot reactivate or equip the rejected
object after target mode clears. Issue #197 and AP-107 are retired.
**Acceptance (2026-07-11):** User-confirmed the non-debug Release fallback
matrix for inactive target mode across inventory, paperdoll, toolbar, radar,
and world clicks, then the active targeted-heal flow through both the main pack
and 3-D paperdoll. The production DAT resolves the authored doll hit mask
`0x100001D6` as a `UiButton`; binding the viewport beneath it cannot receive a
live click. The mask now owns self-target clicks and hides with the viewport in
slot view. Full suite green at the final gate: 4,583 passed, 5 skipped.
### 3.4 Complete retail cursor precedence and catalog
- [ ] Port every reachable branch of `ClientUISystem::UpdateCursorState`, not only