]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
disallow unanchoring or opening panels on locked emitters/APEs (#26600)
authorNemanja <98561806+EmoGarbage404@users.noreply.github.com>
Sun, 31 Mar 2024 06:34:17 +0000 (02:34 -0400)
committerGitHub <noreply@github.com>
Sun, 31 Mar 2024 06:34:17 +0000 (17:34 +1100)
* disallow unanchoring or opening panels on locked emitters/APEs

* no locking open panels

* oops

* needback feedback

* Update Content.Shared/Lock/LockSystem.cs

* Update Content.Shared/Lock/LockSystem.cs

* Update Content.Shared/Lock/LockSystem.cs

* sanity

---------

Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com>
Co-authored-by: metalgearsloth <comedian_vs_clown@hotmail.com>
12 files changed:
Content.Client/Popups/PopupSystem.cs
Content.Server/Popups/PopupSystem.cs
Content.Shared/Lock/LockSystem.cs
Content.Shared/Lock/LockedAnchorableComponent.cs [new file with mode: 0644]
Content.Shared/Lock/LockedWiresPanelComponent.cs [new file with mode: 0644]
Content.Shared/Popups/SharedPopupSystem.cs
Content.Shared/Wires/SharedWiresSystem.cs
Content.Shared/Wires/WiresPanelComponent.cs
Resources/Locale/en-US/lock/lock-component.ftl
Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml
Resources/Prototypes/Entities/Structures/Machines/anomaly_equipment.yml
Resources/Prototypes/Entities/Structures/Power/Generation/Singularity/emitter.yml

index 479fb02906c46bf08297737b66fa86e8124eb00e..fcc8bfc420a144c19edb1409ecf1f22aff0e638e 100644 (file)
@@ -163,10 +163,13 @@ namespace Content.Client.Popups
             PopupEntity(message, uid, type);
         }
 
-        public override void PopupClient(string? message, EntityUid uid, EntityUid recipient, PopupType type = PopupType.Small)
+        public override void PopupClient(string? message, EntityUid uid, EntityUid? recipient, PopupType type = PopupType.Small)
         {
+            if (recipient == null)
+                return;
+
             if (_timing.IsFirstTimePredicted)
-                PopupEntity(message, uid, recipient, type);
+                PopupEntity(message, uid, recipient.Value, type);
         }
 
         public override void PopupEntity(string? message, EntityUid uid, PopupType type = PopupType.Small)
index c5eb3819b54a0ef06ccec021a81900d352f144f4..237ca33a4db4c16484bab6024930098875571ff2 100644 (file)
@@ -88,7 +88,7 @@ namespace Content.Server.Popups
                 RaiseNetworkEvent(new PopupEntityEvent(message, type, GetNetEntity(uid)), actor.PlayerSession);
         }
 
-        public override void PopupClient(string? message, EntityUid uid, EntityUid recipient, PopupType type = PopupType.Small)
+        public override void PopupClient(string? message, EntityUid uid, EntityUid? recipient, PopupType type = PopupType.Small)
         {
             // do nothing duh its for client only
         }
index 74cf5496d9a74ef04bf92cadf5480ea01d071d09..5644a6b02f6ea16c2fe874d22828c1931bdd6432 100644 (file)
@@ -1,5 +1,6 @@
 using Content.Shared.Access.Components;
 using Content.Shared.Access.Systems;
+using Content.Shared.Construction.Components;
 using Content.Shared.DoAfter;
 using Content.Shared.Emag.Systems;
 using Content.Shared.Examine;
@@ -9,6 +10,7 @@ using Content.Shared.Interaction;
 using Content.Shared.Popups;
 using Content.Shared.Storage.Components;
 using Content.Shared.Verbs;
+using Content.Shared.Wires;
 using JetBrains.Annotations;
 using Robust.Shared.Audio.Systems;
 using Robust.Shared.Utility;
@@ -40,8 +42,11 @@ public sealed class LockSystem : EntitySystem
         SubscribeLocalEvent<LockComponent, GotEmaggedEvent>(OnEmagged);
         SubscribeLocalEvent<LockComponent, LockDoAfter>(OnDoAfterLock);
         SubscribeLocalEvent<LockComponent, UnlockDoAfter>(OnDoAfterUnlock);
-    }
 
+        SubscribeLocalEvent<LockedWiresPanelComponent, LockToggleAttemptEvent>(OnLockToggleAttempt);
+        SubscribeLocalEvent<LockedWiresPanelComponent, AttemptChangePanelEvent>(OnAttemptChangePanel);
+        SubscribeLocalEvent<LockedAnchorableComponent, UnanchorAttemptEvent>(OnUnanchorAttempt);
+    }
     private void OnStartup(EntityUid uid, LockComponent lockComp, ComponentStartup args)
     {
         _appearanceSystem.SetData(uid, LockVisuals.Locked, lockComp.Locked);
@@ -226,18 +231,18 @@ public sealed class LockSystem : EntitySystem
 
     private void AddToggleLockVerb(EntityUid uid, LockComponent component, GetVerbsEvent<AlternativeVerb> args)
     {
-        if (!args.CanAccess || !args.CanInteract || !CanToggleLock(uid, args.User))
+        if (!args.CanAccess || !args.CanInteract)
             return;
 
         AlternativeVerb verb = new()
         {
-            Act = component.Locked ?
-                () => TryUnlock(uid, args.User, component) :
-                () => TryLock(uid, args.User, component),
+            Act = component.Locked
+                ? () => TryUnlock(uid, args.User, component)
+                () => TryLock(uid, args.User, component),
             Text = Loc.GetString(component.Locked ? "toggle-lock-verb-unlock" : "toggle-lock-verb-lock"),
-            Icon = component.Locked ?
-                new SpriteSpecifier.Texture(new("/Textures/Interface/VerbIcons/unlock.svg.192dpi.png")) :
-                new SpriteSpecifier.Texture(new("/Textures/Interface/VerbIcons/lock.svg.192dpi.png")),
+            Icon = !component.Locked
+                ? new SpriteSpecifier.Texture(new("/Textures/Interface/VerbIcons/lock.svg.192dpi.png"))
+                : new SpriteSpecifier.Texture(new("/Textures/Interface/VerbIcons/unlock.svg.192dpi.png")),
         };
         args.Verbs.Add(verb);
     }
@@ -275,5 +280,53 @@ public sealed class LockSystem : EntitySystem
 
         TryUnlock(uid, args.User, skipDoAfter: true);
     }
+
+    private void OnLockToggleAttempt(Entity<LockedWiresPanelComponent> ent, ref LockToggleAttemptEvent args)
+    {
+        if (args.Cancelled)
+            return;
+
+        if (!TryComp<WiresPanelComponent>(ent, out var panel) || !panel.Open)
+            return;
+
+        if (!args.Silent)
+        {
+            _sharedPopupSystem.PopupClient(Loc.GetString("construction-step-condition-wire-panel-close"),
+                ent,
+                args.User);
+        }
+        args.Cancelled = true;
+    }
+
+
+    private void OnAttemptChangePanel(Entity<LockedWiresPanelComponent> ent, ref AttemptChangePanelEvent args)
+    {
+        if (args.Cancelled)
+            return;
+
+        if (!TryComp<LockComponent>(ent, out var lockComp) || !lockComp.Locked)
+            return;
+
+        _sharedPopupSystem.PopupClient(Loc.GetString("lock-comp-generic-fail",
+            ("target", Identity.Entity(ent, EntityManager))),
+            ent,
+            args.User);
+        args.Cancelled = true;
+    }
+
+    private void OnUnanchorAttempt(Entity<LockedAnchorableComponent> ent, ref UnanchorAttemptEvent args)
+    {
+        if (args.Cancelled)
+            return;
+
+        if (!TryComp<LockComponent>(ent, out var lockComp) || !lockComp.Locked)
+            return;
+
+        _sharedPopupSystem.PopupClient(Loc.GetString("lock-comp-generic-fail",
+                ("target", Identity.Entity(ent, EntityManager))),
+            ent,
+            args.User);
+        args.Cancel();
+    }
 }
 
diff --git a/Content.Shared/Lock/LockedAnchorableComponent.cs b/Content.Shared/Lock/LockedAnchorableComponent.cs
new file mode 100644 (file)
index 0000000..781b7f6
--- /dev/null
@@ -0,0 +1,13 @@
+using Content.Shared.Construction.Components;
+using Robust.Shared.GameStates;
+
+namespace Content.Shared.Lock;
+
+/// <summary>
+/// This is used for a <see cref="AnchorableComponent"/> that cannot be unanchored while locked.
+/// </summary>
+[RegisterComponent, NetworkedComponent, Access(typeof(LockSystem))]
+public sealed partial class LockedAnchorableComponent : Component
+{
+
+}
diff --git a/Content.Shared/Lock/LockedWiresPanelComponent.cs b/Content.Shared/Lock/LockedWiresPanelComponent.cs
new file mode 100644 (file)
index 0000000..1dbe6a4
--- /dev/null
@@ -0,0 +1,13 @@
+using Content.Shared.Wires;
+using Robust.Shared.GameStates;
+
+namespace Content.Shared.Lock;
+
+/// <summary>
+/// This is used for a <see cref="WiresPanelComponent"/> that cannot be opened while locked.
+/// </summary>
+[RegisterComponent, NetworkedComponent, Access(typeof(LockSystem))]
+public sealed partial class LockedWiresPanelComponent : Component
+{
+
+}
index aeb85de2f5971cca5d98daf84abdd4ca4b88da38..b199884afb48f001244c7193955b2d2abf619316 100644 (file)
@@ -86,7 +86,7 @@ namespace Content.Shared.Popups
         /// Variant of <see cref="PopupEntity(string, EntityUid, EntityUid, PopupType)"/> that only runs on the client, outside of prediction.
         /// Useful for shared code that is always ran by both sides to avoid duplicate popups.
         /// </summary>
-        public abstract void PopupClient(string? message, EntityUid uid, EntityUid recipient, PopupType type = PopupType.Small);
+        public abstract void PopupClient(string? message, EntityUid uid, EntityUid? recipient, PopupType type = PopupType.Small);
 
         /// <summary>
         /// Variant of <see cref="PopupEntity(string, EntityUid, EntityUid, PopupType)"/> for use with prediction. The local client will show
index f069687ffb7da12194fc38f7e20894df5dbdf8fe..b4b0768e0f771f0dba9180468929446136d68da3 100644 (file)
@@ -28,15 +28,24 @@ public abstract class SharedWiresSystem : EntitySystem
         if (args.Cancelled)
             return;
 
-        TogglePanel(uid, panel, !panel.Open);
+        if (!TogglePanel(uid, panel, !panel.Open, args.User))
+            return;
+
         AdminLogger.Add(LogType.Action, LogImpact.Low, $"{ToPrettyString(args.User):user} screwed {ToPrettyString(uid):target}'s maintenance panel {(panel.Open ? "open" : "closed")}");
 
         var sound = panel.Open ? panel.ScrewdriverOpenSound : panel.ScrewdriverCloseSound;
         Audio.PlayPredicted(sound, uid, args.User);
+        args.Handled = true;
     }
 
     private void OnInteractUsing(Entity<WiresPanelComponent> ent, ref InteractUsingEvent args)
     {
+        if (!Tool.HasQuality(args.Used, ent.Comp.OpeningTool))
+            return;
+
+        if (!CanTogglePanel(ent, args.User))
+            return;
+
         if (!Tool.UseTool(
                 args.Used,
                 args.User,
@@ -89,14 +98,25 @@ public abstract class SharedWiresSystem : EntitySystem
             Appearance.SetData(uid, WiresVisuals.MaintenancePanelState, panel.Open && panel.Visible, appearance);
     }
 
-    public void TogglePanel(EntityUid uid, WiresPanelComponent component, bool open)
+    public bool TogglePanel(EntityUid uid, WiresPanelComponent component, bool open, EntityUid? user = null)
     {
+        if (!CanTogglePanel((uid, component), user))
+            return false;
+
         component.Open = open;
         UpdateAppearance(uid, component);
         Dirty(uid, component);
 
         var ev = new PanelChangedEvent(component.Open);
         RaiseLocalEvent(uid, ref ev);
+        return true;
+    }
+
+    public bool CanTogglePanel(Entity<WiresPanelComponent> ent, EntityUid? user)
+    {
+        var attempt = new AttemptChangePanelEvent(ent.Comp.Open, user);
+        RaiseLocalEvent(ent, ref attempt);
+        return !attempt.Cancelled;
     }
 
     public bool IsPanelOpen(Entity<WiresPanelComponent?> entity)
index 9c7444778e77a7c12bd5447382f930e378ffbc12..a18e590e21b1026d503bb6c94cd4272a0539bc9a 100644 (file)
@@ -57,6 +57,12 @@ public sealed partial class WiresPanelComponent : Component
     public LocId? ExamineTextOpen = "wires-panel-component-on-examine-open";
 }
 
+/// <summary>
+/// Event raised on a <see cref="WiresPanelComponent"/> before its open state is about to be changed.
+/// </summary>
+[ByRefEvent]
+public record struct AttemptChangePanelEvent(bool Open, EntityUid? User, bool Cancelled = false);
+
 /// <summary>
 /// Event raised when a panel is opened or closed.
 /// </summary>
index f9f975c96e99f901f95ede78113afd67dcd83c14..380605697baedb86f0ad9c492b2c542f44640d4b 100644 (file)
@@ -3,8 +3,9 @@ lock-comp-on-examined-is-unlocked = The {$entityName} seems to be unlocked.
 lock-comp-do-lock-success = You lock the {$entityName}.
 lock-comp-do-unlock-success = You unlock the {$entityName}.
 lock-comp-has-user-access-fail = Access denied
+lock-comp-generic-fail = {CAPITALIZE(SUBJECT($target))} {CONJUGATE-BE($target)} locked.
 
 ## ToggleLockVerb
 
 toggle-lock-verb-unlock = Unlock
-toggle-lock-verb-lock = Lock
\ No newline at end of file
+toggle-lock-verb-lock = Lock
index dc6e718290b75bdea850189c92f93c264a5f712a..5c7a4e139feeae662b261c5ab8bbf7820b3933a9 100644 (file)
   - type: Lock
     locked: true
   - type: ActivatableUIRequiresLock
+  - type: LockedWiresPanel
   - type: Flashable
   - type: Damageable
     damageContainer: Silicon
index cc9f8035fe712034e9ffdf4d68de5c9cf9a6de03..36d77a236d07c905535627297f1562e77e761220 100644 (file)
     board: APECircuitboard
   - type: Lock
     locked: false
+  - type: LockedWiresPanel
   - type: AccessReader
     access: [[ "Research" ]]
   - type: Emitter
           True: { visible: true }
           False: { visible: false }
   - type: LockVisuals
+  - type: LockedAnchorable
   - type: DeviceNetwork
     deviceNetId: Wireless
     receiveFrequencyId: BasicDevice
index 52698f62cc0b38df0e382330ff0209f687e87449..b999b2bdede8779369af8ef471dba72af63a567d 100644 (file)
@@ -84,6 +84,8 @@
   - type: Lock
     locked: false
   - type: LockVisuals
+  - type: LockedAnchorable
+  - type: LockedWiresPanel
   - type: AccessReader
     access: [[ "Engineering" ]]
   - type: Machine