fix(chargen): Campaign CC gate round 1 Batch A — GF-15 input, GF-5 skills rows, GF-13 GM toggles
GF-15 (the gate blocker): the Summary name field and Finish button were
NOT structurally broken — live repro over the project's own local ACE
test server showed clicks correctly focus the field and land characters.
The real bug only surfaces after the first dialog opens: pressing Finish
empty successfully creates the NoName RetailMessageDialogView (visible,
correct 400x95 geometry) but it renders nothing and silently absorbs
every click across the whole canvas. Root cause: CharacterCreationUiController.Tick
and CharacterManagementUiController.Tick both call UiRoot.BringToFront(Root)
unconditionally every frame (needed so chargen stays above the occluded
management screen, AP-229); a dialog root is a direct sibling under the
same UiRoot, and RetailWindowManager.BringToFront is "highest ZOrder among
siblings + 1" — whichever BringToFront runs last in a frame wins.
RetailDialogFactory.Tick never re-asserted its own dialogs' z-order, so
the next frame's screen Tick buried the dialog behind the screen's opaque
backdrop while it stayed the registered Modal with exclusive input
priority. Fixed by having RetailDialogFactory.Tick re-raise every open
dialog (in open-order) each tick, matching retail's always-on-top dialog
behavior. Live-verified the complete user sequence end to end: click
field, type, press Finish empty, dialog now visibly renders, OK dismisses
cleanly, field still typable afterward. The "[ Name" prefill question is
closed as a non-bug: neither CharGenState::RandomizeCharacter nor
gmCGSummaryPage::InitializePage write text into the field in the decomp;
retail's field is genuinely empty on open, matching acdream already.
GF-5: CharacterCreationSkillsPage.RebuildRows resolved the wrong listbox
template (Templates[0], retail's own 3-child bucket-header row) and
required the root to be a UiButton (it's a plain container). Byte-traced
gmCGSkillsPage::DoSkillRecords + tagSkillRecord's copy-ctor field order
to map every child id in the real row (Templates[1]): name, level/cost
text, and the two real per-row up/down arrow buttons. Wired the arrows to
retail's own plain-click dispatch, retiring (narrowing) AP-213's
click-to-advance/double-click-retreat single-button substitution.
GF-13: dat property 0x3B (Invisible) was never read by the importer.
Elements 0x10000403/0x10000494 ("Non-Admin"/"Non-Envoy") author it true.
A blast-radius sweep found 1,083 elements client-wide author the same
flag, so this fix stays chargen-scoped only (ElementInfo.Invisible /
UiElement.AuthoredInvisible are pure data additions; only
CharacterCreationUiController acts on them, by the authored flag, not a
hardcoded id list). General importer-wide honor filed as ISSUES.md #408;
register row AP-230 records the split.
Gates: solution build green; App 5266/3 skips/0 failed; Runtime 1735/0;
full-solution run 0 failures anywhere. Register: AP-230 filed, AP-213
narrowed. ISSUES: #408 filed.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
6699e0f88c
commit
1d9de5e095
11 changed files with 823 additions and 78 deletions
|
|
@ -255,11 +255,53 @@ public sealed class RetailDialogFactory : IDisposable
|
|||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// GF-15 fix (Campaign CC gate round 1, Batch A, 2026-08-16). Live-repro-
|
||||
/// confirmed root cause: <c>CharacterCreationUiController.Tick</c> and
|
||||
/// <c>CharacterManagementUiController.Tick</c> both call
|
||||
/// <c>UiRoot.BringToFront(Root)</c> UNCONDITIONALLY on every frame while
|
||||
/// their screen is open — a per-tick "stay on top of my sibling screen"
|
||||
/// assertion (needed so chargen never bleeds input to the occluded
|
||||
/// char-management screen underneath it, register AP-229). A dialog this
|
||||
/// factory opens is ALSO a direct sibling of those screen roots under
|
||||
/// the same <c>UiRoot</c> (<c>_host.AddChild(view.Root)</c> in
|
||||
/// <see cref="TryCreateDialog"/>), competing for the SAME z-order slot.
|
||||
/// <see cref="RetailWindowManager.BringToFront"/> is a simple "highest
|
||||
/// ZOrder among <c>_root</c>'s direct children + 1" — whichever sibling's
|
||||
/// own <c>BringToFront</c> call runs LAST in a frame wins the top slot.
|
||||
/// Before this fix, this method never re-asserted a dialog's own
|
||||
/// z-order after the one-time raise in <see cref="TryCreateDialog"/>, so
|
||||
/// the VERY NEXT frame's screen <c>Tick()</c> (which always runs before
|
||||
/// this factory's own <c>Tick()</c> in
|
||||
/// <c>RetailUiRuntime.Tick(double)</c>'s per-frame sequence) silently
|
||||
/// buried the dialog behind the screen's opaque backdrop — while the
|
||||
/// dialog remained the registered <see cref="UiRoot.Modal"/> and kept
|
||||
/// EXCLUSIVE input priority (<c>OnMouseDown</c>'s Modal-vs-bounds gate is
|
||||
/// independent of render/z-order). The user-visible symptom: press
|
||||
/// Finish empty → the NoName dialog is created successfully
|
||||
/// (<c>visible=true</c>, correct geometry, live-DAT-probe-confirmed) but
|
||||
/// renders NOTHING, and every subsequent click across the WHOLE canvas
|
||||
/// resolves to the invisible dialog root instead of the name field or
|
||||
/// Finish button underneath — both GF-15 symptoms from one mechanism.
|
||||
/// Retail's real dialogs are always-on-top overlays by construction (a
|
||||
/// separate presentation layer, not a z-ordered sibling of the game UI);
|
||||
/// re-asserting every open dialog's z-order here, every tick, in
|
||||
/// <see cref="_openOrder"/> order (so the MOST RECENTLY opened dialog —
|
||||
/// the same one <see cref="RefreshModal"/> already treats as
|
||||
/// authoritative — ends up on top) reproduces that invariant without
|
||||
/// touching either screen controller's own already-verified raise.
|
||||
/// </summary>
|
||||
public void Tick()
|
||||
{
|
||||
RetryFailedDialogs();
|
||||
foreach (DialogInfo info in _openOrder.ToArray())
|
||||
info.View?.Tick();
|
||||
{
|
||||
if (info.View is { } view)
|
||||
{
|
||||
_host.BringToFront(view.Root);
|
||||
view.Tick();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue