diff --git a/Content.Server/Atmos/IGridAtmosphereComponent.cs b/Content.Server/Atmos/IGridAtmosphereComponent.cs
index fd5648c091..e16d630708 100644
--- a/Content.Server/Atmos/IGridAtmosphereComponent.cs
+++ b/Content.Server/Atmos/IGridAtmosphereComponent.cs
@@ -1,6 +1,7 @@
using System.Collections.Generic;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Map;
+using Robust.Shared.Maths;
namespace Content.Server.Atmos
{
@@ -151,6 +152,11 @@ namespace Content.Server.Atmos
///
float GetVolumeForCells(int cellCount);
+ ///
+ /// Returns a dictionary of adjacent TileAtmospheres.
+ ///
+ Dictionary GetAdjacentTiles(MapIndices indices, bool includeAirBlocked = false);
+
void Update(float frameTime);
}
}
diff --git a/Content.Server/GameObjects/Components/Atmos/FirelockComponent.cs b/Content.Server/GameObjects/Components/Atmos/FirelockComponent.cs
index 02d3ac22a5..03ec350359 100644
--- a/Content.Server/GameObjects/Components/Atmos/FirelockComponent.cs
+++ b/Content.Server/GameObjects/Components/Atmos/FirelockComponent.cs
@@ -1,35 +1,36 @@
-using System.Threading.Tasks;
+using System;
+using System.Threading.Tasks;
+using Content.Server.Atmos;
using Content.Server.GameObjects.Components.Doors;
using Content.Server.GameObjects.Components.Interactable;
+using Content.Server.Interfaces;
using Content.Shared.GameObjects.Components.Doors;
using Content.Shared.GameObjects.Components.Interactable;
using Content.Shared.Interfaces.GameObjects.Components;
using Robust.Shared.GameObjects;
using Robust.Shared.GameObjects.Components;
using Robust.Shared.Interfaces.GameObjects;
+using Robust.Shared.IoC;
namespace Content.Server.GameObjects.Components.Atmos
{
[RegisterComponent]
- public class FirelockComponent : ServerDoorComponent, IInteractUsing, IActivate, ICollideBehavior
+ public class FirelockComponent : ServerDoorComponent, IInteractUsing, ICollideBehavior
{
+ [Dependency] private IServerNotifyManager _notifyManager = default!;
+
public override string Name => "Firelock";
- public override void Initialize()
- {
- base.Initialize();
- }
+ protected override TimeSpan CloseTimeOne => TimeSpan.FromSeconds(0.1f);
+ protected override TimeSpan CloseTimeTwo => TimeSpan.FromSeconds(0.6f);
+ protected override TimeSpan OpenTimeOne => TimeSpan.FromSeconds(0.1f);
+ protected override TimeSpan OpenTimeTwo => TimeSpan.FromSeconds(0.6f);
public void CollideWith(IEntity collidedWith)
{
// We do nothing.
}
- public void Activate(ActivateEventArgs eventArgs)
- {
- // We do nothing.
- }
-
protected override void Startup()
{
base.Startup();
@@ -60,26 +61,41 @@ namespace Content.Server.GameObjects.Components.Atmos
return closed;
}
- public override void Deny()
+ public override bool CanOpen()
{
+ return !IsHoldingFire() && !IsHoldingPressure() && base.CanOpen();
}
public override bool CanClose(IEntity user) => true;
- public override bool CanOpen(IEntity user) => true;
+ public override bool CanOpen(IEntity user) => CanOpen();
public async Task InteractUsing(InteractUsingEventArgs eventArgs)
{
if (!eventArgs.Using.TryGetComponent(out var tool))
return false;
- if (!await tool.UseTool(eventArgs.User, Owner, 3f, ToolQuality.Prying)) return false;
+ if (tool.HasQuality(ToolQuality.Prying))
+ {
+ var holdingPressure = IsHoldingPressure();
+ var holdingFire = IsHoldingFire();
- if (State == DoorState.Closed)
- Open();
- else if (State == DoorState.Open)
- Close();
+ if (State == DoorState.Closed)
+ {
+ if(holdingPressure)
+ _notifyManager.PopupMessage(Owner, eventArgs.User, "A gush of air blows in your face... Maybe you should reconsider.");
+ }
- return true;
+ if (!await tool.UseTool(eventArgs.User, Owner, holdingPressure || holdingFire ? 1.5f : 0.25f, ToolQuality.Prying)) return false;
+
+ if (State == DoorState.Closed)
+ Open();
+ else if (State == DoorState.Open)
+ Close();
+
+ return true;
+ }
+
+ return false;
}
}
}
diff --git a/Content.Server/GameObjects/Components/Doors/ServerDoorComponent.cs b/Content.Server/GameObjects/Components/Doors/ServerDoorComponent.cs
index 381f276bd0..d2f8f7f65b 100644
--- a/Content.Server/GameObjects/Components/Doors/ServerDoorComponent.cs
+++ b/Content.Server/GameObjects/Components/Doors/ServerDoorComponent.cs
@@ -1,10 +1,12 @@
using System;
using System.Linq;
using System.Threading;
+using Content.Server.Atmos;
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;
@@ -49,11 +51,11 @@ namespace Content.Server.GameObjects.Components.Doors
private AppearanceComponent _appearance;
private CancellationTokenSource _cancellationTokenSource;
- private static readonly TimeSpan CloseTimeOne = TimeSpan.FromSeconds(0.3f);
- private static readonly TimeSpan CloseTimeTwo = TimeSpan.FromSeconds(0.9f);
- private static readonly TimeSpan OpenTimeOne = TimeSpan.FromSeconds(0.3f);
- private static readonly TimeSpan OpenTimeTwo = TimeSpan.FromSeconds(0.9f);
- private static readonly TimeSpan DenyTime = TimeSpan.FromSeconds(0.45f);
+ protected virtual TimeSpan CloseTimeOne => TimeSpan.FromSeconds(0.3f);
+ protected virtual TimeSpan CloseTimeTwo => TimeSpan.FromSeconds(0.9f);
+ protected virtual TimeSpan OpenTimeOne => TimeSpan.FromSeconds(0.3f);
+ protected virtual TimeSpan OpenTimeTwo => TimeSpan.FromSeconds(0.9f);
+ protected virtual TimeSpan DenyTime => TimeSpan.FromSeconds(0.45f);
private const int DoorCrushDamage = 15;
private const float DoorStunTime = 5f;
@@ -263,6 +265,57 @@ namespace Content.Server.GameObjects.Components.Doors
}
}
+ public bool IsHoldingPressure(float threshold = 20)
+ {
+ var atmosphereSystem = EntitySystem.Get();
+
+ if (!Owner.Transform.GridPosition.TryGetTileAtmosphere(out var tileAtmos))
+ return false;
+
+ var gridAtmosphere = atmosphereSystem.GetGridAtmosphere(Owner.Transform.GridID);
+
+ if (gridAtmosphere == null)
+ return false;
+
+ var minMoles = float.MaxValue;
+ var maxMoles = 0f;
+
+ foreach (var (direction, adjacent) in gridAtmosphere.GetAdjacentTiles(tileAtmos.GridIndices))
+ {
+ var moles = adjacent.Air.TotalMoles;
+ if (moles < minMoles)
+ minMoles = moles;
+ if (moles > maxMoles)
+ maxMoles = moles;
+ }
+
+ return (maxMoles - minMoles) > threshold;
+ }
+
+ public bool IsHoldingFire()
+ {
+ var atmosphereSystem = EntitySystem.Get();
+
+ if (!Owner.Transform.GridPosition.TryGetTileAtmosphere(out var tileAtmos))
+ return false;
+
+ if (tileAtmos.Hotspot.Valid)
+ return true;
+
+ var gridAtmosphere = atmosphereSystem.GetGridAtmosphere(Owner.Transform.GridID);
+
+ if (gridAtmosphere == null)
+ return false;
+
+ foreach (var (direction, adjacent) in gridAtmosphere.GetAdjacentTiles(tileAtmos.GridIndices))
+ {
+ if (adjacent.Hotspot.Valid)
+ return true;
+ }
+
+ return false;
+ }
+
public bool Close()
{
bool shouldCheckCrush = false;
diff --git a/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/meta.json b/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/meta.json
index c25c825232..08653842b9 100644
--- a/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/meta.json
+++ b/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/meta.json
@@ -7,6 +7,15 @@
"license": "CC-BY-SA 3.0",
"copyright": "Taken from https://github.com/tgstation/tgstation at 04e43d8c1d5097fdb697addd4395fb849dd341bd",
"states": [
+ {
+ "name": "bolted",
+ "directions": 1,
+ "delays": [
+ [
+ 1.0
+ ]
+ ]
+ },
{
"name": "closed",
"directions": 1,
@@ -16,6 +25,15 @@
]
]
},
+ {
+ "name": "closed_unlit",
+ "directions": 1,
+ "delays": [
+ [
+ 1.0
+ ]
+ ]
+ },
{
"name": "closing",
"directions": 1,
@@ -30,6 +48,20 @@
]
]
},
+ {
+ "name": "closing_unlit",
+ "directions": 1,
+ "delays": [
+ [
+ 0.2,
+ 0.2,
+ 0.2,
+ 0.2,
+ 0.2,
+ 0.2
+ ]
+ ]
+ },
{
"name": "deny",
"directions": 1,
@@ -41,6 +73,17 @@
]
]
},
+ {
+ "name": "deny_unlit",
+ "directions": 1,
+ "delays": [
+ [
+ 0.1,
+ 0.1,
+ 0.1
+ ]
+ ]
+ },
{
"name": "frame1",
"directions": 1,
@@ -109,6 +152,20 @@
]
]
},
+ {
+ "name": "opening_unlit",
+ "directions": 1,
+ "delays": [
+ [
+ 0.2,
+ 0.2,
+ 0.2,
+ 0.2,
+ 0.2,
+ 0.2
+ ]
+ ]
+ },
{
"name": "panel_closing",
"directions": 1,