feat(chargen): Campaign CC slice CC5 — Summary page, Finish flow, RandomizeCharacter port
Fills TS-82's Summary placeholder with a faithful port of gmCGSummaryPage (name field with NameInputFilter + the retail commit-on-focus-lost/submit dispatch + the >32-char ID_CharGen_NameTooLong reject-and-revert path, the REAL three-row-template listbox confirmed against the installed EoR dat before writing any page code, and Summary's own independent gmCG3DView preview instance wired through a second ChargenPreviewController pair mirroring the Appearance page's exact composition shape). Ports CharGenState::RandomizeCharacter and its six sub-primitives into RuntimeCharacterCreationState — not approximated: the RandInt/RollDice semantics are independently confirmed from both the decompiled RNG bodies and the CharGenStateVtbl union struct in acclient.h. Three consumers: the chargen screen's open-roll (retiring AP-214's honest-blank deviation and reproducing the Appearance page's gender-flip-on-init quirk), the Summary page's Random button (behind the retail randomize-warning confirm), and the Appearance page's Random button (narrowing AP-212 to just Heritage/Profession/Town's still-approximated rolls and Skills' still-unported RandomizeSkills). Wires the Finish button (previously ghosted) with retail's NoName/ CreditWarning dialog pair, adds the F12 amendment's HeritageOrGenderUnset local refusal to TryBeginFinish (register AP-223) as a defensive backstop now that the screen-open roll normally makes it unreachable, and wires the four ID_Character_Err_* rejection dialogs for the 0xF643 response codes CC3 already parsed but nothing displayed. Register: TS-82 retired, AP-214 retired, AP-212 narrowed, AP-223/224/225 filed (heritage/gender Finish refusal, Summary's two-bucket skill-list narrowing, the 32-vs-33 name-length threshold reconciliation). Runtime 1722/0 (was 1713), App 5240/3 skips (was 5223/3), Headless 166/0 unchanged, full solution Release build green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
6114b2dda2
commit
34e3a534be
22 changed files with 2217 additions and 79 deletions
|
|
@ -122,7 +122,8 @@ public sealed class CharacterCreationLiveDatTests
|
|||
CharacterCreationUiController? controller =
|
||||
CharacterCreationUiController.CreateDetached(
|
||||
host, screen, ResolveTemplate, dialogs, bindings,
|
||||
new CharacterCreationUiController.DialogStrings("Are you sure?"));
|
||||
new CharacterCreationUiController.DialogStrings(
|
||||
"Are you sure?", "No name", "Unspent credits", "Randomize?", "Name too long"));
|
||||
Assert.NotNull(controller);
|
||||
controller!.AttachAndTick();
|
||||
controller.Dispose();
|
||||
|
|
@ -515,6 +516,62 @@ public sealed class CharacterCreationLiveDatTests
|
|||
return new RetailDialogFactory(host, CreateLayout);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Campaign CC slice CC5 — the Summary page's full authored widget
|
||||
/// catalog: the name field (with <c>NameInputFilter</c>), the how-to
|
||||
/// text, the viewport (Summary's OWN <c>gmCG3DView</c>), and the
|
||||
/// listbox's THREE row templates (single-line, category-header,
|
||||
/// key/value pair) confirmed against the installed EoR dat — see
|
||||
/// <see cref="CharacterCreationSummaryPage"/>'s own class doc for the
|
||||
/// decomp citation (<c>SetSummaryText @ 0x0047b1d0</c>) each template
|
||||
/// maps to.
|
||||
/// </summary>
|
||||
[InstalledDatFact]
|
||||
public void SummaryPage_HasNameFieldListboxTemplatesAndViewport()
|
||||
{
|
||||
using var dats = new DatCollection(DatDirectory, DatAccessType.Read);
|
||||
uint layoutId = RetailDataIdResolver.Resolve(
|
||||
dats,
|
||||
CharacterCreationUiController.RootEnum,
|
||||
5u);
|
||||
ImportedLayout screen = BuildSelected(
|
||||
dats, layoutId, CharacterCreationUiController.RootElementId);
|
||||
|
||||
UiElement summaryRoot = Assert.IsAssignableFrom<UiElement>(
|
||||
screen.FindElement(CharacterCreationUiController.SummaryPageElementId));
|
||||
|
||||
Assert.IsType<UiScrollbar>(
|
||||
UiElement.FindDescendant(summaryRoot, CharacterCreationSummaryPage.ScrollId));
|
||||
Assert.IsType<UiField>(
|
||||
UiElement.FindDescendant(summaryRoot, CharacterCreationSummaryPage.NameTextId));
|
||||
Assert.IsType<UiText>(
|
||||
UiElement.FindDescendant(summaryRoot, CharacterCreationSummaryPage.HowToTextId));
|
||||
Assert.IsType<UiViewport>(
|
||||
UiElement.FindDescendant(summaryRoot, CharacterCreationSummaryPage.ViewportId));
|
||||
|
||||
UiTemplateListBox list = Assert.IsType<UiTemplateListBox>(
|
||||
UiElement.FindDescendant(summaryRoot, CharacterCreationSummaryPage.ListBoxId));
|
||||
Assert.Equal(3, list.Templates.Count);
|
||||
|
||||
UiElement? ResolveRow(int index) =>
|
||||
LayoutImporter.Import(
|
||||
dats,
|
||||
list.Templates[index].TemplateLayoutId,
|
||||
list.Templates[index].TemplateElementId,
|
||||
_ => (0u, 0, 0),
|
||||
null)?.Root;
|
||||
|
||||
UiElement lineRow = Assert.IsAssignableFrom<UiElement>(ResolveRow(0));
|
||||
Assert.IsType<UiText>(UiElement.FindDescendant(lineRow, 0x100002F9u));
|
||||
|
||||
UiElement headerRow = Assert.IsAssignableFrom<UiElement>(ResolveRow(1));
|
||||
Assert.IsType<UiText>(UiElement.FindDescendant(headerRow, 0x100000FEu));
|
||||
|
||||
UiElement pairRow = Assert.IsAssignableFrom<UiElement>(ResolveRow(2));
|
||||
Assert.IsType<UiText>(UiElement.FindDescendant(pairRow, 0x100002FCu));
|
||||
Assert.IsType<UiText>(UiElement.FindDescendant(pairRow, 0x100002FDu));
|
||||
}
|
||||
|
||||
private static void AssertButton(ImportedLayout layout, uint elementId) =>
|
||||
Assert.IsType<UiButton>(layout.FindElement(elementId));
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue