From 5190c049448f31e208f9b22a249adf9f298c0fd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Aguilera=20Puerto?= Date: Wed, 19 Aug 2020 12:23:42 +0200 Subject: [PATCH 01/23] Some work --- .../Components/Doors/AirlockVisualizer.cs | 12 +- .../Atmos/IGridAtmosphereComponent.cs | 6 + Content.Server/Atmos/TileAtmosphere.cs | 19 ++ .../Components/Atmos/AirtightComponent.cs | 2 +- .../Components/Atmos/FirelockComponent.cs | 85 +++++++++ .../Atmos/GridAtmosphereComponent.cs | 95 +++++----- .../Components/Doors/ServerDoorComponent.cs | 8 +- Content.Shared/Maps/TurfHelpers.cs | 29 +++ .../Constructible/Doors/airlock_base.yml | 1 - .../Entities/Constructible/Doors/firelock.yml | 74 ++++++++ .../Structures/Doors/firelock.rsi/closed.png | Bin 0 -> 1120 bytes .../Structures/Doors/firelock.rsi/closing.png | Bin 0 -> 2976 bytes .../Structures/Doors/firelock.rsi/deny.png | Bin 0 -> 2193 bytes .../Structures/Doors/firelock.rsi/frame1.png | Bin 0 -> 1146 bytes .../Structures/Doors/firelock.rsi/frame2.png | Bin 0 -> 1167 bytes .../Structures/Doors/firelock.rsi/frame3.png | Bin 0 -> 1153 bytes .../Structures/Doors/firelock.rsi/frame4.png | Bin 0 -> 1145 bytes .../Structures/Doors/firelock.rsi/locked.png | Bin 0 -> 1497 bytes .../Structures/Doors/firelock.rsi/meta.json | 170 ++++++++++++++++++ .../Structures/Doors/firelock.rsi/open.png | Bin 0 -> 639 bytes .../Structures/Doors/firelock.rsi/opening.png | Bin 0 -> 2983 bytes .../Doors/firelock.rsi/panel_closing.png | Bin 0 -> 343 bytes .../Doors/firelock.rsi/panel_open.png | Bin 0 -> 193 bytes .../Doors/firelock.rsi/panel_opening.png | Bin 0 -> 329 bytes .../Structures/Doors/firelock.rsi/welded.png | Bin 0 -> 318 bytes .../Doors/firelock.rsi/welded_open.png | Bin 0 -> 321 bytes .../Doors/firelock_glass.rsi/closed.png | Bin 0 -> 1262 bytes .../Doors/firelock_glass.rsi/closing.png | Bin 0 -> 2494 bytes .../Doors/firelock_glass.rsi/deny.png | Bin 0 -> 1734 bytes .../Doors/firelock_glass.rsi/locked.png | Bin 0 -> 1270 bytes .../Doors/firelock_glass.rsi/meta.json | 134 ++++++++++++++ .../Doors/firelock_glass.rsi/open.png | Bin 0 -> 563 bytes .../Doors/firelock_glass.rsi/opening.png | Bin 0 -> 2500 bytes .../firelock_glass.rsi/panel_closing.png | Bin 0 -> 343 bytes .../Doors/firelock_glass.rsi/panel_open.png | Bin 0 -> 193 bytes .../firelock_glass.rsi/panel_opening.png | Bin 0 -> 329 bytes .../Doors/firelock_glass.rsi/welded.png | Bin 0 -> 317 bytes .../Doors/firelock_glass.rsi/welded_open.png | Bin 0 -> 321 bytes RobustToolbox | 2 +- SpaceStation14.sln.DotSettings | 1 + 40 files changed, 586 insertions(+), 52 deletions(-) create mode 100644 Content.Server/GameObjects/Components/Atmos/FirelockComponent.cs create mode 100644 Resources/Prototypes/Entities/Constructible/Doors/firelock.yml create mode 100644 Resources/Textures/Constructible/Structures/Doors/firelock.rsi/closed.png create mode 100644 Resources/Textures/Constructible/Structures/Doors/firelock.rsi/closing.png create mode 100644 Resources/Textures/Constructible/Structures/Doors/firelock.rsi/deny.png create mode 100644 Resources/Textures/Constructible/Structures/Doors/firelock.rsi/frame1.png create mode 100644 Resources/Textures/Constructible/Structures/Doors/firelock.rsi/frame2.png create mode 100644 Resources/Textures/Constructible/Structures/Doors/firelock.rsi/frame3.png create mode 100644 Resources/Textures/Constructible/Structures/Doors/firelock.rsi/frame4.png create mode 100644 Resources/Textures/Constructible/Structures/Doors/firelock.rsi/locked.png create mode 100644 Resources/Textures/Constructible/Structures/Doors/firelock.rsi/meta.json create mode 100644 Resources/Textures/Constructible/Structures/Doors/firelock.rsi/open.png create mode 100644 Resources/Textures/Constructible/Structures/Doors/firelock.rsi/opening.png create mode 100644 Resources/Textures/Constructible/Structures/Doors/firelock.rsi/panel_closing.png create mode 100644 Resources/Textures/Constructible/Structures/Doors/firelock.rsi/panel_open.png create mode 100644 Resources/Textures/Constructible/Structures/Doors/firelock.rsi/panel_opening.png create mode 100644 Resources/Textures/Constructible/Structures/Doors/firelock.rsi/welded.png create mode 100644 Resources/Textures/Constructible/Structures/Doors/firelock.rsi/welded_open.png create mode 100644 Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/closed.png create mode 100644 Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/closing.png create mode 100644 Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/deny.png create mode 100644 Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/locked.png create mode 100644 Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/meta.json create mode 100644 Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/open.png create mode 100644 Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/opening.png create mode 100644 Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/panel_closing.png create mode 100644 Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/panel_open.png create mode 100644 Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/panel_opening.png create mode 100644 Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/welded.png create mode 100644 Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/welded_open.png diff --git a/Content.Client/GameObjects/Components/Doors/AirlockVisualizer.cs b/Content.Client/GameObjects/Components/Doors/AirlockVisualizer.cs index 622e9d0c23..8501122b59 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.Server/Atmos/IGridAtmosphereComponent.cs b/Content.Server/Atmos/IGridAtmosphereComponent.cs index 5518881767..fd5648c091 100644 --- a/Content.Server/Atmos/IGridAtmosphereComponent.cs +++ b/Content.Server/Atmos/IGridAtmosphereComponent.cs @@ -45,6 +45,12 @@ namespace Content.Server.Atmos /// void FixVacuum(MapIndices indices); + /// + /// Revalidates indices immediately. + /// + /// + void Revalidate(MapIndices indices); + /// /// Adds an active tile so it becomes processed every update until it becomes inactive. /// Also makes the tile excited. diff --git a/Content.Server/Atmos/TileAtmosphere.cs b/Content.Server/Atmos/TileAtmosphere.cs index b1ad2df3cf..10ff57c948 100644 --- a/Content.Server/Atmos/TileAtmosphere.cs +++ b/Content.Server/Atmos/TileAtmosphere.cs @@ -1051,6 +1051,25 @@ namespace Content.Server.Atmos private void ConsiderFirelocks(TileAtmosphere other) { // TODO ATMOS firelocks! + var reconsiderAdjacent = false; + + foreach (var entity in GridIndices.GetEntitiesInTile(GridIndex)) + { + if (!entity.TryGetComponent(out FirelockComponent firelock)) continue; + reconsiderAdjacent |= firelock.EmergencyPressureStop(); + } + + foreach (var entity in other.GridIndices.GetEntitiesInTile(other.GridIndex)) + { + if (!entity.TryGetComponent(out FirelockComponent firelock)) continue; + reconsiderAdjacent |= firelock.EmergencyPressureStop(); + } + + if (reconsiderAdjacent) + { + UpdateAdjacent(); + other.UpdateAdjacent(); + } } private void React() diff --git a/Content.Server/GameObjects/Components/Atmos/AirtightComponent.cs b/Content.Server/GameObjects/Components/Atmos/AirtightComponent.cs index 07c6ed66e9..0d71d0717d 100644 --- a/Content.Server/GameObjects/Components/Atmos/AirtightComponent.cs +++ b/Content.Server/GameObjects/Components/Atmos/AirtightComponent.cs @@ -28,7 +28,7 @@ namespace Content.Server.GameObjects.Components.Atmos set { _airBlocked = value; - EntitySystem.Get().GetGridAtmosphere(Owner.Transform.GridID)?.Invalidate(_snapGrid.Position); + EntitySystem.Get().GetGridAtmosphere(Owner.Transform.GridID)?.Revalidate(_snapGrid.Position); } } diff --git a/Content.Server/GameObjects/Components/Atmos/FirelockComponent.cs b/Content.Server/GameObjects/Components/Atmos/FirelockComponent.cs new file mode 100644 index 0000000000..02d3ac22a5 --- /dev/null +++ b/Content.Server/GameObjects/Components/Atmos/FirelockComponent.cs @@ -0,0 +1,85 @@ +using System.Threading.Tasks; +using Content.Server.GameObjects.Components.Doors; +using Content.Server.GameObjects.Components.Interactable; +using Content.Shared.GameObjects.Components.Doors; +using Content.Shared.GameObjects.Components.Interactable; +using Content.Shared.Interfaces.GameObjects.Components; +using Robust.Shared.GameObjects; +using Robust.Shared.GameObjects.Components; +using Robust.Shared.Interfaces.GameObjects; + +namespace Content.Server.GameObjects.Components.Atmos +{ + [RegisterComponent] + public class FirelockComponent : ServerDoorComponent, IInteractUsing, IActivate, ICollideBehavior + { + public override string Name => "Firelock"; + + public override void Initialize() + { + base.Initialize(); + } + + public void CollideWith(IEntity collidedWith) + { + // We do nothing. + } + + public void Activate(ActivateEventArgs eventArgs) + { + // We do nothing. + } + + protected override void Startup() + { + base.Startup(); + + var airtightComponent = Owner.EnsureComponent(); + var collidableComponent = Owner.GetComponent(); + + Safety = false; + airtightComponent.AirBlocked = false; + collidableComponent.Hard = 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 void Deny() + { + } + + public override bool CanClose(IEntity user) => true; + public override bool CanOpen(IEntity user) => true; + + public async Task InteractUsing(InteractUsingEventArgs eventArgs) + { + if (!eventArgs.Using.TryGetComponent(out var tool)) + return false; + + if (!await tool.UseTool(eventArgs.User, Owner, 3f, ToolQuality.Prying)) return false; + + if (State == DoorState.Closed) + Open(); + else if (State == DoorState.Open) + Close(); + + return true; + } + } +} diff --git a/Content.Server/GameObjects/Components/Atmos/GridAtmosphereComponent.cs b/Content.Server/GameObjects/Components/Atmos/GridAtmosphereComponent.cs index 05ba999b0b..9948bdba90 100644 --- a/Content.Server/GameObjects/Components/Atmos/GridAtmosphereComponent.cs +++ b/Content.Server/GameObjects/Components/Atmos/GridAtmosphereComponent.cs @@ -147,55 +147,62 @@ namespace Content.Server.GameObjects.Components.Atmos { foreach (var indices in _invalidatedCoords.ToArray()) { - var tile = GetTile(indices); - AddActiveTile(tile); - - if (tile == null) - { - tile = new TileAtmosphere(this, _grid.Index, indices, new GasMixture(GetVolumeForCells(1)){Temperature = Atmospherics.T20C}); - _tiles[indices] = tile; - } - - if (IsSpace(indices)) - { - tile.Air = new GasMixture(GetVolumeForCells(1)); - tile.Air.MarkImmutable(); - _tiles[indices] = tile; - - } else if (IsAirBlocked(indices)) - { - tile.Air = null; - } - else - { - var obs = GetObstructingComponent(indices); - - if (obs != null) - { - if (tile.Air == null && obs.FixVacuum) - { - FixVacuum(tile.GridIndices); - } - } - - tile.Air ??= new GasMixture(GetVolumeForCells(1)){Temperature = Atmospherics.T20C}; - } - - tile.UpdateAdjacent(); - tile.UpdateVisuals(); - - foreach (var direction in Cardinal) - { - var otherIndices = indices.Offset(direction); - var otherTile = GetTile(otherIndices); - AddActiveTile(otherTile); - otherTile?.UpdateAdjacent(direction.GetOpposite()); - } + Revalidate(indices); } _invalidatedCoords.Clear(); } + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Revalidate(MapIndices indices) + { + var tile = GetTile(indices); + AddActiveTile(tile); + + if (tile == null) + { + tile = new TileAtmosphere(this, _grid.Index, indices, new GasMixture(GetVolumeForCells(1)){Temperature = Atmospherics.T20C}); + _tiles[indices] = tile; + } + + if (IsSpace(indices)) + { + tile.Air = new GasMixture(GetVolumeForCells(1)); + tile.Air.MarkImmutable(); + _tiles[indices] = tile; + + } else if (IsAirBlocked(indices)) + { + tile.Air = null; + } + else + { + var obs = GetObstructingComponent(indices); + + if (obs != null) + { + if (tile.Air == null && obs.FixVacuum) + { + FixVacuum(tile.GridIndices); + } + } + + tile.Air ??= new GasMixture(GetVolumeForCells(1)){Temperature = Atmospherics.T20C}; + } + + tile.UpdateAdjacent(); + tile.UpdateVisuals(); + + foreach (var direction in Cardinal) + { + var otherIndices = indices.Offset(direction); + var otherTile = GetTile(otherIndices); + AddActiveTile(otherTile); + otherTile?.UpdateAdjacent(direction.GetOpposite()); + } + } + /// public void FixVacuum(MapIndices indices) { diff --git a/Content.Server/GameObjects/Components/Doors/ServerDoorComponent.cs b/Content.Server/GameObjects/Components/Doors/ServerDoorComponent.cs index ba2bc39377..381f276bd0 100644 --- a/Content.Server/GameObjects/Components/Doors/ServerDoorComponent.cs +++ b/Content.Server/GameObjects/Components/Doors/ServerDoorComponent.cs @@ -61,6 +61,8 @@ namespace Content.Server.GameObjects.Components.Doors [ViewVariables] private bool _occludes; + public bool Occludes => _occludes; + public override void ExposeData(ObjectSerializer serializer) { base.ExposeData(serializer); @@ -133,7 +135,7 @@ namespace Content.Server.GameObjects.Components.Doors } } - private void SetAppearance(DoorVisualState state) + protected void SetAppearance(DoorVisualState state) { if (_appearance != null || Owner.TryGetComponent(out _appearance)) _appearance.SetData(DoorVisuals.VisualState, state); @@ -144,7 +146,7 @@ namespace Content.Server.GameObjects.Components.Doors return true; } - public bool CanOpen(IEntity user) + public virtual bool CanOpen(IEntity user) { if (!CanOpen()) return false; if (!Owner.TryGetComponent(out AccessReader accessReader)) @@ -205,7 +207,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)) diff --git a/Content.Shared/Maps/TurfHelpers.cs b/Content.Shared/Maps/TurfHelpers.cs index b02472cfa5..1b1a8695f8 100644 --- a/Content.Shared/Maps/TurfHelpers.cs +++ b/Content.Shared/Maps/TurfHelpers.cs @@ -1,5 +1,7 @@ #nullable enable using System.Collections.Generic; +using System.Linq; +using System.Runtime.CompilerServices; using Content.Shared.Physics; using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Interfaces.Map; @@ -62,6 +64,7 @@ namespace Content.Shared.Maps /// /// Helper that returns all entities in a turf. /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static IEnumerable GetEntitiesInTile(this TileRef turf, bool approximate = false) { var entityManager = IoCManager.Resolve(); @@ -69,6 +72,32 @@ namespace Content.Shared.Maps return entityManager.GetEntitiesIntersecting(turf.MapIndex, GetWorldTileBox(turf), approximate); } + /// + /// Helper that returns all entities in a turf. + /// + public static IEnumerable GetEntitiesInTile(this GridCoordinates coordinates, bool approximate = false) + { + var turf = coordinates.GetTileRef(); + + if (turf == null) + return Enumerable.Empty(); + + return GetEntitiesInTile(turf.Value); + } + + /// + /// Helper that returns all entities in a turf. + /// + public static IEnumerable GetEntitiesInTile(this MapIndices indices, GridId gridId, bool approximate = false) + { + var turf = indices.GetTileRef(gridId); + + if (turf == null) + return Enumerable.Empty(); + + return GetEntitiesInTile(turf.Value); + } + /// /// 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 ad88ad239f..8383ee0575 100644 --- a/Resources/Prototypes/Entities/Constructible/Doors/airlock_base.yml +++ b/Resources/Prototypes/Entities/Constructible/Doors/airlock_base.yml @@ -54,7 +54,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..ecfe8b2578 --- /dev/null +++ b/Resources/Prototypes/Entities/Constructible/Doors/firelock.yml @@ -0,0 +1,74 @@ +- 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: 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 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 0000000000000000000000000000000000000000..8c90b693a4c9a2b9c9e43b8ff4cb9a299a29d8f4 GIT binary patch literal 1120 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 literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..458698515f18fe40fc9819a3797a907ef8937e74 GIT binary patch literal 1146 zcmV-=1cm#FP)%Fv5!xs4S;`MYbgCb-U2aSR;+b4{(1Nbah_;x#ymH zXRb6jI4A%{Mn*`d)65R1I7>W84HJvSNG6j2$j#)TPKo75eP=>`VJgeSz+XH`*Ey5P zB+~Tsv}h)O)9RZ98@Z{Bvv+VSq9))F2{wbEU_VpkG>ru7K=H`sl?pmBv(}x37Ct=nNii21gzw9@i=Z-X1v$O(j$lsZ7@5W;z3G_ zZG{d=LZa0`(tbT|VInvwqI>novM%V0N^Om;2#N<5_N9`gpS}cEZ~%llB?4iyqACt& zIHRh}Jbv6Z$W>K^Qi&g@rcCk~Rb@t1E&Ha>Ck_*^LWg8skwPZZBKs~L2bYWK#YK~R zE*>}5za83ZngZ$YMx!mIZbVfG3YiSvXw+y%yCfU{JNtr{+pWrcDuu}BfrfQ#BrlaH zq|>JV0NzLhz^rS+&VGFfWTnfV(xOyq7^W^QuQdaPB+*&uI>)eeSc>F16X zrIll&%xYW~!j@2nX&c^Lj^gwA7-#oL$D`oXn)e%z$0YxtSTx4hzmBoDw?{bKP=Q1u zLFM7YBME+4U$@o2)8B85CoW$G;K}^F$tICVFt5pE03ifj;V>JTK_uw34DM4pU>$zg z*|FTCS3)6S_#T*bk)V^J)}&qGFhVpmAwYLe4;#RH%d66rP{=ri_LUl)`NQL)9l4=f zMF8{zD|hdrkMC>x>*vmi?w%gQ$Ff^YBs=ZsY?3$u+Ma~}7mN!0`{Kp1ou0QEvAlp*V5d+SbwX^0N$*`(^d0P>?oC}Y0f&z zLKr9AQE+H`zNSqA%&X(g*5f#!{&6rnp*dr%OTs*0MPql?wL@ z1{$#P`K%@i`KHaQ<2%BCd(*_0^|*uaW(sJY=!N8!RNnr1CY<>`QrTo z0H6F6F&rA@AAj%F0@m^AyPGZYX8T*0@`O7jzWV(&VzC&~;NYOpFQjeyeAB zezMy{uFHGhQcNVrk>9$MC!*B&@{iYz8?t0|JwM$_+e6>L&DZn)0In#^lz|q5SO5S3 M07*qoM6N<$g6e`QrT_o{ literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..67f782bd89cfeac1df4d694cbf126bfbd5c2022e GIT binary patch literal 1167 zcmV;A1aSL_P)N{L%~pl!L{qAP`nCQiK$5qNf%C`u~%MX5gGzrh9;X7x@s4t zWYI;tNZc;kfNPpUaGNo7)dpfyI}0NWDWR3+_!-%fEK9mw%)>L%X#Al0VbIli{b$ZS z_s+dicXzh{=joaB><1U^}2u&t5V2N3UBWxRKh zdy9H(C)7z264eHh{_FP%8^LiA+tDJ+hM+wr)iib@$nQDW7YdGk#uPZg1JK+c5enNC zC2{bEW2(y7!-qA4Tvk;m6!>vu#3mn8RmN1+v2Swi;vfMh)Je`2$)!?NvhNZJ@Ol}Y znX$rM9`MOBQ`fH9$bGWRAR=>y!}3$iD)tNdXq-NVT7#v?VC0bfrO&`Z@v5{=mqH{^Yiqe{JOSJbkox=k#m2@4!C;WV?QLEYf>6a8ewoh`^7~N&^-ywu$!JqOPoJ+7^7~Cc zYn)ZRLz3HdNG;rri zl3VAsuc{0XNJ~6gvTwznLV>dGY+zpqbEi8D9(~Q1^_Kwq>;%$U91m!RgYk2^qked( zBtI_7UaxD6ng^1y%ZKEsZ+{$^3H%!>x!Jukmk4!A+jsFb>zz&sx&~Je zGf|e)8D4J>I+&j<2?bbAXYdq@+|A|adR!*lAlVZDxIL|KBdCd%)0q>IxuGn}D2f7P zO__N$`)J@Po4bO~e{BIEo6YjYhdBT~`6+5TSmhsoAJ7A8`1Im>mAuma=7lWb28pl! zc!PL6j?~@VEsV>lk;Lt3h1K7+EW3tVY~+T#?Tlh0Ig0$|g)C8}%$I+@Y2J_}r|bF2 hX4)Ob0BbH;_NognLPMd;(0G$VSM8#d zEV^hHiQ7dRa7|MPZZn3g+AJI@WnqM&B_*<)`W4xdtk>;AGh>Z38b84OVbIli{pX&0 z?wz^Pz`%e27#l;A9JFEKDl=$e|K_Za|ay|K2 zx0n4K6iX#$mX`r=02B($kB@UrRgr-CXq0JHZAidMJ|B(Zl4Zuay(~X~$lwMuLkaFB zwAfZ?kt8G<4J7T??Gh$}lOnuVjV$Yep0L!^*oq*3U}0Y*a{WBr?zo;R%P0X0%Jf0kE?#c(vWA%q9|uY!;|l$6E42 zfm||a`VZgM(7?n=4_wUN2+p9_e@#TD9i=#_cxAKgj2e@%67G?CtFl4AxX2 z7K>53fB#5=U)I-c_3!rf8so=rKZSqb;*0Ypn^-Ky!omWeB_M>LBN${uGYGY}S_bzj zEwBzh?Cen_Ma{)*rBO_vK zYYU&x$Jp*JuL*&_ZV$i8=kdGUD4td*+fOpo-paG*oA}*s!>=~Zb4g;ky`4-ZLq|tP zwE}aOQ{0(7Jh!{rTTz@&)> zVn?AsMRV3s6v8;^j)Ftm^A&9pU|t-G>A=oCF69BlqsBqI)6|JQ+ry{dMMV3(%1;`pQ<7)Qd=rgwW1)u-g z2|zZR<%{=o0DSUO$Z)8YfBd~i3s}Xc?`<~7>+Nq{$r5an`0DpJh(sbt0|Ns>zntnx z++I}JcwEi0f4tK~uFJbGDkhTS$ZuWA5>hIB`Nx~a4Oz0fo}X@|?V)er`s?|B*+kDu ThG~D%00000NkvXXu0mjfi*YNi literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..6252d37d1ed3122d417d384657798753f4153412 GIT binary patch literal 1145 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�k^?V79mjAc&8Ng-_YOcq#xzxU14{OGPL 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 literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..ae69b8aded52705141caf90baca11d9b6f490f76 GIT binary patch literal 343 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD1|%QND7Ro>V3hN8aSW-L^Y*r57L%g@>xC}A z3Hv&&KdLo4D5MK2ok?X;eBkR;cJGMmk#kCcY(AS#`EY)g>)<%_-zRbR%08euK+tw! zTF~ZA>X8R)3>#8FX2Zb$wYp2w-knVU_Cqs&h1}$hj<hZcpxtMC#10s!RRy;u-(lWFf(gQU1Tr{k)uI+k5XOavZyvUt*}mq#1G7gO%sK{!+EaHX%dbA278C8|dw;V0!qbOyy;rXP+`n3X z&wknWw}N;Usr!CE3^ecWXO(BOFF*bJ^5KlDxiROS*Ib+TCn7f2-8w6;Bi`Zv9e$vh b2{Cqz({Gn8Fx05L1+v1^)z4*}Q$iB}3+IzJ literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..5f3bfeae15880d37195a14cbfdcb01447290f46c GIT binary patch literal 193 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJ4o?@ykcv6U2@U=;9laSW-L^Y)gb*WmyGwg;Iy z9(k8yU;4&y&T|dmshHNJP$69S+;`Uov)CyuS(oNkF8=o0tlx&||A#oE)tx|d7#JEh z&DxcB{M)f_|DE5hjPiOGcKl%XSG{SgD}R3}x>@%6ZkqAzT^(!g_=V-UxX53-Qu=$( z4~ab=zU`W8T56k_c=~G1hoe(Z$ez}pDJ^JdU$?vIPlRo7S2F4x(g z@=iSVzV*9$)#}8scPpj5R_@E6@~-jb&YQouEv_@4F#Ev_b_t01p&0r3M{JqfyZiuG znP-oC)t;?TQj(Lm+x*%hI`l}Q-8`4)cbYfP?DKoZG-)SX7nJdDn(ZH-I+j^)XXb!J NJYD@<);T3K0RT6Fi?RR! literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..54de288e54d54f4cc7dc8c62a0127c981a821dcd GIT binary patch literal 318 zcmV-E0m1%>P)YU6bA4wxkE7`q?fKHFCeAO%_0h7ClOkT-OW?vja(IVP>7(o2*u=9=~8g8rQOsP zbds1JCyP}wIH=3{ZRgL&IRImfF~zM!inM`#yv)k!4f3u7jeK z=x7bIP=MAtH@mS}qsxo)x%ph-m&;U?62@DKCCfqz;5a&)?F8Ff)Ex{_TU$k}V<^u@ zoLs}JDvU=XOkPt6VPa|u97WMAx9%%iT(I!)`~rP@lmEbHs!}0o+sF(9UKKh? zu;MIZ@8mQ$7wiVq?P%Dg5{L+n>*B80!&SSToB1_LDGI}o{`@dwj4}2T??$6i`jodk Q8UO$Q07*qoM6N<$fn+a literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..d5b1d509b5c48ad1be5dc7c0d597f8736be036e1 GIT binary patch literal 321 zcmV-H0lxl;P)8`+h9Y{Agq2cxniVE&?*s&qA|hG3-AgxUV+9@tVfN`sG)<2i6j_JOrgig zff5*WVDS9L=l#gLzVP2^@nG-ZP@bL~_vJr!YBkw>e8Mnvy4{FeZk9|o%Z(7|ril<@ z;Oy#}Coj&=dg^`68|AXpIw2F5MF?~rE=hgr09fuK_s>ndnjQiHg7>d z>np@CbRykgtX}8CiXa2+qco36?Vwd!Aj@sbnCdX21;=LUl%kSxr7ud?a%agu; zzfZsS-uLvlSS&^WU}$Ivxm*s(!7aQ@$!rZmQ50meSpY!D2`-5o9^95+3iydh9jE$# z!CJ14nayUw&CJXYC-_)jCn^@l1dBZJOzQOW6OkvlSJ=aeNgc`nhxe}!Kv5KgoZ!Pe z?+KjdMDNUkw>m{Ct|Etd9uIEIPzDM}4sIc{bua~f6*nZ!i5S)OLw%_oBg;sUiZ4U` zdjSAc0dkaeYy@5r1dQrBPTkUO7RweQT|DR!fJ+zY;(;l3IxWjc@%}{sKmY(FkwaK= z8)@+Besvv{XRkU(FI{!Ny8im|cQ;3M9cfPVTtAjfngtw2jAG%vaHQ{Z=ji7j>EiuN zj2xC!1^2!UGKPzb%k!Vi&n~7&1u0TNT9$#?iD_RhDRF`~a?w7_ zHvI5G6rG)&7{i~ogJIRiFD@?6r=3L{LQuI966xnhX#^&@D+Q09Y#)F$aL6Y?@B~ z)o-mk;@ht^S)y~y83xvhMf8dyx+MvOkY)h@5b5njfl4%I7);__>Ul))J^+3;O?#ou z!SM8HU^T>b7K{i2)`~^n;1NN9o2RcF_m|I&Q2iwP{kp{0;VdZknI{@%KJ#~-+n{x_i zu`N4c_Ne^BF!23_3oiOHiG=I9BNVc~QfO;qd;s|N0Hy$=1S~yy!diEBd;|ZDyn{A( z0eZf^?c{?a*ECIBK2!g#`skY;JAl@I@Ffp{YRezL^~|Mr`j^XP-2dq>NFuceono3M z3P03oJC=xe>ibR#49H>i<#L(93Mh(##m(ckLf3U{T(j`_Q2>1>*+b{@nWmlw`SJSm zmil9f2n0cZesH;wL=KCa$Dt?+xL7Pk8kf`gH-E*stL{DfU&^&}96q~0Y~PT%|NDCW YH=e40LNT=Zga7~l07*qoM6N<$g4A|Z{Qv*} literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..6718ae08e979bc8c73e2ec6081e70f6088157caa GIT binary patch literal 2494 zcmV;v2|@OWP)e6WV7nj25kHs7hFqO^X;_cf4YugJCKB#&1{r=IsZ4fj+GW#edA`zS%zcBpv z@bU3eS^)qsCWP=*Cd2h5uP6#eibVjx8Cf=tl~PrxhraUUe>dC;04S6MoRMWbmC2z0 zqx6U6jq1^9_&t)ouUe`cJ~@72c&zG#Q(6IIio)f9Q(6H92*%{A zrOIKl?Z!+8y!c~62mmmGVvTz&IoNyQQ^YzRUdrZ6hsi5KZA&}Fou*go50RU%=!-?LEy0fQZyOO*>(vSi}g5uE!*+41j6!BU0-$fWdnB zbOahsIDW)*3@3AnKo(!*IiMdFUvFWyPi3=60iXsv2-GI`;#clz=!HjXQ9>UhrK*_9 zX7Nxc0U#O@ z5Q)|`-Yr{6(LiFJ=JT9KJhr*^JrN3NZv3DkknrzW3Uad`&Ou%lR0M8I2i!{wDgud# z0FWzaP;gNQ)FZvpf(a?s}h+M1bfT#LN7zTtq}FN6CjfW>N7ehUD+`RpprrWOMmz}eIy-h6h|_}t8V5dfr&fa!k( zdn+zw1k?NfC;n(W&b(`TePx9^j0nF4&>s%`xSyNf5GyH~>HT)$J54UJ(Rf^o$}(7g zJbkVF`_BUyHX4s>5lM2~UeVa|9FZja?(xTM8(Redxgz^RMSMcjLCrkyp&Eu05F+MVkn)q9f#FEnM^uzjjJFvx7ndL#t1*C6yU@s z7L{cPpeCql#KYg&RXdd11Ovb>(K*o=TQaM`{TlfB7ym^xWL~T^-|rOQ#kVq86a4L6 zMzEF3rjJgJq50eP91v6raI#jRHo-&bw83ZDOV#Zk96f4kC*%0wnP(h1Er~<|KR=J|?rx0F0z-WZ7){4Dx04yk!A{$}`nL9cgYj9rIF|4$Y5liazf!-&?-BK=Qu%ZnpXWqL1g*#sdITCts=@{@d{* zgI5#^1azH$NYc3Y(U5?-Oa43_J8(3EYfBYOt@Jq8 z2lO~x{kat+u=bCI*$3j$=L2S;YdysoMxUzVi6eRVWb*skciZ~W=&oVz!AP?Wq2=uHE@Vi9E%luA(^_pK1=;(l;N_1Fu zFH)eJ`4NG{Z1n*_mFRfY2l$-=z4(4dAmNJuTOS`}ksOO3WD2zMgN#5U1rdFGP$fEE z`h34rpcmio2qb)=x3^cz<#M_{{>~koU0(K8Aai2R9&P4<2desbec93ce-{eqkHs(% ziJ1D48ynsfXuWZwQ=l8aN0KlRiQuQdI`?5jYMr+Jy96F1*Z=e)`2A}?8BD1v{$47X z_(lXoPiw$QuH$dnqNg>iziw}%`F^HA9=@LuNb^OYrjPH%9#=r4OxMRhVtl6gL8L%8 zeh?QSG~bATp!M6KNY}?dVr%2&Z&erM#Xl&^*sLm} zkI~Pn%Aom%1GbAkpXa&qR-Q>OdGLw(smh>Ph68lX`sQxc>$T3QC-5(<+u8`D^tlo4|Ww4w<%&N+u`No!d^zmCw0X+JAKUW|R-%nwdYkfcv(m)=4zMr}v9==tW zHT2nMj>mTsW(}p&u6$;FKoII+FMYnBE0BlpWJL2r+xyk1d;aoe6O)H80#$wd_kdqt zukGNsG?0EE!s7ca4fNtWjeo1cEGysf!DvwG;CihQ(m)>DC5k96EI_M9uJIk{$uE~t zT3j@J1^}t8O&@D@8<#rTs*m?O1z63kKERI^=*9m=Rq@AHU$r@pjzaQ&mna$xdB+Z0 zq&gL60F(o)`uL#K!A^X#0_DdZGd|zl*s!m_ufH~Z2Fxo^N+h@(PnKAhr_0Ataj`EUi?fZgDdZq@XzZlXn)%LlgB$R*4pVw z{`0wSUEB8##30KuGF5RG%{Pg2hYx*;>?iF8up<&NQh8fyyt#>z;@yP4}vE=>PNDL0ssI207*qo IM6N<$f|E$s#Q*>R literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..a2b151c14088c54950b3655357a7f4f7f76654f8 GIT binary patch literal 1734 zcmV;%208hOP)fdS_R!VAN@uM|WE&LCQlrJBxzW(>>>GafHh)KVc$LqAEEoT2sej%DjticbeXYvcsq&sWrBv2GQn~mm8h}J911tD)$AWtTD}Pdp z;5z_dE=`b}<1?HJL7!n@Ow%ygy*E%TSGTPc?pe2SX0m&4U`*4{XBf22HFZ@qJ(nh2 zS`^;_5G5~xy z(TLjGTD0OBEs)GCww)Ll>J6DYu>$pzG}4eLJegT+WAl%m*D*go4|jgnMe?Z!Tn|j+ z)ZhkM$fZ<`vYqHN4D`Xka$=Vo7Vc82Mgh>-yB?UvTSKpMb=%w9v2gKXMfmOQ?YMH~ z3V{3o5JIrpmCGDSB+vtZahU+y_}9NJzax9+wWV2N+vrIqF_K82-s!|@SB_Z_Ap~pO zZp>DQzsBvReCh#pYx#zHl1c9TDU)tdtvBF58wP#Q^dMTBJ`NziS;%G)?&!dwNCXmqu-}ia zNTjGiD|^`Q=g!S607yK3Trob&qKok}ljpcq6%vZ~%7snkD>X~AUa$0nzQd}Gv34#n!&o672x>`i~V&r%bk|$*uJaH0Qd_Y9v((3b6!sV@bEBA zI{@J1o*2#?zQ+}+l9m8nkqEkO+^}p601ibWKsJkSIy*UgS0sY2NTg^6&K$mnlY3(H z{N$b(&h}@BHI^!KTutb;LV$yJ?!@*?Dylv!a`9U zB`$GkQG6N5{W4Ukyl|K4*Y4gt7-~Up9%4|zNe)~z0-CRDEO5yfTf5PqL zmoZU%%bUY649xzJbDPZ_9!q<}E|r6<)Sj~11`6ambX}+SA^^nWag1Ha;MWHZH0FjH2;+@ z9FcJ5b~E>dRwQ5g|MR$D-M@cd${zs$lau8pPGXXQ*djhaq-3j$FWdL|Yq>$#*D;M_ zgSkN{%)BVsB0fN*Y#Sd?DcL4IK$L6|A0SdMO?*JP^isqJlvB2d4-hF^#0Q9!ZQ=t& z$rkYeB4wNS08z32`;j~_2`-*87qQMyK!=`5?OR&iwjl#J1{gKQHY zAWF804-h3=#s^eV!s7#k%j@-$U@%C0J|Fq4M0qI=*Bo57L1;V$r=hYfwIZH&a4f&4Kb~PL`z}xK z`}2N3eeZqWlbGJ#UK0QY1_qGN=aJ~o;YCV1*AGz?kT$ z@A(Cpd<`?3&4QVnoHXs=Bi$XS=nNIiv!?5!c0VuSSrhlR$~Zc%KlTbVNE?kRt$xF4D;Y6H+`S2uQNtBmlq%0AZd% zDC{(n;Kr`8jLP;Q`{<@Kc8%pX7ME@eD+*E!?|Oc8!E6v{MbzTf2cby!7xvN1Khnv1 znJ8(AK(VC54ZPV{-yWcOrT73~r(#0gp$$B1Vph|zA_#aeH5LyBf}^d1NA@4wcrY~< zUl9b%YMQm?%bkAfd8a~bK~LF7oq-g?TVs*Vg;RdDY+KV`T$zc_PwW@8d?4GXJG6Q~x}0UWR#L#%fvtD5dtbBJXz z;u7a)80--JpoVpbCQvHTL8`9f{OT%zy=Gw;NXKG0BgC=)#%}Fe) z6+g9QF3fRY;Oy1)rutHQBMWu_yR--BTc5-|0exOAd`xwGq(lb>k-BxD(hJ9k_c1AsHK3>XH!86T(g30X!$mK_1Y7PKw zSFO|3ZT2l7#jR0$?SX*xmRwsKN`YvJ>{MTusw(<#g?{>XUC9&70JJ^c4$^Xv?3zyY0~1{Y#}1?*H@` z!aQ*Z?V@QKwtlFk?QksOs_#C=Q6R1AOSYEl6Gaj8t4Az_q9|CouH&~yK6D?WFP$r= z8+sDt$AxE2^@n2-a2y9^@8>4WGnijJ0#Ovf^!E0e^`Fz3w|>RBYtEYeFXj3<26OiZ gtv_Vu|NcGy8*%D^Kx|ccGXMYp07*qoM6N<$g8N5G00000 literal 0 HcmV?d00001 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..817344977f --- /dev/null +++ b/Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/meta.json @@ -0,0 +1,134 @@ +{ + "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": "closed", + "directions": 1, + "delays": [ + [ + 1.0 + ] + ] + }, + { + "name": "closing", + "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": "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": "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_glass.rsi/open.png b/Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/open.png new file mode 100644 index 0000000000000000000000000000000000000000..6fcb5b059bd5e888fa554cc84870238315524a50 GIT binary patch literal 563 zcmV-30?hr1P)KR76ox-LS?YwUSEULy3(Ls^$;?{REERi~Fn0hXrb>vR3rkm|ssjrH>e3Ox79eZs zz~E4+^3sKbs1Xh!ZKw1YjExgHxC-Q&fAgL0eZTMCJ-ss=$58;~av9I_sFoT`Q+tgP zQc7Ic1t2>LKYVwC)k0xxfcKpa``vCPX>NUCVUV`AdcVP5BVf9&OEwNaso!M3`!%x; zgK`c=9SRkqzM@XK-=_NSdy?wpt2y!kiTJud@3AIvWlYmyKxB zfXit>Rl*OO03v5FFQ$PUuZyDkW8gY98wUI{MbFm@_RnHRVE0Y!IS?v3g8JKuul__D zx`xj_FO$#bS>cBk_`{cye!q_pu^p&XDq7&9EE7N}#iG!c1dBqT)JPpDEG=m>5NFLs z9heCNozqio&^RkH@ZHx}3gfKEK&@8OW+2Wo0k+m!>~4744D4=rY^}9`-<5E#ZSdh( zZz-N@2Mv%3L38k6RV#l68n0o@HrsHiJ$w^THk)V=;seLB2Eh{XF zX>tL0-Rli~XQhF=3uIo2hr%vMfaIf}MjqNGUNK$5HY3 z;oxKOuYtC0dmt<;an3(KPhFe2*B*Ky8`u3j{{>z0!&oF9kOTk#002ovPDHLkV1m>m B{`>#{ literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..113ddab7b76361111ebf7c2cb35999c487ced60d GIT binary patch literal 2500 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 b2{Cqz({Gn8Fx05L1+v1^)z4*}Q$iB}3+IzJ literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..5f3bfeae15880d37195a14cbfdcb01447290f46c GIT binary patch literal 193 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJ4o?@ykcv6U2@U=;9laSW-L^Y)gb*WmyGwg;Iy z9(k8yU;4&y&T|dmshHNJP$69S+;`Uov)CyuS(oNkF8=o0tlx&||A#oE)tx|d7#JEh z&DxcB{M)f_|DE5hjPiOGcKl%XSG{SgD}R3}x>@%6ZkqAzT^(!g_=V-UxX53-Qu=$( z4~ab=zU`W8T56k_c=~G1hoe(Z$ez}pDJ^JdU$?vIPlRo7S2F4x(g z@=iSVzV*9$)#}8scPpj5R_@E6@~-jb&YQouEv_@4F#Ev_b_t01p&0r3M{JqfyZiuG znP-oC)t;?TQj(Lm+x*%hI`l}Q-8`4)cbYfP?DKoZG-)SX7nJdDn(ZH-I+j^)XXb!J NJYD@<);T3K0RT6Fi?RR! literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..c44b52966425ff9898d26dfdca5a2c36ae42783e GIT binary patch literal 317 zcmV-D0mA-?P)YU6bA4wxkE7`q?fKHFCeAO%_0h7ClOkT-OW?vja(IVP>7(o2*u=9=~8g8rQOsP zbds1JCyP}wDv0N|oj)Jv0E{ul*nekyZ8UdUba=4;t^c7>uha0p4RuStM%JUH? z*YK(e8`+h9Y{Agq2cxniVE&?*s&qA|hG3-AgxUV+9@tVfN`sG)<2i6j_JOrgig zff5*WVDS9L=l#gLzA$21JlH!pl&2@heff`_T1_?|pD+xaZZ{&An&$$&2%|o_b&NM!77tPRN915dxiuOH!XY0G7MR{c{s<data><IncludeFilters /><ExcludeFilters><Filter ModuleMask="Lidgren.Network" ModuleVersionMask="*" ClassMask="*" FunctionMask="*" IsEnabled="True" /></ExcludeFilters></data> True True + True True True True From d7ced7a45ca443e9e9f35f8e9bf3b9c9e7e9029a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Aguilera=20Puerto?= Date: Fri, 21 Aug 2020 16:51:47 +0200 Subject: [PATCH 02/23] unlit layers for firelock.rsi --- .../Structures/Doors/firelock.rsi/bolted.png | Bin 0 -> 1678 bytes .../Doors/firelock.rsi/closed_unlit.png | Bin 0 -> 1652 bytes .../Structures/Doors/firelock.rsi/closing.png | Bin 2976 -> 15631 bytes .../Doors/firelock.rsi/closing_unlit.png | Bin 0 -> 3036 bytes .../Structures/Doors/firelock.rsi/deny.png | Bin 2193 -> 12113 bytes .../Doors/firelock.rsi/deny_unlit.png | Bin 0 -> 1852 bytes .../Structures/Doors/firelock.rsi/locked.png | Bin 1497 -> 1101 bytes .../Structures/Doors/firelock.rsi/opening.png | Bin 2983 -> 15781 bytes .../Doors/firelock.rsi/opening_unlit.png | Bin 0 -> 3037 bytes 9 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 Resources/Textures/Constructible/Structures/Doors/firelock.rsi/bolted.png create mode 100644 Resources/Textures/Constructible/Structures/Doors/firelock.rsi/closed_unlit.png create mode 100644 Resources/Textures/Constructible/Structures/Doors/firelock.rsi/closing_unlit.png create mode 100644 Resources/Textures/Constructible/Structures/Doors/firelock.rsi/deny_unlit.png create mode 100644 Resources/Textures/Constructible/Structures/Doors/firelock.rsi/opening_unlit.png 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 0000000000000000000000000000000000000000..53bdd1ccf4a3d629c9f47575e0ee1d12e92350fc GIT binary patch literal 1678 zcmV;9266d`P) zaB^>EX>4U6ba`-PAZ2)IW&i+q+U-|cax5nd{bvz}_p{Dq4t$B@)Yt~p0ssiw*egA#97Jx_}1JkQ0~66SB{;jzFV z33|CrtzG;LbbWc@u7mnpdMMWlmrKyKa2F_B^VT+B8won!=#(x&b=?NJ7JF@Kzf2t$ z<1yvBOFg!1VYemB!)rn^L}@A%3G)(?h$qWsf!ywfyWq(};3LTxC#m5q#LE%{45Wi9^4~zI|p+$S=&UL%b;=XR) zwUiOjd}UM&_vq|*z}OLTIj?0j!>t(GX%(%+76%}oam0=`s1gGe50q$9Bd2xxK?5cx zUTo-@2f*31BF2@6Y@E_=DASH9W8_ZEMp z1^2N-M6o<#1-p2sD9qT%?I*YZ2>FGZo&ew51%G^%KS)&|s3*(?4z}2DBD&H`Zppz} zz^CYMTZn?qO8`Oy-3nt!fI!S7N|~ZD8xi7I08oSFEQvc1AXT0)l9Nd0U|e|X#ydub zmz6VbGHMfmQ0yiHHdPwHN=cDFmI`vHsc2HwtfnPs)s`ivtT|`PyT~;YOQx31tXQ>H zq@Sv4DzYHg4RKvml#iFacpN2U;6M&_}xC- ztsHXZYM0Xl(SH(>~s%ra(^0gVWgUINr*#s`vv4iQNbwQgIC}gX9{_pJ;)+uqXGWjRPKah3I5}{#c<>Z2 zAvHOr-`;KEM+{IfU`bhhm2pgBF4JfA;Tyt+cy9=AuHAF=6IO*kQ$)T5eF^&S2y%SS z)$lKqSH!?8g6KsTMldKbQ=d&H6Yv~g_we!c zF3PjK&;2<%m7K`{pGZ8zbi*QEC!X50bk6(4VOEqB;&b9rgDyz?$aUG}H_ioz1)do; z(y2M(FtJ!@VY!7_(NKvei6e@tQNECIS>e3JSuIsqnDK!8MxA#{&EeN{v^HH)FMYf_cm~G-PGhg;Bp7(d(tICawI=ZA)g1{ z&*+=7K+i4EvFi5L*vIJukfyE@H^9LmFkGPQHIH`(TYLNWOryUaf)#SDJi-ru00006 zVoOIv0RI600RN!9r;`8x010qNS#tmY3labT3lag+-G2N4000McNliruulE_Tg`LiLHF3)y|)LXqzg#>M?gDHvVged0q3^J0^*hjl%o5Bxa9%It_x6Z0RZZE Y1MFcE!%+AuAOHXW07*qoM6N<$g59JKd;kCd literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..1d33d3f366a9979a09a0409afc76cc00822ac473 GIT binary patch literal 1652 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 delta 2971 zcmV;M3uN?$M7h#1H>RNFe+^A}d zP^n_B6w;;w!XG7x)JPRlDTh=lBnTiRia@BX3PPY(s;HDEmC|z5C8#Kb4Q(fcE)q>+SxHi%U7~8`*!Ai_8q@B*MIjHskOCL0BqQ>fxf;z zcDDE8r+(ktPD@J*M~@ygm6s}CYHe*5MtF6lM9;wnU*H?J4spCc!{KvRnSMkm^QG^u5wvs zR7r7iXtrSfTsqC2@i=-zlS%e%*}`r6_Y-bvVqaGmJK}Kw&u!!He}8h)#+R+|7tWrQ zZrMF41_08)7*r+#dSl!=U;pj|Li;?eWZ^s@124lHXMZQ8yAQ4wEp6x7+1|_VbJ1?( zH*O0s{Ber9vt_1^H+H7ic1j4_aidC#OcWYB1N3w^;Kg6x8G>VGrq+=F;ie`?Cf&M# zj1bHW3=nQ=G7UtzEVI5dM9)Dp-`+ytjSnVVJ2{_B12hhtbKb9MD&SZ?R~MwB4~AE# z2#!HbqJL~b{4&Y>)3we=QtO7SC;wtNjY2s9iQZn6wQB)Glo>lenPlelY13zbaBVFB zGktx8b5W+%tx4nS1JKa4=squsH2#6t&hf)LuRwY$OC}1Vq)dbG#^9i5J-0MA>f6T7 z7dHeru)m)hsq^HgtJKfsvdnAu-m7nG|L)te#eaD_7bRtea!uM2sMT$h3{YJuQ5E%U zSJ5@oAmEg`ZRLM_Q#rAudJd}Z4N+634nRZ+!l3&yct>@$s9iZfSdtBiOb-#clkmOxF*ZUA6u&OvTk>LpMH z7=ND@OpGnz~#jEbqTcaWq^l!nutUqtZf`vEVpn4;qKqGFf}zrGk%OP^8nCM zPOMVp>jTinMwa42P|C5aDpkHd0LSR@zC|pOM2=-usq*y!NDnOm-Gf!Ce0>0#4zD8? zDfb;7i@iF^!*1^B~*s-g~%6;|902c z950xzi~l$8I%efNzZflH-TKPqo>!yYog2jIfmxjXx;r;`9_v)M{xtMl)lw{g?piMV zEb!pf4dROPmHKxRv$IrHRG@^*7=O8#a;;()+fPDPR4$QEsvKl2c|6)Z6slKQ}PSPV6Q#4jp%^#PB(M%bc zDwsSl4pf--*O#E70YUR-@7Ha`(B6p&-g`f5E7$mbF9G@ZWFR;O0SE6-N`Dl7uN+7w z^*U-2Wdz57jJ^G)cfwC}E5KyIki|$*6u|ygO5)&AhFdl)1gbdFUV?9 zlT%E{D4*4%D5EC6ZcV(W^CQNl1rP4a_Xp&&pkcn?H=N38$i(P}C*%1`A zN|xu|b2i6n{NV9sR*ehWEJ_JsvwgTp3xBPSQ6)uY-6;y;Hy`_oF9UF@?SD4Dp3rNnpi1%19I#nR$`nIG^u^Bwa8y!`Q+<@)7sZ|3&D9)AJc{qdSKd$yB5 z9-RI8DIpwv{#qV@o1FIX^5?tp{ZK*q0h{Y1OwX7PH2UK;&CWRls^!|*nxL?`KEjcM zc>41-ekz@2=aC~o?q(%70klcsG|;$|YZG80d_UyGcYPL=G2C?Qh{xIS=9{h+-x-fX zGRdE|ZZ(zfh{xFxkAFMPS~q{brl2GtVgG^Juve7N|30S)l27^gDIu6kr%iu=t*nrJ zy!f{KfZ;Vslw;)tT`u>u><^>%=VsmZLx)VAVU2*{HA&T~=OC~AgknXYm#ln0BG5?z z$e$muud7Q>Iw&+n2fQO-reS^tJMsOFz>U#zOF9Q?9=LAsEiX(Q=t*)HT%KgK47U+ zbP7?ilH?X5YXoXbkdwS3Fdshvnm>NNaCo))z^h!AZ3i05@@;E>PANKef4;iCR1xUL zU#bXn%@2syt$*}2MdwV-lWwza z=+E~xNiI)*fbVIl7QWQc(ILjh#&m!Di3`(w>vv!EB~$)yKlqr|Rh4`)*p&0ftG#06 zcYJdtEB_e;!J;D2D&r)$cuj^6{&CThzo|7sEUr$HVt;4qPj@DH@5Gdeuh$&iBj|s2 z&i51@Ws@wTdjwMtnUB@@Cwz`Tr9#Gwzln&i5vb({XnYyw{qZZFRn$iMoTaGx18|HU!YGSt^#U~SkB^zkmkYoB@p=Y! zpTR8xceTbiJuvH7_pa6$dr$Q1pREzt{&+o~JUwdS>jUsb^53^+L^c@pC|L%GKjQm(rz*k>T|3KE0f9>%y)~t>?+ENxW09I9o1tS#!4u%Fzd|Q6N zB>v98y#D<9l&>=|A3rO*zbRX6=W7~2eUa))Gd}=1fBf~TcU@frBPgMe{?}MlrLJcM znC7%KP&@AOv_eBB!m7#$mmQcf`{Q#m@_(D(2@(^st@9VEY$#-^BPL|7`m8=L-)~v@ z_Tl!~oSIKrkLUKqn1PFxw1Bo-kMrs`TYf2&B`T9Gc|H1}AIE z;s!whP7X~HNT;F9d~UPl2lze%UFyh}A0P>VSOi}Zf`Z@#m&dhl7fAQ8T01}A=zx=*x5PIa#wfcU>@}K-6 zoU^;D`q}qJY~|Md0TbVrAMmh?DXdsCFrPpF;T8VQz$fvV0g0=3SJ>*m z<|cD_B9Y+VFR6FtZsphgc>ccvd*Fr(`SSz(T84sMLk0QspXgS6nSqaPOBBSfTOZ=S zr({#-KYhP?@o?W$YJ@6^LL!mixrfrEPo->w{@g=p+x`#SaN*1RfaS*jKNNptMU;vM RQJeq(002ovPDHLkV1h?_=ZpXV 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 0000000000000000000000000000000000000000..d0b97a40290270f03ee6864e2e272d1750876893 GIT binary patch literal 3036 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 e0RR91_ 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 R-#ZQ@B_=0YD{K(-{{TvosEYsq delta 2181 zcmV;02zvL?UXc-yBYy~3Nkl>Oh~b$)CosZ@&5(NUj0EWXwV-xL#E{kVT!;Cl{Fv;TYl;cr=o=~g04zBqdHsBDD) zsIzljDsW|Cfjx((Nj)Ptb?zBbsT4p{<2RD8G{X1w#n%N6u&*!f_3nwCV`Q`0rp9kH zUu$)9SxW3m#eZk(&@_scwJap)o(`=UGq9*E>u00*-j)6V;je&YabkEF00p2_;=;j$ zyqL)#fD7p~$1|BG$3gZB>2zQv>J=7W0oW81B$ECMst^eGhB~>`jC4pJV6Dpc*UE>< z_k~3?9LoU;MbTuVRPudv%SEcuZ}hubJuZK_(dP@W3V#RziU6BhgpX%39RK8#mQG&G zWS~^yPlpft?8h@1j%PBIDi(@xe5)hIxFt${ATUaANlD{J9jNT*xQf0wU; zvmz#vuz!8q9IEI=6HYLM0Ho6pyIL?hFwivA>Q#}F{NyCjfdP&UXAlDZoK6$bogi%A zHrG_f<+oD(6j%%2T?|)T1ObLWQW4TdGs@@+=mPTNW022*sLf*^yi_8e&H6qAM7z5| zK;f$_2*;PMfM%2t()Jo%ui=lHCr55<44KOTb$|1CwS4ejYmmzqyLa!Fv$M0r<8e;+ z+#(g(%-n+xDn*^8l0`{^s%qF0BzW_w{&`z}uBa-qQbDPXB11sT&`>+dbZst@Ej-|@ znL!p87fB|aZg=_n=H}Sf7iTH&4F7unu2#bjdVc_jMJ2;`7a8vA^7vjiTzuggmQqGj z!GBOdHOfSEjfkfCmVypV^BlH1k7!!$&^1(}jG=(0f~AzX_`rz{QJQ@e)5#T*I(+W0)G^v3`N};0unAxO)cyEXIr*-!$mR5jt>Dp zc&f~2|GNi5p|iWWTu*N=cYzQ7JI$+m2Kjoj5a@qZ`~Ynmi16OkTlB_a^z`<6b}s>cml7%Im#YF?VtYb@vMOB!BSN9ACLf*T2i|#JndzVmjNjzSnGk;bl z**A;$#<8mdPXmiB8?l(H(A}js+2iKw_^o^f$qPVb@;Y`!=ZD|dIRAl4NzSuq!@Lc% zIRy)_fs;d9TlUV$p{<-Bzl~CLoHT6`3d9vKF01U{t8wKUo66*MU~8a{=S-8|kKYcw z<}#M!FIVjL7l4HY=dUecn|~QaGdjpspit0wAPU4fB1ED(_vc!#3-{;BoEX~5 z_1pK^6pc_Q7UR}pvO^cEGYO-`jN(&<5}BVjeqSe)AtvK9bv{N?j1_wK~mPLb$z&6mqxNvq|r zMlN3g=f{B)`(dG|QkG!Z&QXyd<)e=PSq-A=uPhyg%XH=PH&QO&_kWGVl1?Qn)#2|p z-s#b`g~3|~Y)L^%DplXsBTnPB^6Sejw|00>fo~HPXSiAx6H^Op@9zxg`A4gS2~12a zpjZ|aJ@`fC+k`V&6wBh~w8L-Kqw{Z0JA4}WUI6B29ru;$mxqbzfQR*Cs-kHvo8bN+ zVpsV$*MV;bd@=GY(|?na!F^M_b*Tq{TrS7k$MOLD>MymI_j>y;-;ZLNrg!Z(Kfm8( zZ@eF1@QO_`=3mgl;`>7K>kmy#(0bOw!Sn&fgh&c1G8-6}T?yR)xb zP4}NZFhjR#bN2GHz8%^y`66h0{K>p<`sL2})ohP%BtP({(kJ)6wX(*?$3^uo03##o zO&npQ4$>C+0e@ji3u^qj?azPg1mVcRYn(dg1i|h3uoQZJK-g;A{D6&8+vEp?rMAcq z2vgsQ{DAdT+vW#sl-eRcAWXGIen6ONoBV*V6ncKZ$jC^j>tfsF2ZW`z$PWlpZId4m zmfA8uU?bIb`2icPw#g3&OKp=M5SH2|KOii%MSeh-YJQ9SfH2h-`2k_-JCh%W&p00000NkvXX Hu0mjfIVV(q 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 0000000000000000000000000000000000000000..c584771ed1a24d0794a3e6dac0de6b2abfcea6da GIT binary patch literal 1852 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 delta 2978 zcmV;T3tjZ3d#4wWBYz8SNkl-CS>nVoBA*Iv&i((;v79>1OUKJWPb-ha&O{C-kLM~49D>gr-( zV1VuG4&$X>J-m+g_I3^(I%F!ZRKC>F(IJfRx*Cc8ea)W0*KZ!>=unyir>`<~qLTU2 z)~#EG6@K-yWuA24qp2y@Zyu$+Q{sVFI%#ij2e1wP>SfDF3PC2FHq{TxGV`gFE5qrW zpe!$#Kc7l*SAQ&qq&1RAuzS-cw#8xqy!M@q-0|0g0PODV)ys{?ns)d05|m{}zHEhW zYzi|oyP$b3S{s|f9NY)(ooCp-?l7-rz1@kQOr_XP#bo2P}l~#5EbI5 zMXvpAu^8Llc_;6=cg13mNbsl4n@#20VllSGVvcj5@nx-`xz)U)URa=;tbA*Is}^H{ z#qiIrN}wDG;+LHJGdny?sI}EpwkJF0t^4TMh41DKc*OpdDs<+8wu8DTos_~o*|e0+ejE0a3Yx^Tv_LdV)?Oi7ZqY;hW22K9ot5%{A1XK%DRyuHpwzSx} z5{Mgp?A?7PKWuJS;~(?b0+njnl|S%FLTcZ6QVav6fN`ja z=e#A~iy>Uj|--flm^WvOyL`z6>CQVEBfkEPGyIzR~aL9tbde!%>9D zS&ESl@Y&5lq6yUkn+^x4uTuLER)733l7ABJtg90Z%X9se6v0Sm)&g%1!XAp^zy0xK z{-?qMGWBf&IBh@2$k$C(&i(-C^&Y5H%gD`;wA9o1URz-I23ffA%ON9QUw}^5GsrQZ zum%2jeVb#$FZT~p$O5G->pz?`)iv_Hw7_EcUdqbX7vKo}giu)bWD~Hk|TaNUzleE#ehN9YHlrn(y6Yl$rDQsL_hkQ!D0W`K2}5LcX0 z?}Vs^N#>}nu0{z}asGnUd2>2{A<2%8D4!0Ur?$G9$+Tw?SC#OpM2SevP>XA zeY}b>lKMl?_|x__G=2tn=$dAsdmu15SG))I^>hi72iD6>h0Gr4#xF*tdZ3Xnb$54* zdwV{my;I^BZ-lw-XcengMwpqkx3!Q3u&O2`IA85!Utolv-8Rj@5y6WetOdZxkGA?) zb+(SiQ>8tC8KvEgeSgt7!O(EVm0$Hh4TU@~pAj@HucDv_K0jmP%K)KKiT95AsXHAc zBj^8xda;wQY2w5M>S}_(G@;R4TSh)jNl!hn?zB693U58o%J+f#a$x%nP#gCbHMmlw zF^n%njQqCu{X~UqoBV|;69|~vhzgmjzHBPUSFeF#lt4iLw13prs@Jo0;lN6vs!WxU$(PG-Yv%pa925r|_jxQ02V0Yy68Pjo3Q-4qtb<)oKU40;F+q6Re-dNsr zono5gg_M)$Vdtqng-4co>w#(?-1yFQm&yaJd_6Sr-kwhxpAkIOr|_@e%_8|EuGv{_ zv+!$gHkZfaasK^^`ed4~{Q95N>uo%E<2fQV5-)zR))X43@xAuI$G5~?`C@+q8ClNb zfs2>sfq&9X=S_T5aIV&g#8OLN|0!ow?x?|8{C z?OI>DDvAG9e!xZM=gkku7axE7o;`$GTl2=mTYryXaq;=E^idhdN9T&-&;KRjNmNAe zd*g-k1J?Eg;E1{5r3%bi+Y_LFU$bj`e#;ggXFu~MDx;;xM}MC?|D{u>q+54RdGb#B z?NgJ|J^NM)Bi}Yc&jYiv$`_ySeN;xql@H!WMHu~!bgA)eFGg>B z{c_j4F)c~X>C@NK=u?1s2K= zfThn%FsfjFKswgUmCef>^Mp%LO-OKjbP9j(sB3)w7wI}r^MqIVCtUdt?Jgn}vIIT1 z%`Xb(2ecjenkNe|*!jPr;`9AS+gLFnmMl*gvWu{0uqb|^MOf@L=(%lv@f%fsz$M22 YKPr$#lsFn10000007*qoM6N<$g1uP+0RR91 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 0000000000000000000000000000000000000000..816c648cc49d8c4166cbc85aeead83fcec6a327b GIT binary patch literal 3037 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 literal 0 HcmV?d00001 From a5fbe0f024dabe79231185ff59fb0fb9f52c3e37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Aguilera=20Puerto?= Date: Fri, 21 Aug 2020 18:29:43 +0200 Subject: [PATCH 03/23] firelock stuff I guess --- .../Atmos/IGridAtmosphereComponent.cs | 6 ++ .../Components/Atmos/FirelockComponent.cs | 54 ++++++++++------ .../Components/Doors/ServerDoorComponent.cs | 63 +++++++++++++++++-- .../Structures/Doors/firelock.rsi/meta.json | 57 +++++++++++++++++ 4 files changed, 156 insertions(+), 24 deletions(-) diff --git a/Content.Server/Atmos/IGridAtmosphereComponent.cs b/Content.Server/Atmos/IGridAtmosphereComponent.cs index fd5648c091..e16d630708 100644 --- a/Content.Server/Atmos/IGridAtmosphereComponent.cs +++ b/Content.Server/Atmos/IGridAtmosphereComponent.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Map; +using Robust.Shared.Maths; namespace Content.Server.Atmos { @@ -151,6 +152,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); } } diff --git a/Content.Server/GameObjects/Components/Atmos/FirelockComponent.cs b/Content.Server/GameObjects/Components/Atmos/FirelockComponent.cs index 02d3ac22a5..03ec350359 100644 --- a/Content.Server/GameObjects/Components/Atmos/FirelockComponent.cs +++ b/Content.Server/GameObjects/Components/Atmos/FirelockComponent.cs @@ -1,35 +1,36 @@ -using System.Threading.Tasks; +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.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, IActivate, ICollideBehavior + public class FirelockComponent : ServerDoorComponent, IInteractUsing, ICollideBehavior { + [Dependency] private IServerNotifyManager _notifyManager = default!; + public override string Name => "Firelock"; - public override void Initialize() - { - base.Initialize(); - } + 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. } - public void Activate(ActivateEventArgs eventArgs) - { - // We do nothing. - } - protected override void Startup() { base.Startup(); @@ -60,26 +61,41 @@ namespace Content.Server.GameObjects.Components.Atmos return closed; } - public override void Deny() + public override bool CanOpen() { + return !IsHoldingFire() && !IsHoldingPressure() && base.CanOpen(); } public override bool CanClose(IEntity user) => true; - public override bool CanOpen(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 (!await tool.UseTool(eventArgs.User, Owner, 3f, ToolQuality.Prying)) return false; + if (tool.HasQuality(ToolQuality.Prying)) + { + var holdingPressure = IsHoldingPressure(); + var holdingFire = IsHoldingFire(); - if (State == DoorState.Closed) - Open(); - else if (State == DoorState.Open) - Close(); + if (State == DoorState.Closed) + { + if(holdingPressure) + _notifyManager.PopupMessage(Owner, eventArgs.User, "A gush of air blows in your face... Maybe you should reconsider."); + } - return true; + 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/Doors/ServerDoorComponent.cs b/Content.Server/GameObjects/Components/Doors/ServerDoorComponent.cs index 381f276bd0..d2f8f7f65b 100644 --- a/Content.Server/GameObjects/Components/Doors/ServerDoorComponent.cs +++ b/Content.Server/GameObjects/Components/Doors/ServerDoorComponent.cs @@ -1,10 +1,12 @@ using System; using System.Linq; using System.Threading; +using Content.Server.Atmos; using Content.Server.GameObjects.Components.Access; using Content.Server.GameObjects.Components.Atmos; using Content.Server.GameObjects.Components.GUI; using Content.Server.GameObjects.Components.Mobs; +using Content.Server.GameObjects.EntitySystems; using Content.Shared.Damage; using Content.Shared.GameObjects.Components.Body; using Content.Shared.GameObjects.Components.Damage; @@ -49,11 +51,11 @@ namespace Content.Server.GameObjects.Components.Doors private AppearanceComponent _appearance; private CancellationTokenSource _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; @@ -263,6 +265,57 @@ namespace Content.Server.GameObjects.Components.Doors } } + public bool IsHoldingPressure(float threshold = 20) + { + var atmosphereSystem = EntitySystem.Get(); + + if (!Owner.Transform.GridPosition.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.GridPosition.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; diff --git a/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/meta.json b/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/meta.json index c25c825232..08653842b9 100644 --- a/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/meta.json +++ b/Resources/Textures/Constructible/Structures/Doors/firelock.rsi/meta.json @@ -7,6 +7,15 @@ "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, @@ -16,6 +25,15 @@ ] ] }, + { + "name": "closed_unlit", + "directions": 1, + "delays": [ + [ + 1.0 + ] + ] + }, { "name": "closing", "directions": 1, @@ -30,6 +48,20 @@ ] ] }, + { + "name": "closing_unlit", + "directions": 1, + "delays": [ + [ + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2 + ] + ] + }, { "name": "deny", "directions": 1, @@ -41,6 +73,17 @@ ] ] }, + { + "name": "deny_unlit", + "directions": 1, + "delays": [ + [ + 0.1, + 0.1, + 0.1 + ] + ] + }, { "name": "frame1", "directions": 1, @@ -109,6 +152,20 @@ ] ] }, + { + "name": "opening_unlit", + "directions": 1, + "delays": [ + [ + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2 + ] + ] + }, { "name": "panel_closing", "directions": 1, From c137d1bc16275dd1b84075e1fcadb7fcdbe94322 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Aguilera=20Puerto?= Date: Sun, 30 Aug 2020 13:20:08 +0200 Subject: [PATCH 04/23] changes dunno --- .../Atmos/IGridAtmosphereComponent.cs | 3 +- .../Components/Atmos/AirtightComponent.cs | 2 +- .../Atmos/GridAtmosphereComponent.cs | 100 ++++++++++-------- 3 files changed, 56 insertions(+), 49 deletions(-) diff --git a/Content.Server/Atmos/IGridAtmosphereComponent.cs b/Content.Server/Atmos/IGridAtmosphereComponent.cs index 56678a75a1..8060276652 100644 --- a/Content.Server/Atmos/IGridAtmosphereComponent.cs +++ b/Content.Server/Atmos/IGridAtmosphereComponent.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; 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; @@ -152,7 +153,7 @@ namespace Content.Server.Atmos /// /// Returns a dictionary of adjacent TileAtmospheres. /// - Dictionary GetAdjacentTiles(MapIndices indices, bool includeAirBlocked = false); + Dictionary GetAdjacentTiles(MapIndices indices, bool includeAirBlocked = false); void Update(float frameTime); diff --git a/Content.Server/GameObjects/Components/Atmos/AirtightComponent.cs b/Content.Server/GameObjects/Components/Atmos/AirtightComponent.cs index 3703eff58d..e4085a66af 100644 --- a/Content.Server/GameObjects/Components/Atmos/AirtightComponent.cs +++ b/Content.Server/GameObjects/Components/Atmos/AirtightComponent.cs @@ -35,7 +35,7 @@ namespace Content.Server.GameObjects.Components.Atmos if (Owner.TryGetComponent(out SnapGridComponent? snapGrid)) { - EntitySystem.Get().GetGridAtmosphere(Owner.Transform.GridID)?.Invalidate(snapGrid.Position); + EntitySystem.Get().GetGridAtmosphere(Owner.Transform.GridID)?.Revalidate(snapGrid.Position); } } } diff --git a/Content.Server/GameObjects/Components/Atmos/GridAtmosphereComponent.cs b/Content.Server/GameObjects/Components/Atmos/GridAtmosphereComponent.cs index fd56e9d34d..a1186c9bd2 100644 --- a/Content.Server/GameObjects/Components/Atmos/GridAtmosphereComponent.cs +++ b/Content.Server/GameObjects/Components/Atmos/GridAtmosphereComponent.cs @@ -210,60 +210,66 @@ namespace Content.Server.GameObjects.Components.Atmos private 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}); - _tiles[indices] = tile; - } - - if (IsSpace(indices)) - { - tile.Air = new GasMixture(GetVolumeForCells(1)); - tile.Air.MarkImmutable(); - _tiles[indices] = tile; - - } else if (IsAirBlocked(indices)) - { - tile.Air = null; - } - else - { - var obs = GetObstructingComponent(indices); - - if (obs != null) - { - if (tile.Air == null && obs.FixVacuum) - { - FixVacuum(tile.GridIndices); - } - } - - tile.Air ??= new GasMixture(GetVolumeForCells(1)){Temperature = Atmospherics.T20C}; - } - - tile.UpdateAdjacent(); - tile.UpdateVisuals(); - - for (var i = 0; i < Atmospherics.Directions; i++) - { - var direction = (AtmosDirection) (1 << i); - var otherIndices = indices.Offset(direction.ToDirection()); - var otherTile = GetTile(otherIndices); - AddActiveTile(otherTile); - otherTile?.UpdateAdjacent(direction.GetOpposite()); - } + Revalidate(indices); } _invalidatedCoords.Clear(); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Revalidate(MapIndices indices) + { + if (!Owner.TryGetComponent(out IMapGridComponent? mapGrid)) return; + + var tile = GetTile(indices); + + if (tile == null) + { + tile = new TileAtmosphere(this, mapGrid.Grid.Index, indices, new GasMixture(GetVolumeForCells(1)){Temperature = Atmospherics.T20C}); + _tiles[indices] = tile; + } + + if (IsSpace(indices)) + { + tile.Air = new GasMixture(GetVolumeForCells(1)); + tile.Air.MarkImmutable(); + _tiles[indices] = tile; + + } else if (IsAirBlocked(indices)) + { + tile.Air = null; + } + else + { + var obs = GetObstructingComponent(indices); + + if (obs != null) + { + if (tile.Air == null && obs.FixVacuum) + { + FixVacuum(tile.GridIndices); + } + } + + tile.Air ??= new GasMixture(GetVolumeForCells(1)){Temperature = Atmospherics.T20C}; + } + + AddActiveTile(tile); + tile.UpdateAdjacent(); + tile.UpdateVisuals(); + + for (var i = 0; i < Atmospherics.Directions; i++) + { + var direction = (AtmosDirection) (1 << i); + var otherIndices = indices.Offset(direction.ToDirection()); + var otherTile = GetTile(otherIndices); + AddActiveTile(otherTile); + otherTile?.UpdateAdjacent(direction.GetOpposite()); + } + } + /// public void FixVacuum(MapIndices indices) { From 52e98e29d7d54ae985436723b7342af320ea53ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Aguilera=20Puerto?= Date: Sun, 30 Aug 2020 15:00:40 +0200 Subject: [PATCH 05/23] Support for non-fulltile firelocks! --- .../Atmos/IGridAtmosphereComponent.cs | 10 +- Content.Server/Atmos/TileAtmosphere.cs | 2 +- .../Components/Atmos/AirtightComponent.cs | 47 +++++--- .../Atmos/GridAtmosphereComponent.cs | 102 +++++++++--------- Content.Shared/Atmos/AtmosDirection.cs | 8 +- 5 files changed, 95 insertions(+), 74 deletions(-) diff --git a/Content.Server/Atmos/IGridAtmosphereComponent.cs b/Content.Server/Atmos/IGridAtmosphereComponent.cs index 8060276652..20707b9b77 100644 --- a/Content.Server/Atmos/IGridAtmosphereComponent.cs +++ b/Content.Server/Atmos/IGridAtmosphereComponent.cs @@ -1,4 +1,5 @@ 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; @@ -48,7 +49,7 @@ namespace Content.Server.Atmos /// Revalidates indices immediately. /// /// - void Revalidate(MapIndices indices); + void UpdateAdjacentBits(MapIndices indices); /// /// Adds an active tile so it becomes processed every update until it becomes inactive. @@ -117,6 +118,7 @@ namespace Content.Server.Atmos /// Returns a tile. /// /// + /// /// TileAtmosphere GetTile(MapIndices indices, bool createSpace = true); @@ -124,17 +126,19 @@ namespace Content.Server.Atmos /// Returns a tile. /// /// + /// /// TileAtmosphere GetTile(GridCoordinates 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. diff --git a/Content.Server/Atmos/TileAtmosphere.cs b/Content.Server/Atmos/TileAtmosphere.cs index 8091830976..0a09904f53 100644 --- a/Content.Server/Atmos/TileAtmosphere.cs +++ b/Content.Server/Atmos/TileAtmosphere.cs @@ -1122,7 +1122,7 @@ namespace Content.Server.Atmos _adjacentTiles[direction.ToIndex()] = adjacent; adjacent?.UpdateAdjacent(direction.GetOpposite()); - if (adjacent != null && !_gridAtmosphereComponent.IsAirBlocked(adjacent.GridIndices)) + if (adjacent != null && !_gridAtmosphereComponent.IsAirBlocked(adjacent.GridIndices, direction.GetOpposite())) { _adjacentBits |= direction; } diff --git a/Content.Server/GameObjects/Components/Atmos/AirtightComponent.cs b/Content.Server/GameObjects/Components/Atmos/AirtightComponent.cs index e4085a66af..cecd58aae1 100644 --- a/Content.Server/GameObjects/Components/Atmos/AirtightComponent.cs +++ b/Content.Server/GameObjects/Components/Atmos/AirtightComponent.cs @@ -1,5 +1,6 @@ #nullable enable using Content.Server.GameObjects.EntitySystems; +using Content.Shared.Atmos; using Robust.Server.Interfaces.GameObjects; using Robust.Shared.GameObjects; using Robust.Shared.GameObjects.Components.Transform; @@ -22,6 +23,8 @@ namespace Content.Server.GameObjects.Components.Atmos public override string Name => "Airtight"; + [ViewVariables] + private int _airBlockedDirection; private bool _airBlocked = true; private bool _fixVacuum = false; @@ -33,10 +36,18 @@ namespace Content.Server.GameObjects.Components.Atmos { _airBlocked = value; - if (Owner.TryGetComponent(out SnapGridComponent? snapGrid)) - { - EntitySystem.Get().GetGridAtmosphere(Owner.Transform.GridID)?.Revalidate(snapGrid.Position); - } + UpdatePosition(); + } + } + + public AtmosDirection AirBlockedDirection + { + get => (AtmosDirection)_airBlockedDirection; + set + { + _airBlockedDirection = (int) value; + + UpdatePosition(); } } @@ -49,16 +60,16 @@ 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()); } 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. + // 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)}"); @@ -87,13 +98,10 @@ namespace Content.Server.GameObjects.Components.Atmos snapGrid.OnPositionChanged -= OnTransformMove; } - if (_fixVacuum) - { - var mapIndices = Owner.Transform.GridPosition.ToMapIndices(_mapManager); - EntitySystem.Get().GetGridAtmosphere(Owner.Transform.GridID)?.FixVacuum(mapIndices); - } + UpdatePosition(_lastPosition.Item1, _lastPosition.Item2); - UpdatePosition(); + if (_fixVacuum) + EntitySystem.Get().GetGridAtmosphere(_lastPosition.Item1)?.FixVacuum(_lastPosition.Item2); } private void OnTransformMove() @@ -109,13 +117,18 @@ namespace Content.Server.GameObjects.Components.Atmos private void UpdatePosition() { - var mapIndices = Owner.Transform.GridPosition.ToMapIndices(_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 = EntitySystem.Get().GetGridAtmosphere(gridId); + + if (gridAtmos == null) return; + + gridAtmos.UpdateAdjacentBits(pos); + gridAtmos.Invalidate(pos); } } } diff --git a/Content.Server/GameObjects/Components/Atmos/GridAtmosphereComponent.cs b/Content.Server/GameObjects/Components/Atmos/GridAtmosphereComponent.cs index a1186c9bd2..0b94087cd9 100644 --- a/Content.Server/GameObjects/Components/Atmos/GridAtmosphereComponent.cs +++ b/Content.Server/GameObjects/Components/Atmos/GridAtmosphereComponent.cs @@ -210,64 +210,64 @@ namespace Content.Server.GameObjects.Components.Atmos private void Revalidate() { + if (!Owner.TryGetComponent(out IMapGridComponent? mapGrid)) return; + foreach (var indices in _invalidatedCoords.ToArray()) { - Revalidate(indices); + var tile = GetTile(indices); + + if (tile == null) + { + tile = new TileAtmosphere(this, mapGrid.Grid.Index, indices, new GasMixture(GetVolumeForCells(1)){Temperature = Atmospherics.T20C}); + _tiles[indices] = tile; + } + + if (IsSpace(indices)) + { + tile.Air = new GasMixture(GetVolumeForCells(1)); + tile.Air.MarkImmutable(); + _tiles[indices] = tile; + + } else if (IsAirBlocked(indices)) + { + tile.Air = null; + } + else + { + var obs = GetObstructingComponent(indices); + + if (obs != null) + { + if (tile.Air == null && obs.FixVacuum) + { + FixVacuum(tile.GridIndices); + } + } + + tile.Air ??= new GasMixture(GetVolumeForCells(1)){Temperature = Atmospherics.T20C}; + } + + AddActiveTile(tile); + tile.UpdateAdjacent(); + tile.UpdateVisuals(); + + for (var i = 0; i < Atmospherics.Directions; i++) + { + var direction = (AtmosDirection) (1 << i); + var otherIndices = indices.Offset(direction.ToDirection()); + var otherTile = GetTile(otherIndices); + AddActiveTile(otherTile); + otherTile?.UpdateAdjacent(direction.GetOpposite()); + } } _invalidatedCoords.Clear(); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Revalidate(MapIndices indices) + public void UpdateAdjacentBits(MapIndices indices) { - if (!Owner.TryGetComponent(out IMapGridComponent? mapGrid)) return; - - var tile = GetTile(indices); - - if (tile == null) - { - tile = new TileAtmosphere(this, mapGrid.Grid.Index, indices, new GasMixture(GetVolumeForCells(1)){Temperature = Atmospherics.T20C}); - _tiles[indices] = tile; - } - - if (IsSpace(indices)) - { - tile.Air = new GasMixture(GetVolumeForCells(1)); - tile.Air.MarkImmutable(); - _tiles[indices] = tile; - - } else if (IsAirBlocked(indices)) - { - tile.Air = null; - } - else - { - var obs = GetObstructingComponent(indices); - - if (obs != null) - { - if (tile.Air == null && obs.FixVacuum) - { - FixVacuum(tile.GridIndices); - } - } - - tile.Air ??= new GasMixture(GetVolumeForCells(1)){Temperature = Atmospherics.T20C}; - } - - AddActiveTile(tile); - tile.UpdateAdjacent(); - tile.UpdateVisuals(); - - for (var i = 0; i < Atmospherics.Directions; i++) - { - var direction = (AtmosDirection) (1 << i); - var otherIndices = indices.Offset(direction.ToDirection()); - var otherTile = GetTile(otherIndices); - AddActiveTile(otherTile); - otherTile?.UpdateAdjacent(direction.GetOpposite()); - } + GetTile(indices)?.UpdateAdjacent(); } /// @@ -413,10 +413,10 @@ namespace Content.Server.GameObjects.Components.Atmos } /// - public bool IsAirBlocked(MapIndices indices) + public bool IsAirBlocked(MapIndices indices, AtmosDirection direction = AtmosDirection.All) { var ac = GetObstructingComponent(indices); - return ac != null && ac.AirBlocked; + return ac != null && ac.AirBlocked && ac.AirBlockedDirection.HasFlag(direction); } /// diff --git a/Content.Shared/Atmos/AtmosDirection.cs b/Content.Shared/Atmos/AtmosDirection.cs index 450a92e4df..2b46faad18 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, @@ -86,4 +88,6 @@ namespace Content.Shared.Atmos return direction | other; } } + + public sealed class AtmosDirectionFlags { } } From 2b426405eb28a5dbe90c98ff1419db62f4be45ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Aguilera=20Puerto?= Date: Sun, 6 Sep 2020 17:05:01 +0200 Subject: [PATCH 06/23] Fix TurfHelpers --- Content.Shared/Maps/TurfHelpers.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Content.Shared/Maps/TurfHelpers.cs b/Content.Shared/Maps/TurfHelpers.cs index e6c0a75ffb..dc1d322c65 100644 --- a/Content.Shared/Maps/TurfHelpers.cs +++ b/Content.Shared/Maps/TurfHelpers.cs @@ -5,6 +5,8 @@ using System.Runtime.CompilerServices; using System.Diagnostics.CodeAnalysis; using Content.Shared.Physics; using Content.Shared.Utility; +using Robust.Server.GameObjects.EntitySystems.TileLookup; +using Robust.Shared.GameObjects.Systems; using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Interfaces.Map; using Robust.Shared.Interfaces.Physics; @@ -59,7 +61,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; @@ -125,15 +127,15 @@ namespace Content.Shared.Maps [MethodImpl(MethodImplOptions.AggressiveInlining)] public static IEnumerable GetEntitiesInTile(this TileRef turf, bool approximate = false) { - var entityManager = IoCManager.Resolve(); + var gridTileLookup = EntitySystem.Get(); - return entityManager.GetEntitiesIntersecting(turf.MapIndex, GetWorldTileBox(turf), approximate); + return gridTileLookup.GetEntitiesIntersecting(turf.GridIndex, turf.GridIndices); } /// /// Helper that returns all entities in a turf. /// - public static IEnumerable GetEntitiesInTile(this GridCoordinates coordinates, bool approximate = false) + public static IEnumerable GetEntitiesInTile(this EntityCoordinates coordinates, bool approximate = false) { var turf = coordinates.GetTileRef(); From e239b707c508870ac245365e8ebcf58d99b2a2b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Aguilera=20Puerto?= Date: Sun, 6 Sep 2020 17:05:20 +0200 Subject: [PATCH 07/23] Replace GridCoordinates (ew) for EntityCoordinates (YAY) --- .../GameObjects/Components/Doors/ServerDoorComponent.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Content.Server/GameObjects/Components/Doors/ServerDoorComponent.cs b/Content.Server/GameObjects/Components/Doors/ServerDoorComponent.cs index 473e55d68e..5bf56df8a8 100644 --- a/Content.Server/GameObjects/Components/Doors/ServerDoorComponent.cs +++ b/Content.Server/GameObjects/Components/Doors/ServerDoorComponent.cs @@ -49,7 +49,7 @@ namespace Content.Server.GameObjects.Components.Doors protected bool AutoClose = true; protected const float AutoCloseDelay = 5; protected float CloseSpeed = AutoCloseDelay; - + private CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource(); protected virtual TimeSpan CloseTimeOne => TimeSpan.FromSeconds(0.3f); @@ -316,7 +316,7 @@ namespace Content.Server.GameObjects.Components.Doors { var atmosphereSystem = EntitySystem.Get(); - if (!Owner.Transform.GridPosition.TryGetTileAtmosphere(out var tileAtmos)) + if (!Owner.Transform.Coordinates.TryGetTileAtmosphere(out var tileAtmos)) return false; var gridAtmosphere = atmosphereSystem.GetGridAtmosphere(Owner.Transform.GridID); @@ -343,7 +343,7 @@ namespace Content.Server.GameObjects.Components.Doors { var atmosphereSystem = EntitySystem.Get(); - if (!Owner.Transform.GridPosition.TryGetTileAtmosphere(out var tileAtmos)) + if (!Owner.Transform.Coordinates.TryGetTileAtmosphere(out var tileAtmos)) return false; if (tileAtmos.Hotspot.Valid) From d58b7f0ebe966f67aa8d6e0a239d6f5d8bc2f79b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Aguilera=20Puerto?= Date: Sun, 6 Sep 2020 17:15:16 +0200 Subject: [PATCH 08/23] whoops --- Content.Server/Atmos/TileAtmosphere.cs | 3 +- .../Utility/GridTileLookupHelpers.cs | 39 +++++++++++++++++++ Content.Shared/Maps/TurfHelpers.cs | 5 +-- 3 files changed, 43 insertions(+), 4 deletions(-) create mode 100644 Content.Server/Utility/GridTileLookupHelpers.cs diff --git a/Content.Server/Atmos/TileAtmosphere.cs b/Content.Server/Atmos/TileAtmosphere.cs index 2d2db819fd..1a9d5b7e51 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; @@ -1090,7 +1091,7 @@ namespace Content.Server.Atmos // TODO ATMOS firelocks! var reconsiderAdjacent = false; - foreach (var entity in GridIndices.GetEntitiesInTile(GridIndex)) + foreach (var entity in GridIndices.GetEntitiesInTileFast(GridIndex)) { if (!entity.TryGetComponent(out FirelockComponent firelock)) continue; reconsiderAdjacent |= firelock.EmergencyPressureStop(); diff --git a/Content.Server/Utility/GridTileLookupHelpers.cs b/Content.Server/Utility/GridTileLookupHelpers.cs new file mode 100644 index 0000000000..7d5223fe6e --- /dev/null +++ b/Content.Server/Utility/GridTileLookupHelpers.cs @@ -0,0 +1,39 @@ +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) + { + var 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) + { + var turf = indices.GetTileRef(gridId); + + if (turf == null) + return Enumerable.Empty(); + + return GetEntitiesInTileFast(turf.Value); + } + } +} diff --git a/Content.Shared/Maps/TurfHelpers.cs b/Content.Shared/Maps/TurfHelpers.cs index dc1d322c65..d059235264 100644 --- a/Content.Shared/Maps/TurfHelpers.cs +++ b/Content.Shared/Maps/TurfHelpers.cs @@ -5,7 +5,6 @@ using System.Runtime.CompilerServices; using System.Diagnostics.CodeAnalysis; using Content.Shared.Physics; using Content.Shared.Utility; -using Robust.Server.GameObjects.EntitySystems.TileLookup; using Robust.Shared.GameObjects.Systems; using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Interfaces.Map; @@ -127,9 +126,9 @@ namespace Content.Shared.Maps [MethodImpl(MethodImplOptions.AggressiveInlining)] public static IEnumerable GetEntitiesInTile(this TileRef turf, bool approximate = false) { - var gridTileLookup = EntitySystem.Get(); + var entityManager = IoCManager.Resolve(); - return gridTileLookup.GetEntitiesIntersecting(turf.GridIndex, turf.GridIndices); + return entityManager.GetEntitiesIntersecting(turf.MapIndex, GetWorldTileBox(turf), approximate); } /// From bc972156bb0d918fca35d373f20f2c429f548ab6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Aguilera=20Puerto?= Date: Sun, 6 Sep 2020 17:34:45 +0200 Subject: [PATCH 09/23] Fix firelocks --- Content.Server/Atmos/TileAtmosphere.cs | 10 ++++++++-- Content.Shared/Atmos/AtmosDirection.cs | 5 +++++ .../Entities/Constructible/Doors/firelock.yml | 2 ++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/Content.Server/Atmos/TileAtmosphere.cs b/Content.Server/Atmos/TileAtmosphere.cs index 1a9d5b7e51..18927a772e 100644 --- a/Content.Server/Atmos/TileAtmosphere.cs +++ b/Content.Server/Atmos/TileAtmosphere.cs @@ -1159,9 +1159,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 (!_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.Shared/Atmos/AtmosDirection.cs b/Content.Shared/Atmos/AtmosDirection.cs index 2b46faad18..c3991df998 100644 --- a/Content.Shared/Atmos/AtmosDirection.cs +++ b/Content.Shared/Atmos/AtmosDirection.cs @@ -87,6 +87,11 @@ 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/Resources/Prototypes/Entities/Constructible/Doors/firelock.yml b/Resources/Prototypes/Entities/Constructible/Doors/firelock.yml index ecfe8b2578..a4abf989ee 100644 --- a/Resources/Prototypes/Entities/Constructible/Doors/firelock.yml +++ b/Resources/Prototypes/Entities/Constructible/Doors/firelock.yml @@ -15,6 +15,8 @@ - state: closed_unlit shader: unshaded map: ["enum.DoorVisualLayers.BaseUnlit"] + - state: welded + map: ["enum.DoorVisualLayers.BaseWelded"] - state: bolted shader: unshaded map: ["enum.DoorVisualLayers.BaseBolted"] From 3e1015eeda5eb242ae43ecc216c1525ae68a6591 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Aguilera=20Puerto?= Date: Sun, 6 Sep 2020 17:52:11 +0200 Subject: [PATCH 10/23] fix glass firelocks --- .../Doors/firelock_glass.rsi/bolted.png | Bin 0 -> 1678 bytes .../Doors/firelock_glass.rsi/closed_unlit.png | Bin 0 -> 1652 bytes .../firelock_glass.rsi/closing_unlit.png | Bin 0 -> 3036 bytes .../Doors/firelock_glass.rsi/deny_unlit.png | Bin 0 -> 1852 bytes .../Doors/firelock_glass.rsi/meta.json | 59 +++++++++++++++++- .../firelock_glass.rsi/opening_unlit.png | Bin 0 -> 3037 bytes .../Doors/firelock_glass.rsi/welded.png | Bin 317 -> 318 bytes .../Doors/firelock_glass.rsi/welded_open.png | Bin 321 -> 321 bytes 8 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/bolted.png create mode 100644 Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/closed_unlit.png create mode 100644 Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/closing_unlit.png create mode 100644 Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/deny_unlit.png create mode 100644 Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/opening_unlit.png 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 0000000000000000000000000000000000000000..53bdd1ccf4a3d629c9f47575e0ee1d12e92350fc GIT binary patch literal 1678 zcmV;9266d`P) zaB^>EX>4U6ba`-PAZ2)IW&i+q+U-|cax5nd{bvz}_p{Dq4t$B@)Yt~p0ssiw*egA#97Jx_}1JkQ0~66SB{;jzFV z33|CrtzG;LbbWc@u7mnpdMMWlmrKyKa2F_B^VT+B8won!=#(x&b=?NJ7JF@Kzf2t$ z<1yvBOFg!1VYemB!)rn^L}@A%3G)(?h$qWsf!ywfyWq(};3LTxC#m5q#LE%{45Wi9^4~zI|p+$S=&UL%b;=XR) zwUiOjd}UM&_vq|*z}OLTIj?0j!>t(GX%(%+76%}oam0=`s1gGe50q$9Bd2xxK?5cx zUTo-@2f*31BF2@6Y@E_=DASH9W8_ZEMp z1^2N-M6o<#1-p2sD9qT%?I*YZ2>FGZo&ew51%G^%KS)&|s3*(?4z}2DBD&H`Zppz} zz^CYMTZn?qO8`Oy-3nt!fI!S7N|~ZD8xi7I08oSFEQvc1AXT0)l9Nd0U|e|X#ydub zmz6VbGHMfmQ0yiHHdPwHN=cDFmI`vHsc2HwtfnPs)s`ivtT|`PyT~;YOQx31tXQ>H zq@Sv4DzYHg4RKvml#iFacpN2U;6M&_}xC- ztsHXZYM0Xl(SH(>~s%ra(^0gVWgUINr*#s`vv4iQNbwQgIC}gX9{_pJ;)+uqXGWjRPKah3I5}{#c<>Z2 zAvHOr-`;KEM+{IfU`bhhm2pgBF4JfA;Tyt+cy9=AuHAF=6IO*kQ$)T5eF^&S2y%SS z)$lKqSH!?8g6KsTMldKbQ=d&H6Yv~g_we!c zF3PjK&;2<%m7K`{pGZ8zbi*QEC!X50bk6(4VOEqB;&b9rgDyz?$aUG}H_ioz1)do; z(y2M(FtJ!@VY!7_(NKvei6e@tQNECIS>e3JSuIsqnDK!8MxA#{&EeN{v^HH)FMYf_cm~G-PGhg;Bp7(d(tICawI=ZA)g1{ z&*+=7K+i4EvFi5L*vIJukfyE@H^9LmFkGPQHIH`(TYLNWOryUaf)#SDJi-ru00006 zVoOIv0RI600RN!9r;`8x010qNS#tmY3labT3lag+-G2N4000McNliruulE_Tg`LiLHF3)y|)LXqzg#>M?gDHvVged0q3^J0^*hjl%o5Bxa9%It_x6Z0RZZE Y1MFcE!%+AuAOHXW07*qoM6N<$g59JKd;kCd literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..1d33d3f366a9979a09a0409afc76cc00822ac473 GIT binary patch literal 1652 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 e0RR91_ zaB^>EX>4U6ba`-PAZ2)IW&i+q+U-|ua_lG!{Ld-&2uL7=j>DI#_6B?WZEVkEGRe!! z%jVZsOxZ93L|ZKyPgwu_?cpz6oD+vET8otuab?TK4UHPl%Z?|-d_0dUUtRe9${y|= z3{yg#&Y#+@@eOu)nQ&W!`fGcrR}a_A(baKtnD)wy#(V?`JD+yCkOW(2qgd5PsGZMx z+#uJNyV`+eJ3G7ZJ3Jb)B1%)RP-0$*QpA(fg&>`G!(H*@L>Nb@pq*0=M~7WV5Rg}| zcdKK34A83}-&)~0`uEmT@VQ;~^c2f-#R!deJ4oIS{t@Dbh0`4ozwXHG&hVQcyU*&r z&bMp1Afn~Us2Fb1*>f@-F18$UFapZ z(!q1WI6-}GAqqM#2M7_?7J#7y24bNkR46L55+RNi1T`S%l(~Ze65$DuP@_~hC|BNV zV~)}>mW2y%Gqedr2zHZ#8%qsj?{ zwW?{WspcxRRIRmIZN`?Mfnvqfs+qOMp<$s0Uk&3MES-Dmxl1oyd+pZSK>Cb4WR#(! z4jXOqOcOFO%hXw?&9*2kD8 zVeV7B1*xCnjeo~n*wlRoa{<)7Oi~@KO32m)DJXrF;k-5??wBO;XyRD>O^uHSkIlo0o&iw& zKyMwOdh(6k=LV1L9y+Jbazc+@(mwRy6|fS8Ks>O29p zE?~}>(I~II6&EtzQoP{T4L^Ji|J&Nd99t}@b$k)1hy6k2Sn~+1jMay=j`%Mg17Oq( z_`|Ci-pwc8EG5wCZ7m#j3${@g_F)eQ3UF^X(J{~3q%0)MY~^CJ+Sg1xzm;2KdODy(l7H1@ERBh&Gz7APD_bK^Dzy+g7{Z z;yF{Q_2cvo-?Be`9Q`=@UpxAp(m(6`yD}f{I={E>=XCyEnGavk`ByTJ&O_+Kmz4g} zt4Em+U(oq?;f62h{EN)v#cnbmex>vHqyMDzIHnK#rS^BRKczl=QS0AGeK@uLIwYUe z9^cmwdJja;ioXT_lKb$W_kX7LPjzVDv`2m%eUBq#F#aO^3)nKfmH}!O@Bjb-g=s@W zP)S2WAaHVTW@&6?004NLeUUv#!$2IxUsI(;st#5VQOHom!GfrWqgJ5^6-uqps)Na; zA3~FcB*n#1a4k6au~>C*an{wrRS*O}K%5+%6kVjm|0RVMF&-TEt++O%}e`@~^ZloaA~;!%SxNc_lk+2uFR1&0Nm88*_XIpQ#}SZHCng;~*1i6@C8 zimFk*ka1bzyv129RaoPm{Dq;Mw!Fl3ngfVq0gFgNgp3L{P=bXhtr{sNQnVlQ@b^3Z zB)MdAZGe$u9%ZPI96$IU{O;DwPmH@sp%~EqV%r}>KwuZBS8ew3a zt`axE!67hQpzJk|cL!U0`}a(vzaN4Xa;-eV4}Smv00v@9M??Vs0RI60puMM)00009 za7bBm000XT000XT0n*)m`~Uy|2XskIMF->v6%H&4#munc0001oNkl&|PvrI3bK+I5e)39??-Iv_jzZ3uffIYiU<@JxPUk;zgFy^Ae zsh^Mk4p3_@TF)I0aJ*b&(PXQ6fc0^UMU$=O0hT2fO}3f`n4h_5vIPJD0002Mmiqwr q0lBFA0QUjz1Ns}leE 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 literal 0 HcmV?d00001 diff --git a/Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/welded.png b/Resources/Textures/Constructible/Structures/Doors/firelock_glass.rsi/welded.png index c44b52966425ff9898d26dfdca5a2c36ae42783e..54de288e54d54f4cc7dc8c62a0127c981a821dcd 100644 GIT binary patch delta 226 zcmV<803H9m0=@!}Bmo7HB}9KXsLT0n=g-GE0Aq|X#{QY{wb9&Z(c!`VxBiDly-vgX zK7=rlWmCAWgQAq^XbrPafYv%UyRliL%Zu~5`CQ?b%T$yS##@Rd%R&m^I69l{1lwEG z9Sl)hTScs6D9=ZnT*Ip>j7K9(UQ-BRVrmK;MbRv`?kiecu<-Ew0)19{lmEbHs!}0o z+sF(9UKKh?u;MIZ@8mQ$7wiVq?P%Dg5{L+n>*B80!&SSToB1_LDGI}o{`@dw cj4}2T??$6i`jodk8UO$Q07*qoM6N<$f=5Pg(f|Me delta 225 zcmV<703QFo0=)u|Bmo4GB}9KJi08MRKOg4+j4{U8e`kDcGh_wa(3MY}V-V;(TsCSNP>J6{UpnmSV}WkODZ4&SpEo_7-&q zL)6w*5$hPr^ARW4@Tv;q(Fl{*6hfGongT~rG|R2~iWV0vJUqWZ-`-W^Kk%8VR7l!3 zGQ+_5@d=(+g-#NzILp{OInB)ly8(4O8g{7!B7)<(xa;+B)o$lzevDFz!Z4&?Kg<|o bjQuI^7?M)@s<$8700000NkvXXu0mjf&PQ#Z 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 index f13079c8dbe7353b8d360b94fba5e02bf597649d..d5b1d509b5c48ad1be5dc7c0d597f8736be036e1 100644 GIT binary patch delta 169 zcmV;a09OCO0>J{1Zh!FKY4Kq1;832P9QWlvc4{@*e0;(%bh_P$TyB<3Hp`6==%$Gf zV&LrRnkO&L&wA>8%^T&i)H)#(mPH739xh3J>Ht{oBKOZtyyYc);bRvZ{OcJ{1ZhtUhT0Gc0IFzR+$9?&aomx#cAD=J`oo+WGmzyP%&2l3Ix@jVW z7&yDS=E;lmvz~fi^G3NWwNA){Wf20Mhf7kQIslft$o+E@Z+Qt{_}B#p|N4r;g3VhH z(E18744p_f7^~O$up-DnJ2^)xY4O^AN8H^GJWx>-MNt$*Q3@30fBMy%^q2oIk@q$f XH?~(P2oKLN00000NkvXXu0mjfYF|oK From 2d76fbb3c4eb116e45322d45cf6e9ed4ef6dc3f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Aguilera=20Puerto?= Date: Sun, 6 Sep 2020 18:32:38 +0200 Subject: [PATCH 11/23] Big optimizations --- Content.Server/Atmos/TileAtmosphere.cs | 25 ++++--- .../Atmos/GridAtmosphereComponent.cs | 68 +++++++++++++++---- 2 files changed, 68 insertions(+), 25 deletions(-) diff --git a/Content.Server/Atmos/TileAtmosphere.cs b/Content.Server/Atmos/TileAtmosphere.cs index 18927a772e..eba6ad9c20 100644 --- a/Content.Server/Atmos/TileAtmosphere.cs +++ b/Content.Server/Atmos/TileAtmosphere.cs @@ -67,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; } @@ -112,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) { @@ -868,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) @@ -887,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); } @@ -902,7 +907,7 @@ namespace Content.Server.Atmos return; } - if (!other.BlocksAir) + if (!other.BlocksAllAir) { other.Air.TemperatureShare(Air, Atmospherics.WindowHeatTransferCoefficient); } @@ -953,7 +958,7 @@ namespace Content.Server.Atmos public AtmosDirection ConductivityDirections() { - if(BlocksAir) + if(BlocksAllAir) { if(_archivedCycle < _gridAtmosphereComponent.UpdateCounter) Archive(_gridAtmosphereComponent.UpdateCounter); @@ -1150,7 +1155,7 @@ namespace Content.Server.Atmos _adjacentTiles[direction.ToIndex()] = adjacent; adjacent?.UpdateAdjacent(direction.GetOpposite()); - if (adjacent != null && !_gridAtmosphereComponent.IsAirBlocked(adjacent.GridIndices, direction.GetOpposite())) + if (adjacent != null && !BlockedAirflow.HasFlag(direction) && !_gridAtmosphereComponent.IsAirBlocked(adjacent.GridIndices, direction.GetOpposite())) { _adjacentBits |= direction; } @@ -1161,7 +1166,7 @@ namespace Content.Server.Atmos { _adjacentTiles[direction.ToIndex()] = _gridAtmosphereComponent.GetTile(GridIndices.Offset(direction.ToDirection())); - if (!_gridAtmosphereComponent.IsAirBlocked(GridIndices.Offset(direction.ToDirection()), direction.GetOpposite())) + if (!BlockedAirflow.HasFlag(direction) && !_gridAtmosphereComponent.IsAirBlocked(GridIndices.Offset(direction.ToDirection()), direction.GetOpposite())) { _adjacentBits |= direction; } diff --git a/Content.Server/GameObjects/Components/Atmos/GridAtmosphereComponent.cs b/Content.Server/GameObjects/Components/Atmos/GridAtmosphereComponent.cs index a485659b6e..0d203f3330 100644 --- a/Content.Server/GameObjects/Components/Atmos/GridAtmosphereComponent.cs +++ b/Content.Server/GameObjects/Components/Atmos/GridAtmosphereComponent.cs @@ -9,10 +9,12 @@ 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.Map; using Robust.Shared.Serialization; @@ -223,20 +225,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(); @@ -283,6 +284,7 @@ namespace Content.Server.GameObjects.Components.Atmos [MethodImpl(MethodImplOptions.AggressiveInlining)] public virtual void AddActiveTile(TileAtmosphere? tile) { + // TODO ATMOS Optimization: Cache the grid Id for faster superconduction. Do the same for all the other ones. if (!Owner.TryGetComponent(out IMapGridComponent? mapGrid)) return; if (tile?.GridIndex != mapGrid.Grid.Index) return; tile.Excited = true; @@ -404,8 +406,16 @@ namespace Content.Server.GameObjects.Components.Atmos /// public bool IsAirBlocked(MapIndices indices, AtmosDirection direction = AtmosDirection.All) { - var ac = GetObstructingComponent(indices); - return ac != null && ac.AirBlocked && ac.AirBlockedDirection.HasFlag(direction); + foreach (var obstructingComponent in GetObstructingComponents(indices)) + { + if (!obstructingComponent.AirBlocked) + continue; + + if (obstructingComponent.AirBlockedDirection.HasFlag(direction)) + return true; + } + + return false; } /// @@ -769,17 +779,45 @@ 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; + if (!Owner.TryGetComponent(out IMapGridComponent? mapGrid)) return Enumerable.Empty(); - foreach (var v in mapGrid.Grid.GetSnapGridCell(indices, SnapGridOffset.Center)) + var gridLookup = EntitySystem.Get(); + + var list = new List(); + + foreach (var v in gridLookup.GetEntitiesIntersecting(mapGrid.GridIndex, 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() From c3858e6151fd6c246cd8ffcf4eced623f969ce79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Aguilera=20Puerto?= Date: Sun, 6 Sep 2020 19:08:30 +0200 Subject: [PATCH 12/23] Optimize even further --- .../Atmos/GridAtmosphereComponent.cs | 37 +++++++------------ 1 file changed, 13 insertions(+), 24 deletions(-) diff --git a/Content.Server/GameObjects/Components/Atmos/GridAtmosphereComponent.cs b/Content.Server/GameObjects/Components/Atmos/GridAtmosphereComponent.cs index 0d203f3330..11f2e91a78 100644 --- a/Content.Server/GameObjects/Components/Atmos/GridAtmosphereComponent.cs +++ b/Content.Server/GameObjects/Components/Atmos/GridAtmosphereComponent.cs @@ -54,6 +54,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; @@ -157,11 +158,9 @@ 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() @@ -173,7 +172,9 @@ namespace Content.Server.GameObjects.Components.Atmos public override void OnAdd() { base.OnAdd(); - RepopulateTiles(); + + if (Owner.TryGetComponent(out IMapGridComponent? mapGrid)) + _gridId = mapGrid.GridIndex; } public virtual void RepopulateTiles() @@ -201,15 +202,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); 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; } @@ -263,9 +262,8 @@ namespace Content.Server.GameObjects.Components.Atmos /// 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; @@ -284,9 +282,7 @@ namespace Content.Server.GameObjects.Components.Atmos [MethodImpl(MethodImplOptions.AggressiveInlining)] public virtual void AddActiveTile(TileAtmosphere? tile) { - // TODO ATMOS Optimization: Cache the grid Id for faster superconduction. Do the same for all the other ones. - 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); } @@ -305,8 +301,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); } @@ -320,8 +315,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); } @@ -335,8 +329,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); } @@ -390,14 +383,12 @@ 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; @@ -781,13 +772,11 @@ namespace Content.Server.GameObjects.Components.Atmos private IEnumerable GetObstructingComponents(MapIndices indices) { - if (!Owner.TryGetComponent(out IMapGridComponent? mapGrid)) return Enumerable.Empty(); - var gridLookup = EntitySystem.Get(); var list = new List(); - foreach (var v in gridLookup.GetEntitiesIntersecting(mapGrid.GridIndex, indices)) + foreach (var v in gridLookup.GetEntitiesIntersecting(_gridId, indices)) { if (v.TryGetComponent(out var ac)) list.Add(ac); From 2aa1486b134281ad23163028f0e7e7cc1d6320c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Aguilera=20Puerto?= Date: Mon, 7 Sep 2020 13:57:04 +0200 Subject: [PATCH 13/23] Support for non-fulltile airblockers rotating --- .../Components/Atmos/AirtightComponent.cs | 37 ++++++++++++++++ .../Components/Atmos/FirelockComponent.cs | 13 ++++-- Content.Shared/Atmos/AtmosDirection.cs | 43 +++++++++++++++++++ 3 files changed, 89 insertions(+), 4 deletions(-) diff --git a/Content.Server/GameObjects/Components/Atmos/AirtightComponent.cs b/Content.Server/GameObjects/Components/Atmos/AirtightComponent.cs index dce60bf811..0f4bd50457 100644 --- a/Content.Server/GameObjects/Components/Atmos/AirtightComponent.cs +++ b/Content.Server/GameObjects/Components/Atmos/AirtightComponent.cs @@ -1,4 +1,5 @@ #nullable enable +using System; using Content.Server.GameObjects.EntitySystems; using Content.Shared.Atmos; using Robust.Server.Interfaces.GameObjects; @@ -10,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; @@ -30,6 +32,12 @@ namespace Content.Server.GameObjects.Components.Atmos private bool _airBlocked = true; private bool _fixVacuum = false; + [ViewVariables] + private bool _rotateAirBlocked = true; + + [ViewVariables] + private bool _fixAirBlockedDirectionInitialize = true; + [ViewVariables(VVAccess.ReadWrite)] public bool AirBlocked { @@ -63,6 +71,8 @@ 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() @@ -75,9 +85,36 @@ namespace Content.Server.GameObjects.Components.Atmos 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.Zero, Owner.Transform.LocalRotation)); + UpdatePosition(); } + private void RotateEvent(RotateEvent ev) + { + if (!_rotateAirBlocked || ev.Sender != Owner || ev.NewRotation == ev.OldRotation) + return; + + var diff = ev.NewRotation - ev.OldRotation; + + var newAirBlockedDirs = AtmosDirection.Invalid; + + // When we make multiZ atmos, special case this. + for (int i = 0; i < Atmospherics.Directions; i++) + { + var direction = (AtmosDirection) 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)) diff --git a/Content.Server/GameObjects/Components/Atmos/FirelockComponent.cs b/Content.Server/GameObjects/Components/Atmos/FirelockComponent.cs index 03ec350359..b6c416ca97 100644 --- a/Content.Server/GameObjects/Components/Atmos/FirelockComponent.cs +++ b/Content.Server/GameObjects/Components/Atmos/FirelockComponent.cs @@ -35,12 +35,17 @@ namespace Content.Server.GameObjects.Components.Atmos { base.Startup(); - var airtightComponent = Owner.EnsureComponent(); - var collidableComponent = Owner.GetComponent(); + if (Owner.TryGetComponent(out AirtightComponent airtightComponent)) + { + airtightComponent.AirBlocked = false; + } + + if (Owner.TryGetComponent(out ICollidableComponent collidableComponent)) + { + collidableComponent.Hard = false; + } Safety = false; - airtightComponent.AirBlocked = false; - collidableComponent.Hard = false; if (Occludes && Owner.TryGetComponent(out OccluderComponent occluder)) { diff --git a/Content.Shared/Atmos/AtmosDirection.cs b/Content.Shared/Atmos/AtmosDirection.cs index c3991df998..aab6f1b7ad 100644 --- a/Content.Shared/Atmos/AtmosDirection.cs +++ b/Content.Shared/Atmos/AtmosDirection.cs @@ -77,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)), + }; + } + + /// + /// 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! From 3e87cfa7143d0bdbe84060a3ef5bfb3e55634cc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Aguilera=20Puerto?= Date: Mon, 7 Sep 2020 17:45:46 +0200 Subject: [PATCH 14/23] whoops. --- .../GameObjects/Components/Atmos/AirtightComponent.cs | 4 ++-- Content.Shared/Atmos/AtmosDirection.cs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Content.Server/GameObjects/Components/Atmos/AirtightComponent.cs b/Content.Server/GameObjects/Components/Atmos/AirtightComponent.cs index 0f4bd50457..cec4a0b38c 100644 --- a/Content.Server/GameObjects/Components/Atmos/AirtightComponent.cs +++ b/Content.Server/GameObjects/Components/Atmos/AirtightComponent.cs @@ -95,7 +95,7 @@ namespace Content.Server.GameObjects.Components.Atmos private void RotateEvent(RotateEvent ev) { - if (!_rotateAirBlocked || ev.Sender != Owner || ev.NewRotation == ev.OldRotation) + if (!_rotateAirBlocked || ev.Sender != Owner || ev.NewRotation == ev.OldRotation || AirBlockedDirection == AtmosDirection.Invalid) return; var diff = ev.NewRotation - ev.OldRotation; @@ -105,7 +105,7 @@ namespace Content.Server.GameObjects.Components.Atmos // When we make multiZ atmos, special case this. for (int i = 0; i < Atmospherics.Directions; i++) { - var direction = (AtmosDirection) i; + var direction = (AtmosDirection) (1 << i); if (!AirBlockedDirection.HasFlag(direction)) continue; var angle = direction.ToAngle(); angle += diff; diff --git a/Content.Shared/Atmos/AtmosDirection.cs b/Content.Shared/Atmos/AtmosDirection.cs index aab6f1b7ad..fa0f36cc8f 100644 --- a/Content.Shared/Atmos/AtmosDirection.cs +++ b/Content.Shared/Atmos/AtmosDirection.cs @@ -96,7 +96,7 @@ namespace Content.Shared.Atmos AtmosDirection.SouthWest => Angle.FromDegrees(225), AtmosDirection.SouthEast => Angle.FromDegrees(315), - _ => throw new ArgumentOutOfRangeException(nameof(direction)), + _ => throw new ArgumentOutOfRangeException(nameof(direction), $"It was {direction}."), }; } From 511147f299a3c7283cbae7335f09a013b1552915 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Aguilera=20Puerto?= Date: Tue, 8 Sep 2020 15:20:58 +0200 Subject: [PATCH 15/23] Adds edge firelocks --- .../Components/Atmos/AirtightComponent.cs | 2 +- .../Components/Doors/ServerDoorComponent.cs | 6 +- .../Entities/Constructible/Doors/firelock.yml | 32 ++ .../Doors/edge_door_hazard.rsi/alert_cold.png | Bin 0 -> 251 bytes .../Doors/edge_door_hazard.rsi/alert_hot.png | Bin 0 -> 258 bytes .../Doors/edge_door_hazard.rsi/bolted.png | Bin 0 -> 96 bytes .../Doors/edge_door_hazard.rsi/closed.png | Bin 0 -> 1590 bytes .../edge_door_hazard.rsi/closed_unlit.png | Bin 0 -> 96 bytes .../Doors/edge_door_hazard.rsi/closing.png | Bin 0 -> 4048 bytes .../edge_door_hazard.rsi/closing_unlit.png | Bin 0 -> 179 bytes .../Doors/edge_door_hazard.rsi/deny.png | Bin 0 -> 1590 bytes .../Doors/edge_door_hazard.rsi/deny_unlit.png | Bin 0 -> 96 bytes .../Doors/edge_door_hazard.rsi/door_spark.png | Bin 0 -> 5285 bytes .../Doors/edge_door_hazard.rsi/locked.png | Bin 0 -> 1590 bytes .../Doors/edge_door_hazard.rsi/meta.json | 430 ++++++++++++++++++ .../Doors/edge_door_hazard.rsi/open.png | Bin 0 -> 805 bytes .../Doors/edge_door_hazard.rsi/opening.png | Bin 0 -> 4020 bytes .../edge_door_hazard.rsi/opening_unlit.png | Bin 0 -> 179 bytes .../Doors/edge_door_hazard.rsi/palert.png | Bin 0 -> 468 bytes .../edge_door_hazard.rsi/panel_closing.png | Bin 0 -> 343 bytes .../Doors/edge_door_hazard.rsi/panel_open.png | Bin 0 -> 193 bytes .../edge_door_hazard.rsi/panel_opening.png | Bin 0 -> 329 bytes .../Doors/edge_door_hazard.rsi/welded.png | Bin 0 -> 359 bytes .../edge_door_hazard.rsi/welded_open.png | Bin 0 -> 1335 bytes 24 files changed, 467 insertions(+), 3 deletions(-) create mode 100644 Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/alert_cold.png create mode 100644 Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/alert_hot.png create mode 100644 Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/bolted.png create mode 100644 Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/closed.png create mode 100644 Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/closed_unlit.png create mode 100644 Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/closing.png create mode 100644 Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/closing_unlit.png create mode 100644 Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/deny.png create mode 100644 Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/deny_unlit.png create mode 100644 Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/door_spark.png create mode 100644 Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/locked.png create mode 100644 Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/meta.json create mode 100644 Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/open.png create mode 100644 Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/opening.png create mode 100644 Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/opening_unlit.png create mode 100644 Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/palert.png create mode 100644 Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/panel_closing.png create mode 100644 Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/panel_open.png create mode 100644 Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/panel_opening.png create mode 100644 Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/welded.png create mode 100644 Resources/Textures/Constructible/Structures/Doors/edge_door_hazard.rsi/welded_open.png diff --git a/Content.Server/GameObjects/Components/Atmos/AirtightComponent.cs b/Content.Server/GameObjects/Components/Atmos/AirtightComponent.cs index cec4a0b38c..0069a49971 100644 --- a/Content.Server/GameObjects/Components/Atmos/AirtightComponent.cs +++ b/Content.Server/GameObjects/Components/Atmos/AirtightComponent.cs @@ -88,7 +88,7 @@ namespace Content.Server.GameObjects.Components.Atmos Owner.EntityManager.EventBus.SubscribeEvent(EventSource.Local, this, RotateEvent); if(_fixAirBlockedDirectionInitialize) - RotateEvent(new RotateEvent(Owner, Angle.Zero, Owner.Transform.LocalRotation)); + RotateEvent(new RotateEvent(Owner, Angle.South, Owner.Transform.LocalRotation)); UpdatePosition(); } diff --git a/Content.Server/GameObjects/Components/Doors/ServerDoorComponent.cs b/Content.Server/GameObjects/Components/Doors/ServerDoorComponent.cs index 5bf56df8a8..8d9cb7df08 100644 --- a/Content.Server/GameObjects/Components/Doors/ServerDoorComponent.cs +++ b/Content.Server/GameObjects/Components/Doors/ServerDoorComponent.cs @@ -84,6 +84,7 @@ namespace Content.Server.GameObjects.Components.Doors private bool _isWeldedShut; private bool _canWeldShut = true; + private bool _canCrush = true; public override void ExposeData(ObjectSerializer serializer) { @@ -91,6 +92,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() @@ -367,7 +369,7 @@ namespace Content.Server.GameObjects.Components.Doors { 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; @@ -386,7 +388,7 @@ namespace Content.Server.GameObjects.Components.Doors Timer.Spawn(CloseTimeOne, async () => { - if (shouldCheckCrush) + if (shouldCheckCrush && _canCrush) { CheckCrush(); } diff --git a/Resources/Prototypes/Entities/Constructible/Doors/firelock.yml b/Resources/Prototypes/Entities/Constructible/Doors/firelock.yml index a4abf989ee..e7bf98f41c 100644 --- a/Resources/Prototypes/Entities/Constructible/Doors/firelock.yml +++ b/Resources/Prototypes/Entities/Constructible/Doors/firelock.yml @@ -74,3 +74,35 @@ 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 0000000000000000000000000000000000000000..c18f592c9f02f7bc8e8e21c502d87771b5147872 GIT binary patch literal 251 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD1|%QND7OGohdf;zLn`LHy|t0|kbwYefV%cU zpLxo~29syL)bLsofwUPgg&ebxsLQ0DcKtu>b%7 literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..3a572356dc6df4b579a67e59c819a422f5eafeb2 GIT binary patch literal 258 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD1|%QND7OGoCp}#pLn`LHy|t0I*+78xg0l5R zWB*@Yd=3U}xV%&$)a8;x5y$@Us7+svo;-H+eN+Fkj*qo(_ifx(&M&>Jqpi^oYTT6l3mX5IcDyH+&D*=28Qrus$nmDVtYgr+Ar*7p9%SSN@(wNd?w`wN fz5vKX1`XxR4h{^A{hv+-f`mO?{an^LB{Ts5qcarg literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..8968f68da9af508d6aa6a87ce737d82803197ad2 GIT binary patch literal 1590 zcmV-62Fdw}P)kFCm@+j0(ik{TLrdld#$al-cTm&tv%4DUY2Efwry`} z%}^%nwYIi;wrzV2!KqpuuItj<(?jBrA!U|jVObV4V~xy=H4=$Lq%0DN_~ZbNIHP$I9)S9z{OLKtIFqhud+}q z2B_gHAkKik&d{dzv2EL)Wm#J~H~Kn5@(d_%yc(f01b+Ty`CvXj+D&ZjL|<4t(SPb5 zmG6K2*+Cq~;qTiE8(wq$sy`Ig+yJoN2un}(M5kDlJV47Is-uoN>ZqfRI_jvSjyme7 zW1GW(ce@-7zez)4e@7G1Xq3rcA8c@q2h1>#E4QUZ_<`lM^nLRS{-44bUMvIF3<4U`yA~k4~qt~UF%NtOuHCP zKIHU;0|4B)vbe!DFn;?v{kg-W)1^>YYgEkx#3=b~kEnrdmj`Hn0O97Y>q?n8Cxihu z!qEk-!%^W`xm=Fko*ua^hDSz7r_-=DpMM=krxCOoKy0h8kImB-yF~M1i22wmEhjw& za(R&rlF#S){^UO-6pnf91vjQkoY~n~osX#xsZ{Ev(Pj9o;iXb3FO^Dp!)J|`MvGJ` zRr5%(WejD)-pXVt#g0TGzOXqn*60mo!ro9O?9Gfd`ciAbTbT?A18RfT`vGcIdHKu= zuItKFTfk8`(>KGugRt^5bRf_R5+W@YSXv9W0!D+uqpZ8m2s)wN0Ov=$fpXy_lBU6I zm&_3cvt0lj?S2nH7EfZWPG~nkEZPE;;<{Q}#G)-SK~gzt@g?Lsq1^y#)n}Tf{4Y1f zX@PVGtFgb^|Oqb3i!?sB+-}f^+A};yR9Q zXg7e`LsU=rO#3zI0cy3Va@4iD5Lg%#`+9uznUo0+5U7j-K_CzV*tQL@uEV63$+m5; zixfdXy8*;qKJZ6@*0{fR7_`1~nw=f_4KqjzghP@I?X3vWP~b<-7c^;OK^S z1BhFkY7`K6{DlXI>~MVanUA9mTy!DuTEKN(S>LN?fXV>^>j4C20I{z(5(UJ7B?tso z3{{@+gV`?W0iqbHa9$M#JvS=2rLYW6W)7K*2k%m2kfX?pi(*0H2Lt;=koVx#ruUq!50Opea72{*2&O7 z?l4gLF0i;8ATWOWIRg_P0j00A3aC8s1t++t?HRQiAdyHgkb}O?Y1)o7(EKFC{O(oq ze|hw;O^E^eCtxTuL*kGjITL@rkdx$l_x`5_n3|d*nN0HY-9>s2Dud5kBfk3q$z+lr oZY|QgPvP7h3FHpJJ3k)(51VRju0pN1f&c&j07*qoM6N<$f`noH*#H0l literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..0858c19f0521b74f4a058fbddc280ea48a5751bb GIT binary patch literal 96 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=>Ygr+Ar*7p9%SSN@(wNd?w`wN fz5vKX1`XxR4h{^A{hv+-f`mO?{an^LB{Ts5qcarg literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..689f02afa23c5884dfa043dcd27483ae2b35fabe GIT binary patch literal 4048 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 literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..92b5018fb9c1c8dff2e5dd4e58eb5d3c95e6c53d GIT binary patch literal 179 zcmeAS@N?(olHy`uVBq!ia0vp^3qY8I4M=vMPuB%fRh}-6Ar*7p9yDYG@(wNd>YvNY ezW~UjHK;I{u%3Z2b-VOxkWHShelF{r5}E*j1{E~` literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..8968f68da9af508d6aa6a87ce737d82803197ad2 GIT binary patch literal 1590 zcmV-62Fdw}P)kFCm@+j0(ik{TLrdld#$al-cTm&tv%4DUY2Efwry`} z%}^%nwYIi;wrzV2!KqpuuItj<(?jBrA!U|jVObV4V~xy=H4=$Lq%0DN_~ZbNIHP$I9)S9z{OLKtIFqhud+}q z2B_gHAkKik&d{dzv2EL)Wm#J~H~Kn5@(d_%yc(f01b+Ty`CvXj+D&ZjL|<4t(SPb5 zmG6K2*+Cq~;qTiE8(wq$sy`Ig+yJoN2un}(M5kDlJV47Is-uoN>ZqfRI_jvSjyme7 zW1GW(ce@-7zez)4e@7G1Xq3rcA8c@q2h1>#E4QUZ_<`lM^nLRS{-44bUMvIF3<4U`yA~k4~qt~UF%NtOuHCP zKIHU;0|4B)vbe!DFn;?v{kg-W)1^>YYgEkx#3=b~kEnrdmj`Hn0O97Y>q?n8Cxihu z!qEk-!%^W`xm=Fko*ua^hDSz7r_-=DpMM=krxCOoKy0h8kImB-yF~M1i22wmEhjw& za(R&rlF#S){^UO-6pnf91vjQkoY~n~osX#xsZ{Ev(Pj9o;iXb3FO^Dp!)J|`MvGJ` zRr5%(WejD)-pXVt#g0TGzOXqn*60mo!ro9O?9Gfd`ciAbTbT?A18RfT`vGcIdHKu= zuItKFTfk8`(>KGugRt^5bRf_R5+W@YSXv9W0!D+uqpZ8m2s)wN0Ov=$fpXy_lBU6I zm&_3cvt0lj?S2nH7EfZWPG~nkEZPE;;<{Q}#G)-SK~gzt@g?Lsq1^y#)n}Tf{4Y1f zX@PVGtFgb^|Oqb3i!?sB+-}f^+A};yR9Q zXg7e`LsU=rO#3zI0cy3Va@4iD5Lg%#`+9uznUo0+5U7j-K_CzV*tQL@uEV63$+m5; zixfdXy8*;qKJZ6@*0{fR7_`1~nw=f_4KqjzghP@I?X3vWP~b<-7c^;OK^S z1BhFkY7`K6{DlXI>~MVanUA9mTy!DuTEKN(S>LN?fXV>^>j4C20I{z(5(UJ7B?tso z3{{@+gV`?W0iqbHa9$M#JvS=2rLYW6W)7K*2k%m2kfX?pi(*0H2Lt;=koVx#ruUq!50Opea72{*2&O7 z?l4gLF0i;8ATWOWIRg_P0j00A3aC8s1t++t?HRQiAdyHgkb}O?Y1)o7(EKFC{O(oq ze|hw;O^E^eCtxTuL*kGjITL@rkdx$l_x`5_n3|d*nN0HY-9>s2Dud5kBfk3q$z+lr oZY|QgPvP7h3FHpJJ3k)(51VRju0pN1f&c&j07*qoM6N<$f`noH*#H0l literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..0858c19f0521b74f4a058fbddc280ea48a5751bb GIT binary patch literal 96 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=>Ygr+Ar*7p9%SSN@(wNd?w`wN fz5vKX1`XxR4h{^A{hv+-f`mO?{an^LB{Ts5qcarg literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..59ff3aed71d12ed44c41004be9add54df258d851 GIT binary patch literal 5285 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 literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..8968f68da9af508d6aa6a87ce737d82803197ad2 GIT binary patch literal 1590 zcmV-62Fdw}P)kFCm@+j0(ik{TLrdld#$al-cTm&tv%4DUY2Efwry`} z%}^%nwYIi;wrzV2!KqpuuItj<(?jBrA!U|jVObV4V~xy=H4=$Lq%0DN_~ZbNIHP$I9)S9z{OLKtIFqhud+}q z2B_gHAkKik&d{dzv2EL)Wm#J~H~Kn5@(d_%yc(f01b+Ty`CvXj+D&ZjL|<4t(SPb5 zmG6K2*+Cq~;qTiE8(wq$sy`Ig+yJoN2un}(M5kDlJV47Is-uoN>ZqfRI_jvSjyme7 zW1GW(ce@-7zez)4e@7G1Xq3rcA8c@q2h1>#E4QUZ_<`lM^nLRS{-44bUMvIF3<4U`yA~k4~qt~UF%NtOuHCP zKIHU;0|4B)vbe!DFn;?v{kg-W)1^>YYgEkx#3=b~kEnrdmj`Hn0O97Y>q?n8Cxihu z!qEk-!%^W`xm=Fko*ua^hDSz7r_-=DpMM=krxCOoKy0h8kImB-yF~M1i22wmEhjw& za(R&rlF#S){^UO-6pnf91vjQkoY~n~osX#xsZ{Ev(Pj9o;iXb3FO^Dp!)J|`MvGJ` zRr5%(WejD)-pXVt#g0TGzOXqn*60mo!ro9O?9Gfd`ciAbTbT?A18RfT`vGcIdHKu= zuItKFTfk8`(>KGugRt^5bRf_R5+W@YSXv9W0!D+uqpZ8m2s)wN0Ov=$fpXy_lBU6I zm&_3cvt0lj?S2nH7EfZWPG~nkEZPE;;<{Q}#G)-SK~gzt@g?Lsq1^y#)n}Tf{4Y1f zX@PVGtFgb^|Oqb3i!?sB+-}f^+A};yR9Q zXg7e`LsU=rO#3zI0cy3Va@4iD5Lg%#`+9uznUo0+5U7j-K_CzV*tQL@uEV63$+m5; zixfdXy8*;qKJZ6@*0{fR7_`1~nw=f_4KqjzghP@I?X3vWP~b<-7c^;OK^S z1BhFkY7`K6{DlXI>~MVanUA9mTy!DuTEKN(S>LN?fXV>^>j4C20I{z(5(UJ7B?tso z3{{@+gV`?W0iqbHa9$M#JvS=2rLYW6W)7K*2k%m2kfX?pi(*0H2Lt;=koVx#ruUq!50Opea72{*2&O7 z?l4gLF0i;8ATWOWIRg_P0j00A3aC8s1t++t?HRQiAdyHgkb}O?Y1)o7(EKFC{O(oq ze|hw;O^E^eCtxTuL*kGjITL@rkdx$l_x`5_n3|d*nN0HY-9>s2Dud5kBfk3q$z+lr oZY|QgPvP7h3FHpJJ3k)(51VRju0pN1f&c&j07*qoM6N<$f`noH*#H0l literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..3f0b3ef549d656f987efc3beda0a057b5b8d68e4 GIT binary patch literal 805 zcmV+=1KRwFP)>n+%otg8B_z^Z?g&0f1EI+6y5B<@0%J zH>}viv>O)X^LY|NkQrCfZOmpf)T&iD1*Jdy22R01ty;xwHUql>0FcRMk$X|HMqbUUzZI~gm$_kCOr zPZ7sK*lt*KIXs2$`v8FWPM$aT_a5;0qQ-~xEB62;i8LCGMx)VaG#ZUYlW+{+gO{U1 z2&z;nMM< z2gp(Kdyl9AB<>!dT!8$mTR-vT(w7G86Qc^HqcOR%!Z1XwT16(C#dI=3(CNr6K)`ZV z|5l7j6O_?S{3p{!m??DBS|Ps>-K5s!mmvsf6|UfF!K# zL_8nBi8g>+05{qIZUNkA1GoinqYdB|z>PM5TL3rO0B!-?Xal$faH9?27Ql@*fLj1J ztUW>Yxfm21Am@SGINI_4KA(|j{)fSc(iPx14q745JRef2Xd?HV!uW8G=#FslcS;NZ z7d@cexFx4xtYUiCi`68#-|s8asMLVLU;x*3@vHlQ+UK>w=T!&3zZ{VR%NgR2s|VCR jt;KXVV^s0s$K!thCswIxxmdO|00000NkvXXu0mjf3_^Fc literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..7cf50771cdcdd981a02de393cbb2d743446421a2 GIT binary patch literal 4020 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 literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..92b5018fb9c1c8dff2e5dd4e58eb5d3c95e6c53d GIT binary patch literal 179 zcmeAS@N?(olHy`uVBq!ia0vp^3qY8I4M=vMPuB%fRh}-6Ar*7p9yDYG@(wNd>YvNY ezW~UjHK;I{u%3Z2b-VOxkWHShelF{r5}E*j1{E~` literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..3d6343358e2d353eeec4585c162e7de57121782f GIT binary patch literal 468 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD1|%QND7Ro>V4Usg;uumf=k2XPzZL_5V;>h) z%O9Sc{)yp-*1lcr26sH>_k2It!!Nqn!#uIIZu8s!-#2**U($0vX)sq!Av4F>Ufz1o zU)kU9O|NcNyit>r4~zPs z@3$E3pW7s#OqINSVfM|F>ec5h*BAMArLs7@SrFI2z5aXm;oWJDotCRz#GZ)UX9PMH z1U5{a{50d##+e%YDp}W8+%{TuU-s3uo|xh)*YFkzMuF~J%`K@J6Iow=kW~nCjThi= zy|6y~(UaF#SHwkgykTH)I2d$a_sT+}8FoC+&81=Q)jSQc$QFY+hjj@l?N?IHSi zjtKK<{sX@Y?^7GbEAyP7#KqOnxV3hN8aSW-L^Y*r57L%g@>xC}A z3Hv&&KdLo4D5MK2ok?X;eBkR;cJGMmk#kCcY(AS#`EY)g>)<%_-zRbR%08euK+tw! zTF~ZA>X8R)3>#8FX2Zb$wYp2w-knVU_Cqs&h1}$hj<hZcpxtMC#10s!RRy;u-(lWFf(gQU1Tr{k)uI+k5XOavZyvUt*}mq#1G7gO%sK{!+EaHX%dbA278C8|dw;V0!qbOyy;rXP+`n3X z&wknWw}N;Usr!CE3^ecWXO(BOFF*bJ^5KlDxiROS*Ib+TCn7f2-8w6;Bi`Zv9e$vh b2{Cqz({Gn8Fx05L1+v1^)z4*}Q$iB}3+IzJ literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..5f3bfeae15880d37195a14cbfdcb01447290f46c GIT binary patch literal 193 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJ4o?@ykcv6U2@U=;9laSW-L^Y)gb*WmyGwg;Iy z9(k8yU;4&y&T|dmshHNJP$69S+;`Uov)CyuS(oNkF8=o0tlx&||A#oE)tx|d7#JEh z&DxcB{M)f_|DE5hjPiOGcKl%XSG{SgD}R3}x>@%6ZkqAzT^(!g_=V-UxX53-Qu=$( z4~ab=zU`W8T56k_c=~G1hoe(Z$ez}pDJ^JdU$?vIPlRo7S2F4x(g z@=iSVzV*9$)#}8scPpj5R_@E6@~-jb&YQouEv_@4F#Ev_b_t01p&0r3M{JqfyZiuG znP-oC)t;?TQj(Lm+x*%hI`l}Q-8`4)cbYfP?DKoZG-)SX7nJdDn(ZH-I+j^)XXb!J NJYD@<);T3K0RT6Fi?RR! literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..e6bd2ff64f03ec224206ad077cd505fe615d28ab GIT binary patch literal 359 zcmV-t0hs=YP)Zq}6vlCLX^#&j7$`Dh|?nD|8HW*U_YK^ z@#P7Ts7`C=pH)-4-+sGUgE1~FM3$Dj^}yL` zVHYgTbYWEjYmznwWD8akb=Bx3+Ag~`jdvf^H0op`Y;Pvb&gUtYxtTfV+_`h_`JNdD zHN;?lKl$eRb);5SAia3O_ymFEwzuK(@W`f9n3NwH;YmMs{Nrtl5I)jV;)& zcEeoA!)R?sG#UeIX+>C)7y$5ly+qFCFdvUIr?1&ieK*g-_i)78dHtlbU(c$r><(A9;dja9TGg#O~FU1ea+Fa@v2{wDtAY26VB4tU;! zLS_?*r6t@N8bE9zp?J=q=qGDi8KCK6u{}BcOmUgi(b3V-(b3V-(b3V-(ZRB>qI=6gq%vjY_lT~i^3-eBrHjc;Pn#wl`D9?xQN+EM03Y$iaxhnv*|#+ zGNk0(O~FU_o{zgjGt1U*X-vtvU!^c(ZN5}&GavGJ`s8taPK(ldUn#*rfDHEc*ThPo z8KF=}^8jdC9Zs#RpqJywxJtHJsk&R!RB{eDOqaEEl4^OJHJMQOs=4fOpCFKDN3XIe z5fuFdO&2j)Ce{9|xg&~%cU6ADfwq{U*)za!P=L$Bqf|XoqO;9P*AAK|S97kVvkTdD z3i9@j>N!5^w>mgiqQ{P=#s$ zI&HR!cY(=bIa574W^`7 t%--8GFHAgr@|dZakDF Date: Fri, 11 Sep 2020 12:52:40 +0200 Subject: [PATCH 16/23] Fix atmos bug with gasmixture serialization --- Content.Server/Atmos/GasMixture.cs | 4 ++++ 1 file changed, 4 insertions(+) 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) From 272a992011f4ff8af71efce99d87a2bc0ef67ec6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Aguilera=20Puerto?= Date: Fri, 11 Sep 2020 12:54:42 +0200 Subject: [PATCH 17/23] Redundant adjacent update --- .../GameObjects/Components/Atmos/GridAtmosphereComponent.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Content.Server/GameObjects/Components/Atmos/GridAtmosphereComponent.cs b/Content.Server/GameObjects/Components/Atmos/GridAtmosphereComponent.cs index 11f2e91a78..aa2b3e859f 100644 --- a/Content.Server/GameObjects/Components/Atmos/GridAtmosphereComponent.cs +++ b/Content.Server/GameObjects/Components/Atmos/GridAtmosphereComponent.cs @@ -185,6 +185,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()) @@ -246,7 +248,6 @@ namespace Content.Server.GameObjects.Components.Atmos var otherIndices = indices.Offset(direction.ToDirection()); var otherTile = GetTile(otherIndices); AddActiveTile(otherTile); - otherTile?.UpdateAdjacent(direction.GetOpposite()); } } From afc784b2a22039bfadd9705eb00be62a67e02dfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Aguilera=20Puerto?= Date: Fri, 11 Sep 2020 13:34:01 +0200 Subject: [PATCH 18/23] ignored components --- Content.Client/IgnoredComponents.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Content.Client/IgnoredComponents.cs b/Content.Client/IgnoredComponents.cs index 7dea6c8738..783220aaf2 100644 --- a/Content.Client/IgnoredComponents.cs +++ b/Content.Client/IgnoredComponents.cs @@ -176,6 +176,8 @@ "ExtinguisherCabinet", "ExtinguisherCabinetFilled", "FireExtinguisher", + "Firelock", + "AtmosPlaque" }; } } From 218c5deed74bd0fa87a7f64d730b3f701f7d2811 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Aguilera=20Puerto?= Date: Fri, 11 Sep 2020 19:27:17 +0200 Subject: [PATCH 19/23] Add gas mixture tests --- .../Tests/Atmos/GasMixtureTest.cs | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 Content.IntegrationTests/Tests/Atmos/GasMixtureTest.cs diff --git a/Content.IntegrationTests/Tests/Atmos/GasMixtureTest.cs b/Content.IntegrationTests/Tests/Atmos/GasMixtureTest.cs new file mode 100644 index 0000000000..a34ccd0ccc --- /dev/null +++ b/Content.IntegrationTests/Tests/Atmos/GasMixtureTest.cs @@ -0,0 +1,84 @@ +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)] + 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(); + } + } +} From ca7cffbc48450dc7d09527ef355a0f5ef69e4492 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Aguilera=20Puerto?= Date: Fri, 11 Sep 2020 19:59:45 +0200 Subject: [PATCH 20/23] new test case for removeratio test --- Content.IntegrationTests/Tests/Atmos/GasMixtureTest.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Content.IntegrationTests/Tests/Atmos/GasMixtureTest.cs b/Content.IntegrationTests/Tests/Atmos/GasMixtureTest.cs index a34ccd0ccc..0b7f2f9e2d 100644 --- a/Content.IntegrationTests/Tests/Atmos/GasMixtureTest.cs +++ b/Content.IntegrationTests/Tests/Atmos/GasMixtureTest.cs @@ -51,6 +51,7 @@ namespace Content.IntegrationTests.Tests.Atmos [TestCase(0.75f)] [TestCase(1f)] [TestCase(0f)] + [TestCase(Atmospherics.BreathPercentage)] public async Task RemoveRatio(float ratio) { var server = StartServerDummyTicker(); From efcd29bff893184154055a6f55c0b85a226ef663 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Aguilera=20Puerto?= <6766154+Zumorica@users.noreply.github.com> Date: Sat, 12 Sep 2020 19:54:03 +0200 Subject: [PATCH 21/23] Apply suggestions from code review Co-authored-by: DrSmugleaf --- Content.Server/Atmos/TileAtmosphere.cs | 1 - .../GameObjects/Components/Atmos/AirtightComponent.cs | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Content.Server/Atmos/TileAtmosphere.cs b/Content.Server/Atmos/TileAtmosphere.cs index 899dca18be..ca463a5347 100644 --- a/Content.Server/Atmos/TileAtmosphere.cs +++ b/Content.Server/Atmos/TileAtmosphere.cs @@ -1093,7 +1093,6 @@ namespace Content.Server.Atmos private void ConsiderFirelocks(TileAtmosphere other) { - // TODO ATMOS firelocks! var reconsiderAdjacent = false; foreach (var entity in GridIndices.GetEntitiesInTileFast(GridIndex)) diff --git a/Content.Server/GameObjects/Components/Atmos/AirtightComponent.cs b/Content.Server/GameObjects/Components/Atmos/AirtightComponent.cs index 0069a49971..5d1f52de4d 100644 --- a/Content.Server/GameObjects/Components/Atmos/AirtightComponent.cs +++ b/Content.Server/GameObjects/Components/Atmos/AirtightComponent.cs @@ -102,7 +102,7 @@ namespace Content.Server.GameObjects.Components.Atmos var newAirBlockedDirs = AtmosDirection.Invalid; - // When we make multiZ atmos, special case this. + // TODO ATMOS MULTIZ When we make multiZ atmos, special case this. for (int i = 0; i < Atmospherics.Directions; i++) { var direction = (AtmosDirection) (1 << i); From fa74e9f19ffa8fb399bef0deea966b22ef7f78fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Aguilera=20Puerto?= Date: Sat, 12 Sep 2020 20:10:56 +0200 Subject: [PATCH 22/23] address all reviews --- Content.Server/Atmos/TileAtmosphere.cs | 2 +- .../Components/Atmos/AirtightComponent.cs | 7 +++++-- .../Components/Atmos/FirelockComponent.cs | 5 ++--- .../Components/Atmos/GridAtmosphereComponent.cs | 2 ++ Content.Server/Utility/GridTileLookupHelpers.cs | 11 ++++++----- Content.Shared/Maps/TurfHelpers.cs | 12 ++++++------ 6 files changed, 22 insertions(+), 17 deletions(-) diff --git a/Content.Server/Atmos/TileAtmosphere.cs b/Content.Server/Atmos/TileAtmosphere.cs index ca463a5347..db1b89ee45 100644 --- a/Content.Server/Atmos/TileAtmosphere.cs +++ b/Content.Server/Atmos/TileAtmosphere.cs @@ -1101,7 +1101,7 @@ namespace Content.Server.Atmos reconsiderAdjacent |= firelock.EmergencyPressureStop(); } - foreach (var entity in other.GridIndices.GetEntitiesInTile(other.GridIndex)) + foreach (var entity in other.GridIndices.GetEntitiesInTileFast(other.GridIndex)) { if (!entity.TryGetComponent(out FirelockComponent firelock)) continue; reconsiderAdjacent |= firelock.EmergencyPressureStop(); diff --git a/Content.Server/GameObjects/Components/Atmos/AirtightComponent.cs b/Content.Server/GameObjects/Components/Atmos/AirtightComponent.cs index 5d1f52de4d..22c0783548 100644 --- a/Content.Server/GameObjects/Components/Atmos/AirtightComponent.cs +++ b/Content.Server/GameObjects/Components/Atmos/AirtightComponent.cs @@ -24,6 +24,7 @@ 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"; @@ -79,6 +80,8 @@ namespace Content.Server.GameObjects.Components.Atmos { base.Initialize(); + _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. @@ -140,7 +143,7 @@ namespace Content.Server.GameObjects.Components.Atmos UpdatePosition(_lastPosition.Item1, _lastPosition.Item2); if (_fixVacuum) - EntitySystem.Get().GetGridAtmosphere(_lastPosition.Item1)?.FixVacuum(_lastPosition.Item2); + _atmosphereSystem.GetGridAtmosphere(_lastPosition.Item1)?.FixVacuum(_lastPosition.Item2); } private void OnTransformMove() @@ -162,7 +165,7 @@ namespace Content.Server.GameObjects.Components.Atmos private void UpdatePosition(GridId gridId, MapIndices pos) { - var gridAtmos = EntitySystem.Get().GetGridAtmosphere(gridId); + var gridAtmos = _atmosphereSystem.GetGridAtmosphere(gridId); if (gridAtmos == null) return; diff --git a/Content.Server/GameObjects/Components/Atmos/FirelockComponent.cs b/Content.Server/GameObjects/Components/Atmos/FirelockComponent.cs index b6c416ca97..6ef8768e37 100644 --- a/Content.Server/GameObjects/Components/Atmos/FirelockComponent.cs +++ b/Content.Server/GameObjects/Components/Atmos/FirelockComponent.cs @@ -6,6 +6,7 @@ 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; @@ -17,8 +18,6 @@ namespace Content.Server.GameObjects.Components.Atmos [RegisterComponent] public class FirelockComponent : ServerDoorComponent, IInteractUsing, ICollideBehavior { - [Dependency] private IServerNotifyManager _notifyManager = default!; - public override string Name => "Firelock"; protected override TimeSpan CloseTimeOne => TimeSpan.FromSeconds(0.1f); @@ -87,7 +86,7 @@ namespace Content.Server.GameObjects.Components.Atmos if (State == DoorState.Closed) { if(holdingPressure) - _notifyManager.PopupMessage(Owner, eventArgs.User, "A gush of air blows in your face... Maybe you should reconsider."); + 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; diff --git a/Content.Server/GameObjects/Components/Atmos/GridAtmosphereComponent.cs b/Content.Server/GameObjects/Components/Atmos/GridAtmosphereComponent.cs index aa2b3e859f..b8a02bd904 100644 --- a/Content.Server/GameObjects/Components/Atmos/GridAtmosphereComponent.cs +++ b/Content.Server/GameObjects/Components/Atmos/GridAtmosphereComponent.cs @@ -16,6 +16,7 @@ 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; @@ -34,6 +35,7 @@ namespace Content.Server.GameObjects.Components.Atmos [Robust.Shared.IoC.Dependency] private ITileDefinitionManager _tileDefinitionManager = default!; [Robust.Shared.IoC.Dependency] private IServerEntityManager _serverEntityManager = default!; + /// /// Check current execution time every n instances processed. /// diff --git a/Content.Server/Utility/GridTileLookupHelpers.cs b/Content.Server/Utility/GridTileLookupHelpers.cs index 7d5223fe6e..2494815d2f 100644 --- a/Content.Server/Utility/GridTileLookupHelpers.cs +++ b/Content.Server/Utility/GridTileLookupHelpers.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +#nullable enable +using System.Collections.Generic; using System.Linq; using System.Runtime.CompilerServices; using Content.Shared.Maps; @@ -15,9 +16,9 @@ namespace Content.Server.Utility /// Helper that returns all entities in a turf very fast. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static IEnumerable GetEntitiesInTileFast(this TileRef turf) + public static IEnumerable GetEntitiesInTileFast(this TileRef turf, GridTileLookupSystem? gridTileLookup = null) { - var gridTileLookup = EntitySystem.Get(); + gridTileLookup ??= EntitySystem.Get(); return gridTileLookup.GetEntitiesIntersecting(turf.GridIndex, turf.GridIndices); } @@ -26,14 +27,14 @@ namespace Content.Server.Utility /// Helper that returns all entities in a turf. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static IEnumerable GetEntitiesInTileFast(this MapIndices indices, GridId gridId) + 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); + return GetEntitiesInTileFast(turf.Value, gridTileLookup); } } } diff --git a/Content.Shared/Maps/TurfHelpers.cs b/Content.Shared/Maps/TurfHelpers.cs index d059235264..7207647375 100644 --- a/Content.Shared/Maps/TurfHelpers.cs +++ b/Content.Shared/Maps/TurfHelpers.cs @@ -124,9 +124,9 @@ namespace Content.Shared.Maps /// Helper that returns all entities in a turf. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static IEnumerable GetEntitiesInTile(this TileRef turf, bool approximate = false) + 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); } @@ -134,27 +134,27 @@ namespace Content.Shared.Maps /// /// Helper that returns all entities in a turf. /// - public static IEnumerable GetEntitiesInTile(this EntityCoordinates coordinates, bool approximate = false) + 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); + 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) + 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); + return GetEntitiesInTile(turf.Value, approximate, entityManager); } /// From 4604122e910daccaa29cf33a287702fae0ebc71f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Aguilera=20Puerto?= Date: Sat, 12 Sep 2020 20:15:13 +0200 Subject: [PATCH 23/23] cache GridTileLookupSystem reference --- Content.Server/Atmos/TileAtmosphere.cs | 4 ++-- .../GameObjects/Components/Atmos/GridAtmosphereComponent.cs | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Content.Server/Atmos/TileAtmosphere.cs b/Content.Server/Atmos/TileAtmosphere.cs index db1b89ee45..6361574211 100644 --- a/Content.Server/Atmos/TileAtmosphere.cs +++ b/Content.Server/Atmos/TileAtmosphere.cs @@ -1095,13 +1095,13 @@ namespace Content.Server.Atmos { var reconsiderAdjacent = false; - foreach (var entity in GridIndices.GetEntitiesInTileFast(GridIndex)) + 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)) + foreach (var entity in other.GridIndices.GetEntitiesInTileFast(other.GridIndex, _gridAtmosphereComponent.GridTileLookupSystem)) { if (!entity.TryGetComponent(out FirelockComponent firelock)) continue; reconsiderAdjacent |= firelock.EmergencyPressureStop(); diff --git a/Content.Server/GameObjects/Components/Atmos/GridAtmosphereComponent.cs b/Content.Server/GameObjects/Components/Atmos/GridAtmosphereComponent.cs index b8a02bd904..f33e03fd64 100644 --- a/Content.Server/GameObjects/Components/Atmos/GridAtmosphereComponent.cs +++ b/Content.Server/GameObjects/Components/Atmos/GridAtmosphereComponent.cs @@ -35,6 +35,7 @@ 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. @@ -169,6 +170,8 @@ namespace Content.Server.GameObjects.Components.Atmos { base.Initialize(); RepopulateTiles(); + + GridTileLookupSystem = EntitySystem.Get(); } public override void OnAdd()