feat(runtime): Campaign CC slice CC3 — RuntimeCharacterCreationState
Ports retail's CharGenState as the one Runtime-owned character-creation state machine, mirroring RuntimeCharacterSelectionState's exact pattern (snapshot/delta/event-stream, borrow-only view, generation-gated commands, one mutable owner, no App types). Every command ports a named retail function: SetHeritageGroup, SetGender, SetTemplate/ApplyTemplate (Custom = template 0, Olthoi force-lock), the six attribute setters plus GetAbsRemainingCredits/BalanceAttributes (retail's literal round-robin order and fairness cursor), SetSkillLevel plus ResetSkillLevels' free-skill baseline (reusing CC1's ChargenSkillCreditMath two-tier cost lookup verbatim), RandomizeStartArea, and DoFinish's complete gate sequence (empty name / unspent attribute credits / already-Pending / client-side roster-vs-slotCount cap). LiveSessionController gained a sibling IRuntimeCharacterCreationCommands implementation, a CreateCharacter wire hook, and a response handler that reuses existing machinery rather than inventing new paths: the Ok identity is appended to the roster via RuntimeCharacterSelectionState's own ApplyRoster, and the "log straight in" behavior reuses the private EnterSelectedCore. ILiveSessionLifecycleHost gained two default-no-op hooks (ApplyCharacterCreated/ApplyCreationFailed) so AcDream.App needs zero changes to keep compiling; wiring them to the status stream is a CC4 follow-up. Filed four divergence-register rows for the corners deliberately not ported: the FPU-unrecoverable FitTemplateToCharacter auto-detect (AP-207, ACE only reads the field for title text), the per-style color-count approximation (AP-208, CC1's model has no per-style palette data), the classID DAT-DID placeholder (AP-209, ACE ignores the field), and ApplyTemplate's atomic-vs-sequential attribute apply (AP-210). 34 new tests: full state-machine coverage (every Finish gate, every rejection-code mapping, duplicate-NameInUse tolerance, Olthoi lock, attribute balance/lock interaction, uncostable-skill rejection) plus a LiveSessionController integration suite proving the wire send is exactly 55 skill slots (decoded from a real WorldSession + GameMessageCapture) and the full Ok/rejection round trip through WorldSession.ProcessDatagram. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
f3ef7baae2
commit
9a84230c4f
9 changed files with 3043 additions and 5 deletions
File diff suppressed because one or more lines are too long
Loading…
Add table
Add a link
Reference in a new issue