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
{