Minor cleanup of cuffablesystem (#26434)

* Fix cuffs breaking after they stop being pulled

* Do proper interaction check for UncuffAttempt

* Minor cleanup

Take as much out as possible from _net.IsServer() if blocks.
Misc cleanup
This commit is contained in:
nikthechampiongr
2024-03-26 21:15:08 +02:00
committed by GitHub
parent bf7fb53ae5
commit 4630e94c66
2 changed files with 61 additions and 54 deletions

View File

@@ -52,6 +52,14 @@ public sealed partial class HandcuffComponent : Component
[DataField] [DataField]
public bool Removing; public bool Removing;
/// <summary>
/// Whether the cuffs are currently being used to cuff someone.
/// We need the extra information for when the virtual item is deleted because that can happen when you simply stop
/// pulling them on the ground.
/// </summary>
[DataField]
public bool Used;
/// <summary> /// <summary>
/// The path of the RSI file used for the player cuffed overlay. /// The path of the RSI file used for the player cuffed overlay.
/// </summary> /// </summary>
@@ -87,7 +95,7 @@ public sealed partial class HandcuffComponent : Component
} }
/// <summary> /// <summary>
/// Event fired on the User when the User attempts to cuff the Target. /// Event fired on the User when the User attempts to uncuff the Target.
/// Should generate popups on the User. /// Should generate popups on the User.
/// </summary> /// </summary>
[ByRefEvent] [ByRefEvent]

View File

@@ -3,12 +3,10 @@ using Content.Shared.ActionBlocker;
using Content.Shared.Administration.Components; using Content.Shared.Administration.Components;
using Content.Shared.Administration.Logs; using Content.Shared.Administration.Logs;
using Content.Shared.Alert; using Content.Shared.Alert;
using Content.Shared.Atmos.Piping.Unary.Components;
using Content.Shared.Buckle.Components; using Content.Shared.Buckle.Components;
using Content.Shared.Cuffs.Components; using Content.Shared.Cuffs.Components;
using Content.Shared.Database; using Content.Shared.Database;
using Content.Shared.DoAfter; using Content.Shared.DoAfter;
using Content.Shared.Effects;
using Content.Shared.Hands; using Content.Shared.Hands;
using Content.Shared.Hands.Components; using Content.Shared.Hands.Components;
using Content.Shared.Hands.EntitySystems; using Content.Shared.Hands.EntitySystems;
@@ -19,7 +17,6 @@ using Content.Shared.Interaction.Events;
using Content.Shared.Inventory.Events; using Content.Shared.Inventory.Events;
using Content.Shared.Inventory.VirtualItem; using Content.Shared.Inventory.VirtualItem;
using Content.Shared.Item; using Content.Shared.Item;
using Content.Shared.Mobs.Systems;
using Content.Shared.Movement.Events; using Content.Shared.Movement.Events;
using Content.Shared.Movement.Pulling.Events; using Content.Shared.Movement.Pulling.Events;
using Content.Shared.Popups; using Content.Shared.Popups;
@@ -29,12 +26,12 @@ using Content.Shared.Stunnable;
using Content.Shared.Timing; using Content.Shared.Timing;
using Content.Shared.Verbs; using Content.Shared.Verbs;
using Content.Shared.Weapons.Melee.Events; using Content.Shared.Weapons.Melee.Events;
using Robust.Shared.Audio;
using Robust.Shared.Audio.Systems; using Robust.Shared.Audio.Systems;
using Robust.Shared.Containers; using Robust.Shared.Containers;
using Robust.Shared.Network; using Robust.Shared.Network;
using Robust.Shared.Player; using Robust.Shared.Player;
using Robust.Shared.Serialization; using Robust.Shared.Serialization;
using Robust.Shared.Utility;
using PullableComponent = Content.Shared.Movement.Pulling.Components.PullableComponent; using PullableComponent = Content.Shared.Movement.Pulling.Components.PullableComponent;
namespace Content.Shared.Cuffs namespace Content.Shared.Cuffs
@@ -47,8 +44,6 @@ namespace Content.Shared.Cuffs
[Dependency] private readonly ISharedAdminLogManager _adminLog = default!; [Dependency] private readonly ISharedAdminLogManager _adminLog = default!;
[Dependency] private readonly ActionBlockerSystem _actionBlocker = default!; [Dependency] private readonly ActionBlockerSystem _actionBlocker = default!;
[Dependency] private readonly AlertsSystem _alerts = default!; [Dependency] private readonly AlertsSystem _alerts = default!;
[Dependency] private readonly SharedColorFlashEffectSystem _color = default!;
[Dependency] private readonly MobStateSystem _mobState = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!; [Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly SharedContainerSystem _container = default!; [Dependency] private readonly SharedContainerSystem _container = default!;
[Dependency] private readonly SharedDoAfterSystem _doAfter = default!; [Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
@@ -95,9 +90,8 @@ namespace Content.Shared.Cuffs
private void OnUncuffAttempt(ref UncuffAttemptEvent args) private void OnUncuffAttempt(ref UncuffAttemptEvent args)
{ {
if (args.Cancelled) if (args.Cancelled)
{
return; return;
}
if (!Exists(args.User) || Deleted(args.User)) if (!Exists(args.User) || Deleted(args.User))
{ {
// Should this even be possible? // Should this even be possible?
@@ -109,23 +103,29 @@ namespace Content.Shared.Cuffs
// This is because the CanInteract blocking of the cuffs prevents self-uncuff. // This is because the CanInteract blocking of the cuffs prevents self-uncuff.
if (args.User == args.Target) if (args.User == args.Target)
{ {
// This UncuffAttemptEvent check should probably be In MobStateSystem, not here? if (!TryComp<CuffableComponent>(args.User, out var cuffable))
if (_mobState.IsIncapacitated(args.User))
{ {
DebugTools.Assert($"{args.User} tried to uncuff themselves but they are not cuffable.");
return;
}
// We temporarily allow interactions so the cuffable system does not block itself.
// It's assumed that this will always be false.
// Otherwise they would not be trying to uncuff themselves.
cuffable.CanStillInteract = true;
Dirty(args.User, cuffable);
if (!_actionBlocker.CanInteract(args.User, args.User))
args.Cancelled = true; args.Cancelled = true;
}
else cuffable.CanStillInteract = false;
{ Dirty(args.User, cuffable);
// TODO Find a way for cuffable to check ActionBlockerSystem.CanInteract() without blocking itself
}
} }
else else
{ {
// Check if the user can interact. // Check if the user can interact.
if (!_actionBlocker.CanInteract(args.User, args.Target)) if (!_actionBlocker.CanInteract(args.User, args.Target))
{
args.Cancelled = true; args.Cancelled = true;
}
} }
if (args.Cancelled) if (args.Cancelled)
@@ -310,6 +310,7 @@ namespace Content.Shared.Cuffs
if (!args.Cancelled && TryAddNewCuffs(target, user, uid, cuffable)) if (!args.Cancelled && TryAddNewCuffs(target, user, uid, cuffable))
{ {
component.Used = true;
_audio.PlayPredicted(component.EndCuffSound, uid, user); _audio.PlayPredicted(component.EndCuffSound, uid, user);
_popup.PopupEntity(Loc.GetString("handcuff-component-cuff-observer-success-message", _popup.PopupEntity(Loc.GetString("handcuff-component-cuff-observer-success-message",
@@ -613,7 +614,7 @@ namespace Content.Shared.Cuffs
if (!Resolve(target, ref cuffable) || !Resolve(cuffsToRemove, ref cuff)) if (!Resolve(target, ref cuffable) || !Resolve(cuffsToRemove, ref cuff))
return; return;
if (cuff.Removing || TerminatingOrDeleted(cuffsToRemove) || TerminatingOrDeleted(target)) if (!cuff.Used || cuff.Removing || TerminatingOrDeleted(cuffsToRemove) || TerminatingOrDeleted(target))
return; return;
if (user != null) if (user != null)
@@ -625,10 +626,9 @@ namespace Content.Shared.Cuffs
} }
cuff.Removing = true; cuff.Removing = true;
cuff.Used = false;
_audio.PlayPredicted(cuff.EndUncuffSound, target, user); _audio.PlayPredicted(cuff.EndUncuffSound, target, user);
var isOwner = user == target;
_container.Remove(cuffsToRemove, cuffable.Container); _container.Remove(cuffsToRemove, cuffable.Container);
if (_net.IsServer) if (_net.IsServer)
@@ -644,43 +644,42 @@ namespace Content.Shared.Cuffs
{ {
_hands.PickupOrDrop(user, cuffsToRemove); _hands.PickupOrDrop(user, cuffsToRemove);
} }
}
// Only play popups on server because popups suck if (cuffable.CuffedHandCount == 0)
if (cuffable.CuffedHandCount == 0) {
if (user != null)
_popup.PopupPredicted(Loc.GetString("cuffable-component-remove-cuffs-success-message"), user.Value, user.Value);
if (target != user && user != null)
{ {
if (user != null) _popup.PopupPredicted(Loc.GetString("cuffable-component-remove-cuffs-by-other-success-message",
_popup.PopupEntity(Loc.GetString("cuffable-component-remove-cuffs-success-message"), user.Value, user.Value); ("otherName", Identity.Name(user.Value, EntityManager, user))), target, target);
_adminLog.Add(LogType.Action, LogImpact.Medium,
if (target != user && user != null) $"{ToPrettyString(user):player} has successfully uncuffed {ToPrettyString(target):player}");
{
_popup.PopupEntity(Loc.GetString("cuffable-component-remove-cuffs-by-other-success-message",
("otherName", Identity.Name(user.Value, EntityManager, user))), target, target);
_adminLog.Add(LogType.Action, LogImpact.Medium,
$"{ToPrettyString(user):player} has successfully uncuffed {ToPrettyString(target):player}");
}
else
{
_adminLog.Add(LogType.Action, LogImpact.Medium,
$"{ToPrettyString(user):player} has successfully uncuffed themselves");
}
} }
else if (user != null) else
{ {
if (user != target) _adminLog.Add(LogType.Action, LogImpact.Medium,
{ $"{ToPrettyString(user):player} has successfully uncuffed themselves");
_popup.PopupEntity(Loc.GetString("cuffable-component-remove-cuffs-partial-success-message", }
("cuffedHandCount", cuffable.CuffedHandCount), }
("otherName", Identity.Name(user.Value, EntityManager, user.Value))), user.Value, user.Value); else if (user != null)
_popup.PopupEntity(Loc.GetString( {
"cuffable-component-remove-cuffs-by-other-partial-success-message", if (user != target)
("otherName", Identity.Name(user.Value, EntityManager, user.Value)), {
("cuffedHandCount", cuffable.CuffedHandCount)), target, target); _popup.PopupPredicted(Loc.GetString("cuffable-component-remove-cuffs-partial-success-message",
} ("cuffedHandCount", cuffable.CuffedHandCount),
else ("otherName", Identity.Name(user.Value, EntityManager, user.Value))), user.Value, user.Value);
{ _popup.PopupPredicted(Loc.GetString(
_popup.PopupEntity(Loc.GetString("cuffable-component-remove-cuffs-partial-success-message", "cuffable-component-remove-cuffs-by-other-partial-success-message",
("cuffedHandCount", cuffable.CuffedHandCount)), user.Value, user.Value); ("otherName", Identity.Name(user.Value, EntityManager, user.Value)),
} ("cuffedHandCount", cuffable.CuffedHandCount)), target, target);
}
else
{
_popup.PopupPredicted(Loc.GetString("cuffable-component-remove-cuffs-partial-success-message",
("cuffedHandCount", cuffable.CuffedHandCount)), user.Value, user.Value);
} }
} }
cuff.Removing = false; cuff.Removing = false;