Files
tbd-station-14/Content.Server/Radiation/Systems/RadiationSystem.Blockers.cs
2022-11-22 13:12:04 +11:00

168 lines
5.5 KiB
C#

using Content.Server.Radiation.Components;
using Content.Shared.Doors;
using Content.Shared.Doors.Components;
using Robust.Shared.Map.Components;
namespace Content.Server.Radiation.Systems;
// create and update map of radiation blockers
public partial class RadiationSystem
{
private void InitRadBlocking()
{
SubscribeLocalEvent<RadiationBlockerComponent, ComponentInit>(OnInit);
SubscribeLocalEvent<RadiationBlockerComponent, ComponentShutdown>(OnShutdown);
SubscribeLocalEvent<RadiationBlockerComponent, AnchorStateChangedEvent>(OnAnchorChanged);
SubscribeLocalEvent<RadiationBlockerComponent, ReAnchorEvent>(OnReAnchor);
SubscribeLocalEvent<RadiationBlockerComponent, DoorStateChangedEvent>(OnDoorChanged);
SubscribeLocalEvent<RadiationGridResistanceComponent, EntityTerminatingEvent>(OnGridRemoved);
}
private void OnInit(EntityUid uid, RadiationBlockerComponent component, ComponentInit args)
{
if (!component.Enabled)
return;
AddTile(uid, component);
}
private void OnShutdown(EntityUid uid, RadiationBlockerComponent component, ComponentShutdown args)
{
if (component.Enabled)
return;
RemoveTile(uid, component);
}
private void OnAnchorChanged(EntityUid uid, RadiationBlockerComponent component, ref AnchorStateChangedEvent args)
{
if (args.Anchored)
{
AddTile(uid, component);
}
else
{
RemoveTile(uid, component);
}
}
private void OnReAnchor(EntityUid uid, RadiationBlockerComponent component, ref ReAnchorEvent args)
{
// probably grid was split
// we need to remove entity from old resistance map
RemoveTile(uid, component);
// and move it to the new one
AddTile(uid, component);
}
private void OnDoorChanged(EntityUid uid, RadiationBlockerComponent component, DoorStateChangedEvent args)
{
switch (args.State)
{
case DoorState.Open:
SetEnabled(uid, false, component);
break;
case DoorState.Closed:
SetEnabled(uid, true, component);
break;
}
}
private void OnGridRemoved(EntityUid uid, RadiationGridResistanceComponent component, ref EntityTerminatingEvent args)
{
// grid is about to be removed - lets delete grid component first
// this should save a bit performance when blockers will be deleted
RemComp(uid, component);
}
public void SetEnabled(EntityUid uid, bool isEnabled, RadiationBlockerComponent? component = null)
{
if (!Resolve(uid, ref component))
return;
if (isEnabled == component.Enabled)
return;
component.Enabled = isEnabled;
if (!component.Enabled)
RemoveTile(uid, component);
else
AddTile(uid, component);
}
private void AddTile(EntityUid uid, RadiationBlockerComponent component)
{
// check that last position was removed
if (component.CurrentPosition != null)
{
RemoveTile(uid, component);
}
// check if entity even provide some rad protection
if (!component.Enabled || component.RadResistance <= 0)
return;
// check if it's on a grid
var trs = Transform(uid);
if (!trs.Anchored || !TryComp(trs.GridUid, out MapGridComponent? grid))
return;
// save resistance into rad protection grid
var gridId = trs.GridUid.Value;
var tilePos = grid.TileIndicesFor(trs.Coordinates);
AddToTile(gridId, tilePos, component.RadResistance);
// and remember it as last valid position
component.CurrentPosition = (gridId, tilePos);
}
private void RemoveTile(EntityUid uid, RadiationBlockerComponent component)
{
// check if blocker was placed on grid before component was removed
if (component.CurrentPosition == null)
return;
var (gridId, tilePos) = component.CurrentPosition.Value;
// try to remove
RemoveFromTile(gridId, tilePos, component.RadResistance);
component.CurrentPosition = null;
}
private void AddToTile(EntityUid gridUid, Vector2i tilePos, float radResistance)
{
// get existing rad resistance grid or create it if it doesn't exist
var resistance = EnsureComp<RadiationGridResistanceComponent>(gridUid);
var grid = resistance.ResistancePerTile;
// add to existing cell more rad resistance
var newResistance = radResistance;
if (grid.TryGetValue(tilePos, out var existingResistance))
{
newResistance += existingResistance;
}
grid[tilePos] = newResistance;
}
private void RemoveFromTile(EntityUid gridUid, Vector2i tilePos, float radResistance)
{
// get grid
if (!TryComp(gridUid, out RadiationGridResistanceComponent? resistance))
return;
var grid = resistance.ResistancePerTile;
// subtract resistance from tile
if (!grid.TryGetValue(tilePos, out var existingResistance))
return;
existingResistance -= radResistance;
// remove tile from grid if no resistance left
if (existingResistance > 0)
grid[tilePos] = existingResistance;
else
{
grid.Remove(tilePos);
if (grid.Count == 0)
RemComp(gridUid, resistance);
}
}
}