using Content.Shared.Clothing; using Content.Shared.Implants; using Content.Shared.Inventory; using Content.Shared.Mindshield.Components; using Content.Shared.StatusIcon; using Robust.Shared.Prototypes; using Robust.Shared.Timing; namespace Content.Shared.Mindshield; public sealed partial class MindShieldSystem : EntitySystem { [Dependency] private IGameTiming _timing = default!; /// /// Status icon displayed in the sec HUD. /// public static ProtoId StatusIcon = "MindShieldIcon"; public override void Initialize() { base.Initialize(); // Mind shield status events SubscribeLocalEvent>((e, ref k) => OnStatusQuery(e, ref k.Args)); SubscribeLocalEvent>((e, ref k) => OnStatusQuery(e, ref k.Args)); } [SubscribeLocalEvent] private void OnMindshieldUnequip(Entity ent, ref ClothingGotUnequippedEvent args) { if (_timing.ApplyingState) return; RefreshMindshieldStatus(args.Wearer); } [SubscribeLocalEvent] private void OnMindshieldEquip(Entity ent, ref ClothingGotEquippedEvent args) { if (_timing.ApplyingState) return; RefreshMindshieldStatus(args.Wearer); } [SubscribeLocalEvent] private void OnMindshieldRemoved(Entity ent, ref ComponentRemove args) { RefreshMindshieldStatus(ent.Owner); } [SubscribeLocalEvent] private void OnMindshieldImplantRemoved(Entity ent, ref ImplantRemovedEvent args) { RefreshMindshieldStatus(args.Implanted); } [SubscribeLocalEvent] private void OnMindshieldImplanted(Entity ent, ref ImplantImplantedEvent args) { RefreshMindshieldStatus(args.Implanted); } [SubscribeLocalEvent] private void OnMindshieldMapInit(Entity ent, ref MapInitEvent args) { // todo: make it not refresh on implant & clothing items RefreshMindshieldStatus(ent.Owner); } /// /// This function updates . It should be called when anything makes a modification of its mindshielded-ness. /// public void RefreshMindshieldStatus(EntityUid ent) { var ev = new GetMindShieldStatusEvent(); RaiseLocalEvent(ent, ref ev); var mindshielded = ev.IsMindshielded; var visible = ev.IsVisible; if (!mindshielded && !visible) { if (HasComp(ent)) RemCompDeferred(ent); } else { EnsureComp(ent, out var c); c.IsMindshielded = mindshielded; c.IsVisible = visible; Dirty(ent, c); } } [SubscribeLocalEvent] private void OnStatusQuery(Entity e, ref GetMindShieldStatusEvent args) { args.IsMindshielded = true; args.IsVisible = true; } /// /// Retrieves mindshielding data of an entity. Works via , and so requires proper dirtying on the part of mindshield providers. /// /// The entity to check the mindshield status of. /// If the entity has a functional mind shield /// Wether the entity shows a mindshield icon on the sec HUD /// You should never look for a mindshield component and instead use this function. public void GetMindshieldStatus(EntityUid entity, out bool isMindshielded, out bool isVisible) { if (TryComp(entity, out var comp)) { isMindshielded = comp.IsMindshielded; isVisible = comp.IsVisible; } else { isMindshielded = isVisible = false; } } } /// /// Raised in order to get whether an entity is mindshielded visually, mechanically or both. /// [ByRefEvent] public sealed class GetMindShieldStatusEvent : EntityEventArgs, IInventoryRelayEvent { public SlotFlags TargetSlots => SlotFlags.WITHOUT_POCKET; /// /// Whether the entity is mindshielded. /// public bool IsMindshielded; /// /// Whether a mindshield icon is present /// public bool IsVisible; }