ECS airlocks (#13500)
This commit is contained in:
96
Content.Shared/Doors/Components/AirlockComponent.cs
Normal file
96
Content.Shared/Doors/Components/AirlockComponent.cs
Normal file
@@ -0,0 +1,96 @@
|
||||
using System.Threading;
|
||||
using Content.Shared.Doors.Systems;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
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]
|
||||
[Access(typeof(SharedAirlockSystem), Friend = AccessPermissions.ReadWriteExecute, Other = AccessPermissions.Read)]
|
||||
public sealed class AirlockComponent : Component
|
||||
{
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
[DataField("safety")]
|
||||
public bool Safety = true;
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
[DataField("emergencyAccess")]
|
||||
public bool EmergencyAccess = false;
|
||||
|
||||
/// <summary>
|
||||
/// Sound to play when the bolts on the airlock go up.
|
||||
/// </summary>
|
||||
[DataField("boltUpSound")]
|
||||
public SoundSpecifier BoltUpSound = new SoundPathSpecifier("/Audio/Machines/boltsup.ogg");
|
||||
|
||||
/// <summary>
|
||||
/// Sound to play when the bolts on the airlock go down.
|
||||
/// </summary>
|
||||
[DataField("boltDownSound")]
|
||||
public SoundSpecifier BoltDownSound = new SoundPathSpecifier("/Audio/Machines/boltsdown.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("poweredPryModifier")]
|
||||
public readonly float PoweredPryModifier = 9f;
|
||||
|
||||
/// <summary>
|
||||
/// Whether the maintenance panel should be visible even if the airlock is opened.
|
||||
/// </summary>
|
||||
[DataField("openPanelVisible")]
|
||||
public bool OpenPanelVisible = false;
|
||||
|
||||
/// <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("keepOpenIfClicked")]
|
||||
public bool KeepOpenIfClicked = false;
|
||||
|
||||
public bool BoltsDown;
|
||||
|
||||
public bool BoltLightsEnabled = true;
|
||||
|
||||
/// <summary>
|
||||
/// True if the bolt wire is cut, which will force the airlock to always be bolted as long as it has power.
|
||||
/// </summary>
|
||||
[ViewVariables]
|
||||
public bool BoltWireCut;
|
||||
|
||||
/// <summary>
|
||||
/// Whether the airlock should auto close. This value is reset every time the airlock closes.
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public bool AutoClose = true;
|
||||
|
||||
/// <summary>
|
||||
/// Delay until an open door automatically closes.
|
||||
/// </summary>
|
||||
[DataField("autoCloseDelay")]
|
||||
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>
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public float AutoCloseDelayModifier = 1.0f;
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class AirlockComponentState : ComponentState
|
||||
{
|
||||
public readonly bool Safety;
|
||||
|
||||
public AirlockComponentState(bool safety)
|
||||
{
|
||||
Safety = safety;
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared.Doors.Components;
|
||||
|
||||
[NetworkedComponent]
|
||||
public abstract class SharedAirlockComponent : Component
|
||||
{
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
[DataField("safety")]
|
||||
public bool Safety = true;
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
[DataField("emergencyAccess")]
|
||||
public bool EmergencyAccess = false;
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class AirlockComponentState : ComponentState
|
||||
{
|
||||
public readonly bool Safety;
|
||||
|
||||
public AirlockComponentState(bool safety)
|
||||
{
|
||||
Safety = safety;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using Content.Shared.Doors.Components;
|
||||
using Content.Shared.Popups;
|
||||
using Robust.Shared.GameStates;
|
||||
|
||||
namespace Content.Shared.Doors.Systems;
|
||||
@@ -6,24 +7,26 @@ namespace Content.Shared.Doors.Systems;
|
||||
public abstract class SharedAirlockSystem : EntitySystem
|
||||
{
|
||||
[Dependency] protected readonly SharedAppearanceSystem Appearance = default!;
|
||||
[Dependency] protected readonly SharedAudioSystem Audio = default!;
|
||||
[Dependency] protected readonly SharedDoorSystem DoorSystem = default!;
|
||||
[Dependency] protected readonly SharedPopupSystem Popup = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<SharedAirlockComponent, ComponentGetState>(OnGetState);
|
||||
SubscribeLocalEvent<SharedAirlockComponent, ComponentHandleState>(OnHandleState);
|
||||
SubscribeLocalEvent<SharedAirlockComponent, BeforeDoorClosedEvent>(OnBeforeDoorClosed);
|
||||
SubscribeLocalEvent<AirlockComponent, ComponentGetState>(OnGetState);
|
||||
SubscribeLocalEvent<AirlockComponent, ComponentHandleState>(OnHandleState);
|
||||
SubscribeLocalEvent<AirlockComponent, BeforeDoorClosedEvent>(OnBeforeDoorClosed);
|
||||
}
|
||||
|
||||
private void OnGetState(EntityUid uid, SharedAirlockComponent airlock, ref ComponentGetState args)
|
||||
private void OnGetState(EntityUid uid, AirlockComponent airlock, ref ComponentGetState args)
|
||||
{
|
||||
// Need to network airlock safety state to avoid mis-predicts when a door auto-closes as the client walks through the door.
|
||||
args.State = new AirlockComponentState(airlock.Safety);
|
||||
}
|
||||
|
||||
private void OnHandleState(EntityUid uid, SharedAirlockComponent airlock, ref ComponentHandleState args)
|
||||
private void OnHandleState(EntityUid uid, AirlockComponent airlock, ref ComponentHandleState args)
|
||||
{
|
||||
if (args.Current is not AirlockComponentState state)
|
||||
return;
|
||||
@@ -31,21 +34,45 @@ public abstract class SharedAirlockSystem : EntitySystem
|
||||
airlock.Safety = state.Safety;
|
||||
}
|
||||
|
||||
protected virtual void OnBeforeDoorClosed(EntityUid uid, SharedAirlockComponent airlock, BeforeDoorClosedEvent args)
|
||||
protected virtual void OnBeforeDoorClosed(EntityUid uid, AirlockComponent airlock, BeforeDoorClosedEvent args)
|
||||
{
|
||||
if (!airlock.Safety)
|
||||
args.PerformCollisionCheck = false;
|
||||
}
|
||||
|
||||
|
||||
public void UpdateEmergencyLightStatus(SharedAirlockComponent component)
|
||||
public void UpdateEmergencyLightStatus(EntityUid uid, AirlockComponent component)
|
||||
{
|
||||
Appearance.SetData(component.Owner, DoorVisuals.EmergencyLights, component.EmergencyAccess);
|
||||
Appearance.SetData(uid, DoorVisuals.EmergencyLights, component.EmergencyAccess);
|
||||
}
|
||||
|
||||
public void ToggleEmergencyAccess(SharedAirlockComponent component)
|
||||
public void ToggleEmergencyAccess(EntityUid uid, AirlockComponent component)
|
||||
{
|
||||
component.EmergencyAccess = !component.EmergencyAccess;
|
||||
UpdateEmergencyLightStatus(component);
|
||||
UpdateEmergencyLightStatus(uid, component);
|
||||
}
|
||||
|
||||
public void SetAutoCloseDelayModifier(AirlockComponent component, float value)
|
||||
{
|
||||
if (component.AutoCloseDelayModifier.Equals(value))
|
||||
return;
|
||||
|
||||
component.AutoCloseDelayModifier = value;
|
||||
}
|
||||
|
||||
public void SetSafety(AirlockComponent component, bool value)
|
||||
{
|
||||
if (component.Safety == value)
|
||||
return;
|
||||
|
||||
component.Safety = value;
|
||||
}
|
||||
|
||||
public void SetBoltWireCut(AirlockComponent component, bool value)
|
||||
{
|
||||
if (component.BoltWireCut == value)
|
||||
return;
|
||||
|
||||
component.BoltWireCut = value;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user