fix(chargen): Campaign CC gate round 1 Batch C — Summary how-to + scrollbar linkage
Commit 3/3: Summary how-to text + Commit 2's owed scrollbar linkage + bookkeeping sweep. - Ports gmCGSummaryPage::SetHowToText @0x0047ae20 into the Summary page's how-to box (0x10000404, HowToTextId was declared and unused since CC5). Retail concatenates ID_CharGen_SummaryHowTo + a heritage/ gender-specific name-suggestion list (heritages 1-4 — Aluvian/ Gharundim/Sho/Viamontian — only; heritages 5-13's cases in the same switch decompile to a vtable-slot artifact, the same decompiler- mangled-symbol class the Heritage page's own BonusSkillsKeyByHeritage table already documents, so no name-suggestion string exists for them and none is invented) + ID_CharGen_SummaryHowToEnd, directly concatenated (no separator literal) into ONE plain SetText call — no per-run font/color argument, unlike Heritage's ...WithFont calls, so this routes through DatRichText as a single DefaultColor segment. - Wires the description boxes' linked scrollbar to actual text scrolling — Commit 2 made the scrollbar child (0x100002e7) BUILD as a real UiScrollbar; this binds scrollbar.Model = text.Scroll, the exact pattern ChatWindowController already uses for the chat transcript. Live-DAT-measured: only Heritage's description (0x100003c4) and Summary's how-to box (0x10000404) actually author this child — Profession/Town's shorter description boxes do not (a genuine retail authoring fact, not something to "fix" further). Register: AP-215/AP-216/AP-217 rewritten (Batch C's Commit 1 already retired AP-218/AD-103) — no further changes needed this commit; ISSUES #366 (chat's new-unseen-text indicator, 0x1000048C under the chat transcript 0x10000011) NARROWED — its own pre-filed "fix shape" recommendation (a UiText child carve-out mirroring UiMeter's) is EXACTLY what Commit 2 shipped, confirmed by that commit's own client-wide sweep; #366 stays open for the still-missing behavioral half (no controller drives the indicator's visibility/click). Findings doc updated: GF-2/GF-3/GF-4/GF-6/GF-11a/GF-12/GF-14's text half all marked FIXED with their own root-cause notes; the two remaining "suspected shared roots" (frames/labels, rich text) marked CONFIRMED + CLOSED. Full App suite (Debug and Release, live-DAT): 5307 passed / 0 failed / 3 skipped (up from 5304 after Commit 2). Runtime suite: 1735/0, unaffected. Campaign CC gate round 1 Batch C is CODE-COMPLETE across all three commits — GF-2, GF-3, GF-4, GF-6, GF-11a, GF-12, and GF-14's text half are fixed; AP-216/AP-217 partially closed (register-honest about what shipped vs what needs a palette-to-RGB pipeline this batch didn't add). Pending the user's visual gate, with chat + the main game UI flagged for extra attention (Commit 2's client-wide blast radius). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
5190e16915
commit
2349f8b4df
6 changed files with 391 additions and 45 deletions
|
|
@ -1791,29 +1791,25 @@ controllers read instead of the main window's private field.
|
|||
|
||||
## #366 — Chat window's new-unseen-text indicator (0x1000048C) imports but is never independently wired
|
||||
|
||||
**Status:** OPEN — filed 2026-08-10, Campaign CH slice CH6a. The retail main
|
||||
chat window authors a 16×16 "new unseen text" indicator button
|
||||
(`0x1000048C`, base `0x10000527`/`0x21000040`) as a CHILD of the transcript
|
||||
text element `0x10000011` (position `(0,57)` relative to the transcript,
|
||||
i.e. bottom-left of the transcript pane), confirmed in the `0x2100006F`
|
||||
LayoutDesc dump. `UiText.ConsumesDatChildren` is `true` (Type-12 behavioral
|
||||
widgets reproduce their dat sub-elements procedurally per
|
||||
`DatWidgetFactory`'s own doc comment), so `LayoutImporter.BuildWidget`
|
||||
never builds `0x1000048C` as a separate widget — it is silently swallowed,
|
||||
same as under the wrong `0x21000006` layout before it (not a CH6a
|
||||
regression). No controller anywhere binds or drives its visible state.
|
||||
**Not in CH6a's scope** (transcript/input/scrollbar/1-4-buttons only) and
|
||||
not obviously CH6b/CH6c's either — files here as a standalone gap. Fix
|
||||
shape: either give `UiText` an opt-in mechanism to keep specific named
|
||||
non-Type-3 children (mirroring `UiMeter`'s existing text-overlay carve-out
|
||||
in `DatWidgetFactory.BuildWidget`), or handle `0x1000048C` as a special
|
||||
case the same way. Needs research first: what triggers retail's "new text"
|
||||
indicator (unread-since-scroll-position?) and what it visually does on
|
||||
click — not decoded by CH6a.
|
||||
**Status:** OPEN, NARROWED 2026-08-16 at Campaign CC gate round 1 Batch C
|
||||
Commit 2 — the BUILD half of this issue's own "fix shape" recommendation is
|
||||
now DONE. `LayoutImporter.BuildWidget` gained a `UiText`/`UiField`
|
||||
media-bearing-child carve-out (mirroring `UiMeter`'s own text-overlay
|
||||
carve-out, EXACTLY the shape this issue proposed) as part of a chargen
|
||||
description-box fix; the client-wide blast-radius sweep that fix's own
|
||||
tests run
|
||||
(`LayoutImporterMediaBearingChildSweepTests.MediaBearingChildSweep_EnumeratesEveryAffectedType12Element`)
|
||||
independently re-confirmed `0x1000048C` under `0x10000011` in layout
|
||||
`0x2100006F` as one of the affected elements — it now builds as a real
|
||||
widget instead of being silently swallowed. **Still open:** no controller
|
||||
binds or drives its visible state (STILL the original ask — what triggers
|
||||
retail's "new text" indicator, and what it does on click, remains
|
||||
un-researched); this issue stays open for that behavioral half.
|
||||
|
||||
**Where:** `src/AcDream.App/UI/Layout/ChatWindowController.cs`;
|
||||
`src/AcDream.App/UI/Layout/LayoutImporter.cs`
|
||||
(`BuildWidget`/`ConsumesDatChildren` handling); `src/AcDream.App/UI/UiText.cs`.
|
||||
**Where:** `src/AcDream.App/UI/Layout/ChatWindowController.cs` (behavior,
|
||||
still missing); `src/AcDream.App/UI/Layout/LayoutImporter.cs`
|
||||
(`BuildWidget`'s new `UiText or UiField` carve-out — CLOSED the build half);
|
||||
`src/AcDream.App/UI/UiText.cs`.
|
||||
|
||||
## #367 — ChatCommandRouter's local-presentation fallbacks type-0x1A text still lands in the chat scroll, never the SpewBox
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,32 @@ Fixture + live-DAT tests only this round (no graphical client launch);
|
|||
App suite 5282/3 (was 5266/3), Runtime 1735/0 unchanged. Register:
|
||||
AP-222 RETIRED, AP-215 NARROWED (item 1 retired, item 2 stays open).
|
||||
|
||||
**Batch C (text/frame/label fidelity, the largest visual batch) is
|
||||
CODE-COMPLETE 2026-08-16, pending the user's visual gate.** GF-2, GF-3,
|
||||
GF-4, GF-6, GF-11a, GF-12, and GF-14's text half are fixed — see each
|
||||
entry's own FIXED note below. Three commits: (1) chargen-scoped rich
|
||||
text + labels + backdrops (new shared `DatRichText` composer; `UiButton`
|
||||
gains a coexisting `ValueLabel` slot; Heritage/Profession backdrop
|
||||
`SetState` cascades; AP-216/AP-217 partially closed — the "beyond count"/
|
||||
"Eyes-blank" halves ship, the palette-to-RGB "actual color"/"gradient
|
||||
tint" halves stay open, judged disproportionate to add alongside this
|
||||
batch's ~10 other fixes), (2) a CLIENT-WIDE `LayoutImporter` fix
|
||||
un-consuming media-bearing dat children on `UiText`/`UiField` (37 distinct
|
||||
(layout, element) pairs across 15 layouts, independently re-derived —
|
||||
includes MAIN GAME UI and CHAT INPUT, closing the build half of pre-filed
|
||||
issue #366), (3) the Summary how-to text
|
||||
(`gmCGSummaryPage::SetHowToText`) plus the scrollbar-to-text-scroll
|
||||
linkage Commit 2 left unbound. Fixture + live-DAT tests only (no
|
||||
graphical client launch); App suite 5307/3 (was 5282/3, +25 tests, one
|
||||
pre-existing full-suite-only allocation flake unrelated to this batch —
|
||||
passes in isolation and in the full Release run), Runtime 1735/0
|
||||
unchanged. Register: AP-215/AP-216/AP-217 rewritten, AP-218 retired,
|
||||
AD-103 retired. **FLAG FOR THE LEAD: chat and the main game UI both
|
||||
render new dat children (gold frames, an unseen-text indicator) for the
|
||||
first time this batch — the user's own visual check of both is owed
|
||||
before considering Commit 2 closed; automated coverage cannot catch a
|
||||
purely visual placement regression.**
|
||||
|
||||
User ran the six-page chargen flow live (build `1.0.2-cc.e`, RDP session,
|
||||
windowed). Screenshots: retail Heritage, acdream Heritage, retail
|
||||
Profession. The user's side-by-side retail reports are AXIOMS
|
||||
|
|
@ -86,7 +112,17 @@ ISSUES.md; this doc is the six-page batch.
|
|||
exactly one overlay visible per part, tracking the current part's
|
||||
selected color index; retires AP-215's swatch-selection substitution
|
||||
(item 1 — the icon-vs-ordinal item 2 stays open).
|
||||
- **GF-11a Town description text does not change** when switching towns.
|
||||
- **GF-11a Town description text does not change when switching towns —
|
||||
FIXED (Batch C, Commit 1).** The composed string
|
||||
(`gmCGTownPage::SetTownString @0x0047c1f0`'s `howTo + "\n\n" + townText +
|
||||
"\n"` — this ONE composition site is where retail's OWN code, not the
|
||||
authored DAT string content, inserts the separator, confirmed via the
|
||||
compiled format literal's raw bytes `u"\n\n%s\n"`) was already
|
||||
byte-correct; the real gap was rendering it as a single un-wrapped line,
|
||||
so the town-specific SUFFIX rendered past the clipped viewport —
|
||||
switching towns changed the underlying string but not what was visibly
|
||||
on screen. Fixed by routing through `DatRichText.Compose` (same fix
|
||||
family as GF-2).
|
||||
- **GF-13 Summary shows "-Non-admin or Non-envoy" below the name — FIXED
|
||||
(Campaign CC gate round 1, Batch A) — this commit.** Root cause: dat
|
||||
property `0x3B` (Invisible — `UIElement::OnSetAttribute @0x00462d80`
|
||||
|
|
@ -151,20 +187,55 @@ ISSUES.md; this doc is the six-page batch.
|
|||
|
||||
## Presentation families (retail parity)
|
||||
|
||||
- **GF-2 Description textboxes broken everywhere.** acdream renders the
|
||||
raw string with LITERAL `\n` escapes, one truncated line, no wrap, no
|
||||
scroll, no frame. Retail: framed scrollable textbox, multi-paragraph,
|
||||
colored section headers (green "Trained Starting Skills:" etc.),
|
||||
scrollbar + arrows (screenshot 1 right panel).
|
||||
- **GF-3 Profession template description textbox missing** (retail bottom-
|
||||
left panel, "LIFE CASTERS are experts…" — screenshot 3).
|
||||
- **GF-4 Profession labels missing:** "Attribute Credits" caption + value,
|
||||
per-attribute name labels (Strength…Self), Health/Stamina/Mana labels +
|
||||
values. Sliders and template selection themselves WORK.
|
||||
- **GF-6 Appearance spin captions are numbers,** not part names
|
||||
("Hair Style", "Eyes", …). Known rows AP-215 (item 2 — item 1, the
|
||||
swatch-selection substitution, RETIRED at Batch B/GF-9)/AP-218 — the
|
||||
gate promotes them to must-port.
|
||||
- **GF-2 Description textboxes broken everywhere — FIXED (Campaign CC gate
|
||||
round 1, Batch C, Commit 1 + Commit 2).** Root cause was TWO stacked
|
||||
gaps, both closed: (1) the Heritage/Town/Profession description pages
|
||||
bypassed escape-normalize + word-wrap entirely, assigning a raw
|
||||
unwrapped single-`Line` `LinesProvider` — fixed by routing every
|
||||
description box through the new shared `DatRichText.Compose` helper
|
||||
(ports `UIElement_Text::SetStringInfoWithFont`/`AppendStringInfoWithFont`'s
|
||||
composition model: escape-normalize, per-segment word-wrap, per-segment
|
||||
palette color — Heritage's own header/body segments now render in
|
||||
retail's own green/white, matching `AppendStringInfoWithFont`'s font-index
|
||||
argument). (2) The authored gold frame (8 pieces) and linked scrollbar
|
||||
were silently dropped by `UiText.ConsumesDatChildren` — fixed by
|
||||
Commit 2's client-wide `LayoutImporter` carve-out (see GF-12). Both
|
||||
halves are pinned by live-DAT tests (`CharacterCreationLiveDatTests`,
|
||||
`LayoutImporterMediaBearingChildSweepTests`) and unit tests
|
||||
(`DatRichTextTests`).
|
||||
- **GF-3 Profession template description textbox missing — FIXED (Batch C,
|
||||
Commit 1).** `gmCGProfessionPage::InitializePage @0x00483068`'s
|
||||
`m_pTextBox` (`0x100003e0`) was never bound. Fixed:
|
||||
`CharacterCreationProfessionPage` now binds it and composes the
|
||||
per-template string (`ID_CharGen_CustomText`/`BowText`/`SwashText`/
|
||||
`LifeText`/`WarText`/`WayText`/`SoldierText`, `UpdateProfession
|
||||
@0x004821b0`'s per-case literal, plain `SetStringInfo` — one color, no
|
||||
palette) through the same `DatRichText` helper.
|
||||
- **GF-4 Profession labels missing — FIXED (Batch C, Commit 1).** Two
|
||||
distinct mechanisms, both closed: (a) the four display buttons
|
||||
(avail/health/stamina/mana credits) author their caption directly as
|
||||
their own P0x17 AND carry a separate media-less Type-12 value child that
|
||||
`UiButton.ConsumesDatChildren` used to drop entirely — pages substituted
|
||||
the button's own `.Label`, destroying the caption. Fixed by giving
|
||||
`UiButton` a coexisting `ValueLabel`/`ValueBox`/`ValueFont`/`ValueColor`
|
||||
slot (`DatWidgetFactory.BuildButton`, gated on the button's own P0x17
|
||||
caption existing), so the caption and the live value now render
|
||||
independently — the same fix also closes the Skills page's credits
|
||||
badge. (b) The six slider name labels (`0x100002ed`, live-DAT-measured
|
||||
as `UIElement_Button` — retail's `UIElement_Button` is DynamicCast(0xc)-
|
||||
compatible with `UIElement_Text`) are now written once at construction
|
||||
with `CharGenState::GetAttributeName @0x005C3A20`'s six hardcoded
|
||||
literals, matching retail's own single `InitializePage`-time write
|
||||
(never re-written on refresh, same as retail).
|
||||
- **GF-6 Appearance spin captions are numbers — FIXED (Batch C, Commit 1),
|
||||
retiring AP-218.** `gmCGAppearancePage::Update @0x0047e8f0` writes a
|
||||
heritage-flavored STATIC caption to the Hair/Eyes/Skin spins only
|
||||
(normal / `GearText_*` / `OlthoiText_*` variants) — never an index, and
|
||||
never touches the other six spins' own DAT-authored caption at all.
|
||||
Removed the prior 1-based-ordinal/gear-name substitution outright.
|
||||
AP-215's own icon-thumbnail item (the four icon-only spins still show no
|
||||
per-choice icon art — a DIFFERENT, still-open gap) is rewritten, not
|
||||
retired — see that row.
|
||||
- **GF-7 Preview backdrop black** on Appearance (and Summary, GF-14);
|
||||
retail's chargen 3D view shows a scenic backdrop. (The Heritage-page
|
||||
preview area shows terrain in BOTH clients — establish from the decomp
|
||||
|
|
@ -218,19 +289,53 @@ ISSUES.md; this doc is the six-page batch.
|
|||
caption carries its own rect, the label draws within THAT box using
|
||||
its own authored justify instead of the face-relative offset; every
|
||||
other button (`LabelBox` null) keeps the EXACT prior draw math.
|
||||
- **GF-12 Missing authored gold frames** around boxes on every page
|
||||
(Skills/Appearance/Town/Summary called out explicitly).
|
||||
- **GF-14 Summary paperdoll backdrop black** (same family as GF-7);
|
||||
Summary textbox wrapper + scrollbar missing (GF-2 family).
|
||||
- **GF-12 Missing authored gold frames around boxes — FIXED (Batch C,
|
||||
Commit 2).** Root cause: `UiText.ConsumesDatChildren` (true unless a
|
||||
state authors PassToChildren) and `UiField.ConsumesDatChildren`
|
||||
(unconditionally true) dropped EVERY dat child at import time,
|
||||
including the eight gold-frame pieces (`0x100002DE..E3`,
|
||||
`0x100000E8/EA`) every description/report box authors. Fixed by a new
|
||||
`LayoutImporter.BuildWidget` carve-out (mirroring the existing `UiMeter`
|
||||
text-overlay carve-out): build any child with its OWN non-empty
|
||||
`StateMedia`, leaving purely structural/property-only children dropped
|
||||
as before. Independently re-derived blast radius: **37 distinct
|
||||
(layout, element) pairs across 15 layouts** (see the commit message for
|
||||
the full enumeration), including MAIN GAME UI (`0x21000005/0x1000059A`)
|
||||
and CHAT INPUT (`0x2100006F/0x10000011` — closing the BUILD half of
|
||||
pre-filed issue #366's own "fix shape" recommendation, which proposed
|
||||
this EXACT carve-out). Full App suite (5304 tests): zero regressions.
|
||||
**The user's own visual check of chat + the main game UI is still owed**
|
||||
— automated coverage cannot catch a purely visual placement regression.
|
||||
- **GF-14 Summary paperdoll backdrop black** (same family as GF-7,
|
||||
UNCHANGED, out of this batch's scope — the 3-D preview backdrop, not a
|
||||
text-widget gap). **Summary textbox wrapper + scrollbar — FIXED (Batch
|
||||
C, Commit 2 for the frame/build half, Commit 3 for the scrollbar LINK
|
||||
and the how-to text's own content — see the Suspected-shared-roots
|
||||
entry and Commit 3's own composition of `gmCGSummaryPage::SetHowToText`
|
||||
into `0x10000404`).**
|
||||
- **GF-16 Hover tooltips missing on all pages** (retail pops tooltips).
|
||||
|
||||
## Suspected shared roots (to be CONFIRMED by the investigation, not assumed)
|
||||
|
||||
1. Missing frames/labels/statics across every page (GF-3, GF-4 labels,
|
||||
1. ~~Missing frames/labels/statics across every page (GF-3, GF-4 labels,
|
||||
GF-12) — one importer/mount-level gap OR retail writes them at runtime;
|
||||
decide per element from the authored DAT + decomp.
|
||||
2. Rich text (escape decoding, wrap, scroll, frame) — one text-widget gap
|
||||
feeding GF-2/GF-3/GF-11a/GF-14.
|
||||
decide per element from the authored DAT + decomp.~~ CONFIRMED, CLOSED
|
||||
at Batch C: TWO distinct mechanisms, both a single shared fix each. (a)
|
||||
GF-3/GF-4's labels were runtime-composition gaps (unbound description
|
||||
textbox; a value-write clobbering a caption) — fixed per-page, Commit 1.
|
||||
(b) GF-12's frames were the importer-level gap the investigation
|
||||
suspected: `LayoutImporter.BuildWidget`'s `ConsumesDatChildren` handling
|
||||
dropped every dat child of a `UiText`/`UiField`, client-wide — fixed by
|
||||
the new media-bearing-child carve-out, Commit 2.
|
||||
2. ~~Rich text (escape decoding, wrap, scroll, frame) — one text-widget gap
|
||||
feeding GF-2/GF-3/GF-11a/GF-14.~~ CONFIRMED, CLOSED at Batch C: the new
|
||||
shared `DatRichText.Compose` helper (escape-normalize + per-segment
|
||||
word-wrap + per-segment palette color, Commit 1) plus the Commit-2 frame/
|
||||
scrollbar un-consume plus Commit-3's scrollbar-to-text-scroll linkage
|
||||
(`UiScrollbar.Model = text.Scroll`, the same pattern
|
||||
`ChatWindowController` already used) together close the WHOLE family —
|
||||
GF-2/GF-3/GF-11a/GF-14's text half are all FIXED; GF-14's backdrop half
|
||||
(GF-7 family) is unrelated and stays open.
|
||||
3. ~~Selection state media (GF-1 dot, GF-8 sub-tabs, GF-11b white marker,
|
||||
GF-10 zoom art) — the AP-222 measured mechanism (state media authored
|
||||
vs applied) across widget kinds.~~ CLOSED, split into TWO distinct
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue