diff --git a/Content.Server/Hands/Systems/HandsSystem.cs b/Content.Server/Hands/Systems/HandsSystem.cs index ae5a99bf28..0b21800653 100644 --- a/Content.Server/Hands/Systems/HandsSystem.cs +++ b/Content.Server/Hands/Systems/HandsSystem.cs @@ -17,12 +17,14 @@ using Robust.Shared.GameStates; using Robust.Shared.Input.Binding; using Robust.Shared.Map; using Robust.Shared.Player; +using Robust.Shared.Timing; using Robust.Shared.Utility; namespace Content.Server.Hands.Systems { public sealed class HandsSystem : SharedHandsSystem { + [Dependency] private readonly IGameTiming _timing = default!; [Dependency] private readonly StackSystem _stackSystem = default!; [Dependency] private readonly HandVirtualItemSystem _virtualItemSystem = default!; [Dependency] private readonly ActionBlockerSystem _actionBlockerSystem = default!; @@ -43,6 +45,7 @@ namespace Content.Server.Hands.Systems SubscribeLocalEvent(HandleBodyPartRemoved); SubscribeLocalEvent(GetComponentState); + SubscribeLocalEvent(OnUnpaused); SubscribeLocalEvent(OnExploded); @@ -63,6 +66,11 @@ namespace Content.Server.Hands.Systems args.State = new HandsComponentState(hands); } + private void OnUnpaused(Entity ent, ref EntityUnpausedEvent args) + { + ent.Comp.NextThrowTime += args.PausedTime; + } + private void OnExploded(Entity ent, ref BeforeExplodeEvent args) { foreach (var hand in ent.Comp.Hands.Values) @@ -172,6 +180,10 @@ namespace Content.Server.Hands.Systems !_actionBlockerSystem.CanThrow(player, throwEnt)) return false; + if (_timing.CurTime < hands.NextThrowTime) + return false; + hands.NextThrowTime = _timing.CurTime + hands.ThrowCooldown; + if (EntityManager.TryGetComponent(throwEnt, out StackComponent? stack) && stack.Count > 1 && stack.ThrowIndividually) { var splitStack = _stackSystem.Split(throwEnt, 1, EntityManager.GetComponent(player).Coordinates, stack); @@ -201,7 +213,7 @@ namespace Content.Server.Hands.Systems return true; // This can grief the above event so we raise it afterwards - if (!TryDrop(player, throwEnt, handsComp: hands)) + if (IsHolding(player, throwEnt, out _, hands) && !TryDrop(player, throwEnt, handsComp: hands)) return false; _throwingSystem.TryThrow(ev.ItemUid, ev.Direction, ev.ThrowStrength, ev.PlayerUid); diff --git a/Content.Shared/Hands/Components/HandsComponent.cs b/Content.Shared/Hands/Components/HandsComponent.cs index 0bece1d141..ef3b2a6a0e 100644 --- a/Content.Shared/Hands/Components/HandsComponent.cs +++ b/Content.Shared/Hands/Components/HandsComponent.cs @@ -57,6 +57,18 @@ public sealed partial class HandsComponent : Component /// Used by the client. /// public readonly Dictionary> RevealedLayers = new(); + + /// + /// The time at which throws will be allowed again. + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public TimeSpan NextThrowTime; + + /// + /// The minimum time inbetween throws. + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public TimeSpan ThrowCooldown = TimeSpan.FromSeconds(0.5f); } [Serializable, NetSerializable]