mirror of
https://github.com/space-syndicate/space-station-14.git
synced 2026-10-11 19:31:12 +03:00
Signed-off-by: Prole <172158352+Prole0@users.noreply.github.com> Co-authored-by: PJBot <pieterjan.briers+bot@gmail.com> Co-authored-by: ScarKy0 <106310278+ScarKy0@users.noreply.github.com> Co-authored-by: Samuka-C <47865393+Samuka-C@users.noreply.github.com> Co-authored-by: ArtisticRoomba <145879011+ArtisticRoomba@users.noreply.github.com> Co-authored-by: Partmedia <kevinz5000@gmail.com> Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> Co-authored-by: themias <89101928+themias@users.noreply.github.com> Co-authored-by: Victor Shen <71985089+Vexerot@users.noreply.github.com> Co-authored-by: Ed <96445749+TheShuEd@users.noreply.github.com> Co-authored-by: Milon <milonpl.git@proton.me> Co-authored-by: Kirus59 <145689588+Kirus59@users.noreply.github.com> Co-authored-by: Nemanja <98561806+EmoGarbage404@users.noreply.github.com> Co-authored-by: Stomf <5dorkydorks@gmail.com> Co-authored-by: drakewill-CRL <46307022+drakewill-CRL@users.noreply.github.com> Co-authored-by: PraxisMapper <praxismapper@gmail.com> Co-authored-by: EmoGarbage404 <retron404@gmail.com> Co-authored-by: lzk <124214523+lzk228@users.noreply.github.com> Co-authored-by: Princess Cheeseballs <66055347+Pronana@users.noreply.github.com> Co-authored-by: IProduceWidgets <107586145+IProduceWidgets@users.noreply.github.com> Co-authored-by: TytosB <54259736+TytosB@users.noreply.github.com> Co-authored-by: abadaba695 <spacestation13thingy@gmail.com> Co-authored-by: kosticia <kosticia46@gmail.com> Co-authored-by: Thinbug <101073555+Thinbug0@users.noreply.github.com> Co-authored-by: pathetic meowmeow <uhhadd@gmail.com> Co-authored-by: SlamBamActionman <83650252+SlamBamActionman@users.noreply.github.com> Co-authored-by: Boaz1111 <149967078+Boaz1111@users.noreply.github.com> Co-authored-by: ActiveMammmoth <140334666+ActiveMammmoth@users.noreply.github.com> Co-authored-by: Myra <vasilis@pikachu.systems> Co-authored-by: Whatstone <166147148+whatston3@users.noreply.github.com> Co-authored-by: Pieter-Jan Briers <pieterjan.briers+git@gmail.com> Co-authored-by: K-Dynamic <20566341+K-Dynamic@users.noreply.github.com> Co-authored-by: Gentleman-Bird <dcgreen406@gmail.com> Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> Co-authored-by: BIGZi0348 <svalker0348@gmail.com> Co-authored-by: LaCumbiaDelCoronavirus <90893484+LaCumbiaDelCoronavirus@users.noreply.github.com> Co-authored-by: imatsoup <93290208+imatsoup@users.noreply.github.com> Co-authored-by: Matthew Herber <32679887+happyrobot33@users.noreply.github.com> Co-authored-by: Ertanic <36124833+Ertanic@users.noreply.github.com> Co-authored-by: MissKay1994 <15877268+MissKay1994@users.noreply.github.com> Co-authored-by: Errant <35878406+Errant-4@users.noreply.github.com> Co-authored-by: eoineoineoin <helloworld@eoinrul.es> Co-authored-by: Tiniest Shark <head.rebel@yahoo.com> Co-authored-by: nikitosych <boriszyn@gmail.com> Co-authored-by: Tayrtahn <tayrtahn@gmail.com> Co-authored-by: Perry Fraser <perryprog@users.noreply.github.com> Co-authored-by: YoungThug <ramialanbagy@gmail.com> Co-authored-by: beck-thompson <107373427+beck-thompson@users.noreply.github.com> Co-authored-by: metalgearsloth <comedian_vs_clown@hotmail.com> Co-authored-by: Southbridge <7013162+southbridge-fur@users.noreply.github.com> Co-authored-by: Vladislav Suchkov <20380250+murolem@users.noreply.github.com> Co-authored-by: Prole <172158352+Prole0@users.noreply.github.com> Co-authored-by: Unkn0wn_Gh0st <shadowstalkermll@gmail.com> Co-authored-by: 3nderall <101940324+3nderall@users.noreply.github.com> Co-authored-by: Radezolid <snappednexus@gmail.com> Co-authored-by: J <billsmith116@gmail.com> Co-authored-by: Ghagliiarghii <68826635+Ghagliiarghii@users.noreply.github.com> Co-authored-by: chromiumboy <50505512+chromiumboy@users.noreply.github.com> Co-authored-by: youtissoum <51883137+youtissoum@users.noreply.github.com> Co-authored-by: Minemoder5000 <minemoder50000@gmail.com> Co-authored-by: Spanky <scott@wearejacob.com> Co-authored-by: Spessmann <156740760+Spessmann@users.noreply.github.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: brainfood1183 <113240905+brainfood1183@users.noreply.github.com> Co-authored-by: Deerstop <edainturner@gmail.com> Co-authored-by: B_Kirill <153602297+B-Kirill@users.noreply.github.com> Co-authored-by: archee1 <archee3@hotmail.co.uk> Co-authored-by: Cojoke <83733158+Cojoke-dot@users.noreply.github.com> Co-authored-by: Quantum-cross <7065792+Quantum-cross@users.noreply.github.com> Co-authored-by: poklj <compgeek223@gmail.com> Co-authored-by: Krunklehorn <42424291+Krunklehorn@users.noreply.github.com> Co-authored-by: OnyxTheBrave <131422822+OnyxTheBrave@users.noreply.github.com> Co-authored-by: UpAndLeaves <92269094+Alpha-Two@users.noreply.github.com> Co-authored-by: Flareguy <78941145+Flareguy@users.noreply.github.com> Co-authored-by: Zalycon <84675130+Zalycon@users.noreply.github.com> Co-authored-by: deltanedas <39013340+deltanedas@users.noreply.github.com> Co-authored-by: Verm <32827189+Vermidia@users.noreply.github.com> Co-authored-by: nikthechampiongr <32041239+nikthechampiongr@users.noreply.github.com> Co-authored-by: ScarKy0 <scarky0@onet.eu> Co-authored-by: Dmitry <57028746+dimm00n@users.noreply.github.com>
238 lines
9.8 KiB
C#
238 lines
9.8 KiB
C#
using Content.Server.Atmos.Components;
|
|
using Content.Server.Atmos.EntitySystems;
|
|
using Content.Server.Atmos.Monitor.Systems;
|
|
using Content.Server.Power.Components;
|
|
using Content.Server.Power.EntitySystems;
|
|
using Content.Server.Shuttles.Components;
|
|
using Content.Shared.Atmos;
|
|
using Content.Shared.Atmos.Monitor;
|
|
using Content.Shared.Doors.Components;
|
|
using Content.Shared.Doors.Systems;
|
|
using Content.Shared.Power;
|
|
using Robust.Server.GameObjects;
|
|
using Robust.Shared.Map.Components;
|
|
|
|
namespace Content.Server.Doors.Systems
|
|
{
|
|
public sealed class FirelockSystem : SharedFirelockSystem
|
|
{
|
|
[Dependency] private readonly SharedDoorSystem _doorSystem = default!;
|
|
[Dependency] private readonly AtmosphereSystem _atmosSystem = default!;
|
|
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
|
|
[Dependency] private readonly SharedMapSystem _mapping = default!;
|
|
[Dependency] private readonly PointLightSystem _pointLight = default!;
|
|
|
|
private const int UpdateInterval = 30;
|
|
private int _accumulatedTicks;
|
|
|
|
public override void Initialize()
|
|
{
|
|
base.Initialize();
|
|
|
|
SubscribeLocalEvent<FirelockComponent, AtmosAlarmEvent>(OnAtmosAlarm);
|
|
|
|
SubscribeLocalEvent<FirelockComponent, PowerChangedEvent>(PowerChanged);
|
|
|
|
}
|
|
|
|
private void PowerChanged(EntityUid uid, FirelockComponent component, ref PowerChangedEvent args)
|
|
{
|
|
component.Powered = args.Powered;
|
|
Dirty(uid, component);
|
|
}
|
|
|
|
public override void Update(float frameTime)
|
|
{
|
|
_accumulatedTicks += 1;
|
|
if (_accumulatedTicks < UpdateInterval)
|
|
return;
|
|
|
|
_accumulatedTicks = 0;
|
|
|
|
var airtightQuery = GetEntityQuery<AirtightComponent>();
|
|
var appearanceQuery = GetEntityQuery<AppearanceComponent>();
|
|
var xformQuery = GetEntityQuery<TransformComponent>();
|
|
var pointLightQuery = GetEntityQuery<PointLightComponent>();
|
|
|
|
var query = EntityQueryEnumerator<FirelockComponent, DoorComponent>();
|
|
while (query.MoveNext(out var uid, out var firelock, out var door))
|
|
{
|
|
// 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)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (airtightQuery.TryGetComponent(uid, out var airtight)
|
|
&& xformQuery.TryGetComponent(uid, out var xform)
|
|
&& appearanceQuery.TryGetComponent(uid, out var appearance))
|
|
{
|
|
var (pressure, fire) = CheckPressureAndFire(uid, firelock, xform, airtight, airtightQuery);
|
|
_appearance.SetData(uid, DoorVisuals.ClosedLights, fire || pressure, appearance);
|
|
firelock.Temperature = fire;
|
|
firelock.Pressure = pressure;
|
|
_appearance.SetData(uid, FirelockVisuals.PressureWarning, pressure, appearance);
|
|
_appearance.SetData(uid, FirelockVisuals.TemperatureWarning, fire, appearance);
|
|
Dirty(uid, firelock);
|
|
|
|
if (pointLightQuery.TryComp(uid, out var pointLight))
|
|
{
|
|
_pointLight.SetEnabled(uid, fire | pressure, pointLight);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void OnAtmosAlarm(EntityUid uid, FirelockComponent component, AtmosAlarmEvent args)
|
|
{
|
|
if (!this.IsPowered(uid, EntityManager))
|
|
return;
|
|
|
|
if (!TryComp<DoorComponent>(uid, out var doorComponent))
|
|
return;
|
|
|
|
if (args.AlarmType == AtmosAlarmType.Normal)
|
|
{
|
|
if (doorComponent.State == DoorState.Closed)
|
|
_doorSystem.TryOpen(uid);
|
|
}
|
|
else if (args.AlarmType == AtmosAlarmType.Danger)
|
|
{
|
|
EmergencyPressureStop(uid, component, doorComponent);
|
|
}
|
|
}
|
|
|
|
public (bool Pressure, bool Fire) CheckPressureAndFire(EntityUid uid, FirelockComponent firelock)
|
|
{
|
|
var query = GetEntityQuery<AirtightComponent>();
|
|
if (query.TryGetComponent(uid, out AirtightComponent? airtight))
|
|
return CheckPressureAndFire(uid, firelock, Transform(uid), airtight, query);
|
|
return (false, false);
|
|
}
|
|
|
|
public (bool Pressure, bool Fire) CheckPressureAndFire(
|
|
EntityUid uid,
|
|
FirelockComponent firelock,
|
|
TransformComponent xform,
|
|
AirtightComponent airtight,
|
|
EntityQuery<AirtightComponent> airtightQuery)
|
|
{
|
|
if (!airtight.AirBlocked)
|
|
return (false, false);
|
|
|
|
if (TryComp(uid, out DockingComponent? dock) && dock.Docked)
|
|
{
|
|
// Currently docking automatically opens the doors. But maybe in future, check the pressure difference before opening doors?
|
|
return (false, false);
|
|
}
|
|
|
|
if (!HasComp<GridAtmosphereComponent>(xform.ParentUid))
|
|
return (false, false);
|
|
|
|
var grid = Comp<MapGridComponent>(xform.ParentUid);
|
|
var pos = _mapping.CoordinatesToTile(xform.ParentUid, grid, xform.Coordinates);
|
|
var minPressure = float.MaxValue;
|
|
var maxPressure = float.MinValue;
|
|
var minTemperature = float.MaxValue;
|
|
var maxTemperature = float.MinValue;
|
|
var holdingFire = false;
|
|
var holdingPressure = false;
|
|
|
|
// We cannot simply use `_atmosSystem.GetAdjacentTileMixtures` because of how the `includeBlocked` option
|
|
// works, we want to ignore the firelock's blocking, while including blockers on other tiles.
|
|
// GetAdjacentTileMixtures also ignores empty/non-existent tiles, which we don't want. Additionally, for
|
|
// edge-fire locks, we only want to enumerate over a single directions. So AFAIK there is no nice way of
|
|
// achieving all this using existing atmos functions, and the functionality is too specialized to bother
|
|
// adding new public atmos system functions.
|
|
|
|
List<Vector2i> tiles = new(4);
|
|
List<AtmosDirection> directions = new(4);
|
|
for (var i = 0; i < Atmospherics.Directions; i++)
|
|
{
|
|
var dir = (AtmosDirection)(1 << i);
|
|
if (airtight.AirBlockedDirection.HasFlag(dir))
|
|
{
|
|
directions.Add(dir);
|
|
tiles.Add(pos.Offset(dir));
|
|
}
|
|
}
|
|
|
|
// May also have to consider pressure on the same tile as the firelock.
|
|
var count = tiles.Count;
|
|
if (airtight.AirBlockedDirection != AtmosDirection.All)
|
|
tiles.Add(pos);
|
|
|
|
var gasses = _atmosSystem.GetTileMixtures(xform.ParentUid, xform.MapUid, tiles);
|
|
if (gasses == null)
|
|
return (false, false);
|
|
|
|
for (var i = 0; i < count; i++)
|
|
{
|
|
var gas = gasses[i];
|
|
var dir = directions[i];
|
|
var adjacentPos = tiles[i];
|
|
|
|
if (gas != null)
|
|
{
|
|
// Is there some airtight entity blocking this direction? If yes, don't include this direction in the
|
|
// pressure differential
|
|
if (HasAirtightBlocker(_mapping.GetAnchoredEntities(xform.ParentUid, grid, adjacentPos), dir.GetOpposite(), airtightQuery))
|
|
continue;
|
|
|
|
var p = gas.Pressure;
|
|
minPressure = Math.Min(minPressure, p);
|
|
maxPressure = Math.Max(maxPressure, p);
|
|
minTemperature = Math.Min(minTemperature, gas.Temperature);
|
|
maxTemperature = Math.Max(maxTemperature, gas.Temperature);
|
|
}
|
|
|
|
holdingPressure |= maxPressure - minPressure > firelock.PressureThreshold;
|
|
holdingFire |= maxTemperature - minTemperature > firelock.TemperatureThreshold;
|
|
|
|
if (holdingPressure && holdingFire)
|
|
return (holdingPressure, holdingFire);
|
|
}
|
|
|
|
if (airtight.AirBlockedDirection == AtmosDirection.All)
|
|
return (holdingPressure, holdingFire);
|
|
|
|
var local = gasses[count];
|
|
if (local != null)
|
|
{
|
|
var p = local.Pressure;
|
|
minPressure = Math.Min(minPressure, p);
|
|
maxPressure = Math.Max(maxPressure, p);
|
|
minTemperature = Math.Min(minTemperature, local.Temperature);
|
|
maxTemperature = Math.Max(maxTemperature, local.Temperature);
|
|
}
|
|
else
|
|
{
|
|
minPressure = Math.Min(minPressure, 0);
|
|
maxPressure = Math.Max(maxPressure, 0);
|
|
minTemperature = Math.Min(minTemperature, 0);
|
|
maxTemperature = Math.Max(maxTemperature, 0);
|
|
}
|
|
|
|
holdingPressure |= maxPressure - minPressure > firelock.PressureThreshold;
|
|
holdingFire |= maxTemperature - minTemperature > firelock.TemperatureThreshold;
|
|
|
|
return (holdingPressure, holdingFire);
|
|
}
|
|
|
|
private bool HasAirtightBlocker(IEnumerable<EntityUid> enumerable, AtmosDirection dir, EntityQuery<AirtightComponent> airtightQuery)
|
|
{
|
|
foreach (var ent in enumerable)
|
|
{
|
|
if (!airtightQuery.TryGetComponent(ent, out var airtight) || !airtight.AirBlocked)
|
|
continue;
|
|
|
|
if ((airtight.AirBlockedDirection & dir) == dir)
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
}
|
|
}
|