Oops, All Captains! (#14943)
This commit is contained in:
73
Content.Server/GameTicking/Rules/AllCaptainsRuleSystem.cs
Normal file
73
Content.Server/GameTicking/Rules/AllCaptainsRuleSystem.cs
Normal 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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
- type: gameRule
|
||||
id: AllCaptains
|
||||
config:
|
||||
!type:GenericGameRuleConfiguration
|
||||
id: AllCaptains
|
||||
|
||||
- type: gameRule
|
||||
id: DeathMatch
|
||||
config:
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -5,3 +5,4 @@
|
||||
Nukeops: 0.25
|
||||
Traitor: 0.75
|
||||
Zombie: 0.05
|
||||
OopsAllCaptains: 0.20
|
||||
|
||||
Reference in New Issue
Block a user