]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
New Feature: Slot blockers (#35172)
authorWinkarst <74284083+Winkarst-cpu@users.noreply.github.com>
Mon, 12 May 2025 17:35:42 +0000 (20:35 +0300)
committerGitHub <noreply@github.com>
Mon, 12 May 2025 17:35:42 +0000 (10:35 -0700)
* First commit

* More comments

* Update

* Update

* For Beloved Maintainers

* Beck T, my beloved

* Update

* Old stuff

* Update EquipAttemptEvents.cs

* Update UnequipAttemptEvent.cs

---------

Co-authored-by: beck-thompson <107373427+beck-thompson@users.noreply.github.com>
Content.Shared/Inventory/Events/EquipAttemptEvents.cs
Content.Shared/Inventory/Events/UnequipAttemptEvent.cs
Content.Shared/Inventory/InventorySystem.Relay.cs
Content.Shared/Inventory/SlotBlockComponent.cs [new file with mode: 0644]
Content.Shared/Inventory/SlotBlockSystem.cs [new file with mode: 0644]
Resources/Locale/en-US/inventory/components/slot-block-component.ftl [new file with mode: 0644]
Resources/Prototypes/Entities/Clothing/Head/base_clothinghead.yml
Resources/Prototypes/Entities/Clothing/OuterClothing/base_clothingouter.yml

index af0961e0755aa6c28eb21a07621cca240f171cc9..2914dd469ee1db9cef87bd8da19677ff7642115e 100644 (file)
@@ -1,8 +1,10 @@
 namespace Content.Shared.Inventory.Events;
 
 public abstract class EquipAttemptBase(EntityUid equipee, EntityUid equipTarget, EntityUid equipment,
-    SlotDefinition slotDefinition) : CancellableEntityEventArgs
+    SlotDefinition slotDefinition) : CancellableEntityEventArgs, IInventoryRelayEvent
 {
+    public SlotFlags TargetSlots { get; } = SlotFlags.WITHOUT_POCKET;
+
     /// <summary>
     /// The entity performing the action. NOT necessarily the one actually "receiving" the equipment.
     /// </summary>
index 4824556753fb175b1baa69de7aa07ef534457eef..a74b3e2d7ccf3fa2cb54db3f6e7cebf16f1f4e48 100644 (file)
@@ -1,8 +1,10 @@
 namespace Content.Shared.Inventory.Events;
 
 public abstract class UnequipAttemptEventBase(EntityUid unequipee, EntityUid unEquipTarget, EntityUid equipment,
-    SlotDefinition slotDefinition) : CancellableEntityEventArgs
+    SlotDefinition slotDefinition) : CancellableEntityEventArgs, IInventoryRelayEvent
 {
+    public SlotFlags TargetSlots { get; } = SlotFlags.WITHOUT_POCKET;
+
     /// <summary>
     /// The entity performing the action. NOT necessarily the same as the entity whose equipment is being removed..
     /// </summary>
index 1ab9478a8de3d470548a8921b30e979b97910e1b..84f2dc374bb567fe40ce10e72320320379964c3f 100644 (file)
@@ -48,6 +48,8 @@ public partial class InventorySystem
         SubscribeLocalEvent<InventoryComponent, SelfBeforeClimbEvent>(RelayInventoryEvent);
         SubscribeLocalEvent<InventoryComponent, CoefficientQueryEvent>(RelayInventoryEvent);
         SubscribeLocalEvent<InventoryComponent, ZombificationResistanceQueryEvent>(RelayInventoryEvent);
+        SubscribeLocalEvent<InventoryComponent, IsEquippingTargetAttemptEvent>(RelayInventoryEvent);
+        SubscribeLocalEvent<InventoryComponent, IsUnequippingTargetAttemptEvent>(RelayInventoryEvent);
 
         // by-ref events
         SubscribeLocalEvent<InventoryComponent, RefreshFrictionModifiersEvent>(RefRelayInventoryEvent);
diff --git a/Content.Shared/Inventory/SlotBlockComponent.cs b/Content.Shared/Inventory/SlotBlockComponent.cs
new file mode 100644 (file)
index 0000000..dde706a
--- /dev/null
@@ -0,0 +1,16 @@
+using Robust.Shared.GameStates;
+
+namespace Content.Shared.Inventory;
+
+/// <summary>
+/// Used to prevent items from being unequipped and equipped from slots that are listed in <see cref="Slots"/>.
+/// </summary>
+[RegisterComponent, NetworkedComponent, AutoGenerateComponentState, Access(typeof(SlotBlockSystem))]
+public sealed partial class SlotBlockComponent : Component
+{
+    /// <summary>
+    /// Slots that this entity should block.
+    /// </summary>
+    [DataField(required: true), AutoNetworkedField]
+    public SlotFlags Slots = SlotFlags.NONE;
+}
diff --git a/Content.Shared/Inventory/SlotBlockSystem.cs b/Content.Shared/Inventory/SlotBlockSystem.cs
new file mode 100644 (file)
index 0000000..9ac3361
--- /dev/null
@@ -0,0 +1,35 @@
+using Content.Shared.Inventory.Events;
+
+namespace Content.Shared.Inventory;
+
+/// <summary>
+/// Handles prevention of items being unequipped and equipped from slots that are blocked by <see cref="SlotBlockComponent"/>.
+/// </summary>
+public sealed partial class SlotBlockSystem : EntitySystem
+{
+    public override void Initialize()
+    {
+        base.Initialize();
+
+        SubscribeLocalEvent<SlotBlockComponent, InventoryRelayedEvent<IsEquippingTargetAttemptEvent>>(OnEquipAttempt);
+        SubscribeLocalEvent<SlotBlockComponent, InventoryRelayedEvent<IsUnequippingTargetAttemptEvent>>(OnUnequipAttempt);
+    }
+
+    private void OnEquipAttempt(Entity<SlotBlockComponent> ent, ref InventoryRelayedEvent<IsEquippingTargetAttemptEvent> args)
+    {
+        if (args.Args.Cancelled || (args.Args.SlotFlags & ent.Comp.Slots) == 0)
+            return;
+
+        args.Args.Reason = Loc.GetString("slot-block-component-blocked", ("item", ent));
+        args.Args.Cancel();
+    }
+
+    private void OnUnequipAttempt(Entity<SlotBlockComponent> ent, ref InventoryRelayedEvent<IsUnequippingTargetAttemptEvent> args)
+    {
+        if (args.Args.Cancelled || (args.Args.SlotFlags & ent.Comp.Slots) == 0)
+            return;
+
+        args.Args.Reason = Loc.GetString("slot-block-component-blocked", ("item", ent));
+        args.Args.Cancel();
+    }
+}
diff --git a/Resources/Locale/en-US/inventory/components/slot-block-component.ftl b/Resources/Locale/en-US/inventory/components/slot-block-component.ftl
new file mode 100644 (file)
index 0000000..55f8708
--- /dev/null
@@ -0,0 +1 @@
+slot-block-component-blocked = This slot is blocked by {$item}!
index 646a5550370f5f52285b6d736c2200a526c3daf3..8c525791883af4f7fc87ad7ec15d571691d3d38e 100644 (file)
   id: ClothingHeadEVAHelmetBase
   name: base space helmet
   components:
+  - type: SlotBlock
+    slots: [ears, eyes, mask]
   - type: BreathMask
   - type: Item
     size: Normal
   name: base hardsuit helmet
   categories: [ HideSpawnMenu ]
   components:
+  - type: SlotBlock
+    slots: [ears, eyes, mask]
   - type: BreathMask
   - type: Sprite
     state: icon # default state used by most inheritors
 - type: entity
   abstract: true
   # No parent since it isn't an item
-  # must parent both this and the desired helmet base when using 
+  # must parent both this and the desired helmet base when using
   id: ClothingHeadSuitWithLightBase
   name: base hardsuit helmet with light
   categories: [ HideSpawnMenu ]
   components:
+  - type: SlotBlock
+    slots: [ears, eyes, mask]
   - type: Sprite
     layers:
     - state: icon
index 1ee9b765883a63a17ea78f32c36013f890024bc9..ef2119fd8d854a652ac461cbbc9d4a93e63ea5d5 100644 (file)
   id: ClothingOuterHardsuitBase
   name: base hardsuit
   components:
+  - type: SlotBlock
+    slots: [innerclothing, feet]
   - type: PressureProtection
     highPressureMultiplier: 0.3
     lowPressureMultiplier: 1000
   id: ClothingOuterEVASuitBase
   name: base EVA Suit
   components:
+  - type: SlotBlock
+    slots: [innerclothing, feet]
   - type: PressureProtection
     highPressureMultiplier: 0.6
     lowPressureMultiplier: 1000