using System.Linq; using Content.Server.NPC.Components; namespace Content.Server.NPC.Systems; /// /// Prevents an NPC from attacking some entities from an enemy faction. /// 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(EntityUid uid, FactionExceptionComponent component, ComponentShutdown args) { foreach (var ent in component.Hostiles) { if (!_trackerQuery.TryGetComponent(ent, out var trackerComponent)) continue; trackerComponent.Entities.Remove(uid); } foreach (var ent in component.Ignored) { if (!_trackerQuery.TryGetComponent(ent, out var trackerComponent)) continue; trackerComponent.Entities.Remove(uid); } } private void OnTrackerShutdown(EntityUid uid, FactionExceptionTrackerComponent component, ComponentShutdown args) { foreach (var ent in component.Entities) { if (!_exceptionQuery.TryGetComponent(ent, out var exceptionComponent)) continue; exceptionComponent.Ignored.Remove(uid); exceptionComponent.Hostiles.Remove(uid); } } /// /// Returns whether the entity from an enemy faction won't be attacked /// public bool IsIgnored(EntityUid uid, EntityUid target, FactionExceptionComponent? comp = null) { if (!Resolve(uid, ref comp, false)) return false; return comp.Ignored.Contains(target); } /// /// Returns the specific hostile entities for a given entity. /// public IEnumerable GetHostiles(EntityUid uid, FactionExceptionComponent? comp = null) { if (!Resolve(uid, ref comp, false)) return Array.Empty(); return comp.Hostiles; } /// /// Prevents an entity from an enemy faction from being attacked /// public void IgnoreEntity(EntityUid uid, EntityUid target, FactionExceptionComponent? comp = null) { comp ??= EnsureComp(uid); comp.Ignored.Add(target); EnsureComp(target).Entities.Add(uid); } /// /// Prevents a list of entities from an enemy faction from being attacked /// public void IgnoreEntities(EntityUid uid, IEnumerable ignored, FactionExceptionComponent? comp = null) { comp ??= EnsureComp(uid); foreach (var ignore in ignored) { IgnoreEntity(uid, ignore, comp); } } /// /// Makes an entity always be considered hostile. /// public void AggroEntity(EntityUid uid, EntityUid target, FactionExceptionComponent? comp = null) { comp ??= EnsureComp(uid); comp.Hostiles.Add(target); EnsureComp(target).Entities.Add(uid); } /// /// Makes an entity no longer be considered hostile, if it was. /// Doesn't apply to regular faction hostilities. /// public void DeAggroEntity(EntityUid uid, EntityUid target, FactionExceptionComponent? comp = null) { if (!Resolve(uid, ref comp, false)) return; if (!comp.Hostiles.Remove(target) || !_trackerQuery.TryGetComponent(target, out var tracker)) return; tracker.Entities.Remove(uid); } /// /// Makes a list of entities no longer be considered hostile, if it was. /// Doesn't apply to regular faction hostilities. /// public void AggroEntities(EntityUid uid, IEnumerable entities, FactionExceptionComponent? comp = null) { comp ??= EnsureComp(uid); foreach (var ent in entities) { AggroEntity(uid, ent, comp); } } }