From f698f49cdc3d927945787f204c409ce277508178 Mon Sep 17 00:00:00 2001 From: SolStar2 <44028047+ewokswagger@users.noreply.github.com> Date: Thu, 28 Nov 2024 22:45:44 -0500 Subject: [PATCH 01/27] Add events for player updating jobs --- .../DeltaV/Station/Events/PlayerJobAddedEvent.cs | 14 ++++++++++++++ .../Station/Events/PlayerJobsRemovedEvent.cs | 16 ++++++++++++++++ .../Station/Systems/StationJobsSystem.cs | 7 ++++++- 3 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 Content.Server/DeltaV/Station/Events/PlayerJobAddedEvent.cs create mode 100644 Content.Server/DeltaV/Station/Events/PlayerJobsRemovedEvent.cs diff --git a/Content.Server/DeltaV/Station/Events/PlayerJobAddedEvent.cs b/Content.Server/DeltaV/Station/Events/PlayerJobAddedEvent.cs new file mode 100644 index 00000000000..8fd0e22ef83 --- /dev/null +++ b/Content.Server/DeltaV/Station/Events/PlayerJobAddedEvent.cs @@ -0,0 +1,14 @@ +using Robust.Shared.Network; + +namespace Content.Server.DeltaV.Station.Events; + +/// +/// Raised on a staion when a job is added to a player +/// +/// Player who recived a job +/// Id of the jobPrototype added +public sealed class PlayerJobAddedEvent(NetUserId netUserId, string jobPrototypeId) : EntityEventArgs +{ + public NetUserId NetUserId = netUserId; + public string? JobPrototypeId = jobPrototypeId; +} diff --git a/Content.Server/DeltaV/Station/Events/PlayerJobsRemovedEvent.cs b/Content.Server/DeltaV/Station/Events/PlayerJobsRemovedEvent.cs new file mode 100644 index 00000000000..4acfcee9239 --- /dev/null +++ b/Content.Server/DeltaV/Station/Events/PlayerJobsRemovedEvent.cs @@ -0,0 +1,16 @@ +using Content.Shared.Roles; +using Robust.Shared.Network; +using Robust.Shared.Prototypes; + +namespace Content.Server.DeltaV.Station.Events; + +/// +/// Raised on a station when a players jobs are removed +/// +/// Player whos jobs were removed +/// Entry in PlayerJobs removed a list of JobPrototypes +public sealed class PlayerJobsRemovedEvent(NetUserId netUserId, List> playerJobs) : EntityEventArgs +{ + public NetUserId NetUserId = netUserId; + public List>? PlayerJobs = playerJobs; +} diff --git a/Content.Server/Station/Systems/StationJobsSystem.cs b/Content.Server/Station/Systems/StationJobsSystem.cs index 91a8b7ade4a..0be0620d0a2 100644 --- a/Content.Server/Station/Systems/StationJobsSystem.cs +++ b/Content.Server/Station/Systems/StationJobsSystem.cs @@ -1,5 +1,6 @@ using System.Diagnostics.CodeAnalysis; using System.Linq; +using Content.Server.DeltaV.Station.Events; // DeltaV using Content.Server.GameTicking; using Content.Server.Station.Components; using Content.Shared.CCVar; @@ -109,6 +110,7 @@ public bool TryAssignJob(EntityUid station, string jobPrototypeId, NetUserId net if (!TryAdjustJobSlot(station, jobPrototypeId, -1, false, false, stationJobs)) return false; + RaiseLocalEvent(station, new PlayerJobAddedEvent(netUserId, jobPrototypeId), false); // DeltaV added AddedPlayerJobsEvent for noCaptainSystem stationJobs.PlayerJobs.TryAdd(netUserId, new()); stationJobs.PlayerJobs[netUserId].Add(jobPrototypeId); return true; @@ -206,7 +208,10 @@ public bool TryRemovePlayerJobs(EntityUid station, { if (!Resolve(station, ref jobsComponent, false)) return false; - + // DeltaV added RemovedPlayerJobsEvent for noCaptainSystem + if (jobsComponent.PlayerJobs.TryGetValue(userId, out var playerJobsEntry)) + RaiseLocalEvent(station, new PlayerJobsRemovedEvent(userId, playerJobsEntry), false); + // DeltaV end added RemovedPlayerJobsEvent for noCaptainSystem return jobsComponent.PlayerJobs.Remove(userId); } From 5d593645e353635a572419fd4a09ebba9a0a9215 Mon Sep 17 00:00:00 2001 From: SolStar2 <44028047+ewokswagger@users.noreply.github.com> Date: Thu, 28 Nov 2024 22:47:15 -0500 Subject: [PATCH 02/27] Add NoCaptainComponent --- .../Station/Components/NoCaptainComponent.cs | 37 +++++++++++++++++++ .../DeltaV/Station/Systems/NoCaptainSystem.cs | 7 ++++ 2 files changed, 44 insertions(+) create mode 100644 Content.Server/DeltaV/Station/Components/NoCaptainComponent.cs create mode 100644 Content.Server/DeltaV/Station/Systems/NoCaptainSystem.cs diff --git a/Content.Server/DeltaV/Station/Components/NoCaptainComponent.cs b/Content.Server/DeltaV/Station/Components/NoCaptainComponent.cs new file mode 100644 index 00000000000..c98cc5f20a7 --- /dev/null +++ b/Content.Server/DeltaV/Station/Components/NoCaptainComponent.cs @@ -0,0 +1,37 @@ +using Content.Server.DeltaV.Station.Systems; + +namespace Content.Server.DeltaV.Station.Components; + +/// +/// Denotes a station has no captain and holds data for automatic ACO systems +/// +[RegisterComponent, Access(typeof(NoCaptainSystem))] +public sealed partial class NoCaptainComponent : Component +{ + /// + /// How long with no captain before an ACO vote is requested + /// + [DataField] + public TimeSpan RequestACOVoteDelay = TimeSpan.FromMinutes(15); + + /// + /// How long after ACO vote is called the spare id cabinet will be unlocked if applicable + /// + [DataField] + public TimeSpan UnlockAADelay = TimeSpan.FromMinutes(5); + + /// + /// Maximum player count that AA should be unlocked for ACO + /// + /// + /// If there are too many players it's likely that there is a sufficient command staffing to render automatic aa approval redundant. + /// + [DataField] + public int UnlockAAPlayerThreshold = 40; + + /// + /// Used to override other conditions and AA will be unlocked after the delay + /// + [DataField] + public bool? UnlockAAOverride = null; +} diff --git a/Content.Server/DeltaV/Station/Systems/NoCaptainSystem.cs b/Content.Server/DeltaV/Station/Systems/NoCaptainSystem.cs new file mode 100644 index 00000000000..e6509ef37b7 --- /dev/null +++ b/Content.Server/DeltaV/Station/Systems/NoCaptainSystem.cs @@ -0,0 +1,7 @@ +using Content.Server.DeltaV.Station.Events; + +namespace Content.Server.DeltaV.Station.Systems; + +public sealed class NoCaptainSystem : EntitySystem +{ +} From a9d9bd276d975a32a4eae1a85a29dfffaf0776eb Mon Sep 17 00:00:00 2001 From: SolStar2 <44028047+ewokswagger@users.noreply.github.com> Date: Fri, 29 Nov 2024 00:41:12 -0500 Subject: [PATCH 03/27] add and remove NoCaptainComponent logic --- .../Station/Components/NoCaptainComponent.cs | 17 +++++++-- .../Station/Events/PlayerJobsRemovedEvent.cs | 2 +- .../Station/Systems/StationJobsSystem.cs | 6 +++- .../Station/Systems/StationSystem.cs | 35 +++++++++++++++++++ 4 files changed, 56 insertions(+), 4 deletions(-) diff --git a/Content.Server/DeltaV/Station/Components/NoCaptainComponent.cs b/Content.Server/DeltaV/Station/Components/NoCaptainComponent.cs index c98cc5f20a7..6f1351e4726 100644 --- a/Content.Server/DeltaV/Station/Components/NoCaptainComponent.cs +++ b/Content.Server/DeltaV/Station/Components/NoCaptainComponent.cs @@ -1,18 +1,25 @@ using Content.Server.DeltaV.Station.Systems; +using Content.Server.Station.Systems; namespace Content.Server.DeltaV.Station.Components; /// /// Denotes a station has no captain and holds data for automatic ACO systems /// -[RegisterComponent, Access(typeof(NoCaptainSystem))] +[RegisterComponent, Access(typeof(NoCaptainSystem), typeof(StationSystem))] public sealed partial class NoCaptainComponent : Component { /// /// How long with no captain before an ACO vote is requested /// [DataField] - public TimeSpan RequestACOVoteDelay = TimeSpan.FromMinutes(15); + public TimeSpan ACOVoteDelay = TimeSpan.FromMinutes(15); + + /// + /// Set after ACO vote time has come and been handled to avoid duplicate calls + /// + [DataField] + public bool ACOVoteHandled = false; /// /// How long after ACO vote is called the spare id cabinet will be unlocked if applicable @@ -34,4 +41,10 @@ public sealed partial class NoCaptainComponent : Component /// [DataField] public bool? UnlockAAOverride = null; + + /// + /// Used to denote that a captain has left and lost job (i.e. cryo) as apposed to no captain since round start + /// + [DataField] + public bool CaptainDeparted = false; } diff --git a/Content.Server/DeltaV/Station/Events/PlayerJobsRemovedEvent.cs b/Content.Server/DeltaV/Station/Events/PlayerJobsRemovedEvent.cs index 4acfcee9239..017010287d4 100644 --- a/Content.Server/DeltaV/Station/Events/PlayerJobsRemovedEvent.cs +++ b/Content.Server/DeltaV/Station/Events/PlayerJobsRemovedEvent.cs @@ -5,7 +5,7 @@ namespace Content.Server.DeltaV.Station.Events; /// -/// Raised on a station when a players jobs are removed +/// Raised on a station when a after a players jobs are removed from the PlayerJobs /// /// Player whos jobs were removed /// Entry in PlayerJobs removed a list of JobPrototypes diff --git a/Content.Server/Station/Systems/StationJobsSystem.cs b/Content.Server/Station/Systems/StationJobsSystem.cs index 0be0620d0a2..bd2de5d9dd4 100644 --- a/Content.Server/Station/Systems/StationJobsSystem.cs +++ b/Content.Server/Station/Systems/StationJobsSystem.cs @@ -210,9 +210,13 @@ public bool TryRemovePlayerJobs(EntityUid station, return false; // DeltaV added RemovedPlayerJobsEvent for noCaptainSystem if (jobsComponent.PlayerJobs.TryGetValue(userId, out var playerJobsEntry)) + { + jobsComponent.PlayerJobs.Remove(userId); RaiseLocalEvent(station, new PlayerJobsRemovedEvent(userId, playerJobsEntry), false); + return true; + } + return false; // DeltaV end added RemovedPlayerJobsEvent for noCaptainSystem - return jobsComponent.PlayerJobs.Remove(userId); } /// diff --git a/Content.Server/Station/Systems/StationSystem.cs b/Content.Server/Station/Systems/StationSystem.cs index 22c0cba3f78..9ae11cca4a0 100644 --- a/Content.Server/Station/Systems/StationSystem.cs +++ b/Content.Server/Station/Systems/StationSystem.cs @@ -1,5 +1,7 @@ using System.Linq; using Content.Server.Chat.Systems; +using Content.Server.DeltaV.Station.Components; +using Content.Server.DeltaV.Station.Events; using Content.Server.GameTicking; using Content.Server.Station.Components; using Content.Server.Station.Events; @@ -7,6 +9,7 @@ using Content.Shared.Station; using Content.Shared.Station.Components; using JetBrains.Annotations; +using Microsoft.CodeAnalysis.CSharp.Syntax; using Robust.Server.GameObjects; using Robust.Server.Player; using Robust.Shared.Collections; @@ -48,6 +51,8 @@ public override void Initialize() SubscribeLocalEvent(OnStationDeleted); SubscribeLocalEvent(OnStationGridDeleted); SubscribeLocalEvent(OnStationSplitEvent); + SubscribeLocalEvent(OnPlayerJobAdded); // DeltaV + SubscribeLocalEvent(OnPlayerJobsRemoved); // DeltaV _player.PlayerStatusChanged += OnPlayerStatusChanged; } @@ -148,6 +153,34 @@ private void OnRoundEnd(GameRunLevelChangedEvent eventArgs) } } + // DeltaV Handle PlayerJob Events + public void OnPlayerJobAdded(EntityUid station, StationJobsComponent _, PlayerJobAddedEvent args) + { + // Once a captain joins the NoCaptainComponent no longer applies + if (args.JobPrototypeId == "Captain") + { + EntityManager.RemoveComponent(station); + } + } + public void OnPlayerJobsRemoved(EntityUid station, StationJobsComponent stationJobs, PlayerJobsRemovedEvent args) + { + if (args.PlayerJobs == null) + return; + + // If the player that left was the only captain then the same protocols of NoCaptainComponent should take effect + if (args.PlayerJobs.Contains("Captain")) + { + if (stationJobs.PlayerJobs.Count == 0 || !stationJobs.PlayerJobs.Any(playerJobs => playerJobs.Value.Contains("Captain"))) // Expensive but only ran if a cap leaves so fine + { + EnsureComp(station, out var noCaptainComponent); + captainStateComponent.CaptainDeparted = true; + captainStateComponent.UnlockAAOverride = false; // Captain has already brought AA in the round and should have resolved staffing issues already. + captainStateComponent.ACOVoteDelay = TimeSpan.Zero; // Expedite the voting process due to midround and captain equipment being in play. + } + } + } + // DeltaV End handle PlayerJob Events + #endregion Event handlers /// @@ -286,6 +319,8 @@ public EntityUid InitializeNewStation(StationConfig stationConfig, IEnumerable(station); // DeltaV start assuming no captain untill captain joins + var ev = new StationPostInitEvent((station, data)); RaiseLocalEvent(station, ref ev, true); From d8fa64c66d58e6a91fd21353f8771f70603cce35 Mon Sep 17 00:00:00 2001 From: SolStar2 <44028047+ewokswagger@users.noreply.github.com> Date: Fri, 29 Nov 2024 15:43:01 -0500 Subject: [PATCH 04/27] Gernalized to CaptainStateComponent --- ...inComponent.cs => CaptainStateComponent.cs} | 4 ++-- .../Station/Systems/CaptainStateSystem.cs | 18 ++++++++++++++++++ .../DeltaV/Station/Systems/NoCaptainSystem.cs | 7 ------- .../Station/Systems/StationJobsSystem.cs | 6 +++--- .../Station/Systems/StationSystem.cs | 6 +++--- 5 files changed, 26 insertions(+), 15 deletions(-) rename Content.Server/DeltaV/Station/Components/{NoCaptainComponent.cs => CaptainStateComponent.cs} (91%) create mode 100644 Content.Server/DeltaV/Station/Systems/CaptainStateSystem.cs delete mode 100644 Content.Server/DeltaV/Station/Systems/NoCaptainSystem.cs diff --git a/Content.Server/DeltaV/Station/Components/NoCaptainComponent.cs b/Content.Server/DeltaV/Station/Components/CaptainStateComponent.cs similarity index 91% rename from Content.Server/DeltaV/Station/Components/NoCaptainComponent.cs rename to Content.Server/DeltaV/Station/Components/CaptainStateComponent.cs index 6f1351e4726..068708c6b98 100644 --- a/Content.Server/DeltaV/Station/Components/NoCaptainComponent.cs +++ b/Content.Server/DeltaV/Station/Components/CaptainStateComponent.cs @@ -6,8 +6,8 @@ namespace Content.Server.DeltaV.Station.Components; /// /// Denotes a station has no captain and holds data for automatic ACO systems /// -[RegisterComponent, Access(typeof(NoCaptainSystem), typeof(StationSystem))] -public sealed partial class NoCaptainComponent : Component +[RegisterComponent, Access(typeof(CaptainStateSystem), typeof(StationSystem))] +public sealed partial class CaptainStateComponent : Component { /// /// How long with no captain before an ACO vote is requested diff --git a/Content.Server/DeltaV/Station/Systems/CaptainStateSystem.cs b/Content.Server/DeltaV/Station/Systems/CaptainStateSystem.cs new file mode 100644 index 00000000000..39e58938c3d --- /dev/null +++ b/Content.Server/DeltaV/Station/Systems/CaptainStateSystem.cs @@ -0,0 +1,18 @@ +using Content.Server.DeltaV.Station.Components; +using Content.Server.DeltaV.Station.Events; + +namespace Content.Server.DeltaV.Station.Systems; + +public sealed class CaptainStateSystem : EntitySystem +{ + public override void Initialize() + { + SubscribeLocalEvent(OnComponentShutdown); + + base.Initialize(); + } + + private void OnComponentShutdown(Entity ent, ref ComponentShutdown args) + { + } +} diff --git a/Content.Server/DeltaV/Station/Systems/NoCaptainSystem.cs b/Content.Server/DeltaV/Station/Systems/NoCaptainSystem.cs deleted file mode 100644 index e6509ef37b7..00000000000 --- a/Content.Server/DeltaV/Station/Systems/NoCaptainSystem.cs +++ /dev/null @@ -1,7 +0,0 @@ -using Content.Server.DeltaV.Station.Events; - -namespace Content.Server.DeltaV.Station.Systems; - -public sealed class NoCaptainSystem : EntitySystem -{ -} diff --git a/Content.Server/Station/Systems/StationJobsSystem.cs b/Content.Server/Station/Systems/StationJobsSystem.cs index bd2de5d9dd4..ac4ebd22395 100644 --- a/Content.Server/Station/Systems/StationJobsSystem.cs +++ b/Content.Server/Station/Systems/StationJobsSystem.cs @@ -110,7 +110,7 @@ public bool TryAssignJob(EntityUid station, string jobPrototypeId, NetUserId net if (!TryAdjustJobSlot(station, jobPrototypeId, -1, false, false, stationJobs)) return false; - RaiseLocalEvent(station, new PlayerJobAddedEvent(netUserId, jobPrototypeId), false); // DeltaV added AddedPlayerJobsEvent for noCaptainSystem + RaiseLocalEvent(station, new PlayerJobAddedEvent(netUserId, jobPrototypeId), false); // DeltaV added AddedPlayerJobsEvent for CaptainStateSystem stationJobs.PlayerJobs.TryAdd(netUserId, new()); stationJobs.PlayerJobs[netUserId].Add(jobPrototypeId); return true; @@ -208,7 +208,7 @@ public bool TryRemovePlayerJobs(EntityUid station, { if (!Resolve(station, ref jobsComponent, false)) return false; - // DeltaV added RemovedPlayerJobsEvent for noCaptainSystem + // DeltaV added RemovedPlayerJobsEvent for CaptainStateSystem if (jobsComponent.PlayerJobs.TryGetValue(userId, out var playerJobsEntry)) { jobsComponent.PlayerJobs.Remove(userId); @@ -216,7 +216,7 @@ public bool TryRemovePlayerJobs(EntityUid station, return true; } return false; - // DeltaV end added RemovedPlayerJobsEvent for noCaptainSystem + // DeltaV end added RemovedPlayerJobsEvent for CaptainStateSystem } /// diff --git a/Content.Server/Station/Systems/StationSystem.cs b/Content.Server/Station/Systems/StationSystem.cs index 9ae11cca4a0..295f5763f76 100644 --- a/Content.Server/Station/Systems/StationSystem.cs +++ b/Content.Server/Station/Systems/StationSystem.cs @@ -159,7 +159,7 @@ public void OnPlayerJobAdded(EntityUid station, StationJobsComponent _, PlayerJo // Once a captain joins the NoCaptainComponent no longer applies if (args.JobPrototypeId == "Captain") { - EntityManager.RemoveComponent(station); + EntityManager.RemoveComponent(station); } } public void OnPlayerJobsRemoved(EntityUid station, StationJobsComponent stationJobs, PlayerJobsRemovedEvent args) @@ -172,7 +172,7 @@ public void OnPlayerJobsRemoved(EntityUid station, StationJobsComponent stationJ { if (stationJobs.PlayerJobs.Count == 0 || !stationJobs.PlayerJobs.Any(playerJobs => playerJobs.Value.Contains("Captain"))) // Expensive but only ran if a cap leaves so fine { - EnsureComp(station, out var noCaptainComponent); + EnsureComp(station, out var captainStateComponent); captainStateComponent.CaptainDeparted = true; captainStateComponent.UnlockAAOverride = false; // Captain has already brought AA in the round and should have resolved staffing issues already. captainStateComponent.ACOVoteDelay = TimeSpan.Zero; // Expedite the voting process due to midround and captain equipment being in play. @@ -319,7 +319,7 @@ public EntityUid InitializeNewStation(StationConfig stationConfig, IEnumerable(station); // DeltaV start assuming no captain untill captain joins + EnsureComp(station); // DeltaV start assuming no captain untill captain joins var ev = new StationPostInitEvent((station, data)); RaiseLocalEvent(station, ref ev, true); From e2c93dc2d7d165ee12aca46ee24a0a8e23e82bbb Mon Sep 17 00:00:00 2001 From: SolStar2 <44028047+ewokswagger@users.noreply.github.com> Date: Fri, 29 Nov 2024 17:42:16 -0500 Subject: [PATCH 05/27] Generalized CaptainStateComponent --- .../Components/CaptainStateComponent.cs | 20 +++++++++++++----- .../Station/Systems/CaptainStateSystem.cs | 4 ++-- .../Station/Systems/StationSystem.cs | 21 +++++++++++-------- .../Entities/Stations/nanotrasen.yml | 3 ++- 4 files changed, 31 insertions(+), 17 deletions(-) diff --git a/Content.Server/DeltaV/Station/Components/CaptainStateComponent.cs b/Content.Server/DeltaV/Station/Components/CaptainStateComponent.cs index 068708c6b98..63e5ad3345b 100644 --- a/Content.Server/DeltaV/Station/Components/CaptainStateComponent.cs +++ b/Content.Server/DeltaV/Station/Components/CaptainStateComponent.cs @@ -1,5 +1,6 @@ using Content.Server.DeltaV.Station.Systems; using Content.Server.Station.Systems; +using System.ComponentModel.DataAnnotations; namespace Content.Server.DeltaV.Station.Components; @@ -10,19 +11,28 @@ namespace Content.Server.DeltaV.Station.Components; public sealed partial class CaptainStateComponent : Component { /// - /// How long with no captain before an ACO vote is requested + /// Denotes wether the entity has a captain or not + /// + /// + /// Assume no captain unless specified + /// + [DataField] + public bool HasCaptain = false; + + /// + /// How long with no captain before an ACO is requested /// [DataField] - public TimeSpan ACOVoteDelay = TimeSpan.FromMinutes(15); + public TimeSpan ACORequestDelay = TimeSpan.FromMinutes(15); /// - /// Set after ACO vote time has come and been handled to avoid duplicate calls + /// Set after ACO has been requested to avoid duplicate calls /// [DataField] - public bool ACOVoteHandled = false; + public bool ACORequestHandled = false; /// - /// How long after ACO vote is called the spare id cabinet will be unlocked if applicable + /// How long after ACO is requested the spare id cabinet will be unlocked if applicable /// [DataField] public TimeSpan UnlockAADelay = TimeSpan.FromMinutes(5); diff --git a/Content.Server/DeltaV/Station/Systems/CaptainStateSystem.cs b/Content.Server/DeltaV/Station/Systems/CaptainStateSystem.cs index 39e58938c3d..31aa4c6ea8a 100644 --- a/Content.Server/DeltaV/Station/Systems/CaptainStateSystem.cs +++ b/Content.Server/DeltaV/Station/Systems/CaptainStateSystem.cs @@ -7,12 +7,12 @@ public sealed class CaptainStateSystem : EntitySystem { public override void Initialize() { - SubscribeLocalEvent(OnComponentShutdown); + SubscribeLocalEvent (OnComponentInit); base.Initialize(); } - private void OnComponentShutdown(Entity ent, ref ComponentShutdown args) + private void OnComponentInit(Entity ent, ref ComponentInit args) { } } diff --git a/Content.Server/Station/Systems/StationSystem.cs b/Content.Server/Station/Systems/StationSystem.cs index 295f5763f76..8cc9020bec3 100644 --- a/Content.Server/Station/Systems/StationSystem.cs +++ b/Content.Server/Station/Systems/StationSystem.cs @@ -156,10 +156,11 @@ private void OnRoundEnd(GameRunLevelChangedEvent eventArgs) // DeltaV Handle PlayerJob Events public void OnPlayerJobAdded(EntityUid station, StationJobsComponent _, PlayerJobAddedEvent args) { - // Once a captain joins the NoCaptainComponent no longer applies if (args.JobPrototypeId == "Captain") { - EntityManager.RemoveComponent(station); + CaptainStateComponent? captainStateComponent = null; + if (Resolve(station, ref captainStateComponent, false)) + captainStateComponent.HasCaptain = true; } } public void OnPlayerJobsRemoved(EntityUid station, StationJobsComponent stationJobs, PlayerJobsRemovedEvent args) @@ -167,15 +168,19 @@ public void OnPlayerJobsRemoved(EntityUid station, StationJobsComponent stationJ if (args.PlayerJobs == null) return; - // If the player that left was the only captain then the same protocols of NoCaptainComponent should take effect + // If the player that left was the only captain then there is no captain if (args.PlayerJobs.Contains("Captain")) { if (stationJobs.PlayerJobs.Count == 0 || !stationJobs.PlayerJobs.Any(playerJobs => playerJobs.Value.Contains("Captain"))) // Expensive but only ran if a cap leaves so fine { - EnsureComp(station, out var captainStateComponent); - captainStateComponent.CaptainDeparted = true; - captainStateComponent.UnlockAAOverride = false; // Captain has already brought AA in the round and should have resolved staffing issues already. - captainStateComponent.ACOVoteDelay = TimeSpan.Zero; // Expedite the voting process due to midround and captain equipment being in play. + CaptainStateComponent? captainStateComponent = null; + if (Resolve(station, ref captainStateComponent, false)) + { + captainStateComponent.HasCaptain = false; + captainStateComponent.CaptainDeparted = true; + captainStateComponent.UnlockAAOverride = false; // Captain has already brought AA in the round and should have resolved staffing issues already. + captainStateComponent.ACORequestDelay = TimeSpan.Zero; // Expedite the voting process due to midround and captain equipment being in play. + } } } } @@ -319,8 +324,6 @@ public EntityUid InitializeNewStation(StationConfig stationConfig, IEnumerable(station); // DeltaV start assuming no captain untill captain joins - var ev = new StationPostInitEvent((station, data)); RaiseLocalEvent(station, ref ev, true); diff --git a/Resources/Prototypes/Entities/Stations/nanotrasen.yml b/Resources/Prototypes/Entities/Stations/nanotrasen.yml index 5feeaa1b87f..48ecbcd0e8e 100644 --- a/Resources/Prototypes/Entities/Stations/nanotrasen.yml +++ b/Resources/Prototypes/Entities/Stations/nanotrasen.yml @@ -1,4 +1,4 @@ -- type: entity +- type: entity abstract: true id: BaseStationNanotrasen components: @@ -29,6 +29,7 @@ - BaseStationStockMarket # DeltaV categories: [ HideSpawnMenu ] components: + - type: CaptainState # DeltaV - type: Transform - type: entity From a6b971cd0e75acc48d2b06cce42f881ca934b453 Mon Sep 17 00:00:00 2001 From: SolStar2 <44028047+ewokswagger@users.noreply.github.com> Date: Sat, 30 Nov 2024 03:44:49 -0500 Subject: [PATCH 06/27] Add requesting aco vote --- .../Components/CaptainStateComponent.cs | 23 +++--- .../Station/Systems/CaptainStateSystem.cs | 74 ++++++++++++++++++- .../Station/Systems/StationSystem.cs | 4 +- 3 files changed, 83 insertions(+), 18 deletions(-) diff --git a/Content.Server/DeltaV/Station/Components/CaptainStateComponent.cs b/Content.Server/DeltaV/Station/Components/CaptainStateComponent.cs index 63e5ad3345b..60fe817469e 100644 --- a/Content.Server/DeltaV/Station/Components/CaptainStateComponent.cs +++ b/Content.Server/DeltaV/Station/Components/CaptainStateComponent.cs @@ -20,37 +20,34 @@ public sealed partial class CaptainStateComponent : Component public bool HasCaptain = false; /// - /// How long with no captain before an ACO is requested + /// Holds the round time of the last time a captain was present if one is not present currently /// [DataField] - public TimeSpan ACORequestDelay = TimeSpan.FromMinutes(15); + public TimeSpan TimeSinceCaptain = TimeSpan.Zero; /// - /// Set after ACO has been requested to avoid duplicate calls + /// How long with no captain before an ACO is requested /// [DataField] - public bool ACORequestHandled = false; + public TimeSpan ACORequestDelay = TimeSpan.FromMinutes(15); /// - /// How long after ACO is requested the spare id cabinet will be unlocked if applicable + /// Set after ACO has been requested to avoid duplicate calls /// [DataField] - public TimeSpan UnlockAADelay = TimeSpan.FromMinutes(5); + public bool IsACORequestActive = false; /// - /// Maximum player count that AA should be unlocked for ACO + /// Used to denote that AA should be unlocked after the delay /// - /// - /// If there are too many players it's likely that there is a sufficient command staffing to render automatic aa approval redundant. - /// [DataField] - public int UnlockAAPlayerThreshold = 40; + public bool UnlockAA = true; /// - /// Used to override other conditions and AA will be unlocked after the delay + /// How long after ACO is requested the spare id cabinet will be unlocked if applicable /// [DataField] - public bool? UnlockAAOverride = null; + public TimeSpan UnlockAADelay = TimeSpan.FromMinutes(5); /// /// Used to denote that a captain has left and lost job (i.e. cryo) as apposed to no captain since round start diff --git a/Content.Server/DeltaV/Station/Systems/CaptainStateSystem.cs b/Content.Server/DeltaV/Station/Systems/CaptainStateSystem.cs index 31aa4c6ea8a..1eda44e4d41 100644 --- a/Content.Server/DeltaV/Station/Systems/CaptainStateSystem.cs +++ b/Content.Server/DeltaV/Station/Systems/CaptainStateSystem.cs @@ -1,18 +1,84 @@ +using Content.Server.Chat.Systems; using Content.Server.DeltaV.Station.Components; using Content.Server.DeltaV.Station.Events; +using Content.Server.GameTicking; +using Content.Server.Station.Systems; namespace Content.Server.DeltaV.Station.Systems; public sealed class CaptainStateSystem : EntitySystem { - public override void Initialize() + [Dependency] private readonly ChatSystem _chat = default!; + [Dependency] private readonly StationSystem _stationSystem = default!; + [Dependency] public readonly GameTicker GameTicker = default!; + + public override void Update(float frameTime) + { + base.Update(frameTime); + + var currentTime = GameTicker.RoundDuration(); // Caching to reduce redundant calls + var query = EntityQueryEnumerator(); + while (query.MoveNext(out var uid, out var captainState)) + { + if (captainState.HasCaptain == true) + HandleHasCaptain(uid, captainState); + else + HandleNoCaptain(uid, captainState, currentTime); + } + } + + /// + /// Handles cases for when there is a captain + /// + /// + /// + private void HandleHasCaptain(EntityUid uid, CaptainStateComponent captainState) { - SubscribeLocalEvent (OnComponentInit); + // If ACO vote has been called we need to cancel and alert to return to normal chain of command + if (captainState.IsACORequestActive == false) + return; + _chat.DispatchStationAnnouncement(uid, "captain-arrived-revoke-aco-announcement", colorOverride: Color.Gold); + captainState.IsACORequestActive = false; + } - base.Initialize(); + /// + /// Handles cases for when there is no captain + /// + /// + /// + private void HandleNoCaptain(EntityUid uid, CaptainStateComponent captainState, TimeSpan currentTime) + { + if (CheckACORequest(captainState, currentTime)) + { + var message = captainState.UnlockAA ? "no-captain-request-aco-vote-with-aa-announcement" : "no-captain-request-aco-vote-announcement"; + _chat.DispatchStationAnnouncement(uid, Loc.GetString(message), colorOverride: Color.Gold); + captainState.IsACORequestActive = true; + } + if (CheckUnlockAA(captainState, currentTime)) + { + captainState.UnlockAA = false; // Once unlocked don't unlock again + _chat.DispatchStationAnnouncement(uid, Loc.GetString("no-captain-aa-unlocked-announcement"), colorOverride: Color.Gold); + // TODO: Unlock AA + } + } + + /// + /// Checks the conditions for if an ACO should be requested + /// + /// + /// True if conditions are met for an ACO to be requested, False otherwise + private bool CheckACORequest(CaptainStateComponent captainState, TimeSpan currentTime) + { + return !captainState.IsACORequestActive && currentTime > captainState.TimeSinceCaptain + captainState.ACORequestDelay; } - private void OnComponentInit(Entity ent, ref ComponentInit args) + /// + /// Checks the conditions for if AA should be unlocked + /// + /// + /// True if conditions are met for AA to be unlocked, False otherwise + private bool CheckUnlockAA(CaptainStateComponent captainState, TimeSpan currentTime) { + return captainState.UnlockAA && currentTime > captainState.TimeSinceCaptain + captainState.ACORequestDelay + captainState.UnlockAADelay; } } diff --git a/Content.Server/Station/Systems/StationSystem.cs b/Content.Server/Station/Systems/StationSystem.cs index 8cc9020bec3..84e044af4b3 100644 --- a/Content.Server/Station/Systems/StationSystem.cs +++ b/Content.Server/Station/Systems/StationSystem.cs @@ -37,6 +37,7 @@ public sealed class StationSystem : EntitySystem [Dependency] private readonly SharedTransformSystem _transform = default!; [Dependency] private readonly MetaDataSystem _metaData = default!; [Dependency] private readonly MapSystem _map = default!; + [Dependency] public readonly GameTicker GameTicker = default!; // DeltaV private ISawmill _sawmill = default!; @@ -177,8 +178,9 @@ public void OnPlayerJobsRemoved(EntityUid station, StationJobsComponent stationJ if (Resolve(station, ref captainStateComponent, false)) { captainStateComponent.HasCaptain = false; + captainStateComponent.TimeSinceCaptain = GameTicker.RoundDuration(); captainStateComponent.CaptainDeparted = true; - captainStateComponent.UnlockAAOverride = false; // Captain has already brought AA in the round and should have resolved staffing issues already. + captainStateComponent.UnlockAA = false; // Captain has already brought AA in the round and should have resolved staffing issues already. captainStateComponent.ACORequestDelay = TimeSpan.Zero; // Expedite the voting process due to midround and captain equipment being in play. } } From ddbd3d31bb2a4dcaf52f68e5d2a269e035dbcefb Mon Sep 17 00:00:00 2001 From: SolStar2 <44028047+ewokswagger@users.noreply.github.com> Date: Mon, 2 Dec 2024 15:59:50 -0500 Subject: [PATCH 07/27] Add auto unlock aa --- .../Station/Systems/CaptainStateSystem.cs | 15 +++++++--- .../Access/Systems/AccessReaderSystem.cs | 28 +++++++++++++++++++ 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/Content.Server/DeltaV/Station/Systems/CaptainStateSystem.cs b/Content.Server/DeltaV/Station/Systems/CaptainStateSystem.cs index 1eda44e4d41..742db44b71c 100644 --- a/Content.Server/DeltaV/Station/Systems/CaptainStateSystem.cs +++ b/Content.Server/DeltaV/Station/Systems/CaptainStateSystem.cs @@ -1,8 +1,10 @@ using Content.Server.Chat.Systems; using Content.Server.DeltaV.Station.Components; -using Content.Server.DeltaV.Station.Events; using Content.Server.GameTicking; using Content.Server.Station.Systems; +using Content.Shared.Access; +using Content.Shared.Access.Systems; +using Robust.Shared.Prototypes; namespace Content.Server.DeltaV.Station.Systems; @@ -10,13 +12,14 @@ public sealed class CaptainStateSystem : EntitySystem { [Dependency] private readonly ChatSystem _chat = default!; [Dependency] private readonly StationSystem _stationSystem = default!; - [Dependency] public readonly GameTicker GameTicker = default!; + [Dependency] private readonly GameTicker _gameTicker = default!; + [Dependency] private readonly IEntityManager _entityManager = default!; public override void Update(float frameTime) { base.Update(frameTime); - var currentTime = GameTicker.RoundDuration(); // Caching to reduce redundant calls + var currentTime = _gameTicker.RoundDuration(); // Caching to reduce redundant calls var query = EntityQueryEnumerator(); while (query.MoveNext(out var uid, out var captainState)) { @@ -58,7 +61,11 @@ private void HandleNoCaptain(EntityUid uid, CaptainStateComponent captainState, { captainState.UnlockAA = false; // Once unlocked don't unlock again _chat.DispatchStationAnnouncement(uid, Loc.GetString("no-captain-aa-unlocked-announcement"), colorOverride: Color.Gold); - // TODO: Unlock AA + + // Extend access of spare id lockers to command so they can access emergency AA + var spareSafeAccess = new List> { "DV-SpareSafe" }; + var commandAccess = new List> { "Command" }; + _entityManager.System().ExpandAccessForAllReaders(spareSafeAccess, commandAccess); } } diff --git a/Content.Shared/Access/Systems/AccessReaderSystem.cs b/Content.Shared/Access/Systems/AccessReaderSystem.cs index f670ac860be..b4a2b61cecf 100644 --- a/Content.Shared/Access/Systems/AccessReaderSystem.cs +++ b/Content.Shared/Access/Systems/AccessReaderSystem.cs @@ -328,6 +328,34 @@ public void SetAccesses(EntityUid uid, AccessReaderComponent component, List + /// Extends access of readers accepted with the existing accesses to the new accesses. + /// + /// The existing access levels used to identify matching readers. + /// The new access levels to add. + /// List of affected Entities + /// Access Readers with no access restrictions are unaffected to preserve thier status. + public List ExpandAccessForAllReaders(ICollection> existingAcesss, List> newAccess) + { + List affected = new(); + var query = EntityQueryEnumerator(); + while (query.MoveNext(out var uid, out var accessReader)) + { + if (accessReader.AccessLists.Count == 0) // We need to exclude access readers with no restrictions or else all hallway doors will suddenly need the new access + continue; + if (!AreAccessTagsAllowed(existingAcesss, accessReader)) + continue; + affected.Add(uid); + foreach (var access in newAccess) + accessReader.AccessLists.Add(new HashSet>() { access }); + Dirty(uid, accessReader); + RaiseLocalEvent(uid, new AccessReaderConfigurationChangedEvent()); + } + return affected; + } + // DeltaV End expanding access logic + public bool FindAccessItemsInventory(EntityUid uid, out HashSet items) { items = new(); From 4ba9d96078a0be1eb0499ccb29f5dcb90020ee48 Mon Sep 17 00:00:00 2001 From: SolStar2 <44028047+ewokswagger@users.noreply.github.com> Date: Mon, 2 Dec 2024 16:21:55 -0500 Subject: [PATCH 08/27] Remove hardcodecd strings --- .../Components/CaptainStateComponent.cs | 38 +++++++++++++++++-- .../Station/Systems/CaptainStateSystem.cs | 12 ++---- 2 files changed, 39 insertions(+), 11 deletions(-) diff --git a/Content.Server/DeltaV/Station/Components/CaptainStateComponent.cs b/Content.Server/DeltaV/Station/Components/CaptainStateComponent.cs index 60fe817469e..3b070709290 100644 --- a/Content.Server/DeltaV/Station/Components/CaptainStateComponent.cs +++ b/Content.Server/DeltaV/Station/Components/CaptainStateComponent.cs @@ -1,6 +1,7 @@ using Content.Server.DeltaV.Station.Systems; using Content.Server.Station.Systems; -using System.ComponentModel.DataAnnotations; +using Content.Shared.Access; +using Robust.Shared.Prototypes; namespace Content.Server.DeltaV.Station.Components; @@ -31,6 +32,24 @@ public sealed partial class CaptainStateComponent : Component [DataField] public TimeSpan ACORequestDelay = TimeSpan.FromMinutes(15); + /// + /// The message ID used for announcing the cancellation of ACO requests + /// + [DataField] + public string RevokeACOMessage = "captain-arrived-revoke-aco-announcement"; + + /// + /// The message ID for requesting an ACO vote when AA will be unlocked + /// + [DataField] + public string ACORequestWithAAMessage = "no-captain-request-aco-vote-with-aa-announcement"; + + /// + /// The message ID for requesting an ACO vote when AA will not be unlocked + /// + [DataField] + public string ACORequestNoAAMessage = "no-captain-request-aco-vote-announcement"; + /// /// Set after ACO has been requested to avoid duplicate calls /// @@ -50,8 +69,21 @@ public sealed partial class CaptainStateComponent : Component public TimeSpan UnlockAADelay = TimeSpan.FromMinutes(5); /// - /// Used to denote that a captain has left and lost job (i.e. cryo) as apposed to no captain since round start + /// The message ID for announcing that AA has been unlocked for ACO + /// + [DataField] + public string AAUnlockedMessage = "no-captain-aa-unlocked-announcement"; + + /// + /// The access level used to identify spare ID cabinets /// [DataField] - public bool CaptainDeparted = false; + public List> EmergencyAAAccess = new() { "DV-SpareSafe" }; + + /// + /// The access level to grant to spare ID cabinets + /// + [DataField] + public List> ACOAccess = new() { "Command" }; +} } diff --git a/Content.Server/DeltaV/Station/Systems/CaptainStateSystem.cs b/Content.Server/DeltaV/Station/Systems/CaptainStateSystem.cs index 742db44b71c..f7a2cf7e232 100644 --- a/Content.Server/DeltaV/Station/Systems/CaptainStateSystem.cs +++ b/Content.Server/DeltaV/Station/Systems/CaptainStateSystem.cs @@ -2,9 +2,7 @@ using Content.Server.DeltaV.Station.Components; using Content.Server.GameTicking; using Content.Server.Station.Systems; -using Content.Shared.Access; using Content.Shared.Access.Systems; -using Robust.Shared.Prototypes; namespace Content.Server.DeltaV.Station.Systems; @@ -40,7 +38,7 @@ private void HandleHasCaptain(EntityUid uid, CaptainStateComponent captainState) // If ACO vote has been called we need to cancel and alert to return to normal chain of command if (captainState.IsACORequestActive == false) return; - _chat.DispatchStationAnnouncement(uid, "captain-arrived-revoke-aco-announcement", colorOverride: Color.Gold); + _chat.DispatchStationAnnouncement(uid, captainState.RevokeACOMessage, colorOverride: Color.Gold); captainState.IsACORequestActive = false; } @@ -53,19 +51,17 @@ private void HandleNoCaptain(EntityUid uid, CaptainStateComponent captainState, { if (CheckACORequest(captainState, currentTime)) { - var message = captainState.UnlockAA ? "no-captain-request-aco-vote-with-aa-announcement" : "no-captain-request-aco-vote-announcement"; + var message = captainState.UnlockAA ? captainState.ACORequestWithAAMessage : captainState.ACORequestNoAAMessage; _chat.DispatchStationAnnouncement(uid, Loc.GetString(message), colorOverride: Color.Gold); captainState.IsACORequestActive = true; } if (CheckUnlockAA(captainState, currentTime)) { captainState.UnlockAA = false; // Once unlocked don't unlock again - _chat.DispatchStationAnnouncement(uid, Loc.GetString("no-captain-aa-unlocked-announcement"), colorOverride: Color.Gold); + _chat.DispatchStationAnnouncement(uid, Loc.GetString(captainState.AAUnlockedMessage), colorOverride: Color.Gold); // Extend access of spare id lockers to command so they can access emergency AA - var spareSafeAccess = new List> { "DV-SpareSafe" }; - var commandAccess = new List> { "Command" }; - _entityManager.System().ExpandAccessForAllReaders(spareSafeAccess, commandAccess); + _entityManager.System().ExpandAccessForAllReaders(captainState.EmergencyAAAccess, captainState.ACOAccess); } } From a4e0166afa7aa4367a7208961226750546006f29 Mon Sep 17 00:00:00 2001 From: SolStar2 <44028047+ewokswagger@users.noreply.github.com> Date: Mon, 2 Dec 2024 17:25:15 -0500 Subject: [PATCH 09/27] Add localization --- .../DeltaV/Station/Components/CaptainStateComponent.cs | 1 - Content.Server/DeltaV/Station/Systems/CaptainStateSystem.cs | 6 +++--- Content.Server/Station/Systems/StationSystem.cs | 1 - Resources/Locale/en-US/deltav/job/captain-state.ftl | 6 ++++++ 4 files changed, 9 insertions(+), 5 deletions(-) create mode 100644 Resources/Locale/en-US/deltav/job/captain-state.ftl diff --git a/Content.Server/DeltaV/Station/Components/CaptainStateComponent.cs b/Content.Server/DeltaV/Station/Components/CaptainStateComponent.cs index 3b070709290..65933c48e3a 100644 --- a/Content.Server/DeltaV/Station/Components/CaptainStateComponent.cs +++ b/Content.Server/DeltaV/Station/Components/CaptainStateComponent.cs @@ -86,4 +86,3 @@ public sealed partial class CaptainStateComponent : Component [DataField] public List> ACOAccess = new() { "Command" }; } -} diff --git a/Content.Server/DeltaV/Station/Systems/CaptainStateSystem.cs b/Content.Server/DeltaV/Station/Systems/CaptainStateSystem.cs index f7a2cf7e232..fe3329ce6a8 100644 --- a/Content.Server/DeltaV/Station/Systems/CaptainStateSystem.cs +++ b/Content.Server/DeltaV/Station/Systems/CaptainStateSystem.cs @@ -38,7 +38,7 @@ private void HandleHasCaptain(EntityUid uid, CaptainStateComponent captainState) // If ACO vote has been called we need to cancel and alert to return to normal chain of command if (captainState.IsACORequestActive == false) return; - _chat.DispatchStationAnnouncement(uid, captainState.RevokeACOMessage, colorOverride: Color.Gold); + _chat.DispatchStationAnnouncement(uid, Loc.GetString(captainState.RevokeACOMessage), colorOverride: Color.Gold); captainState.IsACORequestActive = false; } @@ -52,13 +52,13 @@ private void HandleNoCaptain(EntityUid uid, CaptainStateComponent captainState, if (CheckACORequest(captainState, currentTime)) { var message = captainState.UnlockAA ? captainState.ACORequestWithAAMessage : captainState.ACORequestNoAAMessage; - _chat.DispatchStationAnnouncement(uid, Loc.GetString(message), colorOverride: Color.Gold); + _chat.DispatchStationAnnouncement(uid, Loc.GetString(message, ("minutes", captainState.UnlockAADelay.TotalMinutes)), colorOverride: Color.Gold); captainState.IsACORequestActive = true; } if (CheckUnlockAA(captainState, currentTime)) { captainState.UnlockAA = false; // Once unlocked don't unlock again - _chat.DispatchStationAnnouncement(uid, Loc.GetString(captainState.AAUnlockedMessage), colorOverride: Color.Gold); + _chat.DispatchStationAnnouncement(uid, Loc.GetString(captainState.AAUnlockedMessage), colorOverride: Color.Red); // Extend access of spare id lockers to command so they can access emergency AA _entityManager.System().ExpandAccessForAllReaders(captainState.EmergencyAAAccess, captainState.ACOAccess); diff --git a/Content.Server/Station/Systems/StationSystem.cs b/Content.Server/Station/Systems/StationSystem.cs index 84e044af4b3..7d64fe2fd2b 100644 --- a/Content.Server/Station/Systems/StationSystem.cs +++ b/Content.Server/Station/Systems/StationSystem.cs @@ -179,7 +179,6 @@ public void OnPlayerJobsRemoved(EntityUid station, StationJobsComponent stationJ { captainStateComponent.HasCaptain = false; captainStateComponent.TimeSinceCaptain = GameTicker.RoundDuration(); - captainStateComponent.CaptainDeparted = true; captainStateComponent.UnlockAA = false; // Captain has already brought AA in the round and should have resolved staffing issues already. captainStateComponent.ACORequestDelay = TimeSpan.Zero; // Expedite the voting process due to midround and captain equipment being in play. } diff --git a/Resources/Locale/en-US/deltav/job/captain-state.ftl b/Resources/Locale/en-US/deltav/job/captain-state.ftl new file mode 100644 index 00000000000..fc66e88cd83 --- /dev/null +++ b/Resources/Locale/en-US/deltav/job/captain-state.ftl @@ -0,0 +1,6 @@ +# Announcements related to captain presence and ACO state + +captain-arrived-revoke-aco-announcement = The Acting Commanding Officer's position is revoked due to the arrival of a NanoTrasen-appointed captain. All personnel are to return to the standard Chain of Command. +no-captain-request-aco-vote-with-aa-announcement = Station records indicate that no captain is currently present. Command personnel are requested to nominate an Acting Commanding Officer in accordance with Standard Operating Procedure. Emergency AA will be unlocked in {$minutes} minutes to ensure continued operational efficiency. +no-captain-request-aco-vote-announcement = Station records indicate that no captain is currently present. Command personnel are requested to nominate an Acting Commanding Officer in accordance with Standard Operating Procedure. +no-captain-aa-unlocked-announcement = Command access authority has been granted to the Spare ID cabinet for use by the Acting Commanding Officer. Unauthorized possession of Emergency AA is punishable under Felony Offense [202]: Grand Theft. From fbe2781cfa5f5169a5e01ca69672d4bfcda0dd2e Mon Sep 17 00:00:00 2001 From: SolStar2 <44028047+ewokswagger@users.noreply.github.com> Date: Mon, 2 Dec 2024 19:02:48 -0500 Subject: [PATCH 10/27] // DeltaV --- Content.Server/Station/Systems/StationSystem.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Content.Server/Station/Systems/StationSystem.cs b/Content.Server/Station/Systems/StationSystem.cs index 7d64fe2fd2b..21a943799cd 100644 --- a/Content.Server/Station/Systems/StationSystem.cs +++ b/Content.Server/Station/Systems/StationSystem.cs @@ -1,7 +1,7 @@ using System.Linq; using Content.Server.Chat.Systems; -using Content.Server.DeltaV.Station.Components; -using Content.Server.DeltaV.Station.Events; +using Content.Server.DeltaV.Station.Components; // DeltaV +using Content.Server.DeltaV.Station.Events; // DeltaV using Content.Server.GameTicking; using Content.Server.Station.Components; using Content.Server.Station.Events; @@ -9,7 +9,6 @@ using Content.Shared.Station; using Content.Shared.Station.Components; using JetBrains.Annotations; -using Microsoft.CodeAnalysis.CSharp.Syntax; using Robust.Server.GameObjects; using Robust.Server.Player; using Robust.Shared.Collections; From bda59b0985e5c1bdfb05f245d1890865da31ffa8 Mon Sep 17 00:00:00 2001 From: SolStar2 <44028047+ewokswagger@users.noreply.github.com> Date: Tue, 3 Dec 2024 01:54:38 -0500 Subject: [PATCH 11/27] pro fix --- .../Components/CaptainStateComponent.cs | 25 ++++++++-------- .../Station/Events/PlayerJobAddedEvent.cs | 14 --------- .../DeltaV/Station/Events/PlayerJobEvents.cs | 21 ++++++++++++++ .../Station/Events/PlayerJobsRemovedEvent.cs | 16 ---------- .../Station/Systems/CaptainStateSystem.cs | 29 +++++++++---------- .../Station/Systems/StationJobsSystem.cs | 7 +++-- .../Station/Systems/StationSystem.cs | 4 +-- 7 files changed, 54 insertions(+), 62 deletions(-) delete mode 100644 Content.Server/DeltaV/Station/Events/PlayerJobAddedEvent.cs create mode 100644 Content.Server/DeltaV/Station/Events/PlayerJobEvents.cs delete mode 100644 Content.Server/DeltaV/Station/Events/PlayerJobsRemovedEvent.cs diff --git a/Content.Server/DeltaV/Station/Components/CaptainStateComponent.cs b/Content.Server/DeltaV/Station/Components/CaptainStateComponent.cs index 65933c48e3a..3eb9bba8b39 100644 --- a/Content.Server/DeltaV/Station/Components/CaptainStateComponent.cs +++ b/Content.Server/DeltaV/Station/Components/CaptainStateComponent.cs @@ -2,13 +2,14 @@ using Content.Server.Station.Systems; using Content.Shared.Access; using Robust.Shared.Prototypes; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom; namespace Content.Server.DeltaV.Station.Components; /// /// Denotes a station has no captain and holds data for automatic ACO systems /// -[RegisterComponent, Access(typeof(CaptainStateSystem), typeof(StationSystem))] +[RegisterComponent, Access(typeof(CaptainStateSystem), typeof(StationSystem)), AutoGenerateComponentPause] public sealed partial class CaptainStateComponent : Component { /// @@ -18,12 +19,12 @@ public sealed partial class CaptainStateComponent : Component /// Assume no captain unless specified /// [DataField] - public bool HasCaptain = false; + public bool HasCaptain; /// /// Holds the round time of the last time a captain was present if one is not present currently /// - [DataField] + [DataField("TimeSinceCaptain", customTypeSerializer: typeof(TimeOffsetSerializer)), AutoPausedField] public TimeSpan TimeSinceCaptain = TimeSpan.Zero; /// @@ -33,28 +34,28 @@ public sealed partial class CaptainStateComponent : Component public TimeSpan ACORequestDelay = TimeSpan.FromMinutes(15); /// - /// The message ID used for announcing the cancellation of ACO requests + /// The localization ID used for announcing the cancellation of ACO requests /// [DataField] - public string RevokeACOMessage = "captain-arrived-revoke-aco-announcement"; + public LocId RevokeACOMessage = "captain-arrived-revoke-aco-announcement"; /// - /// The message ID for requesting an ACO vote when AA will be unlocked + /// The localization ID for requesting an ACO vote when AA will be unlocked /// [DataField] - public string ACORequestWithAAMessage = "no-captain-request-aco-vote-with-aa-announcement"; + public LocId ACORequestWithAAMessage = "no-captain-request-aco-vote-with-aa-announcement"; /// - /// The message ID for requesting an ACO vote when AA will not be unlocked + /// The localization ID for requesting an ACO vote when AA will not be unlocked /// [DataField] - public string ACORequestNoAAMessage = "no-captain-request-aco-vote-announcement"; + public LocId ACORequestNoAAMessage = "no-captain-request-aco-vote-announcement"; /// /// Set after ACO has been requested to avoid duplicate calls /// [DataField] - public bool IsACORequestActive = false; + public bool IsACORequestActive; /// /// Used to denote that AA should be unlocked after the delay @@ -69,10 +70,10 @@ public sealed partial class CaptainStateComponent : Component public TimeSpan UnlockAADelay = TimeSpan.FromMinutes(5); /// - /// The message ID for announcing that AA has been unlocked for ACO + /// The localization ID for announcing that AA has been unlocked for ACO /// [DataField] - public string AAUnlockedMessage = "no-captain-aa-unlocked-announcement"; + public LocId AAUnlockedMessage = "no-captain-aa-unlocked-announcement"; /// /// The access level used to identify spare ID cabinets diff --git a/Content.Server/DeltaV/Station/Events/PlayerJobAddedEvent.cs b/Content.Server/DeltaV/Station/Events/PlayerJobAddedEvent.cs deleted file mode 100644 index 8fd0e22ef83..00000000000 --- a/Content.Server/DeltaV/Station/Events/PlayerJobAddedEvent.cs +++ /dev/null @@ -1,14 +0,0 @@ -using Robust.Shared.Network; - -namespace Content.Server.DeltaV.Station.Events; - -/// -/// Raised on a staion when a job is added to a player -/// -/// Player who recived a job -/// Id of the jobPrototype added -public sealed class PlayerJobAddedEvent(NetUserId netUserId, string jobPrototypeId) : EntityEventArgs -{ - public NetUserId NetUserId = netUserId; - public string? JobPrototypeId = jobPrototypeId; -} diff --git a/Content.Server/DeltaV/Station/Events/PlayerJobEvents.cs b/Content.Server/DeltaV/Station/Events/PlayerJobEvents.cs new file mode 100644 index 00000000000..d34e5994202 --- /dev/null +++ b/Content.Server/DeltaV/Station/Events/PlayerJobEvents.cs @@ -0,0 +1,21 @@ +using Content.Shared.Roles; +using Robust.Shared.Network; +using Robust.Shared.Prototypes; + +namespace Content.Server.DeltaV.Station.Events; + +/// +/// Raised on a station when a after a players jobs are removed from the PlayerJobs +/// +/// Player whos jobs were removed +/// Entry in PlayerJobs removed a list of JobPrototypes +[ByRefEvent] +public record struct PlayerJobsRemovedEvent(NetUserId NetUserId, List> PlayerJobs); + +/// +/// Raised on a staion when a job is added to a player +/// +/// Player who recived a job +/// Id of the jobPrototype added +[ByRefEvent] +public record struct PlayerJobAddedEvent(NetUserId NetUserId, string JobPrototypeId); diff --git a/Content.Server/DeltaV/Station/Events/PlayerJobsRemovedEvent.cs b/Content.Server/DeltaV/Station/Events/PlayerJobsRemovedEvent.cs deleted file mode 100644 index 017010287d4..00000000000 --- a/Content.Server/DeltaV/Station/Events/PlayerJobsRemovedEvent.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Content.Shared.Roles; -using Robust.Shared.Network; -using Robust.Shared.Prototypes; - -namespace Content.Server.DeltaV.Station.Events; - -/// -/// Raised on a station when a after a players jobs are removed from the PlayerJobs -/// -/// Player whos jobs were removed -/// Entry in PlayerJobs removed a list of JobPrototypes -public sealed class PlayerJobsRemovedEvent(NetUserId netUserId, List> playerJobs) : EntityEventArgs -{ - public NetUserId NetUserId = netUserId; - public List>? PlayerJobs = playerJobs; -} diff --git a/Content.Server/DeltaV/Station/Systems/CaptainStateSystem.cs b/Content.Server/DeltaV/Station/Systems/CaptainStateSystem.cs index fe3329ce6a8..e7d52a3edbb 100644 --- a/Content.Server/DeltaV/Station/Systems/CaptainStateSystem.cs +++ b/Content.Server/DeltaV/Station/Systems/CaptainStateSystem.cs @@ -9,59 +9,58 @@ namespace Content.Server.DeltaV.Station.Systems; public sealed class CaptainStateSystem : EntitySystem { [Dependency] private readonly ChatSystem _chat = default!; - [Dependency] private readonly StationSystem _stationSystem = default!; - [Dependency] private readonly GameTicker _gameTicker = default!; - [Dependency] private readonly IEntityManager _entityManager = default!; + [Dependency] private readonly GameTicker _ticker = default!; + [Dependency] private readonly IEntityManager _entity = default!; public override void Update(float frameTime) { base.Update(frameTime); - var currentTime = _gameTicker.RoundDuration(); // Caching to reduce redundant calls + var currentTime = _ticker.RoundDuration(); // Caching to reduce redundant calls var query = EntityQueryEnumerator(); - while (query.MoveNext(out var uid, out var captainState)) + while (query.MoveNext(out var station, out var captainState)) { if (captainState.HasCaptain == true) - HandleHasCaptain(uid, captainState); + HandleHasCaptain(station, captainState); else - HandleNoCaptain(uid, captainState, currentTime); + HandleNoCaptain(station, captainState, currentTime); } } /// /// Handles cases for when there is a captain /// - /// + /// /// - private void HandleHasCaptain(EntityUid uid, CaptainStateComponent captainState) + private void HandleHasCaptain(Entity station, CaptainStateComponent captainState) { // If ACO vote has been called we need to cancel and alert to return to normal chain of command if (captainState.IsACORequestActive == false) return; - _chat.DispatchStationAnnouncement(uid, Loc.GetString(captainState.RevokeACOMessage), colorOverride: Color.Gold); + _chat.DispatchStationAnnouncement(station, Loc.GetString(captainState.RevokeACOMessage), colorOverride: Color.Gold); captainState.IsACORequestActive = false; } /// /// Handles cases for when there is no captain /// - /// + /// /// - private void HandleNoCaptain(EntityUid uid, CaptainStateComponent captainState, TimeSpan currentTime) + private void HandleNoCaptain(Entity station, CaptainStateComponent captainState, TimeSpan currentTime) { if (CheckACORequest(captainState, currentTime)) { var message = captainState.UnlockAA ? captainState.ACORequestWithAAMessage : captainState.ACORequestNoAAMessage; - _chat.DispatchStationAnnouncement(uid, Loc.GetString(message, ("minutes", captainState.UnlockAADelay.TotalMinutes)), colorOverride: Color.Gold); + _chat.DispatchStationAnnouncement(station, Loc.GetString(message, ("minutes", captainState.UnlockAADelay.TotalMinutes)), colorOverride: Color.Gold); captainState.IsACORequestActive = true; } if (CheckUnlockAA(captainState, currentTime)) { captainState.UnlockAA = false; // Once unlocked don't unlock again - _chat.DispatchStationAnnouncement(uid, Loc.GetString(captainState.AAUnlockedMessage), colorOverride: Color.Red); + _chat.DispatchStationAnnouncement(station, Loc.GetString(captainState.AAUnlockedMessage), colorOverride: Color.Red); // Extend access of spare id lockers to command so they can access emergency AA - _entityManager.System().ExpandAccessForAllReaders(captainState.EmergencyAAAccess, captainState.ACOAccess); + _entity.System().ExpandAccessForAllReaders(captainState.EmergencyAAAccess, captainState.ACOAccess); } } diff --git a/Content.Server/Station/Systems/StationJobsSystem.cs b/Content.Server/Station/Systems/StationJobsSystem.cs index ac4ebd22395..672e40b1e2d 100644 --- a/Content.Server/Station/Systems/StationJobsSystem.cs +++ b/Content.Server/Station/Systems/StationJobsSystem.cs @@ -109,8 +109,8 @@ public bool TryAssignJob(EntityUid station, string jobPrototypeId, NetUserId net if (!TryAdjustJobSlot(station, jobPrototypeId, -1, false, false, stationJobs)) return false; - - RaiseLocalEvent(station, new PlayerJobAddedEvent(netUserId, jobPrototypeId), false); // DeltaV added AddedPlayerJobsEvent for CaptainStateSystem + var playerJobAdded = new PlayerJobAddedEvent(netUserId, jobPrototypeId); + RaiseLocalEvent(station, ref playerJobAdded, false); // DeltaV added AddedPlayerJobsEvent for CaptainStateSystem stationJobs.PlayerJobs.TryAdd(netUserId, new()); stationJobs.PlayerJobs[netUserId].Add(jobPrototypeId); return true; @@ -212,7 +212,8 @@ public bool TryRemovePlayerJobs(EntityUid station, if (jobsComponent.PlayerJobs.TryGetValue(userId, out var playerJobsEntry)) { jobsComponent.PlayerJobs.Remove(userId); - RaiseLocalEvent(station, new PlayerJobsRemovedEvent(userId, playerJobsEntry), false); + var playerJobRemovedEvent = new PlayerJobsRemovedEvent(userId, playerJobsEntry); + RaiseLocalEvent(station, ref playerJobRemovedEvent, false); return true; } return false; diff --git a/Content.Server/Station/Systems/StationSystem.cs b/Content.Server/Station/Systems/StationSystem.cs index 21a943799cd..77d152dc5d2 100644 --- a/Content.Server/Station/Systems/StationSystem.cs +++ b/Content.Server/Station/Systems/StationSystem.cs @@ -154,7 +154,7 @@ private void OnRoundEnd(GameRunLevelChangedEvent eventArgs) } // DeltaV Handle PlayerJob Events - public void OnPlayerJobAdded(EntityUid station, StationJobsComponent _, PlayerJobAddedEvent args) + public void OnPlayerJobAdded(Entity station, ref PlayerJobAddedEvent args) { if (args.JobPrototypeId == "Captain") { @@ -163,7 +163,7 @@ public void OnPlayerJobAdded(EntityUid station, StationJobsComponent _, PlayerJo captainStateComponent.HasCaptain = true; } } - public void OnPlayerJobsRemoved(EntityUid station, StationJobsComponent stationJobs, PlayerJobsRemovedEvent args) + public void OnPlayerJobsRemoved(EntityUid station, StationJobsComponent stationJobs, ref PlayerJobsRemovedEvent args) { if (args.PlayerJobs == null) return; From 3c28a4ed588fb8b85bd3075f8440263d2a4b412a Mon Sep 17 00:00:00 2001 From: SolStar2 <44028047+ewokswagger@users.noreply.github.com> Date: Tue, 3 Dec 2024 02:38:49 -0500 Subject: [PATCH 12/27] fax cc please --- Resources/Locale/en-US/deltav/job/captain-state.ftl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Resources/Locale/en-US/deltav/job/captain-state.ftl b/Resources/Locale/en-US/deltav/job/captain-state.ftl index fc66e88cd83..bbae626d7e5 100644 --- a/Resources/Locale/en-US/deltav/job/captain-state.ftl +++ b/Resources/Locale/en-US/deltav/job/captain-state.ftl @@ -1,6 +1,6 @@ # Announcements related to captain presence and ACO state captain-arrived-revoke-aco-announcement = The Acting Commanding Officer's position is revoked due to the arrival of a NanoTrasen-appointed captain. All personnel are to return to the standard Chain of Command. -no-captain-request-aco-vote-with-aa-announcement = Station records indicate that no captain is currently present. Command personnel are requested to nominate an Acting Commanding Officer in accordance with Standard Operating Procedure. Emergency AA will be unlocked in {$minutes} minutes to ensure continued operational efficiency. -no-captain-request-aco-vote-announcement = Station records indicate that no captain is currently present. Command personnel are requested to nominate an Acting Commanding Officer in accordance with Standard Operating Procedure. +no-captain-request-aco-vote-with-aa-announcement = Station records indicate that no captain is currently present. Command personnel are requested to nominate an Acting Commanding Officer and report the results to Central Command in accordance with Standard Operating Procedure. Emergency AA will be unlocked in {$minutes} minutes to ensure continued operational efficiency. +no-captain-request-aco-vote-announcement = Station records indicate that no captain is currently present. Command personnel are requested to nominate an Acting Commanding Officer and report the results to Central Command in accordance with Standard Operating Procedure. no-captain-aa-unlocked-announcement = Command access authority has been granted to the Spare ID cabinet for use by the Acting Commanding Officer. Unauthorized possession of Emergency AA is punishable under Felony Offense [202]: Grand Theft. From 6f20132c1ab7865b13d45bb5e22dce3c443d8395 Mon Sep 17 00:00:00 2001 From: SolStar2 <44028047+ewokswagger@users.noreply.github.com> Date: Tue, 3 Dec 2024 14:58:26 -0500 Subject: [PATCH 13/27] move captain detection to CaptainStateSystem --- .../Station/Systems/CaptainStateSystem.cs | 37 ++++++++++++++++++- .../Station/Systems/StationSystem.cs | 35 ------------------ 2 files changed, 35 insertions(+), 37 deletions(-) diff --git a/Content.Server/DeltaV/Station/Systems/CaptainStateSystem.cs b/Content.Server/DeltaV/Station/Systems/CaptainStateSystem.cs index e7d52a3edbb..2730b8c8d56 100644 --- a/Content.Server/DeltaV/Station/Systems/CaptainStateSystem.cs +++ b/Content.Server/DeltaV/Station/Systems/CaptainStateSystem.cs @@ -1,8 +1,11 @@ using Content.Server.Chat.Systems; using Content.Server.DeltaV.Station.Components; +using Content.Server.DeltaV.Station.Events; using Content.Server.GameTicking; +using Content.Server.Station.Components; using Content.Server.Station.Systems; using Content.Shared.Access.Systems; +using System.Linq; namespace Content.Server.DeltaV.Station.Systems; @@ -12,6 +15,13 @@ public sealed class CaptainStateSystem : EntitySystem [Dependency] private readonly GameTicker _ticker = default!; [Dependency] private readonly IEntityManager _entity = default!; + public override void Initialize() + { + SubscribeLocalEvent(OnPlayerJobAdded); // DeltaV + SubscribeLocalEvent(OnPlayerJobsRemoved); // DeltaV + base.Initialize(); + } + public override void Update(float frameTime) { base.Update(frameTime); @@ -20,13 +30,36 @@ public override void Update(float frameTime) var query = EntityQueryEnumerator(); while (query.MoveNext(out var station, out var captainState)) { - if (captainState.HasCaptain == true) + if (captainState.HasCaptain) HandleHasCaptain(station, captainState); else HandleNoCaptain(station, captainState, currentTime); } } + private void OnPlayerJobAdded(Entity ent, ref PlayerJobAddedEvent args) + { + if (args.JobPrototypeId == "Captain") + { + if (TryComp(ent, out var component)) + component.HasCaptain = true; + } + } + + private void OnPlayerJobsRemoved(Entity ent, ref PlayerJobsRemovedEvent args) + { + if (args.PlayerJobs == null || !args.PlayerJobs.Contains("Captain")) // If the player that left was a captain we need to check if there are any captains left + return; + if (ent.Comp.PlayerJobs.Count != 0 && ent.Comp.PlayerJobs.Any(playerJobs => playerJobs.Value.Contains("Captain"))) // We check the PlayerJobs if there are any cpatins left + return; + if (!TryComp(ent, out var component)) // We update CaptainState if the station has one on the new captain status + return; + component.HasCaptain = false; + component.TimeSinceCaptain = _ticker.RoundDuration(); + component.UnlockAA = false; // Captain has already brought AA in the round and should have resolved staffing issues already. + component.ACORequestDelay = TimeSpan.Zero; // Expedite the voting process due to midround and captain equipment being in play. + } + /// /// Handles cases for when there is a captain /// @@ -35,7 +68,7 @@ public override void Update(float frameTime) private void HandleHasCaptain(Entity station, CaptainStateComponent captainState) { // If ACO vote has been called we need to cancel and alert to return to normal chain of command - if (captainState.IsACORequestActive == false) + if (!captainState.IsACORequestActive) return; _chat.DispatchStationAnnouncement(station, Loc.GetString(captainState.RevokeACOMessage), colorOverride: Color.Gold); captainState.IsACORequestActive = false; diff --git a/Content.Server/Station/Systems/StationSystem.cs b/Content.Server/Station/Systems/StationSystem.cs index 77d152dc5d2..6d750611472 100644 --- a/Content.Server/Station/Systems/StationSystem.cs +++ b/Content.Server/Station/Systems/StationSystem.cs @@ -51,8 +51,6 @@ public override void Initialize() SubscribeLocalEvent(OnStationDeleted); SubscribeLocalEvent(OnStationGridDeleted); SubscribeLocalEvent(OnStationSplitEvent); - SubscribeLocalEvent(OnPlayerJobAdded); // DeltaV - SubscribeLocalEvent(OnPlayerJobsRemoved); // DeltaV _player.PlayerStatusChanged += OnPlayerStatusChanged; } @@ -153,39 +151,6 @@ private void OnRoundEnd(GameRunLevelChangedEvent eventArgs) } } - // DeltaV Handle PlayerJob Events - public void OnPlayerJobAdded(Entity station, ref PlayerJobAddedEvent args) - { - if (args.JobPrototypeId == "Captain") - { - CaptainStateComponent? captainStateComponent = null; - if (Resolve(station, ref captainStateComponent, false)) - captainStateComponent.HasCaptain = true; - } - } - public void OnPlayerJobsRemoved(EntityUid station, StationJobsComponent stationJobs, ref PlayerJobsRemovedEvent args) - { - if (args.PlayerJobs == null) - return; - - // If the player that left was the only captain then there is no captain - if (args.PlayerJobs.Contains("Captain")) - { - if (stationJobs.PlayerJobs.Count == 0 || !stationJobs.PlayerJobs.Any(playerJobs => playerJobs.Value.Contains("Captain"))) // Expensive but only ran if a cap leaves so fine - { - CaptainStateComponent? captainStateComponent = null; - if (Resolve(station, ref captainStateComponent, false)) - { - captainStateComponent.HasCaptain = false; - captainStateComponent.TimeSinceCaptain = GameTicker.RoundDuration(); - captainStateComponent.UnlockAA = false; // Captain has already brought AA in the round and should have resolved staffing issues already. - captainStateComponent.ACORequestDelay = TimeSpan.Zero; // Expedite the voting process due to midround and captain equipment being in play. - } - } - } - } - // DeltaV End handle PlayerJob Events - #endregion Event handlers /// From 97f02252bb69ea7a54d70f49bbb91a7db96d6688 Mon Sep 17 00:00:00 2001 From: SolStar2 <44028047+ewokswagger@users.noreply.github.com> Date: Tue, 3 Dec 2024 17:51:25 -0500 Subject: [PATCH 14/27] track spareidsafe with comp instead --- .../DeltaV/Cabinet/SpareIDSafeComponent.cs | 6 ++++ .../Components/CaptainStateComponent.cs | 8 +----- .../Station/Systems/CaptainStateSystem.cs | 21 ++++++++++++-- .../Station/Systems/StationSystem.cs | 3 -- .../Access/Systems/AccessReaderSystem.cs | 28 ------------------- .../Objects/Specific/Command/safe.yml | 3 +- 6 files changed, 27 insertions(+), 42 deletions(-) create mode 100644 Content.Server/DeltaV/Cabinet/SpareIDSafeComponent.cs diff --git a/Content.Server/DeltaV/Cabinet/SpareIDSafeComponent.cs b/Content.Server/DeltaV/Cabinet/SpareIDSafeComponent.cs new file mode 100644 index 00000000000..089dd68a08d --- /dev/null +++ b/Content.Server/DeltaV/Cabinet/SpareIDSafeComponent.cs @@ -0,0 +1,6 @@ +namespace Content.Server.DeltaV.Cabinet; + +[RegisterComponent] +public sealed partial class SpareIDSafeComponent : Component +{ +} diff --git a/Content.Server/DeltaV/Station/Components/CaptainStateComponent.cs b/Content.Server/DeltaV/Station/Components/CaptainStateComponent.cs index 3eb9bba8b39..0060e97187c 100644 --- a/Content.Server/DeltaV/Station/Components/CaptainStateComponent.cs +++ b/Content.Server/DeltaV/Station/Components/CaptainStateComponent.cs @@ -75,15 +75,9 @@ public sealed partial class CaptainStateComponent : Component [DataField] public LocId AAUnlockedMessage = "no-captain-aa-unlocked-announcement"; - /// - /// The access level used to identify spare ID cabinets - /// - [DataField] - public List> EmergencyAAAccess = new() { "DV-SpareSafe" }; - /// /// The access level to grant to spare ID cabinets /// [DataField] - public List> ACOAccess = new() { "Command" }; + public ProtoId ACOAccess = "Command"; } diff --git a/Content.Server/DeltaV/Station/Systems/CaptainStateSystem.cs b/Content.Server/DeltaV/Station/Systems/CaptainStateSystem.cs index 2730b8c8d56..0bced463a59 100644 --- a/Content.Server/DeltaV/Station/Systems/CaptainStateSystem.cs +++ b/Content.Server/DeltaV/Station/Systems/CaptainStateSystem.cs @@ -1,19 +1,22 @@ using Content.Server.Chat.Systems; +using Content.Server.DeltaV.Cabinet; using Content.Server.DeltaV.Station.Components; using Content.Server.DeltaV.Station.Events; using Content.Server.GameTicking; using Content.Server.Station.Components; -using Content.Server.Station.Systems; +using Content.Shared.Access.Components; +using Content.Shared.Access; using Content.Shared.Access.Systems; +using Robust.Shared.Prototypes; using System.Linq; namespace Content.Server.DeltaV.Station.Systems; public sealed class CaptainStateSystem : EntitySystem { + [Dependency] private readonly AccessReaderSystem _reader = default!; [Dependency] private readonly ChatSystem _chat = default!; [Dependency] private readonly GameTicker _ticker = default!; - [Dependency] private readonly IEntityManager _entity = default!; public override void Initialize() { @@ -93,7 +96,19 @@ private void HandleNoCaptain(Entity station, CaptainStat _chat.DispatchStationAnnouncement(station, Loc.GetString(captainState.AAUnlockedMessage), colorOverride: Color.Red); // Extend access of spare id lockers to command so they can access emergency AA - _entity.System().ExpandAccessForAllReaders(captainState.EmergencyAAAccess, captainState.ACOAccess); + var query = EntityQueryEnumerator(); + while (query.MoveNext(out var spareIDSafe, out var _)) + { + if (!TryComp(spareIDSafe, out var accessReader)) + continue; + var acceses = accessReader.AccessLists; + if (acceses.Count <= 0) // Avoid restricting access for readers with no accesses + continue; + // Awful and disgusting but the accessReader has no proper api for adding acceses to readers without awful type casting. See AccessOverriderSystem + acceses.Add(new HashSet> { captainState.ACOAccess }); + Dirty(spareIDSafe, accessReader); + RaiseLocalEvent(spareIDSafe, new AccessReaderConfigurationChangedEvent()); + } } } diff --git a/Content.Server/Station/Systems/StationSystem.cs b/Content.Server/Station/Systems/StationSystem.cs index 6d750611472..22c0cba3f78 100644 --- a/Content.Server/Station/Systems/StationSystem.cs +++ b/Content.Server/Station/Systems/StationSystem.cs @@ -1,7 +1,5 @@ using System.Linq; using Content.Server.Chat.Systems; -using Content.Server.DeltaV.Station.Components; // DeltaV -using Content.Server.DeltaV.Station.Events; // DeltaV using Content.Server.GameTicking; using Content.Server.Station.Components; using Content.Server.Station.Events; @@ -36,7 +34,6 @@ public sealed class StationSystem : EntitySystem [Dependency] private readonly SharedTransformSystem _transform = default!; [Dependency] private readonly MetaDataSystem _metaData = default!; [Dependency] private readonly MapSystem _map = default!; - [Dependency] public readonly GameTicker GameTicker = default!; // DeltaV private ISawmill _sawmill = default!; diff --git a/Content.Shared/Access/Systems/AccessReaderSystem.cs b/Content.Shared/Access/Systems/AccessReaderSystem.cs index b4a2b61cecf..f670ac860be 100644 --- a/Content.Shared/Access/Systems/AccessReaderSystem.cs +++ b/Content.Shared/Access/Systems/AccessReaderSystem.cs @@ -328,34 +328,6 @@ public void SetAccesses(EntityUid uid, AccessReaderComponent component, List - /// Extends access of readers accepted with the existing accesses to the new accesses. - /// - /// The existing access levels used to identify matching readers. - /// The new access levels to add. - /// List of affected Entities - /// Access Readers with no access restrictions are unaffected to preserve thier status. - public List ExpandAccessForAllReaders(ICollection> existingAcesss, List> newAccess) - { - List affected = new(); - var query = EntityQueryEnumerator(); - while (query.MoveNext(out var uid, out var accessReader)) - { - if (accessReader.AccessLists.Count == 0) // We need to exclude access readers with no restrictions or else all hallway doors will suddenly need the new access - continue; - if (!AreAccessTagsAllowed(existingAcesss, accessReader)) - continue; - affected.Add(uid); - foreach (var access in newAccess) - accessReader.AccessLists.Add(new HashSet>() { access }); - Dirty(uid, accessReader); - RaiseLocalEvent(uid, new AccessReaderConfigurationChangedEvent()); - } - return affected; - } - // DeltaV End expanding access logic - public bool FindAccessItemsInventory(EntityUid uid, out HashSet items) { items = new(); diff --git a/Resources/Prototypes/DeltaV/Entities/Objects/Specific/Command/safe.yml b/Resources/Prototypes/DeltaV/Entities/Objects/Specific/Command/safe.yml index 3998f238062..c551ec1c704 100644 --- a/Resources/Prototypes/DeltaV/Entities/Objects/Specific/Command/safe.yml +++ b/Resources/Prototypes/DeltaV/Entities/Objects/Specific/Command/safe.yml @@ -1,4 +1,4 @@ -- type: entity +- type: entity parent: FireAxeCabinet id: SpareIdCabinet name: spare id cabinet @@ -39,6 +39,7 @@ - IdCard - type: AccessReader access: [["DV-SpareSafe"]] + - type: SpareIDSafe - type: entity id: SpareIdCabinetFilled From 05f40208830bfe5b1c3cf487775bbf6233d0ae85 Mon Sep 17 00:00:00 2001 From: SolStar2 <44028047+ewokswagger@users.noreply.github.com> Date: Wed, 4 Dec 2024 19:05:23 -0500 Subject: [PATCH 15/27] little bit of movement --- .../DeltaV/Station/Systems/CaptainStateSystem.cs | 9 +++++++-- Resources/Prototypes/DeltaV/Entities/Stations/base.yml | 7 +++++++ Resources/Prototypes/Entities/Stations/nanotrasen.yml | 2 +- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/Content.Server/DeltaV/Station/Systems/CaptainStateSystem.cs b/Content.Server/DeltaV/Station/Systems/CaptainStateSystem.cs index 0bced463a59..b09be79d9e5 100644 --- a/Content.Server/DeltaV/Station/Systems/CaptainStateSystem.cs +++ b/Content.Server/DeltaV/Station/Systems/CaptainStateSystem.cs @@ -20,11 +20,16 @@ public sealed class CaptainStateSystem : EntitySystem public override void Initialize() { - SubscribeLocalEvent(OnPlayerJobAdded); // DeltaV - SubscribeLocalEvent(OnPlayerJobsRemoved); // DeltaV + SubscribeLocalEvent(OnPlayerJobAdded); + SubscribeLocalEvent(OnPlayerJobsRemoved); + SubscribeLocalEvent(OnRemove); base.Initialize(); } + private void OnRemove(Entity ent, ref ComponentRemove args) + { + } + public override void Update(float frameTime) { base.Update(frameTime); diff --git a/Resources/Prototypes/DeltaV/Entities/Stations/base.yml b/Resources/Prototypes/DeltaV/Entities/Stations/base.yml index fe31706b262..8e2163ee0e0 100644 --- a/Resources/Prototypes/DeltaV/Entities/Stations/base.yml +++ b/Resources/Prototypes/DeltaV/Entities/Stations/base.yml @@ -19,3 +19,10 @@ - displayName: stock-trading-company-donk basePrice: 90 currentPrice: 90 + +- type: entity + id: BaseStationCaptainState + abstract: true + components: + - type: CaptainState + diff --git a/Resources/Prototypes/Entities/Stations/nanotrasen.yml b/Resources/Prototypes/Entities/Stations/nanotrasen.yml index 48ecbcd0e8e..d294803168e 100644 --- a/Resources/Prototypes/Entities/Stations/nanotrasen.yml +++ b/Resources/Prototypes/Entities/Stations/nanotrasen.yml @@ -25,11 +25,11 @@ - BaseStationSiliconLawCrewsimov - BaseStationAllEventsEligible - BaseStationNanotrasen + - BaseStationCaptainState # DeltaV - BaseStationMail # Nyano component, required for station mail to function - BaseStationStockMarket # DeltaV categories: [ HideSpawnMenu ] components: - - type: CaptainState # DeltaV - type: Transform - type: entity From 5204be1cabecd1cd81d0fc157d37c718889bc21d Mon Sep 17 00:00:00 2001 From: SolStar <44028047+ewokswagger@users.noreply.github.com> Date: Wed, 4 Dec 2024 22:45:11 -0500 Subject: [PATCH 16/27] fix broken formating Signed-off-by: SolStar <44028047+ewokswagger@users.noreply.github.com> From 63c8267c0a64dcbdc9ec6f08dc202382fa790f41 Mon Sep 17 00:00:00 2001 From: SolStar2 <44028047+ewokswagger@users.noreply.github.com> Date: Wed, 4 Dec 2024 22:59:16 -0500 Subject: [PATCH 17/27] pls --- .../DeltaV/Entities/Objects/Specific/Command/safe.yml | 2 +- Resources/Prototypes/DeltaV/Entities/Stations/base.yml | 2 +- Resources/Prototypes/Entities/Stations/nanotrasen.yml | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Resources/Prototypes/DeltaV/Entities/Objects/Specific/Command/safe.yml b/Resources/Prototypes/DeltaV/Entities/Objects/Specific/Command/safe.yml index c551ec1c704..5e62caf1159 100644 --- a/Resources/Prototypes/DeltaV/Entities/Objects/Specific/Command/safe.yml +++ b/Resources/Prototypes/DeltaV/Entities/Objects/Specific/Command/safe.yml @@ -1,4 +1,4 @@ -- type: entity +- type: entity parent: FireAxeCabinet id: SpareIdCabinet name: spare id cabinet diff --git a/Resources/Prototypes/DeltaV/Entities/Stations/base.yml b/Resources/Prototypes/DeltaV/Entities/Stations/base.yml index 844c4aa345a..3c9d62bec9e 100644 --- a/Resources/Prototypes/DeltaV/Entities/Stations/base.yml +++ b/Resources/Prototypes/DeltaV/Entities/Stations/base.yml @@ -27,4 +27,4 @@ id: BaseStationCaptainState abstract: true components: - - type: CaptainState \ No newline at end of file + - type: CaptainState diff --git a/Resources/Prototypes/Entities/Stations/nanotrasen.yml b/Resources/Prototypes/Entities/Stations/nanotrasen.yml index d294803168e..6d88de1df50 100644 --- a/Resources/Prototypes/Entities/Stations/nanotrasen.yml +++ b/Resources/Prototypes/Entities/Stations/nanotrasen.yml @@ -1,4 +1,4 @@ -- type: entity +- type: entity abstract: true id: BaseStationNanotrasen components: @@ -25,8 +25,8 @@ - BaseStationSiliconLawCrewsimov - BaseStationAllEventsEligible - BaseStationNanotrasen - - BaseStationCaptainState # DeltaV - BaseStationMail # Nyano component, required for station mail to function + - BaseStationCaptainState # DeltaV - BaseStationStockMarket # DeltaV categories: [ HideSpawnMenu ] components: From 144dded9e16c1f00957271a509167a5a619b6aba Mon Sep 17 00:00:00 2001 From: SolStar2 <44028047+ewokswagger@users.noreply.github.com> Date: Thu, 5 Dec 2024 17:23:45 -0500 Subject: [PATCH 18/27] Remove unused method --- Content.Server/DeltaV/Station/Systems/CaptainStateSystem.cs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Content.Server/DeltaV/Station/Systems/CaptainStateSystem.cs b/Content.Server/DeltaV/Station/Systems/CaptainStateSystem.cs index b09be79d9e5..c5d6b87b8f9 100644 --- a/Content.Server/DeltaV/Station/Systems/CaptainStateSystem.cs +++ b/Content.Server/DeltaV/Station/Systems/CaptainStateSystem.cs @@ -22,14 +22,9 @@ public override void Initialize() { SubscribeLocalEvent(OnPlayerJobAdded); SubscribeLocalEvent(OnPlayerJobsRemoved); - SubscribeLocalEvent(OnRemove); base.Initialize(); } - private void OnRemove(Entity ent, ref ComponentRemove args) - { - } - public override void Update(float frameTime) { base.Update(frameTime); From fc70f542404c6ae99bfa90fedbc13c0a30bdb81d Mon Sep 17 00:00:00 2001 From: SolStar2 <44028047+ewokswagger@users.noreply.github.com> Date: Thu, 5 Dec 2024 17:51:18 -0500 Subject: [PATCH 19/27] subscribe captainstatecomponent for job events --- .../Station/Systems/CaptainStateSystem.cs | 27 +++++++++---------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/Content.Server/DeltaV/Station/Systems/CaptainStateSystem.cs b/Content.Server/DeltaV/Station/Systems/CaptainStateSystem.cs index c5d6b87b8f9..3cbff5881fb 100644 --- a/Content.Server/DeltaV/Station/Systems/CaptainStateSystem.cs +++ b/Content.Server/DeltaV/Station/Systems/CaptainStateSystem.cs @@ -20,8 +20,8 @@ public sealed class CaptainStateSystem : EntitySystem public override void Initialize() { - SubscribeLocalEvent(OnPlayerJobAdded); - SubscribeLocalEvent(OnPlayerJobsRemoved); + SubscribeLocalEvent(OnPlayerJobAdded); + SubscribeLocalEvent(OnPlayerJobsRemoved); base.Initialize(); } @@ -40,27 +40,24 @@ public override void Update(float frameTime) } } - private void OnPlayerJobAdded(Entity ent, ref PlayerJobAddedEvent args) + private void OnPlayerJobAdded(Entity ent, ref PlayerJobAddedEvent args) { if (args.JobPrototypeId == "Captain") - { - if (TryComp(ent, out var component)) - component.HasCaptain = true; - } + ent.Comp.HasCaptain = true; } - private void OnPlayerJobsRemoved(Entity ent, ref PlayerJobsRemovedEvent args) + private void OnPlayerJobsRemoved(Entity ent, ref PlayerJobsRemovedEvent args) { - if (args.PlayerJobs == null || !args.PlayerJobs.Contains("Captain")) // If the player that left was a captain we need to check if there are any captains left + if (!TryComp(ent, out var stationJobs)) return; - if (ent.Comp.PlayerJobs.Count != 0 && ent.Comp.PlayerJobs.Any(playerJobs => playerJobs.Value.Contains("Captain"))) // We check the PlayerJobs if there are any cpatins left + if (args.PlayerJobs == null || !args.PlayerJobs.Contains("Captain")) // If the player that left was a captain we need to check if there are any captains left return; - if (!TryComp(ent, out var component)) // We update CaptainState if the station has one on the new captain status + if (stationJobs.PlayerJobs.Any(playerJobs => playerJobs.Value.Contains("Captain"))) // We check the PlayerJobs if there are any cpatins left return; - component.HasCaptain = false; - component.TimeSinceCaptain = _ticker.RoundDuration(); - component.UnlockAA = false; // Captain has already brought AA in the round and should have resolved staffing issues already. - component.ACORequestDelay = TimeSpan.Zero; // Expedite the voting process due to midround and captain equipment being in play. + ent.Comp.HasCaptain = false; + ent.Comp.TimeSinceCaptain = _ticker.RoundDuration(); + ent.Comp.UnlockAA = false; // Captain has already brought AA in the round and should have resolved staffing issues already. + ent.Comp.ACORequestDelay = TimeSpan.Zero; // Expedite the voting process due to midround and captain equipment being in play. } /// From 5516ea561f519d34cb2751a0978f69a8625f07d2 Mon Sep 17 00:00:00 2001 From: SolStar2 <44028047+ewokswagger@users.noreply.github.com> Date: Sun, 8 Dec 2024 05:43:42 -0500 Subject: [PATCH 20/27] Cvars, Disabled AA on peri --- .../Components/CaptainStateComponent.cs | 24 ++---------- .../Station/Systems/CaptainStateSystem.cs | 39 ++++++++++++++----- Content.Shared/DeltaV/CCVars/DCCVars.cs | 31 ++++++++++++++- Resources/ConfigPresets/DeltaV/apoapsis.toml | 1 + 4 files changed, 64 insertions(+), 31 deletions(-) diff --git a/Content.Server/DeltaV/Station/Components/CaptainStateComponent.cs b/Content.Server/DeltaV/Station/Components/CaptainStateComponent.cs index 0060e97187c..0e9663a8e00 100644 --- a/Content.Server/DeltaV/Station/Components/CaptainStateComponent.cs +++ b/Content.Server/DeltaV/Station/Components/CaptainStateComponent.cs @@ -9,7 +9,7 @@ namespace Content.Server.DeltaV.Station.Components; /// /// Denotes a station has no captain and holds data for automatic ACO systems /// -[RegisterComponent, Access(typeof(CaptainStateSystem), typeof(StationSystem)), AutoGenerateComponentPause] +[RegisterComponent, Access(typeof(CaptainStateSystem), typeof(StationSystem))] public sealed partial class CaptainStateComponent : Component { /// @@ -21,18 +21,6 @@ public sealed partial class CaptainStateComponent : Component [DataField] public bool HasCaptain; - /// - /// Holds the round time of the last time a captain was present if one is not present currently - /// - [DataField("TimeSinceCaptain", customTypeSerializer: typeof(TimeOffsetSerializer)), AutoPausedField] - public TimeSpan TimeSinceCaptain = TimeSpan.Zero; - - /// - /// How long with no captain before an ACO is requested - /// - [DataField] - public TimeSpan ACORequestDelay = TimeSpan.FromMinutes(15); - /// /// The localization ID used for announcing the cancellation of ACO requests /// @@ -58,16 +46,10 @@ public sealed partial class CaptainStateComponent : Component public bool IsACORequestActive; /// - /// Used to denote that AA should be unlocked after the delay - /// - [DataField] - public bool UnlockAA = true; - - /// - /// How long after ACO is requested the spare id cabinet will be unlocked if applicable + /// Used to denote that AA has been brought into the round either from captain or safe. /// [DataField] - public TimeSpan UnlockAADelay = TimeSpan.FromMinutes(5); + public bool IsAAInPlay; /// /// The localization ID for announcing that AA has been unlocked for ACO diff --git a/Content.Server/DeltaV/Station/Systems/CaptainStateSystem.cs b/Content.Server/DeltaV/Station/Systems/CaptainStateSystem.cs index 3cbff5881fb..86efc16f9f1 100644 --- a/Content.Server/DeltaV/Station/Systems/CaptainStateSystem.cs +++ b/Content.Server/DeltaV/Station/Systems/CaptainStateSystem.cs @@ -9,6 +9,9 @@ using Content.Shared.Access.Systems; using Robust.Shared.Prototypes; using System.Linq; +using Robust.Shared.Configuration; +using Content.Shared.DeltaV.CCVars; +using static Content.Shared.Administration.Notes.AdminMessageEuiState; namespace Content.Server.DeltaV.Station.Systems; @@ -17,11 +20,21 @@ public sealed class CaptainStateSystem : EntitySystem [Dependency] private readonly AccessReaderSystem _reader = default!; [Dependency] private readonly ChatSystem _chat = default!; [Dependency] private readonly GameTicker _ticker = default!; + [Dependency] private readonly IConfigurationManager _cfg = default!; + + private bool _aaEnabled; + private TimeSpan _aaDelay; + private TimeSpan _acoDelay; + private bool _acoOnDeparture; public override void Initialize() { SubscribeLocalEvent(OnPlayerJobAdded); SubscribeLocalEvent(OnPlayerJobsRemoved); + Subs.CVar(_cfg, DCCVars.AutoUnlockAllAccessEnabled, a => _aaEnabled = a, true); + Subs.CVar(_cfg, DCCVars.AutoUnlockAllAccessDelay, a => _aaDelay = a, true); + Subs.CVar(_cfg, DCCVars.RequestAcoDelay, a => _acoDelay = a, true); + Subs.CVar(_cfg, DCCVars.RequestAcoOnCaptainDeparture, a => _acoOnDeparture = a, true); base.Initialize(); } @@ -43,7 +56,10 @@ public override void Update(float frameTime) private void OnPlayerJobAdded(Entity ent, ref PlayerJobAddedEvent args) { if (args.JobPrototypeId == "Captain") + { + ent.Comp.IsAAInPlay = true; ent.Comp.HasCaptain = true; + } } private void OnPlayerJobsRemoved(Entity ent, ref PlayerJobsRemovedEvent args) @@ -55,9 +71,11 @@ private void OnPlayerJobsRemoved(Entity ent, ref PlayerJo if (stationJobs.PlayerJobs.Any(playerJobs => playerJobs.Value.Contains("Captain"))) // We check the PlayerJobs if there are any cpatins left return; ent.Comp.HasCaptain = false; - ent.Comp.TimeSinceCaptain = _ticker.RoundDuration(); - ent.Comp.UnlockAA = false; // Captain has already brought AA in the round and should have resolved staffing issues already. - ent.Comp.ACORequestDelay = TimeSpan.Zero; // Expedite the voting process due to midround and captain equipment being in play. + if (_acoOnDeparture) + { + _chat.DispatchStationAnnouncement(ent, Loc.GetString(ent.Comp.ACORequestNoAAMessage, ("minutes", _aaDelay.TotalMinutes)), colorOverride: Color.Gold); + ent.Comp.IsACORequestActive = true; + } } /// @@ -83,13 +101,13 @@ private void HandleNoCaptain(Entity station, CaptainStat { if (CheckACORequest(captainState, currentTime)) { - var message = captainState.UnlockAA ? captainState.ACORequestWithAAMessage : captainState.ACORequestNoAAMessage; - _chat.DispatchStationAnnouncement(station, Loc.GetString(message, ("minutes", captainState.UnlockAADelay.TotalMinutes)), colorOverride: Color.Gold); + var message = CheckUnlockAA(captainState, null) ? captainState.ACORequestWithAAMessage : captainState.ACORequestNoAAMessage; + _chat.DispatchStationAnnouncement(station, Loc.GetString(message, ("minutes", _aaDelay.TotalMinutes)), colorOverride: Color.Gold); captainState.IsACORequestActive = true; } if (CheckUnlockAA(captainState, currentTime)) { - captainState.UnlockAA = false; // Once unlocked don't unlock again + captainState.IsAAInPlay = true; _chat.DispatchStationAnnouncement(station, Loc.GetString(captainState.AAUnlockedMessage), colorOverride: Color.Red); // Extend access of spare id lockers to command so they can access emergency AA @@ -116,16 +134,19 @@ private void HandleNoCaptain(Entity station, CaptainStat /// True if conditions are met for an ACO to be requested, False otherwise private bool CheckACORequest(CaptainStateComponent captainState, TimeSpan currentTime) { - return !captainState.IsACORequestActive && currentTime > captainState.TimeSinceCaptain + captainState.ACORequestDelay; + return !captainState.IsACORequestActive && currentTime > _acoDelay; } /// /// Checks the conditions for if AA should be unlocked + /// If time is null its condition is ignored /// /// /// True if conditions are met for AA to be unlocked, False otherwise - private bool CheckUnlockAA(CaptainStateComponent captainState, TimeSpan currentTime) + private bool CheckUnlockAA(CaptainStateComponent captainState, TimeSpan? currentTime) { - return captainState.UnlockAA && currentTime > captainState.TimeSinceCaptain + captainState.ACORequestDelay + captainState.UnlockAADelay; + if (captainState.IsAAInPlay || !_aaEnabled) + return false; + return currentTime == null || currentTime > _acoDelay + _aaDelay; } } diff --git a/Content.Shared/DeltaV/CCVars/DCCVars.cs b/Content.Shared/DeltaV/CCVars/DCCVars.cs index 984ff2778af..494ed185d1b 100644 --- a/Content.Shared/DeltaV/CCVars/DCCVars.cs +++ b/Content.Shared/DeltaV/CCVars/DCCVars.cs @@ -1,4 +1,4 @@ -using Robust.Shared.Configuration; +using Robust.Shared.Configuration; namespace Content.Shared.DeltaV.CCVars; @@ -62,6 +62,35 @@ public sealed class DCCVars public static readonly CVarDef RoundEndNoEorgPopupTime = CVarDef.Create("game.round_end_eorg_popup_time", 5f, CVar.SERVER | CVar.REPLICATED); + /* + * Auto ACO + */ + + /// + /// How long with no captain before requesting an ACO be elected. + /// + public static readonly CVarDef RequestAcoDelay = + CVarDef.Create("game.request_aco_delay", TimeSpan.FromMinutes(15), CVar.SERVERONLY | CVar.ARCHIVE); + + /// + /// Determines whether an ACO should be requested when the captain leaves during the round, + /// in addition to cases where there are no captains at round start. + /// + public static readonly CVarDef RequestAcoOnCaptainDeparture = + CVarDef.Create("game.request_aco_on_captain_departure", true, CVar.SERVERONLY | CVar.ARCHIVE); + + /// + /// Determines whether All Access (AA) should be automatically unlocked if no captain is present. + /// + public static readonly CVarDef AutoUnlockAllAccessEnabled = + CVarDef.Create("game.auto_unlock_aa_enabled", true, CVar.SERVERONLY | CVar.ARCHIVE); + + /// + /// How long after an ACO request announcement is made before All Access (AA) should be unlocked. + /// + public static readonly CVarDef AutoUnlockAllAccessDelay = + CVarDef.Create("game.auto_unlock_aa_delay", TimeSpan.FromMinutes(5), CVar.SERVERONLY | CVar.ARCHIVE); + /* * Misc. */ diff --git a/Resources/ConfigPresets/DeltaV/apoapsis.toml b/Resources/ConfigPresets/DeltaV/apoapsis.toml index 6af4b979117..084af59a293 100644 --- a/Resources/ConfigPresets/DeltaV/apoapsis.toml +++ b/Resources/ConfigPresets/DeltaV/apoapsis.toml @@ -1,6 +1,7 @@ [game] hostname = "[EN][MRP] Delta-v (Ψ) | Apoapsis [US East 1]" soft_max_players = 80 +auto_unlock_aa_enabled = false # Disabled for peri until if/when command whitelist [shuttle] emergency_early_launch_allowed = true From 4f19a4536692478aebad3e8bffd3a39827d7770a Mon Sep 17 00:00:00 2001 From: SolStar2 <44028047+ewokswagger@users.noreply.github.com> Date: Sun, 8 Dec 2024 05:59:12 -0500 Subject: [PATCH 21/27] temp fix for intergration test bug --- Content.IntegrationTests/Tests/EntityTest.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Content.IntegrationTests/Tests/EntityTest.cs b/Content.IntegrationTests/Tests/EntityTest.cs index 42bea8989cd..55056de1471 100644 --- a/Content.IntegrationTests/Tests/EntityTest.cs +++ b/Content.IntegrationTests/Tests/EntityTest.cs @@ -268,6 +268,11 @@ await server.WaitPost(() => if (protoId == "MobHumanSpaceNinja") continue; + // TODO fix tests properly upstream + // Fails due to audio components made when making anouncements + if (protoId == "StandardNanotrasenStation") + continue; + var count = server.EntMan.EntityCount; var clientCount = client.EntMan.EntityCount; EntityUid uid = default; From 903de99a5c547d1537479e042804d9122e52e722 Mon Sep 17 00:00:00 2001 From: SolStar2 <44028047+ewokswagger@users.noreply.github.com> Date: Sun, 8 Dec 2024 15:26:43 -0500 Subject: [PATCH 22/27] :3 --- Content.Server/DeltaV/Cabinet/SpareIDSafeComponent.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Content.Server/DeltaV/Cabinet/SpareIDSafeComponent.cs b/Content.Server/DeltaV/Cabinet/SpareIDSafeComponent.cs index 089dd68a08d..40f97486ce3 100644 --- a/Content.Server/DeltaV/Cabinet/SpareIDSafeComponent.cs +++ b/Content.Server/DeltaV/Cabinet/SpareIDSafeComponent.cs @@ -1,6 +1,4 @@ namespace Content.Server.DeltaV.Cabinet; [RegisterComponent] -public sealed partial class SpareIDSafeComponent : Component -{ -} +public sealed partial class SpareIDSafeComponent : Component; From 6584cfcaa600999d3cfec42f72fee28d6f321ec0 Mon Sep 17 00:00:00 2001 From: SolStar2 <44028047+ewokswagger@users.noreply.github.com> Date: Sun, 8 Dec 2024 20:59:12 -0500 Subject: [PATCH 23/27] format fix --- Resources/Prototypes/DeltaV/Entities/Stations/base.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Resources/Prototypes/DeltaV/Entities/Stations/base.yml b/Resources/Prototypes/DeltaV/Entities/Stations/base.yml index 3c9d62bec9e..ffeb605adc2 100644 --- a/Resources/Prototypes/DeltaV/Entities/Stations/base.yml +++ b/Resources/Prototypes/DeltaV/Entities/Stations/base.yml @@ -27,4 +27,4 @@ id: BaseStationCaptainState abstract: true components: - - type: CaptainState + - type: CaptainState From 1d35c10f8f9b9044983fd0d596d4f64a93b6bfba Mon Sep 17 00:00:00 2001 From: SolStar2 <44028047+ewokswagger@users.noreply.github.com> Date: Mon, 9 Dec 2024 01:04:27 -0500 Subject: [PATCH 24/27] spelling ops --- .../Components/CaptainStateComponent.cs | 1 - .../Station/Systems/CaptainStateSystem.cs | 46 ++++++++++++------- Resources/ConfigPresets/DeltaV/apoapsis.toml | 2 +- 3 files changed, 31 insertions(+), 18 deletions(-) diff --git a/Content.Server/DeltaV/Station/Components/CaptainStateComponent.cs b/Content.Server/DeltaV/Station/Components/CaptainStateComponent.cs index 0e9663a8e00..96d7c441071 100644 --- a/Content.Server/DeltaV/Station/Components/CaptainStateComponent.cs +++ b/Content.Server/DeltaV/Station/Components/CaptainStateComponent.cs @@ -2,7 +2,6 @@ using Content.Server.Station.Systems; using Content.Shared.Access; using Robust.Shared.Prototypes; -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom; namespace Content.Server.DeltaV.Station.Components; diff --git a/Content.Server/DeltaV/Station/Systems/CaptainStateSystem.cs b/Content.Server/DeltaV/Station/Systems/CaptainStateSystem.cs index 86efc16f9f1..fe89518b528 100644 --- a/Content.Server/DeltaV/Station/Systems/CaptainStateSystem.cs +++ b/Content.Server/DeltaV/Station/Systems/CaptainStateSystem.cs @@ -5,25 +5,23 @@ using Content.Server.GameTicking; using Content.Server.Station.Components; using Content.Shared.Access.Components; -using Content.Shared.Access; using Content.Shared.Access.Systems; +using Content.Shared.Access; +using Content.Shared.DeltaV.CCVars; +using Robust.Shared.Configuration; using Robust.Shared.Prototypes; using System.Linq; -using Robust.Shared.Configuration; -using Content.Shared.DeltaV.CCVars; -using static Content.Shared.Administration.Notes.AdminMessageEuiState; namespace Content.Server.DeltaV.Station.Systems; public sealed class CaptainStateSystem : EntitySystem { - [Dependency] private readonly AccessReaderSystem _reader = default!; [Dependency] private readonly ChatSystem _chat = default!; [Dependency] private readonly GameTicker _ticker = default!; [Dependency] private readonly IConfigurationManager _cfg = default!; - private bool _aaEnabled; private TimeSpan _aaDelay; + private bool _aaEnabled; private TimeSpan _acoDelay; private bool _acoOnDeparture; @@ -31,8 +29,8 @@ public override void Initialize() { SubscribeLocalEvent(OnPlayerJobAdded); SubscribeLocalEvent(OnPlayerJobsRemoved); - Subs.CVar(_cfg, DCCVars.AutoUnlockAllAccessEnabled, a => _aaEnabled = a, true); Subs.CVar(_cfg, DCCVars.AutoUnlockAllAccessDelay, a => _aaDelay = a, true); + Subs.CVar(_cfg, DCCVars.AutoUnlockAllAccessEnabled, a => _aaEnabled = a, true); Subs.CVar(_cfg, DCCVars.RequestAcoDelay, a => _acoDelay = a, true); Subs.CVar(_cfg, DCCVars.RequestAcoOnCaptainDeparture, a => _acoOnDeparture = a, true); base.Initialize(); @@ -66,14 +64,18 @@ private void OnPlayerJobsRemoved(Entity ent, ref PlayerJo { if (!TryComp(ent, out var stationJobs)) return; - if (args.PlayerJobs == null || !args.PlayerJobs.Contains("Captain")) // If the player that left was a captain we need to check if there are any captains left + if (!args.PlayerJobs.Contains("Captain")) // If the player that left was a captain we need to check if there are any captains left return; if (stationJobs.PlayerJobs.Any(playerJobs => playerJobs.Value.Contains("Captain"))) // We check the PlayerJobs if there are any cpatins left return; ent.Comp.HasCaptain = false; if (_acoOnDeparture) { - _chat.DispatchStationAnnouncement(ent, Loc.GetString(ent.Comp.ACORequestNoAAMessage, ("minutes", _aaDelay.TotalMinutes)), colorOverride: Color.Gold); + _chat.DispatchStationAnnouncement( + ent, + Loc.GetString(ent.Comp.ACORequestNoAAMessage, ("minutes", _aaDelay.TotalMinutes)), + colorOverride: Color.Gold); + ent.Comp.IsACORequestActive = true; } } @@ -88,7 +90,11 @@ private void HandleHasCaptain(Entity station, CaptainSta // If ACO vote has been called we need to cancel and alert to return to normal chain of command if (!captainState.IsACORequestActive) return; - _chat.DispatchStationAnnouncement(station, Loc.GetString(captainState.RevokeACOMessage), colorOverride: Color.Gold); + + _chat.DispatchStationAnnouncement(station, + Loc.GetString(captainState.RevokeACOMessage), + colorOverride: Color.Gold); + captainState.IsACORequestActive = false; } @@ -101,8 +107,16 @@ private void HandleNoCaptain(Entity station, CaptainStat { if (CheckACORequest(captainState, currentTime)) { - var message = CheckUnlockAA(captainState, null) ? captainState.ACORequestWithAAMessage : captainState.ACORequestNoAAMessage; - _chat.DispatchStationAnnouncement(station, Loc.GetString(message, ("minutes", _aaDelay.TotalMinutes)), colorOverride: Color.Gold); + var message = + CheckUnlockAA(captainState, null) + ? captainState.ACORequestWithAAMessage + : captainState.ACORequestNoAAMessage; + + _chat.DispatchStationAnnouncement( + station, + Loc.GetString(message, ("minutes", _aaDelay.TotalMinutes)), + colorOverride: Color.Gold); + captainState.IsACORequestActive = true; } if (CheckUnlockAA(captainState, currentTime)) @@ -112,15 +126,15 @@ private void HandleNoCaptain(Entity station, CaptainStat // Extend access of spare id lockers to command so they can access emergency AA var query = EntityQueryEnumerator(); - while (query.MoveNext(out var spareIDSafe, out var _)) + while (query.MoveNext(out var spareIDSafe, out _)) { if (!TryComp(spareIDSafe, out var accessReader)) continue; - var acceses = accessReader.AccessLists; - if (acceses.Count <= 0) // Avoid restricting access for readers with no accesses + var accesses = accessReader.AccessLists; + if (accesses.Count <= 0) // Avoid restricting access for readers with no accesses continue; // Awful and disgusting but the accessReader has no proper api for adding acceses to readers without awful type casting. See AccessOverriderSystem - acceses.Add(new HashSet> { captainState.ACOAccess }); + accesses.Add(new HashSet> { captainState.ACOAccess }); Dirty(spareIDSafe, accessReader); RaiseLocalEvent(spareIDSafe, new AccessReaderConfigurationChangedEvent()); } diff --git a/Resources/ConfigPresets/DeltaV/apoapsis.toml b/Resources/ConfigPresets/DeltaV/apoapsis.toml index 084af59a293..6e1c4280822 100644 --- a/Resources/ConfigPresets/DeltaV/apoapsis.toml +++ b/Resources/ConfigPresets/DeltaV/apoapsis.toml @@ -1,7 +1,7 @@ [game] hostname = "[EN][MRP] Delta-v (Ψ) | Apoapsis [US East 1]" soft_max_players = 80 -auto_unlock_aa_enabled = false # Disabled for peri until if/when command whitelist +auto_unlock_aa_enabled = false # Disabled for apo until if/when command whitelist [shuttle] emergency_early_launch_allowed = true From 3102804b6f8ea68777e4292297074a023728450e Mon Sep 17 00:00:00 2001 From: SolStar2 <44028047+ewokswagger@users.noreply.github.com> Date: Mon, 9 Dec 2024 01:20:24 -0500 Subject: [PATCH 25/27] nameing ops --- .../DeltaV/Station/Systems/CaptainStateSystem.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Content.Server/DeltaV/Station/Systems/CaptainStateSystem.cs b/Content.Server/DeltaV/Station/Systems/CaptainStateSystem.cs index fe89518b528..d9efb31327d 100644 --- a/Content.Server/DeltaV/Station/Systems/CaptainStateSystem.cs +++ b/Content.Server/DeltaV/Station/Systems/CaptainStateSystem.cs @@ -20,19 +20,19 @@ public sealed class CaptainStateSystem : EntitySystem [Dependency] private readonly GameTicker _ticker = default!; [Dependency] private readonly IConfigurationManager _cfg = default!; - private TimeSpan _aaDelay; private bool _aaEnabled; - private TimeSpan _acoDelay; private bool _acoOnDeparture; + private TimeSpan _aaDelay; + private TimeSpan _acoDelay; public override void Initialize() { SubscribeLocalEvent(OnPlayerJobAdded); SubscribeLocalEvent(OnPlayerJobsRemoved); - Subs.CVar(_cfg, DCCVars.AutoUnlockAllAccessDelay, a => _aaDelay = a, true); Subs.CVar(_cfg, DCCVars.AutoUnlockAllAccessEnabled, a => _aaEnabled = a, true); - Subs.CVar(_cfg, DCCVars.RequestAcoDelay, a => _acoDelay = a, true); Subs.CVar(_cfg, DCCVars.RequestAcoOnCaptainDeparture, a => _acoOnDeparture = a, true); + Subs.CVar(_cfg, DCCVars.AutoUnlockAllAccessDelay, a => _aaDelay = a, true); + Subs.CVar(_cfg, DCCVars.RequestAcoDelay, a => _acoDelay = a, true); base.Initialize(); } From 5f5503bab717aaf3853210be821792c533540543 Mon Sep 17 00:00:00 2001 From: SolStar2 <44028047+ewokswagger@users.noreply.github.com> Date: Mon, 9 Dec 2024 01:23:31 -0500 Subject: [PATCH 26/27] done final real this time (1) (1) --- Content.Server/DeltaV/Station/Systems/CaptainStateSystem.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/Content.Server/DeltaV/Station/Systems/CaptainStateSystem.cs b/Content.Server/DeltaV/Station/Systems/CaptainStateSystem.cs index d9efb31327d..328994d1782 100644 --- a/Content.Server/DeltaV/Station/Systems/CaptainStateSystem.cs +++ b/Content.Server/DeltaV/Station/Systems/CaptainStateSystem.cs @@ -5,7 +5,6 @@ using Content.Server.GameTicking; using Content.Server.Station.Components; using Content.Shared.Access.Components; -using Content.Shared.Access.Systems; using Content.Shared.Access; using Content.Shared.DeltaV.CCVars; using Robust.Shared.Configuration; From e938cf47301a73528c53f63279a2575510eac64d Mon Sep 17 00:00:00 2001 From: SolStar2 <44028047+ewokswagger@users.noreply.github.com> Date: Mon, 9 Dec 2024 01:26:34 -0500 Subject: [PATCH 27/27] remove has an out very nice --- Content.Server/Station/Systems/StationJobsSystem.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Content.Server/Station/Systems/StationJobsSystem.cs b/Content.Server/Station/Systems/StationJobsSystem.cs index 672e40b1e2d..227c5630839 100644 --- a/Content.Server/Station/Systems/StationJobsSystem.cs +++ b/Content.Server/Station/Systems/StationJobsSystem.cs @@ -209,9 +209,8 @@ public bool TryRemovePlayerJobs(EntityUid station, if (!Resolve(station, ref jobsComponent, false)) return false; // DeltaV added RemovedPlayerJobsEvent for CaptainStateSystem - if (jobsComponent.PlayerJobs.TryGetValue(userId, out var playerJobsEntry)) + if (jobsComponent.PlayerJobs.Remove(userId, out var playerJobsEntry)) { - jobsComponent.PlayerJobs.Remove(userId); var playerJobRemovedEvent = new PlayerJobsRemovedEvent(userId, playerJobsEntry); RaiseLocalEvent(station, ref playerJobRemovedEvent, false); return true;