Create button un-ghosts: retail's exact gate (gmCharacterManagementUI:: UpdateButtons @0x004ec240, roster count < allowed slot count) ported into RuntimeCharacterSelectionButtons.CanCreate; the button's OnClick opens the chargen screen through the same CharacterCreationUiController.Open() seam the ACDREAM_OPEN_CHARGEN=1 dev path already used. Exit/Back confirm on chargen needed no new return-path code — character-management is never hidden while chargen is open on top of it — verified end-to-end by a new cross-controller test rather than left as an inspection claim. Full-flow test coverage: a new comprehensive test decodes every 0xF656 field (including the trailing checksum, recomputed via the production CharacterCreate.ComputeChecksum) against a fully populated creation (heritage/gender/all appearance slots/template/explicit skill command/ town/name); a new Theory drives the remaining six 0xF643 rejection codes through the real wire decode path, closing the gap between the already-covered isolated state-machine Theory and an actual WorldSession round trip. Launcher payload cycle: two new tests drive a real Runtime create/reject through the real SessionStatusWriter (wired exactly as LiveSessionRuntimeFactory/HeadlessSessionHost do in production) and read the result back with the real Launcher.Core StatusFileTailer/ StatusEventParser — closing the one gap CC2's own per-layer tests never reached. No gap was found in production wiring itself: GameWindow already constructs a real, non-null SessionStatusWriter for both hosts. Also fixes 4 pre-existing LiveSessionControllerTests assertions that compared a full RuntimeCharacterSelectionButtons record and would have failed once CanCreate started being computed; corrects register row AP-211 to reflect that its own predicted resolution (the Create-button gate landing) has now happened — both layers are intentionally kept as retail-matching enforcement plus defense-in-depth, not one superseding the other. Adds docs/research/2026-08-16-campaign-cc-test-script.md, the user's connected-gate script covering both the launcher and dev-shortcut launch paths, the six-page create flow, every Finish outcome, and the known cosmetic/behavioral divergences (AP-212/213/215/216/217/218/219/220/222/ 224/226/228) so they aren't mistaken for new bugs during the gate. Gates: full solution Release build green; Runtime 1735/0 (was 1726/0, +9), App 5256/3 skips (was 5254/3, +2), Headless 166/0 (unchanged), Launcher.Core 324/0, one full-solution pass across every project clean (no known flakes reproduced this run). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
17 KiB
Campaign CC connected-gate test script
Status: the campaign is CODE-COMPLETE (CC1-CC7) and this script is its connected-gate contract. Every step below is the user's own eyes on the running client — nothing here was run automatically. No automated live character creation has been run against ACE (see §CC-Not-Automated) — the first LIVE create is deliberately left to this gate.
This script covers TWO ways to reach the chargen screen: the real launcher
flow (Campaign LA's product path) and the developer shortcut
(ACDREAM_RETAIL_UI=1 + ACDREAM_OPEN_CHARGEN=1, still available and still
useful for a fast create-only iteration loop). Both land on the exact same
screen and Runtime owner — there is no second code path being tested.
Local ACE connection details (per CLAUDE.md): host 127.0.0.1, port
9000, account testaccount / testpassword. Use a FRESH character name
per attempt (ACE does not forget names within a session) — CC-<yourinitials>-<n>
is a good scheme, e.g. CCAB1, CCAB2.
§CC1 — reaching the screen
Path A — the launcher (product path)
- Launch
AcDream.Launcher(already installed/updated per Campaign LA's own gates — this script does not re-run first-run setup or the update flow; seedocs/research/2026-08-14-campaign-la-test-script.mdif either is in question). - Open Check for updates. Confirm it reports the client already current (no install prompt) — Campaign LA's own gates already proved the install/update mechanics; this step just confirms nothing is stale before the character-creation gate.
- Confirm (or create) a profile pointed at
127.0.0.1:9000,testaccount/testpassword. - Click GUI — character select. The retail character-management
screen (
gmCharacterManagementUI) opens — the flat character list, World name, Enter/Delete/Restore buttons, and the Create button.
Path B — the developer shortcut
$env:ACDREAM_DAT_DIR = "$env:USERPROFILE\Documents\Asheron's Call"
$env:ACDREAM_RETAIL_UI = "1"
$env:ACDREAM_LIVE = "1"
$env:ACDREAM_TEST_HOST = "127.0.0.1"
$env:ACDREAM_TEST_PORT = "9000"
$env:ACDREAM_TEST_USER = "testaccount"
$env:ACDREAM_TEST_PASS = "testpassword"
dotnet run --project src\AcDream.App\AcDream.App.csproj --no-build -c Release
Confirm the SAME character-management screen appears. ACDREAM_OPEN_CHARGEN=1
(add it to the block above) is the CC4-era interim seam that opens the
chargen screen directly on startup, skipping the Create click — still
useful for a fast create-only loop, but Path A/B above is now the REAL path
and should be exercised at least once per gate.
The Create button
- With at least one free character slot (roster count below the account's allowed slot count — most test accounts have several free slots), confirm Create is ENABLED (not greyed out).
- Click Create. The chargen screen (
gmCharGenMainUI) opens directly on the Heritage page — no confirmation, no loading screen. The character-management screen you were just on is not closed or hidden; it simply sits behind the new screen (this matters for the Exit step below). - If your account's roster is completely full (rare on a fresh test
account — every slot occupied), confirm Create is instead GREYED OUT
and does nothing when clicked. This is retail's own gate
(
gmCharacterManagementUI::UpdateButtons) — a full roster ghosts Create exactly like Enter/Delete grey out for an unselected row.
Leaving the screen (Back-at-Heritage and Exit)
- On the Heritage page (the first page), click Back. Confirm a
confirmation dialog appears asking whether to leave character creation
(same text/shape as the Exit button below — Back-at-Heritage and Exit
share retail's one
DoExitconfirmation). - Click Exit (top of the screen, available on every page). Confirm the SAME confirmation dialog appears.
- Confirm the dialog (accept). The chargen screen closes. You are back at the character-management screen you started from — roster, World name, and any prior selection are exactly as you left them (character management was never hidden, so there is nothing to "restore").
- Click Cancel on a repeat Exit attempt instead — confirm the dialog closes and chargen stays open, untouched.
What to report for §CC1
- Create's enabled/greyed state matching the free-slot count you actually have.
- Whether clicking Create opens chargen with no lag/flash/black frame.
- Whether returning from Exit shows the character list exactly as it was (no re-flicker, no lost highlight, no stale World name).
§CC2 — the six-page create flow
The screen does NOT open blank. gmCharGenMainUI's own constructor
rolls a full random character (heritage, gender, appearance, clothing,
template, start area) before the Heritage page ever draws — acdream ports
this faithfully (AP-214, retired). Expected retail quirk: the gender
shown on the Appearance page is the FLIP of the roll — the Appearance
page's own init code reads the just-rolled gender and immediately swaps it
to the opposite one. If you open chargen and see (say) a female Aluvian
with the Appearance page showing "Male" selected, that is CORRECT, not a
bug — do not report it.
Heritage page
- Confirm one of the 13 heritage buttons is already highlighted (the opening roll) — Human heritages (Aluvian/Gharu'ndim/Sho/Viamontian), Tumerok, Gearknight, Lugian, Empyrean, Penumbraen, Shadowbound, Undead, Olthoi, and OlthoiAcid should all be selectable and each show its own description text (starting skills, bonus-skills paragraph where retail has one — Lugian/Olthoi/OlthoiAcid have none, that's retail-correct).
- Click Random. Confirm the highlighted heritage changes to a uniformly-picked one of the 13 — this is AP-212's documented approximation (retail's own Heritage-page Random rolls with retail's own distribution; acdream picks uniformly over every installed heritage). Not a bug to report unless the button does nothing or crashes.
- Select Olthoi or OlthoiAcid. Confirm the Profession, Skills, and Town tabs are hidden (Olthoi variants skip straight to a fixed Custom template with no attribute/skill/town choices) and the screen auto-advances past them.
Profession page
- Select a NON-Olthoi heritage. Confirm 7 template buttons (Custom + 6 presets) and 6 attribute sliders (Strength/Endurance/Coordination/ Quickness/Focus/Self).
- Drag a slider. Confirm the numeric readout updates live and the Available-credits counter decreases/increases correspondingly.
- Click a preset template (not Custom). Confirm all 6 sliders jump to that preset's values and Available credits updates to match.
- Click Random. Confirm heritage/template selection changes (AP-212 — uniform pick, not retail's own weighted roll).
Skills page
- Confirm ONE flat listbox of skills, each row showing name, current level, and train/specialize costs (AP-213 — retail groups these into four sorted buckets; acdream's flat list is a presentation simplification, not a rules difference — do not report the flat ordering as a bug).
- Click a trainable row. Confirm it advances (Untrained -> Trained -> Specialized) and the skill-credits meter decreases; a second click on an already-Specialized row does nothing further (no fourth state).
- Confirm Random is disabled/greyed on this page (retail's
RandomizeSkillsprimitive is unported — AP-212's own documented gap).
Appearance page
- Confirm Face and Clothes sub-tabs, nine spin controls (hair, eyes, nose, mouth, skin under Face; headgear, shirt, trousers, footwear under Clothes), nine color swatches, a shade scrollbar, zoom/rotate buttons, and a live 3D preview playing an idle animation loop.
- Click a spin's left/right arrow zones. Confirm the selected style index advances/retreats and the preview model updates.
- Click a color swatch. Confirm the swatch shows a highlighted "selected" ring/border (AP-215 — acdream's own selection indicator, not retail's overlay mechanism; functionally equivalent).
- Click Zoom In. Confirm the preview freezes its pose (idle animation stops) and the camera tweens closer over about half a second. Click Zoom Out — animation resumes, camera tweens back out.
- Click Rotate Clockwise/Counter-Clockwise. Confirm the model spins continuously at a steady rate (about 3 seconds per full turn); clicking the SAME direction again stops it, clicking the OPPOSITE direction reverses it.
- Click Random (on either sub-tab). Confirm hair/eyes/nose/mouth/skin
(Face) or headgear/shirt/trousers/footwear (Clothes) all re-roll
together — this IS retail's real
RandomizeAppearance/RandomizeClothingprimitive (CC5 ported it verbatim, not approximated). - Select Gearknight, Olthoi, or OlthoiAcid on the Heritage page, then return to Appearance. Confirm the Clothes sub-tab and its four spins are unreachable, Nose/Mouth spins are hidden, and Eyes' arrows are disabled (fixed eyes for these forms).
Known cosmetic gaps on this page — expected, do not report as bugs unless noticeably worse than described: swatches show static art rather than the actual color they represent (AP-216); the gradient circle art next to the swatches never repaints to reflect the current color (AP-217); the four icon-only spins (hair/eyes/nose/mouth) show a plain number instead of an icon thumbnail, while the four clothing spins show real names (AP-215/ AP-218); on Olthoi/OlthoiAcid/Gearknight the Skin spin does not slide up to close the gap left by the hidden Nose/Mouth spins (AP-219); switching heritage INTO or OUT OF Gearknight does not automatically re-roll appearance/clothing the way retail does on that exact transition (AP-220); the currently-selected spin shows no distinct highlighted state versus the other eight (AP-222 — this is a MEASURED gap in acdream's own art, not yet attributed to a specific missing asset; report clearly if you can visually compare with retail here).
Town page
- Confirm four town buttons: Holtburg, Shoushi, Yaraq, Sanamar (not id order — that's retail's own literal ordering, ported faithfully), each with descriptive text.
- Click a town. Confirm it highlights and the description text updates.
Summary page
- Confirm a listbox showing Profession, Gender, Heritage, and Starting Town lines, an "Attributes" header, then Strength/Endurance/ Coordination/Quickness/Focus/Self/Health/Stamina/Mana/Skill Credits as paired rows, then Specialized and Trained skill name lists (retail also lists the two Untrained buckets; acdream's Summary omits them — AP-224, same class of cut as the Skills page's own AP-213).
- Confirm a static 3D preview of the character (no zoom/rotate controls on this page — retail has none here either).
- Click the name field and type a name. Confirm only letters, spaces, apostrophes, and hyphens are accepted (other characters are silently rejected keystroke-by-keystroke).
- Click Random on this page. Confirm a confirmation dialog appears
first ("are you sure you want to randomize?"); confirming it re-rolls
the ENTIRE character (heritage through name) using retail's real
RandomizeCharacterprimitive — the same one the screen-open roll uses.
What to report for §CC2
- Any page that fails to render a control listed above, or where a control visibly does nothing when clicked.
- Anything from the "known cosmetic gaps" list that looks MORE broken than described (e.g. a spin that doesn't advance at all, not just a missing highlight).
- Any crash, freeze, or console error while navigating pages or the tabs.
§CC3 — Finish and its dialogs
Use a fresh, never-before-used character name for the happy path. For every
scenario below, watch the console/log for [UI]/[CC]-prefixed lines —
they help distinguish "nothing happened because the click didn't register"
from "the request went out and ACE is thinking about it."
Happy path
- Complete a legal character (heritage, gender, template with credits fully spent, at least a default set of skills, a town, a fresh name).
- Click Finish on the Summary page. Confirm the screen closes almost immediately (no visible "please wait" dialog for a normal accept — ACE's Ok reply is fast) and you land DIRECTLY in the world as the new character — no return to character management, no fresh character list, matching retail's own "log straight in" behavior.
- If you back out to character management instead (e.g. via a later logout), confirm the new character now appears in the roster alongside any pre-existing ones, in the correct slot.
NameInUse (duplicate name)
- Create a SECOND character using the EXACT name you just used above.
- Click Finish. Confirm the
ID_Character_Err_NameReserveddialog appears ("that name is in use" / similar text) and you stay on the chargen screen — Finish is clickable again afterward. - Expected log noise (register AD-100): ACE sends the NameInUse
rejection TWICE for the same request (a real ACE double-send bug, not
an acdream defect). The FIRST reply drives the dialog above; the SECOND
logs something like
unexpected CharacterGenerationVerificationResponsein the console. That log line is EXPECTED here — do not report it as an error.
The credit-warning confirm flow
- Select the Custom template on the Profession page (leaves several attribute credits unspent) and complete the rest of the character.
- Click Finish. Confirm a warning dialog appears about unspent attribute credits, and Finish does NOT send anything yet.
- Confirm the dialog. Confirm the request now sends anyway, with the
unspent credits — this is retail-correct (
DoFinish's own confirm-arm skips the credit check entirely; ACE accepts an under-spent build).
The randomize warning flow
Already covered in §CC2's Summary-page step 4 above — confirm the warning appears BEFORE any randomization happens, and Cancel leaves the character completely untouched.
The exit warning flow
Already covered in §CC1's "Leaving the screen" section above.
NameTooLong
- On the Summary page, type or paste a name longer than 32 characters and commit it (press Enter, or click elsewhere to move focus away from the field).
- Confirm the
ID_CharGen_NameTooLongdialog appears and the field reverts to its previous (shorter) value — the field itself does not cap your typing at 32 characters as you go; the rejection only fires on commit. That is retail-correct, not a bug.
What to report for §CC3
- Whether the happy path truly lands you in-world with no intermediate screen.
- The exact dialog text shown for each rejection (useful for a later string-table audit even if it looks right).
- Any case where Finish appears to do nothing at all (no dialog, no console line, no world entry) — that would be a real regression, not one of the documented cosmetic gaps above.
§CC4 — ACE-side landmines (not acdream defects)
- Heritage-priced skill over-deduction — LATENT, will not fire with the
installed EoR DAT. ACE's
PlayerFactory.CreatePlayerhas a real overcharge bug when specializing a skill priced by the active heritage's own skill list (versus the global skill table). It was measured against the installed EoR data and found unreachable — every heritage's one priced skill (Arcane Lore) has a heritage NormalCost of 0, which makes ACE's overcharge exactly zero. You should NOT be able to trigger aFailedToSpecializeSkillrejection from a retail-legal build during this gate. If you somehow do, that is worth flagging immediately — it would mean the installed DAT's costs differ from what was measured. - Disabled-Olthoi create -> Pending -> NameDBDown dialog is
retail-correct. If your local ACE has Olthoi character creation
disabled (a server config option), attempting to create an Olthoi/
OlthoiAcid character will surface the
ID_Character_Err_NameDBDowndialog via aPendingresponse code. This is retail's OWN behavior (ACE'solthoi_play_disabledbranch sendsPending, and retail's dispatch has no silent branch for it) — not a "the client swallowed my request" bug.
§CC-Not-Automated
No automated test in this repository has created a character against a
LIVE ACE server. Every field-shape and response-code assertion in Campaign
CC's test suite runs against a real WorldSession and hand-built response
packets (see tests/AcDream.Runtime.Tests/Session/LiveSessionControllerCharacterCreationTests.cs)
— the wire bytes and the state machine are proven byte-for-byte, but the
FIRST character ever created against a real, running ACE process is
whatever you create during this gate. Server state (what names exist,
what heritages are enabled, what the account's slot count is) is entirely
yours to observe; this script deliberately does not assume any of it in
advance.