diff --git a/Content.Server/GameObjects/EntitySystems/HandsSystem.cs b/Content.Server/GameObjects/EntitySystems/HandsSystem.cs index 79b6c9a757..6751a04a5c 100644 --- a/Content.Server/GameObjects/EntitySystems/HandsSystem.cs +++ b/Content.Server/GameObjects/EntitySystems/HandsSystem.cs @@ -1,36 +1,23 @@ -using System; -using System.Linq; -using Content.Server.GameObjects; -using Content.Server.GameObjects.Components; +using System.Linq; using Content.Server.GameObjects.Components.Stack; using Content.Server.Interfaces; using Content.Server.Interfaces.GameObjects; using Content.Server.Throw; using Content.Shared.GameObjects.Components.Inventory; using Content.Shared.Input; -using Content.Shared.Interfaces; -using Content.Shared.Physics; using JetBrains.Annotations; -using Robust.Server.GameObjects; using Robust.Server.GameObjects.EntitySystemMessages; using Robust.Server.GameObjects.EntitySystems; using Robust.Server.Interfaces.Player; using Robust.Shared.GameObjects; -using Robust.Shared.GameObjects.Components; using Robust.Shared.GameObjects.Systems; using Robust.Shared.Input; using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Interfaces.Map; -using Robust.Shared.Interfaces.Physics; -using Robust.Shared.Interfaces.Timing; using Robust.Shared.IoC; using Robust.Shared.Localization; -using Robust.Shared.Log; using Robust.Shared.Map; -using Robust.Shared.Maths; -using Robust.Shared.Physics; using Robust.Shared.Players; -using Robust.Shared.Utility; namespace Content.Server.GameObjects.EntitySystems { @@ -195,7 +182,7 @@ namespace Content.Server.GameObjects.EntitySystems newStackComp.Count = 1; } - ThrowHelper.Throw(throwEnt, ThrowForce, coords, plyEnt.Transform.GridPosition, false, plyEnt); + ThrowHelper.ThrowTo(throwEnt, ThrowForce, coords, plyEnt.Transform.GridPosition, false, plyEnt); return true; } diff --git a/Content.Server/Throw/ThrowHelper.cs b/Content.Server/Throw/ThrowHelper.cs index 8cdf31050a..42e0da9e1d 100644 --- a/Content.Server/Throw/ThrowHelper.cs +++ b/Content.Server/Throw/ThrowHelper.cs @@ -12,13 +12,34 @@ using Robust.Shared.Maths; using Robust.Shared.Physics; using Robust.Shared.Random; using System; -using System.Collections.Generic; -using System.Text; +using Robust.Shared.Interfaces.Physics; namespace Content.Server.Throw { public static class ThrowHelper { + /// + /// Throw an entity in the direction of from . + /// + /// The entity to throw. + /// + /// The force to throw the entity with. + /// Total impulse applied is equal to this force applied for one second. + /// + /// + /// The target location to throw at. + /// This is only used to calculate a direction, + /// actual distance is purely determined by . + /// + /// + /// The position to start the throw from. + /// + /// + /// If true, slightly spread the actual throw angle. + /// + /// + /// The entity that did the throwing. An opposite impulse will be applied to this entity if passed in. + /// public static void Throw(IEntity thrownEnt, float throwForce, GridCoordinates targetLoc, GridCoordinates sourceLoc, bool spread = false, IEntity throwSourceEnt = null) { if (!thrownEnt.TryGetComponent(out CollidableComponent colComp)) @@ -64,11 +85,68 @@ namespace Content.Server.Throw physComp.SetController(); (physComp.Controller as ThrowController)?.StartThrow(angle.ToVec() * spd); - if (throwSourceEnt != null && throwSourceEnt.TryGetComponent(out var physics)) + if (throwSourceEnt != null && throwSourceEnt.TryGetComponent(out var physics) + && physics.Controller is MoverController mover) { - const float ThrowFactor = 5.0f; // Break Newton's Third Law for better gameplay - (physics.Controller as MoverController)?.Push(-angle.ToVec(), spd * ThrowFactor / physics.Mass); + var physicsMgr = IoCManager.Resolve(); + + if (physicsMgr.IsWeightless(throwSourceEnt.Transform.GridPosition)) + { + // We don't check for surrounding entities, + // so you'll still get knocked around if you're hugging the station wall in zero g. + // I got kinda lazy is the reason why. Also it makes a bit of sense. + // If somebody wants they can come along and make it so magboots completely hold you still. + // Would be a cool incentive to use them. + const float ThrowFactor = 5.0f; // Break Newton's Third Law for better gameplay + mover.Push(-angle.ToVec(), spd * ThrowFactor / physics.Mass); + } } } + + /// + /// Throw an entity at the position of from , + /// without overshooting. + /// + /// The entity to throw. + /// + /// The MAXIMUM force to throw the entity with. + /// Throw force increases with distance to target, this is the maximum force allowed. + /// + /// + /// The target location to throw at. + /// This function will try to land at this exact spot, + /// if is large enough to allow for it to be reached. + /// + /// + /// The position to start the throw from. + /// + /// + /// If true, slightly spread the actual throw angle. + /// + /// + /// The entity that did the throwing. An opposite impulse will be applied to this entity if passed in. + /// + public static void ThrowTo(IEntity thrownEnt, float throwForceMax, GridCoordinates targetLoc, + GridCoordinates sourceLoc, bool spread = false, IEntity throwSourceEnt = null) + { + var mapManager = IoCManager.Resolve(); + var timing = IoCManager.Resolve(); + + // Calculate the force necessary to land a throw based on throw duration, mass and distance. + var distance = (targetLoc.ToMapPos(mapManager) - sourceLoc.ToMapPos(mapManager)).Length; + var throwDuration = ThrowController.DefaultThrowTime; + var mass = 1f; + if (thrownEnt.TryGetComponent(out PhysicsComponent physicsComponent)) + { + mass = physicsComponent.Mass; + } + + var velocityNecessary = distance / throwDuration; + var impulseNecessary = velocityNecessary * mass; + var forceNecessary = impulseNecessary * (1f / timing.TickRate); + + // Then clamp it to the max force allowed and call Throw(). + Throw(thrownEnt, Math.Min(forceNecessary, throwForceMax), targetLoc, sourceLoc, spread, throwSourceEnt); + } } } diff --git a/Content.Shared/Physics/ThrowController.cs b/Content.Shared/Physics/ThrowController.cs index 910afff257..69f237c7ad 100644 --- a/Content.Shared/Physics/ThrowController.cs +++ b/Content.Shared/Physics/ThrowController.cs @@ -11,7 +11,7 @@ namespace Content.Shared.Physics private float _throwTime; private SharedPhysicsComponent _component; - private const float DefaultThrowTime = 0.25f; + public const float DefaultThrowTime = 0.25f; public float ThrowTime {