using Content.Server.Antag; using Content.Server.Antag.Components; using Content.Server.GameTicking.Rules.Components; using Content.Shared._DV.Traitor; using Content.Shared.Administration.Logs; using Content.Shared.Database; using Content.Shared.Hands.EntitySystems; using Content.Shared.Mind; using Content.Shared.Mobs.Systems; using Content.Shared.Nuke; using Content.Shared.Popups; namespace Content.Server._DV.Nuke; /// /// When a syndie extracts the nuke disk, gives it to nukies as soon as possible. /// If nukies are taking years and a sleeper steals it, an arbitrary nukie gets it. /// If there are no nukies it waits until a loneop spawns. /// public sealed class NukeDiskSystem : EntitySystem { [Dependency] private readonly ISharedAdminLogManager _adminLogger = default!; [Dependency] private readonly MobStateSystem _mob = default!; [Dependency] private readonly SharedHandsSystem _hands = default!; [Dependency] private readonly SharedPopupSystem _popup = default!; public override void Initialize() { base.Initialize(); SubscribeLocalEvent(OnFultoned); SubscribeLocalEvent(OnAntagEntSelected); } private void OnFultoned(Entity ent, ref FultonedEvent args) { // no free win for using salv fultons if (!HasComp(ent)) return; // just incase another system somehow doesn't do it RemCompDeferred(ent); ent.Comp.Extracted = true; // give it to an arbitrary nukie if a sleeper/whatever steals it // everyone wins if (FindLivingNukie() is {} target) TeleportDisk(ent, target); } private void OnAntagEntSelected(Entity ent, ref AfterAntagEntitySelectedEvent args) { if (FindExtractedDisk() is not {} disk) return; // this nukie is arbitrary but its probably definitely a loneop anyway TeleportDisk(disk, args.EntityUid); } /// /// Tries to give the disk to a living nukie. /// public void TeleportDisk(Entity ent, EntityUid target) { if (!ent.Comp.Extracted) return; ent.Comp.Extracted = false; // no repeated teleports _adminLogger.Add(LogType.Teleport, LogImpact.High, $"Teleported {ToPrettyString(ent):disk} to {ToPrettyString(target)} because it was extracted by a syndie"); _hands.PickupOrDrop(target, ent); _popup.PopupEntity(Loc.GetString("nuke-disk-teleported", ("disk", ent)), target, target); } /// /// Find a nuke disk that has been stolen by a syndie via extraction fulton. /// public Entity? FindExtractedDisk() { var query = EntityQueryEnumerator(); while (query.MoveNext(out var uid, out var comp)) { if (comp.Extracted) return (uid, comp); } return null; } /// /// Find a living nukie mob to give the disk to. /// public EntityUid? FindLivingNukie() { var query = EntityQueryEnumerator(); while (query.MoveNext(out _, out _, out var comp)) { foreach (var (mindId, _) in comp.AssignedMinds) { if (TryComp(mindId, out var mind) && GetEntity(mind.OriginalOwnedEntity) is {} mob && _mob.IsAlive(mob)) { return mob; } } } return null; } }