using Content.Server.NPC.Components; using Content.Server.RoundEnd; using Content.Server.StationEvents.Events; using Content.Shared.Dataset; using Content.Shared.Roles; using Robust.Shared.Map; using Robust.Shared.Prototypes; using Robust.Shared.Serialization.TypeSerializers.Implementations; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; using Robust.Shared.Utility; namespace Content.Server.GameTicking.Rules.Components; [RegisterComponent, Access(typeof(NukeopsRuleSystem), typeof(LoneOpsSpawnRule))] public sealed partial class NukeopsRuleComponent : Component { // TODO Replace with GameRuleComponent.minPlayers /// /// The minimum needed amount of players /// [DataField] public int MinPlayers = 20; /// /// This INCLUDES the operatives. So a value of 3 is satisfied by 2 players & 1 operative /// [DataField] public int PlayersPerOperative = 10; [DataField] public int MaxOps = 5; /// /// What will happen if all of the nuclear operatives will die. Used by LoneOpsSpawn event. /// [DataField] public RoundEndBehavior RoundEndBehavior = RoundEndBehavior.ShuttleCall; /// /// Text for shuttle call if RoundEndBehavior is ShuttleCall. /// [DataField] public string RoundEndTextSender = "comms-console-announcement-title-centcom"; /// /// Text for shuttle call if RoundEndBehavior is ShuttleCall. /// [DataField] public string RoundEndTextShuttleCall = "nuke-ops-no-more-threat-announcement-shuttle-call"; /// /// Text for announcement if RoundEndBehavior is ShuttleCall. Used if shuttle is already called /// [DataField] public string RoundEndTextAnnouncement = "nuke-ops-no-more-threat-announcement"; /// /// Time to emergency shuttle to arrive if RoundEndBehavior is ShuttleCall. /// [DataField] public TimeSpan EvacShuttleTime = TimeSpan.FromMinutes(3); /// /// Whether or not to spawn the nuclear operative outpost. Used by LoneOpsSpawn event. /// [DataField] public bool SpawnOutpost = true; /// /// Whether or not nukie left their outpost /// [DataField] public bool LeftOutpost; /// /// Enables opportunity to get extra TC for war declaration /// [DataField] public bool CanEnableWarOps = true; /// /// Indicates time when war has been declared, null if not declared /// [DataField(customTypeSerializer: typeof(TimeOffsetSerializer))] public TimeSpan? WarDeclaredTime; /// /// This amount of TC will be given to each nukie /// [DataField] public int WarTCAmountPerNukie = 40; /// /// Time allowed for declaration of war /// [DataField("warDeclarationDelay")] public TimeSpan WarDeclarationDelay = TimeSpan.FromMinutes(6); /// /// Delay between war declaration and nuke ops arrival on station map. Gives crew time to prepare /// [DataField] public TimeSpan? WarNukieArriveDelay = TimeSpan.FromMinutes(15); /// /// Minimal operatives count for war declaration /// [DataField] public int WarDeclarationMinOps = 4; [DataField] public EntProtoId SpawnPointProto = "SpawnPointNukies"; [DataField] public EntProtoId GhostSpawnPointProto = "SpawnPointGhostNukeOperative"; [DataField] public ProtoId CommanderRoleProto = "NukeopsCommander"; [DataField] public ProtoId OperativeRoleProto = "Nukeops"; [DataField] public ProtoId MedicRoleProto = "NukeopsMedic"; [DataField] public ProtoId CommanderStartGearProto = "SyndicateCommanderGearFull"; [DataField] public ProtoId MedicStartGearProto = "SyndicateOperativeMedicFull"; [DataField] public ProtoId OperativeStartGearProto = "SyndicateOperativeGearFull"; [DataField(customTypeSerializer: typeof(PrototypeIdSerializer))] public string EliteNames = "SyndicateNamesElite"; [DataField] public string OperationName = "Test Operation"; [DataField(customTypeSerializer: typeof(PrototypeIdSerializer))] public string NormalNames = "SyndicateNamesNormal"; [DataField(customTypeSerializer: typeof(ResPathSerializer))] public ResPath OutpostMap = new("/Maps/nukieplanet.yml"); [DataField(customTypeSerializer: typeof(ResPathSerializer))] public ResPath ShuttleMap = new("/Maps/infiltrator.yml"); [DataField] public WinType WinType = WinType.Neutral; [DataField] public List WinConditions = new (); public MapId? NukiePlanet; // TODO: use components, don't just cache entity UIDs // There have been (and probably still are) bugs where these refer to deleted entities from old rounds. public EntityUid? NukieOutpost; public EntityUid? NukieShuttle; public EntityUid? TargetStation; /// /// Cached starting gear prototypes. /// [DataField] public Dictionary StartingGearPrototypes = new (); /// /// Cached operator name prototypes. /// [DataField] public Dictionary> OperativeNames = new(); /// /// Data to be used in for an operative once the Mind has been added. /// [DataField] public Dictionary OperativeMindPendingData = new(); /// /// Players who played as an operative at some point in the round. /// Stores the mind as well as the entity name /// [DataField] public Dictionary OperativePlayers = new(); [DataField(required: true)] public ProtoId Faction = default!; } public enum WinType : byte { /// /// Operative major win. This means they nuked the station. /// OpsMajor, /// /// Minor win. All nukies were alive at the end of the round. /// Alternatively, some nukies were alive, but the disk was left behind. /// OpsMinor, /// /// Neutral win. The nuke exploded, but on the wrong station. /// Neutral, /// /// Crew minor win. The nuclear authentication disk escaped on the shuttle, /// but some nukies were alive. /// CrewMinor, /// /// Crew major win. This means they either killed all nukies, /// or the bomb exploded too far away from the station, or on the nukie moon. /// CrewMajor } public enum WinCondition : byte { NukeExplodedOnCorrectStation, NukeExplodedOnNukieOutpost, NukeExplodedOnIncorrectLocation, NukeActiveInStation, NukeActiveAtCentCom, NukeDiskOnCentCom, NukeDiskNotOnCentCom, NukiesAbandoned, AllNukiesDead, SomeNukiesAlive, AllNukiesAlive }