diff --git a/src/AcDream.Core/Physics/PhysicsEngine.cs b/src/AcDream.Core/Physics/PhysicsEngine.cs index 696a635..4bfcb3e 100644 --- a/src/AcDream.Core/Physics/PhysicsEngine.cs +++ b/src/AcDream.Core/Physics/PhysicsEngine.cs @@ -691,10 +691,30 @@ public sealed class PhysicsEngine string probeCp = ci.ContactPlaneValid ? "valid" : (ci.LastKnownContactPlaneValid ? "lastKnown" : "none"); - string probeHit = collisionNormalValid - ? System.FormattableString.Invariant( - $"yes n=({collisionNormal.X:F2},{collisionNormal.Y:F2},{collisionNormal.Z:F2})") - : "no"; + string probeHit; + if (collisionNormalValid) + { + // L.2a slice 2 (2026-05-12): include the hit object's guid + + // environment flag so we can tell whether the wall is a building + // (CBuildingObj), a door (CC0Cxxxx range), an NPC, or terrain. + // Without this we know the wall normal but not the responsible + // entity — half the L.2d sub-direction call. + string objPart = ci.LastCollidedObjectGuid.HasValue + ? System.FormattableString.Invariant( + $" obj=0x{ci.LastCollidedObjectGuid.Value:X8}") + : ""; + string envPart = ci.CollidedWithEnvironment ? " env" : ""; + int objCount = ci.CollideObjectGuids.Count; + string objCountPart = objCount > 1 + ? System.FormattableString.Invariant($" nObj={objCount}") + : ""; + probeHit = System.FormattableString.Invariant( + $"yes n=({collisionNormal.X:F2},{collisionNormal.Y:F2},{collisionNormal.Z:F2}){objPart}{envPart}{objCountPart}"); + } + else + { + probeHit = "no"; + } Console.WriteLine(System.FormattableString.Invariant( $"[resolve] ent=0x{movingEntityId:X8} in=({currentPos.X:F3},{currentPos.Y:F3},{currentPos.Z:F3}) cell=0x{cellId:X8} tgt=({targetPos.X:F3},{targetPos.Y:F3},{targetPos.Z:F3}) out=({probePost.X:F3},{probePost.Y:F3},{probePost.Z:F3}) cell=0x{sp.CheckCellId:X8} ok={ok} groundedIn={isOnGround} cp={probeCp} hit={probeHit} walkable={sp.HasLastWalkablePolygon}")); }