using Content.Shared.NPC.Components;
using System.Linq;
namespace Content.Shared.NPC.Systems;
///
/// Prevents an NPC from attacking some entities from an enemy faction.
/// Also makes it attack some entities even if they are in neutral factions (retaliation).
///
public sealed partial class NpcFactionSystem
{
private EntityQuery _exceptionQuery;
private EntityQuery _trackerQuery;
public void InitializeException()
{
_exceptionQuery = GetEntityQuery();
_trackerQuery = GetEntityQuery();
SubscribeLocalEvent(OnShutdown);
SubscribeLocalEvent(OnTrackerShutdown);
}
private void OnShutdown(Entity ent, ref ComponentShutdown args)
{
foreach (var uid in ent.Comp.Hostiles)
{
if (_trackerQuery.TryGetComponent(uid, out var tracker))
tracker.Entities.Remove(ent);
}
foreach (var uid in ent.Comp.Ignored)
{
if (_trackerQuery.TryGetComponent(uid, out var tracker))
tracker.Entities.Remove(ent);
}
}
private void OnTrackerShutdown(Entity ent, ref ComponentShutdown args)
{
foreach (var uid in ent.Comp.Entities)
{
if (!_exceptionQuery.TryGetComponent(uid, out var exception))
continue;
exception.Ignored.Remove(ent);
exception.Hostiles.Remove(ent);
}
}
///
/// Returns whether the entity from an enemy faction won't be attacked
///
public bool IsIgnored(Entity ent, EntityUid target)
{
if (!Resolve(ent, ref ent.Comp, false))
return false;
return ent.Comp.Ignored.Contains(target);
}
///
/// Returns the specific hostile entities for a given entity.
///
public IEnumerable GetHostiles(Entity ent)
{
if (!Resolve(ent, ref ent.Comp, false))
return Array.Empty();
// evil c#
return ent.Comp!.Hostiles;
}
///
/// Prevents an entity from an enemy faction from being attacked
///
public void IgnoreEntity(Entity ent, Entity target)
{
ent.Comp ??= EnsureComp(ent);
ent.Comp.Ignored.Add(target);
target.Comp ??= EnsureComp(target);
target.Comp.Entities.Add(ent);
}
///
/// Prevents a list of entities from an enemy faction from being attacked
///
public void IgnoreEntities(Entity ent, IEnumerable ignored)
{
ent.Comp ??= EnsureComp(ent);
foreach (var ignore in ignored)
{
IgnoreEntity(ent, ignore);
}
}
///
/// Makes an entity always be considered hostile.
///
public void AggroEntity(Entity ent, Entity target)
{
ent.Comp ??= EnsureComp(ent);
ent.Comp.Hostiles.Add(target);
target.Comp ??= EnsureComp(target);
target.Comp.Entities.Add(ent);
}
///
/// Makes an entity no longer be considered hostile, if it was.
/// Doesn't apply to regular faction hostilities.
///
public void DeAggroEntity(Entity ent, EntityUid target)
{
if (!Resolve(ent, ref ent.Comp, false))
return;
if (!ent.Comp.Hostiles.Remove(target) || !_trackerQuery.TryGetComponent(target, out var tracker))
return;
tracker.Entities.Remove(ent);
}
///
/// Makes a list of entities no longer be considered hostile, if it was.
/// Doesn't apply to regular faction hostilities.
///
public void AggroEntities(Entity ent, IEnumerable entities)
{
ent.Comp ??= EnsureComp(ent);
foreach (var uid in entities)
{
AggroEntity(ent, uid);
}
}
}