diff --git a/Content.Server/GameObjects/Components/Doors/ServerDoorComponent.cs b/Content.Server/GameObjects/Components/Doors/ServerDoorComponent.cs index d4579037db..1a0aeb7b21 100644 --- a/Content.Server/GameObjects/Components/Doors/ServerDoorComponent.cs +++ b/Content.Server/GameObjects/Components/Doors/ServerDoorComponent.cs @@ -6,6 +6,7 @@ using Content.Server.GameObjects.Components.Access; using Content.Server.GameObjects.Components.Atmos; using Content.Server.GameObjects.Components.GUI; using Content.Server.GameObjects.Components.Mobs; +using Content.Server.GameObjects.EntitySystems; using Content.Shared.Damage; using Content.Shared.GameObjects.Components.Body; using Content.Shared.GameObjects.Components.Damage; @@ -134,28 +135,53 @@ namespace Content.Server.GameObjects.Components.Doors public bool CanOpen(IEntity user) { if (!CanOpen()) return false; - if (!Owner.TryGetComponent(out AccessReader? accessReader)) + + if (!Owner.TryGetComponent(out var accessReader)) { return true; } - return accessReader.IsAllowed(user); + var doorSystem = EntitySystem.Get(); + var isAirlockExternal = HasAccessType("External"); + + return doorSystem.AccessType switch + { + DoorSystem.AccessTypes.AllowAll => true, + DoorSystem.AccessTypes.AllowAllIdExternal => isAirlockExternal ? accessReader.IsAllowed(user) : true, + DoorSystem.AccessTypes.AllowAllNoExternal => !isAirlockExternal, + _ => accessReader.IsAllowed(user) + }; + } + + /// + /// Returns whether a door has a certain access type. For example, maintenance doors will have access type + /// "Maintenance" in their AccessReader. + /// + private bool HasAccessType(string accesType) + { + if(Owner.TryGetComponent(out var accessReader)) + { + return accessReader.AccessLists.Any(list => list.Contains(accesType)); + } + + return true; } public void TryOpen(IEntity user) { - if (!CanOpen(user)) + if (CanOpen(user)) + { + Open(); + + if (user.TryGetComponent(out HandsComponent? hands) && hands.Count == 0) + { + EntitySystem.Get().PlayFromEntity("/Audio/Effects/bang.ogg", Owner, + AudioParams.Default.WithVolume(-2)); + } + } + else { Deny(); - return; - } - - Open(); - - if (user.TryGetComponent(out HandsComponent? hands) && hands.Count == 0) - { - EntitySystem.Get().PlayFromEntity("/Audio/Effects/bang.ogg", Owner, - AudioParams.Default.WithVolume(-2)); } } diff --git a/Content.Server/GameObjects/EntitySystems/DoorSystem.cs b/Content.Server/GameObjects/EntitySystems/DoorSystem.cs index fb5d0fe432..8feb00ca24 100644 --- a/Content.Server/GameObjects/EntitySystems/DoorSystem.cs +++ b/Content.Server/GameObjects/EntitySystems/DoorSystem.cs @@ -1,10 +1,44 @@ using Content.Server.GameObjects.Components.Doors; +using JetBrains.Annotations; using Robust.Shared.GameObjects.Systems; namespace Content.Server.GameObjects.EntitySystems { + [UsedImplicitly] class DoorSystem : EntitySystem { + /// + /// Determines the base access behavior of all doors on the station. + /// + public AccessTypes AccessType { get; set; } + + /// + /// How door access should be handled. + /// + public enum AccessTypes + { + /// ID based door access. + Id, + /// + /// Allows everyone to open doors, except external which airlocks are still handled with ID's + /// + AllowAllIdExternal, + /// + /// Allows everyone to open doors, except external airlocks which are never allowed, even if the user has + /// ID access. + /// + AllowAllNoExternal, + /// Allows everyone to open all doors. + AllowAll + } + + public override void Initialize() + { + base.Initialize(); + + AccessType = AccessTypes.Id; + } + /// public override void Update(float frameTime) { diff --git a/Content.Server/GameTicking/GameRules/RuleSuspicion.cs b/Content.Server/GameTicking/GameRules/RuleSuspicion.cs index f004eed7d4..7a870375bd 100644 --- a/Content.Server/GameTicking/GameRules/RuleSuspicion.cs +++ b/Content.Server/GameTicking/GameRules/RuleSuspicion.cs @@ -1,9 +1,9 @@ using System; using System.Threading; using Content.Server.GameObjects.Components.Suspicion; +using Content.Server.GameObjects.EntitySystems; using Content.Server.Interfaces.Chat; using Content.Server.Interfaces.GameTicking; -using Content.Server.Mobs; using Content.Server.Mobs.Roles; using Content.Server.Players; using Content.Shared.GameObjects.Components.Damage; @@ -38,6 +38,8 @@ namespace Content.Server.GameTicking.GameRules EntitySystem.Get().PlayGlobal("/Audio/Misc/tatoralert.ogg", AudioParams.Default, (session) => session.ContentData().Mind?.HasRole() ?? false); + EntitySystem.Get().AccessType = DoorSystem.AccessTypes.AllowAllNoExternal; + Timer.SpawnRepeating(DeadCheckDelay, _checkWinConditions, _checkTimerCancel.Token); } @@ -45,6 +47,8 @@ namespace Content.Server.GameTicking.GameRules { base.Removed(); + EntitySystem.Get().AccessType = DoorSystem.AccessTypes.Id; + _checkTimerCancel.Cancel(); }