acdream/tests/AcDream.App.Tests
Erik 5499f0581f fix #FA4-mechanism-MUST-FIX-1,4: truncate (not round) the XP-share percentage; port the world->panel fellow-selection sync
MUST-FIX 1 -- D5's percentage conversion rounds where retail truncates.
gmFellowshipUI::UpdateFellowStats @0x0048ECC9 forms pct*100.0f on the x87
stack then calls _ftol2 (MSVC's round-to-truncate helper), never
MathF.Round. The stored floats for 6 and 8 fellows are 0.44999998807907104
and 0.3499999940395355 (byte-read from the PDB-paired binary), so retail's
own products truncate to 44/34, not 45/35 -- and (int)(pct*100f) alone does
not fix it, since 0.45f*100f already rounds UP to exactly 45.0f in single
precision. Fixed as (int)((double)pct * 100.0), forming the product the
same wider-than-single-precision way retail's x87 does. Pinned with new
[InlineData] cases for both sizes.

MUST-FIX 4 -- gmFellowshipUI::UpdateFellowSelection @0x0048F0F0 (the
world->panel arm of retail's two-directional selection coupling) was never
ported; only the panel->world arm (SelectFellow) shipped. Selecting a
fellow in the WORLD left Dismiss/Assign-Leader disabled and showed no row
highlight. SyncSelectionFromWorld/SetSelectedFellow reproduce the
observable contract (button-enable + a row tint) against this
controller's own guid-keyed row dictionary instead of porting retail's
generic ListBox SetAttribute_InstanceID/SetSelectedItem primitive (scoped
disposition recorded at register row AD-82).

Also in this pass over the controller:
- SF-1: cache the fellowship-name LinesProvider; only reassign on an
  actual name change (was allocating once per Tick, even while hidden).
- SF-2/SF-3: track true membership in _memberGuids, independent of which
  rows finished building. Fixes an unbounded DAT-locked rebuild retry
  when a row template permanently fails to build, and fixes Recruit's
  "already a fellow" check reading render rows instead of membership.
- N-0: the Open/Close caption now flips optimistically on click, matching
  retail's pre-toggle-before-server-echo (lane B feature 11).
- N-1/N-2/N-3: doc-only notes on the meter-child-text gap, the max>0
  guard, and Tick's two-read non-atomicity.
- ResetPageVisibleLatch: the fellowship-controller half of MUST-FIX 3
  (see the SocialPanelController commit for the panel-level half).

Per docs/research/2026-08-12-fa4-review-mechanism.md.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-12 07:33:18 +02:00
..
Audio feat(audio): Campaign A slice A2 — retail's 2D pan+gain mixer replaces AL 3D 2026-08-08 21:58:50 +02:00
Combat fix(ui,runtime): OP4 review fixes — live re-seed, enable-gating, Combat panel re-point, universal timestamps 2026-08-11 05:30:26 +02:00
Composition feat(app): FA2 -- fellowship/allegiance command routing for graphical + headless hosts 2026-08-12 01:32:18 +02:00
Diagnostics fix(diag): resolve the multisampled backbuffer before reading it 2026-07-28 00:54:59 +02:00
Input feat(app): FA2 -- fellowship/allegiance command routing for graphical + headless hosts 2026-08-12 01:32:18 +02:00
Interaction fix(vendor): evidence-based pass — max-first stack ceiling; the local player resolves never-animated MoveTo targets 2026-08-08 17:17:04 +02:00
Net feat(app): FA2 -- fellowship/allegiance command routing for graphical + headless hosts 2026-08-12 01:32:18 +02:00
Physics refactor(physics): hoist the live-entity collision builder to Runtime (#330 groundwork) 2026-08-07 01:49:13 +02:00
Platform feat(render): Vulkan campaign V11 step 2 — delete the OpenGL backend 2026-07-29 02:19:53 +02:00
Plugins feat(D.2b): IUiRegistry plugin UI surface + buffered drain into UiHost 2026-06-14 17:46:37 +02:00
Rendering refactor(settings): OP9 — retire the dead F11 settings surface + fully-superseded GameplaySettings 2026-08-11 13:18:53 +02:00
Runtime feat(runtime,net): Campaign OP slice OP1 — full character-option table, dirty model, real 0x01A1 blob builder 2026-08-10 23:31:34 +02:00
Settings fix(settings): OP9 review residuals — restore SaveAudio live-apply pin, delete dead residues 2026-08-11 13:42:39 +02:00
Spells feat(headless): share immutable gameplay content 2026-07-27 09:00:48 +02:00
Streaming fix(audio): portal cues fire on the sequencer's sound events, not the tunnel visuals 2026-08-09 08:22:48 +02:00
UI fix #FA4-mechanism-MUST-FIX-1,4: truncate (not round) the XP-share percentage; port the world->panel fellow-selection sync 2026-08-12 07:33:18 +02:00
World fix(world): #344 — a mid-teleport world-frame disagreement defers the projection instead of crashing 2026-08-07 10:07:45 +02:00
AcDream.App.Tests.csproj refactor(runtime): own canonical action state 2026-07-26 10:44:09 +02:00
BoundedTestDatCollection.cs perf(content): remove exception-driven setup probes 2026-07-24 15:12:21 +02:00
FramePhaseTestDoubles.cs refactor(runtime): move session lifetime and ordered transport 2026-07-25 19:39:24 +02:00
FrameProfilerReportTests.cs perf(diag): complete trustworthy Slice A capture tooling 2026-07-24 12:46:51 +02:00
FrameStatsBufferTests.cs fix(pipeline): MP0 - profiler toggle-path hygiene + Max() seed (review follow-up) 2026-07-05 19:26:28 +02:00
GameRuntimeTestFactory.cs refactor(runtime): cut graphical host over to canonical root 2026-07-26 19:06:09 +02:00
GlobalUsings.cs Revert "Campaign V slice V4a" - it lost world multisampling 2026-07-27 18:29:28 +02:00
LiveEntityRuntimeFixture.cs test(runtime): restore the world-frame precondition across first-entry fixtures 2026-08-03 13:32:28 +02:00
LiveEntitySpawnFixture.cs feat(runtime): C3c - production placement cutover: both hosts on the residence conductors (routes 1+8) 2026-08-02 18:10:33 +02:00
RuntimeDatAccessArchitectureTests.cs feat(headless): share immutable process content 2026-07-27 08:37:24 +02:00
RuntimeDatCollectionFactoryTests.cs feat(headless): share immutable process content 2026-07-27 08:37:24 +02:00
RuntimeOptionsRetailUiTests.cs test(runtime): add deterministic world gate artifacts 2026-07-20 22:37:16 +02:00
RuntimeOptionsTests.cs feat(render): Vulkan campaign V11 step 2 — delete the OpenGL backend 2026-07-29 02:19:53 +02:00
RuntimeWorldTransitTestDriver.cs refactor(runtime): own teleport destination correlation 2026-07-26 17:52:34 +02:00
ZeroAllocationProbe.cs test(app): measure the warmed path, not the path being warmed (#250) 2026-07-29 03:42:08 +02:00
ZeroAllocationProbeTests.cs test(app): measure the warmed path, not the path being warmed (#250) 2026-07-29 03:42:08 +02:00