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
|
|
@ -24,6 +24,53 @@ What does NOT go here:
|
|||
- Every session: scan OPEN issues at start; promote/close anything we touched during the session before ending.
|
||||
- Promoting to a Phase: mark as `DONE (promoted to Phase X)` + commit SHA where the Phase entry landed.
|
||||
|
||||
## #408 — General importer-wide honor of dat property 0x3B (Invisible) is unshipped (1,083 elements client-wide)
|
||||
|
||||
**Status:** OPEN
|
||||
**Severity:** LOW-MEDIUM (cosmetic — extra/leaked elements render where retail hides them; no gameplay/wire impact)
|
||||
|
||||
Found while fixing GF-13 (Campaign CC gate round 1, Batch A, 2026-08-16):
|
||||
acdream's `LayoutImporter`/`DatWidgetFactory` never read dat property
|
||||
`0x3B` (Invisible — `BoolBaseProperty`), which retail's
|
||||
`UIElement::OnSetAttribute @0x00462d80` case 8
|
||||
(`GetPropertyName()-0x33==8`) honors on EVERY element via
|
||||
`SetVisible(value==0)`. The blast-radius sweep this fix's investigation
|
||||
ran found **1,083 elements client-wide** author `P0x3B=true` — far
|
||||
beyond the two chargen-Summary GM labels (`0x10000403`
|
||||
"Non-Admin"/`0x10000494` "Non-Envoy") the user actually reported.
|
||||
|
||||
The fix (`fix(chargen): Campaign CC gate round 1 Batch A`) added the data
|
||||
plumbing everywhere (`ElementInfo.Invisible`, read in
|
||||
`ElementReader.ApplyCanonicalLegacyProjection`; `UiElement.AuthoredInvisible`,
|
||||
set in `LayoutImporter.BuildWidget`) but deliberately does NOT act on it
|
||||
in the shared importer path — only `CharacterCreationUiController`
|
||||
(`HideAuthoredInvisibleElements`) walks its own mounted subtree and
|
||||
hides what it finds, chargen-scoped only. Register row AP-230 records
|
||||
the split.
|
||||
|
||||
Honoring the flag client-wide (setting `UiElement.Visible = false`
|
||||
directly in `LayoutImporter.BuildWidget` when `info.Invisible` is true,
|
||||
or an equivalent central chokepoint) is straightforward, but 1,083
|
||||
elements is its own visual-regression surface: any one of them could be
|
||||
an element some OTHER screen currently relies on being visible despite
|
||||
authoring the flag (e.g. a state-conditional visibility toggle that
|
||||
happens to leave `0x3B=true` on its default/direct state while a
|
||||
controller separately manages `Visible` at runtime). This needs its own
|
||||
sweep — dump the 1,083 ids grouped by owning LayoutDesc/screen, spot-check
|
||||
a representative sample per screen against retail, then flip the
|
||||
importer-wide switch with a dedicated visual gate — not a one-line
|
||||
change folded into an unrelated fix.
|
||||
|
||||
Fix direction: (1) enumerate the 1,083 ids per LayoutDesc (a live-DAT
|
||||
probe test, similar to `SpewBoxLayoutDumpDiagnostic`); (2) for each
|
||||
distinct screen/LayoutDesc, confirm honoring the flag doesn't hide
|
||||
something the runtime currently manages visibility of dynamically at that
|
||||
SAME element id (would double-drive `Visible`); (3) flip the honor in
|
||||
`LayoutImporter.BuildWidget` (mirroring the chargen-scoped code path
|
||||
already proven live) and delete `CharacterCreationUiController`'s own
|
||||
narrow `HideAuthoredInvisibleElements`/AP-230 in the same commit; (4) run
|
||||
a full-client visual matrix, not just chargen.
|
||||
|
||||
## #407 — Windowed resolution offering starves on RDP/virtual displays (video-mode gating)
|
||||
|
||||
**Status:** DONE (`e601a496`, 2026-08-16 — same gate round, user-directed immediate fix)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue