diff --git a/src/AcDream.App/Rendering/GameWindow.cs b/src/AcDream.App/Rendering/GameWindow.cs index 9c23303..124edb4 100644 --- a/src/AcDream.App/Rendering/GameWindow.cs +++ b/src/AcDream.App/Rendering/GameWindow.cs @@ -220,11 +220,6 @@ public sealed class GameWindow : IDisposable 1f - 2f * (q.Y * q.Y + q.Z * q.Z)); _playerController.Yaw = yaw; - Console.WriteLine($"[PLAYER-INIT] entityPos=({playerEntity.Position.X:F1},{playerEntity.Position.Y:F1},{playerEntity.Position.Z:F1}) " + - $"entityRot=({q.X:F3},{q.Y:F3},{q.Z:F3},{q.W:F3}) " + - $"initCellId=0x{(pinitCellId & 0xFFFFu):X4} " + - $"yaw={yaw:F3} " + - $"physics landblocks={_physicsEngine.LandblockCount}"); _chaseCamera = new AcDream.App.Rendering.ChaseCamera { Aspect = _window!.Size.X / (float)_window.Size.Y, @@ -1505,16 +1500,6 @@ public sealed class GameWindow : IDisposable var result = _playerController.Update((float)dt, input); - // DIAG: dump player state every ~60 frames to see what's happening. - if (_perfFrameCount % 60 == 0) - { - Console.WriteLine($"[PLAYER] pos=({result.Position.X:F1},{result.Position.Y:F1},{result.Position.Z:F1}) " + - $"cell=0x{result.CellId:X8} ground={result.IsOnGround} " + - $"yaw={_playerController.Yaw:F2} " + - $"fwdCmd={result.ForwardCommand?.ToString("X8") ?? "idle"} " + - $"stateChanged={result.MotionStateChanged}"); - } - // Update the player entity's position + rotation so it renders at // the physics-resolved location each frame. if (_entitiesByServerGuid.TryGetValue(_playerServerGuid, out var pe)) @@ -1812,16 +1797,19 @@ public sealed class GameWindow : IDisposable _animatedEntities[pe.Id] = ae; } + // The motion table cycle key is (style << 16) | (command & 0xFFFFFF). + // Without a stance override, the resolver uses the table default + // (which always maps to the idle/Ready cycle regardless of command). + // Pass the NonCombat stance (0x003D) so the resolver builds the + // correct cycle key for walk/run/turn commands. ushort cmdOverride = (ushort)(animCommand & 0xFFFFu); + const ushort NonCombatStance = 0x003D; var cycle = AcDream.Core.Meshing.MotionResolver.GetIdleCycle( ae.Setup, _dats, motionTableIdOverride: _playerMotionTableId, + stanceOverride: NonCombatStance, commandOverride: cmdOverride); - Console.WriteLine($"[PLAYER-ANIM] cmd=0x{animCommand:X8} cmdOverride=0x{cmdOverride:X4} " + - $"cycle={(cycle is null ? "NULL" : $"fr={cycle.Framerate:F1} low={cycle.LowFrame} high={cycle.HighFrame}")} " + - $"setup=0x{pe.SourceGfxObjOrSetupId:X8} mtable=0x{(uint)ae.Setup.DefaultMotionTable:X8}"); - if (cycle is null || cycle.Framerate == 0f || cycle.HighFrame <= cycle.LowFrame) return; ae.Animation = cycle.Animation; diff --git a/tests/AcDream.Core.Tests/Physics/PhysicsEngineTests.cs b/tests/AcDream.Core.Tests/Physics/PhysicsEngineTests.cs index 10b92b8..543555c 100644 --- a/tests/AcDream.Core.Tests/Physics/PhysicsEngineTests.cs +++ b/tests/AcDream.Core.Tests/Physics/PhysicsEngineTests.cs @@ -91,12 +91,16 @@ public class PhysicsEngineTests } [Fact] - public void Resolve_EnterIndoorCell_TransitionsToCell() + public void Resolve_EnterIndoorCell_StaysOutdoor_BecauseTransitionDisabled() { + // Phase B.2 MVP: outdoor→indoor transitions are disabled because + // CellSurface floor polygons are too aggressive (building + // footprints/roofs capture the player). Walking over a cell's XY + // area stays on the outdoor terrain Z. Indoor transitions will be + // re-enabled when portal-based detection lands in Phase E. var engine = new PhysicsEngine(); var terrain = new TerrainSurface(FlatHeightmap(50), LinearHeightTable()); - // Indoor cell with a floor at Z=55 covering (40..60, 40..60). var cellVerts = new Dictionary { [0] = new(40f, 40f, 55f), @@ -115,9 +119,9 @@ public class PhysicsEngineTests new Vector3(30f, 50f, 50f), cellId: 0x0001, delta: new Vector3(20f, 0f, 0f), stepUpHeight: 10f); - // Should transition to the indoor cell and snap to its floor Z. - Assert.Equal(0x0100u, result.CellId); - Assert.Equal(55f, result.Position.Z, precision: 1); + // Should stay outdoor (transition disabled) at terrain Z = 50. + Assert.True(result.CellId < 0x0100u); + Assert.Equal(50f, result.Position.Z, precision: 1); Assert.True(result.IsOnGround); }