diff --git a/src/AcDream.Core/Physics/TransitionTypes.cs b/src/AcDream.Core/Physics/TransitionTypes.cs index 3b8257c..2bc4041 100644 --- a/src/AcDream.Core/Physics/TransitionTypes.cs +++ b/src/AcDream.Core/Physics/TransitionTypes.cs @@ -2849,13 +2849,38 @@ public sealed class Transition // // Matches ACE PhysicsObj's pre-reuse check on the last-known // plane and retail's CPhysicsObj::get_object_info logic. - var sphereCenter = sp.GlobalSphere[0].Origin; + // A6.P3 slice 1 (2026-05-21). Retail uses global_curr_center (NOT + // global_sphere->center) for this proximity check — see + // acclient_2013_pseudo_c.txt:272568. global_sphere is the START + // sphere of the transition; global_curr_center is the CURRENT center + // after sub-step accumulation. Using the wrong one made the proximity + // guard fire on the wrong reference point. + var sphereCenter = sp.GlobalCurrCenter[0].Origin; var radius = sp.GlobalSphere[0].Radius; float angle = Vector3.Dot(ci.LastKnownContactPlane.Normal, sphereCenter) + ci.LastKnownContactPlane.D; if (radius + PhysicsGlobals.EPSILON > MathF.Abs(angle)) { + // ── Mechanism B — restore CP from LKCP per retail ──────────────── + // A6.P3 slice 1 (2026-05-21). Retail oracle: + // acclient_2013_pseudo_c.txt:272577 (inside CTransition::validate_transition + // at line 272547). When the sphere is geometrically close to the + // LastKnownContactPlane, retail restores CP from LKCP via + // set_contact_plane(&collision_info, &last_known_contact_plane, + // last_known_contact_plane_is_water). This closes the gap that the + // stripped TryFindIndoorWalkablePlane synthesis path used to fill — + // when no fresh Path-6 CP write lands in this transition, CP is + // retained from the previous frame instead of being re-synthesized. + // + // NOTE: SetContactPlane also re-latches LKCP fields + // (TransitionTypes.cs:258-261), which is a no-op here since we + // pass LKCP as the source. + ci.SetContactPlane( + ci.LastKnownContactPlane, + ci.LastKnownContactPlaneCellId, + ci.LastKnownContactPlaneIsWater); + // Still close enough to the last-known plane — preserve // grounded state. L.2.3i FloorZ test for OnWalkable. oi.State |= ObjectInfoState.Contact;