NpcFactionSystem.Exception.cs 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. using Content.Shared.NPC.Components;
  2. using System.Linq;
  3. namespace Content.Shared.NPC.Systems;
  4. /// <summary>
  5. /// Prevents an NPC from attacking some entities from an enemy faction.
  6. /// Also makes it attack some entities even if they are in neutral factions (retaliation).
  7. /// </summary>
  8. public sealed partial class NpcFactionSystem
  9. {
  10. private EntityQuery<FactionExceptionComponent> _exceptionQuery;
  11. private EntityQuery<FactionExceptionTrackerComponent> _trackerQuery;
  12. public void InitializeException()
  13. {
  14. _exceptionQuery = GetEntityQuery<FactionExceptionComponent>();
  15. _trackerQuery = GetEntityQuery<FactionExceptionTrackerComponent>();
  16. SubscribeLocalEvent<FactionExceptionComponent, ComponentShutdown>(OnShutdown);
  17. SubscribeLocalEvent<FactionExceptionTrackerComponent, ComponentShutdown>(OnTrackerShutdown);
  18. }
  19. private void OnShutdown(Entity<FactionExceptionComponent> ent, ref ComponentShutdown args)
  20. {
  21. foreach (var uid in ent.Comp.Hostiles)
  22. {
  23. if (_trackerQuery.TryGetComponent(uid, out var tracker))
  24. tracker.Entities.Remove(ent);
  25. }
  26. foreach (var uid in ent.Comp.Ignored)
  27. {
  28. if (_trackerQuery.TryGetComponent(uid, out var tracker))
  29. tracker.Entities.Remove(ent);
  30. }
  31. }
  32. private void OnTrackerShutdown(Entity<FactionExceptionTrackerComponent> ent, ref ComponentShutdown args)
  33. {
  34. foreach (var uid in ent.Comp.Entities)
  35. {
  36. if (!_exceptionQuery.TryGetComponent(uid, out var exception))
  37. continue;
  38. exception.Ignored.Remove(ent);
  39. exception.Hostiles.Remove(ent);
  40. }
  41. }
  42. /// <summary>
  43. /// Returns whether the entity from an enemy faction won't be attacked
  44. /// </summary>
  45. public bool IsIgnored(Entity<FactionExceptionComponent?> ent, EntityUid target)
  46. {
  47. if (!Resolve(ent, ref ent.Comp, false))
  48. return false;
  49. return ent.Comp.Ignored.Contains(target);
  50. }
  51. /// <summary>
  52. /// Returns the specific hostile entities for a given entity.
  53. /// </summary>
  54. public IEnumerable<EntityUid> GetHostiles(Entity<FactionExceptionComponent?> ent)
  55. {
  56. if (!Resolve(ent, ref ent.Comp, false))
  57. return Array.Empty<EntityUid>();
  58. // evil c#
  59. return ent.Comp!.Hostiles;
  60. }
  61. /// <summary>
  62. /// Prevents an entity from an enemy faction from being attacked
  63. /// </summary>
  64. public void IgnoreEntity(Entity<FactionExceptionComponent?> ent, Entity<FactionExceptionTrackerComponent?> target)
  65. {
  66. ent.Comp ??= EnsureComp<FactionExceptionComponent>(ent);
  67. ent.Comp.Ignored.Add(target);
  68. target.Comp ??= EnsureComp<FactionExceptionTrackerComponent>(target);
  69. target.Comp.Entities.Add(ent);
  70. }
  71. /// <summary>
  72. /// Prevents a list of entities from an enemy faction from being attacked
  73. /// </summary>
  74. public void IgnoreEntities(Entity<FactionExceptionComponent?> ent, IEnumerable<EntityUid> ignored)
  75. {
  76. ent.Comp ??= EnsureComp<FactionExceptionComponent>(ent);
  77. foreach (var ignore in ignored)
  78. {
  79. IgnoreEntity(ent, ignore);
  80. }
  81. }
  82. /// <summary>
  83. /// Makes an entity always be considered hostile.
  84. /// </summary>
  85. public void AggroEntity(Entity<FactionExceptionComponent?> ent, Entity<FactionExceptionTrackerComponent?> target)
  86. {
  87. ent.Comp ??= EnsureComp<FactionExceptionComponent>(ent);
  88. ent.Comp.Hostiles.Add(target);
  89. target.Comp ??= EnsureComp<FactionExceptionTrackerComponent>(target);
  90. target.Comp.Entities.Add(ent);
  91. }
  92. /// <summary>
  93. /// Makes an entity no longer be considered hostile, if it was.
  94. /// Doesn't apply to regular faction hostilities.
  95. /// </summary>
  96. public void DeAggroEntity(Entity<FactionExceptionComponent?> ent, EntityUid target)
  97. {
  98. if (!Resolve(ent, ref ent.Comp, false))
  99. return;
  100. if (!ent.Comp.Hostiles.Remove(target) || !_trackerQuery.TryGetComponent(target, out var tracker))
  101. return;
  102. tracker.Entities.Remove(ent);
  103. }
  104. /// <summary>
  105. /// Makes a list of entities no longer be considered hostile, if it was.
  106. /// Doesn't apply to regular faction hostilities.
  107. /// </summary>
  108. public void AggroEntities(Entity<FactionExceptionComponent?> ent, IEnumerable<EntityUid> entities)
  109. {
  110. ent.Comp ??= EnsureComp<FactionExceptionComponent>(ent);
  111. foreach (var uid in entities)
  112. {
  113. AggroEntity(ent, uid);
  114. }
  115. }
  116. }