Commit graph

3 commits

Author SHA1 Message Date
Erik
0b0c7aa485 fix(ui): night-round review — F11/F13/F14/F15 one-liners
F11: logs when a Map tab town-marker's template resolves to something
other than a UiButton — that path previously silently skipped the
TooltipText write with no diagnostic, leaving a mounted-but-empty
tooltip popup indistinguishable from "no template configured".

F13: RetailSkillFormula.FormatFormula now reads Attribute1Multiplier/
Attribute2Multiplier/AdditiveBonus/Divisor through the SAME unsigned
reinterpretation TryCalculate already uses (this class's own doc
comment already stated the invariant; FormatFormula just didn't follow
it). A high-bit-set value would previously both mis-gate hasAttr1/
hasAttr2 and print a negative number, out of sync with what
TryCalculate actually computes with for the same formula. Added
regression tests, empirically verified to fail without the fix.

F14: documented the RefreshHouseMarker gap rather than guessing at the
byte-decode — Position::get_outside_cell_id @0x004527b0 is itself
BN-mangled (its `(eax_2 - eax_2) & objcell_id` return is the same
decompiler-obscures-a-real-conditional artifact class this round hit
elsewhere) and depends on LandDefs::adjust_to_outside, a genuinely
larger port than this round's other findings. HousePosition is wired
() => null in production today (ISSUES #413's remaining scope), so
this method is currently unreachable; left a TODO citing the retail
call chain for whenever that lands.

F15: fixed RefreshCoordinatesAndPlayerMarker's gate to AND-on-both-
present, matching gmMapUI::Update @0x004a2078's exact
`if (m_pCoordinateText != 0 && m_pPlayerLocationIcon != 0)` condition.
The prior `_coordinateText is null && _playerIcon is null` check only
skipped when BOTH were absent (proceeding whenever EITHER was
present), letting coordinate text and the player marker update
independently instead of as the single gated unit retail treats them
as. Added a regression test (player-icon template resolution failure
must also skip the coordinate-text write), empirically verified to
fail without the fix.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-17 05:06:17 +02:00
Erik
356545c530 fix(chargen): Campaign CC CC5 re-review residuals R1-R5 + nits — REVIEW-CLOSED
The narrow re-review of fix commits 0c8e1e7d+2d4168f9 found every code fix
oracle-verified but returned NOT CLOSED on five test/doc residuals plus
three nits and a follow-up filing. All fixed:

- R1: the claimed "external-change->user-commit->SetName" regression test
  for F1 (the deleted _suppressNextFieldEvent latch) never existed — the
  Runtime-layer randomize test doesn't touch the page. Added
  CharacterCreationUiControllerTests.SummaryNameField_RealCommitAfter
  ExternalRefreshWhileUnfocused_StillReachesSetName: drives Refresh with a
  revision bump + changed snapshot.Name while the field is unfocused (the
  programmatic SetText path that used to arm the latch), THEN performs a
  real user commit (field.SetText + field.Submit(), the actual event path),
  asserting SetName receives the player's typed text.
- R2: RetailSkillFormula.CalculateChargenScore and ChargenSkillScoreResolver
  had zero direct coverage (the F12(d) test substitutes skillId*10). Added
  a Untrained/Trained(+5)/Specialized(+10) theory, the divisor-zero skip
  path, and a six-way AttributeId theory (Str=1..Self=6) to
  RetailSkillFormulaTests.cs.
- R3: RetailSkillFormula.cs's doc comment claimed "no retail-authored skill
  sets MinLevel above Untrained=1" without ever reading the field — ACE's
  own SkillBase.cs hedges the same field "// 1-2?". MEASURED (not assumed)
  against the installed EoR dat's global SkillTable
  (CharacterCreationLiveDatTests.SkillTable_MinLevelDistribution_
  NeverExceedsTrained): 23 skills at MinLevel 1, 15 at MinLevel 2, zero
  above 2, of 38 priced skills. ACE's hedge was right; the doc comment now
  states the measured fact and leans on the structural argument (the gate
  holds for Trained/Specialized under any MinLevel in {1,2}) as load-
  bearing, not the unverified data claim.
- R4: filed AP-228 — the Summary/Skills skill-row KEY sources from
  ItemAppraisalTextFormatter.SkillName's hardcoded English switch, where
  retail's own key is DAT-sourced (SkillBase->_name via %hs,
  0x0047b90f-0x0047b915) — same divergence class as AP-226 filed the same
  round, reversed polarity, also present at CC4's Skills page. Softened
  AP-224's "ported exactly, not simplified" claim: it only ever covered the
  row's VALUE/template, never its KEY.
- R5: this commit corrects 0c8e1e7d's gate claim. "Release build zero
  warnings" was false: a clean `dotnet build -c Release -t:Rebuild` shows
  25 pre-existing warnings (18 in tests/AcDream.Core.Tests, 7 in
  tests/AcDream.App.Tests — Composition/HostInputCameraCompositionTests.cs,
  Composition/WorldRenderCompositionTests.cs,
  UI/Layout/OptionsPanelLiveMountProbeTests.cs), none in any file this
  campaign or its residual round touched. History is not amended; this is
  the correction.

Nits: the ChargenPreviewController ctor doc now also cites
gmCGSummaryPage::Update @0x0047baa0 (the per-heritage re-derive site — 0xc
Olthoi/0xd OlthoiAcid/else — not just the one-shot InitializePage seed) as
the stronger justification for why Rebuild re-derives the zoomed-out eye
per heritage on every change. RuntimeCharacterCreationState's F2 comment
("Finish becoming a permanent no-op") reworded: the same unconditional
_verificationPending = false assignment ran pre-fix too, so Finish was
never blocked — only the response FEEDBACK vanished (no dialog, no created
character, nothing), not the request itself. Filed #404 for
ChargenSkillScoreResolver's own independent SkillTable read alongside
ChargenTableReader's (cleanup follow-up, out of this round's scope).

Ledger: CC5 flipped REVIEW-CLOSED in the campaign plan (dual-lens
architectural PASS-with-items / retail-fidelity FAIL -> F1-F14 fix round
0c8e1e7d -> narrow re-review: all code oracle-verified, residuals R1-R5
test/doc -> this commit; re-reviewer pre-authorized lead diff-check close).
This commit's own sha is recorded by a follow-up ledger-only commit,
matching 2d4168f9's own pattern.

Gates: Release build 0 errors (25 pre-existing warnings, unrelated to this
round — see R5 above); App suite 5257/3 skips (was 5242/3), 0 failed;
Runtime suite 1726/0 (unchanged); the three new/measured tests (R1, R2's
ten cases, R3) all pass individually.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-16 01:57:07 +02:00
Erik
557eb7ef6b refactor(net): own live session composition
Extract reset, selection, entered-world, and route construction behind LiveSessionHost while preserving the sole LiveSessionController authority. Retain partial route and subscription cleanup for retry, and replace the embedded ACE-only shortcut with the exact named-retail unsigned skill formula.

Co-authored-by: Codex <codex@openai.com>
2026-07-22 10:36:06 +02:00