acdream/src
Erik 0cb4c59681 fix(phys): A6.P3 #98 — gate ContactPlane assignment by Normal.Z (Shape 1)
Adds PhysicsGlobals.ContactPlaneFlatThreshold = 0.99f and uses it at
both BSPQuery.AdjustSphereToPlane call sites that previously set CP
unconditionally on any walkable polygon found by FindWalkableInternal.

Backed by the retail cdb capture in cellar_up_capture_1: across 161
set_contact_plane writes during 5 seconds of cellar-up climbing,
EVERY write lands on a flat (Normal.Z = 1.0) plane — cellar floor at
world Z=90.95 or cottage floor at world Z=94. The cellar ramp
(Normal.Z = 0.695, walkable per FloorZ but sloped ~46 degrees) is
never set as CP in retail.

Acdream's prior behavior of setting CP=ramp caused two cascading
issues at the top of the ramp:
1. AdjustOffset's slope-projection produced +Z gain per call (correct
   in isolation) but inflated step-up's responsibility to "find the
   next walkable below the lifted check position".
2. step-up's downward step-down probe found no walkable within 0.6m
   below the proposed check (cottage floor at Z=94 is ABOVE, not
   below), so step-down rejected, sphere rolled back. Infinite freeze
   at world Z ~= 92.80.

With CP only set on flat polygons, sloped surfaces drive collision
detection and walkable-poly tracking (via path.SetWalkable) but
don't override the resting CP. The sphere should now climb the ramp
via step-up over the ramp polygon, with CP staying on the flat
cellar floor until the sphere reaches the flat cottage floor.

Tests: 1167 + 8 baseline maintained. No regression. The Issue98
replay tests still pass — they document the failing-frame geometry
(sphere world Z=92.01 below cottage floor), which doesn't change;
the fix prevents the sphere from getting STUCK at that altitude in
the first place. Live visual verification required next.

If the live test shows new failure modes (sphere stuck somewhere
else, doesn't climb at all, climbs but slides off, etc), the
threshold (0.99) or the gating approach itself may need refining.
This is the conservative empirical version of Shape 1; the named-
decomp research did not conclusively prove the exact retail gate.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-23 16:46:12 +02:00
..
AcDream.App chore(phys): A6.P3 #98 triage — revert neg-poly + bldg-check experiments 2026-05-23 15:11:49 +02:00
AcDream.Cli feat(vfx): Phase E.3 particle system + hook wiring + registry 2026-04-18 16:48:17 +02:00
AcDream.Core fix(phys): A6.P3 #98 — gate ContactPlane assignment by Normal.Z (Shape 1) 2026-05-23 16:46:12 +02:00
AcDream.Core.Net fix(physics): close #77 — auto-walk honors ACE CanCharge bit; zero velocity in turn-in-place 2026-05-18 09:33:33 +02:00
AcDream.Plugin.Abstractions feat(core): add IGameState, IEvents, WorldEvents with replay-on-subscribe 2026-04-10 20:29:29 +02:00
AcDream.Plugins.Smoke feat(app): wire IGameState+IEvents into Program and SmokePlugin 2026-04-10 20:31:50 +02:00
AcDream.UI.Abstractions feat(ui): A6.P1 — add ProbePushBack mirror to DebugVM 2026-05-21 18:38:51 +02:00
AcDream.UI.ImGui fix(ui): scope title-bar-only-drag absorber to BeginChild — Settings tabs work 2026-04-26 23:04:10 +02:00