# World interaction completion — pre-M4 program **Status:** Slice 1 user-accepted 2026-07-23. Slice 2 Use-hand selection state passed its connected gate. The follow-up zero-useability/AutoWear correction is code-complete and awaits its connected gate before Assess continues. **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, their rollover/pressed media, and HideDisabled from the real combat fixture; places their artwork by the authored leading/trailing positions; shares the list's single pixel-scroll model; advances one 32-pixel cell per press; and exposes only actively selected spells. Passive object/endowment refresh preserves a manual offset. The mixed 610/800-pixel DAT anchor chain is solved to a fixed 747-pixel combat root, producing exactly 18 visible 32-pixel favorite cells (nine numbered plus nine unnumbered) without consuming the overflow. The initial 57-test/full-suite gate passed; the corrective 104-test focus set, 3,472 App tests / 3 skips, Release solution build, and 7,845 complete-solution tests / 5 skips pass. The corrected 18-cell bar and both overflow directions passed the connected gate. Slice 2 now drives the toolbar hand from canonical `SelectionState` changes and live `ClientObjectTable` updates. The pure Core predicate ports `gmToolbarUI::HandleSelectionChanged`: combat-use items, armor/clothing/jewelry, and `ItemUses` values without `USEABLE_NO` remain active. Clicking still enters the existing `ItemInteractionController` command path, so weapons use the server-confirmed AutoWield transaction and targeted tools enter the existing use-on-target cursor. Empty selection and explicitly unusable spell components are ghosted and ignore clicks. Empty-selection ghosting is the user's explicit choice over retail's generic `TARGET_MODE_USE` entry and is registered as AP-122. The 14-test Core interaction focus, 49-test toolbar focus, Release solution build, 3,474 App tests / 3 skips, and 7,848 complete-solution tests / 5 skips pass. The connected selection-state gate passed. Its follow-up exposed three deeper shared-policy/delivery defects, now corrected from named retail plus the matching binary. `ItemUses::IsUseable @ 0x004FCCC0` tests only `USEABLE_NO`; reset/absent value zero is usable. `ItemHolder::UseObject @ 0x00588A80` sends a carried direct-use item immediately; acdream had incorrectly routed that packet through a world approach lookup, where Blackmoor's Favor has no spatial entity and was silently cancelled. Owned Use now bypasses that query while world-object Use retains the registered AD-27 approach seam. AutoWear applies `CPlayerSystem::AutoWearIsLegal @ 0x0055EF40` through the same double-click and toolbar-hand path, resolves the overlapping worn object from the retail-ordered equipment projection, and emits the exact system line `You must remove your to wear that`. Research: [`../research/2026-07-23-retail-item-use-and-autowear-pseudocode.md`](../research/2026-07-23-retail-item-use-and-autowear-pseudocode.md). The focused 25-test Core and 85-test App sets pass, as do the warning-free Release solution build, 3,476 App tests / 3 skips, and 7,857 complete-solution tests / 5 skips. The carried-use delivery correction adds an end-to-end App pin from Favor activation through wire dispatch and authoritative UseDone busy release. The Release build retains the 17 tracked test-project warnings; 3,477 App tests / 3 skips and 7,858 complete-solution tests / 5 skips pass. ## 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`](../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 positions, dimensions, Normal/rollover/pressed media, 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; passive state refresh does not re-expose it. 6. Carry the combat root's mixed-parent raw-edge policies through the complete imported tree and solve for the retail 18-cell favorite viewport; keep that HUD capacity fixed across desktop resizes. 7. Pin the importer, arrow hit extents, 32-pixel step, no-overflow behavior, controller binding, and selection exposure with focused App tests. 8. 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`. ## Slice 2 — status Use/Assess commands ### Use-hand implementation 1. `ItemInteractionPolicy.IsToolbarUseEnabled` is the pure named-retail selection predicate. 2. `ItemInteractionController.IsToolbarUseEnabled` adapts the selected live object without triggering a request or consuming the use throttle. 3. `ToolbarController` subscribes to canonical `SelectionState.Changed` and selected-object add/update/remove notices, then sets the imported button's normal or ghosted state through `UiButton.Enabled`. 4. Enabled clicks retain the one existing activation path: equipment enters `AutoWieldController`, ordinary use enters the normal Use request owner, and targeted items enter `UseItemOnTarget`, which already owns the retail target cursor. ### Remaining Slice 2 work - Port the magnifying-glass Assess command state and activation. - Run the connected correction gate: activate Blackmoor's Favor, then try to equip armor blocked by an overlapping worn item and verify the named system message. - Continue directly into the Assess information slice after the combined status-control gate.