docs: Campaign LA plan — slices LA0-LA11, recon-grounded; spec corrections
Plan doc with twelve slices, dependencies, review protocol (Opus dual-lens: architectural + retail-faithful), and ledger. Three parallel recon reports grounded the slice bodies: - Retail select screen is gmCharacterManagementUI: flat listbox + Enter/Delete/Restore + dialogs. NO 3D preview (that machinery is chargen-only gmCG3DView) — the spec 3D-preview slice is deleted, the old retail-ui/05-panels.md pedestal claim is uncited and wrong. Restore + CharacterError join scope; delete sends account+slot. - Chat-command core (parser/router/catalog/ChatVM) is dependency-clean BCL+Core; extraction to Runtime is a move, not a rewrite. - Probe reuses the NoCharacters early-exit shape (graceful teardown at the CharacterList stage exists today); roster plumbing is new. - Bake tool needs --progress-json + explicit --out; no whole-file SHA exists — launcher records/verifies its own. - UI Studio is deleted (Campaign V) — stale references corrected. Roadmap + CLAUDE.md Current state carry the campaign pointer. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
afb4e82943
commit
9b0bb25581
4 changed files with 484 additions and 26 deletions
|
|
@ -40,7 +40,7 @@ Decided this session (2026-08-14):
|
|||
| Question | Decision |
|
||||
|---|---|
|
||||
| Headless launch purpose | **Run plugins** (VirindiTank-style) + login commands; same on GUI. Launcher selects which plugins per character |
|
||||
| Character-select screen | **Retail screen, no Create.** 3D rotating preview + Enter World + Delete; Create Character deferred to its own campaign |
|
||||
| Character-select screen | **Retail screen, no Create.** CORRECTED by 2026-08-14 recon: retail's `gmCharacterManagementUI` is a flat listbox + Enter Game / Delete / Restore buttons + dialogs — **no 3D preview exists on retail's select screen** (that machinery, `gmCG3DView`, is character-CREATION-only). We port what retail actually had; Create deferred to its own campaign |
|
||||
| Campaign scope | **Everything now** — launch flows + first-run install + update pipeline in one campaign |
|
||||
| Launcher ↔ client coupling | **Approach A: file-contract orchestrator** (config in, status events out; no game-protocol code in the launcher) |
|
||||
| Update feed | **GitHub Releases** (manifest.json + per-RID zips as release assets) |
|
||||
|
|
@ -211,23 +211,50 @@ enters immediately. New behavior: **no character selector in options →
|
|||
stop at the retail character-select screen.** Selection there feeds the
|
||||
same `EnterWorld` path.
|
||||
|
||||
- **Ownership:** J-owner pattern. A Runtime-owned selection state (roster,
|
||||
highlighted entry, pending-delete confirmation) with typed commands
|
||||
(highlight / enter / delete-request / delete-confirm); App projects the
|
||||
authored screen. Headless never uses it (config always carries a
|
||||
selector; the loader already requires one).
|
||||
- **UI:** imported retail screen via `LayoutImporter` (OP3/FA recipe).
|
||||
The concrete LayoutDesc id and widget tree come from the
|
||||
grep-named-first workflow + `docs/research/retail-ui/` during the plan;
|
||||
retail decomp is the behavior oracle for list interaction, Enter World,
|
||||
and Delete (including retail's delete confirmation flow — ACE serves
|
||||
the character-delete message).
|
||||
- **3D preview:** a void-scene render path — the selected character's
|
||||
Setup + ObjDesc appearance rendered with a dedicated camera/lighting,
|
||||
reusing the existing creature-appearance pipeline outside a landblock.
|
||||
Own slice; the retail screen's rotation behavior is the oracle.
|
||||
- **Non-goals:** Create Character (own future campaign); a login screen
|
||||
("back" exits the client — credentials always arrive via config/env).
|
||||
**CORRECTED 2026-08-14 (named-retail recon):** retail's screen is
|
||||
`gmCharacterManagementUI` (`acclient.h:56545`) — a `UIElement_ListBox`
|
||||
character list plus Create / Enter Game / Delete / Restore buttons and
|
||||
dialog contexts (delete-confirm, please-wait, entering-world, error).
|
||||
**It has NO 3D preview** — the rotating-model viewport (`gmCG3DView` /
|
||||
`UIElement_Viewport` / `CreatureMode`) exists only on character
|
||||
CREATION's appearance/heritage/profession pages. The earlier
|
||||
"3D preview on a pedestal" belief traced to one uncited line in
|
||||
`docs/research/retail-ui/05-panels.md` §13. We port the real screen; a
|
||||
preview would be a deliberate divergence we are NOT taking.
|
||||
|
||||
- **Ownership:** J-owner pattern. A Runtime-owned selection state (roster
|
||||
incl. greyed/pending-delete seconds, highlighted entry, pending-delete
|
||||
confirmation) with typed commands (highlight / enter / delete-request /
|
||||
delete-confirm / restore); App projects the authored screen. Headless
|
||||
never uses it (config always carries a selector; the loader already
|
||||
requires one).
|
||||
- **UI:** imported retail screen. The root layout id is resolved
|
||||
indirectly — retail calls
|
||||
`UIMainFramework::CreateAndAddRootElement(0x10000005, 0x1000039a)` and
|
||||
resolves the concrete DataID via `DBObj::GetDIDByEnum(..., 5)` (the same
|
||||
GetDIDByEnum machinery OP8 already ported for key names, category 4).
|
||||
Child widget ids from the decomp: listbox `0x1000039d`, create
|
||||
`0x100003a0` (hidden/no-op this campaign), enter `0x100003a2`, delete
|
||||
`0x1000039f`, restore `0x1000039e`. Behavior oracles:
|
||||
`RebuildCharacterList@0x004ec3a0`, `SelectCharacter@0x004ec160`,
|
||||
`UpdateButtons@0x004ec240` (Delete↔Restore visibility swap on greyed
|
||||
state), `EnterGame@0x004ed440`,
|
||||
`MakeDeleteCharacterConfirmationDialog@0x004ecca0`.
|
||||
- **Wire (new messages):** `CharacterDelete` 0xF655 (outbound: account
|
||||
String16L + **slot index**, per `Proto_UI::SendDeleteCharacter@0x00546b30`
|
||||
— NOT the guid; inbound: opcode-only ack, then a fresh CharacterList),
|
||||
`CharacterRestore` 0xF7D9 (guid) with response 0xF643, and a
|
||||
`CharacterError` 0xF659 parser (currently absent — acdream cannot
|
||||
surface any character-stage server error today). Enter-world's
|
||||
two-phase handshake (0xF7C8 → 0xF7DF → 0xF657) is already implemented.
|
||||
- **Open items** carried to the plan: the concrete layout DataID (dump
|
||||
enum-table 5 from installed DATs), and whether retail rendered any
|
||||
render-loop-level background scene behind the UI (the pseudo-C only
|
||||
proves the UI class owns no viewport) — both resolved in the screen
|
||||
slice before the user visual gate.
|
||||
- **Non-goals:** Create Character (own future campaign; the Create button
|
||||
exists on the authored screen but is disabled); a login screen ("back"
|
||||
exits the client — credentials always arrive via config/env).
|
||||
- Retail-workflow rules apply: any behavioral deviation ships with its
|
||||
divergence-register row in the same commit.
|
||||
|
||||
|
|
@ -284,7 +311,8 @@ same `EnterWorld` path.
|
|||
→ `RuntimeOptions`, stdin credential resolution, status-event writer
|
||||
output shape, plugin-set narrowing, login-command execution order.
|
||||
- **Character-select:** Runtime selection-state tests; authored screen
|
||||
via UI Studio dumps/screenshots; behavior against retail oracle.
|
||||
exercised by focused App tests (UI Studio no longer exists — deleted at
|
||||
Campaign V); visuals settle at the user gate.
|
||||
- **Headless plugin host:** fixture plugin in the Headless suite
|
||||
(load, capability flag, teardown).
|
||||
- **Connected gates (user-driven):** every launch mode against local ACE
|
||||
|
|
@ -301,12 +329,22 @@ same `EnterWorld` path.
|
|||
after reading CH seams; do not regress CH-accepted chat behavior.
|
||||
2. Current App plugin-loading behavior (what loads today, when) — read
|
||||
before wiring the session-driven set.
|
||||
3. Retail character-select LayoutDesc id + widget tree — research task
|
||||
(grep-named + `docs/research/retail-ui/`).
|
||||
4. Character-delete wire message + ACE handling — verify against
|
||||
holtburger/ACE before implementing the Delete flow.
|
||||
5. Void-scene preview: lighting/camera parameters need the retail oracle
|
||||
(what does retail actually render behind the character?).
|
||||
3. RESOLVED by recon except the concrete root-layout DataID: widget tree +
|
||||
behavior symbols are in §7; the DataID hides behind `GetDIDByEnum`
|
||||
enum-table 5 (enum `0x10000005`) — dump the table from installed DATs
|
||||
in the screen slice.
|
||||
4. RESOLVED by recon: delete = 0xF655 account+slot (ack opcode-only, then
|
||||
fresh CharacterList); restore = 0xF7D9 guid → 0xF643 response; ACE's
|
||||
`secondsSincePendingDelete` computes to a constant 1 during the grace
|
||||
window (ACE quirk — treat any non-zero as "pending delete", don't
|
||||
display it as a countdown). One decomp ambiguity (whether retail's
|
||||
restore carries two extra strings) is noted as a likely decompiler
|
||||
artifact — ACE + holtburger agree on guid-only; follow them and note
|
||||
the register row is NOT needed (wire consensus, no behavior change).
|
||||
5. Whether retail rendered a render-loop-level background scene behind the
|
||||
character-management UI — pseudo-C only proves the UI class owns no
|
||||
viewport. Resolve in the screen slice (user memory of retail + the
|
||||
visual gate settle it).
|
||||
6. Bake tool 4 invocation surface from Launcher.Core (in-process reference
|
||||
vs child process) — child process preferred to keep Launcher.Core free
|
||||
of game-solution references; confirm the tool's CLI is sufficient.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue