acdream/docs/plans/2026-07-23-world-interaction-completion.md
Erik 02c29e67c8 feat(ui): port favorite spell bar overflow
Import the retail arrow-only spell bar scrollbar from LayoutDesc, preserve authored end-button extents and HideDisabled behavior in the shared retained widget, and bind each favorite list to its sole horizontal pixel-scroll model. Match retail selection exposure for off-screen spells and pin the behavior with real-fixture conformance tests.

Document the six-slice world-interaction completion program as the active pre-M4 work order.

Co-authored-by: Codex <codex@openai.com>
2026-07-23 06:35:53 +02:00

5.5 KiB
Raw Blame History

World interaction completion — pre-M4 program

Status: Slice 1 code-complete 2026-07-23; connected visual gate pending. Milestone: M4 prerequisite/preamble. Architecture: retained gameplay UI over shared selection, object, and interaction state. GameWindow remains a composition/callback shell.

Outcome

Close the remaining retail interaction surfaces before the larger M4 quest/emote/character-creation bodies begin:

  1. Favorite spell bars expose their DAT-authored overflow arrows and scroll through every server-persisted favorite.
  2. The status bar's hand and magnifying-glass controls invoke the same Use and Assess commands as their keyboard paths.
  3. Assessing a creature, player, NPC, or object opens its retail information in the canonical shared main-panel host.
  4. World picking can resolve visible equipped children, such as a character's wielded weapon, while selection markers remain anchored to the picked child.
  5. Vendor use opens the authored vendor surface, publishes its inventory, and supports retail selection/browsing.
  6. Vendor buy/sell transactions, quantities, pending-state ownership, and authoritative inventory reconciliation complete the loop.

The program reuses the existing retained-window host, SelectionState, ClientObjectTable, interaction transaction owner, and server-authoritative inventory updates. It does not create parallel panel positions, item tables, selection state, or optimistic inventory outcomes.

Ordered slices

Slice Deliverable Principal owner
1 Spell-bar overflow arrows SpellcastingUiController + generic retained scrollbar/list
2 Status Use/Assess commands focused status-bar controller binding to the existing action router
3 Assessment information panel new retained panel controller mounted by the canonical main-panel host
4 Equipped-child world picking pure world-query/picking policy plus presentation anchor
5 Vendor browse lifecycle vendor session/controller plus authored panel
6 Vendor transactions server-authoritative buy/sell command and reconciliation owner

Each slice begins with named-retail research, produces pseudocode and conformance tests, updates the divergence register if required, and lands as a separate bisectable commit. A visual gate follows each UI-bearing slice.

Slice 1 now imports both 23-pixel arrow buttons and HideDisabled from the real combat fixture, shares the list's single pixel-scroll model, advances one 32-pixel cell per press, and exposes programmatically selected spells. The focused 57-test set, all 3,466 App tests / 3 skips, the Release solution build, and all 7,839 solution tests / 5 skips pass. Only the connected visual gate remains before Slice 2 starts.

Slice 1 — spell-bar overflow arrows

Retail oracle

The authored Magic combat layout contains, inside every favorite-tab group:

  • horizontal scrollbar 0x100000B5, 685×36 at the 800-pixel design width;
  • decrement button 0x10000071, 23×36;
  • increment button 0x10000072, 23×36;
  • item list 0x100000B6, inset by 23 pixels on both sides and 32 pixels high.

The list references the scrollbar through UIElement_Scrollable property 0x71. The scrollbar references increment/decrement buttons through properties 0x77/0x78, and property 0x79 enables HideDisabled. There is no track or thumb in this specific control: the two authored arrows are the whole visible scrollbar.

Named retail references and executable pseudocode are recorded in ../research/2026-07-23-retail-spellbar-overflow-pseudocode.md.

Implementation plan

  1. Generalize DatWidgetFactory.BuildScrollbar so horizontal and vertical scrollbars both import the referenced decrement/increment children, including their authored dimensions and HideDisabled property.
  2. Generalize UiScrollbar to use distinct authored decrement/increment extents for rendering, hit-testing, track geometry, and dragging. Preserve the existing 16-pixel default for layouts whose button children are absent.
  3. Reproduce retail disabled presentation: a model without overflow rejects pointer input; when HideDisabled is authored, the scrollbar also draws nothing and does not claim hit tests.
  4. In SpellcastingUiController, bind each group's scrollbar to its UiItemList.Scroll, enable horizontal scrolling, and retain one independent pixel offset per favorite tab.
  5. Match SpellCastSubMenu::SetSelected: selecting a spell through keyboard, shortcut, or code scrolls that item into view.
  6. Pin the importer, arrow hit extents, 32-pixel step, no-overflow behavior, controller binding, and selection exposure with focused App tests.
  7. Run the App Release suite, solution Release build, and complete Release suite. Then update the roadmap/memory and request the connected visual gate: place more favorites than fit, scroll both directions, change tabs, and verify arrows disappear on a non-overflowing tab.

Invariants

  • DAT supplies the controls and their artwork; no new spell-bar texture or overlay is invented.
  • The scrollbar and list share one UiScrollable; there is no second offset.
  • One arrow press moves one 32-pixel favorite cell, matching UIElement_ListBox::InqScrollDelta.
  • Hidden disabled arrows cannot intercept combat-page dragging or clicks.
  • Existing stack, combat-power, chat, inventory, spellbook, and external container scrollbars retain their current behavior.
  • No substantial feature body enters GameWindow.