Oops, All Captains! (#14943)

This commit is contained in:
Skye
2023-03-30 16:54:38 -07:00
committed by GitHub
parent b71c8b7ec3
commit 8128759ea8
8 changed files with 157 additions and 8 deletions

View File

@@ -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);
}
}

View 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.

View 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);

View 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>

View 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
}

View File

@@ -1,3 +1,9 @@
- type: gameRule
id: AllCaptains
config:
!type:GenericGameRuleConfiguration
id: AllCaptains
- type: gameRule
id: DeathMatch
config:

View File

@@ -119,3 +119,23 @@
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

View File

@@ -5,3 +5,4 @@
Nukeops: 0.25
Traitor: 0.75
Zombie: 0.05
OopsAllCaptains: 0.20