From 2e90bc7b6dca98a336331446de9a116ea3d07bec Mon Sep 17 00:00:00 2001 From: ScarKy0 <106310278+ScarKy0@users.noreply.github.com> Date: Sun, 22 Jun 2025 02:24:12 +0200 Subject: [PATCH] Retractable items get removed by handcuffs (#38441) * init * oops * happens * review * fix --- Content.Shared/Cuffs/SharedCuffableSystem.cs | 29 ++++++++--- .../EntitySystems/SharedHandsSystem.Relay.cs | 2 + .../RetractableItemActionSystem.cs | 49 ++++++++++++++++--- 3 files changed, 65 insertions(+), 15 deletions(-) diff --git a/Content.Shared/Cuffs/SharedCuffableSystem.cs b/Content.Shared/Cuffs/SharedCuffableSystem.cs index 8c4a871177..c55bbdb152 100644 --- a/Content.Shared/Cuffs/SharedCuffableSystem.cs +++ b/Content.Shared/Cuffs/SharedCuffableSystem.cs @@ -15,6 +15,7 @@ using Content.Shared.IdentityManagement; using Content.Shared.Interaction; using Content.Shared.Interaction.Components; using Content.Shared.Interaction.Events; +using Content.Shared.Inventory; using Content.Shared.Inventory.Events; using Content.Shared.Inventory.VirtualItem; using Content.Shared.Item; @@ -472,6 +473,9 @@ namespace Content.Shared.Cuffs if (TryComp(target, out var hands) && hands.Count <= component.CuffedHandCount) return false; + var ev = new TargetHandcuffedEvent(); + RaiseLocalEvent(target, ref ev); + // Success! _hands.TryDrop(user, handcuff); @@ -807,15 +811,24 @@ namespace Content.Shared.Cuffs { return component.Container.ContainedEntities; } + } - [Serializable, NetSerializable] - private sealed partial class UnCuffDoAfterEvent : SimpleDoAfterEvent - { - } + [Serializable, NetSerializable] + public sealed partial class UnCuffDoAfterEvent : SimpleDoAfterEvent; - [Serializable, NetSerializable] - private sealed partial class AddCuffDoAfterEvent : SimpleDoAfterEvent - { - } + [Serializable, NetSerializable] + public sealed partial class AddCuffDoAfterEvent : SimpleDoAfterEvent; + + /// + /// Raised on the target when they get handcuffed. + /// Relayed to their held items. + /// + [ByRefEvent] + public record struct TargetHandcuffedEvent : IInventoryRelayEvent + { + /// + /// All slots to relay to + /// + public SlotFlags TargetSlots { get; set; } } } diff --git a/Content.Shared/Hands/EntitySystems/SharedHandsSystem.Relay.cs b/Content.Shared/Hands/EntitySystems/SharedHandsSystem.Relay.cs index 67db193894..e6f21abf1b 100644 --- a/Content.Shared/Hands/EntitySystems/SharedHandsSystem.Relay.cs +++ b/Content.Shared/Hands/EntitySystems/SharedHandsSystem.Relay.cs @@ -1,5 +1,6 @@ using Content.Shared.Atmos; using Content.Shared.Camera; +using Content.Shared.Cuffs; using Content.Shared.Hands.Components; using Content.Shared.Movement.Systems; using Content.Shared.Projectiles; @@ -22,6 +23,7 @@ public abstract partial class SharedHandsSystem SubscribeLocalEvent(RefRelayEvent); SubscribeLocalEvent(RefRelayEvent); SubscribeLocalEvent(RefRelayEvent); + SubscribeLocalEvent(RefRelayEvent); } private void RelayEvent(Entity entity, ref T args) where T : EntityEventArgs diff --git a/Content.Shared/RetractableItemAction/RetractableItemActionSystem.cs b/Content.Shared/RetractableItemAction/RetractableItemActionSystem.cs index b99b653cf0..c24da14c68 100644 --- a/Content.Shared/RetractableItemAction/RetractableItemActionSystem.cs +++ b/Content.Shared/RetractableItemAction/RetractableItemActionSystem.cs @@ -1,6 +1,10 @@ using Content.Shared.Actions; +using Content.Shared.Cuffs; +using Content.Shared.Hands; +using Content.Shared.Hands.Components; using Content.Shared.Hands.EntitySystems; using Content.Shared.Interaction.Components; +using Content.Shared.Inventory; using Content.Shared.Popups; using Robust.Shared.Audio.Systems; using Robust.Shared.Containers; @@ -26,6 +30,7 @@ public sealed class RetractableItemActionSystem : EntitySystem SubscribeLocalEvent(OnRetractableItemAction); SubscribeLocalEvent(OnActionSummonedShutdown); + Subs.SubscribeWithRelay>(OnItemHandcuffed, inventory: false); } private void OnActionInit(Entity ent, ref MapInitEvent args) @@ -58,16 +63,11 @@ public sealed class RetractableItemActionSystem : EntitySystem if (_hands.IsHolding(args.Performer, ent.Comp.ActionItemUid)) { - RemComp(ent.Comp.ActionItemUid.Value); - var container = _containers.GetContainer(ent, RetractableItemActionComponent.ContainerId); - _containers.Insert(ent.Comp.ActionItemUid.Value, container); - _audio.PlayPredicted(ent.Comp.RetractSounds, action.Comp.AttachedEntity.Value, action.Comp.AttachedEntity.Value); + RetractRetractableItem(args.Performer, ent.Comp.ActionItemUid.Value, ent.Owner); } else { - _hands.TryForcePickup(args.Performer, ent.Comp.ActionItemUid.Value, userHand, checkActionBlocker: false); - _audio.PlayPredicted(ent.Comp.SummonSounds, action.Comp.AttachedEntity.Value, action.Comp.AttachedEntity.Value); - EnsureComp(ent.Comp.ActionItemUid.Value); + SummonRetractableItem(args.Performer, ent.Comp.ActionItemUid.Value, userHand, ent.Owner); } args.Handled = true; @@ -85,6 +85,20 @@ public sealed class RetractableItemActionSystem : EntitySystem PopulateActionItem(action.Owner); } + private void OnItemHandcuffed(Entity ent, ref HeldRelayedEvent args) + { + if (_actions.GetAction(ent.Comp.SummoningAction) is not { } action) + return; + + if (action.Comp.AttachedEntity == null) + return; + + if (_hands.GetActiveHand(action.Comp.AttachedEntity.Value) is not { } userHand) + return; + + RetractRetractableItem(action.Comp.AttachedEntity.Value, ent, action.Owner); + } + private void PopulateActionItem(Entity ent) { if (!Resolve(ent.Owner, ref ent.Comp, false) || TerminatingOrDeleted(ent)) @@ -102,4 +116,25 @@ public sealed class RetractableItemActionSystem : EntitySystem Dirty(ent); } + + private void RetractRetractableItem(EntityUid holder, EntityUid item, Entity action) + { + if (!Resolve(action, ref action.Comp, false)) + return; + + RemComp(item); + var container = _containers.GetContainer(action, RetractableItemActionComponent.ContainerId); + _containers.Insert(item, container); + _audio.PlayPredicted(action.Comp.RetractSounds, holder, holder); + } + + private void SummonRetractableItem(EntityUid holder, EntityUid item, Hand hand, Entity action) + { + if (!Resolve(action, ref action.Comp, false)) + return; + + _hands.TryForcePickup(holder, item, hand, checkActionBlocker: false); + _audio.PlayPredicted(action.Comp.SummonSounds, holder, holder); + EnsureComp(item); + } }