diff --git a/Content.Client/Atmos/AlignAtmosPipeLayers.cs b/Content.Client/Atmos/AlignAtmosPipeLayers.cs
new file mode 100644
index 0000000000..1bf3310a6c
--- /dev/null
+++ b/Content.Client/Atmos/AlignAtmosPipeLayers.cs
@@ -0,0 +1,203 @@
+using Content.Client.Construction;
+using Content.Shared.Atmos.Components;
+using Content.Shared.Atmos.EntitySystems;
+using Content.Shared.Construction.Prototypes;
+using Robust.Client.GameObjects;
+using Robust.Client.Graphics;
+using Robust.Client.Placement;
+using Robust.Client.Placement.Modes;
+using Robust.Client.Utility;
+using Robust.Shared.Enums;
+using Robust.Shared.Map;
+using Robust.Shared.Map.Components;
+using Robust.Shared.Prototypes;
+using Robust.Shared.Utility;
+using System.Numerics;
+using static Robust.Client.Placement.PlacementManager;
+
+namespace Content.Client.Atmos;
+
+///
+/// Allows users to place atmos pipes on different layers depending on how the mouse cursor is positioned within a grid tile.
+///
+///
+/// This placement mode is not on the engine because it is content specific.
+///
+public sealed class AlignAtmosPipeLayers : SnapgridCenter
+{
+ [Dependency] private readonly IEntityManager _entityManager = default!;
+ [Dependency] private readonly IPrototypeManager _protoManager = default!;
+ [Dependency] private readonly IMapManager _mapManager = default!;
+ [Dependency] private readonly IEyeManager _eyeManager = default!;
+
+ private readonly SharedMapSystem _mapSystem;
+ private readonly SharedTransformSystem _transformSystem;
+ private readonly SharedAtmosPipeLayersSystem _pipeLayersSystem;
+ private readonly SpriteSystem _spriteSystem;
+
+ private const float SearchBoxSize = 2f;
+ private EntityCoordinates _unalignedMouseCoords = default;
+ private const float MouseDeadzoneRadius = 0.25f;
+
+ private Color _guideColor = new Color(0, 0, 0.5785f);
+ private const float GuideRadius = 0.1f;
+ private const float GuideOffset = 0.21875f;
+
+ public AlignAtmosPipeLayers(PlacementManager pMan) : base(pMan)
+ {
+ IoCManager.InjectDependencies(this);
+
+ _mapSystem = _entityManager.System();
+ _transformSystem = _entityManager.System();
+ _pipeLayersSystem = _entityManager.System();
+ _spriteSystem = _entityManager.System();
+ }
+
+ ///
+ public override void Render(in OverlayDrawArgs args)
+ {
+ var gridUid = _entityManager.System().GetGrid(MouseCoords);
+
+ if (gridUid == null || Grid == null)
+ return;
+
+ // Draw guide circles for each pipe layer if we are not in line/grid placing mode
+ if (pManager.PlacementType == PlacementTypes.None)
+ {
+ var gridRotation = _transformSystem.GetWorldRotation(gridUid.Value);
+ var worldPosition = _mapSystem.LocalToWorld(gridUid.Value, Grid, MouseCoords.Position);
+ var direction = (_eyeManager.CurrentEye.Rotation + gridRotation + Math.PI / 2).GetCardinalDir();
+ var multi = (direction == Direction.North || direction == Direction.South) ? -1f : 1f;
+
+ args.WorldHandle.DrawCircle(worldPosition, GuideRadius, _guideColor);
+ args.WorldHandle.DrawCircle(worldPosition + gridRotation.RotateVec(new Vector2(multi * GuideOffset, GuideOffset)), GuideRadius, _guideColor);
+ args.WorldHandle.DrawCircle(worldPosition - gridRotation.RotateVec(new Vector2(multi * GuideOffset, GuideOffset)), GuideRadius, _guideColor);
+ }
+
+ base.Render(args);
+ }
+
+ ///
+ public override void AlignPlacementMode(ScreenCoordinates mouseScreen)
+ {
+ _unalignedMouseCoords = ScreenToCursorGrid(mouseScreen);
+ base.AlignPlacementMode(mouseScreen);
+
+ // Exit early if we are in line/grid placing mode
+ if (pManager.PlacementType != PlacementTypes.None)
+ return;
+
+ MouseCoords = _unalignedMouseCoords.AlignWithClosestGridTile(SearchBoxSize, _entityManager, _mapManager);
+
+ var gridId = _transformSystem.GetGrid(MouseCoords);
+
+ if (!_entityManager.TryGetComponent(gridId, out var mapGrid))
+ return;
+
+ var gridRotation = _transformSystem.GetWorldRotation(gridId.Value);
+ CurrentTile = _mapSystem.GetTileRef(gridId.Value, mapGrid, MouseCoords);
+
+ float tileSize = mapGrid.TileSize;
+ GridDistancing = tileSize;
+
+ MouseCoords = new EntityCoordinates(MouseCoords.EntityId, new Vector2(CurrentTile.X + tileSize / 2 + pManager.PlacementOffset.X,
+ CurrentTile.Y + tileSize / 2 + pManager.PlacementOffset.Y));
+
+ // Calculate the position of the mouse cursor with respect to the center of the tile to determine which layer to use
+ var mouseCoordsDiff = _unalignedMouseCoords.Position - MouseCoords.Position;
+ var layer = AtmosPipeLayer.Primary;
+
+ if (mouseCoordsDiff.Length() > MouseDeadzoneRadius)
+ {
+ // Determine the direction of the mouse is relative to the center of the tile, adjusting for the player eye and grid rotation
+ var direction = (new Angle(mouseCoordsDiff) + _eyeManager.CurrentEye.Rotation + gridRotation + Math.PI / 2).GetCardinalDir();
+ layer = (direction == Direction.North || direction == Direction.East) ? AtmosPipeLayer.Secondary : AtmosPipeLayer.Tertiary;
+ }
+
+ // Update the construction menu placer
+ if (pManager.Hijack != null)
+ UpdateHijackedPlacer(layer, mouseScreen);
+
+ // Otherwise update the debug placer
+ else
+ UpdatePlacer(layer);
+ }
+
+ private void UpdateHijackedPlacer(AtmosPipeLayer layer, ScreenCoordinates mouseScreen)
+ {
+ // Try to get alternative prototypes from the construction prototype
+ var constructionSystem = (pManager.Hijack as ConstructionPlacementHijack)?.CurrentConstructionSystem;
+ var altPrototypes = (pManager.Hijack as ConstructionPlacementHijack)?.CurrentPrototype?.AlternativePrototypes;
+
+ if (constructionSystem == null || altPrototypes == null || (int)layer >= altPrototypes.Length)
+ return;
+
+ var newProtoId = altPrototypes[(int)layer];
+
+ if (!_protoManager.TryIndex(newProtoId, out var newProto))
+ return;
+
+ if (newProto.Type != ConstructionType.Structure)
+ {
+ pManager.Clear();
+ return;
+ }
+
+ if (newProto.ID == (pManager.Hijack as ConstructionPlacementHijack)?.CurrentPrototype?.ID)
+ return;
+
+ // Start placing
+ pManager.BeginPlacing(new PlacementInformation()
+ {
+ IsTile = false,
+ PlacementOption = newProto.PlacementMode,
+ }, new ConstructionPlacementHijack(constructionSystem, newProto));
+
+ if (pManager.CurrentMode is AlignAtmosPipeLayers { } newMode)
+ newMode.RefreshGrid(mouseScreen);
+
+ // Update construction guide
+ constructionSystem.GetGuide(newProto);
+ }
+
+ private void UpdatePlacer(AtmosPipeLayer layer)
+ {
+ // Try to get alternative prototypes from the entity atmos pipe layer component
+ if (pManager.CurrentPermission?.EntityType == null)
+ return;
+
+ if (!_protoManager.TryIndex(pManager.CurrentPermission.EntityType, out var currentProto))
+ return;
+
+ if (!currentProto.TryGetComponent(out var atmosPipeLayers, _entityManager.ComponentFactory))
+ return;
+
+ if (!_pipeLayersSystem.TryGetAlternativePrototype(atmosPipeLayers, layer, out var newProtoId))
+ return;
+
+ if (_protoManager.TryIndex(newProtoId, out var newProto))
+ {
+ // Update the placed prototype
+ pManager.CurrentPermission.EntityType = newProtoId;
+
+ // Update the appearance of the ghost sprite
+ if (newProto.TryGetComponent(out var sprite, _entityManager.ComponentFactory))
+ {
+ var textures = new List();
+
+ foreach (var spriteLayer in sprite.AllLayers)
+ {
+ if (spriteLayer.ActualRsi?.Path != null && spriteLayer.RsiState.Name != null)
+ textures.Add(_spriteSystem.RsiStateLike(new SpriteSpecifier.Rsi(spriteLayer.ActualRsi.Path, spriteLayer.RsiState.Name)));
+ }
+
+ pManager.CurrentTextures = textures;
+ }
+ }
+ }
+
+ private void RefreshGrid(ScreenCoordinates mouseScreen)
+ {
+ base.AlignPlacementMode(mouseScreen);
+ }
+}
diff --git a/Content.Client/Atmos/Consoles/AtmosMonitoringConsoleNavMapControl.cs b/Content.Client/Atmos/Consoles/AtmosMonitoringConsoleNavMapControl.cs
index c23ebb6435..20902722ff 100644
--- a/Content.Client/Atmos/Consoles/AtmosMonitoringConsoleNavMapControl.cs
+++ b/Content.Client/Atmos/Consoles/AtmosMonitoringConsoleNavMapControl.cs
@@ -17,6 +17,10 @@ public sealed partial class AtmosMonitoringConsoleNavMapControl : NavMapControl
public int? FocusNetId = null;
private const int ChunkSize = 4;
+ private const float ScaleModifier = 4f;
+
+ private readonly float[] _layerFraction = { 0.5f, 0.75f, 0.25f };
+ private const float LineThickness = 0.05f;
private readonly Color _basePipeNetColor = Color.LightGray;
private readonly Color _unfocusedPipeNetColor = Color.DimGray;
@@ -95,23 +99,23 @@ public sealed partial class AtmosMonitoringConsoleNavMapControl : NavMapControl
foreach (var chunkedLine in atmosPipeNetwork)
{
var leftTop = ScalePosition(new Vector2
- (Math.Min(chunkedLine.Origin.X, chunkedLine.Terminus.X) - 0.1f,
- Math.Min(chunkedLine.Origin.Y, chunkedLine.Terminus.Y) - 0.1f)
+ (Math.Min(chunkedLine.Origin.X, chunkedLine.Terminus.X) - LineThickness,
+ Math.Min(chunkedLine.Origin.Y, chunkedLine.Terminus.Y) - LineThickness)
- offset);
var rightTop = ScalePosition(new Vector2
- (Math.Max(chunkedLine.Origin.X, chunkedLine.Terminus.X) + 0.1f,
- Math.Min(chunkedLine.Origin.Y, chunkedLine.Terminus.Y) - 0.1f)
+ (Math.Max(chunkedLine.Origin.X, chunkedLine.Terminus.X) + LineThickness,
+ Math.Min(chunkedLine.Origin.Y, chunkedLine.Terminus.Y) - LineThickness)
- offset);
var leftBottom = ScalePosition(new Vector2
- (Math.Min(chunkedLine.Origin.X, chunkedLine.Terminus.X) - 0.1f,
- Math.Max(chunkedLine.Origin.Y, chunkedLine.Terminus.Y) + 0.1f)
+ (Math.Min(chunkedLine.Origin.X, chunkedLine.Terminus.X) - LineThickness,
+ Math.Max(chunkedLine.Origin.Y, chunkedLine.Terminus.Y) + LineThickness)
- offset);
var rightBottom = ScalePosition(new Vector2
- (Math.Max(chunkedLine.Origin.X, chunkedLine.Terminus.X) + 0.1f,
- Math.Max(chunkedLine.Origin.Y, chunkedLine.Terminus.Y) + 0.1f)
+ (Math.Max(chunkedLine.Origin.X, chunkedLine.Terminus.X) + LineThickness,
+ Math.Max(chunkedLine.Origin.Y, chunkedLine.Terminus.Y) + LineThickness)
- offset);
if (!pipeVertexUVs.TryGetValue(chunkedLine.Color, out var pipeVertexUV))
@@ -142,7 +146,7 @@ public sealed partial class AtmosMonitoringConsoleNavMapControl : NavMapControl
if (chunks == null || grid == null)
return decodedOutput;
- // Clear stale look up table values
+ // Clear stale look up table values
_horizLines.Clear();
_horizLinesReversed.Clear();
_vertLines.Clear();
@@ -158,7 +162,7 @@ public sealed partial class AtmosMonitoringConsoleNavMapControl : NavMapControl
{
var list = new List();
- foreach (var ((netId, hexColor), atmosPipeData) in chunk.AtmosPipeData)
+ foreach (var ((netId, layer, hexColor), atmosPipeData) in chunk.AtmosPipeData)
{
// Determine the correct coloration for the pipe
var color = Color.FromHex(hexColor) * _basePipeNetColor;
@@ -191,6 +195,9 @@ public sealed partial class AtmosMonitoringConsoleNavMapControl : NavMapControl
_vertLinesReversed[color] = vertLinesReversed;
}
+ var layerFraction = _layerFraction[(int)layer];
+ var origin = new Vector2(grid.TileSize * layerFraction, -grid.TileSize * layerFraction);
+
// Loop over the chunk
for (var tileIdx = 0; tileIdx < ChunkSize * ChunkSize; tileIdx++)
{
@@ -208,21 +215,22 @@ public sealed partial class AtmosMonitoringConsoleNavMapControl : NavMapControl
// Calculate the draw point offsets
var vertLineOrigin = (atmosPipeData & northMask << tileIdx * SharedNavMapSystem.Directions) > 0 ?
- new Vector2(grid.TileSize * 0.5f, -grid.TileSize * 1f) : new Vector2(grid.TileSize * 0.5f, -grid.TileSize * 0.5f);
+ new Vector2(grid.TileSize * layerFraction, -grid.TileSize * 1f) : origin;
var vertLineTerminus = (atmosPipeData & southMask << tileIdx * SharedNavMapSystem.Directions) > 0 ?
- new Vector2(grid.TileSize * 0.5f, -grid.TileSize * 0f) : new Vector2(grid.TileSize * 0.5f, -grid.TileSize * 0.5f);
+ new Vector2(grid.TileSize * layerFraction, -grid.TileSize * 0f) : origin;
var horizLineOrigin = (atmosPipeData & eastMask << tileIdx * SharedNavMapSystem.Directions) > 0 ?
- new Vector2(grid.TileSize * 1f, -grid.TileSize * 0.5f) : new Vector2(grid.TileSize * 0.5f, -grid.TileSize * 0.5f);
+ new Vector2(grid.TileSize * 1f, -grid.TileSize * layerFraction) : origin;
var horizLineTerminus = (atmosPipeData & westMask << tileIdx * SharedNavMapSystem.Directions) > 0 ?
- new Vector2(grid.TileSize * 0f, -grid.TileSize * 0.5f) : new Vector2(grid.TileSize * 0.5f, -grid.TileSize * 0.5f);
+ new Vector2(grid.TileSize * 0f, -grid.TileSize * layerFraction) : origin;
- // Since we can have pipe lines that have a length of a half tile,
- // double the vectors and convert to vector2i so we can merge them
- AddOrUpdateNavMapLine(ConvertVector2ToVector2i(tile + horizLineOrigin, 2), ConvertVector2ToVector2i(tile + horizLineTerminus, 2), horizLines, horizLinesReversed);
- AddOrUpdateNavMapLine(ConvertVector2ToVector2i(tile + vertLineOrigin, 2), ConvertVector2ToVector2i(tile + vertLineTerminus, 2), vertLines, vertLinesReversed);
+ // Scale up the vectors and convert to vector2i so we can merge them
+ AddOrUpdateNavMapLine(ConvertVector2ToVector2i(tile + horizLineOrigin, ScaleModifier),
+ ConvertVector2ToVector2i(tile + horizLineTerminus, ScaleModifier), horizLines, horizLinesReversed);
+ AddOrUpdateNavMapLine(ConvertVector2ToVector2i(tile + vertLineOrigin, ScaleModifier),
+ ConvertVector2ToVector2i(tile + vertLineTerminus, ScaleModifier), vertLines, vertLinesReversed);
}
}
}
@@ -235,7 +243,7 @@ public sealed partial class AtmosMonitoringConsoleNavMapControl : NavMapControl
foreach (var (origin, terminal) in horizLines)
decodedOutput.Add(new AtmosMonitoringConsoleLine
- (ConvertVector2iToVector2(origin, 0.5f), ConvertVector2iToVector2(terminal, 0.5f), sRGB));
+ (ConvertVector2iToVector2(origin, 1f / ScaleModifier), ConvertVector2iToVector2(terminal, 1f / ScaleModifier), sRGB));
}
foreach (var (color, vertLines) in _vertLines)
@@ -245,7 +253,7 @@ public sealed partial class AtmosMonitoringConsoleNavMapControl : NavMapControl
foreach (var (origin, terminal) in vertLines)
decodedOutput.Add(new AtmosMonitoringConsoleLine
- (ConvertVector2iToVector2(origin, 0.5f), ConvertVector2iToVector2(terminal, 0.5f), sRGB));
+ (ConvertVector2iToVector2(origin, 1f / ScaleModifier), ConvertVector2iToVector2(terminal, 1f / ScaleModifier), sRGB));
}
return decodedOutput;
diff --git a/Content.Client/Atmos/Consoles/AtmosMonitoringConsoleSystem.cs b/Content.Client/Atmos/Consoles/AtmosMonitoringConsoleSystem.cs
index bfbb05d2ab..6a4967e4a4 100644
--- a/Content.Client/Atmos/Consoles/AtmosMonitoringConsoleSystem.cs
+++ b/Content.Client/Atmos/Consoles/AtmosMonitoringConsoleSystem.cs
@@ -15,7 +15,7 @@ public sealed class AtmosMonitoringConsoleSystem : SharedAtmosMonitoringConsoleS
private void OnHandleState(EntityUid uid, AtmosMonitoringConsoleComponent component, ref ComponentHandleState args)
{
- Dictionary> modifiedChunks;
+ Dictionary> modifiedChunks;
Dictionary atmosDevices;
switch (args.Current)
@@ -54,7 +54,7 @@ public sealed class AtmosMonitoringConsoleSystem : SharedAtmosMonitoringConsoleS
foreach (var (origin, chunk) in modifiedChunks)
{
var newChunk = new AtmosPipeChunk(origin);
- newChunk.AtmosPipeData = new Dictionary<(int, string), ulong>(chunk);
+ newChunk.AtmosPipeData = new Dictionary(chunk);
component.AtmosPipeChunks[origin] = newChunk;
}
diff --git a/Content.Client/Atmos/Consoles/AtmosMonitoringConsoleWindow.xaml.cs b/Content.Client/Atmos/Consoles/AtmosMonitoringConsoleWindow.xaml.cs
index e25c3af9e9..1a084ea73b 100644
--- a/Content.Client/Atmos/Consoles/AtmosMonitoringConsoleWindow.xaml.cs
+++ b/Content.Client/Atmos/Consoles/AtmosMonitoringConsoleWindow.xaml.cs
@@ -13,6 +13,7 @@ using Robust.Shared.Timing;
using Robust.Shared.Utility;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
+using System.Numerics;
namespace Content.Client.Atmos.Consoles;
@@ -33,6 +34,8 @@ public sealed partial class AtmosMonitoringConsoleWindow : FancyWindow
private ProtoId _navMapConsoleProtoId = "NavMapConsole";
private ProtoId _gasPipeSensorProtoId = "GasPipeSensor";
+ private readonly Vector2[] _pipeLayerOffsets = { new Vector2(0f, 0f), new Vector2(0.25f, 0.25f), new Vector2(-0.25f, -0.25f) };
+
public AtmosMonitoringConsoleWindow(AtmosMonitoringConsoleBoundUserInterface userInterface, EntityUid? owner)
{
RobustXamlLoader.Load(this);
@@ -53,7 +56,7 @@ public sealed partial class AtmosMonitoringConsoleWindow : FancyWindow
consoleCoords = xform.Coordinates;
NavMap.MapUid = xform.GridUid;
- // Assign station name
+ // Assign station name
if (_entManager.TryGetComponent(xform.GridUid, out var stationMetaData))
stationName = stationMetaData.EntityName;
@@ -238,6 +241,10 @@ public sealed partial class AtmosMonitoringConsoleWindow : FancyWindow
var blinks = proto.Blinks || _focusEntity == metaData.NetEntity;
var coords = _entManager.GetCoordinates(metaData.NetCoordinates);
+
+ if (proto.Placement == NavMapBlipPlacement.Offset && metaData.PipeLayer > 0)
+ coords = coords.Offset(_pipeLayerOffsets[(int)metaData.PipeLayer]);
+
var blip = new NavMapBlip(coords, _spriteSystem.Frame0(new SpriteSpecifier.Texture(texture)), color, blinks, proto.Selectable, proto.Scale);
NavMap.TrackedEntities[metaData.NetEntity] = blip;
}
diff --git a/Content.Client/Atmos/EntitySystems/AtmosPipeAppearanceSystem.cs b/Content.Client/Atmos/EntitySystems/AtmosPipeAppearanceSystem.cs
index 2029cb9be5..1a12c3967b 100644
--- a/Content.Client/Atmos/EntitySystems/AtmosPipeAppearanceSystem.cs
+++ b/Content.Client/Atmos/EntitySystems/AtmosPipeAppearanceSystem.cs
@@ -1,6 +1,7 @@
using Content.Client.SubFloor;
using Content.Shared.Atmos;
using Content.Shared.Atmos.Components;
+using Content.Shared.Atmos.EntitySystems;
using Content.Shared.Atmos.Piping;
using JetBrains.Annotations;
using Robust.Client.GameObjects;
@@ -8,7 +9,7 @@ using Robust.Client.GameObjects;
namespace Content.Client.Atmos.EntitySystems;
[UsedImplicitly]
-public sealed class AtmosPipeAppearanceSystem : EntitySystem
+public sealed partial class AtmosPipeAppearanceSystem : SharedAtmosPipeAppearanceSystem
{
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
[Dependency] private readonly SpriteSystem _sprite = default!;
@@ -26,26 +27,37 @@ public sealed class AtmosPipeAppearanceSystem : EntitySystem
if (!TryComp(uid, out SpriteComponent? sprite))
return;
+ var numberOfPipeLayers = GetNumberOfPipeLayers(uid, out _);
+
foreach (var layerKey in Enum.GetValues())
{
- var layer = _sprite.LayerMapReserve((uid, sprite), layerKey);
- _sprite.LayerSetRsi((uid, sprite), layer, component.Sprite.RsiPath);
- _sprite.LayerSetRsiState((uid, sprite), layer, component.Sprite.RsiState);
- _sprite.LayerSetDirOffset((uid, sprite), layer, ToOffset(layerKey));
+ for (byte i = 0; i < numberOfPipeLayers; i++)
+ {
+ var layerName = layerKey.ToString() + i.ToString();
+ var layer = _sprite.LayerMapReserve((uid, sprite), layerName);
+ _sprite.LayerSetRsi((uid, sprite), layer, component.Sprite[i].RsiPath);
+ _sprite.LayerSetRsiState((uid, sprite), layer, component.Sprite[i].RsiState);
+ _sprite.LayerSetDirOffset((uid, sprite), layer, ToOffset(layerKey));
+ }
}
}
- private void HideAllPipeConnection(Entity entity)
+ private void HideAllPipeConnection(Entity entity, AtmosPipeLayersComponent? atmosPipeLayers, int numberOfPipeLayers)
{
var sprite = entity.Comp;
foreach (var layerKey in Enum.GetValues())
{
- if (!_sprite.LayerMapTryGet(entity.AsNullable(), layerKey, out var key, false))
- continue;
+ for (byte i = 0; i < numberOfPipeLayers; i++)
+ {
+ var layerName = layerKey.ToString() + i.ToString();
- var layer = sprite[key];
- layer.Visible = false;
+ if (!_sprite.LayerMapTryGet(entity.AsNullable(), layerName, out var key, false))
+ continue;
+
+ var layer = sprite[key];
+ layer.Visible = false;
+ }
}
}
@@ -61,33 +73,45 @@ public sealed class AtmosPipeAppearanceSystem : EntitySystem
return;
}
- if (!_appearance.TryGetData(uid, PipeVisuals.VisualState, out var worldConnectedDirections, args.Component))
+ var numberOfPipeLayers = GetNumberOfPipeLayers(uid, out var atmosPipeLayers);
+
+ if (!_appearance.TryGetData(uid, PipeVisuals.VisualState, out var worldConnectedDirections, args.Component))
{
- HideAllPipeConnection((uid, args.Sprite));
+ HideAllPipeConnection((uid, args.Sprite), atmosPipeLayers, numberOfPipeLayers);
return;
}
if (!_appearance.TryGetData(uid, PipeColorVisuals.Color, out var color, args.Component))
color = Color.White;
- // transform connected directions to local-coordinates
- var connectedDirections = worldConnectedDirections.RotatePipeDirection(-Transform(uid).LocalRotation);
-
- foreach (var layerKey in Enum.GetValues())
+ for (byte i = 0; i < numberOfPipeLayers; i++)
{
- if (!_sprite.LayerMapTryGet((uid, args.Sprite), layerKey, out var key, false))
- continue;
+ // Extract the cardinal pipe orientations for the current pipe layer
+ // '15' is the four bit mask that is used to extract the pipe orientations of interest from 'worldConnectedDirections'
+ // Fun fact: a collection of four bits is called a 'nibble'! They aren't natively supported :(
+ var pipeLayerConnectedDirections = (PipeDirection)(15 & (worldConnectedDirections >> (PipeDirectionHelpers.PipeDirections * i)));
- var layer = args.Sprite[key];
- var dir = (PipeDirection)layerKey;
- var visible = connectedDirections.HasDirection(dir);
+ // Transform the connected directions to local-coordinates
+ var connectedDirections = pipeLayerConnectedDirections.RotatePipeDirection(-Transform(uid).LocalRotation);
- layer.Visible &= visible;
+ foreach (var layerKey in Enum.GetValues())
+ {
+ var layerName = layerKey.ToString() + i.ToString();
- if (!visible)
- continue;
+ if (!_sprite.LayerMapTryGet((uid, args.Sprite), layerName, out var key, false))
+ continue;
- layer.Color = color;
+ var layer = args.Sprite[key];
+ var dir = (PipeDirection)layerKey;
+ var visible = connectedDirections.HasDirection(dir);
+
+ layer.Visible &= visible;
+
+ if (!visible)
+ continue;
+
+ layer.Color = color;
+ }
}
}
diff --git a/Content.Client/Atmos/EntitySystems/AtmosPipeLayersSystem.cs b/Content.Client/Atmos/EntitySystems/AtmosPipeLayersSystem.cs
new file mode 100644
index 0000000000..f560e0b833
--- /dev/null
+++ b/Content.Client/Atmos/EntitySystems/AtmosPipeLayersSystem.cs
@@ -0,0 +1,56 @@
+using Content.Shared.Atmos.Components;
+using Content.Shared.Atmos.EntitySystems;
+using Robust.Client.GameObjects;
+using Robust.Client.ResourceManagement;
+using Robust.Shared.Reflection;
+using Robust.Shared.Serialization.TypeSerializers.Implementations;
+using Robust.Shared.Utility;
+using System.Diagnostics.CodeAnalysis;
+
+namespace Content.Client.Atmos.EntitySystems;
+
+///
+/// The system responsible for updating the appearance of layered gas pipe
+///
+public sealed partial class AtmosPipeLayersSystem : SharedAtmosPipeLayersSystem
+{
+ [Dependency] private readonly SharedAppearanceSystem _appearance = default!;
+ [Dependency] private readonly IReflectionManager _reflection = default!;
+ [Dependency] private readonly IResourceCache _resourceCache = default!;
+ [Dependency] private readonly SpriteSystem _sprite = default!;
+
+ public override void Initialize()
+ {
+ base.Initialize();
+
+ SubscribeLocalEvent(OnAppearanceChange);
+ }
+
+ private void OnAppearanceChange(Entity ent, ref AppearanceChangeEvent ev)
+ {
+ if (!TryComp(ent, out var sprite))
+ return;
+
+ if (_appearance.TryGetData(ent, AtmosPipeLayerVisuals.Sprite, out var spriteRsi) &&
+ _resourceCache.TryGetResource(SpriteSpecifierSerializer.TextureRoot / spriteRsi, out RSIResource? resource))
+ {
+ _sprite.SetBaseRsi((ent, sprite), resource.RSI);
+ }
+
+ if (_appearance.TryGetData>(ent, AtmosPipeLayerVisuals.SpriteLayers, out var pipeState))
+ {
+ foreach (var (layerKey, rsiPath) in pipeState)
+ {
+ if (TryParseKey(layerKey, out var @enum))
+ _sprite.LayerSetRsi((ent, sprite), @enum, new ResPath(rsiPath));
+ else
+ _sprite.LayerSetRsi((ent, sprite), layerKey, new ResPath(rsiPath));
+ }
+ }
+ }
+
+ private bool TryParseKey(string keyString, [NotNullWhen(true)] out Enum? @enum)
+ {
+ return _reflection.TryParseEnumReference(keyString, out @enum);
+ }
+}
diff --git a/Content.Client/Atmos/UI/GasAnalyzerWindow.xaml.cs b/Content.Client/Atmos/UI/GasAnalyzerWindow.xaml.cs
index bb24da44e1..e280523e43 100644
--- a/Content.Client/Atmos/UI/GasAnalyzerWindow.xaml.cs
+++ b/Content.Client/Atmos/UI/GasAnalyzerWindow.xaml.cs
@@ -136,6 +136,7 @@ namespace Content.Client.Atmos.UI
else
{
// oh shit of fuck its more than 4 this ui isn't gonna look pretty anymore
+ CDeviceMixes.RemoveAllChildren();
for (var i = 1; i < msg.NodeGasMixes.Length; i++)
{
GenerateGasDisplay(msg.NodeGasMixes[i], CDeviceMixes);
diff --git a/Content.Client/Construction/ConstructionPlacementHijack.cs b/Content.Client/Construction/ConstructionPlacementHijack.cs
index e6a8e0f1f0..79112a8f8e 100644
--- a/Content.Client/Construction/ConstructionPlacementHijack.cs
+++ b/Content.Client/Construction/ConstructionPlacementHijack.cs
@@ -1,4 +1,4 @@
-using System.Linq;
+using System.Linq;
using Content.Shared.Construction.Prototypes;
using Robust.Client.GameObjects;
using Robust.Client.Placement;
@@ -13,6 +13,9 @@ namespace Content.Client.Construction
private readonly ConstructionSystem _constructionSystem;
private readonly ConstructionPrototype? _prototype;
+ public ConstructionSystem? CurrentConstructionSystem { get { return _constructionSystem; } }
+ public ConstructionPrototype? CurrentPrototype { get { return _prototype; } }
+
public override bool CanRotate { get; }
public ConstructionPlacementHijack(ConstructionSystem constructionSystem, ConstructionPrototype? prototype)
diff --git a/Content.Server/Atmos/Consoles/AtmosMonitoringConsoleSystem.cs b/Content.Server/Atmos/Consoles/AtmosMonitoringConsoleSystem.cs
index 532ba04d29..a7debbdc80 100644
--- a/Content.Server/Atmos/Consoles/AtmosMonitoringConsoleSystem.cs
+++ b/Content.Server/Atmos/Consoles/AtmosMonitoringConsoleSystem.cs
@@ -282,16 +282,11 @@ public sealed class AtmosMonitoringConsoleSystem : SharedAtmosMonitoringConsoleS
return false;
var direction = xform.LocalRotation.GetCardinalDir();
+ var netId = TryGettingFirstPipeNode(uid, out var _, out var firstNetId) ? firstNetId : -1;
+ var color = TryComp(uid, out var atmosPipeColor) ? atmosPipeColor.Color : Color.White;
+ var layer = TryComp(uid, out var atmosPipeLayers) ? atmosPipeLayers.CurrentPipeLayer : AtmosPipeLayer.Primary;
- if (!TryGettingFirstPipeNode(uid, out var _, out var netId))
- netId = -1;
-
- var color = Color.White;
-
- if (TryComp(uid, out var atmosPipeColor))
- color = atmosPipeColor.Color;
-
- device = new AtmosDeviceNavMapData(GetNetEntity(uid), GetNetCoordinates(xform.Coordinates), netId.Value, component.NavMapBlip.Value, direction, color);
+ device = new AtmosDeviceNavMapData(GetNetEntity(uid), GetNetCoordinates(xform.Coordinates), netId.Value, component.NavMapBlip.Value, direction, color, layer);
return true;
}
@@ -371,7 +366,9 @@ public sealed class AtmosMonitoringConsoleSystem : SharedAtmosMonitoringConsoleS
if (!TryComp(ent, out var entNodeContainer))
continue;
- UpdateAtmosPipeChunk(ent, entNodeContainer, entAtmosPipeColor, tileIdx, ref chunk);
+ var showAbsentConnections = TryComp(ent, out var device) ? device.ShowAbsentConnections : true;
+
+ UpdateAtmosPipeChunk(ent, entNodeContainer, entAtmosPipeColor, tileIdx, ref chunk, showAbsentConnections);
}
// Add or update the chunk on the associated grid
@@ -393,7 +390,13 @@ public sealed class AtmosMonitoringConsoleSystem : SharedAtmosMonitoringConsoleS
}
}
- private void UpdateAtmosPipeChunk(EntityUid uid, NodeContainerComponent nodeContainer, AtmosPipeColorComponent pipeColor, int tileIdx, ref AtmosPipeChunk chunk)
+ private void UpdateAtmosPipeChunk
+ (EntityUid uid,
+ NodeContainerComponent nodeContainer,
+ AtmosPipeColorComponent pipeColor,
+ int tileIdx,
+ ref AtmosPipeChunk chunk,
+ bool showAbsentConnections = true)
{
// Entities that are actively being deleted are not to be drawn
if (MetaData(uid).EntityLifeStage >= EntityLifeStage.Terminating)
@@ -401,16 +404,19 @@ public sealed class AtmosMonitoringConsoleSystem : SharedAtmosMonitoringConsoleS
foreach ((var id, var node) in nodeContainer.Nodes)
{
- if (node is not PipeNode)
+ if (node is not PipeNode { } pipeNode)
+ continue;
+
+ if (!showAbsentConnections && !pipeNode.ReachableNodes.Any(x => x.Owner != uid))
continue;
- var pipeNode = (PipeNode)node;
var netId = GetPipeNodeNetId(pipeNode);
+ var subnet = new AtmosMonitoringConsoleSubnet(netId, pipeNode.CurrentPipeLayer, pipeColor.Color.ToHex());
var pipeDirection = pipeNode.CurrentPipeDirection;
- chunk.AtmosPipeData.TryGetValue((netId, pipeColor.Color.ToHex()), out var atmosPipeData);
+ chunk.AtmosPipeData.TryGetValue(subnet, out var atmosPipeData);
atmosPipeData |= (ulong)pipeDirection << tileIdx * SharedNavMapSystem.Directions;
- chunk.AtmosPipeData[(netId, pipeColor.Color.ToHex())] = atmosPipeData;
+ chunk.AtmosPipeData[subnet] = atmosPipeData;
}
}
diff --git a/Content.Server/Atmos/EntitySystems/AtmosPipeLayersSystem.cs b/Content.Server/Atmos/EntitySystems/AtmosPipeLayersSystem.cs
new file mode 100644
index 0000000000..0cb804bdbd
--- /dev/null
+++ b/Content.Server/Atmos/EntitySystems/AtmosPipeLayersSystem.cs
@@ -0,0 +1,77 @@
+using Content.Server.Atmos.Components;
+using Content.Server.NodeContainer.EntitySystems;
+using Content.Server.NodeContainer.NodeGroups;
+using Content.Server.NodeContainer.Nodes;
+using Content.Shared.Atmos.Components;
+using Content.Shared.Atmos.EntitySystems;
+using Content.Shared.Construction.Components;
+using Content.Shared.NodeContainer;
+using Content.Shared.Popups;
+
+namespace Content.Server.Atmos.EntitySystems;
+
+///
+/// The system responsible for checking and adjusting the connection layering of gas pipes
+///
+public sealed partial class AtmosPipeLayersSystem : SharedAtmosPipeLayersSystem
+{
+ [Dependency] private readonly NodeGroupSystem _nodeGroup = default!;
+ [Dependency] private readonly PipeRestrictOverlapSystem _pipeRestrictOverlap = default!;
+ [Dependency] private readonly SharedPopupSystem _popup = default!;
+ [Dependency] private readonly SharedTransformSystem _xform = default!;
+
+ public override void Initialize()
+ {
+ base.Initialize();
+
+ SubscribeLocalEvent(OnInit);
+ }
+
+ private void OnInit(Entity ent, ref ComponentInit args)
+ {
+ SetPipeLayer(ent, ent.Comp.CurrentPipeLayer);
+ }
+
+ ///
+ public override void SetPipeLayer(Entity ent, AtmosPipeLayer layer, EntityUid? user = null, EntityUid? used = null)
+ {
+ if (ent.Comp.PipeLayersLocked)
+ return;
+
+ base.SetPipeLayer(ent, layer);
+
+ if (!TryComp(ent, out var nodeContainer))
+ return;
+
+ // Update the layer values of all pipe nodes associated with the entity
+ foreach (var (id, node) in nodeContainer.Nodes)
+ {
+ if (node is not PipeNode { } pipeNode)
+ continue;
+
+ if (pipeNode.CurrentPipeLayer == ent.Comp.CurrentPipeLayer)
+ continue;
+
+ pipeNode.CurrentPipeLayer = ent.Comp.CurrentPipeLayer;
+
+ if (pipeNode.NodeGroup != null)
+ _nodeGroup.QueueRemakeGroup((BaseNodeGroup)pipeNode.NodeGroup);
+ }
+
+ // If a user wasn't responsible for unanchoring the pipe, leave it be
+ if (user == null || used == null)
+ return;
+
+ // Unanchor the pipe if its new layer overlaps with another pipe
+ var xform = Transform(ent);
+
+ if (!HasComp(ent) || !_pipeRestrictOverlap.CheckOverlap((ent, nodeContainer, xform)))
+ return;
+
+ RaiseLocalEvent(ent, new BeforeUnanchoredEvent(user.Value, used.Value));
+ _xform.Unanchor(ent, xform);
+ RaiseLocalEvent(ent, new UserUnanchoredEvent(user.Value, used.Value));
+
+ _popup.PopupEntity(Loc.GetString("pipe-restrict-overlap-popup-blocked", ("pipe", ent)), ent, user.Value);
+ }
+}
diff --git a/Content.Server/Atmos/EntitySystems/PipeRestrictOverlapSystem.cs b/Content.Server/Atmos/EntitySystems/PipeRestrictOverlapSystem.cs
index f64aff47f4..351a754105 100644
--- a/Content.Server/Atmos/EntitySystems/PipeRestrictOverlapSystem.cs
+++ b/Content.Server/Atmos/EntitySystems/PipeRestrictOverlapSystem.cs
@@ -4,6 +4,7 @@ using Content.Server.NodeContainer;
using Content.Server.NodeContainer.Nodes;
using Content.Server.Popups;
using Content.Shared.Atmos;
+using Content.Shared.Atmos.Components;
using Content.Shared.Construction.Components;
using Content.Shared.NodeContainer;
using JetBrains.Annotations;
@@ -97,27 +98,27 @@ public sealed class PipeRestrictOverlapSystem : EntitySystem
public bool PipeNodesOverlap(Entity ent, Entity other)
{
- var entDirs = GetAllDirections(ent).ToList();
- var otherDirs = GetAllDirections(other).ToList();
+ var entDirsAndLayers = GetAllDirectionsAndLayers(ent).ToList();
+ var otherDirsAndLayers = GetAllDirectionsAndLayers(other).ToList();
- foreach (var dir in entDirs)
+ foreach (var (dir, layer) in entDirsAndLayers)
{
- foreach (var otherDir in otherDirs)
+ foreach (var (otherDir, otherLayer) in otherDirsAndLayers)
{
- if ((dir & otherDir) != 0)
+ if ((dir & otherDir) != 0 && layer == otherLayer)
return true;
}
}
return false;
- IEnumerable GetAllDirections(Entity pipe)
+ IEnumerable<(PipeDirection, AtmosPipeLayer)> GetAllDirectionsAndLayers(Entity pipe)
{
foreach (var node in pipe.Comp1.Nodes.Values)
{
// we need to rotate the pipe manually like this because the rotation doesn't update for pipes that are unanchored.
if (node is PipeNode pipeNode)
- yield return pipeNode.OriginalPipeDirection.RotatePipeDirection(pipe.Comp2.LocalRotation);
+ yield return (pipeNode.OriginalPipeDirection.RotatePipeDirection(pipe.Comp2.LocalRotation), pipeNode.CurrentPipeLayer);
}
}
}
diff --git a/Content.Server/Atmos/Piping/Components/GasPipeManifoldComponent.cs b/Content.Server/Atmos/Piping/Components/GasPipeManifoldComponent.cs
new file mode 100644
index 0000000000..ded2ffcb07
--- /dev/null
+++ b/Content.Server/Atmos/Piping/Components/GasPipeManifoldComponent.cs
@@ -0,0 +1,11 @@
+namespace Content.Server.Atmos.Piping.Components;
+
+[RegisterComponent]
+public sealed partial class GasPipeManifoldComponent : Component
+{
+ [DataField("inlets")]
+ public HashSet InletNames { get; set; } = new() { "south0", "south1", "south2" };
+
+ [DataField("outlets")]
+ public HashSet OutletNames { get; set; } = new() { "north0", "north1", "north2" };
+}
diff --git a/Content.Server/Atmos/Piping/EntitySystems/AtmosPipeAppearanceSystem.cs b/Content.Server/Atmos/Piping/EntitySystems/AtmosPipeAppearanceSystem.cs
index 3e14fea2d8..17f9d4652f 100644
--- a/Content.Server/Atmos/Piping/EntitySystems/AtmosPipeAppearanceSystem.cs
+++ b/Content.Server/Atmos/Piping/EntitySystems/AtmosPipeAppearanceSystem.cs
@@ -1,14 +1,14 @@
-using Content.Server.NodeContainer;
using Content.Server.NodeContainer.EntitySystems;
using Content.Server.NodeContainer.Nodes;
using Content.Shared.Atmos;
using Content.Shared.Atmos.Components;
+using Content.Shared.Atmos.EntitySystems;
using Content.Shared.NodeContainer;
using Robust.Shared.Map.Components;
namespace Content.Server.Atmos.Piping.EntitySystems;
-public sealed class AtmosPipeAppearanceSystem : EntitySystem
+public sealed partial class AtmosPipeAppearanceSystem : SharedAtmosPipeAppearanceSystem
{
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
[Dependency] private readonly SharedMapSystem _map = default!;
@@ -34,9 +34,12 @@ public sealed class AtmosPipeAppearanceSystem : EntitySystem
if (!TryComp(xform.GridUid, out var grid))
return;
+ var numberOfPipeLayers = GetNumberOfPipeLayers(uid, out var atmosPipeLayers);
+
// get connected entities
var anyPipeNodes = false;
- HashSet connected = new();
+ HashSet<(EntityUid, AtmosPipeLayer)> connected = new();
+
foreach (var node in container.Nodes.Values)
{
if (node is not PipeNode)
@@ -46,8 +49,8 @@ public sealed class AtmosPipeAppearanceSystem : EntitySystem
foreach (var connectedNode in node.ReachableNodes)
{
- if (connectedNode is PipeNode)
- connected.Add(connectedNode.Owner);
+ if (connectedNode is PipeNode { } pipeNode)
+ connected.Add((connectedNode.Owner, pipeNode.CurrentPipeLayer));
}
}
@@ -55,14 +58,22 @@ public sealed class AtmosPipeAppearanceSystem : EntitySystem
return;
// find the cardinal directions of any connected entities
- var netConnectedDirections = PipeDirection.None;
- var tile = _map.TileIndicesFor((xform.GridUid.Value, grid), xform.Coordinates);
- foreach (var neighbour in connected)
- {
- // TODO z-levels, pipes across grids - we shouldn't assume that the neighboring tile's transform is on the same grid
- var otherTile = _map.TileIndicesFor((xform.GridUid.Value, grid), Transform(neighbour).Coordinates);
+ var connectedDirections = new PipeDirection[numberOfPipeLayers];
+ Array.Fill(connectedDirections, PipeDirection.None);
- netConnectedDirections |= (otherTile - tile) switch
+ var tile = _map.TileIndicesFor(xform.GridUid.Value, grid, xform.Coordinates);
+
+ foreach (var (neighbour, pipeLayer) in connected)
+ {
+ var pipeIndex = (int)pipeLayer;
+
+ if (pipeIndex >= numberOfPipeLayers)
+ continue;
+
+ var otherTile = _map.TileIndicesFor(xform.GridUid.Value, grid, Transform(neighbour).Coordinates);
+ var pipeLayerDirections = connectedDirections[pipeIndex];
+
+ pipeLayerDirections |= (otherTile - tile) switch
{
(0, 1) => PipeDirection.North,
(0, -1) => PipeDirection.South,
@@ -70,8 +81,16 @@ public sealed class AtmosPipeAppearanceSystem : EntitySystem
(-1, 0) => PipeDirection.West,
_ => PipeDirection.None
};
+
+ connectedDirections[pipeIndex] = pipeLayerDirections;
}
+ // Convert the pipe direction array into a single int for serialization
+ var netConnectedDirections = 0;
+
+ for (var i = numberOfPipeLayers - 1; i >= 0; i--)
+ netConnectedDirections += (int)connectedDirections[i] << (PipeDirectionHelpers.PipeDirections * i);
+
_appearance.SetData(uid, PipeVisuals.VisualState, netConnectedDirections, appearance);
}
}
diff --git a/Content.Server/Atmos/Piping/EntitySystems/GasPipeManifoldSystem.cs b/Content.Server/Atmos/Piping/EntitySystems/GasPipeManifoldSystem.cs
new file mode 100644
index 0000000000..bb7678d28d
--- /dev/null
+++ b/Content.Server/Atmos/Piping/EntitySystems/GasPipeManifoldSystem.cs
@@ -0,0 +1,68 @@
+using Content.Server.Atmos.EntitySystems;
+using Content.Server.Atmos.Piping.Components;
+using Content.Server.NodeContainer.EntitySystems;
+using Content.Server.NodeContainer.Nodes;
+using Content.Shared.Atmos;
+using Content.Shared.NodeContainer;
+using System.Linq;
+
+namespace Content.Server.Atmos.Piping.EntitySystems;
+
+public sealed partial class GasPipeManifoldSystem : EntitySystem
+{
+ [Dependency] private readonly NodeContainerSystem _nodeContainer = default!;
+
+ public override void Initialize()
+ {
+ base.Initialize();
+
+ SubscribeLocalEvent(OnCompInit);
+ SubscribeLocalEvent(OnAnalyzed);
+ }
+
+ private void OnCompInit(Entity ent, ref ComponentInit args)
+ {
+ if (!TryComp(ent, out var nodeContainer))
+ return;
+
+ foreach (var inletName in ent.Comp.InletNames)
+ {
+ if (!_nodeContainer.TryGetNode(nodeContainer, inletName, out PipeNode? inlet))
+ continue;
+
+ foreach (var outletName in ent.Comp.OutletNames)
+ {
+ if (!_nodeContainer.TryGetNode(nodeContainer, outletName, out PipeNode? outlet))
+ continue;
+
+ inlet.AddAlwaysReachable(outlet);
+ outlet.AddAlwaysReachable(inlet);
+ }
+ }
+ }
+
+ private void OnAnalyzed(Entity ent, ref GasAnalyzerScanEvent args)
+ {
+ // All inlets and outlets have the same gas mixture
+
+ args.GasMixtures = new List<(string, GasMixture?)>();
+
+ if (!TryComp(ent, out var nodeContainer))
+ return;
+
+ var pipeNames = ent.Comp.InletNames.Union(ent.Comp.OutletNames);
+
+ foreach (var pipeName in pipeNames)
+ {
+ if (!_nodeContainer.TryGetNode(nodeContainer, pipeName, out PipeNode? pipe))
+ continue;
+
+ var pipeLocal = pipe.Air.Clone();
+ pipeLocal.Multiply(pipe.Volume / pipe.Air.Volume);
+ pipeLocal.Volume = pipe.Volume;
+
+ args.GasMixtures.Add((Name(ent), pipeLocal));
+ break;
+ }
+ }
+}
diff --git a/Content.Server/NodeContainer/Nodes/PipeNode.cs b/Content.Server/NodeContainer/Nodes/PipeNode.cs
index d30d3b1777..3a76666a2c 100644
--- a/Content.Server/NodeContainer/Nodes/PipeNode.cs
+++ b/Content.Server/NodeContainer/Nodes/PipeNode.cs
@@ -1,10 +1,8 @@
-using Content.Server.Atmos;
using Content.Server.NodeContainer.EntitySystems;
using Content.Server.NodeContainer.NodeGroups;
using Content.Shared.Atmos;
+using Content.Shared.Atmos.Components;
using Content.Shared.NodeContainer;
-using Content.Shared.NodeContainer.NodeGroups;
-using Robust.Shared.Map;
using Robust.Shared.Map.Components;
using Robust.Shared.Utility;
@@ -12,7 +10,7 @@ namespace Content.Server.NodeContainer.Nodes
{
///
/// Connects with other s whose
- /// correctly correspond.
+ /// and correctly correspond.
///
[DataDefinition]
[Virtual]
@@ -24,6 +22,12 @@ namespace Content.Server.NodeContainer.Nodes
[DataField("pipeDirection")]
public PipeDirection OriginalPipeDirection;
+ ///
+ /// The *current* layer to which the pipe node is assigned.
+ ///
+ [DataField("pipeLayer")]
+ public AtmosPipeLayer CurrentPipeLayer = AtmosPipeLayer.Primary;
+
///
/// The *current* pipe directions (accounting for rotation)
/// Used to check if this pipe can connect to another pipe in a given direction.
@@ -204,6 +208,7 @@ namespace Content.Server.NodeContainer.Nodes
foreach (var pipe in PipesInDirection(pos, pipeDir, grid, nodeQuery))
{
if (pipe.NodeGroupID == NodeGroupID
+ && pipe.CurrentPipeLayer == CurrentPipeLayer
&& pipe.CurrentPipeDirection.HasDirection(pipeDir.GetOpposite()))
{
yield return pipe;
diff --git a/Content.Shared/Atmos/Components/AtmosPipeLayersComponent.cs b/Content.Shared/Atmos/Components/AtmosPipeLayersComponent.cs
new file mode 100644
index 0000000000..3081bb8d01
--- /dev/null
+++ b/Content.Shared/Atmos/Components/AtmosPipeLayersComponent.cs
@@ -0,0 +1,122 @@
+using Content.Shared.Atmos.EntitySystems;
+using Content.Shared.DoAfter;
+using Content.Shared.Tools;
+using Robust.Shared.GameStates;
+using Robust.Shared.Prototypes;
+using Robust.Shared.Serialization;
+
+namespace Content.Shared.Atmos.Components;
+
+///
+/// Contains layer data for atmos pipes. Layers allow multiple atmos pipes with the
+/// same orientation to be anchored to the same tile without their contents mixing.
+///
+[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
+[Access(typeof(SharedAtmosPipeLayersSystem))]
+public sealed partial class AtmosPipeLayersComponent : Component
+{
+ ///
+ /// The number of pipe layers this entity supports.
+ /// Must be equal to or less than the number of values
+ /// in .
+ ///
+ [DataField]
+ public byte NumberOfPipeLayers = 3;
+
+ ///
+ /// Determines which layer the pipe is currently assigned.
+ /// Only pipes on the same layer can connect with each other.
+ ///
+ [DataField("pipeLayer"), AutoNetworkedField]
+ [ViewVariables(VVAccess.ReadOnly)]
+ public AtmosPipeLayer CurrentPipeLayer = AtmosPipeLayer.Primary;
+
+ ///
+ /// The RSI paths that the entity will use to update its sprite when its pipe layer changes;
+ /// if empty, the entity sprite will not update when it pipe layer changes.
+ /// If you want to set specific sprite layers to update when the pipe layer changes, use
+ /// instead.
+ ///
+ ///
+ /// If the dictionary is not empty there should be an entry for each atmos pipe layer.
+ ///
+ [DataField]
+ public Dictionary SpriteRsiPaths = new();
+
+ ///
+ /// Used to update specific sprite layers when the entity's pipe layer changes.
+ /// The dictionary key is the name of the sprite layer to be updated, and its value is
+ /// a second dictionary which contains the RSI paths indexed by pipe layer.
+ /// If you want to change the default RSI path used by the entity, use
+ /// instead.
+ ///
+ ///
+ /// If an dictionary is not empty there should be an entry for each pipe layer.
+ ///
+ [DataField]
+ public Dictionary> SpriteLayersRsiPaths = new();
+
+ ///
+ /// Entity prototypes that will be used to replace the current one when using
+ /// position dependent entity placement via AlignAtmosPipeLayers.
+ ///
+ ///
+ /// If the dictionary is not empty there should be an entry for each atmos pipe layer.
+ ///
+ [DataField]
+ public Dictionary AlternativePrototypes = new();
+
+ ///
+ /// The pipe layers of this entity cannot be changed when this value is true.
+ ///
+ [DataField]
+ public bool PipeLayersLocked;
+
+ ///
+ /// Tool quality required to cause a pipe to change layers
+ ///
+ [DataField]
+ public ProtoId Tool = "Screwing";
+
+ ///
+ /// The base delay to use for changing layers.
+ ///
+ [DataField]
+ public float Delay = 1f;
+}
+
+///
+/// Raised when a player attempts to cycle a pipe to its next layer
+///
+[Serializable, NetSerializable]
+public sealed partial class TrySetNextPipeLayerCompletedEvent : SimpleDoAfterEvent;
+
+///
+/// Raised when a player attempts to set a pipe a specified layer
+///
+[Serializable, NetSerializable]
+public sealed partial class TrySettingPipeLayerCompletedEvent : SimpleDoAfterEvent
+{
+ public AtmosPipeLayer PipeLayer;
+
+ public TrySettingPipeLayerCompletedEvent(AtmosPipeLayer pipeLayer)
+ {
+ PipeLayer = pipeLayer;
+ }
+}
+
+[Serializable, NetSerializable]
+public enum AtmosPipeLayerVisuals
+{
+ Sprite,
+ SpriteLayers,
+ DrawDepth,
+}
+
+[Serializable, NetSerializable]
+public enum AtmosPipeLayer
+{
+ Primary,
+ Secondary,
+ Tertiary,
+}
diff --git a/Content.Shared/Atmos/Components/PipeAppearanceComponent.cs b/Content.Shared/Atmos/Components/PipeAppearanceComponent.cs
index b5f979c482..f8599148ea 100644
--- a/Content.Shared/Atmos/Components/PipeAppearanceComponent.cs
+++ b/Content.Shared/Atmos/Components/PipeAppearanceComponent.cs
@@ -5,6 +5,8 @@ namespace Content.Shared.Atmos.Components;
[RegisterComponent]
public sealed partial class PipeAppearanceComponent : Component
{
- [DataField("sprite")]
- public SpriteSpecifier.Rsi Sprite = new(new("Structures/Piping/Atmospherics/pipe.rsi"), "pipeConnector");
+ [DataField]
+ public SpriteSpecifier.Rsi[] Sprite = [new(new("Structures/Piping/Atmospherics/pipe.rsi"), "pipeConnector"),
+ new(new("Structures/Piping/Atmospherics/pipe_alt1.rsi"), "pipeConnector"),
+ new(new("Structures/Piping/Atmospherics/pipe_alt2.rsi"), "pipeConnector")];
}
diff --git a/Content.Shared/Atmos/Consoles/Components/AtmosMonitoringConsoleComponent.cs b/Content.Shared/Atmos/Consoles/Components/AtmosMonitoringConsoleComponent.cs
index 2ac0d2a9af..d01fb4e8bc 100644
--- a/Content.Shared/Atmos/Consoles/Components/AtmosMonitoringConsoleComponent.cs
+++ b/Content.Shared/Atmos/Consoles/Components/AtmosMonitoringConsoleComponent.cs
@@ -64,10 +64,10 @@ public struct AtmosPipeChunk(Vector2i origin)
///
/// Bitmask look up for atmos pipes, 1 for occupied and 0 for empty.
- /// Indexed by the color hexcode of the pipe
+ /// Indexed by the net ID, layer and color hexcode of the pipe
///
[ViewVariables]
- public Dictionary<(int, string), ulong> AtmosPipeData = new();
+ public Dictionary AtmosPipeData = new();
///
/// The last game tick that the chunk was updated
@@ -90,7 +90,7 @@ public struct AtmosDeviceNavMapData
public NetCoordinates NetCoordinates;
///
- /// The associated pipe network ID
+ /// The associated pipe network ID
///
public int NetId = -1;
@@ -109,10 +109,21 @@ public struct AtmosDeviceNavMapData
///
public Color PipeColor;
+ ///
+ /// The pipe layer the entity is on
+ ///
+ public AtmosPipeLayer PipeLayer;
+
///
/// Populate the atmos monitoring console nav map with a single entity
///
- public AtmosDeviceNavMapData(NetEntity netEntity, NetCoordinates netCoordinates, int netId, ProtoId navMapBlip, Direction direction, Color pipeColor)
+ public AtmosDeviceNavMapData(NetEntity netEntity,
+ NetCoordinates netCoordinates,
+ int netId,
+ ProtoId navMapBlip,
+ Direction direction,
+ Color pipeColor,
+ AtmosPipeLayer pipeLayer)
{
NetEntity = netEntity;
NetCoordinates = netCoordinates;
@@ -120,6 +131,7 @@ public struct AtmosDeviceNavMapData
NavMapBlip = navMapBlip;
Direction = direction;
PipeColor = pipeColor;
+ PipeLayer = pipeLayer;
}
}
@@ -154,7 +166,7 @@ public struct AtmosMonitoringConsoleEntry
public NetCoordinates Coordinates;
///
- /// The associated pipe network ID
+ /// The associated pipe network ID
///
public int NetId = -1;
@@ -184,7 +196,7 @@ public struct AtmosMonitoringConsoleEntry
public float TotalMolData;
///
- /// Mol and percentage for all detected gases
+ /// Mol and percentage for all detected gases
///
public Dictionary GasData = new();
@@ -216,6 +228,16 @@ public struct AtmosMonitoringConsoleEntry
}
}
+///
+/// Used to group atmos pipe chunks into subnets based on their properties and
+/// improve the efficiency of rendering these chunks on the atmos monitoring console.
+///
+/// The associated network ID.
+/// The associated pipe layer.
+/// The color of the pipe.
+[Serializable, NetSerializable]
+public record AtmosMonitoringConsoleSubnet(int NetId, AtmosPipeLayer PipeLayer, string HexCode);
+
public enum AtmosPipeChunkDataFacing : byte
{
// Values represent bit shift offsets when retrieving data in the tile array.
diff --git a/Content.Shared/Atmos/Consoles/Components/AtmosMonitoringConsoleDeviceComponent.cs b/Content.Shared/Atmos/Consoles/Components/AtmosMonitoringConsoleDeviceComponent.cs
index 50c3abcfca..a7b83fde48 100644
--- a/Content.Shared/Atmos/Consoles/Components/AtmosMonitoringConsoleDeviceComponent.cs
+++ b/Content.Shared/Atmos/Consoles/Components/AtmosMonitoringConsoleDeviceComponent.cs
@@ -5,7 +5,7 @@ using Robust.Shared.Prototypes;
namespace Content.Shared.Atmos.Components;
///
-/// Entities with this component appear on the
+/// Entities with this component appear on the
/// nav maps of atmos monitoring consoles
///
[RegisterComponent, NetworkedComponent]
@@ -16,6 +16,14 @@ public sealed partial class AtmosMonitoringConsoleDeviceComponent : Component
/// entity on the atmos monitoring console nav map.
/// If null, no blip is drawn (i.e., null for pipes)
///
- [DataField, ViewVariables]
+ [DataField]
public ProtoId? NavMapBlip = null;
+
+ ///
+ /// Sets whether attached atmos pipes will always be rendered
+ /// on the atmos monitoring console nav map, even if these
+ /// pipes are not connected to any pipes in a neighboring tile.
+ ///
+ [DataField]
+ public bool ShowAbsentConnections = true;
}
diff --git a/Content.Shared/Atmos/Consoles/SharedAtmosMonitoringConsoleSystem.cs b/Content.Shared/Atmos/Consoles/SharedAtmosMonitoringConsoleSystem.cs
index e6dd455be7..7fe94efd84 100644
--- a/Content.Shared/Atmos/Consoles/SharedAtmosMonitoringConsoleSystem.cs
+++ b/Content.Shared/Atmos/Consoles/SharedAtmosMonitoringConsoleSystem.cs
@@ -15,7 +15,7 @@ public abstract class SharedAtmosMonitoringConsoleSystem : EntitySystem
private void OnGetState(EntityUid uid, AtmosMonitoringConsoleComponent component, ref ComponentGetState args)
{
- Dictionary> chunks;
+ Dictionary> chunks;
// Should this be a full component state or a delta-state?
if (args.FromTick <= component.CreationTick || component.ForceFullUpdate)
@@ -52,22 +52,22 @@ public abstract class SharedAtmosMonitoringConsoleSystem : EntitySystem
[Serializable, NetSerializable]
protected sealed class AtmosMonitoringConsoleState(
- Dictionary> chunks,
+ Dictionary> chunks,
Dictionary atmosDevices)
: ComponentState
{
- public Dictionary> Chunks = chunks;
+ public Dictionary> Chunks = chunks;
public Dictionary AtmosDevices = atmosDevices;
}
[Serializable, NetSerializable]
protected sealed class AtmosMonitoringConsoleDeltaState(
- Dictionary> modifiedChunks,
+ Dictionary> modifiedChunks,
Dictionary atmosDevices,
HashSet allChunks)
: ComponentState, IComponentDeltaState
{
- public Dictionary> ModifiedChunks = modifiedChunks;
+ public Dictionary> ModifiedChunks = modifiedChunks;
public Dictionary AtmosDevices = atmosDevices;
public HashSet AllChunks = allChunks;
@@ -81,7 +81,7 @@ public abstract class SharedAtmosMonitoringConsoleSystem : EntitySystem
foreach (var (index, data) in ModifiedChunks)
{
- state.Chunks[index] = new Dictionary<(int, string), ulong>(data);
+ state.Chunks[index] = new Dictionary(data);
}
state.AtmosDevices.Clear();
@@ -93,7 +93,7 @@ public abstract class SharedAtmosMonitoringConsoleSystem : EntitySystem
public AtmosMonitoringConsoleState CreateNewFullState(AtmosMonitoringConsoleState state)
{
- var chunks = new Dictionary>(state.Chunks.Count);
+ var chunks = new Dictionary>(state.Chunks.Count);
foreach (var (index, data) in state.Chunks)
{
@@ -101,10 +101,10 @@ public abstract class SharedAtmosMonitoringConsoleSystem : EntitySystem
continue;
if (ModifiedChunks.ContainsKey(index))
- chunks[index] = new Dictionary<(int, string), ulong>(ModifiedChunks[index]);
+ chunks[index] = new Dictionary(ModifiedChunks[index]);
else
- chunks[index] = new Dictionary<(int, string), ulong>(state.Chunks[index]);
+ chunks[index] = new Dictionary(state.Chunks[index]);
}
return new AtmosMonitoringConsoleState(chunks, new(AtmosDevices));
diff --git a/Content.Shared/Atmos/EntitySystems/SharedAtmosPipeAppearanceSystem.cs b/Content.Shared/Atmos/EntitySystems/SharedAtmosPipeAppearanceSystem.cs
new file mode 100644
index 0000000000..c6944ec2de
--- /dev/null
+++ b/Content.Shared/Atmos/EntitySystems/SharedAtmosPipeAppearanceSystem.cs
@@ -0,0 +1,18 @@
+using Content.Shared.Atmos.Components;
+
+namespace Content.Shared.Atmos.EntitySystems;
+
+public abstract partial class SharedAtmosPipeAppearanceSystem : EntitySystem
+{
+ ///
+ /// Returns the max number of pipe layers supported by a entity.
+ ///
+ /// The entity being checked.
+ /// The entity's , if available.
+ /// Returns
+ /// if the entity has the component, or 1 if it does not.
+ protected int GetNumberOfPipeLayers(EntityUid uid, out AtmosPipeLayersComponent? atmosPipeLayers)
+ {
+ return TryComp(uid, out atmosPipeLayers) ? atmosPipeLayers.NumberOfPipeLayers : 1;
+ }
+}
diff --git a/Content.Shared/Atmos/EntitySystems/SharedAtmosPipeLayersSystem.cs b/Content.Shared/Atmos/EntitySystems/SharedAtmosPipeLayersSystem.cs
new file mode 100644
index 0000000000..ff88601330
--- /dev/null
+++ b/Content.Shared/Atmos/EntitySystems/SharedAtmosPipeLayersSystem.cs
@@ -0,0 +1,264 @@
+using Content.Shared.Atmos.Components;
+using Content.Shared.Database;
+using Content.Shared.Examine;
+using Content.Shared.Hands.EntitySystems;
+using Content.Shared.Interaction;
+using Content.Shared.Interaction.Events;
+using Content.Shared.Popups;
+using Content.Shared.SubFloor;
+using Content.Shared.Tools;
+using Content.Shared.Tools.Components;
+using Content.Shared.Tools.Systems;
+using Content.Shared.Verbs;
+using Robust.Shared.Prototypes;
+using System.Diagnostics.CodeAnalysis;
+
+namespace Content.Shared.Atmos.EntitySystems;
+
+///
+/// The system responsible for checking and adjusting the connection layering of gas pipes
+///
+public abstract partial class SharedAtmosPipeLayersSystem : EntitySystem
+{
+ [Dependency] private readonly SharedAppearanceSystem _appearance = default!;
+ [Dependency] private readonly IPrototypeManager _protoManager = default!;
+ [Dependency] private readonly SharedToolSystem _tool = default!;
+ [Dependency] private readonly SharedHandsSystem _hands = default!;
+ [Dependency] private readonly SharedPopupSystem _popup = default!;
+
+ public override void Initialize()
+ {
+ base.Initialize();
+
+ SubscribeLocalEvent(OnExamined);
+ SubscribeLocalEvent>(OnGetVerb);
+ SubscribeLocalEvent(OnInteractUsing);
+ SubscribeLocalEvent(OnUseInHandEvent);
+ SubscribeLocalEvent(OnSetNextPipeLayerCompleted);
+ SubscribeLocalEvent(OnSettingPipeLayerCompleted);
+ }
+
+ private void OnExamined(Entity ent, ref ExaminedEvent args)
+ {
+ var layerName = GetPipeLayerName(ent.Comp.CurrentPipeLayer);
+ args.PushMarkup(Loc.GetString("atmos-pipe-layers-component-current-layer", ("layerName", layerName)));
+ }
+
+ private void OnGetVerb(Entity ent, ref GetVerbsEvent args)
+ {
+ if (!args.CanAccess || !args.CanInteract || !args.CanComplexInteract)
+ return;
+
+ if (ent.Comp.NumberOfPipeLayers <= 1 || ent.Comp.PipeLayersLocked)
+ return;
+
+ if (!_protoManager.TryIndex(ent.Comp.Tool, out var toolProto))
+ return;
+
+ var user = args.User;
+
+ if (TryComp(ent, out var subFloorHide) && subFloorHide.IsUnderCover)
+ {
+ var v = new Verb
+ {
+ Priority = 1,
+ Category = VerbCategory.Adjust,
+ Text = Loc.GetString("atmos-pipe-layers-component-pipes-are-covered"),
+ Disabled = true,
+ Impact = LogImpact.Low,
+ DoContactInteraction = true,
+ };
+
+ args.Verbs.Add(v);
+ }
+
+ else if (!TryGetHeldTool(user, ent.Comp.Tool, out var tool))
+ {
+ var v = new Verb
+ {
+ Priority = 1,
+ Category = VerbCategory.Adjust,
+ Text = Loc.GetString("atmos-pipe-layers-component-tool-missing", ("toolName", Loc.GetString(toolProto.ToolName).ToLower())),
+ Disabled = true,
+ Impact = LogImpact.Low,
+ DoContactInteraction = true,
+ };
+
+ args.Verbs.Add(v);
+ }
+
+ else
+ {
+ for (var i = 0; i < ent.Comp.NumberOfPipeLayers; i++)
+ {
+ var index = i;
+ var layerName = GetPipeLayerName((AtmosPipeLayer)index);
+ var label = Loc.GetString("atmos-pipe-layers-component-select-layer", ("layerName", layerName));
+
+ var v = new Verb
+ {
+ Priority = 1,
+ Category = VerbCategory.Adjust,
+ Text = label,
+ Disabled = index == (int)ent.Comp.CurrentPipeLayer,
+ Impact = LogImpact.Low,
+ DoContactInteraction = true,
+ Act = () =>
+ {
+ _tool.UseTool(tool.Value, user, ent, ent.Comp.Delay, tool.Value.Comp.Qualities, new TrySettingPipeLayerCompletedEvent((AtmosPipeLayer)index));
+ }
+ };
+
+ args.Verbs.Add(v);
+ }
+ }
+ }
+
+ private void OnInteractUsing(Entity ent, ref InteractUsingEvent args)
+ {
+ if (ent.Comp.NumberOfPipeLayers <= 1 || ent.Comp.PipeLayersLocked)
+ return;
+
+ if (TryComp(ent, out var subFloorHide) && subFloorHide.IsUnderCover)
+ {
+ _popup.PopupPredicted(Loc.GetString("atmos-pipe-layers-component-cannot-adjust-pipes"), ent, args.User);
+ return;
+ }
+
+ if (TryComp(args.Used, out var tool) && _tool.HasQuality(args.Used, ent.Comp.Tool, tool))
+ _tool.UseTool(args.Used, args.User, ent, ent.Comp.Delay, tool.Qualities, new TrySetNextPipeLayerCompletedEvent());
+ }
+
+ private void OnUseInHandEvent(Entity ent, ref UseInHandEvent args)
+ {
+ if (ent.Comp.NumberOfPipeLayers <= 1 || ent.Comp.PipeLayersLocked)
+ return;
+
+ if (!TryGetHeldTool(args.User, ent.Comp.Tool, out var tool))
+ {
+ if (_protoManager.TryIndex(ent.Comp.Tool, out var toolProto))
+ {
+ var toolName = Loc.GetString(toolProto.ToolName).ToLower();
+ var message = Loc.GetString("atmos-pipe-layers-component-tool-missing", ("toolName", toolName));
+
+ _popup.PopupPredicted(message, ent, args.User);
+ }
+
+ return;
+ }
+
+ _tool.UseTool(tool.Value, args.User, ent, ent.Comp.Delay, tool.Value.Comp.Qualities, new TrySetNextPipeLayerCompletedEvent());
+ }
+
+ private void OnSetNextPipeLayerCompleted(Entity ent, ref TrySetNextPipeLayerCompletedEvent args)
+ {
+ if (args.Cancelled)
+ return;
+
+ SetNextPipeLayer(ent, args.User, args.Used);
+ }
+
+ private void OnSettingPipeLayerCompleted(Entity ent, ref TrySettingPipeLayerCompletedEvent args)
+ {
+ if (args.Cancelled)
+ return;
+
+ SetPipeLayer(ent, args.PipeLayer, args.User, args.Used);
+ }
+
+ ///
+ /// Increments an entity's pipe layer by 1, wrapping around to 0 if the max pipe layer is reached
+ ///
+ /// The pipe entity
+ /// The player entity who adjusting the pipe layer
+ /// The tool used to adjust the pipe layer
+ public void SetNextPipeLayer(Entity ent, EntityUid? user = null, EntityUid? used = null)
+ {
+ var newLayer = ((int)ent.Comp.CurrentPipeLayer + 1) % ent.Comp.NumberOfPipeLayers;
+ SetPipeLayer(ent, (AtmosPipeLayer)newLayer, user, used);
+ }
+
+ ///
+ /// Sets an entity's pipe layer to a specified value
+ ///
+ /// The pipe entity
+ /// The new layer value
+ /// The player entity who adjusting the pipe layer
+ /// The tool used to adjust the pipe layer
+ public virtual void SetPipeLayer(Entity ent, AtmosPipeLayer layer, EntityUid? user = null, EntityUid? used = null)
+ {
+ if (ent.Comp.PipeLayersLocked)
+ return;
+
+ ent.Comp.CurrentPipeLayer = (AtmosPipeLayer)Math.Clamp((int)layer, 0, ent.Comp.NumberOfPipeLayers - 1);
+ Dirty(ent);
+
+ if (TryComp(ent, out var appearance))
+ {
+ if (ent.Comp.SpriteRsiPaths.TryGetValue(ent.Comp.CurrentPipeLayer, out var path))
+ _appearance.SetData(ent, AtmosPipeLayerVisuals.Sprite, path, appearance);
+
+ if (ent.Comp.SpriteLayersRsiPaths.Count > 0)
+ {
+ var data = new Dictionary();
+
+ foreach (var (layerKey, rsiPaths) in ent.Comp.SpriteLayersRsiPaths)
+ {
+ if (rsiPaths.TryGetValue(ent.Comp.CurrentPipeLayer, out path))
+ data.TryAdd(layerKey, path);
+ }
+
+ _appearance.SetData(ent, AtmosPipeLayerVisuals.SpriteLayers, data, appearance);
+ }
+ }
+
+ if (user != null)
+ {
+ var layerName = GetPipeLayerName(ent.Comp.CurrentPipeLayer);
+ var message = Loc.GetString("atmos-pipe-layers-component-change-layer", ("layerName", layerName));
+
+ _popup.PopupPredicted(message, ent, user);
+ }
+ }
+
+ ///
+ /// Try to find an entity prototype associated with a specified .
+ ///
+ /// The with the alternative prototypes data.
+ /// The atmos pipe layer associated with the entity prototype.
+ /// The returned entity prototype.
+ /// True if there was an entity prototype associated with the layer.
+ public bool TryGetAlternativePrototype(AtmosPipeLayersComponent component, AtmosPipeLayer layer, out EntProtoId proto)
+ {
+ return component.AlternativePrototypes.TryGetValue(layer, out proto);
+ }
+
+ ///
+ /// Checks a player entity's hands to see if they are holding a tool with a specified quality
+ ///
+ /// The player entity
+ /// The tool quality being checked for
+ /// A tool with the specified tool quality
+ /// True if an appropriate tool was found
+ private bool TryGetHeldTool(EntityUid user, ProtoId toolQuality, [NotNullWhen(true)] out Entity? heldTool)
+ {
+ heldTool = null;
+
+ foreach (var heldItem in _hands.EnumerateHeld(user))
+ {
+ if (TryComp(heldItem, out var tool) &&
+ _tool.HasQuality(heldItem, toolQuality, tool))
+ {
+ heldTool = new Entity(heldItem, tool);
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ private string GetPipeLayerName(AtmosPipeLayer layer)
+ {
+ return Loc.GetString("atmos-pipe-layers-component-layer-" + layer.ToString().ToLower());
+ }
+}
diff --git a/Content.Shared/Construction/Prototypes/ConstructionPrototype.cs b/Content.Shared/Construction/Prototypes/ConstructionPrototype.cs
index 0e1a50d9a2..cd38b22b9c 100644
--- a/Content.Shared/Construction/Prototypes/ConstructionPrototype.cs
+++ b/Content.Shared/Construction/Prototypes/ConstructionPrototype.cs
@@ -85,6 +85,12 @@ public sealed partial class ConstructionPrototype : IPrototype
[DataField]
public ProtoId? Mirror { get; private set; }
+ ///
+ /// Possible constructions to replace this one with as determined by the placement mode
+ ///
+ [DataField]
+ public ProtoId[] AlternativePrototypes = [];
+
public IReadOnlyList Conditions => _conditions;
}
diff --git a/Content.Shared/DrawDepth/DrawDepth.cs b/Content.Shared/DrawDepth/DrawDepth.cs
index dbec886971..35fead5b3f 100644
--- a/Content.Shared/DrawDepth/DrawDepth.cs
+++ b/Content.Shared/DrawDepth/DrawDepth.cs
@@ -9,13 +9,15 @@ namespace Content.Shared.DrawDepth
///
/// This is for sub-floors, the floors you see after prying off a tile.
///
- LowFloors = DrawDepthTag.Default - 18,
+ LowFloors = DrawDepthTag.Default - 20,
// various entity types that require different
// draw depths, as to avoid hiding
#region SubfloorEntities
- ThickPipe = DrawDepthTag.Default - 17,
- ThickWire = DrawDepthTag.Default - 16,
+ ThickPipe = DrawDepthTag.Default - 19,
+ ThickWire = DrawDepthTag.Default - 18,
+ ThinPipeAlt2 = DrawDepthTag.Default - 17,
+ ThinPipeAlt1 = DrawDepthTag.Default - 16,
ThinPipe = DrawDepthTag.Default - 15,
ThinWire = DrawDepthTag.Default - 14,
#endregion
diff --git a/Content.Shared/Prototypes/NavMapBlipPrototype.cs b/Content.Shared/Prototypes/NavMapBlipPrototype.cs
index 2fcb6c5ccb..dff9f50054 100644
--- a/Content.Shared/Prototypes/NavMapBlipPrototype.cs
+++ b/Content.Shared/Prototypes/NavMapBlipPrototype.cs
@@ -39,4 +39,17 @@ public sealed partial class NavMapBlipPrototype : IPrototype
///
[DataField]
public float Scale { get; private set; } = 1f;
+
+ ///
+ /// Describes how the blip should be positioned.
+ /// It's up to the individual system to enforce this
+ ///
+ [DataField]
+ public NavMapBlipPlacement Placement { get; private set; } = NavMapBlipPlacement.Centered;
+}
+
+public enum NavMapBlipPlacement
+{
+ Centered, // The blip appears in the center of the tile
+ Offset // The blip is offset from the center of the tile (determined by the system using the blips)
}
diff --git a/Content.Shared/SubFloor/SharedSubFloorHideSystem.cs b/Content.Shared/SubFloor/SharedSubFloorHideSystem.cs
index 812003aae8..c7edf01499 100644
--- a/Content.Shared/SubFloor/SharedSubFloorHideSystem.cs
+++ b/Content.Shared/SubFloor/SharedSubFloorHideSystem.cs
@@ -225,6 +225,7 @@ namespace Content.Shared.SubFloor
ScannerRevealed,
}
+ [Serializable, NetSerializable]
public enum SubfloorLayers : byte
{
FirstLayer
diff --git a/Content.Shared/Verbs/VerbCategory.cs b/Content.Shared/Verbs/VerbCategory.cs
index 9b9197249a..418921d38e 100644
--- a/Content.Shared/Verbs/VerbCategory.cs
+++ b/Content.Shared/Verbs/VerbCategory.cs
@@ -85,5 +85,8 @@ namespace Content.Shared.Verbs
public static readonly VerbCategory SelectType = new("verb-categories-select-type", null);
public static readonly VerbCategory PowerLevel = new("verb-categories-power-level", null);
+
+ public static readonly VerbCategory Adjust =
+ new("verb-categories-adjust", "/Textures/Interface/VerbIcons/screwdriver.png");
}
}
diff --git a/Resources/Locale/en-US/atmos/atmos-pipe-layers.ftl b/Resources/Locale/en-US/atmos/atmos-pipe-layers.ftl
new file mode 100644
index 0000000000..27491efb5e
--- /dev/null
+++ b/Resources/Locale/en-US/atmos/atmos-pipe-layers.ftl
@@ -0,0 +1,10 @@
+atmos-pipe-layers-component-layer-primary = primary
+atmos-pipe-layers-component-layer-secondary = secondary
+atmos-pipe-layers-component-layer-tertiary = tertiary
+
+atmos-pipe-layers-component-change-layer = Adjusted to its {$layerName} configuration.
+atmos-pipe-layers-component-current-layer = It is in its {$layerName} configuration.
+atmos-pipe-layers-component-select-layer = {CAPITALIZE($layerName)} configuration
+atmos-pipe-layers-component-tool-missing = Requires {INDEFINITE($toolName)} {$toolName}
+atmos-pipe-layers-component-pipes-are-covered = The pipes are covered
+atmos-pipe-layers-component-cannot-adjust-pipes = You need to uncover the pipes before they can be adjusted.
\ No newline at end of file
diff --git a/Resources/Locale/en-US/verbs/verb-system.ftl b/Resources/Locale/en-US/verbs/verb-system.ftl
index 64104f796e..d52b43c9a7 100644
--- a/Resources/Locale/en-US/verbs/verb-system.ftl
+++ b/Resources/Locale/en-US/verbs/verb-system.ftl
@@ -28,6 +28,7 @@ verb-categories-lever = Lever
verb-categories-select-type = Select Type
verb-categories-fax = Set Destination
verb-categories-power-level = Power Level
+verb-categories-adjust = Adjust
verb-common-toggle-light = Toggle light
verb-common-close = Close
diff --git a/Resources/Prototypes/Entities/Structures/Machines/Computers/nav_map_blips.yml b/Resources/Prototypes/Entities/Structures/Machines/Computers/nav_map_blips.yml
index bc51557186..93530976f7 100644
--- a/Resources/Prototypes/Entities/Structures/Machines/Computers/nav_map_blips.yml
+++ b/Resources/Prototypes/Entities/Structures/Machines/Computers/nav_map_blips.yml
@@ -13,21 +13,22 @@
color: "#ffcd00"
texturePaths:
- "/Textures/Interface/NavMap/beveled_star.png"
-
+ placement: Offset
+
- type: navMapBlip
id: GasVentOpening
- scale: 0.6667
+ scale: 0.75
color: LightGray
texturePaths:
- "/Textures/Interface/NavMap/beveled_square.png"
-
+
- type: navMapBlip
id: GasVentScrubber
- scale: 0.6667
+ scale: 0.75
color: LightGray
texturePaths:
- "/Textures/Interface/NavMap/beveled_circle.png"
-
+
- type: navMapBlip
id: GasFlowRegulator
scale: 0.75
@@ -37,7 +38,8 @@
- "/Textures/Interface/NavMap/beveled_arrow_east.png"
- "/Textures/Interface/NavMap/beveled_arrow_north.png"
- "/Textures/Interface/NavMap/beveled_arrow_west.png"
-
+ placement: Offset
+
- type: navMapBlip
id: GasValve
scale: 0.6667
@@ -45,12 +47,23 @@
texturePaths:
- "/Textures/Interface/NavMap/beveled_diamond_north_south.png"
- "/Textures/Interface/NavMap/beveled_diamond_east_west.png"
- - "/Textures/Interface/NavMap/beveled_diamond_north_south.png"
+ - "/Textures/Interface/NavMap/beveled_diamond_north_south.png"
- "/Textures/Interface/NavMap/beveled_diamond_east_west.png"
-
+ placement: Offset
+
- type: navMapBlip
id: Thermoregulator
- scale: 0.6667
+ scale: 0.75
color: LightGray
texturePaths:
- - "/Textures/Interface/NavMap/beveled_hexagon.png"
\ No newline at end of file
+ - "/Textures/Interface/NavMap/beveled_hexagon.png"
+
+- type: navMapBlip
+ id: GasPipeManifold
+ scale: 0.9
+ color: LightGray
+ texturePaths:
+ - "/Textures/Interface/NavMap/beveled_rectangle_east_west.png"
+ - "/Textures/Interface/NavMap/beveled_rectangle_north_south.png"
+ - "/Textures/Interface/NavMap/beveled_rectangle_east_west.png"
+ - "/Textures/Interface/NavMap/beveled_rectangle_north_south.png"
diff --git a/Resources/Prototypes/Entities/Structures/Piping/Atmospherics/alt_layers.yml b/Resources/Prototypes/Entities/Structures/Piping/Atmospherics/alt_layers.yml
new file mode 100644
index 0000000000..1f4ab085f1
--- /dev/null
+++ b/Resources/Prototypes/Entities/Structures/Piping/Atmospherics/alt_layers.yml
@@ -0,0 +1,133 @@
+## This file contains duplicated pipe prototypes with
+## different layer offsets to faciliate mapping
+
+# Layer 1
+- type: entity
+ abstract: true
+ id: GasPipeLayerAlt1
+ components:
+ - type: AtmosPipeLayers
+ pipeLayer: 1
+
+# Layer 2
+- type: entity
+ abstract: true
+ id: GasPipeLayerAlt2
+ components:
+ - type: AtmosPipeLayers
+ pipeLayer: 2
+
+# GasPipeStraight
+- type: entity
+ parent: [GasPipeLayerAlt1, GasPipeStraight]
+ id: GasPipeStraightAlt1
+ categories: [ HideSpawnMenu ]
+ components:
+ - type: Sprite
+ drawdepth: ThinPipeAlt1
+ sprite: Structures/Piping/Atmospherics/pipe_alt1.rsi
+ - type: Construction
+ node: straightAlt1
+
+- type: entity
+ parent: [GasPipeLayerAlt2, GasPipeStraight]
+ id: GasPipeStraightAlt2
+ categories: [ HideSpawnMenu ]
+ components:
+ - type: Sprite
+ drawdepth: ThinPipeAlt2
+ sprite: Structures/Piping/Atmospherics/pipe_alt2.rsi
+ - type: Construction
+ node: straightAlt2
+
+# GasPipeHalf
+- type: entity
+ parent: [GasPipeLayerAlt1, GasPipeHalf]
+ id: GasPipeHalfAlt1
+ categories: [ HideSpawnMenu ]
+ components:
+ - type: Sprite
+ drawdepth: ThinPipeAlt1
+ sprite: Structures/Piping/Atmospherics/pipe_alt1.rsi
+ - type: Construction
+ node: halfAlt1
+
+- type: entity
+ parent: [GasPipeLayerAlt2, GasPipeHalf]
+ id: GasPipeHalfAlt2
+ categories: [ HideSpawnMenu ]
+ components:
+ - type: Sprite
+ drawdepth: ThinPipeAlt2
+ sprite: Structures/Piping/Atmospherics/pipe_alt2.rsi
+ - type: Construction
+ node: halfAlt2
+
+# GasPipeBend
+- type: entity
+ parent: [GasPipeLayerAlt1, GasPipeBend]
+ id: GasPipeBendAlt1
+ categories: [ HideSpawnMenu ]
+ components:
+ - type: Sprite
+ drawdepth: ThinPipeAlt1
+ sprite: Structures/Piping/Atmospherics/pipe_alt1.rsi
+ - type: Construction
+ node: bendAlt1
+
+- type: entity
+ parent: [GasPipeLayerAlt2, GasPipeBend]
+ id: GasPipeBendAlt2
+ categories: [ HideSpawnMenu ]
+ components:
+ - type: Sprite
+ drawdepth: ThinPipeAlt2
+ sprite: Structures/Piping/Atmospherics/pipe_alt2.rsi
+ - type: Construction
+ node: bendAlt2
+
+# GasPipeTJunction
+- type: entity
+ parent: [GasPipeLayerAlt1, GasPipeTJunction]
+ id: GasPipeTJunctionAlt1
+ categories: [ HideSpawnMenu ]
+ components:
+ - type: Sprite
+ drawdepth: ThinPipeAlt1
+ sprite: Structures/Piping/Atmospherics/pipe_alt1.rsi
+ - type: Construction
+ node: tjunctionAlt1
+
+- type: entity
+ parent: [GasPipeLayerAlt2, GasPipeTJunction]
+ id: GasPipeTJunctionAlt2
+ categories: [ HideSpawnMenu ]
+ components:
+ - type: Sprite
+ drawdepth: ThinPipeAlt2
+ sprite: Structures/Piping/Atmospherics/pipe_alt2.rsi
+ - type: Construction
+ node: tjunctionAlt2
+
+# GasPipeFourway
+- type: entity
+ parent: [GasPipeLayerAlt1, GasPipeFourway]
+ id: GasPipeFourwayAlt1
+ categories: [ HideSpawnMenu ]
+ components:
+ - type: Sprite
+ drawdepth: ThinPipeAlt1
+ sprite: Structures/Piping/Atmospherics/pipe_alt1.rsi
+ - type: Construction
+ node: fourwayAlt1
+
+- type: entity
+ parent: [GasPipeLayerAlt2, GasPipeFourway]
+ id: GasPipeFourwayAlt2
+ categories: [ HideSpawnMenu ]
+ components:
+ - type: Sprite
+ drawdepth: ThinPipeAlt2
+ sprite: Structures/Piping/Atmospherics/pipe_alt2.rsi
+ - type: Construction
+ node: fourwayAlt2
diff --git a/Resources/Prototypes/Entities/Structures/Piping/Atmospherics/binary.yml b/Resources/Prototypes/Entities/Structures/Piping/Atmospherics/binary.yml
index 33a8414961..88940f4882 100644
--- a/Resources/Prototypes/Entities/Structures/Piping/Atmospherics/binary.yml
+++ b/Resources/Prototypes/Entities/Structures/Piping/Atmospherics/binary.yml
@@ -22,6 +22,11 @@
!type:PipeNode
nodeGroupID: Pipe
pipeDirection: South
+ - type: AtmosPipeLayers
+ spriteRsiPaths:
+ Primary: Structures/Piping/Atmospherics/pump.rsi
+ Secondary: Structures/Piping/Atmospherics/pump_alt1.rsi
+ Tertiary: Structures/Piping/Atmospherics/pump_alt2.rsi
- type: entity
parent: GasBinaryBase
@@ -325,10 +330,12 @@
sprite: Structures/Piping/Atmospherics/gascanisterport.rsi
layers:
- sprite: Structures/Piping/Atmospherics/pipe.rsi
- state: pipeHalf
+ state: pipeUnaryConnectors
map: [ "enum.PipeVisualLayers.Pipe" ]
- state: gasCanisterPort
map: [ "enum.SubfloorLayers.FirstLayer" ]
+ - type: AtmosPipeLayers
+ spriteRsiPaths: {}
- type: Appearance
- type: PipeColorVisuals
- type: GasPort
@@ -363,10 +370,12 @@
sprite: Structures/Piping/Atmospherics/vent.rsi
layers:
- sprite: Structures/Piping/Atmospherics/pipe.rsi
- state: pipeStraight
+ state: pipeBinaryConnectors
map: [ "enum.PipeVisualLayers.Pipe" ]
- state: vent_off
map: [ "enabled", "enum.SubfloorLayers.FirstLayer" ]
+ - type: AtmosPipeLayers
+ spriteRsiPaths: {}
- type: GenericVisualizer
visuals:
enum.VentPumpVisuals.State:
@@ -423,18 +432,24 @@
sprite: Structures/Machines/gasrecycler.rsi
layers:
- sprite: Structures/Piping/Atmospherics/pipe.rsi
- state: pipeStraight
+ state: pipeBinaryConnectors
map: [ "enum.PipeVisualLayers.Pipe" ]
- state: running
- state: unlit
shader: unshaded
+ - type: AtmosPipeLayers
+ spriteLayersRsiPaths:
+ enum.PipeVisualLayers.Pipe:
+ Primary: Structures/Piping/Atmospherics/pipe.rsi
+ Secondary: Structures/Piping/Atmospherics/pipe_alt1.rsi
+ Tertiary: Structures/Piping/Atmospherics/pipe_alt2.rsi
+ - type: Appearance
- type: GenericVisualizer
visuals:
enum.PumpVisuals.Enabled:
enabled:
True: { state: running }
False: { state: unlit }
- - type: Appearance
- type: PipeColorVisuals
- type: Rotatable
- type: GasRecycler
@@ -494,6 +509,9 @@
map: [ "enum.PipeVisualLayers.Pipe" ]
- state: heStraight
map: [ "enum.SubfloorLayers.FirstLayer" ]
+ - type: AtmosPipeLayers
+ spriteRsiPaths: {}
+ numberOfPipeLayers: 1
- type: SubFloorHide
visibleLayers:
- enum.SubfloorLayers.FirstLayer
diff --git a/Resources/Prototypes/Entities/Structures/Piping/Atmospherics/gas_pipe_sensor.yml b/Resources/Prototypes/Entities/Structures/Piping/Atmospherics/gas_pipe_sensor.yml
index 57574f7f7d..c70b33639e 100644
--- a/Resources/Prototypes/Entities/Structures/Piping/Atmospherics/gas_pipe_sensor.yml
+++ b/Resources/Prototypes/Entities/Structures/Piping/Atmospherics/gas_pipe_sensor.yml
@@ -1,5 +1,5 @@
- type: entity
- parent: [AirSensorBase, GasPipeBase]
+ parent: [AirSensorBase, GasBinaryBase]
id: GasPipeSensor
name: gas pipe sensor
description: Reports on the status of the gas in the attached pipe network.
@@ -18,6 +18,11 @@
- map: [ "enum.PowerDeviceVisualLayers.Powered" ]
state: lights
shader: unshaded
+ - type: AtmosPipeLayers
+ spriteRsiPaths:
+ Primary: Structures/Piping/Atmospherics/gas_pipe_sensor.rsi
+ Secondary: Structures/Piping/Atmospherics/gas_pipe_sensor_alt1.rsi
+ Tertiary: Structures/Piping/Atmospherics/gas_pipe_sensor_alt2.rsi
- type: Appearance
- type: GenericVisualizer
visuals:
diff --git a/Resources/Prototypes/Entities/Structures/Piping/Atmospherics/pipes.yml b/Resources/Prototypes/Entities/Structures/Piping/Atmospherics/pipes.yml
index 4d100d434e..6d9d596760 100644
--- a/Resources/Prototypes/Entities/Structures/Piping/Atmospherics/pipes.yml
+++ b/Resources/Prototypes/Entities/Structures/Piping/Atmospherics/pipes.yml
@@ -1,7 +1,7 @@
- type: entity
abstract: true
- id: GasPipeBase
parent: BaseItem
+ id: GasPipeSansLayers
name: gas pipe
description: Holds gas.
placement:
@@ -18,7 +18,6 @@
damageModifierSet: Metallic
- type: SubFloorHide
- type: CollideOnAnchor
- - type: PipeAppearance
- type: Anchorable
- type: Rotatable
- type: Destructible
@@ -51,6 +50,7 @@
drawdepth: ThinPipe
visible: false
- type: Appearance
+ - type: PipeAppearance
- type: PipeColorVisuals
- type: NodeContainer
- type: PipeRestrictOverlap
@@ -66,12 +66,26 @@
- type: StaticPrice
price: 30
+- type: entity
+ abstract: true
+ parent: GasPipeSansLayers
+ id: GasPipeBase
+ components:
+ - type: AtmosPipeLayers
+ spriteLayersRsiPaths:
+ enum.PipeVisualLayers.Pipe:
+ Primary: Structures/Piping/Atmospherics/pipe.rsi
+ Secondary: Structures/Piping/Atmospherics/pipe_alt1.rsi
+ Tertiary: Structures/Piping/Atmospherics/pipe_alt2.rsi
+
#Note: The PipeDirection of the PipeNode should be the south-facing version, because the entity starts at an angle of 0 (south)
- type: entity
parent: GasPipeBase
id: GasPipeHalf
suffix: Half
+ placement:
+ mode: AlignAtmosPipeLayers
components:
- type: NodeContainer
nodes:
@@ -81,11 +95,21 @@
pipeDirection: South
- type: Sprite
layers:
- - state: pipeHalf
- map: [ "enum.PipeVisualLayers.Pipe" ]
+ - state: pipeHalf
+ map: [ "enum.PipeVisualLayers.Pipe" ]
+ - type: AtmosPipeLayers
+ alternativePrototypes:
+ Primary: GasPipeHalf
+ Secondary: GasPipeHalfAlt1
+ Tertiary: GasPipeHalfAlt2
- type: Construction
graph: GasPipe
node: half
+ - type: Item
+ size: Small
+ storedSprite:
+ sprite: Structures/Piping/Atmospherics/pipe.rsi
+ state: storageHalf
- type: GuideHelp
guides:
- Pipes
@@ -95,6 +119,8 @@
parent: GasPipeBase
id: GasPipeStraight
suffix: Straight
+ placement:
+ mode: AlignAtmosPipeLayers
components:
- type: NodeContainer
nodes:
@@ -104,13 +130,17 @@
pipeDirection: Longitudinal
- type: Sprite
layers:
- - state: pipeStraight
- map: [ "enum.PipeVisualLayers.Pipe" ]
+ - state: pipeStraight
+ map: [ "enum.PipeVisualLayers.Pipe" ]
+ - type: AtmosPipeLayers
+ alternativePrototypes:
+ Primary: GasPipeStraight
+ Secondary: GasPipeStraightAlt1
+ Tertiary: GasPipeStraightAlt2
- type: Construction
graph: GasPipe
node: straight
- type: Item
- size: Normal
storedSprite:
sprite: Structures/Piping/Atmospherics/pipe.rsi
state: storageStraight
@@ -132,6 +162,8 @@
parent: GasPipeBase
id: GasPipeBend
suffix: Bend
+ placement:
+ mode: AlignAtmosPipeLayers
components:
- type: NodeContainer
nodes:
@@ -143,11 +175,15 @@
layers:
- state: pipeBend
map: [ "enum.PipeVisualLayers.Pipe" ]
+ - type: AtmosPipeLayers
+ alternativePrototypes:
+ Primary: GasPipeBend
+ Secondary: GasPipeBendAlt1
+ Tertiary: GasPipeBendAlt2
- type: Construction
graph: GasPipe
node: bend
- type: Item
- size: Small
shape:
- 0,0,1,0
- 1,1,1,1
@@ -175,6 +211,8 @@
- type: entity
parent: GasPipeBase
id: GasPipeTJunction
+ placement:
+ mode: AlignAtmosPipeLayers
suffix: TJunction
components:
- type: NodeContainer
@@ -187,14 +225,15 @@
layers:
- state: pipeTJunction
map: [ "enum.PipeVisualLayers.Pipe" ]
+ - type: AtmosPipeLayers
+ alternativePrototypes:
+ Primary: GasPipeTJunction
+ Secondary: GasPipeTJunctionAlt1
+ Tertiary: GasPipeTJunctionAlt2
- type: Construction
graph: GasPipe
node: tjunction
- type: Item
- size: Normal
- shape:
- - 0,0,2,0
- - 1,1,1,1
heldPrefix: TJunction
storedSprite:
sprite: Structures/Piping/Atmospherics/pipe.rsi
@@ -216,6 +255,8 @@
parent: GasPipeBase
id: GasPipeFourway
suffix: Fourway
+ placement:
+ mode: AlignAtmosPipeLayers
components:
- type: Transform
noRot: true
@@ -229,15 +270,19 @@
layers:
- state: pipeFourway
map: [ "enum.PipeVisualLayers.Pipe" ]
+ - type: AtmosPipeLayers
+ alternativePrototypes:
+ Primary: GasPipeFourway
+ Secondary: GasPipeFourwayAlt1
+ Tertiary: GasPipeFourwayAlt2
- type: Construction
graph: GasPipe
node: fourway
- type: Item
- size: Normal
- shape:
- - 1,0,1,2
- - 0,1,2,1
heldPrefix: Fourway
+ storedSprite:
+ sprite: Structures/Piping/Atmospherics/pipe.rsi
+ state: storageFourway
- type: MeleeWeapon
wideAnimationRotation: 90
attackRate: 0.75
@@ -264,9 +309,13 @@
layers:
- state: pipeBroken
map: [ "enum.PipeVisualLayers.Pipe" ]
+ - type: AtmosPipeLayers
+ numberOfPipeLayers: 1
- type: Construction
graph: GasPipe
node: broken
+ - type: Item
+ size: Small
- type: Destructible
thresholds: # override parent to avoid recursive destruction
- trigger:
@@ -279,3 +328,74 @@
guides:
- Pipes
- PipeNetworks
+
+- type: entity
+ parent: GasPipeSansLayers
+ id: GasPipeManifold
+ name: gas pipe manifold
+ description: Allows gas pipes of different configurations to be connected together.
+ placement:
+ mode: SnapgridCenter
+ components:
+ - type: Sprite
+ sprite: Structures/Piping/Atmospherics/manifold.rsi
+ layers:
+ - state: pipeManifold
+ map: [ "enum.PipeVisualLayers.Pipe" ]
+ - type: AtmosPipeLayers
+ pipeLayersLocked: true
+ - type: PipeAppearance
+ sprite:
+ - { sprite: Structures/Piping/Atmospherics/manifold.rsi, state: pipeConnector }
+ - { sprite: Structures/Piping/Atmospherics/manifold.rsi, state: pipeConnector_alt1 }
+ - { sprite: Structures/Piping/Atmospherics/manifold.rsi, state: pipeConnector_alt2 }
+ - type: Construction
+ graph: GasPipe
+ node: manifold
+ - type: Item
+ size: Small
+ shape:
+ - 0,0,1,0
+ storedSprite:
+ sprite: Structures/Piping/Atmospherics/manifold.rsi
+ state: storageManifold
+ - type: NodeContainer
+ nodes:
+ south0:
+ !type:PipeNode
+ nodeGroupID: Pipe
+ pipeDirection: South
+ pipeLayer: 0
+ south1:
+ !type:PipeNode
+ nodeGroupID: Pipe
+ pipeDirection: South
+ pipeLayer: 1
+ south2:
+ !type:PipeNode
+ nodeGroupID: Pipe
+ pipeDirection: South
+ pipeLayer: 2
+ north0:
+ !type:PipeNode
+ nodeGroupID: Pipe
+ pipeDirection: North
+ pipeLayer: 0
+ north1:
+ !type:PipeNode
+ nodeGroupID: Pipe
+ pipeDirection: North
+ pipeLayer: 1
+ north2:
+ !type:PipeNode
+ nodeGroupID: Pipe
+ pipeDirection: North
+ pipeLayer: 2
+ - type: GasPipeManifold
+ - type: AtmosMonitoringConsoleDevice
+ navMapBlip: GasPipeManifold
+ showAbsentConnections: false
+ - type: AtmosDevice
+ - type: Tag
+ tags:
+ - Unstackable
diff --git a/Resources/Prototypes/Entities/Structures/Piping/Atmospherics/unary.yml b/Resources/Prototypes/Entities/Structures/Piping/Atmospherics/unary.yml
index abb0ead4a0..612e144e53 100644
--- a/Resources/Prototypes/Entities/Structures/Piping/Atmospherics/unary.yml
+++ b/Resources/Prototypes/Entities/Structures/Piping/Atmospherics/unary.yml
@@ -44,7 +44,7 @@
sprite: Structures/Piping/Atmospherics/vent.rsi
layers:
- sprite: Structures/Piping/Atmospherics/pipe.rsi
- state: pipeHalf
+ state: pipeUnaryConnectors
map: [ "enum.PipeVisualLayers.Pipe" ]
- state: vent_off
map: [ "enabled", "enum.SubfloorLayers.FirstLayer" ]
@@ -94,7 +94,7 @@
sprite: Structures/Piping/Atmospherics/vent.rsi
layers:
- sprite: Structures/Piping/Atmospherics/pipe.rsi
- state: pipeHalf
+ state: pipeUnaryConnectors
map: [ "enum.PipeVisualLayers.Pipe" ]
- state: vent_passive
map: [ "enum.SubfloorLayers.FirstLayer" ]
@@ -134,7 +134,7 @@
sprite: Structures/Piping/Atmospherics/scrubber.rsi
layers:
- sprite: Structures/Piping/Atmospherics/pipe.rsi
- state: pipeHalf
+ state: pipeUnaryConnectors
map: [ "enum.PipeVisualLayers.Pipe" ]
- state: scrub_off
map: [ "enabled", "enum.SubfloorLayers.FirstLayer" ]
@@ -180,7 +180,7 @@
drawdepth: FloorObjects
sprite: Structures/Piping/Atmospherics/outletinjector.rsi
layers:
- - state: pipeHalf
+ - state: pipeUnaryConnectors
sprite: Structures/Piping/Atmospherics/pipe.rsi
map: [ "enum.PipeVisualLayers.Pipe" ]
- state: injector
@@ -189,6 +189,7 @@
shader: unshaded
map: [ "enum.LightLayers.Unshaded" ]
color: "#990000"
+ - type: Appearance
- type: GenericVisualizer
visuals:
# toggle color of the unshaded light:
@@ -196,7 +197,6 @@
enum.LightLayers.Unshaded:
True: { color: "#5eff5e" }
False: { color: "#990000" }
- - type: Appearance
- type: PipeColorVisuals
- type: GasOutletInjector
- type: Construction
@@ -228,6 +228,12 @@
- type: Rotatable
- type: GasThermoMachine
- type: AtmosPipeColor
+ - type: AtmosPipeLayers
+ spriteLayersRsiPaths:
+ enum.PipeVisualLayers.Pipe:
+ Primary: Structures/Piping/Atmospherics/thermomachine.rsi
+ Secondary: Structures/Piping/Atmospherics/thermomachine_alt1.rsi
+ Tertiary: Structures/Piping/Atmospherics/thermomachine_alt2.rsi
- type: AtmosDevice
- type: UserInterface
interfaces:
@@ -405,6 +411,7 @@
map: ["enum.SolutionContainerLayers.Fill"]
visible: false
- state: trans
+ - type: Appearance
- type: GenericVisualizer
visuals:
enum.PowerDeviceVisuals.Powered:
@@ -414,11 +421,16 @@
- type: SolutionContainerVisuals
maxFillLevels: 7
fillBaseName: fill-
- - type: Appearance
- type: PipeColorVisuals
- type: Rotatable
- type: GasCondenser
- type: AtmosPipeColor
+ - type: AtmosPipeLayers
+ spriteLayersRsiPaths:
+ enum.PipeVisualLayers.Pipe:
+ Primary: Structures/Piping/Atmospherics/condenser.rsi
+ Secondary: Structures/Piping/Atmospherics/condenser_alt1.rsi
+ Tertiary: Structures/Piping/Atmospherics/condenser_alt2.rsi
- type: AtmosDevice
- type: PipeRestrictOverlap
- type: ApcPowerReceiver
@@ -470,3 +482,4 @@
- type: GuideHelp
guides:
- GasCondensing
+
diff --git a/Resources/Prototypes/Recipes/Construction/Graphs/utilities/atmos_pipes.yml b/Resources/Prototypes/Recipes/Construction/Graphs/utilities/atmos_pipes.yml
index 771c63ebd5..14d487fdb5 100644
--- a/Resources/Prototypes/Recipes/Construction/Graphs/utilities/atmos_pipes.yml
+++ b/Resources/Prototypes/Recipes/Construction/Graphs/utilities/atmos_pipes.yml
@@ -10,30 +10,96 @@
amount: 1
doAfter: 1
+ - to: halfAlt1
+ steps:
+ - material: Steel
+ amount: 1
+ doAfter: 1
+
+ - to: halfAlt2
+ steps:
+ - material: Steel
+ amount: 1
+ doAfter: 1
+
- to: straight
steps:
- material: Steel
amount: 1
doAfter: 1
+ - to: straightAlt1
+ steps:
+ - material: Steel
+ amount: 1
+ doAfter: 1
+
+ - to: straightAlt2
+ steps:
+ - material: Steel
+ amount: 1
+ doAfter: 1
+
- to: bend
steps:
- material: Steel
amount: 1
doAfter: 1
+ - to: bendAlt1
+ steps:
+ - material: Steel
+ amount: 1
+ doAfter: 1
+
+ - to: bendAlt2
+ steps:
+ - material: Steel
+ amount: 1
+ doAfter: 1
+
- to: tjunction
steps:
- material: Steel
amount: 1
doAfter: 1
+ - to: tjunctionAlt1
+ steps:
+ - material: Steel
+ amount: 1
+ doAfter: 1
+
+ - to: tjunctionAlt2
+ steps:
+ - material: Steel
+ amount: 1
+ doAfter: 1
+
- to: fourway
steps:
- material: Steel
amount: 1
doAfter: 1
+ - to: fourwayAlt1
+ steps:
+ - material: Steel
+ amount: 1
+ doAfter: 1
+
+ - to: fourwayAlt2
+ steps:
+ - material: Steel
+ amount: 1
+ doAfter: 1
+
+ - to: manifold
+ steps:
+ - material: Steel
+ amount: 2
+ doAfter: 1
+
- node: half
entity: GasPipeHalf
edges:
@@ -50,6 +116,38 @@
- tool: Welding
doAfter: 1
+ - node: halfAlt1
+ entity: GasPipeHalfAlt1
+ edges:
+ - to: start
+ conditions:
+ - !type:EntityAnchored
+ anchored: false
+ completed:
+ - !type:SpawnPrototype
+ prototype: SheetSteel1
+ amount: 1
+ - !type:DeleteEntity
+ steps:
+ - tool: Welding
+ doAfter: 1
+
+ - node: halfAlt2
+ entity: GasPipeHalfAlt2
+ edges:
+ - to: start
+ conditions:
+ - !type:EntityAnchored
+ anchored: false
+ completed:
+ - !type:SpawnPrototype
+ prototype: SheetSteel1
+ amount: 1
+ - !type:DeleteEntity
+ steps:
+ - tool: Welding
+ doAfter: 1
+
- node: straight
entity: GasPipeStraight
edges:
@@ -66,6 +164,38 @@
- tool: Welding
doAfter: 1
+ - node: straightAlt1
+ entity: GasPipeStraightAlt1
+ edges:
+ - to: start
+ conditions:
+ - !type:EntityAnchored
+ anchored: false
+ completed:
+ - !type:SpawnPrototype
+ prototype: SheetSteel1
+ amount: 1
+ - !type:DeleteEntity
+ steps:
+ - tool: Welding
+ doAfter: 1
+
+ - node: straightAlt2
+ entity: GasPipeStraightAlt2
+ edges:
+ - to: start
+ conditions:
+ - !type:EntityAnchored
+ anchored: false
+ completed:
+ - !type:SpawnPrototype
+ prototype: SheetSteel1
+ amount: 1
+ - !type:DeleteEntity
+ steps:
+ - tool: Welding
+ doAfter: 1
+
- node: bend
entity: GasPipeBend
edges:
@@ -82,6 +212,38 @@
- tool: Welding
doAfter: 1
+ - node: bendAlt1
+ entity: GasPipeBendAlt1
+ edges:
+ - to: start
+ conditions:
+ - !type:EntityAnchored
+ anchored: false
+ completed:
+ - !type:SpawnPrototype
+ prototype: SheetSteel1
+ amount: 1
+ - !type:DeleteEntity
+ steps:
+ - tool: Welding
+ doAfter: 1
+
+ - node: bendAlt2
+ entity: GasPipeBendAlt2
+ edges:
+ - to: start
+ conditions:
+ - !type:EntityAnchored
+ anchored: false
+ completed:
+ - !type:SpawnPrototype
+ prototype: SheetSteel1
+ amount: 1
+ - !type:DeleteEntity
+ steps:
+ - tool: Welding
+ doAfter: 1
+
- node: tjunction
entity: GasPipeTJunction
edges:
@@ -98,6 +260,38 @@
- tool: Welding
doAfter: 1
+ - node: tjunctionAlt1
+ entity: GasPipeTJunctionAlt1
+ edges:
+ - to: start
+ conditions:
+ - !type:EntityAnchored
+ anchored: false
+ completed:
+ - !type:SpawnPrototype
+ prototype: SheetSteel1
+ amount: 1
+ - !type:DeleteEntity
+ steps:
+ - tool: Welding
+ doAfter: 1
+
+ - node: tjunctionAlt2
+ entity: GasPipeTJunctionAlt2
+ edges:
+ - to: start
+ conditions:
+ - !type:EntityAnchored
+ anchored: false
+ completed:
+ - !type:SpawnPrototype
+ prototype: SheetSteel1
+ amount: 1
+ - !type:DeleteEntity
+ steps:
+ - tool: Welding
+ doAfter: 1
+
- node: fourway
entity: GasPipeFourway
edges:
@@ -114,6 +308,38 @@
- tool: Welding
doAfter: 1
+ - node: fourwayAlt1
+ entity: GasPipeFourwayAlt1
+ edges:
+ - to: start
+ conditions:
+ - !type:EntityAnchored
+ anchored: false
+ completed:
+ - !type:SpawnPrototype
+ prototype: SheetSteel1
+ amount: 1
+ - !type:DeleteEntity
+ steps:
+ - tool: Welding
+ doAfter: 1
+
+ - node: fourwayAlt2
+ entity: GasPipeFourwayAlt2
+ edges:
+ - to: start
+ conditions:
+ - !type:EntityAnchored
+ anchored: false
+ completed:
+ - !type:SpawnPrototype
+ prototype: SheetSteel1
+ amount: 1
+ - !type:DeleteEntity
+ steps:
+ - tool: Welding
+ doAfter: 1
+
- node: broken
entity: GasPipeBroken
edges:
@@ -129,3 +355,19 @@
steps:
- tool: Welding
doAfter: 1
+
+ - node: manifold
+ entity: GasPipeManifold
+ edges:
+ - to: start
+ conditions:
+ - !type:EntityAnchored
+ anchored: false
+ completed:
+ - !type:SpawnPrototype
+ prototype: SheetSteel1
+ amount: 2
+ - !type:DeleteEntity
+ steps:
+ - tool: Welding
+ doAfter: 1
diff --git a/Resources/Prototypes/Recipes/Construction/utilities.yml b/Resources/Prototypes/Recipes/Construction/utilities.yml
index 575ca3ae4e..67389f85af 100644
--- a/Resources/Prototypes/Recipes/Construction/utilities.yml
+++ b/Resources/Prototypes/Recipes/Construction/utilities.yml
@@ -281,8 +281,40 @@
startNode: start
targetNode: half
category: construction-category-utilities
- placementMode: SnapgridCenter
+ placementMode: AlignAtmosPipeLayers
canBuildInImpassable: true
+ alternativePrototypes:
+ - GasPipeHalf
+ - GasPipeHalfAlt1
+ - GasPipeHalfAlt2
+
+- type: construction
+ id: GasPipeHalfAlt1
+ hide: true
+ graph: GasPipe
+ startNode: start
+ targetNode: halfAlt1
+ category: construction-category-utilities
+ placementMode: AlignAtmosPipeLayers
+ canBuildInImpassable: true
+ alternativePrototypes:
+ - GasPipeHalf
+ - GasPipeHalfAlt1
+ - GasPipeHalfAlt2
+
+- type: construction
+ id: GasPipeHalfAlt2
+ hide: true
+ graph: GasPipe
+ startNode: start
+ targetNode: halfAlt2
+ category: construction-category-utilities
+ placementMode: AlignAtmosPipeLayers
+ canBuildInImpassable: true
+ alternativePrototypes:
+ - GasPipeHalf
+ - GasPipeHalfAlt1
+ - GasPipeHalfAlt2
- type: construction
id: GasPipeStraight
@@ -290,8 +322,40 @@
startNode: start
targetNode: straight
category: construction-category-utilities
- placementMode: SnapgridCenter
+ placementMode: AlignAtmosPipeLayers
canBuildInImpassable: true
+ alternativePrototypes:
+ - GasPipeStraight
+ - GasPipeStraightAlt1
+ - GasPipeStraightAlt2
+
+- type: construction
+ id: GasPipeStraightAlt1
+ hide: true
+ graph: GasPipe
+ startNode: start
+ targetNode: straightAlt1
+ category: construction-category-utilities
+ placementMode: AlignAtmosPipeLayers
+ canBuildInImpassable: true
+ alternativePrototypes:
+ - GasPipeStraight
+ - GasPipeStraightAlt1
+ - GasPipeStraightAlt2
+
+- type: construction
+ id: GasPipeStraightAlt2
+ hide: true
+ graph: GasPipe
+ startNode: start
+ targetNode: straightAlt2
+ category: construction-category-utilities
+ placementMode: AlignAtmosPipeLayers
+ canBuildInImpassable: true
+ alternativePrototypes:
+ - GasPipeStraight
+ - GasPipeStraightAlt1
+ - GasPipeStraightAlt2
- type: construction
id: GasPipeBend
@@ -299,8 +363,40 @@
startNode: start
targetNode: bend
category: construction-category-utilities
- placementMode: SnapgridCenter
+ placementMode: AlignAtmosPipeLayers
canBuildInImpassable: true
+ alternativePrototypes:
+ - GasPipeBend
+ - GasPipeBendAlt1
+ - GasPipeBendAlt2
+
+- type: construction
+ id: GasPipeBendAlt1
+ hide: true
+ graph: GasPipe
+ startNode: start
+ targetNode: bendAlt1
+ category: construction-category-utilities
+ placementMode: AlignAtmosPipeLayers
+ canBuildInImpassable: true
+ alternativePrototypes:
+ - GasPipeBend
+ - GasPipeBendAlt1
+ - GasPipeBendAlt2
+
+- type: construction
+ id: GasPipeBendAlt2
+ hide: true
+ graph: GasPipe
+ startNode: start
+ targetNode: bendAlt2
+ category: construction-category-utilities
+ placementMode: AlignAtmosPipeLayers
+ canBuildInImpassable: true
+ alternativePrototypes:
+ - GasPipeBend
+ - GasPipeBendAlt1
+ - GasPipeBendAlt2
- type: construction
id: GasPipeTJunction
@@ -308,8 +404,40 @@
startNode: start
targetNode: tjunction
category: construction-category-utilities
- placementMode: SnapgridCenter
+ placementMode: AlignAtmosPipeLayers
canBuildInImpassable: true
+ alternativePrototypes:
+ - GasPipeTJunction
+ - GasPipeTJunctionAlt1
+ - GasPipeTJunctionAlt2
+
+- type: construction
+ id: GasPipeTJunctionAlt1
+ hide: true
+ graph: GasPipe
+ startNode: start
+ targetNode: tjunctionAlt1
+ category: construction-category-utilities
+ placementMode: AlignAtmosPipeLayers
+ canBuildInImpassable: true
+ alternativePrototypes:
+ - GasPipeTJunction
+ - GasPipeTJunctionAlt1
+ - GasPipeTJunctionAlt2
+
+- type: construction
+ id: GasPipeTJunctionAlt2
+ hide: true
+ graph: GasPipe
+ startNode: start
+ targetNode: tjunctionAlt2
+ category: construction-category-utilities
+ placementMode: AlignAtmosPipeLayers
+ canBuildInImpassable: true
+ alternativePrototypes:
+ - GasPipeTJunction
+ - GasPipeTJunctionAlt1
+ - GasPipeTJunctionAlt2
- type: construction
id: GasPipeFourway
@@ -317,6 +445,47 @@
startNode: start
targetNode: fourway
category: construction-category-utilities
+ placementMode: AlignAtmosPipeLayers
+ canBuildInImpassable: true
+ alternativePrototypes:
+ - GasPipeFourway
+ - GasPipeFourwayAlt1
+ - GasPipeFourwayAlt2
+
+- type: construction
+ id: GasPipeFourwayAlt1
+ hide: true
+ graph: GasPipe
+ startNode: start
+ targetNode: fourwayAlt1
+ category: construction-category-utilities
+ placementMode: AlignAtmosPipeLayers
+ canBuildInImpassable: true
+ alternativePrototypes:
+ - GasPipeFourway
+ - GasPipeFourwayAlt1
+ - GasPipeFourwayAlt2
+
+- type: construction
+ id: GasPipeFourwayAlt2
+ hide: true
+ graph: GasPipe
+ startNode: start
+ targetNode: fourwayAlt2
+ category: construction-category-utilities
+ placementMode: AlignAtmosPipeLayers
+ canBuildInImpassable: true
+ alternativePrototypes:
+ - GasPipeFourway
+ - GasPipeFourwayAlt1
+ - GasPipeFourwayAlt2
+
+- type: construction
+ id: GasPipeManifold
+ graph: GasPipe
+ startNode: start
+ targetNode: manifold
+ category: construction-category-utilities
placementMode: SnapgridCenter
canBuildInImpassable: true
diff --git a/Resources/Textures/Interface/NavMap/attributions.yml b/Resources/Textures/Interface/NavMap/attributions.yml
index f624c0f448..344b871ae9 100644
--- a/Resources/Textures/Interface/NavMap/attributions.yml
+++ b/Resources/Textures/Interface/NavMap/attributions.yml
@@ -43,6 +43,16 @@
copyright: "Created by chromiumboy"
source: "https://github.com/chromiumboy"
+- files: ["beveled_rectangle_east_west.png"]
+ license: "CC-BY-SA-3.0"
+ copyright: "Created by chromiumboy"
+ source: "https://github.com/chromiumboy"
+
+- files: ["beveled_rectangle_north_south.png"]
+ license: "CC-BY-SA-3.0"
+ copyright: "Created by chromiumboy"
+ source: "https://github.com/chromiumboy"
+
- files: ["beveled_square.png"]
license: "CC-BY-SA-3.0"
copyright: "Created by chromiumboy"
diff --git a/Resources/Textures/Interface/NavMap/beveled_rectangle_east_west.png b/Resources/Textures/Interface/NavMap/beveled_rectangle_east_west.png
new file mode 100644
index 0000000000..9a972cb939
Binary files /dev/null and b/Resources/Textures/Interface/NavMap/beveled_rectangle_east_west.png differ
diff --git a/Resources/Textures/Interface/NavMap/beveled_rectangle_east_west.png.yml b/Resources/Textures/Interface/NavMap/beveled_rectangle_east_west.png.yml
new file mode 100644
index 0000000000..dabd6601f7
--- /dev/null
+++ b/Resources/Textures/Interface/NavMap/beveled_rectangle_east_west.png.yml
@@ -0,0 +1,2 @@
+sample:
+ filter: true
diff --git a/Resources/Textures/Interface/NavMap/beveled_rectangle_north_south.png b/Resources/Textures/Interface/NavMap/beveled_rectangle_north_south.png
new file mode 100644
index 0000000000..a2a870381d
Binary files /dev/null and b/Resources/Textures/Interface/NavMap/beveled_rectangle_north_south.png differ
diff --git a/Resources/Textures/Interface/NavMap/beveled_rectangle_north_south.png.yml b/Resources/Textures/Interface/NavMap/beveled_rectangle_north_south.png.yml
new file mode 100644
index 0000000000..dabd6601f7
--- /dev/null
+++ b/Resources/Textures/Interface/NavMap/beveled_rectangle_north_south.png.yml
@@ -0,0 +1,2 @@
+sample:
+ filter: true
diff --git a/Resources/Textures/Interface/VerbIcons/ATTRIBUTION.txt b/Resources/Textures/Interface/VerbIcons/ATTRIBUTION.txt
index bb584a7c20..ee497a1c04 100644
--- a/Resources/Textures/Interface/VerbIcons/ATTRIBUTION.txt
+++ b/Resources/Textures/Interface/VerbIcons/ATTRIBUTION.txt
@@ -10,3 +10,6 @@ https://game-icons.net/1x1/delapouite/padlock-open.html
bubbles.svg by Lorc under CC BY 3.0
https://game-icons.net/1x1/lorc/bubbles.html
+
+screwdriver.png by Lorc (edited by chromiumboy) under CC BY 3.0
+https://game-icons.net/1x1/lorc/screwdriver.html
diff --git a/Resources/Textures/Interface/VerbIcons/screwdriver.png b/Resources/Textures/Interface/VerbIcons/screwdriver.png
new file mode 100644
index 0000000000..e230262fe0
Binary files /dev/null and b/Resources/Textures/Interface/VerbIcons/screwdriver.png differ
diff --git a/Resources/Textures/Interface/VerbIcons/screwdriver.png.yml b/Resources/Textures/Interface/VerbIcons/screwdriver.png.yml
new file mode 100644
index 0000000000..5c43e23305
--- /dev/null
+++ b/Resources/Textures/Interface/VerbIcons/screwdriver.png.yml
@@ -0,0 +1,2 @@
+sample:
+ filter: true
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/condenser.rsi/meta.json b/Resources/Textures/Structures/Piping/Atmospherics/condenser.rsi/meta.json
index 05a1e617a5..0ad29bf3a8 100644
--- a/Resources/Textures/Structures/Piping/Atmospherics/condenser.rsi/meta.json
+++ b/Resources/Textures/Structures/Piping/Atmospherics/condenser.rsi/meta.json
@@ -1,21 +1,18 @@
{
- "version":1,
- "size":
- {
- "x":32,
- "y":32
+ "version": 1,
+ "size": {
+ "x": 32,
+ "y": 32
},
- "copyright":"Created by EmoGarbage404 (github) for Space Station 14.",
- "license":"CC0-1.0",
- "states":
- [
+ "copyright": "Created by EmoGarbage404 (github) for Space Station 14, edited by chromiumboy.",
+ "license": "CC0-1.0",
+ "states": [
{
- "name":"off"
+ "name": "off"
},
{
- "name":"on",
- "delays":
- [
+ "name": "on",
+ "delays": [
[
0.05,
0.05,
@@ -26,38 +23,38 @@
]
},
{
- "name":"panel"
+ "name": "panel"
},
{
- "name":"trans"
+ "name": "trans"
},
{
- "name":"pipe",
- "directions":4
+ "name": "pipe",
+ "directions": 4
},
{
- "name":"display"
+ "name": "display"
},
{
- "name":"fill-1"
+ "name": "fill-1"
},
{
- "name":"fill-2"
+ "name": "fill-2"
},
{
- "name":"fill-3"
+ "name": "fill-3"
},
{
- "name":"fill-4"
+ "name": "fill-4"
},
{
- "name":"fill-5"
+ "name": "fill-5"
},
{
- "name":"fill-6"
+ "name": "fill-6"
},
{
- "name":"fill-7"
+ "name": "fill-7"
}
]
}
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/condenser.rsi/pipe.png b/Resources/Textures/Structures/Piping/Atmospherics/condenser.rsi/pipe.png
index c9fbbec300..694a3a15b6 100644
Binary files a/Resources/Textures/Structures/Piping/Atmospherics/condenser.rsi/pipe.png and b/Resources/Textures/Structures/Piping/Atmospherics/condenser.rsi/pipe.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/condenser_alt1.rsi/meta.json b/Resources/Textures/Structures/Piping/Atmospherics/condenser_alt1.rsi/meta.json
new file mode 100644
index 0000000000..3176fce2dc
--- /dev/null
+++ b/Resources/Textures/Structures/Piping/Atmospherics/condenser_alt1.rsi/meta.json
@@ -0,0 +1,15 @@
+{
+ "version": 1,
+ "size": {
+ "x": 32,
+ "y": 32
+ },
+ "copyright": "Created by EmoGarbage404 (github) for Space Station 14, edited by chromiumboy.",
+ "license": "CC0-1.0",
+ "states": [
+ {
+ "name": "pipe",
+ "directions": 4
+ }
+ ]
+}
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/condenser_alt1.rsi/pipe.png b/Resources/Textures/Structures/Piping/Atmospherics/condenser_alt1.rsi/pipe.png
new file mode 100644
index 0000000000..e5ae1993fe
Binary files /dev/null and b/Resources/Textures/Structures/Piping/Atmospherics/condenser_alt1.rsi/pipe.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/condenser_alt2.rsi/meta.json b/Resources/Textures/Structures/Piping/Atmospherics/condenser_alt2.rsi/meta.json
new file mode 100644
index 0000000000..3176fce2dc
--- /dev/null
+++ b/Resources/Textures/Structures/Piping/Atmospherics/condenser_alt2.rsi/meta.json
@@ -0,0 +1,15 @@
+{
+ "version": 1,
+ "size": {
+ "x": 32,
+ "y": 32
+ },
+ "copyright": "Created by EmoGarbage404 (github) for Space Station 14, edited by chromiumboy.",
+ "license": "CC0-1.0",
+ "states": [
+ {
+ "name": "pipe",
+ "directions": 4
+ }
+ ]
+}
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/condenser_alt2.rsi/pipe.png b/Resources/Textures/Structures/Piping/Atmospherics/condenser_alt2.rsi/pipe.png
new file mode 100644
index 0000000000..4ac647a2ad
Binary files /dev/null and b/Resources/Textures/Structures/Piping/Atmospherics/condenser_alt2.rsi/pipe.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/gas_pipe_sensor.rsi/base.png b/Resources/Textures/Structures/Piping/Atmospherics/gas_pipe_sensor.rsi/base.png
index 4a9a8f6f20..5858ec39fb 100644
Binary files a/Resources/Textures/Structures/Piping/Atmospherics/gas_pipe_sensor.rsi/base.png and b/Resources/Textures/Structures/Piping/Atmospherics/gas_pipe_sensor.rsi/base.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/gas_pipe_sensor.rsi/lights.png b/Resources/Textures/Structures/Piping/Atmospherics/gas_pipe_sensor.rsi/lights.png
index 6108d2b994..f294bc3fce 100644
Binary files a/Resources/Textures/Structures/Piping/Atmospherics/gas_pipe_sensor.rsi/lights.png and b/Resources/Textures/Structures/Piping/Atmospherics/gas_pipe_sensor.rsi/lights.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/gas_pipe_sensor.rsi/meta.json b/Resources/Textures/Structures/Piping/Atmospherics/gas_pipe_sensor.rsi/meta.json
index 878c7817a2..bfe74c313c 100644
--- a/Resources/Textures/Structures/Piping/Atmospherics/gas_pipe_sensor.rsi/meta.json
+++ b/Resources/Textures/Structures/Piping/Atmospherics/gas_pipe_sensor.rsi/meta.json
@@ -10,15 +10,29 @@
{
"name": "icon"
},
- {
- "name": "base"
+ {
+ "name": "base",
+ "directions": 4
},
- {
+ {
"name": "blank"
},
{
"name": "lights",
+ "directions": 4,
"delays": [
+ [
+ 1.0,
+ 0.25
+ ],
+ [
+ 1.0,
+ 0.25
+ ],
+ [
+ 1.0,
+ 0.25
+ ],
[
1.0,
0.25
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/gas_pipe_sensor_alt1.rsi/base.png b/Resources/Textures/Structures/Piping/Atmospherics/gas_pipe_sensor_alt1.rsi/base.png
new file mode 100644
index 0000000000..0afdd9f846
Binary files /dev/null and b/Resources/Textures/Structures/Piping/Atmospherics/gas_pipe_sensor_alt1.rsi/base.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/gas_pipe_sensor_alt1.rsi/blank.png b/Resources/Textures/Structures/Piping/Atmospherics/gas_pipe_sensor_alt1.rsi/blank.png
new file mode 100644
index 0000000000..7bee0a002b
Binary files /dev/null and b/Resources/Textures/Structures/Piping/Atmospherics/gas_pipe_sensor_alt1.rsi/blank.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/gas_pipe_sensor_alt1.rsi/icon.png b/Resources/Textures/Structures/Piping/Atmospherics/gas_pipe_sensor_alt1.rsi/icon.png
new file mode 100644
index 0000000000..4ac9e76480
Binary files /dev/null and b/Resources/Textures/Structures/Piping/Atmospherics/gas_pipe_sensor_alt1.rsi/icon.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/gas_pipe_sensor_alt1.rsi/lights.png b/Resources/Textures/Structures/Piping/Atmospherics/gas_pipe_sensor_alt1.rsi/lights.png
new file mode 100644
index 0000000000..45d84c3d5c
Binary files /dev/null and b/Resources/Textures/Structures/Piping/Atmospherics/gas_pipe_sensor_alt1.rsi/lights.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/gas_pipe_sensor_alt1.rsi/meta.json b/Resources/Textures/Structures/Piping/Atmospherics/gas_pipe_sensor_alt1.rsi/meta.json
new file mode 100644
index 0000000000..bfe74c313c
--- /dev/null
+++ b/Resources/Textures/Structures/Piping/Atmospherics/gas_pipe_sensor_alt1.rsi/meta.json
@@ -0,0 +1,43 @@
+{
+ "version": 1,
+ "license": "CC-BY-SA-3.0",
+ "copyright": "Created by chromiumboy (github) for SS14, based on the digital valve from /tg/, taken from https://github.com/tgstation/tgstation at commit 57cd1d59ca019dd0e7811ac451f295f818e573da.",
+ "size": {
+ "x": 32,
+ "y": 32
+ },
+ "states": [
+ {
+ "name": "icon"
+ },
+ {
+ "name": "base",
+ "directions": 4
+ },
+ {
+ "name": "blank"
+ },
+ {
+ "name": "lights",
+ "directions": 4,
+ "delays": [
+ [
+ 1.0,
+ 0.25
+ ],
+ [
+ 1.0,
+ 0.25
+ ],
+ [
+ 1.0,
+ 0.25
+ ],
+ [
+ 1.0,
+ 0.25
+ ]
+ ]
+ }
+ ]
+}
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/gas_pipe_sensor_alt2.rsi/base.png b/Resources/Textures/Structures/Piping/Atmospherics/gas_pipe_sensor_alt2.rsi/base.png
new file mode 100644
index 0000000000..131d75e9d2
Binary files /dev/null and b/Resources/Textures/Structures/Piping/Atmospherics/gas_pipe_sensor_alt2.rsi/base.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/gas_pipe_sensor_alt2.rsi/blank.png b/Resources/Textures/Structures/Piping/Atmospherics/gas_pipe_sensor_alt2.rsi/blank.png
new file mode 100644
index 0000000000..7bee0a002b
Binary files /dev/null and b/Resources/Textures/Structures/Piping/Atmospherics/gas_pipe_sensor_alt2.rsi/blank.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/gas_pipe_sensor_alt2.rsi/icon.png b/Resources/Textures/Structures/Piping/Atmospherics/gas_pipe_sensor_alt2.rsi/icon.png
new file mode 100644
index 0000000000..4ac9e76480
Binary files /dev/null and b/Resources/Textures/Structures/Piping/Atmospherics/gas_pipe_sensor_alt2.rsi/icon.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/gas_pipe_sensor_alt2.rsi/lights.png b/Resources/Textures/Structures/Piping/Atmospherics/gas_pipe_sensor_alt2.rsi/lights.png
new file mode 100644
index 0000000000..826c90d5a0
Binary files /dev/null and b/Resources/Textures/Structures/Piping/Atmospherics/gas_pipe_sensor_alt2.rsi/lights.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/gas_pipe_sensor_alt2.rsi/meta.json b/Resources/Textures/Structures/Piping/Atmospherics/gas_pipe_sensor_alt2.rsi/meta.json
new file mode 100644
index 0000000000..bfe74c313c
--- /dev/null
+++ b/Resources/Textures/Structures/Piping/Atmospherics/gas_pipe_sensor_alt2.rsi/meta.json
@@ -0,0 +1,43 @@
+{
+ "version": 1,
+ "license": "CC-BY-SA-3.0",
+ "copyright": "Created by chromiumboy (github) for SS14, based on the digital valve from /tg/, taken from https://github.com/tgstation/tgstation at commit 57cd1d59ca019dd0e7811ac451f295f818e573da.",
+ "size": {
+ "x": 32,
+ "y": 32
+ },
+ "states": [
+ {
+ "name": "icon"
+ },
+ {
+ "name": "base",
+ "directions": 4
+ },
+ {
+ "name": "blank"
+ },
+ {
+ "name": "lights",
+ "directions": 4,
+ "delays": [
+ [
+ 1.0,
+ 0.25
+ ],
+ [
+ 1.0,
+ 0.25
+ ],
+ [
+ 1.0,
+ 0.25
+ ],
+ [
+ 1.0,
+ 0.25
+ ]
+ ]
+ }
+ ]
+}
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/hellfirethermomachine.rsi/meta.json b/Resources/Textures/Structures/Piping/Atmospherics/hellfirethermomachine.rsi/meta.json
index 979d804fb4..f216c2f60d 100644
--- a/Resources/Textures/Structures/Piping/Atmospherics/hellfirethermomachine.rsi/meta.json
+++ b/Resources/Textures/Structures/Piping/Atmospherics/hellfirethermomachine.rsi/meta.json
@@ -1,38 +1,67 @@
{
- "version":1,
- "size":{"x":32,"y":32},
- "copyright":"Base sprites taken from tgstation, split to display on two layers (machinebody/panel) by Menshin, and recolored and edited by EmoGarbage404 (github)",
- "license":"CC-BY-SA-3.0",
- "states":[
+ "version": 1,
+ "size": {
+ "x": 32,
+ "y": 32
+ },
+ "copyright": "Base sprites taken from tgstation, split to display on two layers (machinebody/panel) by Menshin, and recolored and edited by EmoGarbage404 (github) and chromiumboy (github)",
+ "license": "CC-BY-SA-3.0",
+ "states": [
{
- "name":"freezerOff",
- "directions":1
+ "name": "freezerOff",
+ "directions": 1
},
{
- "name":"freezerPanelOpen",
- "directions":1
+ "name": "freezerPanelOpen",
+ "directions": 1
},
{
- "name":"freezerOn",
- "directions":1,
- "delays":[ [ 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1] ]
+ "name": "freezerOn",
+ "directions": 1,
+ "delays": [
+ [
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1
+ ]
+ ]
},
{
- "name":"heaterOff",
- "directions":1
+ "name": "heaterOff",
+ "directions": 1
},
{
- "name":"heaterPanelOpen",
- "directions":1
+ "name": "heaterPanelOpen",
+ "directions": 1
},
{
- "name":"heaterOn",
- "directions":1,
- "delays":[ [ 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1] ]
+ "name": "heaterOn",
+ "directions": 1,
+ "delays": [
+ [
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1
+ ]
+ ]
},
{
- "name":"pipe",
- "directions":4
+ "name": "pipe",
+ "directions": 4
}
]
}
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/hellfirethermomachine.rsi/pipe.png b/Resources/Textures/Structures/Piping/Atmospherics/hellfirethermomachine.rsi/pipe.png
index 620ba905be..e0209a7bc8 100644
Binary files a/Resources/Textures/Structures/Piping/Atmospherics/hellfirethermomachine.rsi/pipe.png and b/Resources/Textures/Structures/Piping/Atmospherics/hellfirethermomachine.rsi/pipe.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/manifold.rsi/meta.json b/Resources/Textures/Structures/Piping/Atmospherics/manifold.rsi/meta.json
new file mode 100644
index 0000000000..315063828b
--- /dev/null
+++ b/Resources/Textures/Structures/Piping/Atmospherics/manifold.rsi/meta.json
@@ -0,0 +1,30 @@
+{
+ "version": 1,
+ "size": {
+ "x": 32,
+ "y": 32
+ },
+ "copyright": "Base sprites taken from tgstation at https://github.com/tgstation/tgstation/commit/662c08272acd7be79531550919f56f846726eabb and edited by chromiumboy (github)",
+ "license": "CC-BY-SA-3.0",
+ "states": [
+ {
+ "name": "pipeManifold",
+ "directions": 4
+ },
+ {
+ "name": "storageManifold"
+ },
+ {
+ "name": "pipeConnector",
+ "directions": 4
+ },
+ {
+ "name": "pipeConnector_alt1",
+ "directions": 4
+ },
+ {
+ "name": "pipeConnector_alt2",
+ "directions": 4
+ }
+ ]
+}
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/manifold.rsi/pipeConnector.png b/Resources/Textures/Structures/Piping/Atmospherics/manifold.rsi/pipeConnector.png
new file mode 100644
index 0000000000..25e7906af1
Binary files /dev/null and b/Resources/Textures/Structures/Piping/Atmospherics/manifold.rsi/pipeConnector.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/manifold.rsi/pipeConnector_alt1.png b/Resources/Textures/Structures/Piping/Atmospherics/manifold.rsi/pipeConnector_alt1.png
new file mode 100644
index 0000000000..3f4debb814
Binary files /dev/null and b/Resources/Textures/Structures/Piping/Atmospherics/manifold.rsi/pipeConnector_alt1.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/manifold.rsi/pipeConnector_alt2.png b/Resources/Textures/Structures/Piping/Atmospherics/manifold.rsi/pipeConnector_alt2.png
new file mode 100644
index 0000000000..f64fc34cd3
Binary files /dev/null and b/Resources/Textures/Structures/Piping/Atmospherics/manifold.rsi/pipeConnector_alt2.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/manifold.rsi/pipeManifold.png b/Resources/Textures/Structures/Piping/Atmospherics/manifold.rsi/pipeManifold.png
new file mode 100644
index 0000000000..f81fbdc29c
Binary files /dev/null and b/Resources/Textures/Structures/Piping/Atmospherics/manifold.rsi/pipeManifold.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/manifold.rsi/storageManifold.png b/Resources/Textures/Structures/Piping/Atmospherics/manifold.rsi/storageManifold.png
new file mode 100644
index 0000000000..a9d3b0da05
Binary files /dev/null and b/Resources/Textures/Structures/Piping/Atmospherics/manifold.rsi/storageManifold.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/pipe.rsi/meta.json b/Resources/Textures/Structures/Piping/Atmospherics/pipe.rsi/meta.json
index aecb62aee5..82106dbfe6 100644
--- a/Resources/Textures/Structures/Piping/Atmospherics/pipe.rsi/meta.json
+++ b/Resources/Textures/Structures/Piping/Atmospherics/pipe.rsi/meta.json
@@ -1,87 +1,98 @@
{
- "version":1,
- "size":{
- "x":32,
- "y":32
- },
- "license":"CC-BY-SA-3.0",
- "copyright":"Inhand sprites by alzore_(discord) for SS14. pipeTrinaryConnectors made by Menshin for SS14 based on pipeTJunction, the rest is taken from https://github.com/tgstation/tgstation at commit 57cd1d59ca019dd0e7811ac451f295f818e573da.",
- "states":[
- {
- "name": "inhand-left",
- "directions":4
- },
- {
- "name":"inhand-right",
- "directions":4
- },
- {
- "name": "Bend-inhand-left",
- "directions":4
- },
- {
- "name":"Bend-inhand-right",
- "directions":4
- },
- {
- "name": "TJunction-inhand-left",
- "directions":4
- },
- {
- "name":"TJunction-inhand-right",
- "directions":4
- },
- {
- "name": "Fourway-inhand-left",
- "directions":4
- },
- {
- "name":"Fourway-inhand-right",
- "directions":4
- },
- {
- "name":"pipeBroken",
- "directions":1
- },
- {
- "name":"pipeTJunction",
- "directions":4
- },
- {
- "name":"pipeHalf",
- "directions":4
- },
- {
- "name":"pipeBend",
- "directions":4
- },
- {
- "name": "pipeFourway",
- "directions":4
- },
- {
- "name":"pipeStraight",
- "directions":4
- },
- {
- "name":"pipeConnector",
- "directions":4
- },
- {
- "name":"pipeTrinaryConnectors",
- "directions":4
- },
- {
- "name":"storageStraight",
- "directions":4
- },
- {
- "name":"storageBend",
- "directions":4
- },
- {
- "name":"storageTJunction",
- "directions":4
- }
- ]
+ "version": 1,
+ "size": {
+ "x": 32,
+ "y": 32
+ },
+ "license": "CC-BY-SA-3.0",
+ "copyright": "Inhand sprites by alzore_(discord) for SS14. pipeTrinaryConnectors made by Menshin for SS14 based on pipeTJunction, the rest is taken from https://github.com/tgstation/tgstation at commit 57cd1d59ca019dd0e7811ac451f295f818e573da, edited by chromiumboy.",
+ "states": [
+ {
+ "name": "inhand-left",
+ "directions": 4
+ },
+ {
+ "name": "inhand-right",
+ "directions": 4
+ },
+ {
+ "name": "Bend-inhand-left",
+ "directions": 4
+ },
+ {
+ "name": "Bend-inhand-right",
+ "directions": 4
+ },
+ {
+ "name": "TJunction-inhand-left",
+ "directions": 4
+ },
+ {
+ "name": "TJunction-inhand-right",
+ "directions": 4
+ },
+ {
+ "name": "Fourway-inhand-left",
+ "directions": 4
+ },
+ {
+ "name": "Fourway-inhand-right",
+ "directions": 4
+ },
+ {
+ "name": "pipeBroken",
+ "directions": 1
+ },
+ {
+ "name": "pipeTJunction",
+ "directions": 4
+ },
+ {
+ "name": "pipeHalf",
+ "directions": 4
+ },
+ {
+ "name": "pipeBend",
+ "directions": 4
+ },
+ {
+ "name": "pipeFourway",
+ "directions": 4
+ },
+ {
+ "name": "pipeStraight",
+ "directions": 4
+ },
+ {
+ "name": "pipeConnector",
+ "directions": 4
+ },
+ {
+ "name": "pipeUnaryConnectors",
+ "directions": 4
+ },
+ {
+ "name": "pipeBinaryConnectors",
+ "directions": 4
+ },
+ {
+ "name": "pipeTrinaryConnectors",
+ "directions": 4
+ },
+ {
+ "name": "storageStraight"
+ },
+ {
+ "name": "storageHalf"
+ },
+ {
+ "name": "storageBend"
+ },
+ {
+ "name": "storageTJunction"
+ },
+ {
+ "name": "storageFourway"
+ }
+ ]
}
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/pipe.rsi/pipeBinaryConnectors.png b/Resources/Textures/Structures/Piping/Atmospherics/pipe.rsi/pipeBinaryConnectors.png
new file mode 100644
index 0000000000..a2fb4b7ff8
Binary files /dev/null and b/Resources/Textures/Structures/Piping/Atmospherics/pipe.rsi/pipeBinaryConnectors.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/pipe.rsi/pipeUnaryConnectors.png b/Resources/Textures/Structures/Piping/Atmospherics/pipe.rsi/pipeUnaryConnectors.png
new file mode 100644
index 0000000000..a4e2286277
Binary files /dev/null and b/Resources/Textures/Structures/Piping/Atmospherics/pipe.rsi/pipeUnaryConnectors.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/pipe.rsi/storageBend.png b/Resources/Textures/Structures/Piping/Atmospherics/pipe.rsi/storageBend.png
index 39ffe213ef..003a49eaec 100644
Binary files a/Resources/Textures/Structures/Piping/Atmospherics/pipe.rsi/storageBend.png and b/Resources/Textures/Structures/Piping/Atmospherics/pipe.rsi/storageBend.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/pipe.rsi/storageFourway.png b/Resources/Textures/Structures/Piping/Atmospherics/pipe.rsi/storageFourway.png
new file mode 100644
index 0000000000..911c0da5f6
Binary files /dev/null and b/Resources/Textures/Structures/Piping/Atmospherics/pipe.rsi/storageFourway.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/pipe.rsi/storageHalf.png b/Resources/Textures/Structures/Piping/Atmospherics/pipe.rsi/storageHalf.png
new file mode 100644
index 0000000000..5eba5e5e30
Binary files /dev/null and b/Resources/Textures/Structures/Piping/Atmospherics/pipe.rsi/storageHalf.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/pipe.rsi/storageStraight.png b/Resources/Textures/Structures/Piping/Atmospherics/pipe.rsi/storageStraight.png
index 715aeb5824..2805fe6626 100644
Binary files a/Resources/Textures/Structures/Piping/Atmospherics/pipe.rsi/storageStraight.png and b/Resources/Textures/Structures/Piping/Atmospherics/pipe.rsi/storageStraight.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/pipe.rsi/storageTJunction.png b/Resources/Textures/Structures/Piping/Atmospherics/pipe.rsi/storageTJunction.png
index af8376a152..92b5d5a006 100644
Binary files a/Resources/Textures/Structures/Piping/Atmospherics/pipe.rsi/storageTJunction.png and b/Resources/Textures/Structures/Piping/Atmospherics/pipe.rsi/storageTJunction.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/pipe_alt1.rsi/meta.json b/Resources/Textures/Structures/Piping/Atmospherics/pipe_alt1.rsi/meta.json
new file mode 100644
index 0000000000..31825d6fe5
--- /dev/null
+++ b/Resources/Textures/Structures/Piping/Atmospherics/pipe_alt1.rsi/meta.json
@@ -0,0 +1,51 @@
+{
+ "version": 1,
+ "size": {
+ "x": 32,
+ "y": 32
+ },
+ "license": "CC-BY-SA-3.0",
+ "copyright": "Inhand sprites by alzore_(discord) for SS14. pipeTrinaryConnectors made by Menshin for SS14 based on pipeTJunction, the rest is taken from https://github.com/tgstation/tgstation at commit 57cd1d59ca019dd0e7811ac451f295f818e573da, edited by chromiumboy.",
+ "states": [
+ {
+ "name": "pipeBroken",
+ "directions": 1
+ },
+ {
+ "name": "pipeTJunction",
+ "directions": 4
+ },
+ {
+ "name": "pipeHalf",
+ "directions": 4
+ },
+ {
+ "name": "pipeBend",
+ "directions": 4
+ },
+ {
+ "name": "pipeFourway",
+ "directions": 4
+ },
+ {
+ "name": "pipeStraight",
+ "directions": 4
+ },
+ {
+ "name": "pipeConnector",
+ "directions": 4
+ },
+ {
+ "name": "pipeUnaryConnectors",
+ "directions": 4
+ },
+ {
+ "name": "pipeBinaryConnectors",
+ "directions": 4
+ },
+ {
+ "name": "pipeTrinaryConnectors",
+ "directions": 4
+ }
+ ]
+}
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/pipe_alt1.rsi/pipeBend.png b/Resources/Textures/Structures/Piping/Atmospherics/pipe_alt1.rsi/pipeBend.png
new file mode 100644
index 0000000000..42fddaa1fd
Binary files /dev/null and b/Resources/Textures/Structures/Piping/Atmospherics/pipe_alt1.rsi/pipeBend.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/pipe_alt1.rsi/pipeBinaryConnectors.png b/Resources/Textures/Structures/Piping/Atmospherics/pipe_alt1.rsi/pipeBinaryConnectors.png
new file mode 100644
index 0000000000..e2eccac093
Binary files /dev/null and b/Resources/Textures/Structures/Piping/Atmospherics/pipe_alt1.rsi/pipeBinaryConnectors.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/pipe_alt1.rsi/pipeBroken.png b/Resources/Textures/Structures/Piping/Atmospherics/pipe_alt1.rsi/pipeBroken.png
new file mode 100644
index 0000000000..8a54fed66d
Binary files /dev/null and b/Resources/Textures/Structures/Piping/Atmospherics/pipe_alt1.rsi/pipeBroken.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/pipe_alt1.rsi/pipeConnector.png b/Resources/Textures/Structures/Piping/Atmospherics/pipe_alt1.rsi/pipeConnector.png
new file mode 100644
index 0000000000..a464bcf59a
Binary files /dev/null and b/Resources/Textures/Structures/Piping/Atmospherics/pipe_alt1.rsi/pipeConnector.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/pipe_alt1.rsi/pipeFourway.png b/Resources/Textures/Structures/Piping/Atmospherics/pipe_alt1.rsi/pipeFourway.png
new file mode 100644
index 0000000000..e9508bbcf4
Binary files /dev/null and b/Resources/Textures/Structures/Piping/Atmospherics/pipe_alt1.rsi/pipeFourway.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/pipe_alt1.rsi/pipeHalf.png b/Resources/Textures/Structures/Piping/Atmospherics/pipe_alt1.rsi/pipeHalf.png
new file mode 100644
index 0000000000..c02216202e
Binary files /dev/null and b/Resources/Textures/Structures/Piping/Atmospherics/pipe_alt1.rsi/pipeHalf.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/pipe_alt1.rsi/pipeStraight.png b/Resources/Textures/Structures/Piping/Atmospherics/pipe_alt1.rsi/pipeStraight.png
new file mode 100644
index 0000000000..d0b0105dc5
Binary files /dev/null and b/Resources/Textures/Structures/Piping/Atmospherics/pipe_alt1.rsi/pipeStraight.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/pipe_alt1.rsi/pipeTJunction.png b/Resources/Textures/Structures/Piping/Atmospherics/pipe_alt1.rsi/pipeTJunction.png
new file mode 100644
index 0000000000..06b945f1c5
Binary files /dev/null and b/Resources/Textures/Structures/Piping/Atmospherics/pipe_alt1.rsi/pipeTJunction.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/pipe_alt1.rsi/pipeTrinaryConnectors.png b/Resources/Textures/Structures/Piping/Atmospherics/pipe_alt1.rsi/pipeTrinaryConnectors.png
new file mode 100644
index 0000000000..f2dd866fbb
Binary files /dev/null and b/Resources/Textures/Structures/Piping/Atmospherics/pipe_alt1.rsi/pipeTrinaryConnectors.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/pipe_alt1.rsi/pipeUnaryConnectors.png b/Resources/Textures/Structures/Piping/Atmospherics/pipe_alt1.rsi/pipeUnaryConnectors.png
new file mode 100644
index 0000000000..a1a79e3096
Binary files /dev/null and b/Resources/Textures/Structures/Piping/Atmospherics/pipe_alt1.rsi/pipeUnaryConnectors.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/pipe_alt2.rsi/meta.json b/Resources/Textures/Structures/Piping/Atmospherics/pipe_alt2.rsi/meta.json
new file mode 100644
index 0000000000..31825d6fe5
--- /dev/null
+++ b/Resources/Textures/Structures/Piping/Atmospherics/pipe_alt2.rsi/meta.json
@@ -0,0 +1,51 @@
+{
+ "version": 1,
+ "size": {
+ "x": 32,
+ "y": 32
+ },
+ "license": "CC-BY-SA-3.0",
+ "copyright": "Inhand sprites by alzore_(discord) for SS14. pipeTrinaryConnectors made by Menshin for SS14 based on pipeTJunction, the rest is taken from https://github.com/tgstation/tgstation at commit 57cd1d59ca019dd0e7811ac451f295f818e573da, edited by chromiumboy.",
+ "states": [
+ {
+ "name": "pipeBroken",
+ "directions": 1
+ },
+ {
+ "name": "pipeTJunction",
+ "directions": 4
+ },
+ {
+ "name": "pipeHalf",
+ "directions": 4
+ },
+ {
+ "name": "pipeBend",
+ "directions": 4
+ },
+ {
+ "name": "pipeFourway",
+ "directions": 4
+ },
+ {
+ "name": "pipeStraight",
+ "directions": 4
+ },
+ {
+ "name": "pipeConnector",
+ "directions": 4
+ },
+ {
+ "name": "pipeUnaryConnectors",
+ "directions": 4
+ },
+ {
+ "name": "pipeBinaryConnectors",
+ "directions": 4
+ },
+ {
+ "name": "pipeTrinaryConnectors",
+ "directions": 4
+ }
+ ]
+}
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/pipe_alt2.rsi/pipeBend.png b/Resources/Textures/Structures/Piping/Atmospherics/pipe_alt2.rsi/pipeBend.png
new file mode 100644
index 0000000000..fc371f495c
Binary files /dev/null and b/Resources/Textures/Structures/Piping/Atmospherics/pipe_alt2.rsi/pipeBend.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/pipe_alt2.rsi/pipeBinaryConnectors.png b/Resources/Textures/Structures/Piping/Atmospherics/pipe_alt2.rsi/pipeBinaryConnectors.png
new file mode 100644
index 0000000000..3573b28923
Binary files /dev/null and b/Resources/Textures/Structures/Piping/Atmospherics/pipe_alt2.rsi/pipeBinaryConnectors.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/pipe_alt2.rsi/pipeBroken.png b/Resources/Textures/Structures/Piping/Atmospherics/pipe_alt2.rsi/pipeBroken.png
new file mode 100644
index 0000000000..8a54fed66d
Binary files /dev/null and b/Resources/Textures/Structures/Piping/Atmospherics/pipe_alt2.rsi/pipeBroken.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/pipe_alt2.rsi/pipeConnector.png b/Resources/Textures/Structures/Piping/Atmospherics/pipe_alt2.rsi/pipeConnector.png
new file mode 100644
index 0000000000..5310c113da
Binary files /dev/null and b/Resources/Textures/Structures/Piping/Atmospherics/pipe_alt2.rsi/pipeConnector.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/pipe_alt2.rsi/pipeFourway.png b/Resources/Textures/Structures/Piping/Atmospherics/pipe_alt2.rsi/pipeFourway.png
new file mode 100644
index 0000000000..f879717da3
Binary files /dev/null and b/Resources/Textures/Structures/Piping/Atmospherics/pipe_alt2.rsi/pipeFourway.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/pipe_alt2.rsi/pipeHalf.png b/Resources/Textures/Structures/Piping/Atmospherics/pipe_alt2.rsi/pipeHalf.png
new file mode 100644
index 0000000000..227a31c2b0
Binary files /dev/null and b/Resources/Textures/Structures/Piping/Atmospherics/pipe_alt2.rsi/pipeHalf.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/pipe_alt2.rsi/pipeStraight.png b/Resources/Textures/Structures/Piping/Atmospherics/pipe_alt2.rsi/pipeStraight.png
new file mode 100644
index 0000000000..5fb9c344f3
Binary files /dev/null and b/Resources/Textures/Structures/Piping/Atmospherics/pipe_alt2.rsi/pipeStraight.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/pipe_alt2.rsi/pipeTJunction.png b/Resources/Textures/Structures/Piping/Atmospherics/pipe_alt2.rsi/pipeTJunction.png
new file mode 100644
index 0000000000..6ff306dc02
Binary files /dev/null and b/Resources/Textures/Structures/Piping/Atmospherics/pipe_alt2.rsi/pipeTJunction.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/pipe_alt2.rsi/pipeTrinaryConnectors.png b/Resources/Textures/Structures/Piping/Atmospherics/pipe_alt2.rsi/pipeTrinaryConnectors.png
new file mode 100644
index 0000000000..4049d71d46
Binary files /dev/null and b/Resources/Textures/Structures/Piping/Atmospherics/pipe_alt2.rsi/pipeTrinaryConnectors.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/pipe_alt2.rsi/pipeUnaryConnectors.png b/Resources/Textures/Structures/Piping/Atmospherics/pipe_alt2.rsi/pipeUnaryConnectors.png
new file mode 100644
index 0000000000..8eb130bbed
Binary files /dev/null and b/Resources/Textures/Structures/Piping/Atmospherics/pipe_alt2.rsi/pipeUnaryConnectors.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/pump_alt1.rsi/meta.json b/Resources/Textures/Structures/Piping/Atmospherics/pump_alt1.rsi/meta.json
new file mode 100644
index 0000000000..ef75896795
--- /dev/null
+++ b/Resources/Textures/Structures/Piping/Atmospherics/pump_alt1.rsi/meta.json
@@ -0,0 +1,157 @@
+{
+ "version": 1,
+ "size": {
+ "x": 32,
+ "y": 32
+ },
+ "license": "CC-BY-SA-3.0",
+ "copyright": "Taken from https://github.com/tgstation/tgstation at commit 57cd1d59ca019dd0e7811ac451f295f818e573da. Signal valve is a digital valve modified by deltanedas. Manual valve modified by Deerstop at https://github.com/space-wizards/space-station-14/pull/34378. Modified by chromiumboy.",
+ "states": [
+ {
+ "name": "pumpDigitalValve",
+ "directions": 4
+ },
+ {
+ "name": "pumpManualValve",
+ "directions": 4
+ },
+ {
+ "name": "pumpManualValveOn",
+ "directions": 4
+ },
+ {
+ "name": "pumpSignalValve",
+ "directions": 4
+ },
+ {
+ "name": "pumpSignalValveOn",
+ "directions": 4
+ },
+ {
+ "name": "pumpPassiveGate",
+ "directions": 4
+ },
+ {
+ "name": "pumpPassiveGateOn",
+ "directions": 4
+ },
+ {
+ "name": "pumpPressure",
+ "directions": 4
+ },
+ {
+ "name": "pumpPressureOn",
+ "directions": 4,
+ "delays": [
+ [
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1
+ ],
+ [
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1
+ ],
+ [
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1
+ ],
+ [
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1
+ ]
+ ]
+ },
+ {
+ "name": "pumpVolume",
+ "directions": 4
+ },
+ {
+ "name": "pumpVolumeOn",
+ "directions": 4,
+ "delays": [
+ [
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1
+ ],
+ [
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1
+ ],
+ [
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1
+ ],
+ [
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1
+ ]
+ ]
+ },
+ {
+ "name": "pumpVolumeBlocked",
+ "directions": 4,
+ "delays": [
+ [
+ 1.0,
+ 1.0
+ ],
+ [
+ 1.0,
+ 1.0
+ ],
+ [
+ 1.0,
+ 1.0
+ ],
+ [
+ 1.0,
+ 1.0
+ ]
+ ]
+ }
+ ]
+}
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/pump_alt1.rsi/pumpDigitalValve.png b/Resources/Textures/Structures/Piping/Atmospherics/pump_alt1.rsi/pumpDigitalValve.png
new file mode 100644
index 0000000000..ec8e261f2b
Binary files /dev/null and b/Resources/Textures/Structures/Piping/Atmospherics/pump_alt1.rsi/pumpDigitalValve.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/pump_alt1.rsi/pumpManualValve.png b/Resources/Textures/Structures/Piping/Atmospherics/pump_alt1.rsi/pumpManualValve.png
new file mode 100644
index 0000000000..2bae097010
Binary files /dev/null and b/Resources/Textures/Structures/Piping/Atmospherics/pump_alt1.rsi/pumpManualValve.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/pump_alt1.rsi/pumpManualValveOn.png b/Resources/Textures/Structures/Piping/Atmospherics/pump_alt1.rsi/pumpManualValveOn.png
new file mode 100644
index 0000000000..f889124d18
Binary files /dev/null and b/Resources/Textures/Structures/Piping/Atmospherics/pump_alt1.rsi/pumpManualValveOn.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/pump_alt1.rsi/pumpPassiveGate.png b/Resources/Textures/Structures/Piping/Atmospherics/pump_alt1.rsi/pumpPassiveGate.png
new file mode 100644
index 0000000000..0d205491ec
Binary files /dev/null and b/Resources/Textures/Structures/Piping/Atmospherics/pump_alt1.rsi/pumpPassiveGate.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/pump_alt1.rsi/pumpPassiveGateOn.png b/Resources/Textures/Structures/Piping/Atmospherics/pump_alt1.rsi/pumpPassiveGateOn.png
new file mode 100644
index 0000000000..e899d0ed0c
Binary files /dev/null and b/Resources/Textures/Structures/Piping/Atmospherics/pump_alt1.rsi/pumpPassiveGateOn.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/pump_alt1.rsi/pumpPressure.png b/Resources/Textures/Structures/Piping/Atmospherics/pump_alt1.rsi/pumpPressure.png
new file mode 100644
index 0000000000..3a634fc929
Binary files /dev/null and b/Resources/Textures/Structures/Piping/Atmospherics/pump_alt1.rsi/pumpPressure.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/pump_alt1.rsi/pumpPressureOn.png b/Resources/Textures/Structures/Piping/Atmospherics/pump_alt1.rsi/pumpPressureOn.png
new file mode 100644
index 0000000000..117ff9c8fb
Binary files /dev/null and b/Resources/Textures/Structures/Piping/Atmospherics/pump_alt1.rsi/pumpPressureOn.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/pump_alt1.rsi/pumpSignalValve.png b/Resources/Textures/Structures/Piping/Atmospherics/pump_alt1.rsi/pumpSignalValve.png
new file mode 100644
index 0000000000..53656aafaf
Binary files /dev/null and b/Resources/Textures/Structures/Piping/Atmospherics/pump_alt1.rsi/pumpSignalValve.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/pump_alt1.rsi/pumpSignalValveOn.png b/Resources/Textures/Structures/Piping/Atmospherics/pump_alt1.rsi/pumpSignalValveOn.png
new file mode 100644
index 0000000000..a2549e268c
Binary files /dev/null and b/Resources/Textures/Structures/Piping/Atmospherics/pump_alt1.rsi/pumpSignalValveOn.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/pump_alt1.rsi/pumpVolume.png b/Resources/Textures/Structures/Piping/Atmospherics/pump_alt1.rsi/pumpVolume.png
new file mode 100644
index 0000000000..55708b37dd
Binary files /dev/null and b/Resources/Textures/Structures/Piping/Atmospherics/pump_alt1.rsi/pumpVolume.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/pump_alt1.rsi/pumpVolumeBlocked.png b/Resources/Textures/Structures/Piping/Atmospherics/pump_alt1.rsi/pumpVolumeBlocked.png
new file mode 100644
index 0000000000..bf41bf2adb
Binary files /dev/null and b/Resources/Textures/Structures/Piping/Atmospherics/pump_alt1.rsi/pumpVolumeBlocked.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/pump_alt1.rsi/pumpVolumeOn.png b/Resources/Textures/Structures/Piping/Atmospherics/pump_alt1.rsi/pumpVolumeOn.png
new file mode 100644
index 0000000000..6a5efbff37
Binary files /dev/null and b/Resources/Textures/Structures/Piping/Atmospherics/pump_alt1.rsi/pumpVolumeOn.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/pump_alt2.rsi/meta.json b/Resources/Textures/Structures/Piping/Atmospherics/pump_alt2.rsi/meta.json
new file mode 100644
index 0000000000..ef75896795
--- /dev/null
+++ b/Resources/Textures/Structures/Piping/Atmospherics/pump_alt2.rsi/meta.json
@@ -0,0 +1,157 @@
+{
+ "version": 1,
+ "size": {
+ "x": 32,
+ "y": 32
+ },
+ "license": "CC-BY-SA-3.0",
+ "copyright": "Taken from https://github.com/tgstation/tgstation at commit 57cd1d59ca019dd0e7811ac451f295f818e573da. Signal valve is a digital valve modified by deltanedas. Manual valve modified by Deerstop at https://github.com/space-wizards/space-station-14/pull/34378. Modified by chromiumboy.",
+ "states": [
+ {
+ "name": "pumpDigitalValve",
+ "directions": 4
+ },
+ {
+ "name": "pumpManualValve",
+ "directions": 4
+ },
+ {
+ "name": "pumpManualValveOn",
+ "directions": 4
+ },
+ {
+ "name": "pumpSignalValve",
+ "directions": 4
+ },
+ {
+ "name": "pumpSignalValveOn",
+ "directions": 4
+ },
+ {
+ "name": "pumpPassiveGate",
+ "directions": 4
+ },
+ {
+ "name": "pumpPassiveGateOn",
+ "directions": 4
+ },
+ {
+ "name": "pumpPressure",
+ "directions": 4
+ },
+ {
+ "name": "pumpPressureOn",
+ "directions": 4,
+ "delays": [
+ [
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1
+ ],
+ [
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1
+ ],
+ [
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1
+ ],
+ [
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1
+ ]
+ ]
+ },
+ {
+ "name": "pumpVolume",
+ "directions": 4
+ },
+ {
+ "name": "pumpVolumeOn",
+ "directions": 4,
+ "delays": [
+ [
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1
+ ],
+ [
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1
+ ],
+ [
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1
+ ],
+ [
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1
+ ]
+ ]
+ },
+ {
+ "name": "pumpVolumeBlocked",
+ "directions": 4,
+ "delays": [
+ [
+ 1.0,
+ 1.0
+ ],
+ [
+ 1.0,
+ 1.0
+ ],
+ [
+ 1.0,
+ 1.0
+ ],
+ [
+ 1.0,
+ 1.0
+ ]
+ ]
+ }
+ ]
+}
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/pump_alt2.rsi/pumpDigitalValve.png b/Resources/Textures/Structures/Piping/Atmospherics/pump_alt2.rsi/pumpDigitalValve.png
new file mode 100644
index 0000000000..4b43b4304e
Binary files /dev/null and b/Resources/Textures/Structures/Piping/Atmospherics/pump_alt2.rsi/pumpDigitalValve.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/pump_alt2.rsi/pumpManualValve.png b/Resources/Textures/Structures/Piping/Atmospherics/pump_alt2.rsi/pumpManualValve.png
new file mode 100644
index 0000000000..c83d71fb70
Binary files /dev/null and b/Resources/Textures/Structures/Piping/Atmospherics/pump_alt2.rsi/pumpManualValve.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/pump_alt2.rsi/pumpManualValveOn.png b/Resources/Textures/Structures/Piping/Atmospherics/pump_alt2.rsi/pumpManualValveOn.png
new file mode 100644
index 0000000000..2adedbc95f
Binary files /dev/null and b/Resources/Textures/Structures/Piping/Atmospherics/pump_alt2.rsi/pumpManualValveOn.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/pump_alt2.rsi/pumpPassiveGate.png b/Resources/Textures/Structures/Piping/Atmospherics/pump_alt2.rsi/pumpPassiveGate.png
new file mode 100644
index 0000000000..668c626712
Binary files /dev/null and b/Resources/Textures/Structures/Piping/Atmospherics/pump_alt2.rsi/pumpPassiveGate.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/pump_alt2.rsi/pumpPassiveGateOn.png b/Resources/Textures/Structures/Piping/Atmospherics/pump_alt2.rsi/pumpPassiveGateOn.png
new file mode 100644
index 0000000000..38ff9270e7
Binary files /dev/null and b/Resources/Textures/Structures/Piping/Atmospherics/pump_alt2.rsi/pumpPassiveGateOn.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/pump_alt2.rsi/pumpPressure.png b/Resources/Textures/Structures/Piping/Atmospherics/pump_alt2.rsi/pumpPressure.png
new file mode 100644
index 0000000000..cb5286e46c
Binary files /dev/null and b/Resources/Textures/Structures/Piping/Atmospherics/pump_alt2.rsi/pumpPressure.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/pump_alt2.rsi/pumpPressureOn.png b/Resources/Textures/Structures/Piping/Atmospherics/pump_alt2.rsi/pumpPressureOn.png
new file mode 100644
index 0000000000..114ed9a627
Binary files /dev/null and b/Resources/Textures/Structures/Piping/Atmospherics/pump_alt2.rsi/pumpPressureOn.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/pump_alt2.rsi/pumpSignalValve.png b/Resources/Textures/Structures/Piping/Atmospherics/pump_alt2.rsi/pumpSignalValve.png
new file mode 100644
index 0000000000..ba0a3ed350
Binary files /dev/null and b/Resources/Textures/Structures/Piping/Atmospherics/pump_alt2.rsi/pumpSignalValve.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/pump_alt2.rsi/pumpSignalValveOn.png b/Resources/Textures/Structures/Piping/Atmospherics/pump_alt2.rsi/pumpSignalValveOn.png
new file mode 100644
index 0000000000..181c6f2ace
Binary files /dev/null and b/Resources/Textures/Structures/Piping/Atmospherics/pump_alt2.rsi/pumpSignalValveOn.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/pump_alt2.rsi/pumpVolume.png b/Resources/Textures/Structures/Piping/Atmospherics/pump_alt2.rsi/pumpVolume.png
new file mode 100644
index 0000000000..0e9f52f6e6
Binary files /dev/null and b/Resources/Textures/Structures/Piping/Atmospherics/pump_alt2.rsi/pumpVolume.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/pump_alt2.rsi/pumpVolumeBlocked.png b/Resources/Textures/Structures/Piping/Atmospherics/pump_alt2.rsi/pumpVolumeBlocked.png
new file mode 100644
index 0000000000..0d267ff178
Binary files /dev/null and b/Resources/Textures/Structures/Piping/Atmospherics/pump_alt2.rsi/pumpVolumeBlocked.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/pump_alt2.rsi/pumpVolumeOn.png b/Resources/Textures/Structures/Piping/Atmospherics/pump_alt2.rsi/pumpVolumeOn.png
new file mode 100644
index 0000000000..85e33e7b7b
Binary files /dev/null and b/Resources/Textures/Structures/Piping/Atmospherics/pump_alt2.rsi/pumpVolumeOn.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/thermomachine.rsi/meta.json b/Resources/Textures/Structures/Piping/Atmospherics/thermomachine.rsi/meta.json
index 4cbb72e1ac..3ba53e431c 100644
--- a/Resources/Textures/Structures/Piping/Atmospherics/thermomachine.rsi/meta.json
+++ b/Resources/Textures/Structures/Piping/Atmospherics/thermomachine.rsi/meta.json
@@ -1,38 +1,67 @@
{
- "version":1,
- "size":{"x":32,"y":32},
- "copyright":"Base sprites taken from tgstation, splitted to display on two layers (machinebody/panel) by Menshin, for SS14",
- "license":"CC-BY-SA-3.0",
- "states":[
+ "version": 1,
+ "size": {
+ "x": 32,
+ "y": 32
+ },
+ "copyright": "Base sprites taken from tgstation, splitted to display on two layers (machinebody/panel) by Menshin, for SS14, edited by chromiumboy",
+ "license": "CC-BY-SA-3.0",
+ "states": [
{
- "name":"freezerOff",
- "directions":1
+ "name": "freezerOff",
+ "directions": 1
},
{
- "name":"freezerPanelOpen",
- "directions":1
+ "name": "freezerPanelOpen",
+ "directions": 1
},
{
- "name":"freezerOn",
- "directions":1,
- "delays":[ [ 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1] ]
+ "name": "freezerOn",
+ "directions": 1,
+ "delays": [
+ [
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1
+ ]
+ ]
},
{
- "name":"heaterOff",
- "directions":1
+ "name": "heaterOff",
+ "directions": 1
},
{
- "name":"heaterPanelOpen",
- "directions":1
+ "name": "heaterPanelOpen",
+ "directions": 1
},
{
- "name":"heaterOn",
- "directions":1,
- "delays":[ [ 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1] ]
+ "name": "heaterOn",
+ "directions": 1,
+ "delays": [
+ [
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1
+ ]
+ ]
},
{
- "name":"pipe",
- "directions":4
+ "name": "pipe",
+ "directions": 4
}
]
-}
\ No newline at end of file
+}
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/thermomachine.rsi/pipe.png b/Resources/Textures/Structures/Piping/Atmospherics/thermomachine.rsi/pipe.png
index 620ba905be..e0209a7bc8 100644
Binary files a/Resources/Textures/Structures/Piping/Atmospherics/thermomachine.rsi/pipe.png and b/Resources/Textures/Structures/Piping/Atmospherics/thermomachine.rsi/pipe.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/thermomachine_alt1.rsi/meta.json b/Resources/Textures/Structures/Piping/Atmospherics/thermomachine_alt1.rsi/meta.json
new file mode 100644
index 0000000000..f8a645528c
--- /dev/null
+++ b/Resources/Textures/Structures/Piping/Atmospherics/thermomachine_alt1.rsi/meta.json
@@ -0,0 +1,15 @@
+{
+ "version": 1,
+ "size": {
+ "x": 32,
+ "y": 32
+ },
+ "copyright": "Base sprites taken from tgstation, splitted to display on two layers (machinebody/panel) by Menshin, for SS14, edited by chromiumboy",
+ "license": "CC-BY-SA-3.0",
+ "states": [
+ {
+ "name": "pipe",
+ "directions": 4
+ }
+ ]
+}
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/thermomachine_alt1.rsi/pipe.png b/Resources/Textures/Structures/Piping/Atmospherics/thermomachine_alt1.rsi/pipe.png
new file mode 100644
index 0000000000..cb6fc36c97
Binary files /dev/null and b/Resources/Textures/Structures/Piping/Atmospherics/thermomachine_alt1.rsi/pipe.png differ
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/thermomachine_alt2.rsi/meta.json b/Resources/Textures/Structures/Piping/Atmospherics/thermomachine_alt2.rsi/meta.json
new file mode 100644
index 0000000000..f8a645528c
--- /dev/null
+++ b/Resources/Textures/Structures/Piping/Atmospherics/thermomachine_alt2.rsi/meta.json
@@ -0,0 +1,15 @@
+{
+ "version": 1,
+ "size": {
+ "x": 32,
+ "y": 32
+ },
+ "copyright": "Base sprites taken from tgstation, splitted to display on two layers (machinebody/panel) by Menshin, for SS14, edited by chromiumboy",
+ "license": "CC-BY-SA-3.0",
+ "states": [
+ {
+ "name": "pipe",
+ "directions": 4
+ }
+ ]
+}
diff --git a/Resources/Textures/Structures/Piping/Atmospherics/thermomachine_alt2.rsi/pipe.png b/Resources/Textures/Structures/Piping/Atmospherics/thermomachine_alt2.rsi/pipe.png
new file mode 100644
index 0000000000..4a52081bc8
Binary files /dev/null and b/Resources/Textures/Structures/Piping/Atmospherics/thermomachine_alt2.rsi/pipe.png differ