Files
tbd-station-14/Content.Shared/Doors/Systems/SharedFirelockSystem.cs
ShadowCommander 1bfa303f36 Firelock temperature and pressure warning lights (#28339)
* Add temperature and pressure lights to firelocks

* Replace sprites with new pressure and temperature light versions

* Remove obsolete deny and locked sprites

* Add SpriteSync for warning light animation synchronization

* Teal lights

* Partial animation implementation

* fixup! Teal lights

* Temperature lights

* Adjusted firelock light heights and added final warning light sprites

* Fix colors

* Testing colors

* Update light sprites

* updated sprites

---------

Co-authored-by: EmoGarbage404 <retron404@gmail.com>
2025-04-21 18:39:28 -04:00

170 lines
5.6 KiB
C#

using Content.Shared.Access.Systems;
using Content.Shared.Doors.Components;
using Content.Shared.Examine;
using Content.Shared.Popups;
using Content.Shared.Prying.Components;
using Robust.Shared.Serialization;
using Robust.Shared.Timing;
namespace Content.Shared.Doors.Systems;
public abstract class SharedFirelockSystem : EntitySystem
{
[Dependency] private readonly AccessReaderSystem _accessReaderSystem = default!;
[Dependency] private readonly SharedPopupSystem _popupSystem = default!;
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
[Dependency] private readonly SharedDoorSystem _doorSystem = default!;
[Dependency] private readonly IGameTiming _gameTiming = default!;
public override void Initialize()
{
base.Initialize();
// Access/Prying
SubscribeLocalEvent<FirelockComponent, BeforeDoorOpenedEvent>(OnBeforeDoorOpened);
SubscribeLocalEvent<FirelockComponent, BeforePryEvent>(OnBeforePry);
SubscribeLocalEvent<FirelockComponent, GetPryTimeModifierEvent>(OnDoorGetPryTimeModifier);
SubscribeLocalEvent<FirelockComponent, PriedEvent>(OnAfterPried);
// Visuals
SubscribeLocalEvent<FirelockComponent, MapInitEvent>(UpdateVisuals);
SubscribeLocalEvent<FirelockComponent, ComponentStartup>(OnComponentStartup);
SubscribeLocalEvent<FirelockComponent, ExaminedEvent>(OnExamined);
}
public bool EmergencyPressureStop(EntityUid uid, FirelockComponent? firelock = null, DoorComponent? door = null)
{
if (!Resolve(uid, ref firelock, ref door))
return false;
if (door.State != DoorState.Open
|| firelock.EmergencyCloseCooldown != null
&& _gameTiming.CurTime < firelock.EmergencyCloseCooldown)
return false;
if (!_doorSystem.TryClose(uid, door))
return false;
return _doorSystem.OnPartialClose(uid, door);
}
#region Access/Prying
private void OnBeforeDoorOpened(EntityUid uid, FirelockComponent component, BeforeDoorOpenedEvent args)
{
// Give the Door remote the ability to force a firelock open even if it is holding back dangerous gas
var overrideAccess = (args.User != null) && _accessReaderSystem.IsAllowed(args.User.Value, uid);
if (!component.Powered || (!overrideAccess && component.IsLocked))
args.Cancel();
else if (args.User != null)
WarnPlayer((uid, component), args.User.Value);
}
private void OnBeforePry(EntityUid uid, FirelockComponent component, ref BeforePryEvent args)
{
if (args.Cancelled || !component.Powered || args.StrongPry || args.PryPowered)
return;
args.Cancelled = true;
}
private void OnDoorGetPryTimeModifier(EntityUid uid, FirelockComponent component, ref GetPryTimeModifierEvent args)
{
WarnPlayer((uid, component), args.User);
if (component.IsLocked)
args.PryTimeModifier *= component.LockedPryTimeModifier;
}
private void WarnPlayer(Entity<FirelockComponent> ent, EntityUid user)
{
if (ent.Comp.Temperature)
{
_popupSystem.PopupClient(Loc.GetString("firelock-component-is-holding-fire-message"),
ent.Owner,
user,
PopupType.MediumCaution);
}
else if (ent.Comp.Pressure)
{
_popupSystem.PopupClient(Loc.GetString("firelock-component-is-holding-pressure-message"),
ent.Owner,
user,
PopupType.MediumCaution);
}
}
private void OnAfterPried(EntityUid uid, FirelockComponent component, ref PriedEvent args)
{
component.EmergencyCloseCooldown = _gameTiming.CurTime + component.EmergencyCloseCooldownDuration;
}
#endregion
#region Visuals
protected virtual void OnComponentStartup(Entity<FirelockComponent> ent, ref ComponentStartup args)
{
UpdateVisuals(ent.Owner,ent.Comp, args);
}
private void UpdateVisuals(EntityUid uid, FirelockComponent component, EntityEventArgs args) => UpdateVisuals(uid, component);
private void UpdateVisuals(EntityUid uid,
FirelockComponent? firelock = null,
DoorComponent? door = null,
AppearanceComponent? appearance = null)
{
if (!Resolve(uid, ref door, ref appearance, false))
return;
// only bother to check pressure on doors that are some variation of closed.
if (door.State != DoorState.Closed
&& door.State != DoorState.Welded
&& door.State != DoorState.Denying)
{
_appearance.SetData(uid, DoorVisuals.ClosedLights, false, appearance);
return;
}
if (!Resolve(uid, ref firelock, ref appearance, false))
return;
_appearance.SetData(uid, DoorVisuals.ClosedLights, firelock.IsLocked, appearance);
}
#endregion
private void OnExamined(Entity<FirelockComponent> ent, ref ExaminedEvent args)
{
using (args.PushGroup(nameof(FirelockComponent)))
{
if (ent.Comp.Pressure)
args.PushMarkup(Loc.GetString("firelock-component-examine-pressure-warning"));
if (ent.Comp.Temperature)
args.PushMarkup(Loc.GetString("firelock-component-examine-temperature-warning"));
}
}
}
[Serializable, NetSerializable]
public enum FirelockVisuals : byte
{
PressureWarning,
TemperatureWarning,
}
[Serializable, NetSerializable]
public enum FirelockVisualLayersPressure : byte
{
Base
}
[Serializable, NetSerializable]
public enum FirelockVisualLayersTemperature : byte
{
Base
}