diff --git a/Content.Client/GameObjects/Components/Doors/AirlockVisualizer.cs b/Content.Client/GameObjects/Components/Doors/AirlockVisualizer.cs index 2c0994a35e..4cc6278333 100644 --- a/Content.Client/GameObjects/Components/Doors/AirlockVisualizer.cs +++ b/Content.Client/GameObjects/Components/Doors/AirlockVisualizer.cs @@ -2,6 +2,7 @@ using Content.Client.GameObjects.Components.Wires; using Content.Shared.Audio; using Content.Shared.GameObjects.Components.Doors; +using JetBrains.Annotations; using Robust.Client.Animations; using Robust.Client.GameObjects; using Robust.Client.GameObjects.Components.Animations; @@ -12,6 +13,7 @@ using YamlDotNet.RepresentationModel; namespace Content.Client.GameObjects.Components.Doors { + [UsedImplicitly] public class AirlockVisualizer : AppearanceVisualizer { private const string AnimationKey = "airlock_animation"; @@ -24,11 +26,17 @@ namespace Content.Client.GameObjects.Components.Doors { base.LoadData(node); + var delay = 0.8f; + var openSound = node.GetNode("open_sound").AsString(); var closeSound = node.GetNode("close_sound").AsString(); var denySound = node.GetNode("deny_sound").AsString(); + if (node.TryGetNode("animation_time", out var yamlNode)) + { + delay = yamlNode.AsFloat(); + } - CloseAnimation = new Animation {Length = TimeSpan.FromSeconds(0.8f)}; + CloseAnimation = new Animation {Length = TimeSpan.FromSeconds(delay)}; { var flick = new AnimationTrackSpriteFlick(); CloseAnimation.AnimationTracks.Add(flick); @@ -50,7 +58,7 @@ namespace Content.Client.GameObjects.Components.Doors sound.KeyFrames.Add(new AnimationTrackPlaySound.KeyFrame(closeSound, 0)); } - OpenAnimation = new Animation {Length = TimeSpan.FromSeconds(0.8f)}; + OpenAnimation = new Animation {Length = TimeSpan.FromSeconds(delay)}; { var flick = new AnimationTrackSpriteFlick(); OpenAnimation.AnimationTracks.Add(flick); diff --git a/Content.Client/IgnoredComponents.cs b/Content.Client/IgnoredComponents.cs index 49f804ca64..c0fd55dfb4 100644 --- a/Content.Client/IgnoredComponents.cs +++ b/Content.Client/IgnoredComponents.cs @@ -176,6 +176,7 @@ "ExtinguisherCabinet", "ExtinguisherCabinetFilled", "FireExtinguisher", + "Firelock", "AtmosPlaque", "Spillable", }; diff --git a/Content.IntegrationTests/Tests/Atmos/GasMixtureTest.cs b/Content.IntegrationTests/Tests/Atmos/GasMixtureTest.cs new file mode 100644 index 0000000000..0b7f2f9e2d --- /dev/null +++ b/Content.IntegrationTests/Tests/Atmos/GasMixtureTest.cs @@ -0,0 +1,85 @@ +using System.Threading.Tasks; +using Content.Server.Atmos; +using Content.Shared.Atmos; +using NUnit.Framework; + +namespace Content.IntegrationTests.Tests.Atmos +{ + [TestFixture] + [TestOf(typeof(GasMixture))] + public class GasMixtureTest : ContentIntegrationTest + { + [Test] + public async Task TestMerge() + { + var server = StartServerDummyTicker(); + + server.Assert(() => + { + var a = new GasMixture(10f); + var b = new GasMixture(10f); + + a.AdjustMoles(Gas.Oxygen, 50); + b.AdjustMoles(Gas.Nitrogen, 50); + + // a now has 50 moles of oxygen + Assert.That(a.TotalMoles, Is.EqualTo(50)); + Assert.That(a.GetMoles(Gas.Oxygen), Is.EqualTo(50)); + + // b now has 50 moles of nitrogen + Assert.That(b.TotalMoles, Is.EqualTo(50)); + Assert.That(b.GetMoles(Gas.Nitrogen), Is.EqualTo(50)); + + b.Merge(a); + + // b now has its contents and the contents of a + Assert.That(b.TotalMoles, Is.EqualTo(100)); + Assert.That(b.GetMoles(Gas.Oxygen), Is.EqualTo(50)); + Assert.That(b.GetMoles(Gas.Nitrogen), Is.EqualTo(50)); + + // a should be the same, however. + Assert.That(a.TotalMoles, Is.EqualTo(50)); + Assert.That(a.GetMoles(Gas.Oxygen), Is.EqualTo(50)); + }); + + await server.WaitIdleAsync(); + } + + [Test] + [TestCase(0.5f)] + [TestCase(0.25f)] + [TestCase(0.75f)] + [TestCase(1f)] + [TestCase(0f)] + [TestCase(Atmospherics.BreathPercentage)] + public async Task RemoveRatio(float ratio) + { + var server = StartServerDummyTicker(); + + server.Assert(() => + { + var a = new GasMixture(10f); + + a.AdjustMoles(Gas.Oxygen, 100); + a.AdjustMoles(Gas.Nitrogen, 100); + + var origTotal = a.TotalMoles; + + // we remove moles from the mixture with a ratio. + var b = a.RemoveRatio(ratio); + + // check that the amount of moles in the original and the new mixture are correct. + Assert.That(b.TotalMoles, Is.EqualTo(origTotal * ratio)); + Assert.That(a.TotalMoles, Is.EqualTo(origTotal - b.TotalMoles)); + + Assert.That(b.GetMoles(Gas.Oxygen), Is.EqualTo(100 * ratio)); + Assert.That(b.GetMoles(Gas.Nitrogen), Is.EqualTo(100 * ratio)); + + Assert.That(a.GetMoles(Gas.Oxygen), Is.EqualTo(100 - b.GetMoles(Gas.Oxygen))); + Assert.That(a.GetMoles(Gas.Nitrogen), Is.EqualTo(100 - b.GetMoles(Gas.Nitrogen))); + }); + + await server.WaitIdleAsync(); + } + } +} diff --git a/Content.Server/Atmos/GasMixture.cs b/Content.Server/Atmos/GasMixture.cs index ddd834eceb..54bb5ad47c 100644 --- a/Content.Server/Atmos/GasMixture.cs +++ b/Content.Server/Atmos/GasMixture.cs @@ -545,6 +545,10 @@ namespace Content.Server.Atmos serializer.DataField(ref _moles, "moles", new float[Atmospherics.TotalNumberOfGases]); serializer.DataField(ref _molesArchived, "molesArchived", new float[Atmospherics.TotalNumberOfGases]); serializer.DataField(ref _temperature, "temperature", Atmospherics.TCMB); + + // The arrays MUST have a specific length. + Array.Resize(ref _moles, Atmospherics.TotalNumberOfGases); + Array.Resize(ref _molesArchived, Atmospherics.TotalNumberOfGases); } public override bool Equals(object? obj) diff --git a/Content.Server/Atmos/IGridAtmosphereComponent.cs b/Content.Server/Atmos/IGridAtmosphereComponent.cs index 1a8f76954c..0d7a827bf9 100644 --- a/Content.Server/Atmos/IGridAtmosphereComponent.cs +++ b/Content.Server/Atmos/IGridAtmosphereComponent.cs @@ -1,8 +1,11 @@ using System.Collections.Generic; +using Content.Server.GameObjects.Components.Atmos; using Content.Server.GameObjects.Components.Atmos.Piping; using Content.Server.GameObjects.Components.NodeContainer.NodeGroups; +using Content.Shared.Atmos; using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Map; +using Robust.Shared.Maths; namespace Content.Server.Atmos { @@ -42,6 +45,12 @@ namespace Content.Server.Atmos /// void FixVacuum(MapIndices indices); + /// + /// Revalidates indices immediately. + /// + /// + void UpdateAdjacentBits(MapIndices indices); + /// /// Adds an active tile so it becomes processed every update until it becomes inactive. /// Also makes the tile excited. @@ -109,6 +118,7 @@ namespace Content.Server.Atmos /// Returns a tile. /// /// + /// /// TileAtmosphere GetTile(MapIndices indices, bool createSpace = true); @@ -116,17 +126,19 @@ namespace Content.Server.Atmos /// Returns a tile. /// /// + /// /// TileAtmosphere GetTile(EntityCoordinates coordinates, bool createSpace = true); /// /// Returns if the tile in question is air-blocked. /// This could be due to a wall, an airlock, etc. - /// Also see AirtightComponent. + /// /// /// + /// /// - bool IsAirBlocked(MapIndices indices); + bool IsAirBlocked(MapIndices indices, AtmosDirection direction); /// /// Returns if the tile in question is space. @@ -142,6 +154,11 @@ namespace Content.Server.Atmos /// float GetVolumeForCells(int cellCount); + /// + /// Returns a dictionary of adjacent TileAtmospheres. + /// + Dictionary GetAdjacentTiles(MapIndices indices, bool includeAirBlocked = false); + void Update(float frameTime); void AddPipeNet(IPipeNet pipeNet); diff --git a/Content.Server/Atmos/TileAtmosphere.cs b/Content.Server/Atmos/TileAtmosphere.cs index 6b11195176..6361574211 100644 --- a/Content.Server/Atmos/TileAtmosphere.cs +++ b/Content.Server/Atmos/TileAtmosphere.cs @@ -6,6 +6,7 @@ using Content.Server.Atmos.Reactions; using Content.Server.GameObjects.Components.Atmos; using Content.Server.GameObjects.EntitySystems.Atmos; using Content.Server.Interfaces; +using Content.Server.Utility; using Content.Shared.Atmos; using Content.Shared.Audio; using Content.Shared.Maps; @@ -66,7 +67,7 @@ namespace Content.Server.Atmos public float HeatCapacity { get; set; } = 1f; [ViewVariables] - public float ThermalConductivity => Tile?.Tile.GetContentTileDefinition().ThermalConductivity ?? 0.05f; + public float ThermalConductivity { get; set; } = 0.05f; [ViewVariables] public bool Excited { get; set; } @@ -111,8 +112,13 @@ namespace Content.Server.Atmos [ViewVariables] public GasMixture Air { get; set; } + [ViewVariables, UsedImplicitly] + private int _blockedAirflow => (int)BlockedAirflow; + + public AtmosDirection BlockedAirflow { get; set; } = AtmosDirection.Invalid; + [ViewVariables] - public bool BlocksAir => _gridAtmosphereComponent.IsAirBlocked(GridIndices); + public bool BlocksAllAir => BlockedAirflow == AtmosDirection.All; public TileAtmosphere(GridAtmosphereComponent atmosphereComponent, GridId gridIndex, MapIndices gridIndices, GasMixture mixture = null, bool immutable = false) { @@ -867,12 +873,12 @@ namespace Content.Server.Atmos private void FinishSuperconduction() { // Conduct with air on my tile if I have it - if (!BlocksAir) + if (!BlocksAllAir) { Temperature = Air.TemperatureShare(ThermalConductivity, Temperature, HeatCapacity); } - FinishSuperconduction(BlocksAir ? Temperature : Air.Temperature); + FinishSuperconduction(BlocksAllAir ? Temperature : Air.Temperature); } private void FinishSuperconduction(float temperature) @@ -886,9 +892,9 @@ namespace Content.Server.Atmos private void NeighborConductWithSource(TileAtmosphere other) { - if (BlocksAir) + if (BlocksAllAir) { - if (!other.BlocksAir) + if (!other.BlocksAllAir) { other.TemperatureShareOpenToSolid(this); } @@ -901,7 +907,7 @@ namespace Content.Server.Atmos return; } - if (!other.BlocksAir) + if (!other.BlocksAllAir) { other.Air.TemperatureShare(Air, Atmospherics.WindowHeatTransferCoefficient); } @@ -952,7 +958,7 @@ namespace Content.Server.Atmos public AtmosDirection ConductivityDirections() { - if(BlocksAir) + if(BlocksAllAir) { if(_archivedCycle < _gridAtmosphereComponent.UpdateCounter) Archive(_gridAtmosphereComponent.UpdateCounter); @@ -1087,7 +1093,25 @@ namespace Content.Server.Atmos private void ConsiderFirelocks(TileAtmosphere other) { - // TODO ATMOS firelocks! + var reconsiderAdjacent = false; + + foreach (var entity in GridIndices.GetEntitiesInTileFast(GridIndex, _gridAtmosphereComponent.GridTileLookupSystem)) + { + if (!entity.TryGetComponent(out FirelockComponent firelock)) continue; + reconsiderAdjacent |= firelock.EmergencyPressureStop(); + } + + foreach (var entity in other.GridIndices.GetEntitiesInTileFast(other.GridIndex, _gridAtmosphereComponent.GridTileLookupSystem)) + { + if (!entity.TryGetComponent(out FirelockComponent firelock)) continue; + reconsiderAdjacent |= firelock.EmergencyPressureStop(); + } + + if (reconsiderAdjacent) + { + UpdateAdjacent(); + other.UpdateAdjacent(); + } } private void React() @@ -1130,7 +1154,7 @@ namespace Content.Server.Atmos _adjacentTiles[direction.ToIndex()] = adjacent; adjacent?.UpdateAdjacent(direction.GetOpposite()); - if (adjacent != null && !_gridAtmosphereComponent.IsAirBlocked(adjacent.GridIndices)) + if (adjacent != null && !BlockedAirflow.HasFlag(direction) && !_gridAtmosphereComponent.IsAirBlocked(adjacent.GridIndices, direction.GetOpposite())) { _adjacentBits |= direction; } @@ -1139,9 +1163,15 @@ namespace Content.Server.Atmos public void UpdateAdjacent(AtmosDirection direction) { - if (!_gridAtmosphereComponent.IsAirBlocked(GridIndices.Offset(direction.ToDirection()))) + _adjacentTiles[direction.ToIndex()] = _gridAtmosphereComponent.GetTile(GridIndices.Offset(direction.ToDirection())); + + if (!BlockedAirflow.HasFlag(direction) && !_gridAtmosphereComponent.IsAirBlocked(GridIndices.Offset(direction.ToDirection()), direction.GetOpposite())) { - _adjacentTiles[direction.ToIndex()] = _gridAtmosphereComponent.GetTile(GridIndices.Offset(direction.ToDirection())); + _adjacentBits |= direction; + } + else + { + _adjacentBits &= ~direction; } } diff --git a/Content.Server/GameObjects/Components/Atmos/AirtightComponent.cs b/Content.Server/GameObjects/Components/Atmos/AirtightComponent.cs index 9e422a8767..22c0783548 100644 --- a/Content.Server/GameObjects/Components/Atmos/AirtightComponent.cs +++ b/Content.Server/GameObjects/Components/Atmos/AirtightComponent.cs @@ -1,5 +1,7 @@ #nullable enable +using System; using Content.Server.GameObjects.EntitySystems; +using Content.Shared.Atmos; using Robust.Server.Interfaces.GameObjects; using Robust.Shared.GameObjects; using Robust.Shared.GameObjects.Components.Transform; @@ -9,6 +11,7 @@ using Robust.Shared.Interfaces.Map; using Robust.Shared.IoC; using Robust.Shared.Log; using Robust.Shared.Map; +using Robust.Shared.Maths; using Robust.Shared.Serialization; using Robust.Shared.ViewVariables; @@ -21,12 +24,21 @@ namespace Content.Server.GameObjects.Components.Atmos [Dependency] private readonly IEntityManager _entityManager = default!; private (GridId, MapIndices) _lastPosition; + private AtmosphereSystem _atmosphereSystem = default!; public override string Name => "Airtight"; + [ViewVariables] + private int _airBlockedDirection; private bool _airBlocked = true; private bool _fixVacuum = false; + [ViewVariables] + private bool _rotateAirBlocked = true; + + [ViewVariables] + private bool _fixAirBlockedDirectionInitialize = true; + [ViewVariables(VVAccess.ReadWrite)] public bool AirBlocked { @@ -35,10 +47,18 @@ namespace Content.Server.GameObjects.Components.Atmos { _airBlocked = value; - if (Owner.TryGetComponent(out SnapGridComponent? snapGrid)) - { - EntitySystem.Get().GetGridAtmosphere(Owner.Transform.GridID)?.Invalidate(snapGrid.Position); - } + UpdatePosition(); + } + } + + public AtmosDirection AirBlockedDirection + { + get => (AtmosDirection)_airBlockedDirection; + set + { + _airBlockedDirection = (int) value; + + UpdatePosition(); } } @@ -51,22 +71,53 @@ namespace Content.Server.GameObjects.Components.Atmos serializer.DataField(ref _airBlocked, "airBlocked", true); serializer.DataField(ref _fixVacuum, "fixVacuum", true); + serializer.DataField(ref _airBlockedDirection, "airBlockedDirection", (int)AtmosDirection.All, WithFormat.Flags()); + serializer.DataField(ref _rotateAirBlocked, "rotateAirBlocked", true); + serializer.DataField(ref _fixAirBlockedDirectionInitialize, "fixAirBlockedDirectionInitialize", true); } public override void Initialize() { base.Initialize(); - // Using the SnapGrid is critical for the performance of the room builder, and thus if - // it is absent the component will not be airtight. A warning is much easier to track - // down than the object magically not being airtight, so log one if the SnapGrid component - // is missing. + _atmosphereSystem = EntitySystem.Get(); + + // Using the SnapGrid is critical for performance, and thus if it is absent the component + // will not be airtight. A warning is much easier to track down than the object magically + // not being airtight, so log one if the SnapGrid component is missing. if (!Owner.EnsureComponent(out SnapGridComponent _)) Logger.Warning($"Entity {Owner} at {Owner.Transform.MapPosition.ToString()} didn't have a {nameof(SnapGridComponent)}"); + Owner.EntityManager.EventBus.SubscribeEvent(EventSource.Local, this, RotateEvent); + + if(_fixAirBlockedDirectionInitialize) + RotateEvent(new RotateEvent(Owner, Angle.South, Owner.Transform.LocalRotation)); + UpdatePosition(); } + private void RotateEvent(RotateEvent ev) + { + if (!_rotateAirBlocked || ev.Sender != Owner || ev.NewRotation == ev.OldRotation || AirBlockedDirection == AtmosDirection.Invalid) + return; + + var diff = ev.NewRotation - ev.OldRotation; + + var newAirBlockedDirs = AtmosDirection.Invalid; + + // TODO ATMOS MULTIZ When we make multiZ atmos, special case this. + for (int i = 0; i < Atmospherics.Directions; i++) + { + var direction = (AtmosDirection) (1 << i); + if (!AirBlockedDirection.HasFlag(direction)) continue; + var angle = direction.ToAngle(); + angle += diff; + newAirBlockedDirs |= angle.ToAtmosDirectionCardinal(); + } + + AirBlockedDirection = newAirBlockedDirs; + } + public void MapInit() { if (Owner.TryGetComponent(out SnapGridComponent? snapGrid)) @@ -89,13 +140,10 @@ namespace Content.Server.GameObjects.Components.Atmos snapGrid.OnPositionChanged -= OnTransformMove; } - if (_fixVacuum) - { - var mapIndices = Owner.Transform.Coordinates.ToMapIndices(_entityManager, _mapManager); - EntitySystem.Get().GetGridAtmosphere(Owner.Transform.GridID)?.FixVacuum(mapIndices); - } + UpdatePosition(_lastPosition.Item1, _lastPosition.Item2); - UpdatePosition(); + if (_fixVacuum) + _atmosphereSystem.GetGridAtmosphere(_lastPosition.Item1)?.FixVacuum(_lastPosition.Item2); } private void OnTransformMove() @@ -111,13 +159,18 @@ namespace Content.Server.GameObjects.Components.Atmos private void UpdatePosition() { - var mapIndices = Owner.Transform.Coordinates.ToMapIndices(_entityManager, _mapManager); - UpdatePosition(Owner.Transform.GridID, mapIndices); + if (Owner.TryGetComponent(out SnapGridComponent? snapGrid)) + UpdatePosition(Owner.Transform.GridID, snapGrid.Position); } private void UpdatePosition(GridId gridId, MapIndices pos) { - EntitySystem.Get().GetGridAtmosphere(gridId)?.Invalidate(pos); + var gridAtmos = _atmosphereSystem.GetGridAtmosphere(gridId); + + if (gridAtmos == null) return; + + gridAtmos.UpdateAdjacentBits(pos); + gridAtmos.Invalidate(pos); } } } diff --git a/Content.Server/GameObjects/Components/Atmos/FirelockComponent.cs b/Content.Server/GameObjects/Components/Atmos/FirelockComponent.cs new file mode 100644 index 0000000000..6ef8768e37 --- /dev/null +++ b/Content.Server/GameObjects/Components/Atmos/FirelockComponent.cs @@ -0,0 +1,105 @@ +using System; +using System.Threading.Tasks; +using Content.Server.Atmos; +using Content.Server.GameObjects.Components.Doors; +using Content.Server.GameObjects.Components.Interactable; +using Content.Server.Interfaces; +using Content.Shared.GameObjects.Components.Doors; +using Content.Shared.GameObjects.Components.Interactable; +using Content.Shared.Interfaces; +using Content.Shared.Interfaces.GameObjects.Components; +using Robust.Shared.GameObjects; +using Robust.Shared.GameObjects.Components; +using Robust.Shared.Interfaces.GameObjects; +using Robust.Shared.IoC; + +namespace Content.Server.GameObjects.Components.Atmos +{ + [RegisterComponent] + public class FirelockComponent : ServerDoorComponent, IInteractUsing, ICollideBehavior + { + public override string Name => "Firelock"; + + protected override TimeSpan CloseTimeOne => TimeSpan.FromSeconds(0.1f); + protected override TimeSpan CloseTimeTwo => TimeSpan.FromSeconds(0.6f); + protected override TimeSpan OpenTimeOne => TimeSpan.FromSeconds(0.1f); + protected override TimeSpan OpenTimeTwo => TimeSpan.FromSeconds(0.6f); + + public void CollideWith(IEntity collidedWith) + { + // We do nothing. + } + + protected override void Startup() + { + base.Startup(); + + if (Owner.TryGetComponent(out AirtightComponent airtightComponent)) + { + airtightComponent.AirBlocked = false; + } + + if (Owner.TryGetComponent(out ICollidableComponent collidableComponent)) + { + collidableComponent.Hard = false; + } + + Safety = false; + + if (Occludes && Owner.TryGetComponent(out OccluderComponent occluder)) + { + occluder.Enabled = false; + } + + State = DoorState.Open; + SetAppearance(DoorVisualState.Open); + } + + public bool EmergencyPressureStop() + { + var closed = State == DoorState.Open && Close(); + + if(closed) + Owner.GetComponent().AirBlocked = true; + + return closed; + } + + public override bool CanOpen() + { + return !IsHoldingFire() && !IsHoldingPressure() && base.CanOpen(); + } + + public override bool CanClose(IEntity user) => true; + public override bool CanOpen(IEntity user) => CanOpen(); + + public async Task InteractUsing(InteractUsingEventArgs eventArgs) + { + if (!eventArgs.Using.TryGetComponent(out var tool)) + return false; + + if (tool.HasQuality(ToolQuality.Prying)) + { + var holdingPressure = IsHoldingPressure(); + var holdingFire = IsHoldingFire(); + + if (State == DoorState.Closed) + { + if(holdingPressure) + Owner.PopupMessage(eventArgs.User, "A gush of air blows in your face... Maybe you should reconsider."); + } + + if (!await tool.UseTool(eventArgs.User, Owner, holdingPressure || holdingFire ? 1.5f : 0.25f, ToolQuality.Prying)) return false; + + if (State == DoorState.Closed) + Open(); + else if (State == DoorState.Open) + Close(); + + return true; + } + + return false; + } + } +} diff --git a/Content.Server/GameObjects/Components/Atmos/GridAtmosphereComponent.cs b/Content.Server/GameObjects/Components/Atmos/GridAtmosphereComponent.cs index 705b9c585f..f33e03fd64 100644 --- a/Content.Server/GameObjects/Components/Atmos/GridAtmosphereComponent.cs +++ b/Content.Server/GameObjects/Components/Atmos/GridAtmosphereComponent.cs @@ -9,11 +9,14 @@ using Content.Server.GameObjects.Components.Atmos.Piping; using Content.Server.GameObjects.Components.NodeContainer.NodeGroups; using Content.Shared.Atmos; using Content.Shared.Maps; +using Robust.Server.GameObjects.EntitySystems.TileLookup; using Robust.Server.Interfaces.GameObjects; using Robust.Shared.GameObjects; using Robust.Shared.GameObjects.Components.Map; using Robust.Shared.GameObjects.Components.Transform; +using Robust.Shared.GameObjects.Systems; using Robust.Shared.Interfaces.Map; +using Robust.Shared.IoC; using Robust.Shared.Map; using Robust.Shared.Serialization; using Robust.Shared.Timing; @@ -32,6 +35,8 @@ namespace Content.Server.GameObjects.Components.Atmos [Robust.Shared.IoC.Dependency] private ITileDefinitionManager _tileDefinitionManager = default!; [Robust.Shared.IoC.Dependency] private IServerEntityManager _serverEntityManager = default!; + public GridTileLookupSystem GridTileLookupSystem { get; private set; } = default!; + /// /// Check current execution time every n instances processed. /// @@ -52,6 +57,7 @@ namespace Content.Server.GameObjects.Components.Atmos private bool _paused = false; private float _timer = 0f; private Stopwatch _stopwatch = new Stopwatch(); + private GridId _gridId; [ViewVariables] public int UpdateCounter { get; private set; } = 0; @@ -155,23 +161,25 @@ namespace Content.Server.GameObjects.Components.Atmos /// public virtual void PryTile(MapIndices indices) { - if (!Owner.TryGetComponent(out IMapGridComponent? mapGridComponent)) return; if (IsSpace(indices) || IsAirBlocked(indices)) return; - var mapGrid = mapGridComponent.Grid; - indices.PryTile(mapGrid.Index, _mapManager, _tileDefinitionManager, _serverEntityManager); + indices.PryTile(_gridId, _mapManager, _tileDefinitionManager, _serverEntityManager); } public override void Initialize() { base.Initialize(); RepopulateTiles(); + + GridTileLookupSystem = EntitySystem.Get(); } public override void OnAdd() { base.OnAdd(); - RepopulateTiles(); + + if (Owner.TryGetComponent(out IMapGridComponent? mapGrid)) + _gridId = mapGrid.GridIndex; } public virtual void RepopulateTiles() @@ -182,6 +190,8 @@ namespace Content.Server.GameObjects.Components.Atmos { if(!Tiles.ContainsKey(tile.GridIndices)) Tiles.Add(tile.GridIndices, new TileAtmosphere(this, tile.GridIndex, tile.GridIndices, new GasMixture(GetVolumeForCells(1)){Temperature = Atmospherics.T20C})); + + Invalidate(tile.GridIndices); } foreach (var (_, tile) in Tiles.ToArray()) @@ -199,16 +209,13 @@ namespace Content.Server.GameObjects.Components.Atmos protected virtual void Revalidate() { - if (!Owner.TryGetComponent(out IMapGridComponent? mapGrid)) return; - foreach (var indices in _invalidatedCoords.ToArray()) { var tile = GetTile(indices); - AddActiveTile(tile); if (tile == null) { - tile = new TileAtmosphere(this, mapGrid.Grid.Index, indices, new GasMixture(GetVolumeForCells(1)){Temperature = Atmospherics.T20C}); + tile = new TileAtmosphere(this, _gridId, indices, new GasMixture(GetVolumeForCells(1)){Temperature = Atmospherics.T20C}); Tiles[indices] = tile; } @@ -224,19 +231,19 @@ namespace Content.Server.GameObjects.Components.Atmos } else { - var obs = GetObstructingComponent(indices); - - if (obs != null) + if (tile.Air == null && NeedsVacuumFixing(indices)) { - if (tile.Air == null && obs.FixVacuum) - { - FixVacuum(tile.GridIndices); - } + FixVacuum(tile.GridIndices); } tile.Air ??= new GasMixture(GetVolumeForCells(1)){Temperature = Atmospherics.T20C}; } + AddActiveTile(tile); + tile.BlockedAirflow = GetBlockedDirections(indices); + + // TODO ATMOS: Query all the contents of this tile (like walls) and calculate the correct thermal conductivity + tile.ThermalConductivity = tile.Tile?.Tile.GetContentTileDefinition().ThermalConductivity ?? 0.5f; tile.UpdateAdjacent(); tile.UpdateVisuals(); @@ -246,19 +253,23 @@ namespace Content.Server.GameObjects.Components.Atmos var otherIndices = indices.Offset(direction.ToDirection()); var otherTile = GetTile(otherIndices); AddActiveTile(otherTile); - otherTile?.UpdateAdjacent(direction.GetOpposite()); } } _invalidatedCoords.Clear(); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void UpdateAdjacentBits(MapIndices indices) + { + GetTile(indices)?.UpdateAdjacent(); + } + /// public virtual void FixVacuum(MapIndices indices) { - if (!Owner.TryGetComponent(out IMapGridComponent? mapGrid)) return; var tile = GetTile(indices); - if (tile?.GridIndex != mapGrid.Grid.Index) return; + if (tile?.GridIndex != _gridId) return; var adjacent = GetAdjacentTiles(indices); tile.Air = new GasMixture(GetVolumeForCells(1)){Temperature = Atmospherics.T20C}; Tiles[indices] = tile; @@ -277,8 +288,7 @@ namespace Content.Server.GameObjects.Components.Atmos [MethodImpl(MethodImplOptions.AggressiveInlining)] public virtual void AddActiveTile(TileAtmosphere? tile) { - if (!Owner.TryGetComponent(out IMapGridComponent? mapGrid)) return; - if (tile?.GridIndex != mapGrid.Grid.Index) return; + if (tile?.GridIndex != _gridId) return; tile.Excited = true; _activeTiles.Add(tile); } @@ -297,8 +307,7 @@ namespace Content.Server.GameObjects.Components.Atmos [MethodImpl(MethodImplOptions.AggressiveInlining)] public virtual void AddHotspotTile(TileAtmosphere? tile) { - if (!Owner.TryGetComponent(out IMapGridComponent? mapGrid)) return; - if (tile?.GridIndex != mapGrid.Grid.Index || tile?.Air == null) return; + if (tile?.GridIndex != _gridId || tile?.Air == null) return; _hotspotTiles.Add(tile); } @@ -312,8 +321,7 @@ namespace Content.Server.GameObjects.Components.Atmos public virtual void AddSuperconductivityTile(TileAtmosphere? tile) { - if (!Owner.TryGetComponent(out IMapGridComponent? mapGrid)) return; - if (tile?.GridIndex != mapGrid.Grid.Index) return; + if (tile?.GridIndex != _gridId) return; _superconductivityTiles.Add(tile); } @@ -327,8 +335,7 @@ namespace Content.Server.GameObjects.Components.Atmos [MethodImpl(MethodImplOptions.AggressiveInlining)] public virtual void AddHighPressureDelta(TileAtmosphere? tile) { - if (!Owner.TryGetComponent(out IMapGridComponent? mapGrid)) return; - if (tile?.GridIndex != mapGrid.Grid.Index) return; + if (tile?.GridIndex != _gridId) return; _highPressureDelta.Add(tile); } @@ -382,24 +389,30 @@ namespace Content.Server.GameObjects.Components.Atmos /// public TileAtmosphere? GetTile(MapIndices indices, bool createSpace = true) { - if (!Owner.TryGetComponent(out IMapGridComponent? mapGrid)) return null; - if (Tiles.TryGetValue(indices, out var tile)) return tile; // We don't have that tile! if (IsSpace(indices) && createSpace) { - return new TileAtmosphere(this, mapGrid.Grid.Index, indices, new GasMixture(GetVolumeForCells(1)){Temperature = Atmospherics.TCMB}, true); + return new TileAtmosphere(this, _gridId, indices, new GasMixture(GetVolumeForCells(1)){Temperature = Atmospherics.TCMB}, true); } return null; } /// - public bool IsAirBlocked(MapIndices indices) + public bool IsAirBlocked(MapIndices indices, AtmosDirection direction = AtmosDirection.All) { - var ac = GetObstructingComponent(indices); - return ac != null && ac.AirBlocked; + foreach (var obstructingComponent in GetObstructingComponents(indices)) + { + if (!obstructingComponent.AirBlocked) + continue; + + if (obstructingComponent.AirBlockedDirection.HasFlag(direction)) + return true; + } + + return false; } /// @@ -763,17 +776,43 @@ namespace Content.Server.GameObjects.Components.Atmos return true; } - private AirtightComponent? GetObstructingComponent(MapIndices indices) + private IEnumerable GetObstructingComponents(MapIndices indices) { - if (!Owner.TryGetComponent(out IMapGridComponent? mapGrid)) return default; + var gridLookup = EntitySystem.Get(); - foreach (var v in mapGrid.Grid.GetSnapGridCell(indices, SnapGridOffset.Center)) + var list = new List(); + + foreach (var v in gridLookup.GetEntitiesIntersecting(_gridId, indices)) { - if (v.Owner.TryGetComponent(out var ac)) - return ac; + if (v.TryGetComponent(out var ac)) + list.Add(ac); } - return null; + return list; + } + + private bool NeedsVacuumFixing(MapIndices indices) + { + var value = false; + + foreach (var airtightComponent in GetObstructingComponents(indices)) + { + value |= airtightComponent.FixVacuum; + } + + return value; + } + + private AtmosDirection GetBlockedDirections(MapIndices indices) + { + var value = AtmosDirection.Invalid; + + foreach (var airtightComponent in GetObstructingComponents(indices)) + { + value |= airtightComponent.AirBlockedDirection; + } + + return value; } public void Dispose() diff --git a/Content.Server/GameObjects/Components/Doors/ServerDoorComponent.cs b/Content.Server/GameObjects/Components/Doors/ServerDoorComponent.cs index cebf82ab73..79b48d6453 100644 --- a/Content.Server/GameObjects/Components/Doors/ServerDoorComponent.cs +++ b/Content.Server/GameObjects/Components/Doors/ServerDoorComponent.cs @@ -2,6 +2,7 @@ using System; using System.Linq; using System.Threading; +using Content.Server.Atmos; using System.Threading.Tasks; using Content.Server.GameObjects.Components.Access; using Content.Server.GameObjects.Components.Atmos; @@ -51,14 +52,14 @@ namespace Content.Server.GameObjects.Components.Doors protected const float AutoCloseDelay = 5; [ViewVariables(VVAccess.ReadWrite)] protected float CloseSpeed = AutoCloseDelay; - + private CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource(); - private static readonly TimeSpan CloseTimeOne = TimeSpan.FromSeconds(0.3f); - private static readonly TimeSpan CloseTimeTwo = TimeSpan.FromSeconds(0.9f); - private static readonly TimeSpan OpenTimeOne = TimeSpan.FromSeconds(0.3f); - private static readonly TimeSpan OpenTimeTwo = TimeSpan.FromSeconds(0.9f); - private static readonly TimeSpan DenyTime = TimeSpan.FromSeconds(0.45f); + protected virtual TimeSpan CloseTimeOne => TimeSpan.FromSeconds(0.3f); + protected virtual TimeSpan CloseTimeTwo => TimeSpan.FromSeconds(0.9f); + protected virtual TimeSpan OpenTimeOne => TimeSpan.FromSeconds(0.3f); + protected virtual TimeSpan OpenTimeTwo => TimeSpan.FromSeconds(0.9f); + protected virtual TimeSpan DenyTime => TimeSpan.FromSeconds(0.45f); private const int DoorCrushDamage = 15; private const float DoorStunTime = 5f; @@ -67,6 +68,8 @@ namespace Content.Server.GameObjects.Components.Doors [ViewVariables(VVAccess.ReadWrite)] private bool _occludes; + public bool Occludes => _occludes; + [ViewVariables(VVAccess.ReadWrite)] public bool IsWeldedShut { @@ -85,6 +88,9 @@ namespace Content.Server.GameObjects.Components.Doors private bool _isWeldedShut; private bool _canWeldShut = true; + + [ViewVariables(VVAccess.ReadWrite)] + private bool _canCrush = true; public override void ExposeData(ObjectSerializer serializer) { @@ -92,6 +98,7 @@ namespace Content.Server.GameObjects.Components.Doors serializer.DataField(ref _occludes, "occludes", true); serializer.DataField(ref _isWeldedShut, "welded", false); + serializer.DataField(ref _canCrush, "canCrush", true); } public override void OnRemove() @@ -146,7 +153,7 @@ namespace Content.Server.GameObjects.Components.Doors } } - private void SetAppearance(DoorVisualState state) + protected void SetAppearance(DoorVisualState state) { if (Owner.TryGetComponent(out AppearanceComponent? appearance)) { @@ -159,7 +166,7 @@ namespace Content.Server.GameObjects.Components.Doors return !_isWeldedShut; } - public bool CanOpen(IEntity user) + public virtual bool CanOpen(IEntity user) { if (!CanOpen()) return false; @@ -253,7 +260,7 @@ namespace Content.Server.GameObjects.Components.Doors return true; } - public bool CanClose(IEntity user) + public virtual bool CanClose(IEntity user) { if (!CanClose()) return false; if (!Owner.TryGetComponent(out AccessReader? accessReader)) @@ -313,11 +320,62 @@ namespace Content.Server.GameObjects.Components.Doors } } + public bool IsHoldingPressure(float threshold = 20) + { + var atmosphereSystem = EntitySystem.Get(); + + if (!Owner.Transform.Coordinates.TryGetTileAtmosphere(out var tileAtmos)) + return false; + + var gridAtmosphere = atmosphereSystem.GetGridAtmosphere(Owner.Transform.GridID); + + if (gridAtmosphere == null) + return false; + + var minMoles = float.MaxValue; + var maxMoles = 0f; + + foreach (var (direction, adjacent) in gridAtmosphere.GetAdjacentTiles(tileAtmos.GridIndices)) + { + var moles = adjacent.Air.TotalMoles; + if (moles < minMoles) + minMoles = moles; + if (moles > maxMoles) + maxMoles = moles; + } + + return (maxMoles - minMoles) > threshold; + } + + public bool IsHoldingFire() + { + var atmosphereSystem = EntitySystem.Get(); + + if (!Owner.Transform.Coordinates.TryGetTileAtmosphere(out var tileAtmos)) + return false; + + if (tileAtmos.Hotspot.Valid) + return true; + + var gridAtmosphere = atmosphereSystem.GetGridAtmosphere(Owner.Transform.GridID); + + if (gridAtmosphere == null) + return false; + + foreach (var (direction, adjacent) in gridAtmosphere.GetAdjacentTiles(tileAtmos.GridIndices)) + { + if (adjacent.Hotspot.Valid) + return true; + } + + return false; + } + public bool Close() { bool shouldCheckCrush = false; - if (Owner.TryGetComponent(out ICollidableComponent? collidable) && collidable.IsColliding(Vector2.Zero, false)) + if (_canCrush && Owner.TryGetComponent(out ICollidableComponent? collidable) && collidable.IsColliding(Vector2.Zero, false)) { if (Safety) return false; @@ -336,7 +394,7 @@ namespace Content.Server.GameObjects.Components.Doors Timer.Spawn(CloseTimeOne, async () => { - if (shouldCheckCrush) + if (shouldCheckCrush && _canCrush) { CheckCrush(); } diff --git a/Content.Server/Utility/GridTileLookupHelpers.cs b/Content.Server/Utility/GridTileLookupHelpers.cs new file mode 100644 index 0000000000..2494815d2f --- /dev/null +++ b/Content.Server/Utility/GridTileLookupHelpers.cs @@ -0,0 +1,40 @@ +#nullable enable +using System.Collections.Generic; +using System.Linq; +using System.Runtime.CompilerServices; +using Content.Shared.Maps; +using Robust.Server.GameObjects.EntitySystems.TileLookup; +using Robust.Shared.GameObjects.Systems; +using Robust.Shared.Interfaces.GameObjects; +using Robust.Shared.Map; + +namespace Content.Server.Utility +{ + public static class GridTileLookupHelpers + { + /// + /// Helper that returns all entities in a turf very fast. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static IEnumerable GetEntitiesInTileFast(this TileRef turf, GridTileLookupSystem? gridTileLookup = null) + { + gridTileLookup ??= EntitySystem.Get(); + + return gridTileLookup.GetEntitiesIntersecting(turf.GridIndex, turf.GridIndices); + } + + /// + /// Helper that returns all entities in a turf. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static IEnumerable GetEntitiesInTileFast(this MapIndices indices, GridId gridId, GridTileLookupSystem? gridTileLookup = null) + { + var turf = indices.GetTileRef(gridId); + + if (turf == null) + return Enumerable.Empty(); + + return GetEntitiesInTileFast(turf.Value, gridTileLookup); + } + } +} diff --git a/Content.Shared/Atmos/AtmosDirection.cs b/Content.Shared/Atmos/AtmosDirection.cs index 450a92e4df..fa0f36cc8f 100644 --- a/Content.Shared/Atmos/AtmosDirection.cs +++ b/Content.Shared/Atmos/AtmosDirection.cs @@ -1,13 +1,15 @@ using System; using Robust.Shared.Maths; +using Robust.Shared.Serialization; namespace Content.Shared.Atmos { /// /// The reason we use this over is that we are going to do some heavy bitflag usage. /// - [Flags] - public enum AtmosDirection : byte + [Flags, Serializable] + [FlagsFor(typeof(AtmosDirectionFlags))] + public enum AtmosDirection { Invalid = 0, North = 1 << 0, @@ -75,6 +77,49 @@ namespace Content.Shared.Atmos }; } + /// + /// Converts a direction to an angle, where angle is -PI to +PI. + /// + /// + /// + public static Angle ToAngle(this AtmosDirection direction) + { + return direction switch + { + AtmosDirection.East => Angle.FromDegrees(0), + AtmosDirection.North => Angle.FromDegrees(90), + AtmosDirection.West => Angle.FromDegrees(180), + AtmosDirection.South => Angle.FromDegrees(270), + + AtmosDirection.NorthEast => Angle.FromDegrees(45), + AtmosDirection.NorthWest => Angle.FromDegrees(135), + AtmosDirection.SouthWest => Angle.FromDegrees(225), + AtmosDirection.SouthEast => Angle.FromDegrees(315), + + _ => throw new ArgumentOutOfRangeException(nameof(direction), $"It was {direction}."), + }; + } + + /// + /// Converts an angle to a cardinal AtmosDirection + /// + /// + /// + public static AtmosDirection ToAtmosDirectionCardinal(this Angle angle) + { + return angle.GetCardinalDir().ToAtmosDirection(); + } + + /// + /// Converts an angle to an AtmosDirection + /// + /// + /// + public static AtmosDirection ToAtmosDirection(this Angle angle) + { + return angle.GetDir().ToAtmosDirection(); + } + public static int ToIndex(this AtmosDirection direction) { // This will throw if you pass an invalid direction. Not this method's fault, but yours! @@ -85,5 +130,12 @@ namespace Content.Shared.Atmos { return direction | other; } + + public static AtmosDirection WithoutFlag(this AtmosDirection direction, AtmosDirection other) + { + return direction & ~other; + } } + + public sealed class AtmosDirectionFlags { } } diff --git a/Content.Shared/Maps/TurfHelpers.cs b/Content.Shared/Maps/TurfHelpers.cs index 406d91331e..7207647375 100644 --- a/Content.Shared/Maps/TurfHelpers.cs +++ b/Content.Shared/Maps/TurfHelpers.cs @@ -1,8 +1,11 @@ #nullable enable using System.Collections.Generic; +using System.Linq; +using System.Runtime.CompilerServices; using System.Diagnostics.CodeAnalysis; using Content.Shared.Physics; using Content.Shared.Utility; +using Robust.Shared.GameObjects.Systems; using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Interfaces.Map; using Robust.Shared.Interfaces.Physics; @@ -57,7 +60,7 @@ namespace Content.Shared.Maps if (!mapManager.TryGetGrid(coordinates.GetGridId(entityManager), out var grid)) return null; - if (!grid.TryGetTileRef(coordinates.ToMapIndices(entityManager, mapManager), out var tile)) + if (!grid.TryGetTileRef(coordinates, out var tile)) return null; return tile; @@ -120,13 +123,40 @@ namespace Content.Shared.Maps /// /// Helper that returns all entities in a turf. /// - public static IEnumerable GetEntitiesInTile(this TileRef turf, bool approximate = false) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static IEnumerable GetEntitiesInTile(this TileRef turf, bool approximate = false, IEntityManager? entityManager = null) { - var entityManager = IoCManager.Resolve(); + entityManager ??= IoCManager.Resolve(); return entityManager.GetEntitiesIntersecting(turf.MapIndex, GetWorldTileBox(turf), approximate); } + /// + /// Helper that returns all entities in a turf. + /// + public static IEnumerable GetEntitiesInTile(this EntityCoordinates coordinates, bool approximate = false, IEntityManager? entityManager = null) + { + var turf = coordinates.GetTileRef(); + + if (turf == null) + return Enumerable.Empty(); + + return GetEntitiesInTile(turf.Value, approximate, entityManager); + } + + /// + /// Helper that returns all entities in a turf. + /// + public static IEnumerable GetEntitiesInTile(this MapIndices indices, GridId gridId, bool approximate = false, IEntityManager? entityManager = null) + { + var turf = indices.GetTileRef(gridId); + + if (turf == null) + return Enumerable.Empty(); + + return GetEntitiesInTile(turf.Value, approximate, entityManager); + } + /// /// Checks if a turf has something dense on it. /// diff --git a/Resources/Prototypes/Entities/Constructible/Doors/airlock_base.yml b/Resources/Prototypes/Entities/Constructible/Doors/airlock_base.yml index 54163a71c3..324bd96eb9 100644 --- a/Resources/Prototypes/Entities/Constructible/Doors/airlock_base.yml +++ b/Resources/Prototypes/Entities/Constructible/Doors/airlock_base.yml @@ -56,7 +56,6 @@ type: WiresBoundUserInterface - type: Airtight fixVacuum: true - adjacentAtmosphere: true - type: Occluder - type: SnapGrid offset: Center diff --git a/Resources/Prototypes/Entities/Constructible/Doors/firelock.yml b/Resources/Prototypes/Entities/Constructible/Doors/firelock.yml new file mode 100644 index 0000000000..e7bf98f41c --- /dev/null +++ b/Resources/Prototypes/Entities/Constructible/Doors/firelock.yml @@ -0,0 +1,108 @@ +- type: entity + id: Firelock + name: firelock + description: Apply crowbar. + components: + - type: Clickable + - type: InteractionOutline + - type: Sprite + netsync: false + drawdepth: Mobs # They're on the same layer as mobs, perspective. + sprite: Constructible/Structures/Doors/firelock.rsi + layers: + - state: closed + map: ["enum.DoorVisualLayers.Base"] + - state: closed_unlit + shader: unshaded + map: ["enum.DoorVisualLayers.BaseUnlit"] + - state: welded + map: ["enum.DoorVisualLayers.BaseWelded"] + - state: bolted + shader: unshaded + map: ["enum.DoorVisualLayers.BaseBolted"] + - state: panel_open + map: ["enum.WiresVisualLayers.MaintenancePanel"] + - type: Icon + sprite: Constructible/Structures/Doors/firelock.rsi + state: closed + - type: Collidable + shapes: + - !type:PhysShapeAabb + bounds: "-0.49,-0.49,0.49,0.49" # don't want this colliding with walls or they won't close + mask: + - MobImpassable + layer: + - Opaque + - Impassable + - MobImpassable + - VaultImpassable + - SmallImpassable + - type: Firelock + - type: Appearance + visuals: + - type: AirlockVisualizer + open_sound: /Audio/Machines/airlock_open.ogg + close_sound: /Audio/Machines/airlock_close.ogg + deny_sound: /Audio/Machines/airlock_deny.ogg + animation_time: 0.6 + - type: WiresVisualizer + - type: Wires + BoardName: "Firelock Control" + LayoutId: Firelock + - type: UserInterface + interfaces: + - key: enum.WiresUiKey.Key + type: WiresBoundUserInterface + - type: Airtight + fixVacuum: true + - type: Occluder + - type: SnapGrid + offset: Center + placement: + mode: SnapgridCenter + +- type: entity + id: FirelockGlass + parent: Firelock + name: glass firelock + components: + - type: Firelock + occludes: false + - type: Occluder + enabled: false + - type: Sprite + sprite: Constructible/Structures/Doors/firelock_glass.rsi + - type: Icon + sprite: Constructible/Structures/Doors/firelock_glass.rsi + +- type: entity + id: FirelockEdge + parent: Firelock + name: firelock + prefix: south + components: + - type: Firelock + occludes: false + canCrush: false + - type: Occluder + enabled: false + - type: Sprite + sprite: Constructible/Structures/Doors/edge_door_hazard.rsi + - type: Icon + sprite: Constructible/Structures/Doors/edge_door_hazard.rsi + - type: Airtight + fixVacuum: true + airBlockedDirection: + - South + - type: Collidable + shapes: + - !type:PhysShapeAabb + bounds: "-0.49,-0.49,-0.2,0.49" # don't want this colliding with walls or they won't close + mask: + - MobImpassable + layer: + - Opaque + - Impassable + - MobImpassable + - VaultImpassable + - SmallImpassable diff --git a/Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/alert_cold.png b/Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/alert_cold.png new file mode 100644 index 0000000000..c18f592c9f Binary files /dev/null and b/Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/alert_cold.png differ diff --git a/Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/alert_hot.png b/Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/alert_hot.png new file mode 100644 index 0000000000..3a572356dc Binary files /dev/null and b/Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/alert_hot.png differ diff --git a/Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/bolted.png b/Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/bolted.png new file mode 100644 index 0000000000..0858c19f05 Binary files /dev/null and b/Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/bolted.png differ diff --git a/Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/closed.png b/Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/closed.png new file mode 100644 index 0000000000..8968f68da9 Binary files /dev/null and b/Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/closed.png differ diff --git a/Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/closed_unlit.png b/Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/closed_unlit.png new file mode 100644 index 0000000000..0858c19f05 Binary files /dev/null and b/Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/closed_unlit.png differ diff --git a/Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/closing.png b/Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/closing.png new file mode 100644 index 0000000000..689f02afa2 Binary files /dev/null and b/Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/closing.png differ diff --git a/Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/closing_unlit.png b/Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/closing_unlit.png new file mode 100644 index 0000000000..92b5018fb9 Binary files /dev/null and b/Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/closing_unlit.png differ diff --git a/Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/deny.png b/Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/deny.png new file mode 100644 index 0000000000..8968f68da9 Binary files /dev/null and b/Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/deny.png differ diff --git a/Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/deny_unlit.png b/Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/deny_unlit.png new file mode 100644 index 0000000000..0858c19f05 Binary files /dev/null and b/Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/deny_unlit.png differ diff --git a/Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/door_spark.png b/Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/door_spark.png new file mode 100644 index 0000000000..59ff3aed71 Binary files /dev/null and b/Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/door_spark.png differ diff --git a/Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/locked.png b/Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/locked.png new file mode 100644 index 0000000000..8968f68da9 Binary files /dev/null and b/Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/locked.png differ diff --git a/Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/meta.json b/Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/meta.json new file mode 100644 index 0000000000..8ad6942753 --- /dev/null +++ b/Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/meta.json @@ -0,0 +1,430 @@ +{ + "version": 1, + "size": { + "x": 32, + "y": 32 + }, + "license": "CC-BY-SA 3.0", + "copyright": "Taken from https://github.com/vgstation-coders/vgstation13/ at 38b65a605df7ae2907d6bf0d4aebc5faa1bbc561", + "states": [ + { + "name": "alert_cold", + "directions": 4, + "delays": [ + [ + 0.5, + 0.5 + ], + [ + 0.5, + 0.5 + ], + [ + 0.5, + 0.5 + ], + [ + 0.5, + 0.5 + ] + ] + }, + { + "name": "alert_hot", + "directions": 4, + "delays": [ + [ + 0.5, + 0.5 + ], + [ + 0.5, + 0.5 + ], + [ + 0.5, + 0.5 + ], + [ + 0.5, + 0.5 + ] + ] + }, + { + "name": "bolted", + "directions": 4, + "delays": [ + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ] + ] + }, + { + "name": "closed", + "directions": 4, + "delays": [ + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ] + ] + }, + { + "name": "closed_unlit", + "directions": 4, + "delays": [ + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ] + ] + }, + { + "name": "closing", + "directions": 4, + "delays": [ + [ + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2 + ], + [ + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2 + ], + [ + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2 + ], + [ + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2 + ] + ] + }, + { + "name": "closing_unlit", + "directions": 4, + "delays": [ + [ + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2 + ], + [ + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2 + ], + [ + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2 + ], + [ + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2 + ] + ] + }, + { + "name": "deny", + "directions": 4, + "delays": [ + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ] + ] + }, + { + "name": "deny_unlit", + "directions": 4, + "delays": [ + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ] + ] + }, + { + "name": "locked", + "directions": 4, + "delays": [ + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ] + ] + }, + { + "name": "open", + "directions": 4, + "delays": [ + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ] + ] + }, + { + "name": "opening", + "directions": 4, + "delays": [ + [ + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2 + ], + [ + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2 + ], + [ + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2 + ], + [ + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2 + ] + ] + }, + { + "name": "opening_unlit", + "directions": 4, + "delays": [ + [ + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2 + ], + [ + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2 + ], + [ + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2 + ], + [ + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2 + ] + ] + }, + { + "name": "palert", + "directions": 4, + "delays": [ + [ + 0.5, + 0.5 + ], + [ + 0.5, + 0.5 + ], + [ + 0.5, + 0.5 + ], + [ + 0.5, + 0.5 + ] + ] + }, + { + "name": "panel_closing", + "directions": 1, + "delays": [ + [ + 0.1, + 0.1, + 0.07, + 0.07, + 0.07, + 0.07, + 0.27 + ] + ] + }, + { + "name": "panel_open", + "directions": 1, + "delays": [ + [ + 1.0 + ] + ] + }, + { + "name": "panel_opening", + "directions": 1, + "delays": [ + [ + 0.2, + 0.07, + 0.07, + 0.07, + 0.07, + 0.07, + 0.2 + ] + ] + }, + { + "name": "welded", + "directions": 4, + "delays": [ + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ] + ] + }, + { + "name": "welded_open", + "directions": 4, + "delays": [ + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ] + ] + } + ] +} \ No newline at end of file diff --git a/Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/open.png b/Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/open.png new file mode 100644 index 0000000000..3f0b3ef549 Binary files /dev/null and b/Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/open.png differ diff --git a/Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/opening.png b/Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/opening.png new file mode 100644 index 0000000000..7cf50771cd Binary files /dev/null and b/Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/opening.png differ diff --git a/Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/opening_unlit.png b/Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/opening_unlit.png new file mode 100644 index 0000000000..92b5018fb9 Binary files /dev/null and b/Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/opening_unlit.png differ diff --git a/Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/palert.png b/Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/palert.png new file mode 100644 index 0000000000..3d6343358e Binary files /dev/null and b/Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/palert.png differ diff --git a/Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/panel_closing.png b/Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/panel_closing.png new file mode 100644 index 0000000000..ae69b8aded Binary files /dev/null and b/Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/panel_closing.png differ diff --git a/Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/panel_open.png b/Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/panel_open.png new file mode 100644 index 0000000000..5f3bfeae15 Binary files /dev/null and b/Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/panel_open.png differ diff --git a/Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/panel_opening.png b/Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/panel_opening.png new file mode 100644 index 0000000000..8271b80b11 Binary files /dev/null and b/Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/panel_opening.png differ diff --git a/Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/welded.png b/Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/welded.png new file mode 100644 index 0000000000..e6bd2ff64f Binary files /dev/null and b/Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/welded.png differ diff --git a/Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/welded_open.png b/Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/welded_open.png new file mode 100644 index 0000000000..f0d674692d Binary files /dev/null and b/Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/welded_open.png differ diff --git a/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/bolted.png b/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/bolted.png new file mode 100644 index 0000000000..53bdd1ccf4 Binary files /dev/null and b/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/bolted.png differ diff --git a/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/closed.png b/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/closed.png new file mode 100644 index 0000000000..8c90b693a4 Binary files /dev/null and b/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/closed.png differ diff --git a/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/closed_unlit.png b/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/closed_unlit.png new file mode 100644 index 0000000000..1d33d3f366 Binary files /dev/null and b/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/closed_unlit.png differ diff --git a/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/closing.png b/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/closing.png new file mode 100644 index 0000000000..4347bf8afe Binary files /dev/null and b/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/closing.png differ diff --git a/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/closing_unlit.png b/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/closing_unlit.png new file mode 100644 index 0000000000..d0b97a4029 Binary files /dev/null and b/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/closing_unlit.png differ diff --git a/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/deny.png b/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/deny.png new file mode 100644 index 0000000000..225d45a82a Binary files /dev/null and b/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/deny.png differ diff --git a/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/deny_unlit.png b/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/deny_unlit.png new file mode 100644 index 0000000000..c584771ed1 Binary files /dev/null and b/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/deny_unlit.png differ diff --git a/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/frame1.png b/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/frame1.png new file mode 100644 index 0000000000..458698515f Binary files /dev/null and b/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/frame1.png differ diff --git a/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/frame2.png b/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/frame2.png new file mode 100644 index 0000000000..67f782bd89 Binary files /dev/null and b/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/frame2.png differ diff --git a/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/frame3.png b/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/frame3.png new file mode 100644 index 0000000000..5421154834 Binary files /dev/null and b/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/frame3.png differ diff --git a/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/frame4.png b/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/frame4.png new file mode 100644 index 0000000000..6252d37d1e Binary files /dev/null and b/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/frame4.png differ diff --git a/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/locked.png b/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/locked.png new file mode 100644 index 0000000000..12ccff5cb0 Binary files /dev/null and b/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/locked.png differ diff --git a/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/meta.json b/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/meta.json new file mode 100644 index 0000000000..08653842b9 --- /dev/null +++ b/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/meta.json @@ -0,0 +1,227 @@ +{ + "version": 1, + "size": { + "x": 32, + "y": 32 + }, + "license": "CC-BY-SA 3.0", + "copyright": "Taken from https://github.com/tgstation/tgstation at 04e43d8c1d5097fdb697addd4395fb849dd341bd", + "states": [ + { + "name": "bolted", + "directions": 1, + "delays": [ + [ + 1.0 + ] + ] + }, + { + "name": "closed", + "directions": 1, + "delays": [ + [ + 1.0 + ] + ] + }, + { + "name": "closed_unlit", + "directions": 1, + "delays": [ + [ + 1.0 + ] + ] + }, + { + "name": "closing", + "directions": 1, + "delays": [ + [ + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2 + ] + ] + }, + { + "name": "closing_unlit", + "directions": 1, + "delays": [ + [ + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2 + ] + ] + }, + { + "name": "deny", + "directions": 1, + "delays": [ + [ + 0.1, + 0.1, + 0.1 + ] + ] + }, + { + "name": "deny_unlit", + "directions": 1, + "delays": [ + [ + 0.1, + 0.1, + 0.1 + ] + ] + }, + { + "name": "frame1", + "directions": 1, + "delays": [ + [ + 1.0 + ] + ] + }, + { + "name": "frame2", + "directions": 1, + "delays": [ + [ + 1.0 + ] + ] + }, + { + "name": "frame3", + "directions": 1, + "delays": [ + [ + 1.0 + ] + ] + }, + { + "name": "frame4", + "directions": 1, + "delays": [ + [ + 1.0 + ] + ] + }, + { + "name": "locked", + "directions": 1, + "delays": [ + [ + 1.0 + ] + ] + }, + { + "name": "open", + "directions": 1, + "delays": [ + [ + 1.0 + ] + ] + }, + { + "name": "opening", + "directions": 1, + "delays": [ + [ + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2 + ] + ] + }, + { + "name": "opening_unlit", + "directions": 1, + "delays": [ + [ + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2 + ] + ] + }, + { + "name": "panel_closing", + "directions": 1, + "delays": [ + [ + 0.1, + 0.1, + 0.07, + 0.07, + 0.07, + 0.07, + 0.27 + ] + ] + }, + { + "name": "panel_open", + "directions": 1, + "delays": [ + [ + 1.0 + ] + ] + }, + { + "name": "panel_opening", + "directions": 1, + "delays": [ + [ + 0.2, + 0.07, + 0.07, + 0.07, + 0.07, + 0.07, + 0.2 + ] + ] + }, + { + "name": "welded", + "directions": 1, + "delays": [ + [ + 1.0 + ] + ] + }, + { + "name": "welded_open", + "directions": 1, + "delays": [ + [ + 1.0 + ] + ] + } + ] +} \ No newline at end of file diff --git a/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/open.png b/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/open.png new file mode 100644 index 0000000000..a89b493a8b Binary files /dev/null and b/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/open.png differ diff --git a/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/opening.png b/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/opening.png new file mode 100644 index 0000000000..79a05996ad Binary files /dev/null and b/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/opening.png differ diff --git a/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/opening_unlit.png b/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/opening_unlit.png new file mode 100644 index 0000000000..816c648cc4 Binary files /dev/null and b/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/opening_unlit.png differ diff --git a/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/panel_closing.png b/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/panel_closing.png new file mode 100644 index 0000000000..ae69b8aded Binary files /dev/null and b/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/panel_closing.png differ diff --git a/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/panel_open.png b/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/panel_open.png new file mode 100644 index 0000000000..5f3bfeae15 Binary files /dev/null and b/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/panel_open.png differ diff --git a/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/panel_opening.png b/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/panel_opening.png new file mode 100644 index 0000000000..8271b80b11 Binary files /dev/null and b/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/panel_opening.png differ diff --git a/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/welded.png b/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/welded.png new file mode 100644 index 0000000000..54de288e54 Binary files /dev/null and b/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/welded.png differ diff --git a/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/welded_open.png b/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/welded_open.png new file mode 100644 index 0000000000..d5b1d509b5 Binary files /dev/null and b/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/welded_open.png differ diff --git a/Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/bolted.png b/Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/bolted.png new file mode 100644 index 0000000000..53bdd1ccf4 Binary files /dev/null and b/Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/bolted.png differ diff --git a/Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/closed.png b/Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/closed.png new file mode 100644 index 0000000000..602b83df5b Binary files /dev/null and b/Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/closed.png differ diff --git a/Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/closed_unlit.png b/Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/closed_unlit.png new file mode 100644 index 0000000000..1d33d3f366 Binary files /dev/null and b/Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/closed_unlit.png differ diff --git a/Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/closing.png b/Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/closing.png new file mode 100644 index 0000000000..6718ae08e9 Binary files /dev/null and b/Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/closing.png differ diff --git a/Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/closing_unlit.png b/Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/closing_unlit.png new file mode 100644 index 0000000000..d0b97a4029 Binary files /dev/null and b/Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/closing_unlit.png differ diff --git a/Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/deny.png b/Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/deny.png new file mode 100644 index 0000000000..a2b151c140 Binary files /dev/null and b/Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/deny.png differ diff --git a/Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/deny_unlit.png b/Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/deny_unlit.png new file mode 100644 index 0000000000..c584771ed1 Binary files /dev/null and b/Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/deny_unlit.png differ diff --git a/Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/locked.png b/Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/locked.png new file mode 100644 index 0000000000..5c87415ec1 Binary files /dev/null and b/Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/locked.png differ diff --git a/Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/meta.json b/Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/meta.json new file mode 100644 index 0000000000..c4328c5639 --- /dev/null +++ b/Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/meta.json @@ -0,0 +1,191 @@ +{ + "version": 1, + "size": { + "x": 32, + "y": 32 + }, + "license": "CC-BY-SA 3.0", + "copyright": "Taken from https://github.com/tgstation/tgstation at 04e43d8c1d5097fdb697addd4395fb849dd341bd", + "states": [ + { + "name": "bolted", + "directions": 1, + "delays": [ + [ + 1.0 + ] + ] + }, + { + "name": "closed", + "directions": 1, + "delays": [ + [ + 1.0 + ] + ] + }, + { + "name": "closed_unlit", + "directions": 1, + "delays": [ + [ + 1.0 + ] + ] + }, + { + "name": "closing", + "directions": 1, + "delays": [ + [ + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2 + ] + ] + }, + { + "name": "closing_unlit", + "directions": 1, + "delays": [ + [ + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2 + ] + ] + }, + { + "name": "deny", + "directions": 1, + "delays": [ + [ + 0.1, + 0.1, + 0.1 + ] + ] + }, + { + "name": "deny_unlit", + "directions": 1, + "delays": [ + [ + 0.1, + 0.1, + 0.1 + ] + ] + }, + { + "name": "locked", + "directions": 1, + "delays": [ + [ + 1.0 + ] + ] + }, + { + "name": "open", + "directions": 1, + "delays": [ + [ + 1.0 + ] + ] + }, + { + "name": "opening", + "directions": 1, + "delays": [ + [ + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2 + ] + ] + }, + { + "name": "opening_unlit", + "directions": 1, + "delays": [ + [ + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2 + ] + ] + }, + { + "name": "panel_closing", + "directions": 1, + "delays": [ + [ + 0.1, + 0.1, + 0.07, + 0.07, + 0.07, + 0.07, + 0.27 + ] + ] + }, + { + "name": "panel_open", + "directions": 1, + "delays": [ + [ + 1.0 + ] + ] + }, + { + "name": "panel_opening", + "directions": 1, + "delays": [ + [ + 0.2, + 0.07, + 0.07, + 0.07, + 0.07, + 0.07, + 0.2 + ] + ] + }, + { + "name": "welded", + "directions": 1, + "delays": [ + [ + 1.0 + ] + ] + }, + { + "name": "welded_open", + "directions": 1, + "delays": [ + [ + 1.0 + ] + ] + } + ] +} diff --git a/Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/open.png b/Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/open.png new file mode 100644 index 0000000000..6fcb5b059b Binary files /dev/null and b/Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/open.png differ diff --git a/Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/opening.png b/Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/opening.png new file mode 100644 index 0000000000..113ddab7b7 Binary files /dev/null and b/Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/opening.png differ diff --git a/Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/opening_unlit.png b/Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/opening_unlit.png new file mode 100644 index 0000000000..816c648cc4 Binary files /dev/null and b/Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/opening_unlit.png differ diff --git a/Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/panel_closing.png b/Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/panel_closing.png new file mode 100644 index 0000000000..ae69b8aded Binary files /dev/null and b/Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/panel_closing.png differ diff --git a/Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/panel_open.png b/Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/panel_open.png new file mode 100644 index 0000000000..5f3bfeae15 Binary files /dev/null and b/Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/panel_open.png differ diff --git a/Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/panel_opening.png b/Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/panel_opening.png new file mode 100644 index 0000000000..8271b80b11 Binary files /dev/null and b/Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/panel_opening.png differ diff --git a/Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/welded.png b/Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/welded.png new file mode 100644 index 0000000000..54de288e54 Binary files /dev/null and b/Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/welded.png differ diff --git a/Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/welded_open.png b/Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/welded_open.png new file mode 100644 index 0000000000..d5b1d509b5 Binary files /dev/null and b/Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/welded_open.png differ diff --git a/SpaceStation14.sln.DotSettings b/SpaceStation14.sln.DotSettings index f0a586f719..be0b3eff72 100644 --- a/SpaceStation14.sln.DotSettings +++ b/SpaceStation14.sln.DotSettings @@ -66,6 +66,7 @@ <data><IncludeFilters /><ExcludeFilters><Filter ModuleMask="Lidgren.Network" ModuleVersionMask="*" ClassMask="*" FunctionMask="*" IsEnabled="True" /></ExcludeFilters></data> True True + True True True True