--- /dev/null
+using Content.Shared.IconSmoothing;
+using Robust.Client.GameObjects;
+
+namespace Content.Client.IconSmoothing;
+
+public sealed partial class IconSmoothSystem
+{
+ // Handles drawing edge sprites on the non-smoothed edges.
+
+ private void InitializeEdge()
+ {
+ SubscribeLocalEvent<SmoothEdgeComponent, ComponentStartup>(OnEdgeStartup);
+ SubscribeLocalEvent<SmoothEdgeComponent, ComponentShutdown>(OnEdgeShutdown);
+ }
+
+ private void OnEdgeStartup(EntityUid uid, SmoothEdgeComponent component, ComponentStartup args)
+ {
+ if (!TryComp<SpriteComponent>(uid, out var sprite))
+ return;
+
+ sprite.LayerSetOffset(EdgeLayer.South, new Vector2(0, -1f));
+ sprite.LayerSetOffset(EdgeLayer.East, new Vector2(1f, 0f));
+ sprite.LayerSetOffset(EdgeLayer.North, new Vector2(0, 1f));
+ sprite.LayerSetOffset(EdgeLayer.West, new Vector2(-1f, 0f));
+
+ sprite.LayerSetVisible(EdgeLayer.South, false);
+ sprite.LayerSetVisible(EdgeLayer.East, false);
+ sprite.LayerSetVisible(EdgeLayer.North, false);
+ sprite.LayerSetVisible(EdgeLayer.West, false);
+ }
+
+ private void OnEdgeShutdown(EntityUid uid, SmoothEdgeComponent component, ComponentShutdown args)
+ {
+ if (!TryComp<SpriteComponent>(uid, out var sprite))
+ return;
+
+ sprite.LayerMapRemove(EdgeLayer.South);
+ sprite.LayerMapRemove(EdgeLayer.East);
+ sprite.LayerMapRemove(EdgeLayer.North);
+ sprite.LayerMapRemove(EdgeLayer.West);
+ }
+
+ private void CalculateEdge(EntityUid uid, DirectionFlag directions, SpriteComponent? sprite = null, SmoothEdgeComponent? component = null)
+ {
+ if (!Resolve(uid, ref sprite, ref component, false))
+ return;
+
+ for (var i = 0; i < 4; i++)
+ {
+ var dir = (DirectionFlag) Math.Pow(2, i);
+ var edge = GetEdge(dir);
+
+ if ((dir & directions) != 0x0)
+ {
+ sprite.LayerSetVisible(edge, false);
+ continue;
+ }
+
+ sprite.LayerSetVisible(edge, true);
+ }
+ }
+
+ private EdgeLayer GetEdge(DirectionFlag direction)
+ {
+ switch (direction)
+ {
+ case DirectionFlag.South:
+ return EdgeLayer.South;
+ case DirectionFlag.East:
+ return EdgeLayer.East;
+ case DirectionFlag.North:
+ return EdgeLayer.North;
+ case DirectionFlag.West:
+ return EdgeLayer.West;
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+ }
+
+ private enum EdgeLayer : byte
+ {
+ South,
+ East,
+ North,
+ West
+ }
+}
+using Content.Shared.IconSmoothing;
using JetBrains.Annotations;
using Robust.Client.GameObjects;
using Robust.Shared.Map;
/// Entity system implementing the logic for <see cref="IconSmoothComponent"/>
/// </summary>
[UsedImplicitly]
- internal sealed class IconSmoothSystem : EntitySystem
+ public sealed partial class IconSmoothSystem : EntitySystem
{
[Dependency] private readonly IMapManager _mapManager = default!;
{
base.Initialize();
+ InitializeEdge();
SubscribeLocalEvent<IconSmoothComponent, AnchorStateChangedEvent>(OnAnchorChanged);
SubscribeLocalEvent<IconSmoothComponent, ComponentShutdown>(OnShutdown);
SubscribeLocalEvent<IconSmoothComponent, ComponentStartup>(OnStartup);
EntityQuery<TransformComponent> xformQuery,
IconSmoothComponent? smooth = null)
{
+ TransformComponent? xform;
+ MapGridComponent? grid = null;
+
// The generation check prevents updating an entity multiple times per tick.
// As it stands now, it's totally possible for something to get queued twice.
// Generation on the component is set after an update so we can cull updates that happened this generation.
|| smooth.Mode == IconSmoothingMode.NoSprite
|| smooth.UpdateGeneration == _generation)
{
+ if (smooth != null &&
+ TryComp<SmoothEdgeComponent>(uid, out var edge) &&
+ xformQuery.TryGetComponent(uid, out xform))
+ {
+ var directions = DirectionFlag.None;
+
+ if (_mapManager.TryGetGrid(xform.GridUid, out grid))
+ {
+ var pos = grid.TileIndicesFor(xform.Coordinates);
+
+ if (MatchingEntity(smooth, grid.GetAnchoredEntities(pos.Offset(Direction.North)), smoothQuery))
+ directions |= DirectionFlag.North;
+ if (MatchingEntity(smooth, grid.GetAnchoredEntities(pos.Offset(Direction.South)), smoothQuery))
+ directions |= DirectionFlag.South;
+ if (MatchingEntity(smooth, grid.GetAnchoredEntities(pos.Offset(Direction.East)), smoothQuery))
+ directions |= DirectionFlag.East;
+ if (MatchingEntity(smooth, grid.GetAnchoredEntities(pos.Offset(Direction.West)), smoothQuery))
+ directions |= DirectionFlag.West;
+ }
+
+ CalculateEdge(uid, directions, component: edge);
+ }
+
return;
}
+
+ xform = xformQuery.GetComponent(uid);
smooth.UpdateGeneration = _generation;
if (!spriteQuery.TryGetComponent(uid, out var sprite))
return;
}
- var xform = xformQuery.GetComponent(uid);
-
- MapGridComponent? grid = null;
-
if (xform.Anchored)
{
if (!_mapManager.TryGetGrid(xform.GridUid, out grid))
if (matching)
{
sprite.LayerSetState(0, $"{smooth.StateBase}1");
- return;
}
-
- sprite.LayerSetState(0, $"{smooth.StateBase}0");
+ else
+ {
+ sprite.LayerSetState(0, $"{smooth.StateBase}0");
+ }
}
private void CalculateNewSpriteCardinal(MapGridComponent? grid, IconSmoothComponent smooth, SpriteComponent sprite, TransformComponent xform, EntityQuery<IconSmoothComponent> smoothQuery)
dirs |= CardinalConnectDirs.West;
sprite.LayerSetState(0, $"{smooth.StateBase}{(int) dirs}");
+
+ var directions = DirectionFlag.None;
+
+ if ((dirs & CardinalConnectDirs.South) != 0x0)
+ directions |= DirectionFlag.South;
+ if ((dirs & CardinalConnectDirs.East) != 0x0)
+ directions |= DirectionFlag.East;
+ if ((dirs & CardinalConnectDirs.North) != 0x0)
+ directions |= DirectionFlag.North;
+ if ((dirs & CardinalConnectDirs.West) != 0x0)
+ directions |= DirectionFlag.West;
+
+ CalculateEdge(sprite.Owner, directions, sprite);
}
private bool MatchingEntity(IconSmoothComponent smooth, IEnumerable<EntityUid> candidates, EntityQuery<IconSmoothComponent> smoothQuery)
sprite.LayerSetState(CornerLayers.SE, $"{smooth.StateBase}{(int) cornerSE}");
sprite.LayerSetState(CornerLayers.SW, $"{smooth.StateBase}{(int) cornerSW}");
sprite.LayerSetState(CornerLayers.NW, $"{smooth.StateBase}{(int) cornerNW}");
+
+ var directions = DirectionFlag.None;
+
+ if ((cornerSE & cornerSW) != CornerFill.None)
+ directions |= DirectionFlag.South;
+
+ if ((cornerSE & cornerNE) != CornerFill.None)
+ directions |= DirectionFlag.East;
+
+ if ((cornerNE & cornerNW) != CornerFill.None)
+ directions |= DirectionFlag.North;
+
+ if ((cornerNW & cornerSW) != CornerFill.None)
+ directions |= DirectionFlag.West;
+
+ CalculateEdge(sprite.Owner, directions, sprite);
}
private (CornerFill ne, CornerFill nw, CornerFill sw, CornerFill se) CalculateCornerFill(MapGridComponent grid, IconSmoothComponent smooth, TransformComponent xform, EntityQuery<IconSmoothComponent> smoothQuery)
--- /dev/null
+namespace Content.Client.Mining;
+
+public sealed class OreVeinVisualsComponent
+{
+
+}
--- /dev/null
+using Robust.Shared.GameStates;
+
+namespace Content.Shared.IconSmoothing;
+
+/// <summary>
+/// Applies an edge sprite to <see cref="IconSmoothComponent"/> for non-smoothed directions.
+/// </summary>
+[RegisterComponent, NetworkedComponent]
+public sealed class SmoothEdgeComponent : Component
+{
+
+}
/// This is a prototype for defining ores that generate in rock
/// </summary>
[Prototype("ore")]
-[DataDefinition]
public sealed class OrePrototype : IPrototype
{
/// <inheritdoc/>
- type: OreVein
oreChance: 0.33
oreRarityPrototypeId: RandomOreDistributionStandard
+
+# Rocks and ore veins
+- type: entity
+ id: WallRock
+ parent: BaseStructure
+ name: rock
+ components:
+ - type: Gatherable
+ whitelist:
+ tags:
+ - Pickaxe
+ - type: Damageable
+ damageContainer: Inorganic
+ damageModifierSet: Metallic
+ - type: Destructible
+ thresholds:
+ - trigger:
+ !type:DamageTrigger
+ damage: 150
+ behaviors:
+ - !type:DoActsBehavior
+ acts: ["Destruction"]
+ - type: Occluder
+ - type: Airtight
+ - type: Fixtures
+ fixtures:
+ - shape:
+ !type:PhysShapeAabb
+ bounds: "-0.5,-0.5,0.5,0.5"
+ density: 100
+ mask:
+ - FullTileMask
+ layer:
+ - WallLayer
+ - type: IconSmooth
+ key: walls
+ mode: NoSprite
+ - type: SmoothEdge
+ - type: Sprite
+ sprite: Structures/Walls/rock.rsi
+ netsync: false
+ layers:
+ - state: rock
+ - map: [ "enum.EdgeLayer.South" ]
+ state: rock_south
+ - map: [ "enum.EdgeLayer.East" ]
+ state: rock_east
+ - map: [ "enum.EdgeLayer.North" ]
+ state: rock_north
+ - map: [ "enum.EdgeLayer.West" ]
+ state: rock_west
+
+# Ore veins
+- type: entity
+ id: WallRockGold
+ parent: WallRock
+ description: An ore vein rich with gold
+ suffix: Gold
+ components:
+ - type: OreVein
+ oreChance: 1.0
+ currentOre: OreGold
+ - type: Sprite
+ layers:
+ - state: rock
+ - map: [ "enum.EdgeLayer.South" ]
+ state: rock_south
+ - map: [ "enum.EdgeLayer.East" ]
+ state: rock_east
+ - map: [ "enum.EdgeLayer.North" ]
+ state: rock_north
+ - map: [ "enum.EdgeLayer.West" ]
+ state: rock_west
+ - state: rock_gold
+
+- type: entity
+ id: WallRockPlasma
+ parent: WallRock
+ description: An ore vein rich with plasma
+ suffix: Plasma
+ components:
+ - type: OreVein
+ oreChance: 1.0
+ currentOre: OrePlasma
+ - type: Sprite
+ layers:
+ - state: rock
+ - map: [ "enum.EdgeLayer.South" ]
+ state: rock_south
+ - map: [ "enum.EdgeLayer.East" ]
+ state: rock_east
+ - map: [ "enum.EdgeLayer.North" ]
+ state: rock_north
+ - map: [ "enum.EdgeLayer.West" ]
+ state: rock_west
+ - state: rock_phoron
+
+- type: entity
+ id: WallRockQuartz
+ parent: WallRock
+ description: An ore vein rich with quartz
+ suffix: Quartz
+ components:
+ - type: OreVein
+ oreChance: 1.0
+ currentOre: OreSpaceQuartz
+ - type: Sprite
+ layers:
+ - state: rock
+ - map: [ "enum.EdgeLayer.South" ]
+ state: rock_south
+ - map: [ "enum.EdgeLayer.East" ]
+ state: rock_east
+ - map: [ "enum.EdgeLayer.North" ]
+ state: rock_north
+ - map: [ "enum.EdgeLayer.West" ]
+ state: rock_west
+ - state: rock_quartz
+
+- type: entity
+ id: WallRockSilver
+ parent: WallRock
+ description: An ore vein rich with silver
+ suffix: Silver
+ components:
+ - type: OreVein
+ oreChance: 1.0
+ currentOre: OreSilver
+ - type: Sprite
+ layers:
+ - state: rock
+ - map: [ "enum.EdgeLayer.South" ]
+ state: rock_south
+ - map: [ "enum.EdgeLayer.East" ]
+ state: rock_east
+ - map: [ "enum.EdgeLayer.North" ]
+ state: rock_north
+ - map: [ "enum.EdgeLayer.West" ]
+ state: rock_west
+ - state: rock_silver
+
+# Yes I know it drops steel but we may get smelting at some point
+- type: entity
+ id: WallRockTin
+ parent: WallRock
+ description: An ore vein rich with steel
+ suffix: Steel
+ components:
+ - type: OreVein
+ oreChance: 1.0
+ currentOre: OreSteel
+ - type: Sprite
+ layers:
+ - state: rock
+ - map: [ "enum.EdgeLayer.South" ]
+ state: rock_south
+ - map: [ "enum.EdgeLayer.East" ]
+ state: rock_east
+ - map: [ "enum.EdgeLayer.North" ]
+ state: rock_north
+ - map: [ "enum.EdgeLayer.West" ]
+ state: rock_west
+ - state: rock_tin
+
+- type: entity
+ id: WallRockUranium
+ parent: WallRock
+ description: An ore vein rich with uranium
+ suffix: Uranium
+ components:
+ - type: OreVein
+ oreChance: 1.0
+ currentOre: OreUranium
+ - type: Sprite
+ layers:
+ - state: rock
+ - map: [ "enum.EdgeLayer.South" ]
+ state: rock_south
+ - map: [ "enum.EdgeLayer.East" ]
+ state: rock_east
+ - map: [ "enum.EdgeLayer.North" ]
+ state: rock_north
+ - map: [ "enum.EdgeLayer.West" ]
+ state: rock_west
+ - state: rock_uranium
--- /dev/null
+{
+ "version": 1,
+ "license": "CC-BY-SA-3.0",
+ "copyright": "https://github.com/Citadel-Station-13/Citadel-Station-13-RP/blob/817e7c1f225876b45891e3f06908e6d032f0a8bc/icons/turf/walls.dmi",
+ "size": {
+ "x": 32,
+ "y": 32
+ },
+ "states": [
+ {
+ "name": "rock"
+ },
+ {
+ "name": "rock_south"
+ },
+ {
+ "name": "rock_east"
+ },
+ {
+ "name": "rock_north"
+ },
+ {
+ "name": "rock_west"
+ },
+ {
+ "name": "rock_bauxite"
+ },
+ {
+ "name": "rock_carbon"
+ },
+ {
+ "name": "rock_copper"
+ },
+ {
+ "name": "rock_diamond"
+ },
+ {
+ "name": "rock_gold"
+ },
+ {
+ "name": "rock_hematite"
+ },
+ {
+ "name": "rock_lead"
+ },
+ {
+ "name": "rock_marble"
+ },
+ {
+ "name": "rock_painite"
+ },
+ {
+ "name": "rock_phoron"
+ },
+ {
+ "name": "rock_platinum"
+ },
+ {
+ "name": "rock_quartz"
+ },
+ {
+ "name": "rock_rutile"
+ },
+ {
+ "name": "rock_silver"
+ },
+ {
+ "name": "rock_tin"
+ },
+ {
+ "name": "rock_uranium"
+ },
+ {
+ "name": "rock_verdantium"
+ },
+ {
+ "name": "rock_void_opal"
+ }
+ ]
+}
\ No newline at end of file