From 0378a2379051b9c13843b8204ac7891d3b06bf4f Mon Sep 17 00:00:00 2001 From: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> Date: Sun, 17 Jul 2022 19:36:08 +1000 Subject: [PATCH] Make shuttle brakes use thrusters and bandaid shuttle movement (#9826) --- .../Physics/Controllers/MoverController.cs | 238 +++++++++++++----- .../Shuttles/Components/ShuttleComponent.cs | 2 +- .../Systems/ShuttleSystem.FasterThanLight.cs | 4 +- .../Shuttles/Systems/ShuttleSystem.cs | 34 +-- Content.Shared/CCVar/CCVars.cs | 17 -- .../Systems/SharedMoverController.Pushing.cs | 6 +- .../Movement/Systems/SharedMoverController.cs | 5 +- 7 files changed, 188 insertions(+), 118 deletions(-) diff --git a/Content.Server/Physics/Controllers/MoverController.cs b/Content.Server/Physics/Controllers/MoverController.cs index 9623964279..e304169000 100644 --- a/Content.Server/Physics/Controllers/MoverController.cs +++ b/Content.Server/Physics/Controllers/MoverController.cs @@ -13,7 +13,6 @@ namespace Content.Server.Physics.Controllers public sealed class MoverController : SharedMoverController { [Dependency] private readonly IMapManager _mapManager = default!; - [Dependency] private readonly ShuttleSystem _shuttle = default!; [Dependency] private readonly ThrusterSystem _thruster = default!; private Dictionary> _shuttlePilots = new(); @@ -233,49 +232,20 @@ namespace Content.Server.Physics.Controllers { if (Paused(shuttle.Owner) || FTLLocked(shuttle) || !TryComp(shuttle.Owner, out PhysicsComponent? body)) continue; + var shuttleNorthAngle = Transform(body.Owner).WorldRotation; + // Collate movement linear and angular inputs together var linearInput = Vector2.Zero; + var brakeInput = 0f; var angularInput = 0f; foreach (var (pilot, _, consoleXform) in pilots) { var pilotInput = GetPilotVelocityInput(pilot); - // On the one hand we could just make it relay inputs to brake - // but uhh may be disorienting? n if (pilotInput.Brakes > 0f) { - if (body.LinearVelocity.Length > 0f) - { - var force = body.LinearVelocity.Normalized * pilotInput.Brakes / body.InvMass * 3f; - var impulse = force * body.InvMass * frameTime; - - if (impulse.Length > body.LinearVelocity.Length) - { - body.LinearVelocity = Vector2.Zero; - } - else - { - body.ApplyLinearImpulse(-force * frameTime); - } - } - - if (body.AngularVelocity != 0f) - { - var force = body.AngularVelocity * pilotInput.Brakes / body.InvI * 2f; - var impulse = force * body.InvI * frameTime; - - if (MathF.Abs(impulse) > MathF.Abs(body.AngularVelocity)) - { - body.AngularVelocity = 0f; - } - else - { - body.ApplyAngularImpulse(-force * frameTime); - } - } - - continue; + brakeInput += pilotInput.Brakes; } if (pilotInput.Strafe.Length > 0f) @@ -293,12 +263,141 @@ namespace Content.Server.Physics.Controllers var count = pilots.Count; linearInput /= count; angularInput /= count; + brakeInput /= count; + + /* + * So essentially: + * 1. We do the same calcs for braking as we do for linear thrust so it's similar to a player pressing it + * but we also need to handle when they get close to 0 hence why it sets velocity directly. + * + * 2. We do a similar calculation to mob movement where the closer you are to your speed cap the slower you accelerate + * + * TODO: Could combine braking linear input and thrust more but my brain was just not working debugging + * TODO: Need to have variable speed caps based on thruster count or whatever + */ // Handle shuttle movement + if (brakeInput > 0f) + { + if (body.LinearVelocity.Length > 0f) + { + // Get velocity relative to the shuttle so we know which thrusters to fire + var shuttleVelocity = (-shuttleNorthAngle).RotateVec(body.LinearVelocity); + var force = Vector2.Zero; + + if (shuttleVelocity.X < 0f) + { + _thruster.DisableLinearThrustDirection(shuttle, DirectionFlag.West); + _thruster.EnableLinearThrustDirection(shuttle, DirectionFlag.East); + + var index = (int) Math.Log2((int) DirectionFlag.East); + force.X += shuttle.LinearThrust[index]; + } + else if (shuttleVelocity.X > 0f) + { + _thruster.DisableLinearThrustDirection(shuttle, DirectionFlag.East); + _thruster.EnableLinearThrustDirection(shuttle, DirectionFlag.West); + + var index = (int) Math.Log2((int) DirectionFlag.West); + force.X -= shuttle.LinearThrust[index]; + } + + if (shuttleVelocity.Y < 0f) + { + _thruster.DisableLinearThrustDirection(shuttle, DirectionFlag.South); + _thruster.EnableLinearThrustDirection(shuttle, DirectionFlag.North); + + var index = (int) Math.Log2((int) DirectionFlag.North); + force.Y += shuttle.LinearThrust[index]; + } + else if (shuttleVelocity.Y > 0f) + { + _thruster.DisableLinearThrustDirection(shuttle, DirectionFlag.North); + _thruster.EnableLinearThrustDirection(shuttle, DirectionFlag.South); + + var index = (int) Math.Log2((int) DirectionFlag.South); + force.Y -= shuttle.LinearThrust[index]; + } + + var impulse = force * brakeInput; + var wishDir = impulse.Normalized; + // TODO: Adjust max possible speed based on total thrust in particular direction. + var wishSpeed = 20f; + + var currentSpeed = Vector2.Dot(shuttleVelocity, wishDir); + var addSpeed = wishSpeed - currentSpeed; + + if (addSpeed > 0f) + { + var accelSpeed = impulse.Length * frameTime; + accelSpeed = MathF.Min(accelSpeed, addSpeed); + impulse = impulse.Normalized * accelSpeed * body.InvMass; + + // Cap inputs + if (shuttleVelocity.X < 0f) + { + impulse.X = MathF.Min(impulse.X, -shuttleVelocity.X); + } + else if (shuttleVelocity.X > 0f) + { + impulse.X = MathF.Max(impulse.X, -shuttleVelocity.X); + } + + if (shuttleVelocity.Y < 0f) + { + impulse.Y = MathF.Min(impulse.Y, -shuttleVelocity.Y); + } + else if (shuttleVelocity.Y > 0f) + { + impulse.Y = MathF.Max(impulse.Y, -shuttleVelocity.Y); + } + + PhysicsSystem.SetLinearVelocity(body, body.LinearVelocity + shuttleNorthAngle.RotateVec(impulse)); + } + } + else + { + _thruster.DisableLinearThrusters(shuttle); + } + + if (body.AngularVelocity != 0f) + { + var impulse = shuttle.AngularThrust * brakeInput * (body.AngularVelocity > 0f ? -1f : 1f); + var wishSpeed = MathF.PI; + + if (impulse < 0f) + wishSpeed *= -1f; + + var currentSpeed = body.AngularVelocity; + var addSpeed = wishSpeed - currentSpeed; + + if (!addSpeed.Equals(0f)) + { + var accelSpeed = impulse * body.InvI * frameTime; + + if (accelSpeed < 0f) + accelSpeed = MathF.Max(accelSpeed, addSpeed); + else + accelSpeed = MathF.Min(accelSpeed, addSpeed); + + if (body.AngularVelocity < 0f && body.AngularVelocity + accelSpeed > 0f) + accelSpeed = -body.AngularVelocity; + else if (body.AngularVelocity > 0f && body.AngularVelocity + accelSpeed < 0f) + accelSpeed = -body.AngularVelocity; + + PhysicsSystem.SetAngularVelocity(body, body.AngularVelocity + accelSpeed); + _thruster.SetAngularThrust(shuttle, true); + } + } + } + if (linearInput.Length.Equals(0f)) { - _thruster.DisableLinearThrusters(shuttle); - body.LinearDamping = _shuttle.ShuttleIdleLinearDamping * body.InvMass; + body.SleepingAllowed = true; + + if (brakeInput.Equals(0f)) + _thruster.DisableLinearThrusters(shuttle); + if (body.LinearVelocity.Length < 0.08) { body.LinearVelocity = Vector2.Zero; @@ -306,11 +405,10 @@ namespace Content.Server.Physics.Controllers } else { - body.LinearDamping = 0; + body.SleepingAllowed = false; var angle = linearInput.ToWorldAngle(); var linearDir = angle.GetDir(); var dockFlag = linearDir.AsFlag(); - var shuttleNorth = EntityManager.GetComponent(body.Owner).WorldRotation.ToWorldVec(); var totalForce = new Vector2(); @@ -335,46 +433,52 @@ namespace Content.Server.Physics.Controllers continue; } - float length; - Angle thrustAngle; + var index = (int) Math.Log2((int) dir); + var thrust = shuttle.LinearThrust[index]; switch (dir) { case DirectionFlag.North: - length = linearInput.Y; - thrustAngle = new Angle(MathF.PI); + totalForce.Y += thrust; break; case DirectionFlag.South: - length = -linearInput.Y; - thrustAngle = new Angle(0f); + totalForce.Y -= thrust; break; case DirectionFlag.East: - length = linearInput.X; - thrustAngle = new Angle(MathF.PI / 2f); + totalForce.X += thrust; break; case DirectionFlag.West: - length = -linearInput.X; - thrustAngle = new Angle(-MathF.PI / 2f); + totalForce.X -= thrust; break; default: throw new ArgumentOutOfRangeException(); } _thruster.EnableLinearThrustDirection(shuttle, dir); - - var index = (int) Math.Log2((int) dir); - var force = thrustAngle.RotateVec(shuttleNorth) * shuttle.LinearThrust[index] * length; - - totalForce += force; } - body.ApplyLinearImpulse(totalForce * frameTime); + // We don't want to touch damping if no inputs are given + // so we'll just add an artifical drag to the velocity input. + var shuttleVelocity = (-shuttleNorthAngle).RotateVec(body.LinearVelocity); + + var wishDir = totalForce.Normalized; + // TODO: Adjust max possible speed based on total thrust in particular direction. + var wishSpeed = 20f; + + var currentSpeed = Vector2.Dot(shuttleVelocity, wishDir); + var addSpeed = wishSpeed - currentSpeed; + + if (addSpeed > 0f) + { + var accelSpeed = totalForce.Length * frameTime; + accelSpeed = MathF.Min(accelSpeed, addSpeed); + body.ApplyLinearImpulse(shuttleNorthAngle.RotateVec(totalForce.Normalized * accelSpeed)); + } } if (MathHelper.CloseTo(angularInput, 0f)) { _thruster.SetAngularThrust(shuttle, false); - body.AngularDamping = _shuttle.ShuttleIdleAngularDamping * body.InvI; body.SleepingAllowed = true; if (Math.Abs(body.AngularVelocity) < 0.01f) @@ -384,18 +488,28 @@ namespace Content.Server.Physics.Controllers } else { - body.AngularDamping = 0; body.SleepingAllowed = false; + var impulse = shuttle.AngularThrust * -angularInput; + var wishSpeed = MathF.PI; - var maxSpeed = Math.Min(_shuttle.ShuttleMaxAngularMomentum * body.InvI, _shuttle.ShuttleMaxAngularSpeed); - var maxTorque = body.Inertia * _shuttle.ShuttleMaxAngularAcc; + if (impulse < 0f) + wishSpeed *= -1f; - var torque = Math.Min(shuttle.AngularThrust, maxTorque); - var dragTorque = body.AngularVelocity * (torque / maxSpeed); + var currentSpeed = body.AngularVelocity; + var addSpeed = wishSpeed - currentSpeed; - body.ApplyAngularImpulse((-angularInput * torque - dragTorque) * frameTime); + if (!addSpeed.Equals(0f)) + { + var accelSpeed = impulse * body.InvI * frameTime; - _thruster.SetAngularThrust(shuttle, true); + if (accelSpeed < 0f) + accelSpeed = MathF.Max(accelSpeed, addSpeed); + else + accelSpeed = MathF.Min(accelSpeed, addSpeed); + + PhysicsSystem.SetAngularVelocity(body, body.AngularVelocity + accelSpeed); + _thruster.SetAngularThrust(shuttle, true); + } } } } diff --git a/Content.Server/Shuttles/Components/ShuttleComponent.cs b/Content.Server/Shuttles/Components/ShuttleComponent.cs index 749458ef91..b5fe77ebf6 100644 --- a/Content.Server/Shuttles/Components/ShuttleComponent.cs +++ b/Content.Server/Shuttles/Components/ShuttleComponent.cs @@ -22,7 +22,7 @@ namespace Content.Server.Shuttles.Components /// /// The thrusters contributing to the angular impulse of the shuttle. /// - public readonly List AngularThrusters = new List(); + public readonly List AngularThrusters = new(); [ViewVariables] public float AngularThrust = 0f; diff --git a/Content.Server/Shuttles/Systems/ShuttleSystem.FasterThanLight.cs b/Content.Server/Shuttles/Systems/ShuttleSystem.FasterThanLight.cs index 0a15dc5306..219727fac0 100644 --- a/Content.Server/Shuttles/Systems/ShuttleSystem.FasterThanLight.cs +++ b/Content.Server/Shuttles/Systems/ShuttleSystem.FasterThanLight.cs @@ -261,8 +261,8 @@ public sealed partial class ShuttleSystem { body.LinearVelocity = Vector2.Zero; body.AngularVelocity = 0f; - body.LinearDamping = ShuttleIdleLinearDamping; - body.AngularDamping = ShuttleIdleAngularDamping; + body.LinearDamping = ShuttleLinearDamping; + body.AngularDamping = ShuttleAngularDamping; } TryComp(comp.Owner, out shuttle); diff --git a/Content.Server/Shuttles/Systems/ShuttleSystem.cs b/Content.Server/Shuttles/Systems/ShuttleSystem.cs index a9b8e714ad..cb9eed5e30 100644 --- a/Content.Server/Shuttles/Systems/ShuttleSystem.cs +++ b/Content.Server/Shuttles/Systems/ShuttleSystem.cs @@ -21,14 +21,8 @@ namespace Content.Server.Shuttles.Systems public const float TileMassMultiplier = 0.5f; - public float ShuttleMaxLinearSpeed; - - public float ShuttleMaxAngularMomentum; - public float ShuttleMaxAngularAcc; - public float ShuttleMaxAngularSpeed; - - public float ShuttleIdleLinearDamping; - public float ShuttleIdleAngularDamping; + public const float ShuttleLinearDamping = 0.05f; + public const float ShuttleAngularDamping = 0.05f; public override void Initialize() { @@ -47,14 +41,6 @@ namespace Content.Server.Shuttles.Systems SubscribeLocalEvent(OnGridInit); SubscribeLocalEvent(OnGridFixtureChange); - - var configManager = IoCManager.Resolve(); - configManager.OnValueChanged(CCVars.ShuttleMaxLinearSpeed, SetShuttleMaxLinearSpeed, true); - configManager.OnValueChanged(CCVars.ShuttleMaxAngularSpeed, SetShuttleMaxAngularSpeed, true); - configManager.OnValueChanged(CCVars.ShuttleIdleLinearDamping, SetShuttleIdleLinearDamping, true); - configManager.OnValueChanged(CCVars.ShuttleIdleAngularDamping, SetShuttleIdleAngularDamping, true); - configManager.OnValueChanged(CCVars.ShuttleMaxAngularAcc, SetShuttleMaxAngularAcc, true); - configManager.OnValueChanged(CCVars.ShuttleMaxAngularMomentum, SetShuttleMaxAngularMomentum, true); } public override void Update(float frameTime) @@ -71,23 +57,11 @@ namespace Content.Server.Shuttles.Systems CleanupHyperspace(); } - private void SetShuttleMaxLinearSpeed(float value) => ShuttleMaxLinearSpeed = value; - private void SetShuttleMaxAngularSpeed(float value) => ShuttleMaxAngularSpeed = value; - private void SetShuttleMaxAngularAcc(float value) => ShuttleMaxAngularAcc = value; - private void SetShuttleMaxAngularMomentum(float value) => ShuttleMaxAngularMomentum = value; - private void SetShuttleIdleLinearDamping(float value) => ShuttleIdleLinearDamping = value; - private void SetShuttleIdleAngularDamping(float value) => ShuttleIdleAngularDamping = value; - public override void Shutdown() { base.Shutdown(); ShutdownEscape(); ShutdownEmergencyConsole(); - _configManager.UnsubValueChanged(CCVars.ShuttleMaxLinearSpeed, SetShuttleMaxLinearSpeed); - _configManager.UnsubValueChanged(CCVars.ShuttleMaxAngularSpeed, SetShuttleMaxAngularSpeed); - _configManager.UnsubValueChanged(CCVars.ShuttleIdleLinearDamping, SetShuttleIdleLinearDamping); - _configManager.UnsubValueChanged(CCVars.ShuttleIdleAngularDamping, SetShuttleIdleAngularDamping); - _configManager.UnsubValueChanged(CCVars.ShuttleMaxAngularMomentum, SetShuttleMaxAngularMomentum); } private void OnShuttleAdd(EntityUid uid, ShuttleComponent component, ComponentAdd args) @@ -159,8 +133,8 @@ namespace Content.Server.Shuttles.Systems component.BodyType = BodyType.Dynamic; component.BodyStatus = BodyStatus.InAir; component.FixedRotation = false; - component.LinearDamping = ShuttleIdleLinearDamping; - component.AngularDamping = ShuttleIdleAngularDamping; + component.LinearDamping = ShuttleLinearDamping; + component.AngularDamping = ShuttleAngularDamping; } private void Disable(PhysicsComponent component) diff --git a/Content.Shared/CCVar/CCVars.cs b/Content.Shared/CCVar/CCVars.cs index 5649bbe1ee..1e60b2cc97 100644 --- a/Content.Shared/CCVar/CCVars.cs +++ b/Content.Shared/CCVar/CCVars.cs @@ -869,23 +869,6 @@ namespace Content.Shared.CCVar /* * Shuttles */ - public static readonly CVarDef ShuttleMaxLinearSpeed = - CVarDef.Create("shuttle.max_linear_speed", 13f, CVar.SERVERONLY); - - public static readonly CVarDef ShuttleMaxAngularSpeed = - CVarDef.Create("shuttle.max_angular_speed", 1.4f, CVar.SERVERONLY); - - public static readonly CVarDef ShuttleMaxAngularAcc = - CVarDef.Create("shuttle.max_angular_acc", 2f, CVar.SERVERONLY); - - public static readonly CVarDef ShuttleMaxAngularMomentum = - CVarDef.Create("shuttle.max_angular_momentum", 60000f, CVar.SERVERONLY); - - public static readonly CVarDef ShuttleIdleLinearDamping = - CVarDef.Create("shuttle.idle_linear_damping", 50f, CVar.SERVERONLY); - - public static readonly CVarDef ShuttleIdleAngularDamping = - CVarDef.Create("shuttle.idle_angular_damping", 100f, CVar.SERVERONLY); /// /// Whether cargo shuttles are enabled. diff --git a/Content.Shared/Movement/Systems/SharedMoverController.Pushing.cs b/Content.Shared/Movement/Systems/SharedMoverController.Pushing.cs index a3a92fdb31..b29ee8c5b4 100644 --- a/Content.Shared/Movement/Systems/SharedMoverController.Pushing.cs +++ b/Content.Shared/Movement/Systems/SharedMoverController.Pushing.cs @@ -22,18 +22,18 @@ public abstract partial class SharedMoverController if (_pushingEnabled) { - _physics.KinematicControllerCollision += OnMobCollision; + PhysicsSystem.KinematicControllerCollision += OnMobCollision; } else { - _physics.KinematicControllerCollision -= OnMobCollision; + PhysicsSystem.KinematicControllerCollision -= OnMobCollision; } } private void ShutdownPushing() { if (_pushingEnabled) - _physics.KinematicControllerCollision -= OnMobCollision; + PhysicsSystem.KinematicControllerCollision -= OnMobCollision; _configManager.UnsubValueChanged(CCVars.MobPushing, SetPushing); } diff --git a/Content.Shared/Movement/Systems/SharedMoverController.cs b/Content.Shared/Movement/Systems/SharedMoverController.cs index 1ee75a4f4e..4f8d431edd 100644 --- a/Content.Shared/Movement/Systems/SharedMoverController.cs +++ b/Content.Shared/Movement/Systems/SharedMoverController.cs @@ -35,7 +35,6 @@ namespace Content.Shared.Movement.Systems [Dependency] private readonly InventorySystem _inventory = default!; [Dependency] private readonly SharedContainerSystem _container = default!; [Dependency] private readonly SharedMobStateSystem _mobState = default!; - [Dependency] private readonly SharedPhysicsSystem _physics = default!; [Dependency] private readonly TagSystem _tags = default!; private const float StepSoundMoveDistanceRunning = 2; @@ -131,7 +130,7 @@ namespace Content.Shared.Movement.Systems touching = ev.CanMove; if (!touching && TryComp(xform.Owner, out var mobMover)) - touching |= IsAroundCollider(_physics, xform, mobMover, physicsComponent); + touching |= IsAroundCollider(PhysicsSystem, xform, mobMover, physicsComponent); } if (!touching) @@ -227,7 +226,7 @@ namespace Content.Shared.Movement.Systems if (!weightless || touching) Accelerate(ref velocity, in worldTotal, accel, frameTime); - _physics.SetLinearVelocity(physicsComponent, velocity); + PhysicsSystem.SetLinearVelocity(physicsComponent, velocity); } private void Friction(float minimumFrictionSpeed, float frameTime, float friction, ref Vector2 velocity)