diff --git a/Assets/Scripts/ServerShared/Behaviors/VelocityLimit.cs b/Assets/Scripts/ServerShared/Behaviors/VelocityLimit.cs index 407e5f949..95508ad4e 100644 --- a/Assets/Scripts/ServerShared/Behaviors/VelocityLimit.cs +++ b/Assets/Scripts/ServerShared/Behaviors/VelocityLimit.cs @@ -45,7 +45,11 @@ public class VelocityLimit : Behavior { Limit = Evaluate(_data.TopSpeed); if (length(Entity.Velocity) > Limit) - Entity.Velocity = normalize(Entity.Velocity) * Limit; + { + var clamped = normalize(Entity.Velocity) * Limit; + Entity.LimitClamp += Entity.Velocity - clamped; + Entity.Velocity = clamped; + } return true; } } \ No newline at end of file diff --git a/Assets/Scripts/ServerShared/Entity.cs b/Assets/Scripts/ServerShared/Entity.cs index 0e8a35679..db33c321c 100644 --- a/Assets/Scripts/ServerShared/Entity.cs +++ b/Assets/Scripts/ServerShared/Entity.cs @@ -29,6 +29,11 @@ public abstract class Entity public float2 Acceleration; public ManoeuvreTrack Manoeuvre; + // The planar velocity a VelocityLimit removed during the current base update. A limit is the ship's ceiling, not a + // change of vector the pilot made, so Acceleration reads the velocity change with this put back. VelocityLimit is + // the one writer, Entity.Update zeroes it, and it is never saved. + public float2 LimitClamp; + public float[,] Temperature; public float[,] NewTemperature; public bool2[,] HullConductivity; @@ -1350,6 +1355,7 @@ public abstract class Entity if (!_active) return; var velocityBefore = Velocity; + LimitClamp = float2(0, 0); var hullData = ItemManager.GetData(Hull) as HullData; // Mining Cut 3: a chunk target is lost the moment this entity can no longer see it -- the lost-track rule @@ -1466,7 +1472,7 @@ public abstract class Entity } else Position.y = Zone.GetHeight(Position.xz) + hullData.GridOffset; - Acceleration = delta > 0f ? (Velocity - velocityBefore) / delta : float2(0, 0); + Acceleration = delta > 0f ? (Velocity + LimitClamp - velocityBefore) / delta : float2(0, 0); Manoeuvre.Observe(Acceleration, delta, ItemManager.GameplaySettings.SolutionWindow); }