diff --git a/tests/AcDream.Core.Tests/Physics/CellarUpTrajectoryReplayTests.cs b/tests/AcDream.Core.Tests/Physics/CellarUpTrajectoryReplayTests.cs index 90df2dd..3f8297b 100644 --- a/tests/AcDream.Core.Tests/Physics/CellarUpTrajectoryReplayTests.cs +++ b/tests/AcDream.Core.Tests/Physics/CellarUpTrajectoryReplayTests.cs @@ -488,21 +488,68 @@ public class CellarUpTrajectoryReplayTests /// bumping the cottage floor from BELOW. /// /// - /// This is the actual #98 bug, NOT a step-up / AdjustOffset problem - /// — it's a head-sphere collision against a polygon that retail - /// doesn't have (cottage floor should be punched-through above the - /// ramp). Whether the harness reproduces the cap pinpoints whether - /// the cottage-cell floor polygon set is the cause. + /// This is the actual #98 bug, NOT a step-up / AdjustOffset problem. + /// Live capture's [resolve] probe pinpoints the blocking + /// entity: obj=0xA9B47900 — a landblock-baked static building + /// (the cottage GfxObj). The cottage's floor polygons live in this + /// GfxObj, registered as a ShadowEntry, NOT in any of the cottage's + /// cells. The harness's + /// loads cell fixtures but does NOT register the cottage GfxObj, so + /// the harness fails to reproduce the cap — DOCUMENTED here as the + /// divergence pattern. + /// + /// + /// + /// Documents-the-bug pattern: passes WHILE the harness lacks the + /// cottage GfxObj. When a future session adds the cottage GfxObj + /// (full polygon list extracted from the live [poly-dump] + + /// [resolve-bldg] probes), this test will start failing — + /// the signal to flip it from documenting-the-bug to enforcing-the-fix. /// /// [Fact] - public void LiveCompare_FirstCap_HeadHitsCottageFloor() + public void LiveCompare_FirstCap_HarnessMissesCottageFloorBecauseCottageGfxObjNotRegistered() { var (engine, _) = BuildEngineWithCellarFixtures(); var captured = LoadCapturedRecord(record => record.Result.CollisionNormalValid && record.Result.CollisionNormal.Z < -0.99f); - AssertCallMatchesCapture(engine, captured); + Assert.NotNull(captured.BodyBefore); + + var body = SeedBodyFromSnapshot(captured.BodyBefore); + var harnessResult = engine.ResolveWithTransition( + currentPos: captured.Input.CurrentPos, + targetPos: captured.Input.TargetPos, + cellId: captured.Input.CellId, + sphereRadius: captured.Input.SphereRadius, + sphereHeight: captured.Input.SphereHeight, + stepUpHeight: captured.Input.StepUpHeight, + stepDownHeight: captured.Input.StepDownHeight, + isOnGround: captured.Input.IsOnGround, + body: body, + moverFlags: (ObjectInfoState)captured.Input.MoverFlags, + movingEntityId: captured.Input.MovingEntityId); + + // Live reported cn=(0,0,-1) blocking the climb at this point. + Assert.True(captured.Result.CollisionNormalValid, + "Captured record must have collisionNormalValid=true."); + Assert.True(captured.Result.CollisionNormal.Z < -0.99f, + $"Captured record must have downward collision normal; got " + + $"{captured.Result.CollisionNormal}."); + + // Harness does NOT reproduce the live downward push because the + // cottage GfxObj is not registered — the blocking polygon lives + // in static obj 0xA9B47900, which BuildEngineWithCellarFixtures + // intentionally skips today (RegisterStairRampGfxObj is commented + // out). When the cottage GfxObj's full polygon set is added to + // the harness, this assertion will start to fail — flip the test + // to assert the live cn=(0,0,-1) round-trips at that point. + Assert.False( + harnessResult.CollisionNormalValid + && harnessResult.CollisionNormal.Z < -0.99f, + "Harness should NOT reproduce the cottage-floor cap yet — " + + "if it does, the cottage GfxObj has been added and this test " + + "needs to flip to AssertCallMatchesCapture(engine, captured)."); } ///