]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Oops, All Captains! (#14943)
authorSkye <22365940+Skyedra@users.noreply.github.com>
Thu, 30 Mar 2023 23:54:38 +0000 (16:54 -0700)
committerGitHub <noreply@github.com>
Thu, 30 Mar 2023 23:54:38 +0000 (18:54 -0500)
Content.Server/GameTicking/Rules/AllCaptainsRuleSystem.cs [new file with mode: 0644]
Content.Server/GameTicking/Rules/TraitorRuleSystem.cs
Content.Server/Players/PlayTimeTracking/PlayTimeTrackingSystem.cs
Content.Server/Station/Components/StationJobsComponent.cs
Content.Server/Station/Systems/StationJobsSystem.cs
Resources/Prototypes/GameRules/roundstart.yml
Resources/Prototypes/game_presets.yml
Resources/Prototypes/secret_weights.yml

diff --git a/Content.Server/GameTicking/Rules/AllCaptainsRuleSystem.cs b/Content.Server/GameTicking/Rules/AllCaptainsRuleSystem.cs
new file mode 100644 (file)
index 0000000..6d755af
--- /dev/null
@@ -0,0 +1,73 @@
+using System.Linq;
+using Content.Server.GameTicking.Presets;
+using Content.Server.GameTicking.Rules.Configurations;
+using Content.Server.Station.Components;
+using Content.Shared.Random;
+using Content.Shared.Random.Helpers;
+using Robust.Shared.Map;
+using Robust.Shared.Prototypes;
+using Robust.Shared.Random;
+using Robust.Shared.Configuration;
+using Content.Shared.CCVar;
+
+namespace Content.Server.GameTicking.Rules;
+
+public sealed class AllCaptainsRuleSystem : GameRuleSystem
+{
+    [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
+    [Dependency] private readonly IRobustRandom _random = default!;
+    [Dependency] private readonly GameTicker _ticker = default!;
+    [Dependency] private readonly IConfigurationManager _cfg = default!;
+
+    public override string Prototype => "AllCaptains";
+
+    private EntityUid holdJobs; // dunno if there should only be one reference like this because I'm a ss14 noob but hey  it's only gotta work one day :P
+
+    public override void Added()
+    {
+    }
+
+    public override void Started()
+    {
+        // temporarily disable role timers -- super hacky way workaround for client to be aware that role timers aren't required
+        // without having to set up some kind of replication
+        _cfg.SetCVar(CCVars.GameRoleTimers, false);
+    }
+
+    public override void Ended()
+    {
+        _cfg.SetCVar(CCVars.GameRoleTimers, true);
+    }
+
+    public StationJobsComponent GetJobs(EntityUid station)
+    {
+        if (!holdJobs.IsValid() || !HasComp<StationJobsComponent>(holdJobs)) // this doesn't check station parameter since all captains mode is the same for all stations.
+        {
+            holdJobs = Spawn(null, new EntityCoordinates(station, Vector2.Zero));
+            var stationJobs = AddComp<StationJobsComponent>(holdJobs);
+
+            // Create captains-only specific job list
+            var mapJobList = new Dictionary<string, List<int?>> {{"Captain", new List<int?>{int.MaxValue, int.MaxValue}}};
+
+            stationJobs.RoundStartTotalJobs = mapJobList.Values.Where(x => x[0] is not null && x[0] > 0).Sum(x => x[0]!.Value);
+            stationJobs.MidRoundTotalJobs = mapJobList.Values.Where(x => x[1] is not null && x[1] > 0).Sum(x => x[1]!.Value);
+            stationJobs.TotalJobs = stationJobs.MidRoundTotalJobs;
+            stationJobs.JobList = mapJobList.ToDictionary(x => x.Key, x =>
+            {
+                if (x.Value[1] <= -1)
+                    return null;
+                return (uint?) x.Value[1];
+            });
+            stationJobs.RoundStartJobList = mapJobList.ToDictionary(x => x.Key, x =>
+            {
+                if (x.Value[0] <= -1)
+                    return null;
+                return (uint?) x.Value[0];
+            });
+            stationJobs.OverflowJobs = new HashSet<string>{"Captain"}; //stationData.StationConfig.OverflowJobs.ToHashSet();
+        }
+
+        return Comp<StationJobsComponent>(holdJobs);
+    }
+
+}
index e005357f1f43093549b405cdcdf87288b18f8dee..02969d685245d2562cd9908997c016a8a1141930 100644 (file)
@@ -36,6 +36,7 @@ public sealed class TraitorRuleSystem : GameRuleSystem
     [Dependency] private readonly MobStateSystem _mobStateSystem = default!;
     [Dependency] private readonly UplinkSystem _uplink = default!;
     [Dependency] private readonly SharedAudioSystem _audioSystem = default!;
+    [Dependency] private readonly AllCaptainsRuleSystem _allCaptainsRule = default!;
 
     private ISawmill _sawmill = default!;
 
@@ -178,7 +179,8 @@ public sealed class TraitorRuleSystem : GameRuleSystem
         foreach (var player in candidates.Keys)
         {
             // Role prevents antag.
-            if (!(player.Data.ContentData()?.Mind?.AllRoles.All(role => role is not Job { CanBeAntag: false }) ?? false))
+            if (!(_allCaptainsRule != null && _allCaptainsRule.RuleStarted) && // all captains mode lets some of the captains be traitors :3
+                !(player.Data.ContentData()?.Mind?.AllRoles.All(role => role is not Job { CanBeAntag: false }) ?? false))
             {
                 continue;
             }
@@ -296,7 +298,8 @@ public sealed class TraitorRuleSystem : GameRuleSystem
         if (ev.JobId == null || !_prototypeManager.TryIndex<JobPrototype>(ev.JobId, out var job))
             return;
 
-        if (!job.CanBeAntag)
+        if (!job.CanBeAntag &&
+            !(_allCaptainsRule != null && _allCaptainsRule.RuleStarted)) // all captains mode lets some of the captains be traitors :3
             return;
 
         // Before the announcement is made, late-joiners are considered the same as players who readied.
index 1ff9eeee49ca5eddab76f1c956e6e488b383b5c4..a3c3b7d3c7442ed483457b36c75e5385c7484a83 100644 (file)
@@ -2,6 +2,7 @@ using System.Linq;
 using Content.Server.Afk;
 using Content.Server.Afk.Events;
 using Content.Server.GameTicking;
+using Content.Server.GameTicking.Rules;
 using Content.Server.Roles;
 using Content.Shared.CCVar;
 using Content.Shared.GameTicking;
@@ -28,6 +29,7 @@ public sealed class PlayTimeTrackingSystem : EntitySystem
     [Dependency] private readonly IPrototypeManager _prototypes = default!;
     [Dependency] private readonly IConfigurationManager _cfg = default!;
     [Dependency] private readonly PlayTimeTrackingManager _tracking = default!;
+    [Dependency] private readonly AllCaptainsRuleSystem _allCaptainsRule = default!;
 
     public override void Initialize()
     {
@@ -159,7 +161,8 @@ public sealed class PlayTimeTrackingSystem : EntitySystem
     {
         if (!_prototypes.TryIndex<JobPrototype>(role, out var job) ||
             job.Requirements == null ||
-            !_cfg.GetCVar(CCVars.GameRoleTimers))
+            !_cfg.GetCVar(CCVars.GameRoleTimers) ||
+            (_allCaptainsRule != null && _allCaptainsRule.RuleStarted))
             return true;
 
         var playTimes = _tracking.GetTrackerTimes(player);
@@ -170,7 +173,7 @@ public sealed class PlayTimeTrackingSystem : EntitySystem
     public HashSet<string> GetDisallowedJobs(IPlayerSession player)
     {
         var roles = new HashSet<string>();
-        if (!_cfg.GetCVar(CCVars.GameRoleTimers))
+        if (!_cfg.GetCVar(CCVars.GameRoleTimers) || (_allCaptainsRule != null && _allCaptainsRule.RuleStarted))
             return roles;
 
         var playTimes = _tracking.GetTrackerTimes(player);
@@ -197,7 +200,7 @@ public sealed class PlayTimeTrackingSystem : EntitySystem
 
     public void RemoveDisallowedJobs(NetUserId userId, ref List<string> jobs)
     {
-        if (!_cfg.GetCVar(CCVars.GameRoleTimers))
+        if (!_cfg.GetCVar(CCVars.GameRoleTimers) || (_allCaptainsRule != null && _allCaptainsRule.RuleStarted))
             return;
 
         var player = _playerManager.GetSessionByUserId(userId);
index 42295fcca7ea9f37c19f812d35842eb68ca831a2..100fcc1aef413ffc65bf8308f8e02df61e303a84 100644 (file)
@@ -1,4 +1,5 @@
-using Content.Server.Station.Systems;
+using Content.Server.GameTicking.Rules;
+using Content.Server.Station.Systems;
 using Content.Shared.Roles;
 using JetBrains.Annotations;
 using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Dictionary;
@@ -9,7 +10,7 @@ namespace Content.Server.Station.Components;
 /// <summary>
 /// Stores information about a station's job selection.
 /// </summary>
-[RegisterComponent, Access(typeof(StationJobsSystem)), PublicAPI]
+[RegisterComponent, Access(typeof(StationJobsSystem), typeof(AllCaptainsRuleSystem)), PublicAPI]
 public sealed class StationJobsComponent : Component
 {
     /// <summary>
index 268d50739d23255eefdf1e11ecac05068d8e41cd..12f8611f436583d3e1e05b7e315eb9f90c4fbf37 100644 (file)
@@ -1,6 +1,7 @@
 using System.Diagnostics.CodeAnalysis;
 using System.Linq;
 using Content.Server.GameTicking;
+using Content.Server.GameTicking.Rules;
 using Content.Server.Station.Components;
 using Content.Shared.CCVar;
 using Content.Shared.GameTicking;
@@ -25,6 +26,7 @@ public sealed partial class StationJobsSystem : EntitySystem
     [Dependency] private readonly GameTicker _gameTicker = default!;
     [Dependency] private readonly StationSystem _stationSystem = default!;
     [Dependency] private readonly IPlayerManager _playerManager = default!;
+    [Dependency] private readonly AllCaptainsRuleSystem _allCaptainsRule = default!;
 
     /// <inheritdoc/>
     public override void Initialize()
@@ -33,6 +35,8 @@ public sealed partial class StationJobsSystem : EntitySystem
         SubscribeLocalEvent<StationJobsComponent, StationRenamedEvent>(OnStationRenamed);
         SubscribeLocalEvent<StationJobsComponent, ComponentShutdown>(OnStationDeletion);
         SubscribeLocalEvent<PlayerJoinedLobbyEvent>(OnPlayerJoinedLobby);
+        SubscribeLocalEvent<GameRuleStartedEvent>(OnGameRuleStarted);
+        SubscribeLocalEvent<GameRuleEndedEvent>(OnGameRuleEnded);
         _configurationManager.OnValueChanged(CCVars.GameDisallowLateJoins, _ => UpdateJobsAvailable(), true);
     }
 
@@ -136,6 +140,9 @@ public sealed partial class StationJobsSystem : EntitySystem
 
         var jobList = stationJobs.JobList;
 
+        if (_allCaptainsRule != null && _allCaptainsRule.RuleStarted)
+           jobList = _allCaptainsRule.GetJobs(station).JobList;
+
         // This should:
         // - Return true when zero slots are added/removed.
         // - Return true when you add.
@@ -214,6 +221,11 @@ public sealed partial class StationJobsSystem : EntitySystem
 
         var jobList = stationJobs.JobList;
 
+        // If all captains mode, override job list with the allcaptains job list -- prevents modifying the "real" job list
+        // in case mode changes later.
+        if (_allCaptainsRule != null && _allCaptainsRule.RuleStarted)
+           jobList = _allCaptainsRule.GetJobs(station).JobList;
+
         switch (jobList.ContainsKey(jobPrototypeId))
         {
             case false:
@@ -313,7 +325,11 @@ public sealed partial class StationJobsSystem : EntitySystem
         if (!Resolve(station, ref stationJobs))
             throw new ArgumentException("Tried to use a non-station entity as a station!", nameof(station));
 
-        if (stationJobs.JobList.TryGetValue(jobPrototypeId, out var job))
+        var jobList = stationJobs.JobList;
+        if (_allCaptainsRule != null && _allCaptainsRule.RuleStarted)
+           jobList = _allCaptainsRule.GetJobs(station).JobList;
+
+        if (jobList.TryGetValue(jobPrototypeId, out var job))
         {
             slots = job;
             return true;
@@ -337,6 +353,9 @@ public sealed partial class StationJobsSystem : EntitySystem
         if (!Resolve(station, ref stationJobs))
             throw new ArgumentException("Tried to use a non-station entity as a station!", nameof(station));
 
+        if (_allCaptainsRule != null && _allCaptainsRule.RuleStarted)
+            return _allCaptainsRule.GetJobs(station).JobList.Where(x => x.Value != 0).Select(x => x.Key).ToHashSet();
+
         return stationJobs.JobList.Where(x => x.Value != 0).Select(x => x.Key).ToHashSet();
     }
 
@@ -352,6 +371,9 @@ public sealed partial class StationJobsSystem : EntitySystem
         if (!Resolve(station, ref stationJobs))
             throw new ArgumentException("Tried to use a non-station entity as a station!", nameof(station));
 
+        if (_allCaptainsRule != null && _allCaptainsRule.RuleStarted)
+            return _allCaptainsRule.GetJobs(station).OverflowJobs.ToHashSet();
+
         return stationJobs.OverflowJobs.ToHashSet();
     }
 
@@ -367,6 +389,9 @@ public sealed partial class StationJobsSystem : EntitySystem
         if (!Resolve(station, ref stationJobs))
             throw new ArgumentException("Tried to use a non-station entity as a station!", nameof(station));
 
+        if (_allCaptainsRule != null && _allCaptainsRule.RuleStarted)
+            return _allCaptainsRule.GetJobs(station).JobList;
+
         return stationJobs.JobList;
     }
 
@@ -382,6 +407,9 @@ public sealed partial class StationJobsSystem : EntitySystem
         if (!Resolve(station, ref stationJobs))
             throw new ArgumentException("Tried to use a non-station entity as a station!", nameof(station));
 
+        if (_allCaptainsRule != null && _allCaptainsRule.RuleStarted)
+            return _allCaptainsRule.GetJobs(station).RoundStartJobList;
+
         return stationJobs.RoundStartJobList;
     }
 
@@ -467,6 +495,8 @@ public sealed partial class StationJobsSystem : EntitySystem
         foreach (var station in _stationSystem.Stations)
         {
             var list = Comp<StationJobsComponent>(station).JobList.ToDictionary(x => x.Key, x => x.Value);
+            if (_allCaptainsRule != null && _allCaptainsRule.RuleStarted)
+                list = _allCaptainsRule.GetJobs(station).JobList.ToDictionary(x => x.Key, x => x.Value);
             jobs.Add(station, list);
             stationNames.Add(station, Name(station));
         }
@@ -491,5 +521,17 @@ public sealed partial class StationJobsSystem : EntitySystem
         UpdateJobsAvailable();
     }
 
+    private void OnGameRuleStarted(GameRuleStartedEvent msg)
+    {
+        if (msg.Rule.ID == "AllCaptains")
+            UpdateJobsAvailable();
+    }
+
+    private void OnGameRuleEnded(GameRuleEndedEvent msg)
+    {
+        if (msg.Rule.ID == "AllCaptains")
+            UpdateJobsAvailable();
+    }
+
     #endregion
 }
index 5a62ca270619b50d8d5acdd625b135d60236eaf2..31849e1b596261dd3e93c0a736fce71fcbdfbda1 100644 (file)
@@ -1,3 +1,9 @@
+- type: gameRule
+  id: AllCaptains
+  config:
+    !type:GenericGameRuleConfiguration
+    id: AllCaptains
+
 - type: gameRule
   id: DeathMatch
   config:
index f56452f20be03a6613dde13de1afb988616600f1..f73bafae7be64eb9d97dfab3e571fce3ca76d798 100644 (file)
   rules:
     - Pirates
     - BasicStationEventScheduler
+
+- type: gamePreset
+  id: OopsAllCaptains
+  alias:
+    - captains
+    - captain
+    - onlycaptains
+    - OnlyCaptains
+    - oopsonlycaptains
+    - oopsallcaptains
+    - allcaptains
+    - AllCaptains
+  name: "Oops! All Captains."
+  description: "Look at you.  You're the captain now."
+  showInVote: true
+  rules:
+    - AllCaptains
+    - Traitor
+    - BasicStationEventScheduler
+
index 9c392a1549e649b4688d967f97a4ba8022f1059e..d9378a6dcf1aecc3f8206fe65ec2a8baf658d82e 100644 (file)
@@ -5,3 +5,4 @@
     Nukeops: 0.25
     Traitor: 0.75
     Zombie: 0.05
+    OopsAllCaptains: 0.20