From 112f7d834656e8946a1d516c3f949d29ad9f7424 Mon Sep 17 00:00:00 2001 From: collinlunn <60152240+collinlunn@users.noreply.github.com> Date: Mon, 22 Feb 2021 19:18:30 -0700 Subject: [PATCH] Pipe visualizers (#3042) * modifies pipe sprites to look not connected * pipe connector sprites * PipeConnectorVisualizer * Remove pipe visualizer * Revert "Remove pipe visualizer" This reverts commit dc8da93f99f20aa55247c6a94d26c7a75a3d1782. * PipeDirection can be set with the sprite updating correctly * fixes meta files * removes unused vent/scrubber directions * OnConnectedDirectionsNeedsUpdating * comments + OnConnectedDirectionsNeedsUpdating gets called * fix connecteddirections bug * Combines ConnectedDirections sent to visualizer * fixes unconnected pipe sprites * Adds PipeConnectorVisualizer to other piping entities * code cleanup * Fixed bug with ConnectedDirections not being set correctly * diff fix * rotation simplification * Improves rsi serialization * enable nullable * wip * visualizer cleanup * nullable cleanup Co-authored-by: py01 --- .../Atmos/Piping/PipeConnectorVisualizer.cs | 86 +++++++ .../Components/Atmos/Piping/PipeVisualizer.cs | 41 ++-- .../Components/NodeContainer/Nodes/Node.cs | 6 +- .../NodeContainer/Nodes/PipeNode.cs | 221 +++++++++++++++--- .../Components/Atmos/SharedPipeComponent.cs | 29 ++- .../Constructible/Ground/gascanisterports.yml | 3 + .../Constructible/Ground/gasfilters.yml | 1 + .../Entities/Constructible/Ground/pipes.yml | 9 +- .../Entities/Constructible/Ground/pumps.yml | 1 + .../Constructible/Ground/scrubbers.yml | 1 + .../Entities/Constructible/Ground/vents.yml | 1 + .../Atmos/gascanisterport.rsi/meta.json | 1 - .../Constructible/Atmos/pipe.rsi/meta.json | 13 +- .../Constructible/Atmos/pipe.rsi/pipeBend.png | Bin 854 -> 3965 bytes .../Atmos/pipe.rsi/pipeConnectorEast.png | Bin 0 -> 1029 bytes .../Atmos/pipe.rsi/pipeConnectorNorth.png | Bin 0 -> 1113 bytes .../Atmos/pipe.rsi/pipeConnectorSouth.png | Bin 0 -> 1140 bytes .../Atmos/pipe.rsi/pipeConnectorWest.png | Bin 0 -> 1047 bytes .../Atmos/pipe.rsi/pipeFourway.png | Bin 538 -> 2244 bytes .../Constructible/Atmos/pipe.rsi/pipeHalf.png | Bin 469 -> 2417 bytes .../Atmos/pipe.rsi/pipeStraight.png | Bin 643 -> 3619 bytes .../Atmos/pipe.rsi/pipeTJunction.png | Bin 1218 -> 5708 bytes .../Atmos/scrubber.rsi/meta.json | 2 - .../Atmos/scrubber.rsi/scrubOff.png | Bin 6169 -> 2422 bytes .../Constructible/Atmos/vent.rsi/meta.json | 2 - .../Constructible/Atmos/vent.rsi/ventOff.png | Bin 6506 -> 1768 bytes 26 files changed, 343 insertions(+), 74 deletions(-) create mode 100644 Content.Client/GameObjects/Components/Atmos/Piping/PipeConnectorVisualizer.cs create mode 100644 Resources/Textures/Constructible/Atmos/pipe.rsi/pipeConnectorEast.png create mode 100644 Resources/Textures/Constructible/Atmos/pipe.rsi/pipeConnectorNorth.png create mode 100644 Resources/Textures/Constructible/Atmos/pipe.rsi/pipeConnectorSouth.png create mode 100644 Resources/Textures/Constructible/Atmos/pipe.rsi/pipeConnectorWest.png diff --git a/Content.Client/GameObjects/Components/Atmos/Piping/PipeConnectorVisualizer.cs b/Content.Client/GameObjects/Components/Atmos/Piping/PipeConnectorVisualizer.cs new file mode 100644 index 0000000000..a2f9561ddd --- /dev/null +++ b/Content.Client/GameObjects/Components/Atmos/Piping/PipeConnectorVisualizer.cs @@ -0,0 +1,86 @@ +#nullable enable +using System; +using Content.Shared.GameObjects.Components.Atmos; +using JetBrains.Annotations; +using Robust.Client.GameObjects; +using Robust.Client.Graphics; +using Robust.Client.ResourceManagement; +using Robust.Shared.GameObjects; +using Robust.Shared.IoC; +using Robust.Shared.Log; +using Robust.Shared.Serialization; +using YamlDotNet.RepresentationModel; + +namespace Content.Client.GameObjects.Components.Atmos +{ + [UsedImplicitly] + public class PipeConnectorVisualizer : AppearanceVisualizer + { + private string _baseState = string.Empty; + + private RSI? _connectorRsi; + + public override void LoadData(YamlMappingNode node) + { + base.LoadData(node); + var serializer = YamlObjectSerializer.NewReader(node); + + serializer.DataField(ref _baseState, "baseState", "pipeConnector"); + + var rsiString = SharedSpriteComponent.TextureRoot / serializer.ReadDataField("rsi", "Constructible/Atmos/pipe.rsi"); + var resourceCache = IoCManager.Resolve(); + if (resourceCache.TryGetResource(rsiString, out RSIResource? rsi)) + _connectorRsi = rsi.RSI; + else + Logger.Error($"{nameof(PipeVisualizer)} could not load to load RSI {rsiString}."); + } + + public override void InitializeEntity(IEntity entity) + { + base.InitializeEntity(entity); + + if (!entity.TryGetComponent(out var sprite)) + return; + + if (_connectorRsi == null) + return; + + foreach (Layer layerKey in Enum.GetValues(typeof(Layer))) + { + sprite.LayerMapReserveBlank(layerKey); + var layer = sprite.LayerMapGet(layerKey); + sprite.LayerSetRSI(layer, _connectorRsi); + var layerState = _baseState + ((PipeDirection) layerKey).ToString(); + sprite.LayerSetState(layer, layerState); + } + } + + public override void OnChangeData(AppearanceComponent component) + { + base.OnChangeData(component); + + if (!component.Owner.TryGetComponent(out var sprite)) + return; + + if (!component.TryGetData(PipeVisuals.VisualState, out PipeVisualState state)) + return; + + foreach (Layer layerKey in Enum.GetValues(typeof(Layer))) + { + var dir = (PipeDirection) layerKey; + var layerVisible = state.ConnectedDirections.HasDirection(dir); + + var layer = sprite.LayerMapGet(layerKey); + sprite.LayerSetVisible(layer, layerVisible); + } + } + + private enum Layer : byte + { + NorthConnection = PipeDirection.North, + SouthConnection = PipeDirection.South, + EastConnection = PipeDirection.East, + WestConnection = PipeDirection.West, + } + } +} diff --git a/Content.Client/GameObjects/Components/Atmos/Piping/PipeVisualizer.cs b/Content.Client/GameObjects/Components/Atmos/Piping/PipeVisualizer.cs index 2ac90e484d..90ec516dd0 100644 --- a/Content.Client/GameObjects/Components/Atmos/Piping/PipeVisualizer.cs +++ b/Content.Client/GameObjects/Components/Atmos/Piping/PipeVisualizer.cs @@ -1,4 +1,4 @@ -using System; +#nullable enable using Content.Shared.GameObjects.Components.Atmos; using JetBrains.Annotations; using Robust.Client.GameObjects; @@ -12,47 +12,44 @@ using YamlDotNet.RepresentationModel; namespace Content.Client.GameObjects.Components.Atmos { + /// + /// Sets the state of the sprite based on what shape of pipe it is. + /// [UsedImplicitly] public class PipeVisualizer : AppearanceVisualizer { - private string _rsiString; - - private RSI _pipeRSI; + private RSI? _pipeRSI; public override void LoadData(YamlMappingNode node) { base.LoadData(node); - var serializer = YamlObjectSerializer.NewReader(node); - serializer.DataField(ref _rsiString, "rsiString", "Constructible/Atmos/pipe.rsi"); - - var rsiPath = SharedSpriteComponent.TextureRoot / _rsiString; - try - { - var resourceCache = IoCManager.Resolve(); - var resource = resourceCache.GetResource(rsiPath); - _pipeRSI = resource.RSI; - } - catch (Exception e) - { - Logger.ErrorS("go.ventvisualizer", "Unable to load RSI '{0}'. Trace:\n{1}", rsiPath, e); - } + + var rsiString = SharedSpriteComponent.TextureRoot / serializer.ReadDataField("rsi", "Constructible/Atmos/pipe.rsi"); + var resourceCache = IoCManager.Resolve(); + if (resourceCache.TryGetResource(rsiString, out RSIResource? rsi)) + _pipeRSI = rsi.RSI; + else + Logger.Error($"{nameof(PipeVisualizer)} could not load to load RSI {rsiString}."); } public override void InitializeEntity(IEntity entity) { base.InitializeEntity(entity); - if (!entity.TryGetComponent(out ISpriteComponent sprite)) return; + if (!entity.TryGetComponent(out var sprite)) return; sprite.LayerMapReserveBlank(Layer.PipeBase); var pipeBaseLayer = sprite.LayerMapGet(Layer.PipeBase); - sprite.LayerSetRSI(pipeBaseLayer, _pipeRSI); + + if (_pipeRSI != null) + sprite.LayerSetRSI(pipeBaseLayer, _pipeRSI); + sprite.LayerSetVisible(pipeBaseLayer, true); } public override void OnChangeData(AppearanceComponent component) { base.OnChangeData(component); - if (!component.Owner.TryGetComponent(out ISpriteComponent sprite)) return; + if (!component.Owner.TryGetComponent(out var sprite)) return; if (!component.TryGetData(PipeVisuals.VisualState, out PipeVisualState pipeVisualState)) return; var pipeBase = sprite.LayerMapGet(Layer.PipeBase); var pipeBaseStateId = GetPipeBaseStateId(pipeVisualState); @@ -62,7 +59,7 @@ namespace Content.Client.GameObjects.Components.Atmos private string GetPipeBaseStateId(PipeVisualState pipeVisualState) { var stateId = "pipe"; - stateId += pipeVisualState.PipeDirection.PipeDirectionToPipeShape().ToString(); + stateId += pipeVisualState.PipeShape.ToString(); return stateId; } diff --git a/Content.Server/GameObjects/Components/NodeContainer/Nodes/Node.cs b/Content.Server/GameObjects/Components/NodeContainer/Nodes/Node.cs index 7f0deb81e8..aed1369f8c 100644 --- a/Content.Server/GameObjects/Components/NodeContainer/Nodes/Node.cs +++ b/Content.Server/GameObjects/Components/NodeContainer/Nodes/Node.cs @@ -36,7 +36,7 @@ namespace Content.Server.GameObjects.Components.NodeContainer.Nodes /// /// If this node should be considered for connection by other nodes. /// - private bool Connectable => !_deleting && Anchored; + public bool Connectable => !_deleting && Anchored; private bool Anchored => !Owner.TryGetComponent(out var physics) || physics.Anchored; @@ -55,7 +55,7 @@ namespace Content.Server.GameObjects.Components.NodeContainer.Nodes Owner = owner; } - public void OnContainerStartup() + public virtual void OnContainerStartup() { TryAssignGroupIfNeeded(); CombineGroupWithReachable(); @@ -82,7 +82,7 @@ namespace Content.Server.GameObjects.Components.NodeContainer.Nodes } } - public void OnContainerRemove() + public virtual void OnContainerRemove() { _deleting = true; NodeGroup.RemoveNode(this); diff --git a/Content.Server/GameObjects/Components/NodeContainer/Nodes/PipeNode.cs b/Content.Server/GameObjects/Components/NodeContainer/Nodes/PipeNode.cs index ded93418c0..a4f497de63 100644 --- a/Content.Server/GameObjects/Components/NodeContainer/Nodes/PipeNode.cs +++ b/Content.Server/GameObjects/Components/NodeContainer/Nodes/PipeNode.cs @@ -1,3 +1,4 @@ +#nullable enable using System.Collections.Generic; using Content.Server.Atmos; using Content.Server.GameObjects.Components.NodeContainer.NodeGroups; @@ -5,27 +6,59 @@ using Content.Server.Interfaces; using Content.Shared.GameObjects.Components.Atmos; using Robust.Server.GameObjects; using Robust.Shared.GameObjects; +using Robust.Shared.Maths; using Robust.Shared.Serialization; using Robust.Shared.ViewVariables; namespace Content.Server.GameObjects.Components.NodeContainer.Nodes { /// - /// Connects with other s whose + /// Connects with other s whose /// correctly correspond. /// public class PipeNode : Node, IGasMixtureHolder, IRotatableNode { - [ViewVariables] - public PipeDirection PipeDirection { get => _pipeDirection; set => SetPipeDirection(value); } - private PipeDirection _pipeDirection; + /// + /// Modifies the of this pipe, and ensures the sprite is correctly rotated. + /// This is a property for the sake of calling the method via ViewVariables. + /// + [ViewVariables(VVAccess.ReadWrite)] + public PipeDirection SetPipeDirectionAndSprite { get => PipeDirection; set => AdjustPipeDirectionAndSprite(value); } + /// + /// The directions in which this pipe can connect to other pipes around it. + /// Used to check if this pipe can connect to another pipe in a given direction. + /// + [ViewVariables] + public PipeDirection PipeDirection { get; private set; } + + /// + /// The directions in which this node is connected to other nodes. + /// Used by . + /// + [ViewVariables(VVAccess.ReadWrite)] + private PipeDirection ConnectedDirections { get => _connectedDirections; set { _connectedDirections = value; UpdateAppearance(); } } + private PipeDirection _connectedDirections; + + /// + /// The this pipe is a part of. Set to when not in an . + /// [ViewVariables] private IPipeNet _pipeNet = PipeNet.NullNet; + /// + /// If is set to . + /// When true, this pipe may be storing gas in . + /// [ViewVariables] private bool _needsPipeNet = true; + /// + /// Prevents rotation events from re-calculating the . + /// Used while rotating the sprite to the correct orientation while not affecting the pipe. + /// + private bool IgnoreRotation { get; set; } + /// /// The gases in this pipe. /// @@ -47,19 +80,19 @@ namespace Content.Server.GameObjects.Components.NodeContainer.Nodes /// Only for usage by s. /// [ViewVariables] - public GasMixture LocalAir { get; set; } + public GasMixture LocalAir { get; set; } = default!; [ViewVariables] public float Volume => LocalAir.Volume; - private AppearanceComponent _appearance; + private AppearanceComponent? _appearance; private const float DefaultVolume = 1; public override void ExposeData(ObjectSerializer serializer) { base.ExposeData(serializer); - serializer.DataField(ref _pipeDirection, "pipeDirection", PipeDirection.None); + serializer.DataField(this, x => x.PipeDirection, "pipeDirection", PipeDirection.None); serializer.DataField(this, x => x.LocalAir, "gasMixture", new GasMixture(DefaultVolume)); } @@ -67,9 +100,21 @@ namespace Content.Server.GameObjects.Components.NodeContainer.Nodes { base.Initialize(owner); Owner.TryGetComponent(out _appearance); + } + + public override void OnContainerStartup() + { + base.OnContainerStartup(); + OnConnectedDirectionsNeedsUpdating(); UpdateAppearance(); } + public override void OnContainerRemove() + { + base.OnContainerRemove(); + UpdateAdjacentConnectedDirections(); + } + public void JoinPipeNet(IPipeNet pipeNet) { _pipeNet = pipeNet; @@ -82,61 +127,165 @@ namespace Content.Server.GameObjects.Components.NodeContainer.Nodes _needsPipeNet = true; } + /// + /// Rotates the when the entity is rotated, and re-calculates the . + /// void IRotatableNode.RotateEvent(RotateEvent ev) { + if (IgnoreRotation) + return; + var diff = ev.NewRotation - ev.OldRotation; PipeDirection = PipeDirection.RotatePipeDirection(diff); + RefreshNodeGroup(); + OnConnectedDirectionsNeedsUpdating(); + UpdateAppearance(); } protected override IEnumerable GetReachableNodes() { for (var i = 0; i < PipeDirectionHelpers.PipeDirections; i++) { - var pipeDirection = (PipeDirection) (1 << i); + var pipeDir = (PipeDirection) (1 << i); - var ownNeededConnection = pipeDirection; - var theirNeededConnection = ownNeededConnection.GetOpposite(); - if (!_pipeDirection.HasDirection(ownNeededConnection)) - { + if (!PipeDirection.HasDirection(pipeDir)) continue; - } - var pipeNodesInDirection = new List(); + foreach (var pipe in LinkableNodesInDirection(pipeDir)) + yield return pipe; + } + } - var entities = Owner.GetComponent() - .GetInDir(pipeDirection.ToDirection()); + /// + /// Gets the pipes that can connect to us from entities on the tile adjacent in a direction. + /// + private IEnumerable LinkableNodesInDirection(PipeDirection pipeDir) + { + foreach (var pipe in PipesInDirection(pipeDir)) + { + if (pipe.PipeDirection.HasDirection(pipeDir.GetOpposite())) + yield return pipe; + } + } - foreach (var entity in entities) + /// + /// Gets the pipes from entities on the tile adjacent in a direction. + /// + private IEnumerable PipesInDirection(PipeDirection pipeDir) + { + var entities = Owner.GetComponent() + .GetInDir(pipeDir.ToDirection()); + + foreach (var entity in entities) + { + if (!entity.TryGetComponent(out var container)) + continue; + + foreach (var node in container.Nodes) { - if (entity.TryGetComponent(out var container)) - { - foreach (var node in container.Nodes) - { - if (node is PipeNode pipeNode && pipeNode._pipeDirection.HasDirection(theirNeededConnection)) - { - pipeNodesInDirection.Add(pipeNode); - } - } - } - } - - foreach (var pipeNode in pipeNodesInDirection) - { - yield return pipeNode; + if (node is PipeNode pipe) + yield return pipe; } } } - private void UpdateAppearance() + /// + /// Updates the of this and all sorrounding pipes. + /// + private void OnConnectedDirectionsNeedsUpdating() { - _appearance?.SetData(PipeVisuals.VisualState, new PipeVisualState(PipeDirection)); + UpdateConnectedDirections(); + UpdateAdjacentConnectedDirections(); } - private void SetPipeDirection(PipeDirection pipeDirection) + /// + /// Checks what directions there are connectable pipes in, to update . + /// + private void UpdateConnectedDirections() { - _pipeDirection = pipeDirection; + ConnectedDirections = PipeDirection.None; + for (var i = 0; i < PipeDirectionHelpers.PipeDirections; i++) + { + var pipeDir = (PipeDirection) (1 << i); + + if (!PipeDirection.HasDirection(pipeDir)) + continue; + + foreach (var pipe in LinkableNodesInDirection(pipeDir)) + { + if (pipe.Connectable && pipe.NodeGroupID == NodeGroupID) + { + ConnectedDirections |= pipeDir; + break; + } + } + } + } + + /// + /// Calls on all adjacent pipes, + /// to update their when this pipe is changed. + /// + private void UpdateAdjacentConnectedDirections() + { + for (var i = 0; i < PipeDirectionHelpers.PipeDirections; i++) + { + var pipeDir = (PipeDirection) (1 << i); + foreach (var pipe in LinkableNodesInDirection(pipeDir)) + pipe.UpdateConnectedDirections(); + } + } + + /// + /// Updates the . + /// Gets the combined of every pipe on this entity, so the visualizer on this entity can draw the pipe connections. + /// + private void UpdateAppearance() + { + var netConnectedDirections = PipeDirection.None; + if (Owner.TryGetComponent(out var container)) + { + foreach (var node in container.Nodes) + { + if (node is PipeNode pipe) + { + netConnectedDirections |= pipe.ConnectedDirections; + } + } + } + + _appearance?.SetData(PipeVisuals.VisualState, new PipeVisualState(PipeDirection.PipeDirectionToPipeShape(), netConnectedDirections)); + } + + /// + /// Changes the directions of this pipe while ensuring the sprite is correctly rotated. + /// + public void AdjustPipeDirectionAndSprite(PipeDirection newDir) + { + IgnoreRotation = true; + + var baseDir = newDir.PipeDirectionToPipeShape().ToBaseDirection(); + + var newAngle = Angle.FromDegrees(0); + + for (var i = 0; i < PipeDirectionHelpers.PipeDirections; i++) + { + var pipeDir = (PipeDirection) (1 << i); + var angle = pipeDir.ToAngle(); + if (baseDir.RotatePipeDirection(angle) == newDir) //finds what angle the entity needs to be rotated from the base to be set to the correct direction + { + newAngle = angle; + break; + } + } + + Owner.Transform.LocalRotation = newAngle; //rotate the entity so the sprite's new state will be of the correct direction + PipeDirection = newDir; + RefreshNodeGroup(); + OnConnectedDirectionsNeedsUpdating(); UpdateAppearance(); + IgnoreRotation = false; } } } diff --git a/Content.Shared/GameObjects/Components/Atmos/SharedPipeComponent.cs b/Content.Shared/GameObjects/Components/Atmos/SharedPipeComponent.cs index 6f24813fcb..141a8fa6cf 100644 --- a/Content.Shared/GameObjects/Components/Atmos/SharedPipeComponent.cs +++ b/Content.Shared/GameObjects/Components/Atmos/SharedPipeComponent.cs @@ -13,15 +13,19 @@ namespace Content.Shared.GameObjects.Components.Atmos [Serializable, NetSerializable] public class PipeVisualState { - public readonly PipeDirection PipeDirection; + public readonly PipeShape PipeShape; - public PipeVisualState(PipeDirection pipeDirection) + public readonly PipeDirection ConnectedDirections; + + public PipeVisualState(PipeShape pipeShape, PipeDirection connectedDirections) { - PipeDirection = pipeDirection; + PipeShape = pipeShape; + ConnectedDirections = connectedDirections; } } [Flags] + [Serializable, NetSerializable] public enum PipeDirection { None = 0, @@ -63,6 +67,25 @@ namespace Content.Shared.GameObjects.Components.Atmos Fourway } + public static class PipeShapeHelpers + { + /// + /// Gets the direction of a shape when facing 0 degrees (the initial direction of entities). + /// + public static PipeDirection ToBaseDirection(this PipeShape shape) + { + return shape switch + { + PipeShape.Half => PipeDirection.East, + PipeShape.Straight => PipeDirection.Lateral, + PipeShape.Bend => PipeDirection.SEBend, + PipeShape.TJunction => PipeDirection.TEast, + PipeShape.Fourway => PipeDirection.Fourway, + _ => throw new ArgumentOutOfRangeException(nameof(shape), $"{shape} does not have an associated {nameof(PipeDirection)}."), + }; + } + } + public static class PipeDirectionHelpers { public const int PipeDirections = 4; diff --git a/Resources/Prototypes/Entities/Constructible/Ground/gascanisterports.yml b/Resources/Prototypes/Entities/Constructible/Ground/gascanisterports.yml index 130ee8efdc..dee9563f98 100644 --- a/Resources/Prototypes/Entities/Constructible/Ground/gascanisterports.yml +++ b/Resources/Prototypes/Entities/Constructible/Ground/gascanisterports.yml @@ -16,6 +16,9 @@ - sprite: Constructible/Atmos/pipe.rsi state: pipeHalf - state: gasCanisterPort + - type: Appearance + visuals: + - type: PipeConnectorVisualizer - type: Damageable - type: Destructible thresholds: diff --git a/Resources/Prototypes/Entities/Constructible/Ground/gasfilters.yml b/Resources/Prototypes/Entities/Constructible/Ground/gasfilters.yml index 9c351f2c6d..2c2e20c5ab 100644 --- a/Resources/Prototypes/Entities/Constructible/Ground/gasfilters.yml +++ b/Resources/Prototypes/Entities/Constructible/Ground/gasfilters.yml @@ -28,6 +28,7 @@ - state: gasFilter - type: Appearance visuals: + - type: PipeConnectorVisualizer - type: GasFilterVisualizer - type: entity diff --git a/Resources/Prototypes/Entities/Constructible/Ground/pipes.yml b/Resources/Prototypes/Entities/Constructible/Ground/pipes.yml index b57e230ce1..6499f2467e 100644 --- a/Resources/Prototypes/Entities/Constructible/Ground/pipes.yml +++ b/Resources/Prototypes/Entities/Constructible/Ground/pipes.yml @@ -25,6 +25,7 @@ - type: Appearance visuals: - type: PipeVisualizer + - type: PipeConnectorVisualizer - type: Icon sprite: Constructible/Atmos/pipe.rsi @@ -55,7 +56,7 @@ pipeDirection: Lateral - type: Icon state: pipeStraight - + - type: entity parent: PipeBase id: PipeBend @@ -68,7 +69,7 @@ pipeDirection: SEBend - type: Icon state: pipeBend - + - type: entity parent: PipeBase id: PipeTJunction @@ -81,7 +82,7 @@ pipeDirection: TEast - type: Icon state: pipeTJunction - + - type: entity parent: PipeBase id: PipeFourway @@ -93,4 +94,4 @@ nodeGroupID: Pipe pipeDirection: Fourway - type: Icon - state: pipeFourway + state: pipeFourway \ No newline at end of file diff --git a/Resources/Prototypes/Entities/Constructible/Ground/pumps.yml b/Resources/Prototypes/Entities/Constructible/Ground/pumps.yml index e44732f0a4..52ce92b8cb 100644 --- a/Resources/Prototypes/Entities/Constructible/Ground/pumps.yml +++ b/Resources/Prototypes/Entities/Constructible/Ground/pumps.yml @@ -28,6 +28,7 @@ - state: pumpPressure - type: Appearance visuals: + - type: PipeConnectorVisualizer - type: PumpVisualizer - type: entity diff --git a/Resources/Prototypes/Entities/Constructible/Ground/scrubbers.yml b/Resources/Prototypes/Entities/Constructible/Ground/scrubbers.yml index 88b03d265a..389c02727f 100644 --- a/Resources/Prototypes/Entities/Constructible/Ground/scrubbers.yml +++ b/Resources/Prototypes/Entities/Constructible/Ground/scrubbers.yml @@ -28,6 +28,7 @@ - state: scrubOff - type: Appearance visuals: + - type: PipeConnectorVisualizer - type: SiphonVisualizer - type: entity diff --git a/Resources/Prototypes/Entities/Constructible/Ground/vents.yml b/Resources/Prototypes/Entities/Constructible/Ground/vents.yml index 59cdf618f7..87bb311852 100644 --- a/Resources/Prototypes/Entities/Constructible/Ground/vents.yml +++ b/Resources/Prototypes/Entities/Constructible/Ground/vents.yml @@ -28,6 +28,7 @@ - state: ventOff - type: Appearance visuals: + - type: PipeConnectorVisualizer - type: VentVisualizer - type: entity diff --git a/Resources/Textures/Constructible/Atmos/gascanisterport.rsi/meta.json b/Resources/Textures/Constructible/Atmos/gascanisterport.rsi/meta.json index 6cbbd9f2e8..da02e91ee9 100644 --- a/Resources/Textures/Constructible/Atmos/gascanisterport.rsi/meta.json +++ b/Resources/Textures/Constructible/Atmos/gascanisterport.rsi/meta.json @@ -9,7 +9,6 @@ "states":[ { "name":"gasCanisterPort", - "directions":1 } ] } \ No newline at end of file diff --git a/Resources/Textures/Constructible/Atmos/pipe.rsi/meta.json b/Resources/Textures/Constructible/Atmos/pipe.rsi/meta.json index d9f1869ab8..727ffdb390 100644 --- a/Resources/Textures/Constructible/Atmos/pipe.rsi/meta.json +++ b/Resources/Textures/Constructible/Atmos/pipe.rsi/meta.json @@ -21,11 +21,22 @@ }, { "name":"pipeFourway", - "directions":1 }, { "name":"pipeStraight", "directions":4 + }, + { + "name":"pipeConnectorSouth", + }, + { + "name":"pipeConnectorNorth", + }, + { + "name":"pipeConnectorEast", + }, + { + "name":"pipeConnectorWest", } ] } \ No newline at end of file diff --git a/Resources/Textures/Constructible/Atmos/pipe.rsi/pipeBend.png b/Resources/Textures/Constructible/Atmos/pipe.rsi/pipeBend.png index ad0f05fbd4c90c04cbc66048f2478d47f29f26a2..b6408718ebabf37e4eedfef7601b7378670ebcb0 100644 GIT binary patch literal 3965 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 X-_^u=F}^#^00000NkvXXu0mjfO~0Yv delta 832 zcmV-G1Hb(J9@YksBYy)ONklK0ZF? z>+5SiJ3C{oHM_n`G-+6fbON+(K-+Wzv~57!bON+(K-+Wzw0~_t+jIi7Z9v;ZFM#s7 zNC3ccxum9yaV5(#^m;v~aj4VNQ?Jf1E-tuD5ys;&rqd~^ssaE=DeK=KA*BR>`Wba_ zaNyi|Q4}~iIl<-SCEwlMeY*%nQ6NoIOePZ$ZMv_j3e1erXar`)YPA9pp{gnfAwWc6 z=05^lU0peKet&p)h%`;{`1sh^fIiD|xuiVL831l?Z$I5mDTVcV4FD+1a`RuF=U+A; z%QDPnGfXCvFSl)qZ4oR=DHvm5jKN?qKv|acOcPPPJ%|WGZ2Z4+*}p;v-re1WF{X*J zIMamhaSDTW;LKhD~YotbcQ=Sfcd-mS}x|F{b{mAEgffHs=5$!t3j+*L#8$z!I$! zR7!!F(d+fR-V>w%+c`ep6`*_?`_>i!aGJsW{e5Iv)<_t17C>vwzO@CGs;d6V+kb>j zZb~UJ9*-O8+erYeHBYBg?Ck6yO;c|p?4WG!-hUVaDJ7U0{eB-rgy-ky`V*X;`JyPi z!=Tp|NYfPe_xG61W?n|vL<{hKe}9HN&%Lt5UIGBX)6)|k9v(2C&z;%}As~c+F$T-*>?{B0000< KMNUMnLSTaSOL~+5 diff --git a/Resources/Textures/Constructible/Atmos/pipe.rsi/pipeConnectorEast.png b/Resources/Textures/Constructible/Atmos/pipe.rsi/pipeConnectorEast.png new file mode 100644 index 0000000000000000000000000000000000000000..c26ad0b9cac12e98efe2f1f24feb419ffecefb73 GIT binary patch literal 1029 zcmV+g1p51lP) zaB^>EX>4U6ba`-PAZ2)IW&i+q+U=KHmLn$&hTmC5mVj>$g}4@KK;kJCMw z%v)S^l_()3&>3P_PL*Qs604AGB+?-x+IY^w+%p7p~+FQbO#nJ4b%i` zzKw-;+`Qv8N{HMEmP~L)i{^82uav)1ZjR<$OP9!}TdpuJUaJPfSmf3dRscftgoxipQ#eN(hMTl(}3<(JMKw=cgN9IU` zJSOld7&(h_1pzYSPHuvYNC2F~D>nK>+O}+bsd2Obgh`MHG+7E@sT$T#)PyxuOiZ1b z1&fv}TL}_0SO_78bw-saQKQ8WV@xr}k|b%e6jDqnIRvVaAzep5;dEP<^CEPvpL)Mu*xWrrR#wsX-m%hYMQAi7jRz#!4U_7Xd72Ud*tc zRe6zH%zS2S3S&?sTW~rpVj!r4*e2cB-N}8)&6)lyZv0Q=+(P#|$hn2?ko%F_3u?XW zUliGZ)-GH*^)hj=;Rq_6@Q3sG*QNWf4&IL5j{dKXa8h^zMWDoR-`Wql&PmX5zM z_*r>(RC^w^1+JsujP`>thB3lwn;GZIH~!pj8qnQQt+Nczh1Lkv3fDHvYKcZ_>m&GU z>Ao}gS^0MKcJy}iTH+(VG@o(FIL_Ee%b8qXSKV=L{h;hB*KLfouX_gQMG%00000NkvXXu0mjfo{!BP literal 0 HcmV?d00001 diff --git a/Resources/Textures/Constructible/Atmos/pipe.rsi/pipeConnectorNorth.png b/Resources/Textures/Constructible/Atmos/pipe.rsi/pipeConnectorNorth.png new file mode 100644 index 0000000000000000000000000000000000000000..30c6e83d71e8e4c619ca6f5b1c8ba8ab41f54a1e GIT binary patch literal 1113 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 delta 444 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 delta 619 zcmV-x0+juu9D@arBYy%)Nklcv#*^-*0-oUUa|TiBk_3Nx$R#iRjB$YlW`s zxNbI*epUc>y!WuKYf}TX{Y?QNBJkcfH9*_X3P7zD0KV>kMt=Y#{Y^cn6j5Mu;H zgn6Eu8ldfOUVlkwz70zF*#QV4s1AZsepUcN2(WEivz&{hzbPM3N>R-RNcfuqKtyV@ zfRvvVfZOc`IcMnmzDdqS($5M&&KY8iYJ;GppA~?;+bzq|+yHIAErnaeTIn!JKRY87 zLQqSIN&4Aiz_x9Gh$`yQMUB7$XEj`MtbJ=Yx_O+Sv~ z_}fPy#$*UN=i?wkO6k~;*g1c{ZdhK+Ud!zD{)tcdaTo?V=hn{qZad!l zaB^>EX>4U6ba`-PAZ2)IW&i+q+O1kya^yM={O2j=2;xp2hZ`c^4d(ch39?o%?e-fx z?6M^lMIeDh0xGlq`;VCa;47w*Oo+Lpn$m@@P(yVMf0S!~?N@sR{jFc&oWlPv$IbnO z!y%7XzyD3^T;Fg!KHiYe8*G0)Zt^(ml(Wz|aa+*y&JKT^>&jWkyM5fA|4lvbYvIY9 z^CQFQ>Dc$F_y0qNGiJnk-Wj*N^%s5z-o^9B`i58jcHZG49&6s?wfX4n=e{%dKi`~p z|Le_nS3Af3t1HZv&IResN9VYWpZiWd^t>bcxbw>iD>h!wU(ddiSwz;hu7w0oC3B3r znWBH;Lbx+{eOtnJ#!tlGS-&g33rrk9Yy!=W?_q4U4&D|U?6eL0So%8bz!rmBF5}g? z0StJo`0T113P#|!6_zK zkL%(U%t>dP=UD(Q!o4FlV?7YKlJ(Ihdu8XcweVvBJ`Fo}KDZ79Y>aMNBf!S{1aOMu zz44xG^;#F*J`8FB5YZ=}0ZsJ{V1*D7KRFb{P>VhW6Jty<#}aF7$)}KFN+~CDRLeex z9COM!mt1ozzJwA>D!G(WORKJWP*|*~W>ZV8wKd$dVd;iW~!C0W}*5 z&a^}f2!>@{6nn?+f!w#anHc^GH}@5ChS2>#kTZntAomfsPf(jpD~eZun1%G|!Gd)>;2uwt6ot0Z5?S~6W9 zsSPhHw!Ey&)K|%Jl_+`kyk?c&XYD>^u?f65r!3H|T_G;xfaky!K99-e)|3Eur9N>l z0Outo>DZX~obby_$+*XC;$Lhr|K2-4Td2c3b>v#H5s6Lm0Pi%Z8AvX`)KX{vI9w&8|+KwUx`mU3O&|LyxW5vH%Hqdz!eKUw&YzqD#zbRZDyELoRtK`rHqwfA9mRKa5;pYrH5Qa{F<{Pac~&` z4hh*`qGeJDYHBP4KJjfk5ZcVvFU{_K&4kLj{a2U4sg{7sN{A91tSNRd$iU9}%ok-- zv?1D$uQvNNEZ-Am79(~-SoG;@4%jXeL+{SRzy*u7xq5C6SUI0p$kIXvTx;46<9$jn zvWP*XXl4IRDC$n7YGyu zL6^b~SMX4rj);l*rWtchOOn^gqD%CghjV{ytpO^>TyV#eS;yA!A*#Nx*1VgmZx|q!#*_k;5Mkm=c>AY|Yb={N z-}jP1vJleS^{7WuFWLSHtuwgfDYzI~7jxcx6{{T{)3@_P*^XtT7Vv;v6}v}TBTb1E zL)s(+6T;Af%u~f5z9-y}Ny}SR)QB6Wty*zuyv;`D!#_ac_tgq(G*kf}grQ4qg`p2h;`(MQDzRv*^y4P;|ay zrB!21V_e@Ox9sD3@R@q2M{=}S=p_gv1eB_q8o`nbXjYLD?o^Jy16ikLwm$sH}GEQt-@Hny*dM)$F49oR}wH+lR{XMZRio zRI@X7g&qP!P}Mr&L^&FBD}Z642kFtZ6#+fuA0w7N4Guf%Vh8if-v?H00i}{7rWoP zS528YB zLgqli4oE~;3sbeq_?k-HflzRVl^N6tmviA3rYWEk2R>mgi}jiApjclN%d{CO9Qp2C zD$IcsAw+TYP&Aj57PCVkH}JJO8`(1Ep4bW3mV#prN-^v!JF)*(h8Q7HtC7#+J^Hl>Z z$Qu987o77*AaKxNbfXvaTHO?_Hse6oh*s3X^9fQBj#AQFh4Hu8k#rJ><~A5spfwwM zX!tBsu;XpWTL6Yy0%sb?dWeZgwWvFy1}~jNznBM%Uckw^#|i;j#)=63Tn5x=U%KN4 z1~s#)VpEKunUDuD*R{iBI-xzC#DZ$E`Frk=?Z5OlQbTqsZ?C$fPyr-SapdZbZ#con7WiU=lLC7^*F z6sOltQi>*zzd&o96%f*|JNPzF1z83NZ?Q3xn~sYd+WdKhVE+9K;(ejF35}pKmEeHW zh^!TpMglL6M#|Xw2%5SggLEom&R7ObQoJVEUBh>+p3>GmI+oew$0$X4=j;Y8EwyZC zO~Q3pO`V+)3(Iv#b!%}nvnC-e6BQ-Pjs2$AzP*}1UGURa^GGW9GJ@K+GH)$yMNM2n zTbI8N1!{+cgJcTKJwruJorv}s0im;*oLL^!a`s=)H6)r*`Un~AiRKdOF`5Lhe~km$ zy&)jWRA``uETKV~kyLPJ_%ebcerTO}p^P`{bT|R2xU6-`nvu%3qYR>A4TTJHY!BNE zKmj2?Z2hgN=H1rcnrgmf#|$}Jv`^T1T#?67SWFP*p2UkgGP#pAM~~euC3Rk`y;=Y6 z*bMT59Dh}8%5Pfh>ohl;*C^=GuQ{vJHx!V$8_rQt4gNMJjhY~@1W(Qi#{~L!ONDJk zZHd6d0}LQ3b|RGwXls|2^)MnX5E>g77E{FYZ6G#4++g%f?w@SD(!6t)@z*an=zS>6 z+JEi+WTni!MHNCTeyd^QM+s{_)v)o}q^y)o>_E!O$ZVxTE?5V$?q0%Fu%9Z%AQ+jV zyqtY(UCsxw1m%yf=6(Q0(rc#4$uz-jFZiF(rThp#>zjkfLC?tvr7-r9cE;0L%|l*0 z)*?j#m$KtUo1sWH&TNDoAVv1B*DNuoz`**LP>uj_icCBSIi=;Ne2uTUlA0F=Fvu#Eu*5yKt z_UuvZnYUQnUgBtMqu|ZLhXfVk1fWV`RP(6x+hnIdJ(mMx=pTFD{X~WzHIcl48ju|g-g;xKu-5Q_F=QXwU>^v z&ddtA5hIju-r3JV-o4c?*34^1qEk2jN?=oK}N&}`#TO92Pa_q352DN%=6R1LDdIG>*Jt-gSpuEu)uaB&g--Q z0jM}5t@mUL5}F|cT{1+s7521^k)KukSDgoqJ=Zl~%xB7Nobx)(LD{-KOw4tXXVj_c z#@yaVs_b={p_Ohuo~wv@@VO3;IgYu_qRf4GjFiZbS34Z4KAX4?qZm^*_#WQ6W!@)?@zoFk#StwXEWnQ7S08Cdr{RvvEy zYhm$lXbILH8Z=}-x)1I0!A6t;=-*7>2O)HTkU0i{zS04L&Q_l(2{8t@6b_YNnH-GF zhaKjJl>A`i(XSm-&(G0<7%Nn~4g|@*hSj23_%*$Z$S3(l%xH z#feql?vVy;n~6N^m?dF7&%RCr$_Ff;Ul2z1oSJpJr)GNij8s&Fy-!rk??x&gCo1N5 zBbAR674y51%KJp6O|x9)(=NV=wS4y5MJVqVJH^ZgNX(yAARVPLOE`M;a1~TwpssSGR)Lo=A|aPsz>h$3$H>aIMD;z{KkG zyVTf9BOax}A?b_GAUuXrBYl~S#AD>!?7iM+?>9x&cd&z#4QHmm5Ruq4RgQXbRe2 z&om&k0OQanC+j>G#~qMfm+T3IZ012pg^b)qs{#WJYDU3g!!eV27v7)hZrTg+U3_4Z z>)8HF3pZi`-SlGa)>@BB0!4P=+O(fxB?bv4r~fmu=BxhTC(TzbsNfK}EGp(`YCkT7 zvyw&{xjq^k(FgvY0lubKa$Gqc6%@ zXx+gl_LEQk)Vb%noNWlO>dx?~0zU#k#m-L_=$L8l=j#wIUyX}EeXp}3^Q&Re#|eQm zpMBg2G9COpRpKDy_8`J)CjtHK$6MFJ=g25WERYdpn=>M`{74BtV%2sFOr*-D)1`cd zl}D-+zg0hxw8+Hzi6p>i&PS3^CPqLBf)_b5(Rnvp8BR>T29UvCp+x=%V8Vxo&9sk( z00006VoOIv00000008+zyMF)x010qNS#tmYE+YT{E+YYWr9XB6000McNliru%D(M9`Em{fDH)tOOkr-|2 zQ$*4W743sQfGt|Jh$woYovWxQf+(UzVmf-B#h){n=~K=4&u5zM%?L-&HFJ62XYQ8^ z9BAQiSd5O2ik+PuMn^|QI2;yM_wwLSOC%CxG8xg)(P3*J#}eT6dYPS_wY`sH2{=DL z2cWmN7hTugMS!ZR|J}UDL%Cdbp9hr7WdeZ!rBcbgApoE#in|FALb#Ivzu*7n>N)}n zg#rLCFE94P$cY5>^z^*(eZw%gy}h;cESeJuh(sbxPfyd{-p$UrTWnJQ5TwD-~#YiTT z^!N93c6P?@?k<3k_xF)i@2|z+4KUPcuJ1&&0&Ur}4FPI;~_f z86gV`kH>>y7ziQo`FtpfVxG2xgM$DJ4GjTsd3i}R8Z`+R7#Mi7Uax?uR4NP&4Y9DW z0HCDPX=?EsWq56EZ2A$Wa#MNt%VU8hp1yuqKDnNhS% zCLV@ zf}^7&k;!EEEdJ@~>AU?84i3!ECnqNWY;SLW3V(5NQ7E;|1XWe*x}ZFLZ*Fet#$Ya& z`|u1m-`6!pmc)ect5dcuBR2rtuKRyKF@i+jv zT+W?&K&e!cC9OL>;OOWGK#@(2-?zXw+CQNWNF)*fw&(M9@LQ@6Xx4nb)%cbPXx4nb z)%cbOXy$yr)%cbZAvvE{RrTBR099291Oga_0bmRNcRcQ70(?H-n~-oF0kRCYQ;a#9 z06DR;(~)xIT%f7bVJkn9bAf?@0iK_qSz229*114EeSlSbORR;%VNsoY6pKaf?(W>< z0RST-BaDxao3lY(*G27YPR6F9Ckq2+0d~z60gdMKeSLidgFy;~0*a!T53Xt2r}P0b!xKW_ z_xs=J6RPzAEhRwe10EkAfv?Z!zp4+A`h>HyGeV&d(P)&1hlkb?0Py(uC^b4{vsnzo zU~g})VF;AVWm8a5TiMC1t~w0lS)%JY%gf6E?C$Q;)zxKso~>lciFrUX-$IVm2gG7A zQmGVeZEc*Mo|4UGxx2gj%>=)#7AO{rras_rlC=NJB>vjk8WR%}-`@|AdH|^paI#q< zK{{#UZkH^#pw8B(XC7;imt*~#O3$$7v y&`f;C>I0gE?^u06v+!-{1Jdbq%k%-w!v6y#Sk|@Zj^&vE00003kd}wR0dWy`~VX^ItwZq{sD~@ z(ZoQly@`K7G-B*Y`~g@{Sr{9E*2;*H&`1b{2_Lh}Tlmgq!H)-K_HmyTPP4n2oqK1` z&YitG=K?N7Bod)JJ3I9H`kEdeAJbSYMtN;{>>SunfztQqm475j*p@2^kYyQ)qJUBg z!!U$wxsm|GFhB^wbUGEbYf)sDEJ?Gx@bO(eQe`7!HR}RTa@_6fZ9?7>~!F8jHu{-?jsQqA0NXTNKRy zro2yhR zD3wY$I5evEPw1N0Mh9+0O0BA3A(PE1SFHmnf9+>^|1_s!5{!2kx0z=-`v~;0E9vzvpo<9 zfKrOlXaq@;psK2QZWsnU9uFi*f>Nzk7al;r-v6<_VyM4Fc=KX z_P>E~Mmd$fXlFVzamDA2u*lBR(0num_xm*sZR0{omALVix?RMMl zvHb|R-dZFQp^7rgom*!B*S~k z%GlA35F)^i9T}$~M1b|X>Q)F5;PJe7w_|tKDcBMMgb-T>;{?_rAk=vs0`G5LRG)Ja zLIl{U(mDk$0_Ia+J4DK55R1jk`hcUOBdTfIYSjlYFyci*(A5O6#aBckb2R}gs|_;v ze1ARwVxM7G6TlYZm0bhYA+YKpz!EU8*UN3g)dVobN@PdMmAZhf>M&0yrVAvKNel)9 zoSdBes4nnXeE_e2F4i_SHmFtN8jr{5cDt)H0{|eC$snK4o7$kNs&rnPW3kC<4rVkt zNy2nG{h$?o1wsgPT{pE!P1BIi=W&03kAJhXGv3D#FOm67pD&e4OWXNVGGnbju+|5N zLWqE`^!cr=Ed&Aq42MHgk7sY5>GG6PbC$4cYu$kLp85I&Ykhzyga}~u0li)iz;gQh zhk^XB*MA3ApU`Tx5Dtf->pEUvUzheZ<5#FRfL^c1YIIPm)j$Zr&CSii{RttUlz*Bt zWInxRvqV)@l*?rRK)qgvrfKHP6M-x906V`zuB;D;$KxoKN(csnXf~Uu)oSQ=yIi(h zIRotU&%G(i>H`)nNwX8o|M~ej3Wb7DeF7H&tR8^X2e=tr1WYCq0QPK1I1MfWSk^Wg zjcgr^6Id5W@O1hOnjixg0W9`C9w-lFSzg^LvEP6-0ZtFVX{(a+C8t{ii9sY-Tlz+?<_sJ zbN}|>Gpzj@df!h4!I%nt!hx5NL_CwPBK{*WwEjfjCy89|c#81nu?vsacfotSy^CG6 zTP|-y5n{f7C**fAy5*#w$L>Vv*&=#f`OU!WvBc-=Id*&2z1QWPrHn}Ba69$l%6Y>? zgfq$cEaNWtDc;Mu8}14h2N0V;v*R9t8Zn~1DbXaOP3yFS224!6xS(Yoz`$iy3O61H zjN~_MF4ANMsla0ZHG!BPw$NF(o%IG)tUL)bnV^h+@WqEad?x(P{ZO>GQSnCgk|xx*80;uEj}1oecu!ar^WlD$S*k&=p*TuP~>6{}KH)tYOmwYF-F zo1lbg%dLb~TWe-m)S%k%wPA)?=Po^U?YWm;d+RnppOJ=+Jj$q}4Vye=BK>EcCCob8 zv_%V4T50LZtE{@(vJI|n*=g&}yX?B#wg+l|H>z(@qj$*t95uR8bHvh_S6)$rxRe(a zI7C~^SuEcBR0*(hw7u&Qx2-;=)GhCfyCzoOqzw9~YI zQP7zX_LRH%!DdTBZ))~wo6Rt~c1DZy2sKbdbzyvTbpco%ih)S2sh=wpf8TAxlR#JN z$@3va8fzA9=&|>vms6O?hJDt?vH=4#H&bk##mdYUCW?U0q)2->)m0lI=};0hBgqN` zxkg!KyQ`A>7)RNO&T|{y3x3dgD7UbGt?7D^h^u1=8RdgWs~R3A;#`mfD_ZZUI4D?A#`Z9^lf@a)v*;c zE;u7YQO$!Cb+_QipxU9I4_Os|{Eap@K7$?92DE|TaM+s~$J@*eU#B)W*x?nldfG0M zrO~$}(9pv?>;ygxKF+~dhY#Fh1PD)?13`j=bXIKqaM5{pn2Vislum1)#SZTu3UX&tKRoHmP~@3fvqxol#o>Ch5$WBpKxRHP z{CRl@U)2q#<#g(dD?h|>EJ*$0aeVbJz~f}6^vM`^?%-@NNqTJ-Js+V^-Q2riAW>0h zKm~k-f8X>}QVn{qASWDu{OzsenUIg9^qoW3i4sD0_L!YIID|5#sNcX2S$LHdM|QNC zgL(F;+XYO$*56x?RqAb`z z3VJ(T!pK#D!N{;BzH`_A9JL=Sy5nZP?y4TH;#OcQc6i&>nHx}gDarYxli`=5fPXvlyS9^rUyrz4vhMg$*|Nzhi6FAI{Fs?g6qaGw)p2e+8i1?XG;EwF+^T zWk@Lr!w}oH&Dm@=Ln+14(b2u@x+@9UT9#Z&NfbrQW;4pNB+qk-qCiTC<2VQ*ux*<- zjwy;_X%W^kLepy>UmSsdyWXOl9rq>@(mL;8b3xH0$MOl{g`U8fk zHX@=ZdSukEq57@pcXoEz-rmNtEbi_;^Y{26>W{Yt2hC?Zkw4N1LjF4cll=V$0G>bl z1<&)TR4Q1OMZI2sI~tANt>u9zikMEP4Qfl|u+ ze|~i=tSn4=fZQr8E(B+ASJENLiMKd|rk|5E^6d@A^n7 z|6M0^U6&xJe=?mq0K9nlin1(?2O2?W$R}fk)|%s!Q{KF8qLjjM9BQ>HTD$8vqBxET z!w`V0%L|iYfJP8+IOf|#wSCb_n1aTa%UxIG8yOksfwr!K=Ia+ITc6@Sb zYCah&V@v?8HF=(6+crs(ENsc&%z*2 zJ|)*`L;$1F=v}>Df9p67p679QcaP`!+}zwy;S>4$5A5&yRI3)A=ktSYn^~ZgT52FI z97g|K@@N{)@l(xxG!1LD+RD>#Yt?;VZ*T9b`#_Q;e3yOTdu~J8*i%W5rYY#16++7Y1iaQi5ez?24yIX+*<%&~^dnqo(;V4?1Lm%JY z%Qty>d4Io6<}fWw8C-|jg+ zU|tv8JXKte-_cMydgVVL9QCd*%uh z?@yNRp2}AX>^35{R-RT`GCE10Zl4ml24X+M^PETZ15V!$8Ft(^b)AB`YdKVnh>b8F z>AN4UVed{jx?i6>%#tn}9{H~Y@P)Ph@{_nVE4lNd==Xi|q>b2Qr7vzNBeq&GfMX@P}7>5Y-9WR$_9M#~SqkO8Pp*%P> z(RxRUvry-szBlD>GFnq0GA~p7gkzlp?*uS!t|pCtNWiGG@cTM!wAgCT1_j+zG`PY; z4m`gP?3MFUta%nV;Y@w+L@2|&Yh#W(UNx^r?xjq&l;4IoNk*=-L?DOjU2tW-Hjfre z|6r~p8b+k4D2OT7eCRsFRgvpD%=>LqiM63LSqa$ub-y~|hnWg*j-G98t@HH2uQ)aS zx{tN($3A-v75P4Yn!h3W%D#3kO_C#X|N5uAAoNN3U5>6*p2H$qs`dxxvNRoC_vTk~ zur<@cJm{+B{O{FHsLy57{2}S&!;;f7jOm#`W`Cb2xfcyX9C+sywj6aOI${JjA2wV5L ze}hv$T*b{>O~-D|N)UvZO^-T8#$jvQ)bR`}sEOq`KK--hNN12iEur$HJe(XB2idb)4 zVTQN1k=b36-40nah#){Ts?#TV3*k8dzM`&17f{HRrH;uOhxGQ5T5gAaA}DL5Z^!QdR9R-ur0WBS(nm$6v= z=FQ>I>{SQL+p@8N-+L?cSuUqIoRk!UB$sXmIUhOFT)#}!@nO4eU3bXgHb$&k51ymF z)~Ty<%^7d?9t8BFC?f|?rZIYG*|BjK1{XTZ#ge-A%2qikcXNra@E+7E|LKYkbBEe4 zC%{rTd<0hI2k(KkUOwQ-pLPp#OpEf%zv0d82BtIp_RNPMc34X$YwY{falWC!&_%^| z?Ob)?E|?7Tmw7Fx?pHcJKR!ne(R^3hCsGp#G{Nfv2koW{b+X0TJ6fkcakS~u{DQaU zSpH@A?UM86FO7JJZAMFSt}Pb_4_?loMTVK!7!E45b)o1B@^%1%k08R>1V3f6xz%IT zuy6=B7Q^$rGEH7D&sECJ+x4niiJ6{aP(D&wVlDPJ$AR^kl1fY!5{1CA^mmd7ko%B} zNbm+5bRgW-`WUH%{0oXEqgWVzb&jA>mktQuw0Z0iu8zWiQG1yQGp0-uu_~rI*i#Wq zq7x6ChUkb)^~*@%yr7&W$j{8X`@B`90S~NM{2II*opth)Pr_Jy*7tCP@jfYXJfBEP zVhA$ghfrBbh@L9%4T_)7RXQ1Tn6tbH&v$PSUPrm0lp$S1Lj5y$id6S0*Jp$H=4E?a zE11O1ogST}UpA#w!1fl+p+_6_t#kcPUHrPuhW{ z36}8x4&mT>md^Nv;3m4l*UOo%SlwwRmZi+9K5%{)dT)lkA`|Q6D8^(jsBjR+%HsU0 zC`!PLp6X3}b>ElFxn7RTLpd`J-XT1XO?_TJHP026p1JVU@1_%ss*N)CY-FA!KWkYv zV#$CnXj6+j2Cd90tN5=3zDP5$Y%vNuB@^uwFT~mt_TcA)esB^nofE{9=AB~?VgusN zvb|qKRw?T9V>8vc`Y}imMMf&6Tea?g_W89gn9NJ;goNs;lh)3rixMx|z}5lEmI8`yHXpf=U!2$k+em-iw7_P!+z;dn zWk$cq!YQ-Q&IaM+WouhF7X{5ZBv9<)YxY{jbUR@R%82*S<9HCfH4BKciXvt}rJJh) zqw*e9R)R3O*c(GgNrJfLF;K}s$RSoe)fTqOhbO3XH}9mXnwoz(q>c5R{p86IpLX$o zg}E;!g8XecHKH(H-6W^9_0Qg94@?&y+0kEKg4qVm(WeKj_Sr5@qbNOU`j_fdoF7&!!#xw)ds$1){LbjD-EZ!WT{g|3 zXx)_Q;4y3xprgp6`$Bbr2~lzk5l|hoz1qlT6fcs&nv4IcISS_s^?S??0e9Q92@)bx z7qGo(pI#V;s)lS~=}gL>Eenqd1NmvDDeYV1kY6v}JfX41X(n{wC^A&ulNR#)DLl4R zCzsgi29)7zJ!1ba(KslXdl*L%B7_I5YMCSoAa`fgA6tZFDy5Yw4J=(0F68nkB-i|E z(ar)a{nOTEEwY5=vM_*=kSvnCxMlgPj3k610uur}=x8gOX3 z9$P$7j&pc8!>M`Rq5|6xMM66P0Pb)GlG zPA1aVpJADy{gb+@$1s&*<9vM5N5_Pu@IXbmYrPlwm-?>ArGnM;Kx4&cE5<-&`EWNm zJ8K}z(}3BYvM<@ugyZWp=WOY=$sO3_1$0jRHJZ~7rfk)R$R$bOTwXr?ub7XMrJWg! z`qeG8i?EFn9Cvx23eV(tIOAb5g-E>p7bP5$Wx*9OE~%>c$3!b)Yb_fN#?3XbQ&=*2i94q3}1-B_ljW}N6X+|ICh^po^rhTMq zyQnBUV;ANC3Rf8`?XROAzl7W|=ub zC6@B{QUMMPnAGR7nv`mr)smz+b%WDeBE0($l8Kw7?MK8IMbZhlv|lGJ*KRucbW1T& z2|p94{#HXnjf_k4Ru3j}>Ssi?zEdGP$?fslcsW8%fk}-S%;afgfNEAcIS-N~V^Kj5 z0)#gar5;KJZ+s=s?PT3}|E1sGmf%iajTJ4EL@sQ9{3j;!QN6fJMQn+mZDPssKn-|hNs(B#RAP)9Q<;LbHG z64lF7lwwXW9nmh*{q_tv5Jp|tZc=ZxYh22lQnCVOG=EwJmuTY(8dAQ((VvH+PvU72 zD5Jh^#eSza4{XAS^R^L{4;`(6M83e%&O&Ef#7NRV317HhAY*CcTkfORxc*RjNfEj{ z#QzC&{aT8XEgWmaL6R5Z#8_C~Io9xlnLwc(jcKbGC0U;QBi*ppXDrOoUB)rqEq%5% zK?omMd(=}@NijLP-RlU#gsReiJ{-l+Ddax-Hwp~!0Qm661>thP#ks}4y2e8h0@2t zfkH(ubuk-dh*nnrinX@#;)bvZvibUJ_xR*OAxL9Ar_Qt;?>G|<=()iab! z@#cH*`I-r!&3XZ9`j#*-ZO7?S+7Fd zXZ9G6nsmf`h1^$VP(bJv<$raDW!@>0*iAL>CRz;1;A>1uZwt*;2cRnIAzZ8&m7d3_ zx$2!iGw0HGjvCE2&_*j|>d!K|8DuWM51$lZz4X9!ItA(SYfZfVm0duRCO3@4U-zIZ zXHF8DoDlBB7q$LZvSpNu+{;nE0%bY8vh|a~s=Fo*io=K}TJk1-KO(46`w)fpT>sug zkZiV0*(3D#YB{@Z#K-(_t(1t_a2?<_PX{-QZr^m+J?X~lP?y#iWZg1!;JKCR`p%fB zqDpDV{*?)4r~i$VgM5wH(H7J00Wavna`!66+AOb6Yp8vC;gR<;DY+0tO<)i41Gj_i zW=A3nBxmp?NFq3R(K)$#(M@OEaoIwZ-G1eSD+^YXO3NG8{C?0ly3!ju(-=vwWRO+D z0QU2OU`y`-}!}5YIAsib; zgm!OHH%c;BW^j#r*r5lh>}mU*H%8^r#if3tQ+GjQ2`tr@%P*eBT}!ip;8_1ToVE`} zSF}q=7v!XiXc)IW6TS}`$(i6@dE{NcY;)d2vUC|Smr)~L)H0j^{ujmc_8^lSBewo{ zB3p2UeD;_7cVKHwng>Cw?f|}e_P@r)tQbN>WF{GllYttniWM=b4eEHOOjLw^V!ZLG zsdup}5z14c@iK~Yj}U7ITQf2ND1u}Vs@3dAlIwH%8D-bfEgHBd931P(u4QP@m#VKP zz*-(18dFJAnf|+~T5JHON7JeHDd6=ASo?{LnNDGZ+Rozp8$q5t|ByH05Xu*U++_3_ zhO56K{`Qt!Ia6KsdRoe+iN)V=VPzej$h>mZikp{tb&lQrlvZgPUwzv4FRltL>ilc| zk5gQU)#X2~cob^U6h8P* zpvi=B4PK)Hnw%2b4pA{axmiy?fBWZL_|LZ_qAeZrG~I{veQY9C!c#JccDW@}@k>vx ziO@?@3eQRCElh{&&4l6?sb0mvD7P4WyW`yMOD9xn>ED44fgPzQS>~_LUP&(Xw(dy$D!k~S%fpWGqwFMOqx$bvLux7Y$X0v7 zjxcmzI+%pWKN%+XQI1@#XEPl~`=f`@8~RV`8OKZcz3vQYi9DE^@DG|t=5Pc925U?m ztzvqLmo0JZh`8U%QQbvidj6;+gV%ls)98v$2Jo!80GO&qOwZ*@e{<{pGKWLr9vHkf zb%()a-vwbVh%`NCiqw335nmwpH_AB9NWqezdsiau{_bY>JclEDJ8E^Zp$7Gw7mBpw zbD`*NNv$>P{r3*9r#sR(uR)|TIiUWj^45IY&ZT0!9Wq?<6nR^+H7f=Q7{fiAbeyHB z#qckF%2Y%Cd2&(kyj4g^6R1#rP%91nO7t|dQ-Um+(gLgGDyj9b=6aHV0ba(GgK4(EY64@`E zS_Q{eax5NeXFN}Wi2=EH>zT3&Sh;sO7_%sMr(#0+d=adC=*`zzQf<>Y;j=sP6})+= z^YE>!5g}Ramd2WCH7J!%n12`g^tfXe+WC{7$;QR^zIzN4M1);@$d2msUlh8TlAQE2 ze_jZw_JC)G=_Ie~3IMP({6k2dWn$20C5D@ViVVgM5+UFX+ZvPUD*yoP`Mr?P@?1K~ zR#BtSAqp=z9Sp{7dL7)rupDTO$@_gmn1G&VNIDI~OXs)qs;=jTd9zUfjEre-0JBZ!lY zPz%(qK?`J5_-6E0C=xj~F79+^l+<9ppY!Evcfe!>E{%}h!2m&BT^$Ty+nnvmk*0|B z1qNfjydCw(5rYzL>eYrq{MsI}KsWg4iLEDFV<&pH>hsD^N z&koCGDdII0^cUG;E>t@xE(dAD{@_UgR$2(v9Uo{cfhTaNotX$ynMWib?%wZ@@Vviy@VAD<`DC=wzRZ=gMJYr z23@?Y(a!OGT!9L7KVH3m&M7^56u=t&WA!+GVZp7=A>x2y`3Dy-`4&}$Xq(d)8?BA(TO_`uX-V!Uem>w`l4R2&KvAr1eIIopk3fC(`!>v4>c=*AMgx*KFFg`Xzz*Ua)f(d~&zJAxD~C zf}5=08BFDO>VImykNT=te3}Pv1@-77MtQ!7!=q!)ylE%Oh{hdtm_L3+DJxdE>B|1a zT~9y}=I7d4g>oDEQSQ2fO@Vk%n3e$v-#6ptFmq%lN{o5;Bulbsp7%IWcl|W&`{d{n zGJ(p>A;qklJkQnfdbH1fE>HXx=bfPuDu+b+9PqX$z(%AHT-A~Le9=krjPe!JH~ukh zLcKjbNcfKfBDX^ii!Y}>#y)EzK`|dzU`P5a(hutihVVDY@WuuJ;qXkWJt#{VDnfC{ z`_#-&w!MY$ef;6O!lUACh`Y!4^iwBPXzB0F3=ttA;dAkx`-f8{h2L@YrJC-_wcqaU zuIJe{W=u>>?>y;8zMS0re0qgnwFhU<&7+=xyMHdlBF;##vArE?)uhn0NGXcc#pK2) zUNW_QbCdbaaSdFhb#w8DkWMo61wMV>I$bVqi;XDt1V-pN(uS|N01e)MME-+GH5HYI zlUoTAuc^-`{O@QIC*isV21Gkeg^|x80GU}?HpYVi1&*IST{(!Zj~E9%UBQ*!=Gv(g z_=zkR6v&sixK?xyboyL-UhLr~GfvqyhXS^?wg47Qx^&O|+~NO_T~bm~cexsJJf$HcL!zZlKrzwP)|%cZHXOe8%N}P=X2g$@mPW;htem*^)2k&p^~{wl`pNq^ zx*60phG8(vgIRZ{ON15XBubl$`vQ*g0}<#XS~!0%WsHx7PcI#bM;HG33BZe5G2oMC RJn+wORgh7Yu9Gwg{x9Bn1k3;c diff --git a/Resources/Textures/Constructible/Atmos/vent.rsi/meta.json b/Resources/Textures/Constructible/Atmos/vent.rsi/meta.json index 0346b40ada..d1c58a5057 100644 --- a/Resources/Textures/Constructible/Atmos/vent.rsi/meta.json +++ b/Resources/Textures/Constructible/Atmos/vent.rsi/meta.json @@ -9,11 +9,9 @@ "states":[ { "name":"ventOff", - "directions":4 }, { "name":"ventOn", - "directions":1, "delays":[ [ 0.08, 0.08, 0.08, 0.08 ] ] } ] diff --git a/Resources/Textures/Constructible/Atmos/vent.rsi/ventOff.png b/Resources/Textures/Constructible/Atmos/vent.rsi/ventOff.png index bda0e1482652bcde93ccda7737ad0d20716d4587..4b8d5db40e680869be57da49f1eaaa406d5a592b 100644 GIT binary patch delta 1759 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 Q?EnA(07*qoM6N<$g5XL$r2qf`