feat(phys): A6.P3 slice 1 step 1 — add Mechanism B (LKCP restore)
Restores CollisionInfo.ContactPlane from LastKnownContactPlane when:
- LKCP is valid
- the sphere's current center is geometrically close to the LKCP
plane (|dot(global_curr_center, N) + d| <= radius + EPSILON)
Matches retail's validate_transition LKCP-restore at
acclient_2013_pseudo_c.txt:272577 (CTransition::validate_transition,
address 0050aa70, lines 272565-272582). Slice 1 step 1 of the
A6.P3 indoor CP retention fix. Step 2 (Task 5) strips the
TryFindIndoorWalkablePlane synthesis from FindEnvCollisions.
Also fixes the proximity-check sphere: was using
sp.GlobalSphere[0].Origin (start sphere); now uses
sp.GlobalCurrCenter[0].Origin (current center) per retail
(acclient_2013_pseudo_c.txt:272568).
Tests: 1147 pass, 9 fail (8 pre-existing + 1 IndoorContactPlaneRetention
from T3 — expected; T5 lands the actual synthesis-strip fix).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
a32f56955d
commit
5aba071aec
1 changed files with 26 additions and 1 deletions
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue