diff --git a/Content.Shared/Cuffs/SharedCuffableSystem.cs b/Content.Shared/Cuffs/SharedCuffableSystem.cs index aad5f68952..5fa4d5989f 100644 --- a/Content.Shared/Cuffs/SharedCuffableSystem.cs +++ b/Content.Shared/Cuffs/SharedCuffableSystem.cs @@ -553,7 +553,25 @@ namespace Content.Shared.Cuffs if (!_doAfter.TryStartDoAfter(doAfterEventArgs)) return; - _popup.PopupEntity(Loc.GetString("cuffable-component-start-removing-cuffs-message"), user, Filter.Local(), false); + if (_net.IsServer) + { + _popup.PopupEntity(Loc.GetString("cuffable-component-start-uncuffing-observer", + ("user", Identity.Name(user, EntityManager)), ("target", Identity.Name(target, EntityManager))), + target, Filter.Pvs(target, entityManager: EntityManager) + .RemoveWhere(e => e.AttachedEntity == target || e.AttachedEntity == user), true); + + if (target == user) + { + _popup.PopupEntity(Loc.GetString("cuffable-component-start-uncuffing-self"), user, user); + } + else + { + _popup.PopupEntity(Loc.GetString("cuffable-component-start-uncuffing-target-message", + ("targetName", Identity.Name(target, EntityManager, user))), user, user); + _popup.PopupEntity(Loc.GetString("cuffable-component-start-uncuffing-by-other-message", + ("otherName", Identity.Name(user, EntityManager, target))), target, target); + } + } _audio.PlayPredicted(isOwner ? cuff.StartBreakoutSound : cuff.StartUncuffSound, target, user); } @@ -571,20 +589,22 @@ namespace Content.Shared.Cuffs cuffable.Container.Remove(cuffsToRemove); - if (cuff.BreakOnRemove) - { - QueueDel(cuffsToRemove); - var trash = Spawn(cuff.BrokenPrototype, Transform(cuffsToRemove).Coordinates); - _hands.PickupOrDrop(user, trash); - } - else - { - _hands.PickupOrDrop(user, cuffsToRemove); - } - // Only play popups on server because popups suck if (_net.IsServer) { + // Handles spawning broken cuffs on server to avoid client misprediction + if (cuff.BreakOnRemove) + { + QueueDel(cuffsToRemove); + var trash = Spawn(cuff.BrokenPrototype, Transform(cuffsToRemove).Coordinates); + _hands.PickupOrDrop(user, trash); + } + else + { + _hands.PickupOrDrop(user, cuffsToRemove); + } + + // Only play popups on server because popups suck if (cuffable.CuffedHandCount == 0) { _popup.PopupEntity(Loc.GetString("cuffable-component-remove-cuffs-success-message"), user, user); diff --git a/Resources/Locale/en-US/cuffs/components/cuffable-component.ftl b/Resources/Locale/en-US/cuffs/components/cuffable-component.ftl index 8efb76cda6..2ac1f98502 100644 --- a/Resources/Locale/en-US/cuffs/components/cuffable-component.ftl +++ b/Resources/Locale/en-US/cuffs/components/cuffable-component.ftl @@ -1,6 +1,11 @@ cuffable-component-cannot-interact-message = You can't do that! cuffable-component-cannot-remove-cuffs-too-far-message = You are too far away to remove the cuffs. -cuffable-component-start-removing-cuffs-message = You start removing the cuffs. + +cuffable-component-start-uncuffing-self = You start uncuffing yourself. +cuffable-component-start-uncuffing-observer = {$user} starts uncuffing {$target}! +cuffable-component-start-uncuffing-target-message = You start uncuffing {$targetName}. +cuffable-component-start-uncuffing-by-other-message = {$otherName} starts uncuffing you! + cuffable-component-remove-cuffs-success-message = You successfully remove the cuffs. cuffable-component-remove-cuffs-by-other-success-message = {$otherName} uncuffs your hands. cuffable-component-remove-cuffs-to-other-partial-success-message = You successfully remove the cuffs. {$cuffedHandCount} of {$otherName}'s hands remain cuffed.