CatStation/Content.Shared/Doors/Components/AirlockComponent.cs
Whatstone 09ac03b932
Door/FirelockComponent cleanup + nullable layer states + firelock panel fix (#44714)
* destroy firelock empty sprites with fury

* fix the meta.json

* remove unused states

* we need all the layers

* string? never heard of it

* DoorSystem cleanup, FirelockSystem layer checks

* DoorComponent cleanup

* FirelockComponent cleanup

* firelock panel animation

* fix offset (-15/16, bad math)

* component cleanup and comments

* door cleanup

* 9-state firelock animations, no locked/deny state

* "comments"

* dedicated edge firelock panel, null airlock states

* screw it, subscriptions for airlocksystem too

* format

---------

Co-authored-by: Pok245 <113675512+Pok27@users.noreply.github.com>
2026-10-04 22:47:04 +00:00

170 lines
5.4 KiB
C#

using Content.Shared.DeviceLinking;
using Content.Shared.Doors.Systems;
using Robust.Shared.Audio;
using Robust.Shared.GameStates;
using Robust.Shared.Prototypes;
namespace Content.Shared.Doors.Components;
/// <summary>
/// Companion component to DoorComponent that handles airlock-specific behavior -- wires, requiring power to operate, bolts, and allowing automatic closing.
/// </summary>
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
[Access(typeof(SharedAirlockSystem), Friend = AccessPermissions.ReadWriteExecute, Other = AccessPermissions.Read)]
public sealed partial class AirlockComponent : Component
{
[DataField, AutoNetworkedField]
public bool Powered;
// Need to network airlock safety state to avoid mis-predicts when a door auto-closes as the client walks through the door.
[DataField, AutoNetworkedField]
public bool Safety = true;
[DataField, AutoNetworkedField]
public bool EmergencyAccess;
/// <summary>
/// Sound to play when the airlock emergency access is turned on.
/// </summary>
[DataField]
public SoundSpecifier EmergencyOnSound = new SoundPathSpecifier("/Audio/Machines/airlock_emergencyon.ogg");
/// <summary>
/// Sound to play when the airlock emergency access is turned off.
/// </summary>
[DataField]
public SoundSpecifier EmergencyOffSound = new SoundPathSpecifier("/Audio/Machines/airlock_emergencyoff.ogg");
/// <summary>
/// Pry modifier for a powered airlock.
/// Most anything that can pry powered has a pry speed bonus,
/// so this default is closer to 6 effectively on e.g. jaws (9 seconds when applied to other default.)
/// </summary>
[DataField]
public float PoweredPryModifier = 9f;
/// <summary>
/// Whether the maintenance panel should be visible even if the airlock is opened.
/// </summary>
[DataField]
public bool OpenPanelVisible;
/// <summary>
/// Whether the airlock should stay open if the airlock was clicked.
/// If the airlock was bumped into it will still auto close.
/// </summary>
[DataField]
public bool KeepOpenIfClicked;
/// <summary>
/// Whether the airlock should auto close. This value is reset every time the airlock closes.
/// </summary>
[DataField, AutoNetworkedField]
public bool AutoClose = true;
/// <summary>
/// Delay until an open door automatically closes.
/// </summary>
[DataField]
public TimeSpan AutoCloseDelay = TimeSpan.FromSeconds(5f);
/// <summary>
/// Multiplicative modifier for the auto-close delay. Can be modified by hacking the airlock wires. Setting to
/// zero will disable auto-closing.
/// </summary>
[DataField]
public float AutoCloseDelayModifier = 1.0f;
/// <summary>
/// The receiver port for turning off automatic closing.
/// </summary>
[DataField]
public ProtoId<SinkPortPrototype> AutoClosePort = "AutoClose";
[DataField]
public LocId PryFailedPopup = "airlock-component-cannot-pry-is-powered-message";
#region Graphics
/// <summary>
/// Whether the door lights should be visible.
/// </summary>
[DataField]
public bool OpenUnlitVisible;
/// <summary>
/// Whether the door should display emergency access lights.
/// </summary>
[DataField]
public bool EmergencyAccessLayer = true;
/// <summary>
/// Whether or not to animate the panel when the door opens or closes.
/// </summary>
[DataField]
public bool AnimatePanel = true;
/// <summary>
/// The sprite state used to animate the airlock frame when the airlock opens.
/// </summary>
[DataField]
public string? OpeningSpriteState = "opening_unlit";
/// <summary>
/// The sprite state used to animate the airlock panel when the airlock opens.
/// </summary>
[DataField]
public string? OpeningPanelSpriteState = "panel_opening";
/// <summary>
/// The sprite state to use for the wire panel when the airlock is open. The
/// first frame will be used for when the airlock is closed.
/// </summary>
[DataField]
public string? OpenPanelSpriteState = "panel_open";
/// <summary>
/// The sprite state used to animate the airlock frame when the airlock closes.
/// </summary>
[DataField]
public string? ClosingSpriteState = "closing_unlit";
/// <summary>
/// The sprite state used to animate the airlock panel when the airlock closes.
/// </summary>
[DataField]
public string? ClosingPanelSpriteState = "panel_closing";
/// <summary>
/// The sprite state used for the open airlock lights.
/// </summary>
[DataField]
public string? OpenSpriteState = "open_unlit";
/// <summary>
/// The sprite state used for the closed airlock lights.
/// </summary>
[DataField]
public string? ClosedSpriteState = "closed_unlit";
/// <summary>
/// The sprite state used for the 'access denied' lights animation.
/// </summary>
[DataField]
public string? DenySpriteState = "deny_unlit";
/// <summary>
/// How long the animation played when the airlock denies access is in seconds.
/// </summary>
[DataField]
public float DenyAnimationTime = 0.3f;
/// <summary>
/// Pry modifier for a bolted airlock.
/// Currently only zombies can pry bolted airlocks.
/// </summary>
[DataField]
public float BoltedPryModifier = 3f;
#endregion Graphics
}