diff --git a/Content.Server/Cuffs/CuffableSystem.cs b/Content.Server/Cuffs/CuffableSystem.cs index fae5113d20..07bbece33e 100644 --- a/Content.Server/Cuffs/CuffableSystem.cs +++ b/Content.Server/Cuffs/CuffableSystem.cs @@ -1,3 +1,4 @@ +using System.Linq; using Content.Server.Cuffs.Components; using Content.Server.Hands.Components; using Content.Shared.ActionBlocker; @@ -5,6 +6,7 @@ using Content.Shared.Cuffs; using Content.Shared.Hands; using Content.Shared.Popups; using Content.Shared.Verbs; +using Content.Shared.Weapons.Melee.Events; using JetBrains.Annotations; using Robust.Shared.Player; using Content.Shared.Interaction; @@ -32,6 +34,7 @@ namespace Content.Server.Cuffs SubscribeLocalEvent(OnUncuffAttempt); SubscribeLocalEvent>(AddUncuffVerb); SubscribeLocalEvent(OnCuffAfterInteract); + SubscribeLocalEvent(OnCuffMeleeHit); SubscribeLocalEvent(OnCuffsRemoved); } @@ -65,57 +68,68 @@ namespace Content.Server.Cuffs private void OnCuffAfterInteract(EntityUid uid, HandcuffComponent component, AfterInteractEvent args) { - if (component.Cuffing) + if (args.Target is not {Valid: true} target) return; - - if (args.Target is not {Valid: true} target || - !EntityManager.TryGetComponent(args.Target.Value, out var cuffed)) - { - return; - } - - // TODO these messages really need third-party variants. I.e., "{$user} starts cuffing {$target}!" - - if (component.Broken) - { - _popup.PopupEntity(Loc.GetString("handcuff-component-cuffs-broken-error"), args.User, Filter.Entities(args.User)); - return; - } - - if (!EntityManager.TryGetComponent(target, out var hands)) - { - _popup.PopupEntity(Loc.GetString("handcuff-component-target-has-no-hands-error",("targetName", args.Target)), args.User, Filter.Entities(args.User)); - return; - } - - if (cuffed.CuffedHandCount >= hands.Count) - { - _popup.PopupEntity(Loc.GetString("handcuff-component-target-has-no-free-hands-error",("targetName", args.Target)), args.User, Filter.Entities(args.User)); - return; - } - + if (!args.CanReach) { _popup.PopupEntity(Loc.GetString("handcuff-component-too-far-away-error"), args.User, Filter.Entities(args.User)); return; } - if (args.Target == args.User) + TryCuffing(uid, args.User, args.Target.Value, component); + args.Handled = true; + } + + private void TryCuffing(EntityUid handcuff, EntityUid user, EntityUid target, HandcuffComponent component) + { + if (component.Cuffing || !EntityManager.TryGetComponent(target, out var cuffed)) + return; + + if (component.Broken) { - _popup.PopupEntity(Loc.GetString("handcuff-component-target-self"), args.User, Filter.Entities(args.User)); + _popup.PopupEntity(Loc.GetString("handcuff-component-cuffs-broken-error"), user, Filter.Entities(user)); + return; + } + + if (!EntityManager.TryGetComponent(target, out var hands)) + { + _popup.PopupEntity(Loc.GetString("handcuff-component-target-has-no-hands-error",("targetName", target)), user, Filter.Entities(user)); + return; + } + + if (cuffed.CuffedHandCount >= hands.Count) + { + _popup.PopupEntity(Loc.GetString("handcuff-component-target-has-no-free-hands-error",("targetName", target)), user, Filter.Entities(user)); + return; + } + + // TODO these messages really need third-party variants. I.e., "{$user} starts cuffing {$target}!" + if (target == user) + { + _popup.PopupEntity(Loc.GetString("handcuff-component-target-self"), user, Filter.Entities(user)); } else { - _popup.PopupEntity(Loc.GetString("handcuff-component-start-cuffing-target-message",("targetName", args.Target)), args.User, Filter.Entities(args.User)); - _popup.PopupEntity(Loc.GetString("handcuff-component-start-cuffing-by-other-message",("otherName", args.User)), target, Filter.Entities(args.Target.Value)); + _popup.PopupEntity(Loc.GetString("handcuff-component-start-cuffing-target-message",("targetName", target)), user, Filter.Entities(user)); + _popup.PopupEntity(Loc.GetString("handcuff-component-start-cuffing-by-other-message",("otherName", user)), target, Filter.Entities(target)); } - _audio.PlayPvs(component.StartCuffSound, uid); + _audio.PlayPvs(component.StartCuffSound, handcuff); - component.TryUpdateCuff(args.User, target, cuffed); + component.TryUpdateCuff(user, target, cuffed); + } + + private void OnCuffMeleeHit(EntityUid uid, HandcuffComponent component, MeleeHitEvent args) + { + if (!args.HitEntities.Any()) + return; + + TryCuffing(uid, args.User, args.HitEntities.First(), component); args.Handled = true; } + private void OnUncuffAttempt(UncuffAttemptEvent args) { if (args.Cancelled) diff --git a/Resources/Prototypes/Entities/Objects/Misc/handcuffs.yml b/Resources/Prototypes/Entities/Objects/Misc/handcuffs.yml index 442e6fe0da..36c1c83eaa 100644 --- a/Resources/Prototypes/Entities/Objects/Misc/handcuffs.yml +++ b/Resources/Prototypes/Entities/Objects/Misc/handcuffs.yml @@ -15,6 +15,11 @@ - type: Tag tags: - Handcuffs + - type: MeleeWeapon + animation: WeaponArcDisarm + damage: + types: + Blunt: 0 - type: entity name: makeshift handcuffs