fix(physics): restore retail step-down placement validation
This commit is contained in:
parent
4fbd93ecdb
commit
1fd5da67b4
4 changed files with 333 additions and 38 deletions
|
|
@ -2050,18 +2050,13 @@ public sealed class Transition
|
|||
stepDownHeight);
|
||||
stepDownHeight = probeHeight;
|
||||
|
||||
// L.2.3h (2026-04-29): pass runPlacement=false. This
|
||||
// branch's job is to maintain ground contact during normal
|
||||
// movement (e.g., walking over small bumps or near walls).
|
||||
// The Placement check inside DoStepDown is too strict for
|
||||
// this use — minor wall overlap from a prior wall-slide
|
||||
// would fail Placement and trigger the L.2.3e edge-block,
|
||||
// leaving the player stuck near walls. DoStepUp still runs
|
||||
// Placement for the step-UP-through-walls protection.
|
||||
// Retail always finishes a successful step-down with a
|
||||
// PLACEMENT_INSERT. That final pass validates that the
|
||||
// supported candidate can actually contain the mover.
|
||||
bool steppedDown = false;
|
||||
for (int probe = 0; probe < probeCount; probe++)
|
||||
{
|
||||
if (DoStepDown(stepDownHeight, zVal, engine, runPlacement: false))
|
||||
if (DoStepDown(stepDownHeight, zVal, engine))
|
||||
{
|
||||
steppedDown = true;
|
||||
break;
|
||||
|
|
@ -2326,7 +2321,7 @@ public sealed class Transition
|
|||
Vector3 backToCurrent = sp.GlobalCurrCenter[0].Origin - sp.GlobalSphere[0].Origin;
|
||||
sp.AddOffsetToCheckPos(backToCurrent);
|
||||
|
||||
_ = DoStepDown(stepDownHeight, zVal, engine, runPlacement: false);
|
||||
_ = DoStepDown(stepDownHeight, zVal, engine);
|
||||
|
||||
ci.ContactPlaneValid = false;
|
||||
ci.ContactPlaneIsWater = false;
|
||||
|
|
@ -5140,8 +5135,7 @@ public sealed class Transition
|
|||
/// Ported from pseudocode section 5 (StepDown).
|
||||
/// ACE: Transition.StepDown(float stepDownHeight, float zVal).
|
||||
/// </summary>
|
||||
private bool DoStepDown(float stepDownHeight, float walkableZ, PhysicsEngine engine,
|
||||
bool runPlacement = true)
|
||||
private bool DoStepDown(float stepDownHeight, float walkableZ, PhysicsEngine engine)
|
||||
{
|
||||
var sp = SpherePath;
|
||||
|
||||
|
|
@ -5156,7 +5150,7 @@ public sealed class Transition
|
|||
PhysicsDiagnostics.LogStepWalk(
|
||||
"stepdown-enter", -1, 0, sp, CollisionInfo, ObjectInfo,
|
||||
Vector3.Zero, Vector3.Zero,
|
||||
detail: $"height={stepDownHeight:F4} walkableZ={walkableZ:F4} runPlacement={runPlacement}");
|
||||
detail: $"height={stepDownHeight:F4} walkableZ={walkableZ:F4}");
|
||||
}
|
||||
|
||||
// If NOT in step-up mode, apply the downward offset.
|
||||
|
|
@ -5170,7 +5164,7 @@ public sealed class Transition
|
|||
PhysicsDiagnostics.LogStepWalk(
|
||||
"stepdown-after-offset", -1, 0, sp, CollisionInfo, ObjectInfo,
|
||||
downOffset, downOffset,
|
||||
detail: $"height={stepDownHeight:F4} walkableZ={walkableZ:F4} runPlacement={runPlacement}");
|
||||
detail: $"height={stepDownHeight:F4} walkableZ={walkableZ:F4}");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -5183,7 +5177,7 @@ public sealed class Transition
|
|||
"stepdown-after-insert", -1, 0, sp, CollisionInfo, ObjectInfo,
|
||||
Vector3.Zero, Vector3.Zero,
|
||||
transitState,
|
||||
$"height={stepDownHeight:F4} walkableZ={walkableZ:F4} runPlacement={runPlacement}");
|
||||
$"height={stepDownHeight:F4} walkableZ={walkableZ:F4}");
|
||||
}
|
||||
|
||||
sp.StepDown = false;
|
||||
|
|
@ -5234,23 +5228,11 @@ public sealed class Transition
|
|||
return false;
|
||||
}
|
||||
|
||||
// L.2.3h (2026-04-29): Placement validation is for the
|
||||
// DoStepUp use case (prevents climbing through walls by
|
||||
// stepping up onto ground beyond a tall wall). For the
|
||||
// "maintain contact during normal movement" use case (called
|
||||
// from TransitionalInsert's contact-recovery branch), the
|
||||
// Placement check is over-strict — slight wall overlap from
|
||||
// a prior wall-slide makes Placement reject, then the caller
|
||||
// returns Collided (L.2.3e) and the player gets stuck near
|
||||
// walls without ever touching them.
|
||||
//
|
||||
// ACE Transition.cs:731-741 runs Placement here unconditionally,
|
||||
// but ACE's pre-step-down state is cleaner — we have residual
|
||||
// wall-slide artifacts that make Placement misfire.
|
||||
if (!runPlacement)
|
||||
return true;
|
||||
|
||||
// Placement validation: can we actually stand here?
|
||||
// Retail CTransition::step_down (0x0050B2A0) always finishes a
|
||||
// successful transitional support probe with PLACEMENT_INSERT.
|
||||
// This rejects candidates that found support while still
|
||||
// overlapping solid geometry, for both ordinary contact
|
||||
// maintenance and StepUp.
|
||||
//
|
||||
// A6.P3 slice 4 (2026-05-22) — reset WalkInterp to 1.0 before
|
||||
// the placement_insert. The prior TransitionalInsert(5) probe
|
||||
|
|
@ -5324,12 +5306,18 @@ public sealed class Transition
|
|||
"stepdown-reject", -1, 0, sp, CollisionInfo, ObjectInfo,
|
||||
Vector3.Zero, Vector3.Zero,
|
||||
transitState,
|
||||
$"height={stepDownHeight:F4} walkableZ={walkableZ:F4} runPlacement={runPlacement}");
|
||||
$"height={stepDownHeight:F4} walkableZ={walkableZ:F4}");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
internal bool DoStepDownForTest(
|
||||
float stepDownHeight,
|
||||
float walkableZ,
|
||||
PhysicsEngine engine)
|
||||
=> DoStepDown(stepDownHeight, walkableZ, engine);
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Step-up
|
||||
// -----------------------------------------------------------------------
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue