fix(CT): CT3 fix round — port Refresh's unconditional selection clear, drop unresolvable-id rows
Opus dual-lens review of CT3 (03e073b7) found 1 BLOCKER + 2 SHOULD-FIX + notes.
BLOCKER: CharacterTitlesController never ported Refresh @0x0049abc0's own
SetSelectedItem(nullptr, 1) (@0x0049ac5a) — retail clears the current
title selection UNCONDITIONALLY on every Refresh() call, regardless of
whether the previously-selected id is still earned. OnTableReplaced
(0x0029) and OnDisplayTitleChanged (the display half of 0x002B) are
retail's two Refresh() call sites, so both now clear _selectedTitleId
before rebuilding/re-highlighting. OnTitleAdded (0x002B's add half) is a
DIFFERENT retail method — RecvNotice_AddCharacterTitle @0x0049a990 splices
one row without ever touching m_pSelectedItem — so it deliberately still
preserves selection. Net effect: after the user sets a display title and
ACE echoes 0x002B, the previously-highlighted row now goes dark and the
Set-as-Display button re-ghosts, matching retail; earning a new title
while a row is selected still leaves that selection alone.
SHOULD-FIX: ported AddTitleToList @0x0049A840's early-outs
(@0x0049a873/@0x0049a914) — an id of 0, or an id CharacterTitleResolver
fails to resolve, now produces NO row at all. The "Unknown" fallback
literal belongs only to the display-title text (Refresh @0x0049abc0's
other half), never a row — this was previously ported backwards.
SHOULD-FIX: rows and the display text now use their UiText's own authored
DefaultColor instead of a hardcoded Vector4.One, and each LinesProvider
now returns a cached UiText.Line[] built once per text change instead of
allocating a fresh array literal every draw call (pattern:
CharacterCreationSkillsPage.cs:829).
Notes (all ruled in): corrected two CharacterStatController comments that
falsely claimed the Titles page authors its own copies of the raise
buttons (verified against the fixture — it does not; the hide loop that
comment guarded is a defensive no-op given Visible's draw/click cascade,
kept only for the contentPage-not-found fallback); switched the row sort
from List.Sort to a stable OrderBy/ThenBy (ties broken by title id) so
equal-text rows keep retail's insert-after-equals order; wrapped the
title-resolver delegate in RetailUiRuntime.MountCharacter with the same
DatLock the row-template resolver already takes (DatCollection is
documented not thread-safe); set the list box's authored 24px row height
so wheel/line scroll lands row-aligned; kept the bind-time display-text
refresh with a comment explaining why the pre-notice "Unknown" frame is
unreachable in live play (ACE always sends 0x0029 before this panel can
open).
Tests: inverted TableReplaced_SelectedTitleStillEarned_KeepsSelectionHighlighted
into TableReplaced_ClearsSelection_EvenWhenTheSelectedIdIsStillEarned (cites
@0x0049ac5a), added its DisplayTitleChanged twin, and added
TitleAdded_PreservesSelection (the case most at risk from the blocker fix).
Inverted Rows_UnresolvedTitle_ShowsRetailUnknownLiteral into
Rows_UnresolvedTitle_ProducesNoRow (cites @0x0049a873/@0x0049a914) and added
Rows_TitleIdZero_ProducesNoRow for the other early-out. Extended
ClickingSetDisplay_..._AndMutatesNothingLocally to assert the row set and
selection are untouched by the click. Added
Fixture_PageCaptions_ResolveToNonEmptyText, which rebuilds the committed
character_2100002E.json fixture with a stub string resolver to pin this
class's own claim that the two page captions (0x1000052E/0x10000531) carry
a resolvable authored StringInfo.
Verified pre-existing/unrelated: the full hermetic suite run surfaced 2
failures in AcDream.App.Tests (LiveEntityNetworkBranchRoutingTests IL-shape
assertion, GameWindowRenderLeafCompositionTests IL-shape assertion) that
also fail with these five files stashed back to their pre-fix-round state —
confirmed unrelated to this change.
Build green. CharacterTitlesControllerTests: 24/24 (was 21, +3 net after
one invert-and-split and two new facts). Full hermetic solution suite
(Lane!=InstalledDat/PreparedPackage/Live/Manual/Timing/Windows/Linux/
SystemFont, Purpose!=Diagnostic, Status!=KnownFailure): only the two
pre-existing IL-shape failures above; every other project green.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
4ea946257d
commit
4cc9448b0a
5 changed files with 287 additions and 33 deletions
|
|
@ -233,12 +233,40 @@ not yet acted on):
|
|||
to a wire arrival; the reverse still holds (every genuine new row has
|
||||
a `TitleAdded` firing).
|
||||
|
||||
**CT3 — Titles page UI.** Bind the authored page through the standard
|
||||
**CT3 — Titles page UI. REVIEW-CLOSED 2026-08-24: landed `03e073b7`,
|
||||
Opus dual-lens review (1 BLOCKER + 2 should-fix + notes, all applied
|
||||
in the fix round below).** Bind the authored page through the standard
|
||||
GUI classes (`UiTemplateListBox`/`UiScrollbar`/`UiButton` — zero
|
||||
bespoke widgets): sorted rows via the ported title-table lookup,
|
||||
selection, ghost-when-current logic (state 0xd contract), display-title
|
||||
text, Set-as-Display round trip, scrollbar. Retires half of AP-109.
|
||||
|
||||
**CT3 fix round (Opus dual-lens review, 2026-08-24).** BLOCKER: ported
|
||||
`Refresh @0x0049abc0`'s unconditional `SetSelectedItem(nullptr, 1)`
|
||||
(`@0x0049ac5a`) — selection now clears on BOTH `TableReplaced` and
|
||||
`DisplayTitleChanged`, regardless of whether the previously-selected id
|
||||
is still earned in the new table, but deliberately survives
|
||||
`TitleAdded` (`RecvNotice_AddCharacterTitle @0x0049a990` splices one
|
||||
row without ever touching `m_pSelectedItem` — a genuinely different
|
||||
retail method from `Refresh`). SHOULD-FIX: `AddTitleToList @0x0049A840`'s
|
||||
early-outs (`@0x0049a873`/`@0x0049a914`) ported — an id of 0, or an id
|
||||
`CharacterTitleResolver.Resolve` fails to resolve, now produces NO row
|
||||
at all (the `"Unknown"` fallback literal belongs only to the
|
||||
display-title text, never a row — this was previously ported
|
||||
backwards); rows use the row template's own authored `DefaultColor`
|
||||
instead of a hardcoded white, and each row/display-text `UiText.Line[]`
|
||||
is built once per text change and cached instead of reallocated every
|
||||
draw call. Notes also applied: corrected two comments that falsely
|
||||
claimed the Titles page authors its own copies of the raise buttons
|
||||
(verified against the fixture — it does not; the hide loop that
|
||||
comment guarded is a defensive no-op, kept only for the
|
||||
contentPage-not-found fallback path), switched the row sort from
|
||||
`List.Sort` to a stable `OrderBy`/`ThenBy` (ties broken by title id),
|
||||
wrapped the title-resolver delegate in the same `DatLock` the
|
||||
row-template resolver already takes (`RetailUiRuntime.MountCharacter`),
|
||||
and set the list box's authored 24px row height so wheel/line scroll
|
||||
lands row-aligned.
|
||||
|
||||
**CT4 — Header identity block.** Retail composition: name; "<Gender>
|
||||
<Heritage> <DisplayTitle>"; PK status line — authored fonts/colors
|
||||
(pure white per probe), live refresh on display-title change and PK
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue