fix(physics): restore retail path-6 collision response
This commit is contained in:
parent
acec33eca8
commit
75b6f6b6c9
8 changed files with 523 additions and 223 deletions
|
|
@ -396,18 +396,12 @@ public class BSPStepUpTests
|
|||
|
||||
/// <summary>
|
||||
/// Airborne mover descending toward a steep slope (normal.Z < FloorZ):
|
||||
/// Path 6 returns <see cref="TransitionState.Slid"/> and does NOT set
|
||||
/// the Collide flag — the steep-normal slide-tangent branch (L.4,
|
||||
/// commit b1af56e, 2026-04-30) intercepts the hit before SetCollide is
|
||||
/// called and projects the move along the steep face instead, keeping the
|
||||
/// body airborne with the falling animation.
|
||||
///
|
||||
/// <para>This is a documented intentional deviation from retail (retail calls
|
||||
/// set_collide unconditionally; our interim port uses slide-tangent while
|
||||
/// the retail step_up_slide / cliff_slide chain port is completed).</para>
|
||||
/// retail Path 6 still calls SetCollide, installs LandingZ, and returns
|
||||
/// Adjusted. Polygon steepness is handled by the outer transition chain,
|
||||
/// not by a BSP-layer tangent shortcut.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void C3_Path6_AirborneMoverHitsSteepSlope_ReturnsSlid()
|
||||
public void C3_Path6_AirborneMoverHitsSteepSlope_DefersThroughSetCollide()
|
||||
{
|
||||
var (root, resolved) = BSPStepUpFixtures.SlopedUnwalkable();
|
||||
|
||||
|
|
@ -427,13 +421,11 @@ public class BSPStepUpTests
|
|||
root, resolved, t, localSphere, null,
|
||||
currPos, Vector3.UnitZ, 1.0f);
|
||||
|
||||
// L.4 slide-tangent (b1af56e, 2026-04-30): steep polygon hit by
|
||||
// airborne sphere returns Slid (not Adjusted) and does NOT set
|
||||
// the Collide flag — the into-wall displacement is removed and
|
||||
// CollisionNormal/SlidingNormal are set instead.
|
||||
Assert.Equal(TransitionState.Slid, result);
|
||||
Assert.False(t.SpherePath.Collide,
|
||||
"Collide must NOT be set when the L.4 steep-slope slide-tangent fires");
|
||||
Assert.Equal(TransitionState.Adjusted, result);
|
||||
Assert.True(t.SpherePath.Collide);
|
||||
Assert.Equal(PhysicsGlobals.LandingZ, t.SpherePath.WalkableAllowance);
|
||||
Assert.False(t.CollisionInfo.CollisionNormalValid);
|
||||
Assert.False(t.CollisionInfo.SlidingNormalValid);
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
|
|
@ -594,17 +586,7 @@ public class BSPStepUpTests
|
|||
/// every frame replays the same hard stop and the character hangs in falling
|
||||
/// animation until another correction breaks the loop.
|
||||
/// </summary>
|
||||
[Fact(Skip = "Issue #116 shape-2 — the engine slides IN-FRAME to Z=1.92 " +
|
||||
"on the first airborne wall frame; this pin expects an L.2c hard stop " +
|
||||
"at Z=2.0. Ghidra (2026-06-12) confirms retail CSphere::slide_sphere " +
|
||||
"(0x00537440) applies the slide IN-FRAME (add_offset_to_check_pos → " +
|
||||
"SLID_TS), so our 1.92 is faithful TO slide_sphere and the Z=2.0 " +
|
||||
"expectation is the SUSPECT half — but whether retail's first " +
|
||||
"airborne frame REACHES slide_sphere (→1.92) or hard-stops upstream " +
|
||||
"(collide_with_environment dispatch / no last-known plane) needs a " +
|
||||
"cdb trace of an airborne wall hit before flipping the assertion. The " +
|
||||
"#116 threshold fix (EpsilonSq→F_EPSILON) did NOT change this — the D4 " +
|
||||
"offset is a real slide, not degenerate. See docs/ISSUES.md #116.")]
|
||||
[Fact]
|
||||
public void D4_AirborneMover_TallWall_PersistsSlidingNormalAcrossFrames()
|
||||
{
|
||||
var (root, resolved) = BSPStepUpFixtures.TallWall();
|
||||
|
|
@ -630,6 +612,8 @@ public class BSPStepUpTests
|
|||
|
||||
Assert.True(body.TransientState.HasFlag(TransientStateFlags.Sliding),
|
||||
"First airborne wall hit should cache SlidingNormal for the next frame.");
|
||||
// Path 6's primary-sphere SetCollide hard-stops this first frame; the
|
||||
// persisted normal then permits the downward tangent on frame two.
|
||||
Assert.Equal(2.0f, frame1.Position.Z, precision: 3);
|
||||
|
||||
var frame2 = engine.ResolveWithTransition(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue