fix(chargen): Campaign CC gate round 1 Batch D — gmCG3DView environment backdrop
Retail's chargen 3D views (Appearance and Summary) are not black behind the model: gmCG3DView::Update @0x004EE9D0 constructs a SECOND CPhysicsObj from the current heritage's HeritageGroup_CG.environmentSetupID field (acclient.h verbatim struct layout; the decompiler elides the actual field read, but HeritageGroup_CG::GetSubDataIDs @0x005c05d0 explicitly walks iconImage/setupID/environmentSetupID by name, confirming the identity) and adds it to the SAME viewport's creature_mode_objects the player object lives in, inserted BEFORE the player (whose own re-AddObject happens much later, at ~0x004ef199, after the full clothing ObjDesc composes). The backdrop gets no explicit position/orientation/scale — CPhysicsObj:: makeObject(eax_32, 0, 1) leaves it at the scene origin with identity orientation, same as the player object's own placement. This id was already parsed as ChargenHeritageOptions.EnvironmentSetupId (ChargenTableReader.cs) but never consumed anywhere in production (GF-7/ GF-14). Fixed by: - ChargenPreviewEntityBuilder.TryBuildBackdrop: builds a plain, unposed Setup mesh from the heritage's EnvironmentSetupId, returning null for id 0/unset or an unresolvable Setup (retail's own INVALID_DID gate). - PrivateEntityViewportRenderer: an optional second entity slot (SetBackdrop), reserved via a backdropRenderId constructor parameter so paperdoll and creature-appraisal — which never pass one — cannot acquire a second entity even by accident (SetBackdrop throws without a reserved slot). Per-entity mesh-reference/texture-owner lifetime is factored into a private EntitySlot helper shared by both the main and backdrop slots. Draw-entity assembly is a pure, directly-testable helper (BuildDrawEntities) that puts the backdrop first, matching retail's own AddObject insertion order. - ChargenPreviewController.Rebuild: rebuilds the backdrop whenever the HERITAGE changes (narrower than the existing camera-eye-reset gate, since environmentSetupID is a pure function of heritage, never gender or appearance selection). Both Appearance and Summary get the fix from the same ChargenPreviewRenderer facade — confirmed both pages call the identical gmCG3DView::Update on their own gmCG3DView instance, so no page-specific code was needed. Lighting was independently re-verified against the same function's SetLight call (DISTANT_LIGHT, intensity 2.0, direction (0.3, 1.9, 0.65), default white color) and found to already match byte-for-byte what CC6a shipped. Also files docs/ISSUES.md #409 for GF-16 (client-wide UI tooltip system), investigated in the same root-cause pass but explicitly out of this batch's scope, and marks it DEFERRED in the findings doc. Tests: 11 new/extended (ChargenPreviewEntityBuilderTests.TryBuildBackdrop_*, ChargenPreviewControllerTests backdrop rebuild/swap/absent/no-op cases, PrivateEntityViewportRendererDrawOrderTests pinning the paperdoll/creature- appraisal single-entity invariant). Live-DAT measurement: all 13 retail heritages' EnvironmentSetupId resolve to a real, drawable installed Setup. App suite 5307/3 -> 5321/3 (+14, 0 regressions). Runtime 1735/0 unchanged. Launcher.Core.Tests 337/0 and Launcher.Tests 67/0 unchanged (first build of the merged tree carrying the #406 launcher merge). Full solution: 14508 total / 14504 passed / 4 skipped / 0 failed, dotnet test exit code 0. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
0b05b58514
commit
63bf64c934
9 changed files with 866 additions and 103 deletions
|
|
@ -41,6 +41,23 @@ 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.**
|
||||
|
||||
**Batch D (chargen 3D preview backdrop) is CODE-COMPLETE 2026-08-16, pending
|
||||
the user's visual gate.** GF-7 and GF-14 are fixed — see each entry's own
|
||||
FIXED note below. GF-16 (client-wide tooltips) was investigated in the same
|
||||
root-cause pass but is explicitly out of this batch's scope — deferred as
|
||||
`docs/ISSUES.md` #409 with its own decomp anchors. Fixture + live-DAT tests
|
||||
only this round (no graphical client launch); App suite went from 5307/3 to
|
||||
5321/3 (+14, zero regressions), Runtime 1735/0 unchanged. Both Launcher test
|
||||
projects (this being the first build of the merged tree carrying the #406
|
||||
launcher merge) pass at their own baselines: Launcher.Core.Tests 337/0,
|
||||
Launcher.Tests 67/0. Blast radius: `PrivateEntityViewportRenderer` (shared
|
||||
with paperdoll and creature-appraisal) gained an OPTIONAL second entity
|
||||
slot reserved via a `backdropRenderId` constructor parameter — paperdoll
|
||||
and creature-appraisal never pass one, so their draw stays single-entity
|
||||
by construction (`SetBackdrop` throws if called without a reserved slot,
|
||||
and the entity-list-assembly helper `BuildDrawEntities` degrades to
|
||||
exactly the main entity whenever no backdrop is configured/set).
|
||||
|
||||
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
|
||||
|
|
@ -236,10 +253,43 @@ ISSUES.md; this doc is the six-page batch.
|
|||
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
|
||||
what actually renders behind the model per page/view.)
|
||||
- **GF-7 Preview backdrop black on Appearance (and Summary, GF-14) — FIXED
|
||||
(Campaign CC gate round 1, Batch D).** Root cause: retail's
|
||||
`gmCG3DView::Update @0x004EE9D0` (~0x004eecd3-0x004eed44) constructs a
|
||||
SECOND `CPhysicsObj` from the current heritage's own
|
||||
`HeritageGroup_CG.environmentSetupID` field (verbatim struct layout,
|
||||
`acclient.h`) and adds it to the SAME viewport's `creature_mode_objects`
|
||||
the player object lives in — this codebase already parsed that id as
|
||||
`ChargenHeritageOptions.EnvironmentSetupId` (`ChargenTableReader.cs`)
|
||||
but never consumed it anywhere. The decompiler elides the actual field
|
||||
read (`var_b8`/`eax_32`, an unresolved-call artifact — see
|
||||
`claude-memory/feedback_bn_decomp_field_names.md`); cross-referencing
|
||||
`acclient.h`'s `HeritageGroup_CG` struct (environmentSetupID sits right
|
||||
after setupID) confirmed what the elided value is. The backdrop object
|
||||
gets NO explicit position/orientation/scale — `CPhysicsObj::makeObject`
|
||||
(0x004eed2f) leaves it at the scene origin with identity orientation,
|
||||
same as the player object's own default placement, and retail's own
|
||||
`AddObject` insertion order puts the backdrop BEFORE the player (the
|
||||
player's own re-`AddObject` happens later, at ~0x004ef199, after the
|
||||
full clothing ObjDesc composes). Fixed by extending
|
||||
`ChargenPreviewEntityBuilder` with `TryBuildBackdrop` (builds a plain,
|
||||
unposed Setup mesh from the heritage's `EnvironmentSetupId`, returning
|
||||
null for id 0/unset or an unresolvable Setup — matching retail's own
|
||||
`if (eax_32 != INVALID_DID.id)` gate at 0x004eed29), giving
|
||||
`PrivateEntityViewportRenderer` an optional second entity slot
|
||||
(`SetBackdrop`, reserved via a `backdropRenderId` constructor param so
|
||||
paperdoll/creature-appraisal — which never pass one — cannot acquire a
|
||||
second entity even by accident), and wiring `ChargenPreviewController`
|
||||
to rebuild the backdrop whenever the HERITAGE changes (narrower than the
|
||||
existing camera-eye-reset gate, since `environmentSetupID` is a pure
|
||||
function of heritage, never gender or appearance selection). Both
|
||||
Appearance and Summary get the fix from the SAME `ChargenPreviewRenderer`
|
||||
facade — no page-specific code needed, confirmed both pages call the
|
||||
identical `gmCG3DView::Update` on their own separate `gmCG3DView`
|
||||
instance. Lighting was independently re-verified against the same
|
||||
function's `SetLight` call (`DISTANT_LIGHT, 2.0, (0.3, 1.9, 0.65)`
|
||||
direction, default white color) and found to ALREADY match byte-for-byte
|
||||
what CC6a shipped — no lighting change was needed.
|
||||
- **GF-8 Appearance Face/Clothes sub-tab selection unmarked — FIXED
|
||||
(Campaign CC gate round 1, Batch B).** Same root and same fix as GF-1:
|
||||
the Face (`0x100003A9`)/Clothes (`0x100003AA`) sub-tab buttons author
|
||||
|
|
@ -306,14 +356,22 @@ ISSUES.md; this doc is the six-page batch.
|
|||
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-14 Summary paperdoll backdrop black — FIXED (Campaign CC gate round
|
||||
1, Batch D, same fix as GF-7 above — both pages call the identical
|
||||
`gmCG3DView::Update` on their own `gmCG3DView` instance).** **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).
|
||||
DEFERRED to its own gate round — filed as
|
||||
[`docs/ISSUES.md` #409](../ISSUES.md) with the decomp anchors
|
||||
(`UIElement::StartTooltipAtMouse @0x00460D70`,
|
||||
`UIElementManager::StartTooltip @0x0045DE90` + `@0x00459700`, layout DID
|
||||
`0x21000041`, properties P0x47-P0x4B, ~253 authored elements, prefs
|
||||
`Misc_TooltipEnable`/`Misc_TooltipDelay`) the Batch D investigation
|
||||
surfaced. Out of Batch D's scope: it is a CLIENT-WIDE mechanism, not the
|
||||
chargen 3D preview backdrop Batch D actually fixed (GF-7/GF-14 above).
|
||||
|
||||
## Suspected shared roots (to be CONFIRMED by the investigation, not assumed)
|
||||
|
||||
|
|
@ -349,7 +407,13 @@ ISSUES.md; this doc is the six-page batch.
|
|||
distinct from the art/media commit, and NOT gated by the same art-
|
||||
availability check `ActiveState` is). See each GF's own FIXED entry
|
||||
above and the retired AP-222 / narrowed AP-215 register rows.
|
||||
4. Preview backdrop (GF-7/GF-14) — what gmCG3DView clears/draws.
|
||||
4. ~~Preview backdrop (GF-7/GF-14) — what gmCG3DView clears/draws.~~
|
||||
CONFIRMED, CLOSED at Batch D: `gmCG3DView::Update`'s own
|
||||
`m_pbgObject`/`m_bgSetupID` pair, sourced from the heritage's
|
||||
`HeritageGroup_CG.environmentSetupID` field — already parsed into this
|
||||
codebase as `ChargenHeritageOptions.EnvironmentSetupId` but never
|
||||
consumed before this fix. See GF-7's own FIXED entry above for the full
|
||||
decomp citation.
|
||||
5. ~~Input routing on Summary (GF-15) — focus/typing path on the stacked
|
||||
chargen screen.~~ CLOSED: focus/typing routing was never broken (live-
|
||||
verified); the real cause was `RetailDialogFactory` never re-asserting
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue