]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Makes thieving gloves sneakier (#21398)
authorTemporalOroboros <TemporalOroboros@gmail.com>
Fri, 3 Nov 2023 02:10:58 +0000 (19:10 -0700)
committerGitHub <noreply@github.com>
Fri, 3 Nov 2023 02:10:58 +0000 (22:10 -0400)
* Hidden DoAfters

* Fix formatting warnings

* Hide progress bar and pickup animation

* Copy Hidden field in copy constructor

Content.Client/DoAfter/DoAfterOverlay.cs
Content.Client/DoAfter/DoAfterSystem.cs
Content.Server/Strip/StrippableSystem.cs
Content.Shared/DoAfter/DoAfterArgs.cs

index 1fc00a81b94b9ed6e95fc75f8e794cb27a09206e..2957dafdb7a83f0b434761ebbd9d33ac18154efe 100644 (file)
@@ -4,6 +4,7 @@ using Robust.Client.GameObjects;
 using Robust.Client.Graphics;
 using Robust.Shared.Enums;
 using Robust.Shared.Graphics;
+using Robust.Client.Player;
 using Robust.Shared.Prototypes;
 using Robust.Shared.Timing;
 using Robust.Shared.Utility;
@@ -14,6 +15,7 @@ public sealed class DoAfterOverlay : Overlay
 {
     private readonly IEntityManager _entManager;
     private readonly IGameTiming _timing;
+    private readonly IPlayerManager _player;
     private readonly SharedTransformSystem _transform;
     private readonly MetaDataSystem _meta;
 
@@ -31,13 +33,14 @@ public sealed class DoAfterOverlay : Overlay
 
     public override OverlaySpace Space => OverlaySpace.WorldSpaceBelowFOV;
 
-    public DoAfterOverlay(IEntityManager entManager, IPrototypeManager protoManager, IGameTiming timing)
+    public DoAfterOverlay(IEntityManager entManager, IPrototypeManager protoManager, IGameTiming timing, IPlayerManager player)
     {
         _entManager = entManager;
         _timing = timing;
+        _player = player;
         _transform = _entManager.EntitySysManager.GetEntitySystem<SharedTransformSystem>();
         _meta = _entManager.EntitySysManager.GetEntitySystem<MetaDataSystem>();
-        var sprite = new SpriteSpecifier.Rsi(new ("/Textures/Interface/Misc/progress_bar.rsi"), "icon");
+        var sprite = new SpriteSpecifier.Rsi(new("/Textures/Interface/Misc/progress_bar.rsi"), "icon");
         _barTexture = _entManager.EntitySysManager.GetEntitySystem<SpriteSystem>().Frame0(sprite);
 
         _shader = protoManager.Index<ShaderPrototype>("unshaded").Instance();
@@ -58,6 +61,7 @@ public sealed class DoAfterOverlay : Overlay
         var curTime = _timing.CurTime;
 
         var bounds = args.WorldAABB.Enlarged(5f);
+        var localEnt = _player.LocalSession?.AttachedEntity;
 
         var metaQuery = _entManager.GetEntityQuery<MetaDataComponent>();
         var enumerator = _entManager.AllEntityQueryEnumerator<ActiveDoAfterComponent, DoAfterComponent, SpriteComponent, TransformComponent>();
@@ -88,6 +92,17 @@ public sealed class DoAfterOverlay : Overlay
 
             foreach (var doAfter in comp.DoAfters.Values)
             {
+                // Hide some DoAfters from other players for stealthy actions (ie: thieving gloves)
+                var alpha = 1f;
+                if (doAfter.Args.Hidden)
+                {
+                    if (uid != localEnt)
+                        continue;
+
+                    // Hints to the local player that this do-after is not visible to other players.
+                    alpha = 0.5f;
+                }
+
                 // Use the sprite itself if we know its bounds. This means short or tall sprites don't get overlapped
                 // by the bar.
                 float yOffset = sprite.Bounds.Height / 2f + 0.05f;
@@ -108,15 +123,15 @@ public sealed class DoAfterOverlay : Overlay
                 {
                     var elapsed = doAfter.CancelledTime.Value - doAfter.StartTime;
                     elapsedRatio = (float) Math.Min(1, elapsed.TotalSeconds / doAfter.Args.Delay.TotalSeconds);
-                    var cancelElapsed  = (time - doAfter.CancelledTime.Value).TotalSeconds;
+                    var cancelElapsed = (time - doAfter.CancelledTime.Value).TotalSeconds;
                     var flash = Math.Floor(cancelElapsed / FlashTime) % 2 == 0;
-                    color = new Color(1f, 0f, 0f, flash ? 1f : 0f);
+                    color = new Color(1f, 0f, 0f, flash ? alpha : 0f);
                 }
                 else
                 {
                     var elapsed = time - doAfter.StartTime;
                     elapsedRatio = (float) Math.Min(1, elapsed.TotalSeconds / doAfter.Args.Delay.TotalSeconds);
-                    color = GetProgressColor(elapsedRatio);
+                    color = GetProgressColor(elapsedRatio, alpha);
                 }
 
                 var xProgress = (EndX - StartX) * elapsedRatio + StartX;
@@ -131,14 +146,14 @@ public sealed class DoAfterOverlay : Overlay
         handle.SetTransform(Matrix3.Identity);
     }
 
-    public static Color GetProgressColor(float progress)
+    public static Color GetProgressColor(float progress, float alpha = 1f)
     {
         if (progress >= 1.0f)
         {
-            return new Color(0f, 1f, 0f);
+            return new Color(0f, 1f, 0f, alpha);
         }
         // lerp
         var hue = (5f / 18f) * progress;
-        return Color.FromHsv((hue, 1f, 0.75f, 1f));
+        return Color.FromHsv((hue, 1f, 0.75f, alpha));
     }
 }
index 8c2d8344d384498a8c948183b5a1f4a92c0e2b2b..38e1a714aca9c8a5af1260aa5e23403c420a52b6 100644 (file)
@@ -21,7 +21,7 @@ public sealed class DoAfterSystem : SharedDoAfterSystem
     public override void Initialize()
     {
         base.Initialize();
-        _overlay.AddOverlay(new DoAfterOverlay(EntityManager, _prototype, GameTiming));
+        _overlay.AddOverlay(new DoAfterOverlay(EntityManager, _prototype, GameTiming, _player));
     }
 
     public override void Shutdown()
index 75374e7de502c2d692ae0651b69912cacdaecb21..b354f9071adadc39a3b5aafe9665f3b532c01e50 100644 (file)
@@ -221,6 +221,7 @@ namespace Content.Server.Strip
             var doAfterArgs = new DoAfterArgs(EntityManager, user, ev.Time, new AwaitedDoAfterEvent(), null, target: target, used: held)
             {
                 ExtraCheck = Check,
+                Hidden = ev.Stealth,
                 AttemptFrequency = AttemptFrequency.EveryTick,
                 BreakOnDamage = true,
                 BreakOnTargetMove = true,
@@ -294,6 +295,7 @@ namespace Content.Server.Strip
             var doAfterArgs = new DoAfterArgs(EntityManager, user, ev.Time, new AwaitedDoAfterEvent(), null, target: target, used: held)
             {
                 ExtraCheck = Check,
+                Hidden = ev.Stealth,
                 AttemptFrequency = AttemptFrequency.EveryTick,
                 BreakOnDamage = true,
                 BreakOnTargetMove = true,
@@ -308,7 +310,7 @@ namespace Content.Server.Strip
             if (result != DoAfterStatus.Finished) return;
 
             _handsSystem.TryDrop(user, checkActionBlocker: false, handsComp: userHands);
-            _handsSystem.TryPickup(target, held, handName, checkActionBlocker: false, animateUser: true, handsComp: hands);
+            _handsSystem.TryPickup(target, held, handName, checkActionBlocker: false, animateUser: !ev.Stealth, animate: !ev.Stealth, handsComp: hands);
             _adminLogger.Add(LogType.Stripping, LogImpact.Medium, $"{ToPrettyString(user):user} has placed the item {ToPrettyString(held):item} in {ToPrettyString(target):target}'s hands");
             // hand update will trigger strippable update
         }
@@ -354,6 +356,7 @@ namespace Content.Server.Strip
             var doAfterArgs = new DoAfterArgs(EntityManager, user, ev.Time, new AwaitedDoAfterEvent(), null, target: target, used: item)
             {
                 ExtraCheck = Check,
+                Hidden = ev.Stealth,
                 AttemptFrequency = AttemptFrequency.EveryTick,
                 BreakOnDamage = true,
                 BreakOnTargetMove = true,
@@ -389,7 +392,7 @@ namespace Content.Server.Strip
             // Raise a dropped event, so that things like gas tank internals properly deactivate when stripping
             RaiseLocalEvent(item, new DroppedEvent(user), true);
 
-            _handsSystem.PickupOrDrop(user, item);
+            _handsSystem.PickupOrDrop(user, item, animateUser: !ev.Stealth, animate: !ev.Stealth);
             _adminLogger.Add(LogType.Stripping, LogImpact.Medium, $"{ToPrettyString(user):user} has stripped the item {ToPrettyString(item):item} from {ToPrettyString(target):target}");
 
         }
@@ -430,6 +433,7 @@ namespace Content.Server.Strip
             var doAfterArgs = new DoAfterArgs(EntityManager, user, ev.Time, new AwaitedDoAfterEvent(), null, target: target, used: item)
             {
                 ExtraCheck = Check,
+                Hidden = ev.Stealth,
                 AttemptFrequency = AttemptFrequency.EveryTick,
                 BreakOnDamage = true,
                 BreakOnTargetMove = true,
@@ -439,7 +443,7 @@ namespace Content.Server.Strip
                 DuplicateCondition = DuplicateConditions.SameTool
             };
 
-            if (Check() && _handsSystem.TryGetHand(target, handName, out var handSlot, hands) && handSlot.HeldEntity != null)
+            if (!ev.Stealth && Check() && _handsSystem.TryGetHand(target, handName, out var handSlot, hands) && handSlot.HeldEntity != null)
             {
                 _popup.PopupEntity(
                     Loc.GetString("strippable-component-alert-owner",
@@ -456,7 +460,7 @@ namespace Content.Server.Strip
                 return;
 
             _handsSystem.TryDrop(target, item, checkActionBlocker: false, handsComp: hands);
-            _handsSystem.PickupOrDrop(user, item, handsComp: userHands);
+            _handsSystem.PickupOrDrop(user, item, animateUser: !ev.Stealth, animate: !ev.Stealth, handsComp: userHands);
             // hand update will trigger strippable update
             _adminLogger.Add(LogType.Stripping, LogImpact.Medium,
                 $"{ToPrettyString(user):user} has stripped the item {ToPrettyString(item):item} from {ToPrettyString(target):target}");
index c5cbc1f30286a05187b183b885635a80785d88de..d2729ad3c64472e168a1d875fca83e96f7af307b 100644 (file)
@@ -40,6 +40,12 @@ public sealed partial class DoAfterArgs
 
     public NetEntity? NetUsed;
 
+    /// <summary>
+    /// Whether the progress bar for this DoAfter should be hidden from other players.
+    /// </summary>
+    [DataField]
+    public bool Hidden;
+
     #region Event options
     /// <summary>
     ///     The event that will get raised when the DoAfter has finished. If null, this will simply raise a <see cref="SimpleDoAfterEvent"/>
@@ -239,6 +245,7 @@ public sealed partial class DoAfterArgs
         Delay = other.Delay;
         Target = other.Target;
         Used = other.Used;
+        Hidden = other.Hidden;
         EventTarget = other.EventTarget;
         Broadcast = other.Broadcast;
         NeedHand = other.NeedHand;