merge: Campaign LA LA8 - retail character screen review-closed
This commit is contained in:
commit
fe63ce186a
20 changed files with 3431 additions and 37 deletions
|
|
@ -165,6 +165,16 @@ window registration, plugin mounts, cursor feedback, layout persistence, and the
|
|||
retained tick/draw/restore/dispose paths. Panel-specific construction must not
|
||||
move back into `GameWindow.OnLoad`.
|
||||
|
||||
The graphical no-selector launch projects Runtime's sole
|
||||
`RuntimeCharacterSelectionState` through the retained character-management root
|
||||
resolved from DAT enum table 5 (`0x10000005` -> `0x21000004`, selected root
|
||||
`0x1000039A`). App borrows the view and routes generation-capturing typed
|
||||
commands; it owns no roster, highlight, operation, error, or lifecycle mirror.
|
||||
The authored screen is a flat ListBox and buttons, with the shared retail dialog
|
||||
catalog for confirmation, wait, and error presentation. It contains no viewport
|
||||
or character preview. Explicit-selector graphical launches and no-window hosts
|
||||
do not mount this presentation.
|
||||
|
||||
Magic follows the same boundary. Core `Spellbook` is the one learned/favorite/
|
||||
desired/enchantment state projection; Core.Net owns exact manifest and live
|
||||
message parsing; Runtime `RuntimeActionState.SpellCast` owns validated cast
|
||||
|
|
|
|||
120
docs/research/2026-08-14-la8-character-management-ui.md
Normal file
120
docs/research/2026-08-14-la8-character-management-ui.md
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
# LA8 retained character-management UI evidence
|
||||
|
||||
Date: 2026-08-14
|
||||
|
||||
This note records the retail and installed-DAT evidence for Campaign LA slice
|
||||
LA8, plus the exact ownership and presentation boundary implemented by the
|
||||
slice. LA7b remains the authority for pre-world Runtime and wire behavior.
|
||||
|
||||
## Named-retail evidence
|
||||
|
||||
The implementation was derived from
|
||||
`docs/research/named-retail/acclient_2013_pseudo_c.txt` and the corresponding
|
||||
`acclient.h` definition before the screen was written.
|
||||
|
||||
- `DBObj::GetDIDByEnum` (`0x004153A0`) forwards to
|
||||
`DBCache::GetDIDFromEnumStatic`; retail resolves the category/table mapping
|
||||
before loading a LayoutDesc.
|
||||
- `gmCharacterManagementUI::gmCharacterManagementUI` (`0x004EC8F0`) calls
|
||||
`UIMainFramework::CreateAndAddRootElement(0x10000005, 0x1000039A)`, then
|
||||
binds ListBox `0x1000039D`, Create `0x100003A0`, Enter `0x100003A2`, Delete
|
||||
`0x1000039F`, and Restore `0x1000039E`.
|
||||
- The verbatim header at `acclient.h:56545` declares exactly that ListBox,
|
||||
those four button pointers, the selected row/guid, and four dialog contexts.
|
||||
It declares no viewport, `gmCG3DView`, or preview owner.
|
||||
- `RebuildCharacterList` (`0x004EC3A0`) creates each row through
|
||||
`AddItemFromTemplateList`, then resizes it using signed integer division:
|
||||
`max(listHeight / max(rosterCount, allowedSlots), listHeight / 10)`. Thus a
|
||||
320-pixel list with five allowed slots uses 64-pixel rows, while rosters over
|
||||
ten clamp at 32 pixels. It retains character identity, displays pending
|
||||
deletion in red, sorts by ordinal name, moves greyed entries to the tail,
|
||||
and restores/falls back selection. LA8 preserves the already canonical LA7b
|
||||
display order and identity instead of sorting an App copy.
|
||||
- `SelectCharacter` (`0x004EC160`) and `UpdateButtons` (`0x004EC240`) establish
|
||||
the highlight and button matrix: no or greyed selection disables Enter and
|
||||
Delete; an active selection shows/enables Delete; a greyed selection hides
|
||||
Delete and shows/enables Restore.
|
||||
- `ListenToElementMessage` (`0x004ED5A0`) routes the list selection message,
|
||||
button clicks, and row-template `0x100003A5` activation message `0x1A`.
|
||||
Double-activating a row calls `EnterGame` (`0x004ED440`).
|
||||
- `MakeDeleteCharacterConfirmationDialog` (`0x004ECCA0`) uses retail dialog
|
||||
type 5 and compares the typed response with the localized DELETE response
|
||||
case-insensitively. `MakePleaseWaitDialog` (`0x004ECED0`) and
|
||||
`MakeEnteringWorldDialog` (`0x004ED090`) use the wait machinery. Error
|
||||
presentation enters through `MakeErrorMessageDialog` (`0x004ECB10`). The
|
||||
destructor (`0x004EC080`) closes every owned dialog context.
|
||||
|
||||
The shared dialog factory switch supplies catalog roots/classes used here:
|
||||
message type 3 is root `0x24` / class `0x17`; confirmation-text-input type 5
|
||||
is root `0x2C` / class `0x15`; the existing wait type 2 is root `0x31` /
|
||||
class `0x19`. The message button is `0x26`. Type 5 uses field `0x2C`, accept
|
||||
`0x2E`, reject `0x2F`, and result property `0x9C`.
|
||||
|
||||
## Installed-DAT proof
|
||||
|
||||
The permanent read-only acceptance probe is
|
||||
`tests/AcDream.App.Tests/UI/Layout/CharacterManagementLiveDatTests.cs`. Run it
|
||||
with `ACDREAM_PROBE_LIVE_MOUNT=1`; it reads the ordinary
|
||||
`%USERPROFILE%/Documents/Asheron's Call` DAT set unless `ACDREAM_DAT_DIR`
|
||||
overrides the location. It uses production `DatCollection`,
|
||||
`RetailDataIdResolver`, and `LayoutImporter`; it does not write the DATs.
|
||||
When the opt-in flag or installed data is absent, discovery records an explicit
|
||||
skip rather than adding a no-op pass to default suite totals.
|
||||
|
||||
The installed September-2013 data proves:
|
||||
|
||||
- enum category/table 5 maps `0x10000005` to concrete LayoutDesc DID
|
||||
**`0x21000004`**;
|
||||
- selected root `0x1000039A` is 800 x 600 with eight authored children;
|
||||
- the root itself authors image media `0x06007576`; that proves a retained
|
||||
layout asset, not a separate render-loop background scene;
|
||||
- its ListBox template is `{ 0x21000004, 0x100003A5 }`;
|
||||
- the template is a 160 x 16 `UiButton`, font `0x40000009`, with Normal,
|
||||
NormalRollover, NormalPressed, Highlight, HighlightRollover, and the authored
|
||||
`0xFFFFFFFF` default state;
|
||||
- the authored captions are Create Character, ENTER, DELETE, and RESTORE;
|
||||
- neither the selected root nor any descendant is a `UiViewport`;
|
||||
- enum-table-5 dialog key 2 maps to catalog DID `0x2100003C`, containing the
|
||||
type-3 and type-5 roots/children above;
|
||||
- string table `0x23000002` contains DELETE, Please Wait, Entering World, and
|
||||
the delete-confirmation template. The template has the PLAYER variable and
|
||||
resolves it into the selected character name.
|
||||
|
||||
## Ownership, composition, and lifecycle
|
||||
|
||||
`RetailUiRuntime` imports the exact enum-resolved root only for a graphical
|
||||
launch with no explicit character selector. Its focused binding borrows
|
||||
`IRuntimeCharacterSelectionView`; every highlight, enter, delete-request,
|
||||
delete-confirm, restore, and cancel action crosses the existing deferred
|
||||
adapter as a generation-capturing Runtime command. App retains no gameplay
|
||||
mirror. Explicit-selector graphical launches keep their existing flow, and
|
||||
headless does not compose this App presentation.
|
||||
|
||||
The controller instantiates the authored row template in Runtime display
|
||||
order, projects red pending-delete rows and the exact button matrix, and opens
|
||||
the shared retail dialogs. Delete wait survives the opcode-only acknowledgement
|
||||
until the fresh roster arrives. Restore is fire-and-observe: a silent ACE
|
||||
no-reply ends only when Runtime expires its correlation; retail's Please Wait
|
||||
opens before the synchronous restore command and closes immediately if that
|
||||
command rejects or throws. Entering-world wait opens before the existing
|
||||
synchronous Enter command; error, reset, reconnect, missing/displaced adapter,
|
||||
and disposal close owned contexts without re-entrant commands. A failed
|
||||
transient row-template import leaves the Runtime revision unconsumed and
|
||||
retries on the next frame. Initial dialog-catalog, character root, and string
|
||||
misses likewise retry on later ticks without mounting a duplicate root or
|
||||
controller. Dialog presenter/catalog failures move their contexts to an
|
||||
internal retry ledger, so UI callbacks do not retain poisoned active/queued
|
||||
entries and the same context can appear after resource recovery. Priority
|
||||
contexts remain ahead of ordinary retries and preserve retail's nested
|
||||
preemption order when creation recovers. The mount coordinator owns a detached
|
||||
controller before attaching its root or running the first template-resolving
|
||||
tick; any partial failure disposes that exact controller before retry, so roots
|
||||
and handlers cannot accumulate.
|
||||
|
||||
There is deliberately no 3D preview and no claimed character-select background
|
||||
scene. The screen root remains neutral with respect to render-loop background
|
||||
composition. LA11's user visual gate owns that unresolved visual choice, plus
|
||||
the live local-ACE delete/restore check. Because Enter currently completes its
|
||||
established ServerReady transaction synchronously, LA11 must also verify that
|
||||
the entering-world wait is perceptible on the real frame path; this slice does
|
||||
not introduce a second queue or lifecycle owner merely to force a paint.
|
||||
Loading…
Add table
Add a link
Reference in a new issue