using Content.Shared._Sunrise.CarpQueen; using Content.Shared.Damage; using Content.Shared.Damage.Components; using Content.Shared.Damage.Systems; using Content.Shared.Mobs.Components; using Content.Shared.NPC.Components; using Content.Shared.NPC.Systems; namespace Content.Server._Sunrise.CarpQueen; /// /// System that makes tamed carps retaliate against entities that damage their remembered friends. /// public sealed class CarpServantRetaliationSystem : EntitySystem { [Dependency] private readonly NpcFactionSystem _npcFaction = default!; public override void Initialize() { base.Initialize(); SubscribeLocalEvent(OnDamageChanged); } private void OnDamageChanged(EntityUid uid, DamageableComponent component, DamageChangedEvent args) { // Only react to damage increases if (!args.DamageIncreased) return; // Get the damaged entity (uid is the entity that received damage) var damagedEntity = uid; // Get the attacker if (args.Origin is not { } attacker) return; // Don't retaliate against inanimate objects if (!HasComp(attacker)) return; // Find all carps that remember the damaged entity as a friend var query = EntityQueryEnumerator(); while (query.MoveNext(out var carpUid, out var memory)) { // Skip if carp is being deleted if (TerminatingOrDeleted(carpUid)) continue; // Check if the damaged entity is one of this carp's remembered friends if (!memory.RememberedFriends.Contains(damagedEntity)) continue; var attackerIsFriend = memory.RememberedFriends.Contains(attacker); var isServant = TryComp(carpUid, out var servant) && servant.Queen != null; if (isServant) { // Servants only retaliate when the queen is harmed if (servant!.Queen != damagedEntity) continue; } else { // Free-roaming carp do not retaliate against other remembered friends if (attackerIsFriend) continue; } // Aggro on the attacker var exception = EnsureComp(carpUid); // Also handle discipline logic: if attacker was in forbidden targets, remove it // This allows the carp to attack again after the attacker damaged the owner if (memory.ForbiddenTargets.Remove(attacker)) { Dirty(carpUid, memory); } // Unignore and aggro the attacker (allows attack after discipline was cleared) _npcFaction.UnignoreEntity((carpUid, exception), attacker); _npcFaction.AggroEntity((carpUid, exception), (attacker, null)); } } }