* Explosions * fix yaml typo and prevent silly UI inputs * oop * Use modified contains() checks And remove IEnumerable * Buff nuke, nerf meteors * optimize the entity lookup stuff a bit * fix tile (0,0) error forgot to do an initial Enumerator.MoveNext(), so the first tile was always the "null" tile. * remove celebration * byte -> int * remove diag edge tile dict * fix one bug but there is another * fix the other bug turns out dividing a ushort leads to rounding errors. Why TF is the grid tile size even a ushort in the first place. * improve edge map * fix minor bug If the initial-explosion tile had an airtight entity on it, the tile was processed twice. * some reviews (transform queries, eye.mapid, and tilesizes in overlays) * Apply suggestions from code review Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> * is map paused * GetAllTiles ignores space by default * WriteLine -> WriteError * First -> FirstOrDefault() * default prototype const string * entity query * misc review changes * grid edge max distance * fix fire texture defn bad use of type serializer and ioc-resolves * Remove ExplosionLaunched And allow nukes to throw items towards the outer part of an explosion * no hot-reload disclaimer * replace prototype id string with int index * optimise damage a tiiiiny bit. * entity queries * comments * misc mirror comments * cvars * admin logs * move intensity-per-state to prototype * update tile event to ECS event * git mv * Tweak rpg & minibomb also fix merge bug * you don't exist anymore go away * Fix build Co-authored-by: moonheart08 <moonheart08@users.noreply.github.com> Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com>
150 lines
5.6 KiB
C#
150 lines
5.6 KiB
C#
using Content.Server.Atmos.Components;
|
|
using Content.Server.Explosion.EntitySystems;
|
|
using Content.Server.Kudzu;
|
|
using Content.Shared.Atmos;
|
|
using JetBrains.Annotations;
|
|
using Robust.Shared.GameObjects;
|
|
using Robust.Shared.IoC;
|
|
using Robust.Shared.Map;
|
|
using Robust.Shared.Maths;
|
|
|
|
namespace Content.Server.Atmos.EntitySystems
|
|
{
|
|
[UsedImplicitly]
|
|
public sealed class AirtightSystem : EntitySystem
|
|
{
|
|
[Dependency] private readonly IMapManager _mapManager = default!;
|
|
[Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!;
|
|
[Dependency] private readonly ExplosionSystem _explosionSystem = default!;
|
|
|
|
public override void Initialize()
|
|
{
|
|
SubscribeLocalEvent<AirtightComponent, ComponentInit>(OnAirtightInit);
|
|
SubscribeLocalEvent<AirtightComponent, ComponentShutdown>(OnAirtightShutdown);
|
|
SubscribeLocalEvent<AirtightComponent, AnchorStateChangedEvent>(OnAirtightPositionChanged);
|
|
SubscribeLocalEvent<AirtightComponent, RotateEvent>(OnAirtightRotated);
|
|
}
|
|
|
|
private void OnAirtightInit(EntityUid uid, AirtightComponent airtight, ComponentInit args)
|
|
{
|
|
var xform = EntityManager.GetComponent<TransformComponent>(uid);
|
|
|
|
if (airtight.FixAirBlockedDirectionInitialize)
|
|
{
|
|
var rotateEvent = new RotateEvent(airtight.Owner, Angle.Zero, xform.WorldRotation, xform);
|
|
OnAirtightRotated(uid, airtight, ref rotateEvent);
|
|
}
|
|
|
|
// Adding this component will immediately anchor the entity, because the atmos system
|
|
// requires airtight entities to be anchored for performance.
|
|
xform.Anchored = true;
|
|
|
|
UpdatePosition(airtight);
|
|
}
|
|
|
|
private void OnAirtightShutdown(EntityUid uid, AirtightComponent airtight, ComponentShutdown args)
|
|
{
|
|
var xform = Transform(uid);
|
|
|
|
// If the grid is deleting no point updating atmos.
|
|
if (_mapManager.TryGetGrid(xform.GridID, out var grid))
|
|
{
|
|
if (MetaData(grid.GridEntityId).EntityLifeStage > EntityLifeStage.MapInitialized) return;
|
|
}
|
|
|
|
SetAirblocked(airtight, false, xform);
|
|
}
|
|
|
|
private void OnAirtightPositionChanged(EntityUid uid, AirtightComponent airtight, ref AnchorStateChangedEvent args)
|
|
{
|
|
var xform = EntityManager.GetComponent<TransformComponent>(uid);
|
|
|
|
var gridId = xform.GridID;
|
|
var coords = xform.Coordinates;
|
|
|
|
var grid = _mapManager.GetGrid(gridId);
|
|
var tilePos = grid.TileIndicesFor(coords);
|
|
|
|
// Update and invalidate new position.
|
|
airtight.LastPosition = (gridId, tilePos);
|
|
InvalidatePosition(gridId, tilePos);
|
|
}
|
|
|
|
private void OnAirtightRotated(EntityUid uid, AirtightComponent airtight, ref RotateEvent ev)
|
|
{
|
|
if (!airtight.RotateAirBlocked || airtight.InitialAirBlockedDirection == (int)AtmosDirection.Invalid)
|
|
return;
|
|
|
|
airtight.CurrentAirBlockedDirection = (int) Rotate((AtmosDirection)airtight.InitialAirBlockedDirection, ev.NewRotation);
|
|
UpdatePosition(airtight);
|
|
RaiseLocalEvent(uid, new AirtightChanged(airtight));
|
|
}
|
|
|
|
public void SetAirblocked(AirtightComponent airtight, bool airblocked, TransformComponent? xform = null)
|
|
{
|
|
if (!Resolve(airtight.Owner, ref xform)) return;
|
|
|
|
airtight.AirBlocked = airblocked;
|
|
UpdatePosition(airtight, xform);
|
|
RaiseLocalEvent(airtight.Owner, new AirtightChanged(airtight));
|
|
}
|
|
|
|
public void UpdatePosition(AirtightComponent airtight, TransformComponent? xform = null)
|
|
{
|
|
if (!Resolve(airtight.Owner, ref xform)) return;
|
|
|
|
if (!xform.Anchored || !xform.GridID.IsValid())
|
|
return;
|
|
|
|
var grid = _mapManager.GetGrid(xform.GridID);
|
|
airtight.LastPosition = (xform.GridID, grid.TileIndicesFor(xform.Coordinates));
|
|
InvalidatePosition(airtight.LastPosition.Item1, airtight.LastPosition.Item2, airtight.FixVacuum && !airtight.AirBlocked);
|
|
}
|
|
|
|
public void InvalidatePosition(GridId gridId, Vector2i pos, bool fixVacuum = false)
|
|
{
|
|
if (!gridId.IsValid())
|
|
return;
|
|
|
|
var query = EntityManager.GetEntityQuery<AirtightComponent>();
|
|
_explosionSystem.UpdateAirtightMap(gridId, pos, query);
|
|
// TODO make atmos system use query
|
|
_atmosphereSystem.UpdateAdjacent(gridId, pos);
|
|
_atmosphereSystem.InvalidateTile(gridId, pos);
|
|
|
|
if(fixVacuum)
|
|
_atmosphereSystem.FixVacuum(gridId, pos);
|
|
}
|
|
|
|
private AtmosDirection Rotate(AtmosDirection myDirection, Angle myAngle)
|
|
{
|
|
var newAirBlockedDirs = AtmosDirection.Invalid;
|
|
|
|
if (myAngle == Angle.Zero)
|
|
return myDirection;
|
|
|
|
// TODO ATMOS MULTIZ: When we make multiZ atmos, special case this.
|
|
for (var i = 0; i < Atmospherics.Directions; i++)
|
|
{
|
|
var direction = (AtmosDirection) (1 << i);
|
|
if (!myDirection.IsFlagSet(direction)) continue;
|
|
var angle = direction.ToAngle();
|
|
angle += myAngle;
|
|
newAirBlockedDirs |= angle.ToAtmosDirectionCardinal();
|
|
}
|
|
|
|
return newAirBlockedDirs;
|
|
}
|
|
}
|
|
|
|
public sealed class AirtightChanged : EntityEventArgs
|
|
{
|
|
public AirtightComponent Airtight;
|
|
|
|
public AirtightChanged(AirtightComponent airtight)
|
|
{
|
|
Airtight = airtight;
|
|
}
|
|
}
|
|
}
|