Files
OldThink/Content.Server/Doors/Systems/FirelockSystem.cs
ThereDrD0 164251ffa7 Cherrypicks 5 (#399)
* Give moldy food the "Trash" tag (#29380)

Make moldy food items have the "Trash" tag, so they can be collected.

* Add "Structure" tag to switches, buttons, and levers (#29378)
shit
Co-authored-by: Eoin Mcloughlin <helloworld@eoinrul.es>

* Revamped Meteor Swarm (#28974)

* meteor code and balanced values

* Meteor Swarms

* Update meteors.yml

* Update meteors.yml

* HOO! (fix overkill bug and buff space dust)

* undo BloodstreamComponent.cs changes

* DamageDistribution -> DamageTypes

* part 2.

* meteor fixes

* improve meteor spawning (#29057)

* Decrease meteor frequency (#29194)

* Make Projectiles Only Hit a Variety of Station Objects Unless Clicked on (#28571)

* Revert "Make Projectiles Only Hit a Variety of Station Objects Unless Clicked on (#28571)"

This reverts commit 4f934f02f17ce55cabc03b965eb1df7738d63148.

* Makes machine parts stackable, removes unused field in stack prototypes (#28434)

* Makes machine parts stacks, removes unused field in stack prototypes

* forgor

* Fix tests

* Fixes lathe construction. Yes. This sucks but there's no better way that doesnt involve refactoring machine parts completely

* detail

* a

* Add pressure and temperature warning text to firelocks (#28341)

* fix firelocks

* missing nukies can be filled in by ghost roles (#28316)

* Revert "missing nukies can be filled in by ghost roles (#28316)"

This reverts commit 99f13e1e45bc778a4941316fde5d89d7b91337ce.

* welding gas mask (#27108)

* welding gas mask

* eek

* Canes + Cane Blade for Syndicate Librarians (#25873)

* Cane + Cane Blade

* Add - type: ContainerContainer

* Add another - type: ContainerContainer

* Fix and add proper ContainerContainer component

* Add UserInterface component

* Remove Space

* Stat Changes

* review

---------

Co-authored-by: metalgearsloth <comedian_vs_clown@hotmail.com>

* Fix stupid NPC. (#26868)

* init commit

* Review

---------

Co-authored-by: metalgearsloth <comedian_vs_clown@hotmail.com>

* fixes

---------

Co-authored-by: VeritableCalamity <34698192+Veritable-Calamity@users.noreply.github.com>
Co-authored-by: eoineoineoin <github@eoinrul.es>
Co-authored-by: Nemanja <98561806+EmoGarbage404@users.noreply.github.com>
Co-authored-by: Cojoke <83733158+Cojoke-dot@users.noreply.github.com>
Co-authored-by: AJCM-git <60196617+AJCM-git@users.noreply.github.com>
Co-authored-by: ShadowCommander <10494922+ShadowCommander@users.noreply.github.com>
Co-authored-by: deltanedas <39013340+deltanedas@users.noreply.github.com>
Co-authored-by: Ps3Moira <113228053+ps3moira@users.noreply.github.com>
Co-authored-by: metalgearsloth <comedian_vs_clown@hotmail.com>
Co-authored-by: Vigers Ray <60344369+VigersRay@users.noreply.github.com>
2024-06-30 10:04:27 +03:00

239 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 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 AtmosAlarmableSystem _atmosAlarmable = 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)
{
// TODO this should REALLLLY not be door specific appearance thing.
_appearance.SetData(uid, DoorVisuals.Powered, args.Powered);
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;
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;
}
}
}