diff --git a/src/AcDream.App/Input/PlayerMovementController.cs b/src/AcDream.App/Input/PlayerMovementController.cs index 469a74f..faa0b7f 100644 --- a/src/AcDream.App/Input/PlayerMovementController.cs +++ b/src/AcDream.App/Input/PlayerMovementController.cs @@ -64,8 +64,14 @@ public sealed class PlayerMovementController public float VerticalVelocity { get; private set; } public bool IsAirborne { get; private set; } - public float JumpImpulse { get; set; } = 3.5f; // placeholder; retail scales by Jump skill - public float GravityAccel { get; set; } = 20f; + /// + /// Jump velocity Z. AC formula: sqrt(height * 19.6) where + /// height = BurdenMod * (JumpSkill / (JumpSkill + 1300) * 22.2 + 0.05) * power. + /// For a typical new char (skill=100, burden=50%, power=1.0) ≈ 5.07. + /// + public float JumpImpulse { get; set; } = 5.0f; + /// AC's gravity constant (F_GRAVITY = 9.8 m/s²). + public float GravityAccel { get; set; } = 9.8f; public float AirControlFactor { get; set; } = 0.2f; /// diff --git a/src/AcDream.App/Rendering/GameWindow.cs b/src/AcDream.App/Rendering/GameWindow.cs index 833e93c..8bc256f 100644 --- a/src/AcDream.App/Rendering/GameWindow.cs +++ b/src/AcDream.App/Rendering/GameWindow.cs @@ -1562,11 +1562,22 @@ public sealed class GameWindow : IDisposable int observerCx = _liveCenterX; int observerCy = _liveCenterY; - if (_liveSession is not null + if (_playerMode && _playerController is not null) + { + // Player mode: follow the physics-resolved player position. + // The player walks via the local physics engine; the server + // doesn't echo back our autonomous moves, so _lastLivePlayer* + // stays at the login position. Compute the landblock from the + // controller's current world-space position instead. + var pp = _playerController.Position; + observerCx = _liveCenterX + (int)System.Math.Floor(pp.X / 192f); + observerCy = _liveCenterY + (int)System.Math.Floor(pp.Y / 192f); + } + else if (_liveSession is not null && _liveSession.CurrentState == AcDream.Core.Net.WorldSession.State.InWorld && _lastLivePlayerLandblockId is { } lid) { - // Live mode: follow the server's last-known player position. + // Live mode (fly camera): follow the server's last-known player position. observerCx = (int)((lid >> 24) & 0xFFu); observerCy = (int)((lid >> 16) & 0xFFu); }