--- /dev/null
+using Content.Shared.Inventory;
+using Robust.Shared.GameStates;
+
+namespace Content.Shared.Trigger.Components.Triggers;
+
+/// <summary>
+/// Triggers when an entity equips another entity.
+/// The user is the entity being equipped.
+/// </summary>
+[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
+public sealed partial class TriggerOnDidEquipComponent : BaseTriggerOnXComponent
+{
+ /// <summary>
+ /// The slots entities being equipped to will trigger the entity.
+ /// </summary>
+ [DataField, AutoNetworkedField]
+ public SlotFlags SlotFlags;
+}
--- /dev/null
+using Content.Shared.Inventory;
+using Robust.Shared.GameStates;
+
+namespace Content.Shared.Trigger.Components.Triggers;
+
+/// <summary>
+/// Triggers when an entity unequips another entity.
+/// The user is the entity being unequipped.
+/// </summary>
+[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
+public sealed partial class TriggerOnDidUnequipComponent : BaseTriggerOnXComponent
+{
+ /// <summary>
+ /// The slots that entities being unequipped from will trigger the entity.
+ /// </summary>
+ [DataField, AutoNetworkedField]
+ public SlotFlags SlotFlags;
+}
--- /dev/null
+using Content.Shared.Inventory;
+using Robust.Shared.GameStates;
+
+namespace Content.Shared.Trigger.Components.Triggers;
+
+/// <summary>
+/// Triggers when an entity is equipped to another entity.
+/// The user is the entity being equipped to (i.e. the equipee).
+/// </summary>
+[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
+public sealed partial class TriggerOnGotEquippedComponent : BaseTriggerOnXComponent
+{
+ /// <summary>
+ /// The slots that being equipped to will trigger the entity.
+ /// </summary>
+ [DataField, AutoNetworkedField]
+ public SlotFlags SlotFlags;
+}
--- /dev/null
+using Content.Shared.Inventory;
+using Robust.Shared.GameStates;
+
+namespace Content.Shared.Trigger.Components.Triggers;
+
+/// <summary>
+/// Triggers when an entity is unequipped from another entity.
+/// The user is the entity being unequipped from (i.e. the (un)equipee).
+/// </summary>
+[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
+public sealed partial class TriggerOnGotUnequippedComponent : BaseTriggerOnXComponent
+{
+ /// <summary>
+ /// The slots that being unequipped from will trigger the entity.
+ /// </summary>
+ [DataField, AutoNetworkedField]
+ public SlotFlags SlotFlags;
+}
--- /dev/null
+using Content.Shared.Trigger.Components.Triggers;
+using Robust.Shared.Timing;
+using Content.Shared.Inventory.Events;
+
+namespace Content.Shared.Trigger.Systems;
+
+/// <summary>
+/// System for creating triggers when entities are equipped or unequipped from inventory slots.
+/// </summary>
+public sealed class TriggerOnEquipmentSystem : EntitySystem
+{
+ [Dependency] private readonly TriggerSystem _trigger = default!;
+ [Dependency] private readonly IGameTiming _timing = default!;
+
+ public override void Initialize()
+ {
+ base.Initialize();
+
+ SubscribeLocalEvent<TriggerOnDidEquipComponent, DidEquipEvent>(OnDidEquip);
+ SubscribeLocalEvent<TriggerOnDidUnequipComponent, DidUnequipEvent>(OnDidUnequip);
+ SubscribeLocalEvent<TriggerOnGotEquippedComponent, GotEquippedEvent>(OnGotEquipped);
+ SubscribeLocalEvent<TriggerOnGotUnequippedComponent, GotUnequippedEvent>(OnGotUnequipped);
+ }
+
+ // Used by entities when equipping or unequipping other entities
+ private void OnDidEquip(Entity<TriggerOnDidEquipComponent> ent, ref DidEquipEvent args)
+ {
+ if (_timing.ApplyingState)
+ return;
+
+ if ((ent.Comp.SlotFlags & args.SlotFlags) == 0)
+ return;
+
+ _trigger.Trigger(ent.Owner, args.Equipment, ent.Comp.KeyOut);
+ }
+
+ private void OnDidUnequip(Entity<TriggerOnDidUnequipComponent> ent, ref DidUnequipEvent args)
+ {
+ if (_timing.ApplyingState)
+ return;
+
+ if ((ent.Comp.SlotFlags & args.SlotFlags) == 0)
+ return;
+
+ _trigger.Trigger(ent.Owner, args.Equipment, ent.Comp.KeyOut);
+ }
+
+ // Used by entities when they get equipped or unequipped
+ private void OnGotEquipped(Entity<TriggerOnGotEquippedComponent> ent, ref GotEquippedEvent args)
+ {
+ if (_timing.ApplyingState)
+ return;
+
+ if ((ent.Comp.SlotFlags & args.SlotFlags) == 0)
+ return;
+
+ _trigger.Trigger(ent.Owner, args.Equipee, ent.Comp.KeyOut);
+ }
+
+ private void OnGotUnequipped(Entity<TriggerOnGotUnequippedComponent> ent, ref GotUnequippedEvent args)
+ {
+ if (_timing.ApplyingState)
+ return;
+
+ if ((ent.Comp.SlotFlags & args.SlotFlags) == 0)
+ return;
+
+ _trigger.Trigger(ent.Owner, args.Equipee, ent.Comp.KeyOut);
+ }
+}