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;
}