]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
refactor nukeops rule a bit (#19792)
authordeltanedas <39013340+deltanedas@users.noreply.github.com>
Sat, 16 Sep 2023 11:48:42 +0000 (12:48 +0100)
committerGitHub <noreply@github.com>
Sat, 16 Sep 2023 11:48:42 +0000 (21:48 +1000)
Co-authored-by: deltanedas <@deltanedas:kde.org>
Content.Server/GameTicking/Rules/Components/NukeopsRuleComponent.cs
Content.Server/GameTicking/Rules/NukeopsRuleSystem.cs
Resources/Locale/en-US/game-ticking/game-presets/preset-nukeops.ftl

index 8795bf1950bf4b2a78419bddfa5341dd8e61d64f..760b684e1ade604b227c2e2f874575d4f5b80b99 100644 (file)
@@ -154,11 +154,10 @@ public sealed partial class NukeopsRuleComponent : Component
 
     /// <summary>
     ///     Players who played as an operative at some point in the round.
-    ///     Stores the session as well as the entity name
+    ///     Stores the mind as well as the entity name
     /// </summary>
-    /// todo: don't store sessions, dingus
     [DataField("operativePlayers")]
-    public Dictionary<string, ICommonSession> OperativePlayers = new();
+    public Dictionary<string, EntityUid> OperativePlayers = new();
 
     [DataField("faction", customTypeSerializer: typeof(PrototypeIdSerializer<NpcFactionPrototype>), required: true)]
     public string Faction = default!;
index 20d0871448c9d47565d75d137c2b761871eb2107..4787b7d7dca9e501614ffcb87b27149814a2f235 100644 (file)
@@ -55,29 +55,29 @@ namespace Content.Server.GameTicking.Rules;
 
 public sealed class NukeopsRuleSystem : GameRuleSystem<NukeopsRuleComponent>
 {
+    [Dependency] private readonly ChatSystem _chat = default!;
+    [Dependency] private readonly EmergencyShuttleSystem _emergency = default!;
+    [Dependency] private readonly HumanoidAppearanceSystem _humanoid = default!;
+    [Dependency] private readonly IChatManager _chatManager = default!;
+    [Dependency] private readonly IGameTiming _gameTiming = default!;
+    [Dependency] private readonly IMapManager _mapManager = default!;
+    [Dependency] private readonly IPlayerManager _playerManager = default!;
     [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
     [Dependency] private readonly IRobustRandom _random = default!;
     [Dependency] private readonly IServerPreferencesManager _prefs = default!;
-    [Dependency] private readonly IChatManager _chatManager = default!;
-    [Dependency] private readonly IMapManager _mapManager = default!;
-    [Dependency] private readonly IPlayerManager _playerSystem = default!;
-    [Dependency] private readonly EmergencyShuttleSystem _emergency = default!;
+    [Dependency] private readonly MapLoaderSystem _map = default!;
+    [Dependency] private readonly MetaDataSystem _metaData = default!;
+    [Dependency] private readonly MindSystem _mind = default!;
     [Dependency] private readonly NpcFactionSystem _npcFaction = default!;
-    [Dependency] private readonly HumanoidAppearanceSystem _humanoidSystem = default!;
-    [Dependency] private readonly StationSpawningSystem _stationSpawningSystem = default!;
+    [Dependency] private readonly PopupSystem _popupSystem = default!;
     [Dependency] private readonly RoundEndSystem _roundEndSystem = default!;
-    [Dependency] private readonly SharedAudioSystem _audioSystem = default!;
-    [Dependency] private readonly MapLoaderSystem _map = default!;
-    [Dependency] private readonly ShuttleSystem _shuttle = default!;
-    [Dependency] private readonly MindSystem _mindSystem = default!;
+    [Dependency] private readonly SharedAudioSystem _audio = default!;
     [Dependency] private readonly SharedRoleSystem _roles = default!;
-    [Dependency] private readonly MetaDataSystem _metaData = default!;
-    [Dependency] private readonly IGameTiming _gameTiming = default!;
-    [Dependency] private readonly ChatSystem _chatSystem = default!;
-    [Dependency] private readonly StoreSystem _storeSystem = default!;
+    [Dependency] private readonly ShuttleSystem _shuttle = default!;
+    [Dependency] private readonly StationSpawningSystem _stationSpawning = default!;
+    [Dependency] private readonly StoreSystem _store = default!;
     [Dependency] private readonly TagSystem _tag = default!;
-    [Dependency] private readonly PopupSystem _popupSystem = default!;
-    [Dependency] private readonly WarDeclaratorSystem _warDeclaratorSystem = default!;
+    [Dependency] private readonly WarDeclaratorSystem _warDeclarator = default!;
 
     [ValidatePrototypeId<CurrencyPrototype>]
     private const string TelecrystalCurrencyPrototype = "Telecrystal";
@@ -122,7 +122,7 @@ public sealed class NukeopsRuleSystem : GameRuleSystem<NukeopsRuleComponent>
             if (!GameTicker.IsGameRuleAdded(ruleEnt, gameRule))
                 continue;
 
-            var found = nukeops.OperativePlayers.Values.Any(v => v.AttachedEntity == opUid);
+            var found = nukeops.OperativePlayers.Values.Any(v => v == opUid);
             if (found)
             {
                 comps = (nukeops, gameRule);
@@ -193,9 +193,9 @@ public sealed class NukeopsRuleSystem : GameRuleSystem<NukeopsRuleComponent>
 
         var nukieRule = comps.Value.Item1;
         nukieRule.WarDeclaredTime = _gameTiming.CurTime;
-        _chatSystem.DispatchGlobalAnnouncement(msg, title, announcementSound: announcementSound, colorOverride: colorOverride);
+        _chat.DispatchGlobalAnnouncement(msg, title, announcementSound: announcementSound, colorOverride: colorOverride);
         DistributeExtraTC(nukieRule);
-        _warDeclaratorSystem.RefreshAllUI(comps.Value.Item1, comps.Value.Item2);
+        _warDeclarator.RefreshAllUI(comps.Value.Item1, comps.Value.Item2);
     }
 
     private void DistributeExtraTC(NukeopsRuleComponent nukieRule)
@@ -212,7 +212,7 @@ public sealed class NukeopsRuleSystem : GameRuleSystem<NukeopsRuleComponent>
             if (Transform(uid).MapID != Transform(nukieRule.NukieOutpost.Value).MapID) // Will receive bonus TC only on their start outpost
                 continue;
 
-            _storeSystem.TryAddCurrency(new () { { TelecrystalCurrencyPrototype, nukieRule.WarTCAmountPerNukie } }, uid, component);
+            _store.TryAddCurrency(new () { { TelecrystalCurrencyPrototype, nukieRule.WarTCAmountPerNukie } }, uid, component);
 
             var msg = Loc.GetString("store-currency-war-boost-given", ("target", uid));
             _popupSystem.PopupEntity(msg, uid);
@@ -228,13 +228,11 @@ public sealed class NukeopsRuleSystem : GameRuleSystem<NukeopsRuleComponent>
                 continue;
 
             // If entity has a prior mind attached, add them to the players list.
-            if (!_mindSystem.TryGetMind(uid, out _, out var mind))
+            if (!_mind.TryGetMind(uid, out var mind, out _))
                 continue;
 
-            var session = mind?.Session;
             var name = MetaData(uid).EntityName;
-            if (session != null)
-                nukeops.OperativePlayers.Add(name, session);
+            nukeops.OperativePlayers.Add(name, mind);
         }
     }
 
@@ -345,7 +343,7 @@ public sealed class NukeopsRuleSystem : GameRuleSystem<NukeopsRuleComponent>
         while (query.MoveNext(out _, out var nukeops, out var actor))
         {
             _chatManager.DispatchServerMessage(actor.PlayerSession, Loc.GetString("nukeops-welcome", ("station", component.TargetStation.Value)));
-            _audioSystem.PlayGlobal(nukeops.GreetSoundNotification, actor.PlayerSession);
+            _audio.PlayGlobal(nukeops.GreetSoundNotification, actor.PlayerSession);
             filter.AddPlayer(actor.PlayerSession);
         }
     }
@@ -393,14 +391,28 @@ public sealed class NukeopsRuleSystem : GameRuleSystem<NukeopsRuleComponent>
         }
 
         var allAlive = true;
-        foreach (var (_, state) in EntityQuery<NukeOperativeComponent, MobStateComponent>())
+        var mindQuery = GetEntityQuery<MindComponent>();
+        var mobStateQuery = GetEntityQuery<MobStateComponent>();
+        foreach (var (_, mindId) in component.OperativePlayers)
         {
-            if (state.CurrentState is MobState.Alive)
+            // mind got deleted somehow so ignore it
+            if (!mindQuery.TryGetComponent(mindId, out var mind))
                 continue;
 
+            // check if player got gibbed or ghosted or something - count as dead
+            if (mind.OwnedEntity != null &&
+                // if the player somehow isn't a mob anymore that also counts as dead
+                mobStateQuery.TryGetComponent(mind.OwnedEntity.Value, out var mobState) &&
+                // have to be alive, not crit or dead
+                mobState.CurrentState is MobState.Alive)
+            {
+                continue;
+            }
+
             allAlive = false;
             break;
         }
+
         // If all nuke ops were alive at the end of the round,
         // the nuke ops win. This is to prevent people from
         // running away the moment nuke ops appear.
@@ -443,6 +455,7 @@ public sealed class NukeopsRuleSystem : GameRuleSystem<NukeopsRuleComponent>
 
     private void OnRoundEndText(RoundEndTextAppendEvent ev)
     {
+        var mindQuery = GetEntityQuery<MindComponent>();
         foreach (var nukeops in EntityQuery<NukeopsRuleComponent>())
         {
             var winText = Loc.GetString($"nukeops-{nukeops.WinType.ToString().ToLower()}");
@@ -457,10 +470,16 @@ public sealed class NukeopsRuleSystem : GameRuleSystem<NukeopsRuleComponent>
             }
 
             ev.AddLine(Loc.GetString("nukeops-list-start"));
-            foreach (var (name, session) in nukeops.OperativePlayers)
+            foreach (var (name, mindId) in nukeops.OperativePlayers)
             {
-                var listing = Loc.GetString("nukeops-list-name", ("name", name), ("user", session.Name));
-                ev.AddLine(listing);
+                if (mindQuery.TryGetComponent(mindId, out var mind) && mind.Session != null)
+                {
+                    ev.AddLine(Loc.GetString("nukeops-list-name-user", ("name", name), ("user", mind.Session.Name)));
+                }
+                else
+                {
+                    ev.AddLine(Loc.GetString("nukeops-list-name", ("name", name)));
+                }
             }
         }
     }
@@ -548,7 +567,7 @@ public sealed class NukeopsRuleSystem : GameRuleSystem<NukeopsRuleComponent>
 
     private void OnMobStateChanged(EntityUid uid, NukeOperativeComponent component, MobStateChangedEvent ev)
     {
-        if(ev.NewMobState == MobState.Dead)
+        if (ev.NewMobState == MobState.Dead)
             CheckRoundShouldEnd();
     }
 
@@ -601,7 +620,7 @@ public sealed class NukeopsRuleSystem : GameRuleSystem<NukeopsRuleComponent>
                 }
             }
 
-            var numNukies = MathHelper.Clamp(_playerSystem.PlayerCount / playersPerOperative, 1, maxOperatives);
+            var numNukies = MathHelper.Clamp(_playerManager.PlayerCount / playersPerOperative, 1, maxOperatives);
 
             for (var i = 0; i < numNukies; i++)
             {
@@ -693,11 +712,14 @@ public sealed class NukeopsRuleSystem : GameRuleSystem<NukeopsRuleComponent>
             {
                 ev.PlayerPool.Remove(session);
                 GameTicker.PlayerJoinGame(session);
+
+                if (!_mind.TryGetMind(session, out var mind, out _))
+                    continue;
+
                 var name = session.AttachedEntity == null
                     ? string.Empty
-                    : MetaData(session.AttachedEntity.Value).EntityName;
-                // TODO: Fix this being able to have duplicates
-                nukeops.OperativePlayers[name] = session;
+                    : Name(session.AttachedEntity.Value);
+                nukeops.OperativePlayers[name] = mind;
             }
         }
     }
@@ -733,7 +755,7 @@ public sealed class NukeopsRuleSystem : GameRuleSystem<NukeopsRuleComponent>
 
     private void OnMindAdded(EntityUid uid, NukeOperativeComponent component, MindAddedMessage args)
     {
-        if (!_mindSystem.TryGetMind(uid, out var mindId, out var mind))
+        if (!_mind.TryGetMind(uid, out var mindId, out var mind))
             return;
 
         foreach (var (nukeops, gameRule) in EntityQuery<NukeopsRuleComponent, GameRuleComponent>())
@@ -748,13 +770,11 @@ public sealed class NukeopsRuleSystem : GameRuleSystem<NukeopsRuleComponent>
             if (mind.Session is not { } playerSession)
                 return;
 
-            if (nukeops.OperativePlayers.ContainsValue(playerSession))
+            if (nukeops.OperativePlayers.ContainsValue(mindId))
                 return;
 
-            var name = MetaData(uid).EntityName;
-
-            nukeops.OperativePlayers.Add(name, playerSession);
-            _warDeclaratorSystem.RefreshAllUI(nukeops, gameRule);
+            nukeops.OperativePlayers.Add(Name(uid), mindId);
+            _warDeclarator.RefreshAllUI(nukeops, gameRule);
 
             if (GameTicker.RunLevel != GameRunLevel.InRound)
                 return;
@@ -764,7 +784,7 @@ public sealed class NukeopsRuleSystem : GameRuleSystem<NukeopsRuleComponent>
                 _chatManager.DispatchServerMessage(playerSession, Loc.GetString("nukeops-welcome", ("station", nukeops.TargetStation.Value)));
 
                  // Notificate player about new role assignment
-                 _audioSystem.PlayGlobal(component.GreetSoundNotification, playerSession);
+                 _audio.PlayGlobal(component.GreetSoundNotification, playerSession);
             }
         }
     }
@@ -866,11 +886,11 @@ public sealed class NukeopsRuleSystem : GameRuleSystem<NukeopsRuleComponent>
 
         if (profile != null)
         {
-            _humanoidSystem.LoadProfile(mob, profile);
+            _humanoid.LoadProfile(mob, profile);
         }
 
         if (component.StartingGearPrototypes.TryGetValue(gear, out var gearPrototype))
-            _stationSpawningSystem.EquipStartingGear(mob, gearPrototype, profile);
+            _stationSpawning.EquipStartingGear(mob, gearPrototype, profile);
 
         _npcFaction.RemoveFaction(mob, "NanoTrasen", false);
         _npcFaction.AddFaction(mob, "Syndicate");
@@ -885,7 +905,7 @@ public sealed class NukeopsRuleSystem : GameRuleSystem<NukeopsRuleComponent>
         var spawns = new List<EntityCoordinates>();
 
         // Forgive me for hardcoding prototypes
-        foreach (var (_, meta, xform) in EntityManager.EntityQuery<SpawnPointComponent, MetaDataComponent, TransformComponent>(true))
+        foreach (var (_, meta, xform) in EntityQuery<SpawnPointComponent, MetaDataComponent, TransformComponent>(true))
         {
             if (meta.EntityPrototype?.ID != component.SpawnPointPrototype)
                 continue;
@@ -899,7 +919,7 @@ public sealed class NukeopsRuleSystem : GameRuleSystem<NukeopsRuleComponent>
 
         if (spawns.Count == 0)
         {
-            spawns.Add(EntityManager.GetComponent<TransformComponent>(outpostUid).Coordinates);
+            spawns.Add(Transform(outpostUid).Coordinates);
             Logger.WarningS("nukies", $"Fell back to default spawn for nukies!");
         }
 
@@ -917,17 +937,17 @@ public sealed class NukeopsRuleSystem : GameRuleSystem<NukeopsRuleComponent>
                     species = _prototypeManager.Index<SpeciesPrototype>(SharedHumanoidAppearanceSystem.DefaultSpecies);
                 }
 
-                var mob = EntityManager.SpawnEntity(species.Prototype, _random.Pick(spawns));
+                var mob = Spawn(species.Prototype, _random.Pick(spawns));
                 SetupOperativeEntity(mob, spawnDetails.Name, spawnDetails.Gear, profile, component);
-                var newMind = _mindSystem.CreateMind(session.UserId, spawnDetails.Name);
-                _mindSystem.SetUserId(newMind, session.UserId);
+                var newMind = _mind.CreateMind(session.UserId, spawnDetails.Name);
+                _mind.SetUserId(newMind, session.UserId);
                 _roles.MindAddRole(newMind, new NukeopsRoleComponent { PrototypeId = spawnDetails.Role });
 
-                _mindSystem.TransferTo(newMind, mob);
+                _mind.TransferTo(newMind, mob);
             }
             else if (addSpawnPoints)
             {
-                var spawnPoint = EntityManager.SpawnEntity(component.GhostSpawnPointProto, _random.Pick(spawns));
+                var spawnPoint = Spawn(component.GhostSpawnPointProto, _random.Pick(spawns));
                 var ghostRole = EnsureComp<GhostRoleComponent>(spawnPoint);
                 EnsureComp<GhostRoleMobSpawnerComponent>(spawnPoint);
                 ghostRole.RoleName = Loc.GetString(nukeOpsAntag.Name);
@@ -955,7 +975,7 @@ public sealed class NukeopsRuleSystem : GameRuleSystem<NukeopsRuleComponent>
         var playersPerOperative = component.PlayersPerOperative;
         var maxOperatives = component.MaxOperatives;
 
-        var playerPool = _playerSystem.ServerSessions.ToList();
+        var playerPool = _playerManager.ServerSessions.ToList();
         var numNukies = MathHelper.Clamp(playerPool.Count / playersPerOperative, 1, maxOperatives);
 
         var operatives = new List<IPlayerSession>();
@@ -1050,7 +1070,7 @@ public sealed class NukeopsRuleSystem : GameRuleSystem<NukeopsRuleComponent>
                 nukeops.LeftOutpost = true;
 
                 if (TryGetRuleFromGrid(gridUid.Value, out var comps))
-                    _warDeclaratorSystem.RefreshAllUI(comps.Value.Item1, comps.Value.Item2);
+                    _warDeclarator.RefreshAllUI(comps.Value.Item1, comps.Value.Item2);
             }
         }
     }
@@ -1096,13 +1116,13 @@ public sealed class NukeopsRuleSystem : GameRuleSystem<NukeopsRuleComponent>
         var query = EntityQuery<NukeOperativeComponent, MindContainerComponent, MetaDataComponent>(true);
         foreach (var (_, mindComp, metaData) in query)
         {
-            if (!mindComp.HasMind || !_mindSystem.TryGetSession(mindComp.Mind.Value, out var session))
+            if (!mindComp.HasMind)
                 continue;
-            component.OperativePlayers.Add(metaData.EntityName, session);
+
+            component.OperativePlayers.Add(metaData.EntityName, mindComp.Mind.Value);
         }
 
         if (GameTicker.RunLevel == GameRunLevel.InRound)
             SpawnOperativesForGhostRoles(uid, component);
     }
-
 }
index 09ee01a8f4d1407ed4e763ad4ff7326928b935a3..686468815722b2a0d0390eb3fa905986a91c6e07 100644 (file)
@@ -24,7 +24,8 @@ nukeops-cond-somenukiesalive = Some nuclear operatives died.
 nukeops-cond-allnukiesalive = No nuclear operatives died.
 
 nukeops-list-start = The operatives were:
-nukeops-list-name = - [color=White]{$name}[/color] ([color=gray]{$user}[/color])
+nukeops-list-name = - [color=White]{$name}[/color]
+nukeops-list-name-user = - [color=White]{$name}[/color] ([color=gray]{$user}[/color])
 nukeops-not-enough-ready-players = Not enough players readied up for the game! There were {$readyPlayersCount} players readied up out of {$minimumPlayers} needed. Can't start Nukeops.
 nukeops-no-one-ready = No players readied up! Can't start Nukeops.