diff --git a/src/AcDream.App/Input/PlayerMovementController.cs b/src/AcDream.App/Input/PlayerMovementController.cs index 2a4896b..63b92ac 100644 --- a/src/AcDream.App/Input/PlayerMovementController.cs +++ b/src/AcDream.App/Input/PlayerMovementController.cs @@ -234,6 +234,12 @@ public sealed class PlayerMovementController private float _autoWalkMinDistance; private float _autoWalkDistanceToObject; private bool _autoWalkMoveTowards; + // Wire's WalkRunThreshold — retail semantic: locomotion runs while + // remaining distance > threshold, walks once inside threshold. ACE's + // Use/PickUp path uses MoveToParameters.SetDefaults() = 15.0f, so + // most pickup targets walk the entire way. ACE's charge path sets + // it to 1.0f so combat chase runs almost the whole way. + private float _autoWalkWalkRunThreshold; /// /// True while a server-initiated auto-walk (MoveToObject inbound) is @@ -343,13 +349,15 @@ public sealed class PlayerMovementController Vector3 destinationWorld, float minDistance, float distanceToObject, - bool moveTowards) + bool moveTowards, + float walkRunThreshold) { _autoWalkActive = true; _autoWalkDestination = destinationWorld; _autoWalkMinDistance = minDistance; _autoWalkDistanceToObject = distanceToObject; _autoWalkMoveTowards = moveTowards; + _autoWalkWalkRunThreshold = walkRunThreshold; } /// @@ -444,14 +452,25 @@ public sealed class PlayerMovementController while (Yaw < -MathF.PI) Yaw += 2f * MathF.PI; } - // Synthesize "running forward" input. The rest of Update reads + // Walk vs run per the wire's WalkRunThreshold. Retail semantics: + // dist > threshold → RUN, dist ≤ threshold → WALK. ACE's default + // for Use/PickUp is 15.0 m (so close targets walk the whole way); + // ACE's combat charge path sets it to 1.0 m (so chase runs to the + // last metre then walks the final approach). Matches the user's + // observed retail behaviour: "When at a distance X it should + // start running towards the double clicked target… When at a + // shorter distance it should walk to it." + bool shouldRun = dist > _autoWalkWalkRunThreshold; + + // Synthesize "moving forward" input. The rest of Update reads // Yaw + input.Forward + input.Run to drive _motion + body - // velocity exactly as it does for user-driven W+Shift. We zero - // any mouse delta so a stale frame doesn't fight the steering. + // velocity exactly as it does for user-driven W (+ optional Shift). + // We zero any mouse delta so a stale frame doesn't fight the + // steering. return input with { Forward = true, - Run = true, + Run = shouldRun, Backward = false, StrafeLeft = false, StrafeRight = false, diff --git a/src/AcDream.App/Rendering/GameWindow.cs b/src/AcDream.App/Rendering/GameWindow.cs index 6d002a9..bc81639 100644 --- a/src/AcDream.App/Rendering/GameWindow.cs +++ b/src/AcDream.App/Rendering/GameWindow.cs @@ -3338,11 +3338,12 @@ public sealed class GameWindow : IDisposable destWorld, pathData.MinDistance, pathData.DistanceToObject, - update.MotionState.MoveTowards); + update.MotionState.MoveTowards, + pathData.WalkRunThreshold); if (AcDream.Core.Physics.PhysicsDiagnostics.ProbeAutoWalkEnabled) { Console.WriteLine(System.FormattableString.Invariant( - $"[autowalk-begin] dest=({destWorld.X:F2},{destWorld.Y:F2},{destWorld.Z:F2}) minDist={pathData.MinDistance:F2} objDist={pathData.DistanceToObject:F2} towards={update.MotionState.MoveTowards}")); + $"[autowalk-begin] dest=({destWorld.X:F2},{destWorld.Y:F2},{destWorld.Z:F2}) minDist={pathData.MinDistance:F2} objDist={pathData.DistanceToObject:F2} walkRunThresh={pathData.WalkRunThreshold:F2} towards={update.MotionState.MoveTowards}")); } } // Note: do NOT cancel auto-walk on a non-MoveTo motion