From 08d9d46b46e7ff7a104b7f8174e9e26dd3452298 Mon Sep 17 00:00:00 2001 From: Winkarst <74284083+Winkarst-cpu@users.noreply.github.com> Date: Mon, 12 May 2025 20:35:42 +0300 Subject: [PATCH] New Feature: Slot blockers (#35172) * 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> --- .../Inventory/Events/EquipAttemptEvents.cs | 4 ++- .../Inventory/Events/UnequipAttemptEvent.cs | 4 ++- .../Inventory/InventorySystem.Relay.cs | 2 ++ .../Inventory/SlotBlockComponent.cs | 16 +++++++++ Content.Shared/Inventory/SlotBlockSystem.cs | 35 +++++++++++++++++++ .../components/slot-block-component.ftl | 1 + .../Clothing/Head/base_clothinghead.yml | 8 ++++- .../OuterClothing/base_clothingouter.yml | 4 +++ 8 files changed, 71 insertions(+), 3 deletions(-) create mode 100644 Content.Shared/Inventory/SlotBlockComponent.cs create mode 100644 Content.Shared/Inventory/SlotBlockSystem.cs create mode 100644 Resources/Locale/en-US/inventory/components/slot-block-component.ftl diff --git a/Content.Shared/Inventory/Events/EquipAttemptEvents.cs b/Content.Shared/Inventory/Events/EquipAttemptEvents.cs index af0961e075..2914dd469e 100644 --- a/Content.Shared/Inventory/Events/EquipAttemptEvents.cs +++ b/Content.Shared/Inventory/Events/EquipAttemptEvents.cs @@ -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; + /// /// The entity performing the action. NOT necessarily the one actually "receiving" the equipment. /// diff --git a/Content.Shared/Inventory/Events/UnequipAttemptEvent.cs b/Content.Shared/Inventory/Events/UnequipAttemptEvent.cs index 4824556753..a74b3e2d7c 100644 --- a/Content.Shared/Inventory/Events/UnequipAttemptEvent.cs +++ b/Content.Shared/Inventory/Events/UnequipAttemptEvent.cs @@ -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; + /// /// The entity performing the action. NOT necessarily the same as the entity whose equipment is being removed.. /// diff --git a/Content.Shared/Inventory/InventorySystem.Relay.cs b/Content.Shared/Inventory/InventorySystem.Relay.cs index 1ab9478a8d..84f2dc374b 100644 --- a/Content.Shared/Inventory/InventorySystem.Relay.cs +++ b/Content.Shared/Inventory/InventorySystem.Relay.cs @@ -48,6 +48,8 @@ public partial class InventorySystem SubscribeLocalEvent(RelayInventoryEvent); SubscribeLocalEvent(RelayInventoryEvent); SubscribeLocalEvent(RelayInventoryEvent); + SubscribeLocalEvent(RelayInventoryEvent); + SubscribeLocalEvent(RelayInventoryEvent); // by-ref events SubscribeLocalEvent(RefRelayInventoryEvent); diff --git a/Content.Shared/Inventory/SlotBlockComponent.cs b/Content.Shared/Inventory/SlotBlockComponent.cs new file mode 100644 index 0000000000..dde706addf --- /dev/null +++ b/Content.Shared/Inventory/SlotBlockComponent.cs @@ -0,0 +1,16 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared.Inventory; + +/// +/// Used to prevent items from being unequipped and equipped from slots that are listed in . +/// +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState, Access(typeof(SlotBlockSystem))] +public sealed partial class SlotBlockComponent : Component +{ + /// + /// Slots that this entity should block. + /// + [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 index 0000000000..9ac3361cb9 --- /dev/null +++ b/Content.Shared/Inventory/SlotBlockSystem.cs @@ -0,0 +1,35 @@ +using Content.Shared.Inventory.Events; + +namespace Content.Shared.Inventory; + +/// +/// Handles prevention of items being unequipped and equipped from slots that are blocked by . +/// +public sealed partial class SlotBlockSystem : EntitySystem +{ + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent>(OnEquipAttempt); + SubscribeLocalEvent>(OnUnequipAttempt); + } + + private void OnEquipAttempt(Entity ent, ref InventoryRelayedEvent 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 ent, ref InventoryRelayedEvent 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 index 0000000000..55f870812b --- /dev/null +++ b/Resources/Locale/en-US/inventory/components/slot-block-component.ftl @@ -0,0 +1 @@ +slot-block-component-blocked = This slot is blocked by {$item}! diff --git a/Resources/Prototypes/Entities/Clothing/Head/base_clothinghead.yml b/Resources/Prototypes/Entities/Clothing/Head/base_clothinghead.yml index 646a555037..8c52579188 100644 --- a/Resources/Prototypes/Entities/Clothing/Head/base_clothinghead.yml +++ b/Resources/Prototypes/Entities/Clothing/Head/base_clothinghead.yml @@ -105,6 +105,8 @@ id: ClothingHeadEVAHelmetBase name: base space helmet components: + - type: SlotBlock + slots: [ears, eyes, mask] - type: BreathMask - type: Item size: Normal @@ -140,6 +142,8 @@ 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 @@ -181,11 +185,13 @@ - 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 diff --git a/Resources/Prototypes/Entities/Clothing/OuterClothing/base_clothingouter.yml b/Resources/Prototypes/Entities/Clothing/OuterClothing/base_clothingouter.yml index 1ee9b76588..ef2119fd8d 100644 --- a/Resources/Prototypes/Entities/Clothing/OuterClothing/base_clothingouter.yml +++ b/Resources/Prototypes/Entities/Clothing/OuterClothing/base_clothingouter.yml @@ -105,6 +105,8 @@ id: ClothingOuterHardsuitBase name: base hardsuit components: + - type: SlotBlock + slots: [innerclothing, feet] - type: PressureProtection highPressureMultiplier: 0.3 lowPressureMultiplier: 1000 @@ -149,6 +151,8 @@ id: ClothingOuterEVASuitBase name: base EVA Suit components: + - type: SlotBlock + slots: [innerclothing, feet] - type: PressureProtection highPressureMultiplier: 0.6 lowPressureMultiplier: 1000