Layering for atmospheric pipes (#36124)
Co-authored-by: ArtisticRoomba <145879011+ArtisticRoomba@users.noreply.github.com> Co-authored-by: Kevin Zheng <kevinz5000@gmail.com>
203
Content.Client/Atmos/AlignAtmosPipeLayers.cs
Normal file
@@ -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;
|
||||
|
||||
/// <summary>
|
||||
/// Allows users to place atmos pipes on different layers depending on how the mouse cursor is positioned within a grid tile.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This placement mode is not on the engine because it is content specific.
|
||||
/// </remarks>
|
||||
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<SharedMapSystem>();
|
||||
_transformSystem = _entityManager.System<SharedTransformSystem>();
|
||||
_pipeLayersSystem = _entityManager.System<SharedAtmosPipeLayersSystem>();
|
||||
_spriteSystem = _entityManager.System<SpriteSystem>();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Render(in OverlayDrawArgs args)
|
||||
{
|
||||
var gridUid = _entityManager.System<SharedTransformSystem>().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);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
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<MapGridComponent>(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<EntityPrototype>(pManager.CurrentPermission.EntityType, out var currentProto))
|
||||
return;
|
||||
|
||||
if (!currentProto.TryGetComponent<AtmosPipeLayersComponent>(out var atmosPipeLayers, _entityManager.ComponentFactory))
|
||||
return;
|
||||
|
||||
if (!_pipeLayersSystem.TryGetAlternativePrototype(atmosPipeLayers, layer, out var newProtoId))
|
||||
return;
|
||||
|
||||
if (_protoManager.TryIndex<EntityPrototype>(newProtoId, out var newProto))
|
||||
{
|
||||
// Update the placed prototype
|
||||
pManager.CurrentPermission.EntityType = newProtoId;
|
||||
|
||||
// Update the appearance of the ghost sprite
|
||||
if (newProto.TryGetComponent<SpriteComponent>(out var sprite, _entityManager.ComponentFactory))
|
||||
{
|
||||
var textures = new List<IDirectionalTextureProvider>();
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -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))
|
||||
@@ -158,7 +162,7 @@ public sealed partial class AtmosMonitoringConsoleNavMapControl : NavMapControl
|
||||
{
|
||||
var list = new List<AtmosMonitoringConsoleLine>();
|
||||
|
||||
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;
|
||||
|
||||
@@ -15,7 +15,7 @@ public sealed class AtmosMonitoringConsoleSystem : SharedAtmosMonitoringConsoleS
|
||||
|
||||
private void OnHandleState(EntityUid uid, AtmosMonitoringConsoleComponent component, ref ComponentHandleState args)
|
||||
{
|
||||
Dictionary<Vector2i, Dictionary<(int, string), ulong>> modifiedChunks;
|
||||
Dictionary<Vector2i, Dictionary<AtmosMonitoringConsoleSubnet, ulong>> modifiedChunks;
|
||||
Dictionary<NetEntity, AtmosDeviceNavMapData> 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<AtmosMonitoringConsoleSubnet, ulong>(chunk);
|
||||
|
||||
component.AtmosPipeChunks[origin] = newChunk;
|
||||
}
|
||||
|
||||
@@ -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<NavMapBlipPrototype> _navMapConsoleProtoId = "NavMapConsole";
|
||||
private ProtoId<NavMapBlipPrototype> _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);
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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<PipeConnectionLayer>())
|
||||
{
|
||||
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<SpriteComponent> entity)
|
||||
private void HideAllPipeConnection(Entity<SpriteComponent> entity, AtmosPipeLayersComponent? atmosPipeLayers, int numberOfPipeLayers)
|
||||
{
|
||||
var sprite = entity.Comp;
|
||||
|
||||
foreach (var layerKey in Enum.GetValues<PipeConnectionLayer>())
|
||||
{
|
||||
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<PipeDirection>(uid, PipeVisuals.VisualState, out var worldConnectedDirections, args.Component))
|
||||
var numberOfPipeLayers = GetNumberOfPipeLayers(uid, out var atmosPipeLayers);
|
||||
|
||||
if (!_appearance.TryGetData<int>(uid, PipeVisuals.VisualState, out var worldConnectedDirections, args.Component))
|
||||
{
|
||||
HideAllPipeConnection((uid, args.Sprite));
|
||||
HideAllPipeConnection((uid, args.Sprite), atmosPipeLayers, numberOfPipeLayers);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_appearance.TryGetData<Color>(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<PipeConnectionLayer>())
|
||||
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<PipeConnectionLayer>())
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
56
Content.Client/Atmos/EntitySystems/AtmosPipeLayersSystem.cs
Normal file
@@ -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;
|
||||
|
||||
/// <summary>
|
||||
/// The system responsible for updating the appearance of layered gas pipe
|
||||
/// </summary>
|
||||
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<AtmosPipeLayersComponent, AppearanceChangeEvent>(OnAppearanceChange);
|
||||
}
|
||||
|
||||
private void OnAppearanceChange(Entity<AtmosPipeLayersComponent> ent, ref AppearanceChangeEvent ev)
|
||||
{
|
||||
if (!TryComp<SpriteComponent>(ent, out var sprite))
|
||||
return;
|
||||
|
||||
if (_appearance.TryGetData<string>(ent, AtmosPipeLayerVisuals.Sprite, out var spriteRsi) &&
|
||||
_resourceCache.TryGetResource(SpriteSpecifierSerializer.TextureRoot / spriteRsi, out RSIResource? resource))
|
||||
{
|
||||
_sprite.SetBaseRsi((ent, sprite), resource.RSI);
|
||||
}
|
||||
|
||||
if (_appearance.TryGetData<Dictionary<string, string>>(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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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<AtmosPipeColorComponent>(uid, out var atmosPipeColor) ? atmosPipeColor.Color : Color.White;
|
||||
var layer = TryComp<AtmosPipeLayersComponent>(uid, out var atmosPipeLayers) ? atmosPipeLayers.CurrentPipeLayer : AtmosPipeLayer.Primary;
|
||||
|
||||
if (!TryGettingFirstPipeNode(uid, out var _, out var netId))
|
||||
netId = -1;
|
||||
|
||||
var color = Color.White;
|
||||
|
||||
if (TryComp<AtmosPipeColorComponent>(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<NodeContainerComponent>(ent, out var entNodeContainer))
|
||||
continue;
|
||||
|
||||
UpdateAtmosPipeChunk(ent, entNodeContainer, entAtmosPipeColor, tileIdx, ref chunk);
|
||||
var showAbsentConnections = TryComp<AtmosMonitoringConsoleDeviceComponent>(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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
77
Content.Server/Atmos/EntitySystems/AtmosPipeLayersSystem.cs
Normal file
@@ -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;
|
||||
|
||||
/// <summary>
|
||||
/// The system responsible for checking and adjusting the connection layering of gas pipes
|
||||
/// </summary>
|
||||
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<AtmosPipeLayersComponent, ComponentInit>(OnInit);
|
||||
}
|
||||
|
||||
private void OnInit(Entity<AtmosPipeLayersComponent> ent, ref ComponentInit args)
|
||||
{
|
||||
SetPipeLayer(ent, ent.Comp.CurrentPipeLayer);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void SetPipeLayer(Entity<AtmosPipeLayersComponent> ent, AtmosPipeLayer layer, EntityUid? user = null, EntityUid? used = null)
|
||||
{
|
||||
if (ent.Comp.PipeLayersLocked)
|
||||
return;
|
||||
|
||||
base.SetPipeLayer(ent, layer);
|
||||
|
||||
if (!TryComp<NodeContainerComponent>(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<PipeRestrictOverlapComponent>(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);
|
||||
}
|
||||
}
|
||||
@@ -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<NodeContainerComponent, TransformComponent> ent, Entity<NodeContainerComponent, TransformComponent> 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<PipeDirection> GetAllDirections(Entity<NodeContainerComponent, TransformComponent> pipe)
|
||||
IEnumerable<(PipeDirection, AtmosPipeLayer)> GetAllDirectionsAndLayers(Entity<NodeContainerComponent, TransformComponent> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
namespace Content.Server.Atmos.Piping.Components;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed partial class GasPipeManifoldComponent : Component
|
||||
{
|
||||
[DataField("inlets")]
|
||||
public HashSet<string> InletNames { get; set; } = new() { "south0", "south1", "south2" };
|
||||
|
||||
[DataField("outlets")]
|
||||
public HashSet<string> OutletNames { get; set; } = new() { "north0", "north1", "north2" };
|
||||
}
|
||||
@@ -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<MapGridComponent>(xform.GridUid, out var grid))
|
||||
return;
|
||||
|
||||
var numberOfPipeLayers = GetNumberOfPipeLayers(uid, out var atmosPipeLayers);
|
||||
|
||||
// get connected entities
|
||||
var anyPipeNodes = false;
|
||||
HashSet<EntityUid> 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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<GasPipeManifoldComponent, ComponentInit>(OnCompInit);
|
||||
SubscribeLocalEvent<GasPipeManifoldComponent, GasAnalyzerScanEvent>(OnAnalyzed);
|
||||
}
|
||||
|
||||
private void OnCompInit(Entity<GasPipeManifoldComponent> ent, ref ComponentInit args)
|
||||
{
|
||||
if (!TryComp<NodeContainerComponent>(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<GasPipeManifoldComponent> ent, ref GasAnalyzerScanEvent args)
|
||||
{
|
||||
// All inlets and outlets have the same gas mixture
|
||||
|
||||
args.GasMixtures = new List<(string, GasMixture?)>();
|
||||
|
||||
if (!TryComp<NodeContainerComponent>(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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// Connects with other <see cref="PipeNode"/>s whose <see cref="PipeDirection"/>
|
||||
/// correctly correspond.
|
||||
/// and <see cref="CurrentPipeLayer"/> correctly correspond.
|
||||
/// </summary>
|
||||
[DataDefinition]
|
||||
[Virtual]
|
||||
@@ -24,6 +22,12 @@ namespace Content.Server.NodeContainer.Nodes
|
||||
[DataField("pipeDirection")]
|
||||
public PipeDirection OriginalPipeDirection;
|
||||
|
||||
/// <summary>
|
||||
/// The *current* layer to which the pipe node is assigned.
|
||||
/// </summary>
|
||||
[DataField("pipeLayer")]
|
||||
public AtmosPipeLayer CurrentPipeLayer = AtmosPipeLayer.Primary;
|
||||
|
||||
/// <summary>
|
||||
/// 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;
|
||||
|
||||
122
Content.Shared/Atmos/Components/AtmosPipeLayersComponent.cs
Normal file
@@ -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;
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
|
||||
[Access(typeof(SharedAtmosPipeLayersSystem))]
|
||||
public sealed partial class AtmosPipeLayersComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// The number of pipe layers this entity supports.
|
||||
/// Must be equal to or less than the number of values
|
||||
/// in <see cref="AtmosPipeLayer"/>.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public byte NumberOfPipeLayers = 3;
|
||||
|
||||
/// <summary>
|
||||
/// Determines which layer the pipe is currently assigned.
|
||||
/// Only pipes on the same layer can connect with each other.
|
||||
/// </summary>
|
||||
[DataField("pipeLayer"), AutoNetworkedField]
|
||||
[ViewVariables(VVAccess.ReadOnly)]
|
||||
public AtmosPipeLayer CurrentPipeLayer = AtmosPipeLayer.Primary;
|
||||
|
||||
/// <summary>
|
||||
/// 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
|
||||
/// <see cref="SpriteLayersRsiPaths"/> instead.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If the dictionary is not empty there should be an entry for each atmos pipe layer.
|
||||
/// </remarks>
|
||||
[DataField]
|
||||
public Dictionary<AtmosPipeLayer, string> SpriteRsiPaths = new();
|
||||
|
||||
/// <summary>
|
||||
/// 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
|
||||
/// <see cref="SpriteRsiPaths"/> instead.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If an dictionary is not empty there should be an entry for each pipe layer.
|
||||
/// </remarks>
|
||||
[DataField]
|
||||
public Dictionary<string, Dictionary<AtmosPipeLayer, string>> SpriteLayersRsiPaths = new();
|
||||
|
||||
/// <summary>
|
||||
/// Entity prototypes that will be used to replace the current one when using
|
||||
/// position dependent entity placement via AlignAtmosPipeLayers.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If the dictionary is not empty there should be an entry for each atmos pipe layer.
|
||||
/// </remarks>
|
||||
[DataField]
|
||||
public Dictionary<AtmosPipeLayer, EntProtoId> AlternativePrototypes = new();
|
||||
|
||||
/// <summary>
|
||||
/// The pipe layers of this entity cannot be changed when this value is true.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public bool PipeLayersLocked;
|
||||
|
||||
/// <summary>
|
||||
/// Tool quality required to cause a pipe to change layers
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public ProtoId<ToolQualityPrototype> Tool = "Screwing";
|
||||
|
||||
/// <summary>
|
||||
/// The base delay to use for changing layers.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public float Delay = 1f;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raised when a player attempts to cycle a pipe to its next layer
|
||||
/// </summary>
|
||||
[Serializable, NetSerializable]
|
||||
public sealed partial class TrySetNextPipeLayerCompletedEvent : SimpleDoAfterEvent;
|
||||
|
||||
/// <summary>
|
||||
/// Raised when a player attempts to set a pipe a specified layer
|
||||
/// </summary>
|
||||
[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,
|
||||
}
|
||||
@@ -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")];
|
||||
}
|
||||
|
||||
@@ -64,10 +64,10 @@ public struct AtmosPipeChunk(Vector2i origin)
|
||||
|
||||
/// <summary>
|
||||
/// 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
|
||||
/// </summary>
|
||||
[ViewVariables]
|
||||
public Dictionary<(int, string), ulong> AtmosPipeData = new();
|
||||
public Dictionary<AtmosMonitoringConsoleSubnet, ulong> AtmosPipeData = new();
|
||||
|
||||
/// <summary>
|
||||
/// The last game tick that the chunk was updated
|
||||
@@ -109,10 +109,21 @@ public struct AtmosDeviceNavMapData
|
||||
/// </summary>
|
||||
public Color PipeColor;
|
||||
|
||||
/// <summary>
|
||||
/// The pipe layer the entity is on
|
||||
/// </summary>
|
||||
public AtmosPipeLayer PipeLayer;
|
||||
|
||||
/// <summary>
|
||||
/// Populate the atmos monitoring console nav map with a single entity
|
||||
/// </summary>
|
||||
public AtmosDeviceNavMapData(NetEntity netEntity, NetCoordinates netCoordinates, int netId, ProtoId<NavMapBlipPrototype> navMapBlip, Direction direction, Color pipeColor)
|
||||
public AtmosDeviceNavMapData(NetEntity netEntity,
|
||||
NetCoordinates netCoordinates,
|
||||
int netId,
|
||||
ProtoId<NavMapBlipPrototype> 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -216,6 +228,16 @@ public struct AtmosMonitoringConsoleEntry
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
/// <param name="NetId">The associated network ID.</param>
|
||||
/// <param name="PipeLayer">The associated pipe layer.</param>
|
||||
/// <param name="HexCode">The color of the pipe.</param>
|
||||
[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.
|
||||
|
||||
@@ -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)
|
||||
/// </summary>
|
||||
[DataField, ViewVariables]
|
||||
[DataField]
|
||||
public ProtoId<NavMapBlipPrototype>? NavMapBlip = null;
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public bool ShowAbsentConnections = true;
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ public abstract class SharedAtmosMonitoringConsoleSystem : EntitySystem
|
||||
|
||||
private void OnGetState(EntityUid uid, AtmosMonitoringConsoleComponent component, ref ComponentGetState args)
|
||||
{
|
||||
Dictionary<Vector2i, Dictionary<(int, string), ulong>> chunks;
|
||||
Dictionary<Vector2i, Dictionary<AtmosMonitoringConsoleSubnet, ulong>> 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<Vector2i, Dictionary<(int, string), ulong>> chunks,
|
||||
Dictionary<Vector2i, Dictionary<AtmosMonitoringConsoleSubnet, ulong>> chunks,
|
||||
Dictionary<NetEntity, AtmosDeviceNavMapData> atmosDevices)
|
||||
: ComponentState
|
||||
{
|
||||
public Dictionary<Vector2i, Dictionary<(int, string), ulong>> Chunks = chunks;
|
||||
public Dictionary<Vector2i, Dictionary<AtmosMonitoringConsoleSubnet, ulong>> Chunks = chunks;
|
||||
public Dictionary<NetEntity, AtmosDeviceNavMapData> AtmosDevices = atmosDevices;
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
protected sealed class AtmosMonitoringConsoleDeltaState(
|
||||
Dictionary<Vector2i, Dictionary<(int, string), ulong>> modifiedChunks,
|
||||
Dictionary<Vector2i, Dictionary<AtmosMonitoringConsoleSubnet, ulong>> modifiedChunks,
|
||||
Dictionary<NetEntity, AtmosDeviceNavMapData> atmosDevices,
|
||||
HashSet<Vector2i> allChunks)
|
||||
: ComponentState, IComponentDeltaState<AtmosMonitoringConsoleState>
|
||||
{
|
||||
public Dictionary<Vector2i, Dictionary<(int, string), ulong>> ModifiedChunks = modifiedChunks;
|
||||
public Dictionary<Vector2i, Dictionary<AtmosMonitoringConsoleSubnet, ulong>> ModifiedChunks = modifiedChunks;
|
||||
public Dictionary<NetEntity, AtmosDeviceNavMapData> AtmosDevices = atmosDevices;
|
||||
public HashSet<Vector2i> 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<AtmosMonitoringConsoleSubnet, ulong>(data);
|
||||
}
|
||||
|
||||
state.AtmosDevices.Clear();
|
||||
@@ -93,7 +93,7 @@ public abstract class SharedAtmosMonitoringConsoleSystem : EntitySystem
|
||||
|
||||
public AtmosMonitoringConsoleState CreateNewFullState(AtmosMonitoringConsoleState state)
|
||||
{
|
||||
var chunks = new Dictionary<Vector2i, Dictionary<(int, string), ulong>>(state.Chunks.Count);
|
||||
var chunks = new Dictionary<Vector2i, Dictionary<AtmosMonitoringConsoleSubnet, ulong>>(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<AtmosMonitoringConsoleSubnet, ulong>(ModifiedChunks[index]);
|
||||
|
||||
else
|
||||
chunks[index] = new Dictionary<(int, string), ulong>(state.Chunks[index]);
|
||||
chunks[index] = new Dictionary<AtmosMonitoringConsoleSubnet, ulong>(state.Chunks[index]);
|
||||
}
|
||||
|
||||
return new AtmosMonitoringConsoleState(chunks, new(AtmosDevices));
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
using Content.Shared.Atmos.Components;
|
||||
|
||||
namespace Content.Shared.Atmos.EntitySystems;
|
||||
|
||||
public abstract partial class SharedAtmosPipeAppearanceSystem : EntitySystem
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns the max number of pipe layers supported by a entity.
|
||||
/// </summary>
|
||||
/// <param name="uid">The entity being checked.</param>
|
||||
/// <param name="atmosPipeLayers">The entity's <see cref="AtmosPipeLayersComponent"/>, if available.</param>
|
||||
/// <returns>Returns <see cref="AtmosPipeLayersComponent.NumberOfPipeLayers"/>
|
||||
/// if the entity has the component, or 1 if it does not.</returns>
|
||||
protected int GetNumberOfPipeLayers(EntityUid uid, out AtmosPipeLayersComponent? atmosPipeLayers)
|
||||
{
|
||||
return TryComp(uid, out atmosPipeLayers) ? atmosPipeLayers.NumberOfPipeLayers : 1;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
/// <summary>
|
||||
/// The system responsible for checking and adjusting the connection layering of gas pipes
|
||||
/// </summary>
|
||||
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<AtmosPipeLayersComponent, ExaminedEvent>(OnExamined);
|
||||
SubscribeLocalEvent<AtmosPipeLayersComponent, GetVerbsEvent<Verb>>(OnGetVerb);
|
||||
SubscribeLocalEvent<AtmosPipeLayersComponent, InteractUsingEvent>(OnInteractUsing);
|
||||
SubscribeLocalEvent<AtmosPipeLayersComponent, UseInHandEvent>(OnUseInHandEvent);
|
||||
SubscribeLocalEvent<AtmosPipeLayersComponent, TrySetNextPipeLayerCompletedEvent>(OnSetNextPipeLayerCompleted);
|
||||
SubscribeLocalEvent<AtmosPipeLayersComponent, TrySettingPipeLayerCompletedEvent>(OnSettingPipeLayerCompleted);
|
||||
}
|
||||
|
||||
private void OnExamined(Entity<AtmosPipeLayersComponent> 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<AtmosPipeLayersComponent> ent, ref GetVerbsEvent<Verb> 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<SubFloorHideComponent>(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<AtmosPipeLayersComponent> ent, ref InteractUsingEvent args)
|
||||
{
|
||||
if (ent.Comp.NumberOfPipeLayers <= 1 || ent.Comp.PipeLayersLocked)
|
||||
return;
|
||||
|
||||
if (TryComp<SubFloorHideComponent>(ent, out var subFloorHide) && subFloorHide.IsUnderCover)
|
||||
{
|
||||
_popup.PopupPredicted(Loc.GetString("atmos-pipe-layers-component-cannot-adjust-pipes"), ent, args.User);
|
||||
return;
|
||||
}
|
||||
|
||||
if (TryComp<ToolComponent>(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<AtmosPipeLayersComponent> 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<AtmosPipeLayersComponent> ent, ref TrySetNextPipeLayerCompletedEvent args)
|
||||
{
|
||||
if (args.Cancelled)
|
||||
return;
|
||||
|
||||
SetNextPipeLayer(ent, args.User, args.Used);
|
||||
}
|
||||
|
||||
private void OnSettingPipeLayerCompleted(Entity<AtmosPipeLayersComponent> ent, ref TrySettingPipeLayerCompletedEvent args)
|
||||
{
|
||||
if (args.Cancelled)
|
||||
return;
|
||||
|
||||
SetPipeLayer(ent, args.PipeLayer, args.User, args.Used);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Increments an entity's pipe layer by 1, wrapping around to 0 if the max pipe layer is reached
|
||||
/// </summary>
|
||||
/// <param name="ent">The pipe entity</param>
|
||||
/// <param name="user">The player entity who adjusting the pipe layer</param>
|
||||
/// <param name="used">The tool used to adjust the pipe layer</param>
|
||||
public void SetNextPipeLayer(Entity<AtmosPipeLayersComponent> ent, EntityUid? user = null, EntityUid? used = null)
|
||||
{
|
||||
var newLayer = ((int)ent.Comp.CurrentPipeLayer + 1) % ent.Comp.NumberOfPipeLayers;
|
||||
SetPipeLayer(ent, (AtmosPipeLayer)newLayer, user, used);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets an entity's pipe layer to a specified value
|
||||
/// </summary>
|
||||
/// <param name="ent">The pipe entity</param>
|
||||
/// <param name="layer">The new layer value</param>
|
||||
/// <param name="user">The player entity who adjusting the pipe layer</param>
|
||||
/// <param name="used">The tool used to adjust the pipe layer</param>
|
||||
public virtual void SetPipeLayer(Entity<AtmosPipeLayersComponent> 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<AppearanceComponent>(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<string, string>();
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Try to find an entity prototype associated with a specified <see cref="AtmosPipeLayer"/>.
|
||||
/// </summary>
|
||||
/// <param name="component">The <see cref="AtmosPipeLayersComponent"/> with the alternative prototypes data.</param>
|
||||
/// <param name="layer">The atmos pipe layer associated with the entity prototype.</param>
|
||||
/// <param name="proto">The returned entity prototype.</param>
|
||||
/// <returns>True if there was an entity prototype associated with the layer.</returns>
|
||||
public bool TryGetAlternativePrototype(AtmosPipeLayersComponent component, AtmosPipeLayer layer, out EntProtoId proto)
|
||||
{
|
||||
return component.AlternativePrototypes.TryGetValue(layer, out proto);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks a player entity's hands to see if they are holding a tool with a specified quality
|
||||
/// </summary>
|
||||
/// <param name="user">The player entity</param>
|
||||
/// <param name="toolQuality">The tool quality being checked for</param>
|
||||
/// <param name="heldTool">A tool with the specified tool quality</param>
|
||||
/// <returns>True if an appropriate tool was found</returns>
|
||||
private bool TryGetHeldTool(EntityUid user, ProtoId<ToolQualityPrototype> toolQuality, [NotNullWhen(true)] out Entity<ToolComponent>? heldTool)
|
||||
{
|
||||
heldTool = null;
|
||||
|
||||
foreach (var heldItem in _hands.EnumerateHeld(user))
|
||||
{
|
||||
if (TryComp<ToolComponent>(heldItem, out var tool) &&
|
||||
_tool.HasQuality(heldItem, toolQuality, tool))
|
||||
{
|
||||
heldTool = new Entity<ToolComponent>(heldItem, tool);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private string GetPipeLayerName(AtmosPipeLayer layer)
|
||||
{
|
||||
return Loc.GetString("atmos-pipe-layers-component-layer-" + layer.ToString().ToLower());
|
||||
}
|
||||
}
|
||||
@@ -85,6 +85,12 @@ public sealed partial class ConstructionPrototype : IPrototype
|
||||
[DataField]
|
||||
public ProtoId<ConstructionPrototype>? Mirror { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Possible constructions to replace this one with as determined by the placement mode
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public ProtoId<ConstructionPrototype>[] AlternativePrototypes = [];
|
||||
|
||||
public IReadOnlyList<IConstructionCondition> Conditions => _conditions;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,13 +9,15 @@ namespace Content.Shared.DrawDepth
|
||||
/// <summary>
|
||||
/// This is for sub-floors, the floors you see after prying off a tile.
|
||||
/// </summary>
|
||||
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
|
||||
|
||||
@@ -39,4 +39,17 @@ public sealed partial class NavMapBlipPrototype : IPrototype
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public float Scale { get; private set; } = 1f;
|
||||
|
||||
/// <summary>
|
||||
/// Describes how the blip should be positioned.
|
||||
/// It's up to the individual system to enforce this
|
||||
/// </summary>
|
||||
[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)
|
||||
}
|
||||
|
||||
@@ -225,6 +225,7 @@ namespace Content.Shared.SubFloor
|
||||
ScannerRevealed,
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public enum SubfloorLayers : byte
|
||||
{
|
||||
FirstLayer
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
10
Resources/Locale/en-US/atmos/atmos-pipe-layers.ftl
Normal file
@@ -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.
|
||||
@@ -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
|
||||
|
||||
@@ -13,17 +13,18 @@
|
||||
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"
|
||||
@@ -37,6 +38,7 @@
|
||||
- "/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
|
||||
@@ -47,10 +49,21 @@
|
||||
- "/Textures/Interface/NavMap/beveled_diamond_east_west.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"
|
||||
|
||||
- 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"
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
After Width: | Height: | Size: 390 B |
@@ -0,0 +1,2 @@
|
||||
sample:
|
||||
filter: true
|
||||
|
After Width: | Height: | Size: 394 B |
@@ -0,0 +1,2 @@
|
||||
sample:
|
||||
filter: true
|
||||
@@ -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
|
||||
|
||||
BIN
Resources/Textures/Interface/VerbIcons/screwdriver.png
Normal file
|
After Width: | Height: | Size: 713 B |
@@ -0,0 +1,2 @@
|
||||
sample:
|
||||
filter: true
|
||||
@@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 344 B After Width: | Height: | Size: 279 B |
@@ -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
|
||||
}
|
||||
]
|
||||
}
|
||||
|
After Width: | Height: | Size: 571 B |
@@ -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
|
||||
}
|
||||
]
|
||||
}
|
||||
|
After Width: | Height: | Size: 363 B |
|
Before Width: | Height: | Size: 248 B After Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 183 B After Width: | Height: | Size: 2.7 KiB |
@@ -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
|
||||
|
||||
|
After Width: | Height: | Size: 621 B |
|
After Width: | Height: | Size: 83 B |
|
After Width: | Height: | Size: 523 B |
|
After Width: | Height: | Size: 393 B |
@@ -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
|
||||
]
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
After Width: | Height: | Size: 621 B |
|
After Width: | Height: | Size: 83 B |
|
After Width: | Height: | Size: 523 B |
|
After Width: | Height: | Size: 398 B |
@@ -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
|
||||
]
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 321 B After Width: | Height: | Size: 307 B |
@@ -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
|
||||
}
|
||||
]
|
||||
}
|
||||
|
After Width: | Height: | Size: 457 B |
|
After Width: | Height: | Size: 458 B |
|
After Width: | Height: | Size: 455 B |
|
After Width: | Height: | Size: 8.8 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
@@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
After Width: | Height: | Size: 3.5 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 449 B After Width: | Height: | Size: 270 B |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 503 B After Width: | Height: | Size: 305 B |
|
Before Width: | Height: | Size: 509 B After Width: | Height: | Size: 333 B |
@@ -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
|
||||
}
|
||||
]
|
||||
}
|
||||
|
After Width: | Height: | Size: 912 B |
|
After Width: | Height: | Size: 788 B |
|
After Width: | Height: | Size: 643 B |
|
After Width: | Height: | Size: 206 B |
|
After Width: | Height: | Size: 911 B |
|
After Width: | Height: | Size: 540 B |
|
After Width: | Height: | Size: 721 B |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 972 B |
|
After Width: | Height: | Size: 690 B |
@@ -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
|
||||
}
|
||||
]
|
||||
}
|
||||
|
After Width: | Height: | Size: 890 B |
|
After Width: | Height: | Size: 774 B |
|
After Width: | Height: | Size: 643 B |
|
After Width: | Height: | Size: 207 B |
|
After Width: | Height: | Size: 877 B |
|
After Width: | Height: | Size: 545 B |
|
After Width: | Height: | Size: 719 B |
|
After Width: | Height: | Size: 1.2 KiB |