From f3927e24db366d84330234554a87111c7e447f76 Mon Sep 17 00:00:00 2001 From: soul Date: Thu, 29 Oct 2026 10:18:20 +0100 Subject: [PATCH] Pin a docked ship to its parent before the inactive return; no flight while docked Docking deactivates the ship, and Entity.Update returned before the parent pin, so a docked ship kept integrating its own velocity and gravity (Ship.Update) for as long as it sat in the bay, and undocked wherever it had fallen to at whatever speed it had reached. Drag used to bleed that off; with no drag below top speed it flung the ship into the void. Co-Authored-By: Claude Opus 5.5 --- Assets/Scripts/ServerShared/Entity.cs | 14 ++++++++------ Assets/Scripts/ServerShared/Ship.cs | 22 +++++++++++++--------- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/Assets/Scripts/ServerShared/Entity.cs b/Assets/Scripts/ServerShared/Entity.cs index 510e3a51d..2394a6134 100644 --- a/Assets/Scripts/ServerShared/Entity.cs +++ b/Assets/Scripts/ServerShared/Entity.cs @@ -1821,6 +1821,13 @@ public abstract class Entity public virtual void Update(float delta) { TurnRate = 0; + // A parented entity (a docked ship) sits on its parent, active or not: docking deactivates the ship, so this pin + // comes before the inactive return, or the ship keeps whatever pose its own physics last gave it. + if (Parent != null) + { + Position = Parent.Position; + Velocity = Parent.Velocity; + } if (!_active) return; var velocityBefore = Velocity; @@ -1937,12 +1944,7 @@ public abstract class Entity foreach(var child in Children) child.Update(delta); - if (Parent != null) - { - Position = Parent.Position; - Velocity = Parent.Velocity; - } - else Position.y = RideHeight(Position.xz); + if (Parent == null) Position.y = RideHeight(Position.xz); Acceleration = delta > 0f ? (Velocity + LimitClamp - velocityBefore) / delta : float2(0, 0); Manoeuvre.Observe(Acceleration, delta, ItemManager.GameplaySettings.SolutionWindow); diff --git a/Assets/Scripts/ServerShared/Ship.cs b/Assets/Scripts/ServerShared/Ship.cs index b4a6ff93e..1266f5c90 100644 --- a/Assets/Scripts/ServerShared/Ship.cs +++ b/Assets/Scripts/ServerShared/Ship.cs @@ -167,15 +167,19 @@ public class Ship : Entity // No drag below top speed: ships coast and orbits do not decay; drag bleeds off only the excess over the hull's top // speed (aetheria-gravity:ruling:no-drag-below-top-speed). The VelocityLimit clamp still caps it, so the excess is // what this step's forces added; a soft cap, where surfing the beat is a temporary boost, is the ruling's other half. - var velocityMagnitude = length(Velocity); - var topSpeed = float.PositiveInfinity; - foreach (var limit in GetBehaviors()) topSpeed = min(topSpeed, limit.Limit); - if (velocityMagnitude > topSpeed) - Velocity = normalize(Velocity) * (topSpeed + decay(velocityMagnitude - topSpeed, HullData.Drag * ItemManager.GameplaySettings.DragScale, delta)); - - Position.xz += Velocity * delta; - - Velocity += Zone.GetForce(Position.xz) * delta; + // A docked ship has no flight of its own: its parent owns its pose (Entity.Update). + if (Parent == null) + { + var velocityMagnitude = length(Velocity); + var topSpeed = float.PositiveInfinity; + foreach (var limit in GetBehaviors()) topSpeed = min(topSpeed, limit.Limit); + if (velocityMagnitude > topSpeed) + Velocity = normalize(Velocity) * (topSpeed + decay(velocityMagnitude - topSpeed, HullData.Drag * ItemManager.GameplaySettings.DragScale, delta)); + + Position.xz += Velocity * delta; + + Velocity += Zone.GetForce(Position.xz) * delta; + } var normal = Zone.GetNormal(Position.xz); var shipRight = Direction.Rotate(ItemRotation.Clockwise); var forward = cross(float3(shipRight.x, 0, shipRight.y), normal);