From bb7eced1684613a4808c1641861f90c4d4de41aa Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 14 Apr 2026 10:17:59 +0200 Subject: [PATCH] fix(movement): jump works locally (airborne velocity preserved) Two fixes for jump physics: - Skip ground-snap when velocity Z > 0 (prevents immediate re-landing at high framerates where per-frame Z delta < 0.05 snap threshold) - Guard apply_current_movement velocity write behind OnWalkable check (prevents MotionInterpreter.DoMotion from zeroing jump velocity on every frame while airborne) - Guard PlayerMovementController velocity replacement behind OnWalkable (preserves momentum during airborne flight) Also fix run speed: compute RunRate locally via PlayerWeenie.InqRunRate instead of waiting for server UpdateMotion echo (server doesn't echo to sender). With Run skill 200, run speed is now 9.5 m/s instead of 4.0 m/s. Strip all diagnostic logging from previous debug sessions. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../Input/PlayerMovementController.cs | 31 ++++++------------- src/AcDream.App/Rendering/GameWindow.cs | 1 - 2 files changed, 9 insertions(+), 23 deletions(-) diff --git a/src/AcDream.App/Input/PlayerMovementController.cs b/src/AcDream.App/Input/PlayerMovementController.cs index 97e8226..bfdaa69 100644 --- a/src/AcDream.App/Input/PlayerMovementController.cs +++ b/src/AcDream.App/Input/PlayerMovementController.cs @@ -97,8 +97,6 @@ public sealed class PlayerMovementController // Jump charge state. private bool _jumpCharging; - private int _debugSpeedLogCounter; - private int _debugJumpFrames; private float _jumpExtent; private const float JumpChargeRate = 1.0f; // 0→1 over 1 second @@ -196,8 +194,15 @@ public sealed class PlayerMovementController float forwardCmdSpeed; if (input.Forward) { - forwardCmd = input.Run ? MotionCommand.RunForward : MotionCommand.WalkForward; - forwardCmdSpeed = 1.0f; + forwardCmd = input.Run ? MotionCommand.RunForward : MotionCommand.WalkForward; + // When running, use the PlayerWeenie's RunRate as ForwardSpeed. + // The retail server computes this from Run skill + encumbrance and + // broadcasts it in UpdateMotion, but it doesn't echo to the sender. + // We compute locally using the same formula. + if (input.Run && _weenie.InqRunRate(out float runRate)) + forwardCmdSpeed = runRate; + else + forwardCmdSpeed = 1.0f; } else if (input.Backward) { @@ -246,8 +251,6 @@ public sealed class PlayerMovementController else if (input.StrafeLeft) localX = -MotionInterpreter.SidestepAnimSpeed * 0.5f; - if (input.Forward && _debugSpeedLogCounter++ % 60 == 0) - Console.WriteLine($"DEBUG speed: stateVel.Y={stateVel.Y:F2} MyRunRate={_motion.MyRunRate:F3} localY={localY:F2}"); _body.set_local_velocity(new Vector3(localX, localY, savedWorldVz)); } @@ -275,12 +278,6 @@ public sealed class PlayerMovementController { _motion.LeaveGround(); outJumpExtent = _jumpExtent; - _debugJumpFrames = 500; // log until landing - Console.WriteLine($"DEBUG jump FIRED: extent={_jumpExtent:F2} vel={_body.Velocity} onWalk={_body.OnWalkable}"); - } - else - { - Console.WriteLine($"DEBUG jump FAILED: extent={_jumpExtent:F2} result={jumpResult} onWalk={_body.OnWalkable} contact={_body.InContact}"); } _jumpCharging = false; _jumpExtent = 0f; @@ -295,12 +292,6 @@ public sealed class PlayerMovementController _body.calc_acceleration(); _body.UpdatePhysicsInternal(dt); - if (_debugJumpFrames > 0) - { - _debugJumpFrames--; - Console.WriteLine($"DEBUG jump frame: pos.Z={_body.Position.Z:F3} vel.Z={_body.Velocity.Z:F3} onWalk={_body.OnWalkable} accel.Z={_body.Acceleration.Z:F1} dt={dt:F4}"); - } - // ── 5. Terrain/cell Z snap and ground-contact detection ─────────────── // Use PhysicsEngine.Resolve to find the ground surface Z under the player. // We pass a zero delta because PhysicsBody already moved the position. @@ -326,11 +317,7 @@ public sealed class PlayerMovementController _body.Velocity = new Vector3(_body.Velocity.X, _body.Velocity.Y, 0f); if (wasAirborne) - { - Console.WriteLine($"DEBUG LANDED: bodyZ={bodyZ:F3} groundZ={groundZ:F3} vel.Z={_body.Velocity.Z:F3}"); _motion.HitGround(); - _debugJumpFrames = 0; - } } else { diff --git a/src/AcDream.App/Rendering/GameWindow.cs b/src/AcDream.App/Rendering/GameWindow.cs index 2e279f6..981070b 100644 --- a/src/AcDream.App/Rendering/GameWindow.cs +++ b/src/AcDream.App/Rendering/GameWindow.cs @@ -967,7 +967,6 @@ public sealed class GameWindow : IDisposable && update.MotionState.ForwardSpeed.HasValue && update.MotionState.ForwardSpeed.Value > 0f) { - Console.WriteLine($"DEBUG RunRate: guid={update.Guid:X8} fwd={update.MotionState.ForwardSpeed.Value:F3}"); _playerController.ApplyServerRunRate(update.MotionState.ForwardSpeed.Value); }