feat(ui): Campaign CT slice CT4 — header identity block retail-exact
Retires the rest of AP-109's UI half: the character panel's Name/Heritage/ PkStatus/Level header identity block is now live and DAT-faithful on both Attributes and Skills pages (verified: CharacterStatController.Bind already scopes Label/LabelAuthoredColor to the ONE physically-visible page container, so both tabs share the same bound widgets). - Name/Heritage/PkStatus/Level switch from hand-picked Body/Gold runtime colors to the widget's own authored DefaultColor (LabelAuthoredColor) — CT1's live-DAT pin (HeaderElements_AuthorExpectedFontsAndColors) confirmed all four already carry the correct FontColor (white/white/white/pale-gold with Outline); the former "runtime color, dat carries none" comment was false. - PkStatus resolves through StringTable 0x23000001 by key (ID_StatManagement_Header_PKStatus_PK/_PKL/_NPK) with a bitwise IsPK/IsPKLite test (gmStatManagementUI::UpdatePKStatus @0x004F00A0) instead of the prior exact-equality switch, which silently dropped combined-flag PlayerKillerStatus values. Live-DAT-verified strings: "Player Killer" / "Player Killer Lite" / "Non-Player Killer" (new InstalledDat pin PkStatusKeys_ResolveExpectedAuthoredStrings). - Level shows "%d"-formatted InqInt(0x19) or the PE-recovered literal "???" when absent (CharacterSheet.Level is now int?). - Heritage line appends CT2/CT3's resolved RuntimeCharacterTitleState display title through CharacterTitleResolver, refreshing live on both TableReplaced (0x0029) and DisplayTitleChanged (0x002B) — CharacterSheetProvider's ChangeBinding now subscribes to both. - Name-line ruling: ships the PLAIN-NAME case only. Retail's allegiance rank-title prefix (AllegianceData::GetFullName @0x005B6950 -> AllegianceSystem::GetTitle @0x005B8DD0) needs a ~200-string, 22-function heritage x gender table (verbatim decomp literals, e.g. GetAluvianMaleTitle @0x005B7BC0's Yeoman/Baronet/.../High King) judged out of reasonable size for this slice. RuntimeAllegianceState already carries the local player's own rank; only the string table is missing. Registered, not silently omitted. - Luminance pair (0x100005C5/0x100005C6): CharacterSheet.AvailableLuminance/ MaximumLuminance (PropertyInt64 6/7) already flow generically through both the PlayerDescription snapshot and the live 0x02CF private-update parsers (no wiring gap). The retail show/hide gate (Level >= 200 && MaximumLuminance != 0, UpdateExperience @0x004F0A70) is wired and toggles Visible on both elements every sheet refresh; the exact caption/value text could not be recovered this slice (retail's SetText source resolves through a Binary-Ninja-mislabeled data pointer, not a StringTable key — a DAT string-table sweep found no match), so content stays unbound rather than guessed. - AP-109 narrowed accordingly (register row amended in the same commit). Tests: CharacterStatControllerTests (heritage composition + live title update, name stays plain, level int/"???" with authored — not constant — color across 3 cases, PK line shows resolved text in authored color across 3 statuses, luminance visibility across 5 level/luminance combinations) and CharacterSheetProviderTests (PK key-by-status resolution including a combined-flag case, no-resolver leaves PkStatus null, Level null-vs-present, title resolution + live refresh on both title events + unsubscribe-on- dispose, luminance Int64 read-through). Full hermetic solution suite green under Release (0 failures across all 14 test projects); InstalledDat pins green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
aa8106d57a
commit
ed652ed8ad
10 changed files with 646 additions and 32 deletions
File diff suppressed because one or more lines are too long
Loading…
Add table
Add a link
Reference in a new issue