ECS airlocks (#13500)
This commit is contained in:
@@ -1,7 +0,0 @@
|
|||||||
using Content.Shared.Doors.Components;
|
|
||||||
|
|
||||||
namespace Content.Client.Doors;
|
|
||||||
|
|
||||||
[RegisterComponent]
|
|
||||||
[ComponentReference(typeof(SharedAirlockComponent))]
|
|
||||||
public sealed class AirlockComponent : SharedAirlockComponent { }
|
|
||||||
@@ -38,6 +38,8 @@ namespace Content.IntegrationTests.Tests.Doors
|
|||||||
components:
|
components:
|
||||||
- type: Door
|
- type: Door
|
||||||
- type: Airlock
|
- type: Airlock
|
||||||
|
- type: ApcPowerReceiver
|
||||||
|
needsPower: false
|
||||||
- type: Physics
|
- type: Physics
|
||||||
bodyType: Static
|
bodyType: Static
|
||||||
- type: Fixtures
|
- type: Fixtures
|
||||||
@@ -54,7 +56,6 @@ namespace Content.IntegrationTests.Tests.Doors
|
|||||||
await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true, ExtraPrototypes = Prototypes});
|
await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true, ExtraPrototypes = Prototypes});
|
||||||
var server = pairTracker.Pair.Server;
|
var server = pairTracker.Pair.Server;
|
||||||
|
|
||||||
var mapManager = server.ResolveDependency<IMapManager>();
|
|
||||||
var entityManager = server.ResolveDependency<IEntityManager>();
|
var entityManager = server.ResolveDependency<IEntityManager>();
|
||||||
var doors = entityManager.EntitySysManager.GetEntitySystem<DoorSystem>();
|
var doors = entityManager.EntitySysManager.GetEntitySystem<DoorSystem>();
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ using Content.Shared.Construction.Components;
|
|||||||
using Content.Shared.Containers.ItemSlots;
|
using Content.Shared.Containers.ItemSlots;
|
||||||
using Content.Shared.Damage;
|
using Content.Shared.Damage;
|
||||||
using Content.Shared.Database;
|
using Content.Shared.Database;
|
||||||
|
using Content.Shared.Doors.Components;
|
||||||
using Content.Shared.Inventory;
|
using Content.Shared.Inventory;
|
||||||
using Content.Shared.PDA;
|
using Content.Shared.PDA;
|
||||||
using Content.Shared.Stacks;
|
using Content.Shared.Stacks;
|
||||||
@@ -72,7 +73,7 @@ public sealed partial class AdminVerbSystem
|
|||||||
: "/Textures/Interface/AdminActions/bolt.png",
|
: "/Textures/Interface/AdminActions/bolt.png",
|
||||||
Act = () =>
|
Act = () =>
|
||||||
{
|
{
|
||||||
airlock.SetBoltsWithAudio(!airlock.BoltsDown);
|
_airlockSystem.SetBoltsWithAudio(args.Target, airlock, !airlock.BoltsDown);
|
||||||
},
|
},
|
||||||
Impact = LogImpact.Medium,
|
Impact = LogImpact.Medium,
|
||||||
Message = Loc.GetString(airlock.BoltsDown
|
Message = Loc.GetString(airlock.BoltsDown
|
||||||
@@ -90,7 +91,7 @@ public sealed partial class AdminVerbSystem
|
|||||||
IconTexture = "/Textures/Interface/AdminActions/emergency_access.png",
|
IconTexture = "/Textures/Interface/AdminActions/emergency_access.png",
|
||||||
Act = () =>
|
Act = () =>
|
||||||
{
|
{
|
||||||
_airlockSystem.ToggleEmergencyAccess(airlock);
|
_airlockSystem.ToggleEmergencyAccess(args.Target, airlock);
|
||||||
},
|
},
|
||||||
Impact = LogImpact.Medium,
|
Impact = LogImpact.Medium,
|
||||||
Message = Loc.GetString(airlock.EmergencyAccess
|
Message = Loc.GetString(airlock.EmergencyAccess
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using Content.Shared.Construction;
|
using Content.Shared.Construction;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Content.Server.Doors.Components;
|
using Content.Server.Doors.Components;
|
||||||
|
using Content.Shared.Doors.Components;
|
||||||
using Content.Shared.Examine;
|
using Content.Shared.Examine;
|
||||||
|
|
||||||
namespace Content.Server.Construction.Conditions
|
namespace Content.Server.Construction.Conditions
|
||||||
|
|||||||
@@ -1,186 +0,0 @@
|
|||||||
using System.Threading;
|
|
||||||
using Content.Server.Power.Components;
|
|
||||||
// using Content.Server.WireHacking;
|
|
||||||
using Content.Shared.Doors.Components;
|
|
||||||
using Robust.Shared.Audio;
|
|
||||||
using Robust.Shared.Player;
|
|
||||||
// using static Content.Shared.Wires.SharedWiresComponent;
|
|
||||||
// using static Content.Shared.Wires.SharedWiresComponent.WiresAction;
|
|
||||||
|
|
||||||
namespace Content.Server.Doors.Components
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Companion component to DoorComponent that handles airlock-specific behavior -- wires, requiring power to operate, bolts, and allowing automatic closing.
|
|
||||||
/// </summary>
|
|
||||||
[RegisterComponent]
|
|
||||||
[ComponentReference(typeof(SharedAirlockComponent))]
|
|
||||||
public sealed class AirlockComponent : SharedAirlockComponent
|
|
||||||
{
|
|
||||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
|
||||||
|
|
||||||
/// <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>
|
|
||||||
/// Duration for which power will be disabled after pulsing either power wire.
|
|
||||||
/// </summary>
|
|
||||||
[DataField("powerWiresTimeout")]
|
|
||||||
public float PowerWiresTimeout = 5.0f;
|
|
||||||
|
|
||||||
/// <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;
|
|
||||||
|
|
||||||
private CancellationTokenSource _powerWiresPulsedTimerCancel = new();
|
|
||||||
private bool _powerWiresPulsed;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// True if either power wire was pulsed in the last <see cref="PowerWiresTimeout"/>.
|
|
||||||
/// </summary>
|
|
||||||
[ViewVariables(VVAccess.ReadWrite)]
|
|
||||||
private bool PowerWiresPulsed
|
|
||||||
{
|
|
||||||
get => _powerWiresPulsed;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
_powerWiresPulsed = value;
|
|
||||||
// UpdateWiresStatus();
|
|
||||||
// UpdatePowerCutStatus();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool _boltsDown;
|
|
||||||
|
|
||||||
[ViewVariables(VVAccess.ReadWrite)]
|
|
||||||
public bool BoltsDown
|
|
||||||
{
|
|
||||||
get => _boltsDown;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
_boltsDown = value;
|
|
||||||
UpdateBoltLightStatus();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool _boltLightsEnabled = true;
|
|
||||||
|
|
||||||
public bool BoltLightsEnabled
|
|
||||||
{
|
|
||||||
get => _boltLightsEnabled;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
_boltLightsEnabled = value;
|
|
||||||
UpdateBoltLightStatus();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[ViewVariables(VVAccess.ReadWrite)]
|
|
||||||
public bool BoltLightsVisible
|
|
||||||
{
|
|
||||||
get => _boltLightsEnabled && BoltsDown && IsPowered()
|
|
||||||
&& _entityManager.TryGetComponent<DoorComponent>(Owner, out var doorComponent) && doorComponent.State == DoorState.Closed;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
_boltLightsEnabled = value;
|
|
||||||
UpdateBoltLightStatus();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <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;
|
|
||||||
|
|
||||||
protected override void Initialize()
|
|
||||||
{
|
|
||||||
base.Initialize();
|
|
||||||
|
|
||||||
if (_entityManager.TryGetComponent<ApcPowerReceiverComponent>(Owner, out var receiverComponent) &&
|
|
||||||
_entityManager.TryGetComponent<AppearanceComponent>(Owner, out var appearanceComponent))
|
|
||||||
{
|
|
||||||
appearanceComponent.SetData(DoorVisuals.Powered, receiverComponent.Powered);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool CanChangeState()
|
|
||||||
{
|
|
||||||
return IsPowered() && !IsBolted();
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsBolted()
|
|
||||||
{
|
|
||||||
return _boltsDown;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsPowered()
|
|
||||||
{
|
|
||||||
return !_entityManager.TryGetComponent<ApcPowerReceiverComponent>(Owner, out var receiverComponent) || receiverComponent.Powered;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void UpdateBoltLightStatus()
|
|
||||||
{
|
|
||||||
if (_entityManager.TryGetComponent<AppearanceComponent>(Owner, out var appearanceComponent))
|
|
||||||
{
|
|
||||||
appearanceComponent.SetData(DoorVisuals.BoltLights, BoltLightsVisible);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetBoltsWithAudio(bool newBolts)
|
|
||||||
{
|
|
||||||
if (newBolts == BoltsDown)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
BoltsDown = newBolts;
|
|
||||||
|
|
||||||
SoundSystem.Play(newBolts ? BoltDownSound.GetSound() : BoltUpSound.GetSound(), Filter.Pvs(Owner), Owner);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
using Content.Server.Doors.Components;
|
|
||||||
using Content.Server.Power.Components;
|
using Content.Server.Power.Components;
|
||||||
using Content.Server.Power.EntitySystems;
|
using Content.Server.Power.EntitySystems;
|
||||||
using Content.Shared.Tools.Components;
|
using Content.Shared.Tools.Components;
|
||||||
@@ -7,7 +6,6 @@ using Content.Shared.Doors;
|
|||||||
using Content.Shared.Doors.Components;
|
using Content.Shared.Doors.Components;
|
||||||
using Content.Shared.Doors.Systems;
|
using Content.Shared.Doors.Systems;
|
||||||
using Content.Shared.Interaction;
|
using Content.Shared.Interaction;
|
||||||
using Content.Shared.Popups;
|
|
||||||
using Robust.Server.GameObjects;
|
using Robust.Server.GameObjects;
|
||||||
|
|
||||||
namespace Content.Server.Doors.Systems
|
namespace Content.Server.Doors.Systems
|
||||||
@@ -21,6 +19,7 @@ namespace Content.Server.Doors.Systems
|
|||||||
{
|
{
|
||||||
base.Initialize();
|
base.Initialize();
|
||||||
|
|
||||||
|
SubscribeLocalEvent<AirlockComponent, ComponentInit>(OnAirlockInit);
|
||||||
SubscribeLocalEvent<AirlockComponent, PowerChangedEvent>(OnPowerChanged);
|
SubscribeLocalEvent<AirlockComponent, PowerChangedEvent>(OnPowerChanged);
|
||||||
SubscribeLocalEvent<AirlockComponent, DoorStateChangedEvent>(OnStateChanged);
|
SubscribeLocalEvent<AirlockComponent, DoorStateChangedEvent>(OnStateChanged);
|
||||||
SubscribeLocalEvent<AirlockComponent, BeforeDoorOpenedEvent>(OnBeforeDoorOpened);
|
SubscribeLocalEvent<AirlockComponent, BeforeDoorOpenedEvent>(OnBeforeDoorOpened);
|
||||||
@@ -30,11 +29,19 @@ namespace Content.Server.Doors.Systems
|
|||||||
SubscribeLocalEvent<AirlockComponent, BeforeDoorPryEvent>(OnDoorPry);
|
SubscribeLocalEvent<AirlockComponent, BeforeDoorPryEvent>(OnDoorPry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnAirlockInit(EntityUid uid, AirlockComponent component, ComponentInit args)
|
||||||
|
{
|
||||||
|
if (TryComp<ApcPowerReceiverComponent>(uid, out var receiverComponent))
|
||||||
|
{
|
||||||
|
Appearance.SetData(uid, DoorVisuals.Powered, receiverComponent.Powered);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void OnPowerChanged(EntityUid uid, AirlockComponent component, ref PowerChangedEvent args)
|
private void OnPowerChanged(EntityUid uid, AirlockComponent component, ref PowerChangedEvent args)
|
||||||
{
|
{
|
||||||
if (TryComp<AppearanceComponent>(uid, out var appearanceComponent))
|
if (TryComp<AppearanceComponent>(uid, out var appearanceComponent))
|
||||||
{
|
{
|
||||||
appearanceComponent.SetData(DoorVisuals.Powered, args.Powered);
|
Appearance.SetData(uid, DoorVisuals.Powered, args.Powered, appearanceComponent);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!TryComp(uid, out DoorComponent? door))
|
if (!TryComp(uid, out DoorComponent? door))
|
||||||
@@ -49,12 +56,13 @@ namespace Content.Server.Doors.Systems
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (component.BoltWireCut)
|
if (component.BoltWireCut)
|
||||||
component.SetBoltsWithAudio(true);
|
SetBoltsWithAudio(uid, component, true);
|
||||||
|
|
||||||
UpdateAutoClose(uid, door: door);
|
UpdateAutoClose(uid, door: door);
|
||||||
}
|
}
|
||||||
|
|
||||||
// BoltLights also got out
|
// BoltLights also got out
|
||||||
component.UpdateBoltLightStatus();
|
UpdateBoltLightStatus(uid, component);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnStateChanged(EntityUid uid, AirlockComponent component, DoorStateChangedEvent args)
|
private void OnStateChanged(EntityUid uid, AirlockComponent component, DoorStateChangedEvent args)
|
||||||
@@ -70,8 +78,7 @@ namespace Content.Server.Doors.Systems
|
|||||||
|| args.State != DoorState.Open;
|
|| args.State != DoorState.Open;
|
||||||
}
|
}
|
||||||
// If the door is closed, we should look if the bolt was locked while closing
|
// If the door is closed, we should look if the bolt was locked while closing
|
||||||
component.UpdateBoltLightStatus();
|
UpdateBoltLightStatus(uid, component);
|
||||||
|
|
||||||
UpdateAutoClose(uid, component);
|
UpdateAutoClose(uid, component);
|
||||||
|
|
||||||
// Make sure the airlock auto closes again next time it is opened
|
// Make sure the airlock auto closes again next time it is opened
|
||||||
@@ -93,7 +100,7 @@ namespace Content.Server.Doors.Systems
|
|||||||
if (!airlock.AutoClose)
|
if (!airlock.AutoClose)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!airlock.CanChangeState())
|
if (!CanChangeState(uid, airlock))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var autoev = new BeforeDoorAutoCloseEvent();
|
var autoev = new BeforeDoorAutoCloseEvent();
|
||||||
@@ -106,11 +113,11 @@ namespace Content.Server.Doors.Systems
|
|||||||
|
|
||||||
private void OnBeforeDoorOpened(EntityUid uid, AirlockComponent component, BeforeDoorOpenedEvent args)
|
private void OnBeforeDoorOpened(EntityUid uid, AirlockComponent component, BeforeDoorOpenedEvent args)
|
||||||
{
|
{
|
||||||
if (!component.CanChangeState())
|
if (!CanChangeState(uid, component))
|
||||||
args.Cancel();
|
args.Cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnBeforeDoorClosed(EntityUid uid, SharedAirlockComponent component, BeforeDoorClosedEvent args)
|
protected override void OnBeforeDoorClosed(EntityUid uid, AirlockComponent component, BeforeDoorClosedEvent args)
|
||||||
{
|
{
|
||||||
base.OnBeforeDoorClosed(uid, component, args);
|
base.OnBeforeDoorClosed(uid, component, args);
|
||||||
|
|
||||||
@@ -123,7 +130,7 @@ namespace Content.Server.Doors.Systems
|
|||||||
|
|
||||||
if (TryComp(uid, out DoorComponent? door)
|
if (TryComp(uid, out DoorComponent? door)
|
||||||
&& !door.Partial
|
&& !door.Partial
|
||||||
&& !Comp<AirlockComponent>(uid).CanChangeState())
|
&& !CanChangeState(uid, component))
|
||||||
{
|
{
|
||||||
args.Cancel();
|
args.Cancel();
|
||||||
}
|
}
|
||||||
@@ -131,7 +138,7 @@ namespace Content.Server.Doors.Systems
|
|||||||
|
|
||||||
private void OnBeforeDoorDenied(EntityUid uid, AirlockComponent component, BeforeDoorDeniedEvent args)
|
private void OnBeforeDoorDenied(EntityUid uid, AirlockComponent component, BeforeDoorDeniedEvent args)
|
||||||
{
|
{
|
||||||
if (!component.CanChangeState())
|
if (!CanChangeState(uid, component))
|
||||||
args.Cancel();
|
args.Cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,18 +167,68 @@ namespace Content.Server.Doors.Systems
|
|||||||
|
|
||||||
private void OnDoorPry(EntityUid uid, AirlockComponent component, BeforeDoorPryEvent args)
|
private void OnDoorPry(EntityUid uid, AirlockComponent component, BeforeDoorPryEvent args)
|
||||||
{
|
{
|
||||||
if (component.IsBolted())
|
if (component.BoltsDown)
|
||||||
{
|
{
|
||||||
component.Owner.PopupMessage(args.User, Loc.GetString("airlock-component-cannot-pry-is-bolted-message"));
|
Popup.PopupEntity(Loc.GetString("airlock-component-cannot-pry-is-bolted-message"), uid, args.User);
|
||||||
args.Cancel();
|
args.Cancel();
|
||||||
}
|
}
|
||||||
if (component.IsPowered())
|
|
||||||
|
if (this.IsPowered(uid, EntityManager))
|
||||||
{
|
{
|
||||||
if (HasComp<ToolForcePoweredComponent>(args.Tool))
|
if (HasComp<ToolForcePoweredComponent>(args.Tool))
|
||||||
return;
|
return;
|
||||||
component.Owner.PopupMessage(args.User, Loc.GetString("airlock-component-cannot-pry-is-powered-message"));
|
Popup.PopupEntity(Loc.GetString("airlock-component-cannot-pry-is-powered-message"), uid, args.User);
|
||||||
args.Cancel();
|
args.Cancel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool CanChangeState(EntityUid uid, AirlockComponent component)
|
||||||
|
{
|
||||||
|
return this.IsPowered(uid, EntityManager) && !component.BoltsDown;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateBoltLightStatus(EntityUid uid, AirlockComponent component)
|
||||||
|
{
|
||||||
|
if (!TryComp<AppearanceComponent>(uid, out var appearance))
|
||||||
|
return;
|
||||||
|
|
||||||
|
Appearance.SetData(uid, DoorVisuals.BoltLights, GetBoltLightsVisible(uid, component), appearance);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetBoltsWithAudio(EntityUid uid, AirlockComponent component, bool newBolts)
|
||||||
|
{
|
||||||
|
if (newBolts == component.BoltsDown)
|
||||||
|
return;
|
||||||
|
|
||||||
|
component.BoltsDown = newBolts;
|
||||||
|
Audio.PlayPvs(newBolts ? component.BoltDownSound : component.BoltUpSound, uid);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool GetBoltLightsVisible(EntityUid uid, AirlockComponent component)
|
||||||
|
{
|
||||||
|
return component.BoltLightsEnabled &&
|
||||||
|
component.BoltsDown &&
|
||||||
|
this.IsPowered(uid, EntityManager) &&
|
||||||
|
TryComp<DoorComponent>(uid, out var doorComponent) &&
|
||||||
|
doorComponent.State == DoorState.Closed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetBoltLightsEnabled(EntityUid uid, AirlockComponent component, bool value)
|
||||||
|
{
|
||||||
|
if (component.BoltLightsEnabled == value)
|
||||||
|
return;
|
||||||
|
|
||||||
|
component.BoltLightsEnabled = value;
|
||||||
|
UpdateBoltLightStatus(uid, component);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetBoltsDown(EntityUid uid, AirlockComponent component, bool value)
|
||||||
|
{
|
||||||
|
if (component.BoltsDown == value)
|
||||||
|
return;
|
||||||
|
|
||||||
|
component.BoltsDown = value;
|
||||||
|
UpdateBoltLightStatus(uid, component);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ using Robust.Shared.Audio;
|
|||||||
using Robust.Shared.Containers;
|
using Robust.Shared.Containers;
|
||||||
using Robust.Shared.Player;
|
using Robust.Shared.Player;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Content.Server.Power.EntitySystems;
|
||||||
using Robust.Shared.Physics.Components;
|
using Robust.Shared.Physics.Components;
|
||||||
using Robust.Shared.Physics.Events;
|
using Robust.Shared.Physics.Events;
|
||||||
|
|
||||||
@@ -27,6 +28,7 @@ namespace Content.Server.Doors.Systems;
|
|||||||
public sealed class DoorSystem : SharedDoorSystem
|
public sealed class DoorSystem : SharedDoorSystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly AccessReaderSystem _accessReaderSystem = default!;
|
[Dependency] private readonly AccessReaderSystem _accessReaderSystem = default!;
|
||||||
|
[Dependency] private readonly AirlockSystem _airlock = default!;
|
||||||
[Dependency] private readonly AirtightSystem _airtightSystem = default!;
|
[Dependency] private readonly AirtightSystem _airtightSystem = default!;
|
||||||
[Dependency] private readonly ConstructionSystem _constructionSystem = default!;
|
[Dependency] private readonly ConstructionSystem _constructionSystem = default!;
|
||||||
[Dependency] private readonly ToolSystem _toolSystem = default!;
|
[Dependency] private readonly ToolSystem _toolSystem = default!;
|
||||||
@@ -230,7 +232,7 @@ public sealed class DoorSystem : SharedDoorSystem
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
// If the door is on emergency access we skip the checks.
|
// If the door is on emergency access we skip the checks.
|
||||||
if (TryComp<SharedAirlockComponent>(uid, out var airlock) && airlock.EmergencyAccess)
|
if (TryComp<AirlockComponent>(uid, out var airlock) && airlock.EmergencyAccess)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (!Resolve(uid, ref access, false))
|
if (!Resolve(uid, ref access, false))
|
||||||
@@ -270,7 +272,7 @@ public sealed class DoorSystem : SharedDoorSystem
|
|||||||
{
|
{
|
||||||
if(TryComp<AirlockComponent>(uid, out var airlockComponent))
|
if(TryComp<AirlockComponent>(uid, out var airlockComponent))
|
||||||
{
|
{
|
||||||
if (airlockComponent.BoltsDown || !airlockComponent.IsPowered())
|
if (airlockComponent.BoltsDown || !this.IsPowered(uid, EntityManager))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (door.State == DoorState.Closed)
|
if (door.State == DoorState.Closed)
|
||||||
@@ -294,8 +296,8 @@ public sealed class DoorSystem : SharedDoorSystem
|
|||||||
if (door.OpenSound != null)
|
if (door.OpenSound != null)
|
||||||
PlaySound(uid, door.OpenSound, AudioParams.Default.WithVolume(-5), user, predicted);
|
PlaySound(uid, door.OpenSound, AudioParams.Default.WithVolume(-5), user, predicted);
|
||||||
|
|
||||||
if(lastState == DoorState.Emagging && TryComp<AirlockComponent>(door.Owner, out var airlockComponent))
|
if(lastState == DoorState.Emagging && TryComp<AirlockComponent>(uid, out var airlockComponent))
|
||||||
airlockComponent?.SetBoltsWithAudio(!airlockComponent.IsBolted());
|
_airlock.SetBoltsWithAudio(uid, airlockComponent, !airlockComponent.BoltsDown);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void CheckDoorBump(DoorComponent component, PhysicsComponent body)
|
protected override void CheckDoorBump(DoorComponent component, PhysicsComponent body)
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
using Content.Server.Doors.Components;
|
using Content.Server.Doors.Components;
|
||||||
|
using Content.Server.Doors.Systems;
|
||||||
using Content.Server.Wires;
|
using Content.Server.Wires;
|
||||||
using Content.Shared.Doors;
|
using Content.Shared.Doors;
|
||||||
|
using Content.Shared.Doors.Components;
|
||||||
using Content.Shared.Wires;
|
using Content.Shared.Wires;
|
||||||
|
|
||||||
namespace Content.Server.Doors;
|
namespace Content.Server.Doors;
|
||||||
@@ -21,7 +23,7 @@ public sealed class DoorBoltLightWireAction : BaseWireAction
|
|||||||
|
|
||||||
public override StatusLightData? GetStatusLightData(Wire wire)
|
public override StatusLightData? GetStatusLightData(Wire wire)
|
||||||
{
|
{
|
||||||
StatusLightState lightState = StatusLightState.Off;
|
var lightState = StatusLightState.Off;
|
||||||
if (IsPowered(wire.Owner) && EntityManager.TryGetComponent<AirlockComponent>(wire.Owner, out var door))
|
if (IsPowered(wire.Owner) && EntityManager.TryGetComponent<AirlockComponent>(wire.Owner, out var door))
|
||||||
{
|
{
|
||||||
lightState = door.BoltLightsEnabled
|
lightState = door.BoltLightsEnabled
|
||||||
@@ -42,7 +44,7 @@ public sealed class DoorBoltLightWireAction : BaseWireAction
|
|||||||
base.Cut(user, wire);
|
base.Cut(user, wire);
|
||||||
if (EntityManager.TryGetComponent<AirlockComponent>(wire.Owner, out var door))
|
if (EntityManager.TryGetComponent<AirlockComponent>(wire.Owner, out var door))
|
||||||
{
|
{
|
||||||
door.BoltLightsVisible = false;
|
EntityManager.System<AirlockSystem>().SetBoltLightsEnabled(wire.Owner, door, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -53,7 +55,7 @@ public sealed class DoorBoltLightWireAction : BaseWireAction
|
|||||||
base.Mend(user, wire);
|
base.Mend(user, wire);
|
||||||
if (EntityManager.TryGetComponent<AirlockComponent>(wire.Owner, out var door))
|
if (EntityManager.TryGetComponent<AirlockComponent>(wire.Owner, out var door))
|
||||||
{
|
{
|
||||||
door.BoltLightsVisible = true;
|
EntityManager.System<AirlockSystem>().SetBoltLightsEnabled(wire.Owner, door, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -64,7 +66,7 @@ public sealed class DoorBoltLightWireAction : BaseWireAction
|
|||||||
base.Pulse(user, wire);
|
base.Pulse(user, wire);
|
||||||
if (EntityManager.TryGetComponent<AirlockComponent>(wire.Owner, out var door))
|
if (EntityManager.TryGetComponent<AirlockComponent>(wire.Owner, out var door))
|
||||||
{
|
{
|
||||||
door.BoltLightsVisible = !door.BoltLightsEnabled;
|
EntityManager.System<AirlockSystem>().SetBoltLightsEnabled(wire.Owner, door, !door.BoltLightsEnabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
using Content.Server.Doors.Components;
|
using Content.Server.Doors.Components;
|
||||||
|
using Content.Server.Doors.Systems;
|
||||||
using Content.Server.Wires;
|
using Content.Server.Wires;
|
||||||
using Content.Shared.Doors;
|
using Content.Shared.Doors;
|
||||||
|
using Content.Shared.Doors.Components;
|
||||||
|
using Content.Shared.Doors.Systems;
|
||||||
using Content.Shared.Wires;
|
using Content.Shared.Wires;
|
||||||
|
|
||||||
namespace Content.Server.Doors;
|
namespace Content.Server.Doors;
|
||||||
@@ -42,11 +45,11 @@ public sealed class DoorBoltWireAction : BaseWireAction
|
|||||||
public override bool Cut(EntityUid user, Wire wire)
|
public override bool Cut(EntityUid user, Wire wire)
|
||||||
{
|
{
|
||||||
base.Cut(user, wire);
|
base.Cut(user, wire);
|
||||||
if (EntityManager.TryGetComponent<AirlockComponent>(wire.Owner, out var door))
|
if (EntityManager.TryGetComponent<AirlockComponent>(wire.Owner, out var airlock))
|
||||||
{
|
{
|
||||||
door.BoltWireCut = true;
|
EntityManager.System<SharedAirlockSystem>().SetBoltWireCut(airlock, true);
|
||||||
if (!door.BoltsDown && IsPowered(wire.Owner))
|
if (!airlock.BoltsDown && IsPowered(wire.Owner))
|
||||||
door.SetBoltsWithAudio(true);
|
EntityManager.System<AirlockSystem>().SetBoltsWithAudio(wire.Owner, airlock, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -56,7 +59,7 @@ public sealed class DoorBoltWireAction : BaseWireAction
|
|||||||
{
|
{
|
||||||
base.Mend(user, wire);
|
base.Mend(user, wire);
|
||||||
if (EntityManager.TryGetComponent<AirlockComponent>(wire.Owner, out var door))
|
if (EntityManager.TryGetComponent<AirlockComponent>(wire.Owner, out var door))
|
||||||
door.BoltWireCut = false;
|
EntityManager.System<SharedAirlockSystem>().SetBoltWireCut(door, true);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -68,11 +71,11 @@ public sealed class DoorBoltWireAction : BaseWireAction
|
|||||||
{
|
{
|
||||||
if (IsPowered(wire.Owner))
|
if (IsPowered(wire.Owner))
|
||||||
{
|
{
|
||||||
door.SetBoltsWithAudio(!door.BoltsDown);
|
EntityManager.System<AirlockSystem>().SetBoltsWithAudio(wire.Owner, door, !door.BoltsDown);
|
||||||
}
|
}
|
||||||
else if (!door.BoltsDown)
|
else if (!door.BoltsDown)
|
||||||
{
|
{
|
||||||
door.SetBoltsWithAudio(true);
|
EntityManager.System<AirlockSystem>().SetBoltsWithAudio(wire.Owner, door, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
using Content.Server.Doors.Components;
|
using Content.Server.Doors.Components;
|
||||||
using Content.Server.Wires;
|
using Content.Server.Wires;
|
||||||
using Content.Shared.Doors;
|
using Content.Shared.Doors;
|
||||||
|
using Content.Shared.Doors.Components;
|
||||||
|
using Content.Shared.Doors.Systems;
|
||||||
using Content.Shared.Wires;
|
using Content.Shared.Wires;
|
||||||
|
|
||||||
namespace Content.Server.Doors;
|
namespace Content.Server.Doors;
|
||||||
@@ -47,7 +49,7 @@ public sealed class DoorSafetyWireAction : BaseWireAction
|
|||||||
if (EntityManager.TryGetComponent<AirlockComponent>(wire.Owner, out var door))
|
if (EntityManager.TryGetComponent<AirlockComponent>(wire.Owner, out var door))
|
||||||
{
|
{
|
||||||
WiresSystem.TryCancelWireAction(wire.Owner, PulseTimeoutKey.Key);
|
WiresSystem.TryCancelWireAction(wire.Owner, PulseTimeoutKey.Key);
|
||||||
door.Safety = false;
|
EntityManager.System<SharedAirlockSystem>().SetSafety(door, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -58,7 +60,7 @@ public sealed class DoorSafetyWireAction : BaseWireAction
|
|||||||
base.Mend(user, wire);
|
base.Mend(user, wire);
|
||||||
if (EntityManager.TryGetComponent<AirlockComponent>(wire.Owner, out var door))
|
if (EntityManager.TryGetComponent<AirlockComponent>(wire.Owner, out var door))
|
||||||
{
|
{
|
||||||
door.Safety = true;
|
EntityManager.System<SharedAirlockSystem>().SetSafety(door, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -69,7 +71,7 @@ public sealed class DoorSafetyWireAction : BaseWireAction
|
|||||||
base.Pulse(user, wire);
|
base.Pulse(user, wire);
|
||||||
if (EntityManager.TryGetComponent<AirlockComponent>(wire.Owner, out var door))
|
if (EntityManager.TryGetComponent<AirlockComponent>(wire.Owner, out var door))
|
||||||
{
|
{
|
||||||
door.Safety = false;
|
EntityManager.System<SharedAirlockSystem>().SetSafety(door, false);
|
||||||
WiresSystem.StartWireAction(wire.Owner, _timeout, PulseTimeoutKey.Key, new TimedWireEvent(AwaitSafetyTimerFinish, wire));
|
WiresSystem.StartWireAction(wire.Owner, _timeout, PulseTimeoutKey.Key, new TimedWireEvent(AwaitSafetyTimerFinish, wire));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,7 +92,7 @@ public sealed class DoorSafetyWireAction : BaseWireAction
|
|||||||
{
|
{
|
||||||
if (EntityManager.TryGetComponent<AirlockComponent>(wire.Owner, out var door))
|
if (EntityManager.TryGetComponent<AirlockComponent>(wire.Owner, out var door))
|
||||||
{
|
{
|
||||||
door.Safety = true;
|
EntityManager.System<SharedAirlockSystem>().SetSafety(door, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
using Content.Server.Doors.Components;
|
using Content.Server.Doors.Components;
|
||||||
using Content.Server.Wires;
|
using Content.Server.Wires;
|
||||||
using Content.Shared.Doors;
|
using Content.Shared.Doors;
|
||||||
|
using Content.Shared.Doors.Components;
|
||||||
|
using Content.Shared.Doors.Systems;
|
||||||
using Content.Shared.Wires;
|
using Content.Shared.Wires;
|
||||||
|
|
||||||
namespace Content.Server.Doors;
|
namespace Content.Server.Doors;
|
||||||
@@ -56,7 +58,7 @@ public sealed class DoorTimingWireAction : BaseWireAction
|
|||||||
if (EntityManager.TryGetComponent<AirlockComponent>(wire.Owner, out var door))
|
if (EntityManager.TryGetComponent<AirlockComponent>(wire.Owner, out var door))
|
||||||
{
|
{
|
||||||
WiresSystem.TryCancelWireAction(wire.Owner, PulseTimeoutKey.Key);
|
WiresSystem.TryCancelWireAction(wire.Owner, PulseTimeoutKey.Key);
|
||||||
door.AutoCloseDelayModifier = 0.01f;
|
EntityManager.System<SharedAirlockSystem>().SetAutoCloseDelayModifier(door, 0.01f);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -67,7 +69,7 @@ public sealed class DoorTimingWireAction : BaseWireAction
|
|||||||
base.Mend(user, wire);
|
base.Mend(user, wire);
|
||||||
if (EntityManager.TryGetComponent<AirlockComponent>(wire.Owner, out var door))
|
if (EntityManager.TryGetComponent<AirlockComponent>(wire.Owner, out var door))
|
||||||
{
|
{
|
||||||
door.AutoCloseDelayModifier = 1f;
|
EntityManager.System<SharedAirlockSystem>().SetAutoCloseDelayModifier(door, 1f);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -78,7 +80,7 @@ public sealed class DoorTimingWireAction : BaseWireAction
|
|||||||
base.Pulse(user, wire);
|
base.Pulse(user, wire);
|
||||||
if (EntityManager.TryGetComponent<AirlockComponent>(wire.Owner, out var door))
|
if (EntityManager.TryGetComponent<AirlockComponent>(wire.Owner, out var door))
|
||||||
{
|
{
|
||||||
door.AutoCloseDelayModifier = 0.5f;
|
EntityManager.System<SharedAirlockSystem>().SetAutoCloseDelayModifier(door, 0.5f);
|
||||||
WiresSystem.StartWireAction(wire.Owner, _timeout, PulseTimeoutKey.Key, new TimedWireEvent(AwaitTimingTimerFinish, wire));
|
WiresSystem.StartWireAction(wire.Owner, _timeout, PulseTimeoutKey.Key, new TimedWireEvent(AwaitTimingTimerFinish, wire));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,7 +103,7 @@ public sealed class DoorTimingWireAction : BaseWireAction
|
|||||||
{
|
{
|
||||||
if (EntityManager.TryGetComponent<AirlockComponent>(wire.Owner, out var door))
|
if (EntityManager.TryGetComponent<AirlockComponent>(wire.Owner, out var door))
|
||||||
{
|
{
|
||||||
door.AutoCloseDelayModifier = 1f;
|
EntityManager.System<SharedAirlockSystem>().SetAutoCloseDelayModifier(door, 1f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ using Content.Server.Body.Components;
|
|||||||
using Content.Server.Body.Systems;
|
using Content.Server.Body.Systems;
|
||||||
using Content.Server.Coordinates.Helpers;
|
using Content.Server.Coordinates.Helpers;
|
||||||
using Content.Server.DoAfter;
|
using Content.Server.DoAfter;
|
||||||
using Content.Server.Doors.Components;
|
using Content.Server.Doors.Systems;
|
||||||
using Content.Server.Magic.Events;
|
using Content.Server.Magic.Events;
|
||||||
using Content.Server.Weapons.Ranged.Systems;
|
using Content.Server.Weapons.Ranged.Systems;
|
||||||
using Content.Shared.Actions;
|
using Content.Shared.Actions;
|
||||||
@@ -18,9 +18,7 @@ using Content.Shared.Spawners.Components;
|
|||||||
using Content.Shared.Storage;
|
using Content.Shared.Storage;
|
||||||
using Robust.Server.GameObjects;
|
using Robust.Server.GameObjects;
|
||||||
using Robust.Shared.Audio;
|
using Robust.Shared.Audio;
|
||||||
using Robust.Shared.GameObjects;
|
|
||||||
using Robust.Shared.Map;
|
using Robust.Shared.Map;
|
||||||
using Robust.Shared.Physics.Components;
|
|
||||||
using Robust.Shared.Player;
|
using Robust.Shared.Player;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
using Robust.Shared.Random;
|
using Robust.Shared.Random;
|
||||||
@@ -38,6 +36,7 @@ public sealed class MagicSystem : EntitySystem
|
|||||||
[Dependency] private readonly IMapManager _mapManager = default!;
|
[Dependency] private readonly IMapManager _mapManager = default!;
|
||||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||||
[Dependency] private readonly IRobustRandom _random = default!;
|
[Dependency] private readonly IRobustRandom _random = default!;
|
||||||
|
[Dependency] private readonly AirlockSystem _airlock = default!;
|
||||||
[Dependency] private readonly BodySystem _bodySystem = default!;
|
[Dependency] private readonly BodySystem _bodySystem = default!;
|
||||||
[Dependency] private readonly EntityLookupSystem _lookup = default!;
|
[Dependency] private readonly EntityLookupSystem _lookup = default!;
|
||||||
[Dependency] private readonly SharedDoorSystem _doorSystem = default!;
|
[Dependency] private readonly SharedDoorSystem _doorSystem = default!;
|
||||||
@@ -46,6 +45,7 @@ public sealed class MagicSystem : EntitySystem
|
|||||||
[Dependency] private readonly GunSystem _gunSystem = default!;
|
[Dependency] private readonly GunSystem _gunSystem = default!;
|
||||||
[Dependency] private readonly PhysicsSystem _physics = default!;
|
[Dependency] private readonly PhysicsSystem _physics = default!;
|
||||||
[Dependency] private readonly SharedTransformSystem _transformSystem = default!;
|
[Dependency] private readonly SharedTransformSystem _transformSystem = default!;
|
||||||
|
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
@@ -272,7 +272,7 @@ public sealed class MagicSystem : EntitySystem
|
|||||||
|
|
||||||
_transformSystem.SetCoordinates(args.Performer, args.Target);
|
_transformSystem.SetCoordinates(args.Performer, args.Target);
|
||||||
transform.AttachToGridOrMap();
|
transform.AttachToGridOrMap();
|
||||||
SoundSystem.Play(args.BlinkSound.GetSound(), Filter.Pvs(args.Target), args.Performer, AudioParams.Default.WithVolume(args.BlinkVolume));
|
_audio.PlayPvs(args.BlinkSound, args.Performer, AudioParams.Default.WithVolume(args.BlinkVolume));
|
||||||
args.Handled = true;
|
args.Handled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -289,13 +289,13 @@ public sealed class MagicSystem : EntitySystem
|
|||||||
var transform = Transform(args.Performer);
|
var transform = Transform(args.Performer);
|
||||||
var coords = transform.Coordinates;
|
var coords = transform.Coordinates;
|
||||||
|
|
||||||
SoundSystem.Play(args.KnockSound.GetSound(), Filter.Pvs(coords), args.Performer, AudioParams.Default.WithVolume(args.KnockVolume));
|
_audio.PlayPvs(args.KnockSound, args.Performer, AudioParams.Default.WithVolume(args.KnockVolume));
|
||||||
|
|
||||||
//Look for doors and don't open them if they're already open.
|
//Look for doors and don't open them if they're already open.
|
||||||
foreach (var entity in _lookup.GetEntitiesInRange(coords, args.Range))
|
foreach (var entity in _lookup.GetEntitiesInRange(coords, args.Range))
|
||||||
{
|
{
|
||||||
if (TryComp<AirlockComponent>(entity, out var airlock))
|
if (TryComp<AirlockComponent>(entity, out var airlock))
|
||||||
airlock.BoltsDown = false;
|
_airlock.SetBoltsDown(entity, airlock, false);
|
||||||
|
|
||||||
if (TryComp<DoorComponent>(entity, out var doorComp) && doorComp.State is not DoorState.Open)
|
if (TryComp<DoorComponent>(entity, out var doorComp) && doorComp.State is not DoorState.Open)
|
||||||
_doorSystem.StartOpening(doorComp.Owner);
|
_doorSystem.StartOpening(doorComp.Owner);
|
||||||
|
|||||||
@@ -8,6 +8,9 @@ public static class StaticPowerSystem
|
|||||||
// ReSharper disable once UnusedParameter.Global
|
// ReSharper disable once UnusedParameter.Global
|
||||||
public static bool IsPowered(this EntitySystem system, EntityUid uid, IEntityManager entManager, ApcPowerReceiverComponent? receiver = null)
|
public static bool IsPowered(this EntitySystem system, EntityUid uid, IEntityManager entManager, ApcPowerReceiverComponent? receiver = null)
|
||||||
{
|
{
|
||||||
return entManager.TryGetComponent<ApcPowerReceiverComponent>(uid, out receiver) && receiver.Powered;
|
if (receiver == null && !entManager.TryGetComponent(uid, out receiver))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return receiver.Powered;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,10 +18,11 @@ namespace Content.Server.Remotes
|
|||||||
public sealed class DoorRemoteSystem : EntitySystem
|
public sealed class DoorRemoteSystem : EntitySystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly IAdminLogManager _adminLogger = default!;
|
[Dependency] private readonly IAdminLogManager _adminLogger = default!;
|
||||||
|
[Dependency] private readonly AirlockSystem _airlock = default!;
|
||||||
[Dependency] private readonly SharedPopupSystem _popupSystem = default!;
|
[Dependency] private readonly SharedPopupSystem _popupSystem = default!;
|
||||||
[Dependency] private readonly DoorSystem _doorSystem = default!;
|
[Dependency] private readonly DoorSystem _doorSystem = default!;
|
||||||
[Dependency] private readonly SharedInteractionSystem _interactionSystem = default!;
|
[Dependency] private readonly SharedInteractionSystem _interactionSystem = default!;
|
||||||
[Dependency] private readonly SharedAirlockSystem _sharedAirlockSystem = default!;
|
// I'm so sorry [Dependency] private readonly SharedAirlockSystem _sharedAirlockSystem = default!;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
@@ -90,12 +91,12 @@ namespace Content.Server.Remotes
|
|||||||
case OperatingMode.ToggleBolts:
|
case OperatingMode.ToggleBolts:
|
||||||
if (!airlockComp.BoltWireCut)
|
if (!airlockComp.BoltWireCut)
|
||||||
{
|
{
|
||||||
airlockComp.SetBoltsWithAudio(!airlockComp.IsBolted());
|
_airlock.SetBoltsWithAudio(uid, airlockComp, !airlockComp.BoltsDown);
|
||||||
_adminLogger.Add(LogType.Action, LogImpact.Medium, $"{ToPrettyString(args.User):player} used {ToPrettyString(args.Used)} on {ToPrettyString(args.Target.Value)} to {(airlockComp.IsBolted() ? "" : "un")}bolt it");
|
_adminLogger.Add(LogType.Action, LogImpact.Medium, $"{ToPrettyString(args.User):player} used {ToPrettyString(args.Used)} on {ToPrettyString(args.Target.Value)} to {(airlockComp.BoltsDown ? "" : "un")}bolt it");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OperatingMode.ToggleEmergencyAccess:
|
case OperatingMode.ToggleEmergencyAccess:
|
||||||
_sharedAirlockSystem.ToggleEmergencyAccess(airlockComp);
|
_airlock.ToggleEmergencyAccess(uid, airlockComp);
|
||||||
_adminLogger.Add(LogType.Action, LogImpact.Medium, $"{ToPrettyString(args.User):player} used {ToPrettyString(args.Used)} on {ToPrettyString(args.Target.Value)} to set emergency access {(airlockComp.EmergencyAccess ? "on" : "off")}");
|
_adminLogger.Add(LogType.Action, LogImpact.Medium, $"{ToPrettyString(args.User):player} used {ToPrettyString(args.Used)} on {ToPrettyString(args.Target.Value)} to set emergency access {(airlockComp.EmergencyAccess ? "on" : "off")}");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
using Content.Server.Doors.Components;
|
|
||||||
using Content.Server.Doors.Systems;
|
using Content.Server.Doors.Systems;
|
||||||
using Content.Server.NPC.Pathfinding;
|
using Content.Server.NPC.Pathfinding;
|
||||||
using Content.Server.Shuttles.Components;
|
using Content.Server.Shuttles.Components;
|
||||||
@@ -10,7 +9,6 @@ using Robust.Shared.Map;
|
|||||||
using Robust.Shared.Physics;
|
using Robust.Shared.Physics;
|
||||||
using Robust.Shared.Physics.Collision.Shapes;
|
using Robust.Shared.Physics.Collision.Shapes;
|
||||||
using Robust.Shared.Physics.Components;
|
using Robust.Shared.Physics.Components;
|
||||||
using Robust.Shared.Physics.Dynamics;
|
|
||||||
using Robust.Shared.Physics.Dynamics.Joints;
|
using Robust.Shared.Physics.Dynamics.Joints;
|
||||||
using Robust.Shared.Physics.Systems;
|
using Robust.Shared.Physics.Systems;
|
||||||
using Robust.Shared.Utility;
|
using Robust.Shared.Utility;
|
||||||
@@ -20,6 +18,7 @@ namespace Content.Server.Shuttles.Systems
|
|||||||
public sealed partial class DockingSystem : EntitySystem
|
public sealed partial class DockingSystem : EntitySystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly IMapManager _mapManager = default!;
|
[Dependency] private readonly IMapManager _mapManager = default!;
|
||||||
|
[Dependency] private readonly AirlockSystem _airlocks = default!;
|
||||||
[Dependency] private readonly DoorSystem _doorSystem = default!;
|
[Dependency] private readonly DoorSystem _doorSystem = default!;
|
||||||
[Dependency] private readonly FixtureSystem _fixtureSystem = default!;
|
[Dependency] private readonly FixtureSystem _fixtureSystem = default!;
|
||||||
[Dependency] private readonly PathfindingSystem _pathfinding = default!;
|
[Dependency] private readonly PathfindingSystem _pathfinding = default!;
|
||||||
@@ -273,7 +272,7 @@ namespace Content.Server.Shuttles.Systems
|
|||||||
// Listen it makes intersection tests easier; you can probably dump this but it requires a bunch more boilerplate
|
// Listen it makes intersection tests easier; you can probably dump this but it requires a bunch more boilerplate
|
||||||
// TODO: I want this to ideally be 2 fixtures to force them to have some level of alignment buuuttt
|
// TODO: I want this to ideally be 2 fixtures to force them to have some level of alignment buuuttt
|
||||||
// I also need collisionmanager for that yet again so they get dis.
|
// I also need collisionmanager for that yet again so they get dis.
|
||||||
_fixtureSystem.TryCreateFixture(uid, shape, DockingFixture, hard: false);
|
_fixtureSystem.TryCreateFixture(uid, shape, DockingFixture, hard: false, body: physicsComponent);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -351,7 +350,7 @@ namespace Content.Server.Shuttles.Systems
|
|||||||
doorA.ChangeAirtight = false;
|
doorA.ChangeAirtight = false;
|
||||||
if (TryComp<AirlockComponent>(dockA.Owner, out var airlockA))
|
if (TryComp<AirlockComponent>(dockA.Owner, out var airlockA))
|
||||||
{
|
{
|
||||||
airlockA.SetBoltsWithAudio(true);
|
_airlocks.SetBoltsWithAudio(dockA.Owner, airlockA, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -363,7 +362,7 @@ namespace Content.Server.Shuttles.Systems
|
|||||||
doorB.ChangeAirtight = false;
|
doorB.ChangeAirtight = false;
|
||||||
if (TryComp<AirlockComponent>(dockB.Owner, out var airlockB))
|
if (TryComp<AirlockComponent>(dockB.Owner, out var airlockB))
|
||||||
{
|
{
|
||||||
airlockB.SetBoltsWithAudio(true);
|
_airlocks.SetBoltsWithAudio(dockB.Owner, airlockB, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -448,12 +447,12 @@ namespace Content.Server.Shuttles.Systems
|
|||||||
|
|
||||||
if (TryComp<AirlockComponent>(dock.Owner, out var airlockA))
|
if (TryComp<AirlockComponent>(dock.Owner, out var airlockA))
|
||||||
{
|
{
|
||||||
airlockA.SetBoltsWithAudio(false);
|
_airlocks.SetBoltsWithAudio(dock.Owner, airlockA, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TryComp<AirlockComponent>(dock.DockedWith, out var airlockB))
|
if (TryComp<AirlockComponent>(dock.DockedWith, out var airlockB))
|
||||||
{
|
{
|
||||||
airlockB.SetBoltsWithAudio(false);
|
_airlocks.SetBoltsWithAudio(dock.DockedWith.Value, airlockB, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TryComp(dock.Owner, out DoorComponent? doorA))
|
if (TryComp(dock.Owner, out DoorComponent? doorA))
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ using Robust.Shared.Utility;
|
|||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using Content.Server.Shuttles.Events;
|
using Content.Server.Shuttles.Events;
|
||||||
using Content.Shared.Buckle.Components;
|
using Content.Shared.Buckle.Components;
|
||||||
|
using Content.Shared.Doors.Components;
|
||||||
using Robust.Shared.Map.Components;
|
using Robust.Shared.Map.Components;
|
||||||
using Robust.Shared.Physics.Components;
|
using Robust.Shared.Physics.Components;
|
||||||
|
|
||||||
@@ -25,6 +26,7 @@ public sealed partial class ShuttleSystem
|
|||||||
* This is a way to move a shuttle from one location to another, via an intermediate map for fanciness.
|
* This is a way to move a shuttle from one location to another, via an intermediate map for fanciness.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
[Dependency] private readonly AirlockSystem _airlock = default!;
|
||||||
[Dependency] private readonly DoorSystem _doors = default!;
|
[Dependency] private readonly DoorSystem _doors = default!;
|
||||||
[Dependency] private readonly ShuttleConsoleSystem _console = default!;
|
[Dependency] private readonly ShuttleConsoleSystem _console = default!;
|
||||||
[Dependency] private readonly SharedTransformSystem _transform = default!;
|
[Dependency] private readonly SharedTransformSystem _transform = default!;
|
||||||
@@ -344,7 +346,7 @@ public sealed partial class ShuttleSystem
|
|||||||
if (xform.ParentUid != uid) continue;
|
if (xform.ParentUid != uid) continue;
|
||||||
|
|
||||||
_doors.TryClose(door.Owner);
|
_doors.TryClose(door.Owner);
|
||||||
door.SetBoltsWithAudio(enabled);
|
_airlock.SetBoltsWithAudio(door.Owner, door, enabled);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
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.Doors.Components;
|
||||||
|
using Content.Shared.Popups;
|
||||||
using Robust.Shared.GameStates;
|
using Robust.Shared.GameStates;
|
||||||
|
|
||||||
namespace Content.Shared.Doors.Systems;
|
namespace Content.Shared.Doors.Systems;
|
||||||
@@ -6,24 +7,26 @@ namespace Content.Shared.Doors.Systems;
|
|||||||
public abstract class SharedAirlockSystem : EntitySystem
|
public abstract class SharedAirlockSystem : EntitySystem
|
||||||
{
|
{
|
||||||
[Dependency] protected readonly SharedAppearanceSystem Appearance = default!;
|
[Dependency] protected readonly SharedAppearanceSystem Appearance = default!;
|
||||||
|
[Dependency] protected readonly SharedAudioSystem Audio = default!;
|
||||||
[Dependency] protected readonly SharedDoorSystem DoorSystem = default!;
|
[Dependency] protected readonly SharedDoorSystem DoorSystem = default!;
|
||||||
|
[Dependency] protected readonly SharedPopupSystem Popup = default!;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
base.Initialize();
|
base.Initialize();
|
||||||
|
|
||||||
SubscribeLocalEvent<SharedAirlockComponent, ComponentGetState>(OnGetState);
|
SubscribeLocalEvent<AirlockComponent, ComponentGetState>(OnGetState);
|
||||||
SubscribeLocalEvent<SharedAirlockComponent, ComponentHandleState>(OnHandleState);
|
SubscribeLocalEvent<AirlockComponent, ComponentHandleState>(OnHandleState);
|
||||||
SubscribeLocalEvent<SharedAirlockComponent, BeforeDoorClosedEvent>(OnBeforeDoorClosed);
|
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.
|
// 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);
|
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)
|
if (args.Current is not AirlockComponentState state)
|
||||||
return;
|
return;
|
||||||
@@ -31,21 +34,45 @@ public abstract class SharedAirlockSystem : EntitySystem
|
|||||||
airlock.Safety = state.Safety;
|
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)
|
if (!airlock.Safety)
|
||||||
args.PerformCollisionCheck = false;
|
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;
|
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