]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Decal Spawners (#37066)
authorSouthbridge <7013162+southbridge-fur@users.noreply.github.com>
Tue, 27 May 2025 23:55:48 +0000 (19:55 -0400)
committerGitHub <noreply@github.com>
Tue, 27 May 2025 23:55:48 +0000 (16:55 -0700)
Co-authored-by: ArtisticRoomba <145879011+ArtisticRoomba@users.noreply.github.com>
Content.Server/Spawners/Components/RandomDecalSpawnerComponent.cs [new file with mode: 0644]
Content.Server/Spawners/EntitySystems/RandomDecalSpawnerSystem.cs [new file with mode: 0644]
Resources/Prototypes/Entities/Markers/Spawners/Random/Decals/base.yml [new file with mode: 0644]
Resources/Prototypes/Entities/Markers/Spawners/Random/Decals/dirt.yml [new file with mode: 0644]
Resources/Prototypes/Entities/Markers/Spawners/Random/Decals/flora.yml [new file with mode: 0644]
Resources/Prototypes/Entities/Markers/Spawners/Random/Decals/splatters.yml [new file with mode: 0644]
Resources/Prototypes/GameRules/roundstart.yml
Resources/Prototypes/GameRules/variation.yml
Resources/Textures/Markers/cross.rsi/decal.png [new file with mode: 0644]
Resources/Textures/Markers/cross.rsi/meta.json

diff --git a/Content.Server/Spawners/Components/RandomDecalSpawnerComponent.cs b/Content.Server/Spawners/Components/RandomDecalSpawnerComponent.cs
new file mode 100644 (file)
index 0000000..50e9137
--- /dev/null
@@ -0,0 +1,122 @@
+using Robust.Shared.Prototypes;
+using Content.Shared.Maps;
+using Content.Shared.Decals;
+
+namespace Content.Server.Spawners.Components;
+
+/// <summary>
+/// This component spawns decals around the entity on MapInit.
+/// See doc strings for the various parameters for more information.
+/// </summary>
+[RegisterComponent, EntityCategory("Spawner")]
+public sealed partial class RandomDecalSpawnerComponent : Component
+{
+    /// <summary>
+    /// A list of decals to randomly select from when spawning.
+    /// </summary>
+    [DataField]
+    public List<ProtoId<DecalPrototype>> Decals = new();
+
+    /// <summary>
+    /// Radius (in tiles) to spawn decals in. 0 will target only the tile the entity is on.
+    /// </summary>
+    [DataField]
+    public float Radius = 1f;
+
+    /// <summary>
+    /// Probability that a particular decal gets spawned.
+    /// </summary>
+    [DataField]
+    public float Prob = 1f;
+
+    /// <summary>
+    /// The maximum amount of decals to spawn across the entire radius.
+    /// </summary>
+    [DataField]
+    public int MaxDecals = 1;
+
+    /// <summary>
+    /// The maximum amount of decals to spawn within a tile.
+    /// </summary>
+    /// <remarks>
+    /// A value <= 0 or null is considered unlimited.
+    /// </remarks>
+    [DataField]
+    public int? MaxDecalsPerTile = null;
+
+    /// <summary>
+    /// Whether decals should have a random rotation applied to them.
+    /// </summary>
+    [DataField]
+    public bool RandomRotation = false;
+
+    /// <summary>
+    /// Whether decals should snap to 90 degree orientations, does nothing if RandomRotation is false.
+    /// </summary>
+    [DataField]
+    public bool SnapRotation = false;
+
+    /// <summary>
+    /// Whether decals should snap to the center omf a grid space or be placed randoly.
+    /// </summary>
+    /// <remarks>
+    /// A null value will cause this to attempt to use the default value (DefaultSnap) for the decal.
+    /// </remarks>
+    [DataField]
+    public bool? SnapPosition = false;
+
+    /// <summary>
+    /// zIndex for the generated decals
+    /// </summary>
+    [DataField]
+    public int ZIndex = 0;
+
+    /// <summary>
+    /// Color for the generated decals. Does nothing if RandomColorList is set.
+    /// </summary>
+    [DataField]
+    public Color Color = Color.White;
+
+    /// <summary>
+    /// A random color to select from. Overrides Color if set.
+    /// </summary>
+    [DataField]
+    public List<Color>? RandomColorList = new();
+
+    /// <summary>
+    /// Whether the new decals are cleanable or not
+    /// </summary>
+    /// <remarks>
+    /// A null value will cause this to attempt to use the default value (DefaultCleanable) for the decal.
+    /// </remarks>
+    [DataField]
+    public bool? Cleanable = null;
+
+    /// <summary>
+    /// A list of tile prototype IDs to only place decals on.
+    /// </summary>
+    /// <remarks>
+    /// Causes the TileBlacklist to be ignored if this is set.
+    /// Note that due to the nature of tile-based placement, it's possible for decals to "spill over" onto nearby tiles.
+    /// This is mostly so dirt decals don't go on diagonal tiles that won't work for them.
+    /// </remarks>
+    [DataField]
+    public List<ProtoId<ContentTileDefinition>> TileWhitelist = new();
+
+    /// <summary>
+    /// A list of tile prototype IDs to avoid placing decals on.
+    /// </summary>
+    /// <remarks>
+    /// Ignored if TileWhitelist is set.
+    /// Note that due to the nature of tile-based placement, it's possible for decals to "spill over" onto nearby tiles.
+    /// This is mostly so dirt decals don't go on diagonal tiles that won't work for them.
+    /// </remarks>
+    [DataField]
+    public List<ProtoId<ContentTileDefinition>> TileBlacklist = new();
+
+    /// <summary>
+    /// Sets whether to delete the entity with this component after the spawner is finished.
+    /// </summary>
+    [DataField]
+    public bool DeleteSpawnerAfterSpawn = false;
+}
diff --git a/Content.Server/Spawners/EntitySystems/RandomDecalSpawnerSystem.cs b/Content.Server/Spawners/EntitySystems/RandomDecalSpawnerSystem.cs
new file mode 100644 (file)
index 0000000..1182bc1
--- /dev/null
@@ -0,0 +1,130 @@
+using System.Numerics;
+using Content.Server.Decals;
+using Content.Server.Spawners.Components;
+using Robust.Shared.Map;
+using Robust.Shared.Map.Components;
+using Robust.Shared.Prototypes;
+using Robust.Shared.Random;
+
+namespace Content.Server.Spawners.EntitySystems;
+
+public sealed class RandomDecalSpawnerSystem : EntitySystem
+{
+    [Dependency] private readonly DecalSystem _decal = default!;
+    [Dependency] private readonly SharedMapSystem _map = default!;
+    [Dependency] private readonly IPrototypeManager _prototypes = default!;
+    [Dependency] private readonly IRobustRandom _random = default!;
+    [Dependency] private readonly ITileDefinitionManager _tileDefs = default!;
+
+    public override void Initialize()
+    {
+        base.Initialize();
+
+        SubscribeLocalEvent<RandomDecalSpawnerComponent, MapInitEvent>(OnMapInit);
+    }
+
+    private void OnMapInit(EntityUid uid, RandomDecalSpawnerComponent component, MapInitEvent args)
+    {
+        TrySpawn(uid);
+        if (component.DeleteSpawnerAfterSpawn)
+            QueueDel(uid);
+    }
+
+    public bool TrySpawn(Entity<RandomDecalSpawnerComponent?> ent)
+    {
+        if (!TryComp<RandomDecalSpawnerComponent>(ent, out var comp))
+            return false;
+
+        if (comp.Decals.Count == 0)
+            return false;
+
+        var tileWhitelist = new List<ITileDefinition>();
+        if (comp.TileWhitelist.Count > 0)
+        {
+            foreach (var tileProto in comp.TileWhitelist)
+            {
+                if (_tileDefs.TryGetDefinition(tileProto, out var tileDef))
+                    tileWhitelist.Add(tileDef);
+            }
+        }
+        else if (comp.TileBlacklist.Count > 0)
+        {
+            foreach (var tileDef in _tileDefs)
+            {
+                if (!comp.TileBlacklist.Contains(tileDef.ID))
+                    tileWhitelist.Add(tileDef);
+            }
+        }
+
+        var xform = Transform(ent);
+        if (!TryComp<MapGridComponent>(xform.GridUid, out var grid))
+            return false;
+
+        var addedDecals = new Dictionary<string, int>();
+
+        for (var i = 0; i < comp.MaxDecals; i++)
+        {
+            if (comp.Prob < 1f && _random.NextFloat() > comp.Prob)
+                continue;
+
+            // The vector added here is just to center the generated decals to the tile the spawner is on.
+            var localPos = xform.Coordinates.Position + _random.NextVector2(comp.Radius) + new Vector2(-0.5f, -0.5f);
+            var position = new EntityCoordinates(xform.GridUid.Value, localPos);
+
+            var tileRef = _map.GetTileRef(xform.GridUid.Value, grid, position);
+
+            if (tileWhitelist.Count > 0)
+            {
+                _tileDefs.TryGetDefinition(tileRef.Tile.TypeId, out var currTileDef);
+                if (currTileDef is null || !tileWhitelist.Contains(currTileDef))
+                    continue;
+            }
+
+            var tileRefStr = tileRef.ToString();
+            if (comp.MaxDecalsPerTile is > 0)
+            {
+                addedDecals.TryAdd(tileRefStr, 0);
+                if (addedDecals[tileRefStr] >= comp.MaxDecalsPerTile)
+                    continue;
+            }
+
+            var decalProtoId = _random.Pick(comp.Decals);
+            var decalProto = _prototypes.Index(decalProtoId);
+            var snapPosition = comp.SnapPosition ?? decalProto.DefaultSnap;
+            if (snapPosition)
+            {
+                position = position.WithPosition(tileRef.GridIndices * grid.TileSize);
+            }
+
+            var cleanable = comp.Cleanable ?? decalProto.DefaultCleanable;
+
+            var rotation = Angle.Zero;
+            if (comp.RandomRotation)
+            {
+                if (comp.SnapRotation)
+                    rotation = new Angle((MathF.PI / 2f) * _random.Next(3));
+                else
+                    rotation = _random.NextAngle();
+            }
+
+            var color = comp.Color;
+            if (comp.RandomColorList != null && comp.RandomColorList.Count != 0)
+                color = _random.Pick(comp.RandomColorList);
+
+            _decal.TryAddDecal(
+                decalProtoId,
+                position,
+                out _,
+                color,
+                rotation,
+                comp.ZIndex,
+                cleanable
+            );
+
+            if (comp.MaxDecalsPerTile is > 0)
+                addedDecals[tileRefStr]++;
+        }
+
+        return true;
+    }
+}
diff --git a/Resources/Prototypes/Entities/Markers/Spawners/Random/Decals/base.yml b/Resources/Prototypes/Entities/Markers/Spawners/Random/Decals/base.yml
new file mode 100644 (file)
index 0000000..3c5fc97
--- /dev/null
@@ -0,0 +1,10 @@
+- type: entity
+  parent: MarkerBase
+  id: DecalSpawnerBase
+  name: Decal Spawner
+  abstract: true
+  components:
+  - type: Sprite
+    layers:
+    - state: green
+    - state: decal
diff --git a/Resources/Prototypes/Entities/Markers/Spawners/Random/Decals/dirt.yml b/Resources/Prototypes/Entities/Markers/Spawners/Random/Decals/dirt.yml
new file mode 100644 (file)
index 0000000..3286abe
--- /dev/null
@@ -0,0 +1,157 @@
+- type: entity
+  parent: DecalSpawnerBase
+  id: DecalSpawnerDirtBase
+  abstract: true
+  components:
+  - type: RandomDecalSpawner
+    decals:
+    - DirtLight
+    - DirtMedium
+    - DirtHeavy
+    maxDecalsPerTile: 1
+    snapPosition: true
+    zIndex: 1
+    prob: 0.8
+    color: '#FFFFFF7F'
+    cleanable: true
+    tileBlacklist: # Everything here just looks bad if it gets regular dirt on it
+    - FloorSteelMono
+    - FloorSteelDiagonal
+    - FloorSteelOffset
+    - FloorSteelDiagonalMini
+    - FloorWood
+    - FloorWoodLarge
+    - FloorWhiteMono
+    - FloorWhiteDiagonal
+    - FloorWhiteOffset
+    - FloorWhiteDiagonalMini
+    - FloorDarkMono
+    - FloorDarkDiagonal
+    - FloorDarkOffset
+    - FloorDarkDiagonalMini
+    - FloorArcadeBlue
+    - FloorArcadeBlue2
+    - FloorArcadeRed
+    - FloorEighties
+    - FloorCarpetClown
+    - FloorCarpetOffice
+    - FloorBoxing
+    - FloorGym
+    - FloorGlass
+    - FloorRGlass
+    - FloorAstroGrass
+    - FloorMowedAstroGrass
+    - FloorJungleAstroGrass
+    - FloorAstroIce
+    - FloorAstroSnow
+    - FloorAstroAsteroidSand
+    - FloorFlesh
+    - FloorAsteroidSandUnvariantized
+    - FloorAsteroidIronsandUnvariantized
+    - FloorCave
+    - FloorAsteroidIronsand
+    - FloorAsteroidTile
+    - FloorAsteroidSandDug
+    - FloorAsteroidSand
+    - FloorDirt
+    - FloorGrassLight
+    - FloorGrassDark
+    - FloorGrassJungle
+    - FloorGrass
+    - FloorAsphalt
+    - FloorReinforced
+    - FloorLino
+    deleteSpawnerAfterSpawn: true
+
+- type: entity
+  parent: DecalSpawnerDirtBase
+  id: DecalSpawnerDirtSingle
+  suffix: Dirt, 0 Radius
+  components:
+  - type: RandomDecalSpawner
+    radius: 0
+    prob: 1.0
+    maxDecals: 1
+
+- type: entity
+  parent: DecalSpawnerDirtBase
+  id: DecalSpawnerDirtNear
+  suffix: Dirt, 1.5 Radius
+  components:
+  - type: RandomDecalSpawner
+    radius: 1.5
+    maxDecals: 5
+
+- type: entity
+  parent: DecalSpawnerDirtBase
+  id: DecalSpawnerDirtWide
+  suffix: Dirt, 3 Radius
+  components:
+  - type: RandomDecalSpawner
+    radius: 3
+    maxDecals: 20
+    maxDecalsPerTile: 2
+
+- type: entity
+  parent: DecalSpawnerDirtBase
+  id: DecalSpawnerDirtMonospace
+  suffix: Dirt, Monospace, 1 Radius
+  components:
+  - type: RandomDecalSpawner
+    radius: 1
+    maxDecals: 5
+    decals:
+    - Dirt
+    - DirtHeavyMonotile
+    tileBlacklist:
+    - FloorSteelDiagonal
+    - FloorSteelOffset
+    - FloorSteelDiagonalMini
+    - FloorWhiteDiagonal
+    - FloorWhiteOffset
+    - FloorWhiteDiagonalMini
+    - FloorDarkDiagonal
+    - FloorDarkOffset
+    - FloorDarkDiagonalMini
+    - FloorArcadeBlue
+    - FloorArcadeBlue2
+    - FloorArcadeRed
+    - FloorEighties
+    - FloorCarpetClown
+    - FloorCarpetOffice
+    - FloorBoxing
+    - FloorGym
+    - FloorAstroGrass
+    - FloorMowedAstroGrass
+    - FloorJungleAstroGrass
+    - FloorAstroIce
+    - FloorAstroSnow
+    - FloorAstroAsteroidSand
+    - FloorFlesh
+    - FloorAsteroidSandUnvariantized
+    - FloorAsteroidIronsandUnvariantized
+    - FloorCave
+    - FloorAsteroidIronsand
+    - FloorAsteroidTile
+    - FloorAsteroidSandDug
+    - FloorAsteroidSand
+    - FloorDirt
+    - FloorGrassLight
+    - FloorGrassDark
+    - FloorGrassJungle
+    - FloorGrass
+    - FloorAsphalt
+    - FloorReinforced
+
+- type: entity
+  parent: DecalSpawnerDirtMonospace
+  id: DecalSpawnerBurns
+  suffix: Burns, 1 Radius
+  components:
+  - type: RandomDecalSpawner
+    decals:
+    - burnt1
+    - burnt2
+    - burnt3
+    - burnt4
+    radius: 1
diff --git a/Resources/Prototypes/Entities/Markers/Spawners/Random/Decals/flora.yml b/Resources/Prototypes/Entities/Markers/Spawners/Random/Decals/flora.yml
new file mode 100644 (file)
index 0000000..5164ca7
--- /dev/null
@@ -0,0 +1,183 @@
+- type: entity
+  parent: DecalSpawnerBase
+  id: DecalSpawnerFloraBase
+  abstract: true
+  components:
+  - type: RandomDecalSpawner
+    radius: 0.3
+    zIndex: 1
+    deleteSpawnerAfterSpawn: true
+    tileWhitelist:
+    - FloorAstroGrass
+    - FloorMowedAstroGrass
+    - FloorJungleAstroGrass
+    - FloorAstroIce
+    - FloorAstroSnow
+    - FloorAstroAsteroidSand
+    - FloorAsteroidSandUnvariantized
+    - FloorAsteroidIronsandUnvariantized
+    - FloorCave
+    - FloorAsteroidIronsand
+    - FloorAsteroidTile
+    - FloorAsteroidSandDug
+    - FloorAsteroidSand
+    - FloorDirt
+    - FloorGrassLight
+    - FloorGrassDark
+    - FloorGrassJungle
+    - FloorGrass
+
+- type: entity
+  parent: DecalSpawnerFloraBase
+  id: DecalSpawnerGrassyRock
+  suffix: Grassy Rock
+  components:
+  - type: Sprite
+    layers:
+    - state: green
+    - state: decal
+    - sprite: Decals/Flora/flora_rocks.rsi
+      state: rock01
+  - type: RandomDecalSpawner
+    decals:
+    - Rock01
+    - Rock02
+    - Rock03
+    - Rock04
+    - Rock05
+    - Rock06
+    - Rock07
+
+- type: entity
+  parent: DecalSpawnerFloraBase
+  id: DecalSpawnerBasaltRock
+  suffix: Basalt Rock
+  components:
+  - type: Sprite
+    layers:
+    - state: green
+    - state: decal
+    - sprite: Decals/basalt.rsi
+      state: basalt1
+  - type: RandomDecalSpawner
+    decals:
+    - Basalt1
+    - Basalt2
+    - Basalt3
+    - Basalt4
+    - Basalt5
+    - Basalt6
+    - Basalt7
+    - Basalt8
+    - Basalt9
+
+- type: entity
+  parent: DecalSpawnerFloraBase
+  id: DecalSpawnerBushesAC
+  suffix: Bushes (a-c)
+  components:
+  - type: Sprite
+    layers:
+    - state: green
+    - state: decal
+    - sprite: Decals/Flora/flora_bushes.rsi
+      state: busha1
+  - type: RandomDecalSpawner
+    decals:
+    - Busha1
+    - Busha2
+    - Busha3
+    - Bushb1
+    - Bushb2
+    - Bushb3
+    - Bushc1
+    - Bushc2
+    - Bushc3
+
+# I really don't want to add all the rest of the bushes right now, leaving this as an exercise for someone else.
+
+- type: entity
+  parent: DecalSpawnerFloraBase
+  id: DecalSpawnerFlowers
+  suffix: Flowers
+  components:
+  - type: Sprite
+    layers:
+    - state: green
+    - state: decal
+    - sprite: Decals/Flora/flora_flowers.rsi
+      state: flowersbr1
+  - type: RandomDecalSpawner
+    decals:
+    - Flowersbr1
+    - Flowersbr2
+    - Flowersbr3
+    - Flowerspv1
+    - Flowerspv2
+    - Flowerspv3
+    - Flowersy1
+    - Flowersy2
+    - Flowersy3
+    - Flowersy4
+
+- type: entity
+  parent: DecalSpawnerFloraBase
+  id: DecalSpawnerGrassAB
+  suffix: Grass (a-b)
+  components:
+  - type: Sprite
+    layers:
+    - state: green
+    - state: decal
+    - sprite: Decals/Flora/flora_grass.rsi
+      state: grassa1
+  - type: RandomDecalSpawner
+    decals:
+    - Grassa1
+    - Grassa2
+    - Grassa3
+    - Grassa4
+    - Grassa5
+    - Grassb1
+    - Grassb2
+    - Grassb3
+    - Grassb4
+    - Grassb5
+
+- type: entity
+  parent: DecalSpawnerFloraBase
+  id: DecalSpawnerGrassC
+  suffix: Grass (c)
+  components:
+  - type: Sprite
+    layers:
+    - state: green
+    - state: decal
+    - sprite: Decals/Flora/flora_grass.rsi
+      state: grassc1
+  - type: RandomDecalSpawner
+    decals:
+    - Grassc1
+    - Grassc2
+    - Grassc3
+    - Grassc4
+
+- type: entity
+  parent: DecalSpawnerFloraBase
+  id: DecalSpawnerGrassDE
+  suffix: Grass (d-e)
+  components:
+  - type: Sprite
+    layers:
+    - state: green
+    - state: decal
+    - sprite: Decals/Flora/flora_grass.rsi
+      state: grassd1
+  - type: RandomDecalSpawner
+    decals:
+    - Grassd1
+    - Grassd2
+    - Grassd3
+    - Grasse1
+    - Grasse2
+    - Grasse3
diff --git a/Resources/Prototypes/Entities/Markers/Spawners/Random/Decals/splatters.yml b/Resources/Prototypes/Entities/Markers/Spawners/Random/Decals/splatters.yml
new file mode 100644 (file)
index 0000000..f498616
--- /dev/null
@@ -0,0 +1,102 @@
+- type: entity
+  parent: DecalSpawnerBase
+  id: DecalSpawnerBloodSplatters
+  suffix: Blood Splatters, Footprints
+  components:
+  - type: RandomDecalSpawner
+    decals:
+    - footprint
+    - splatter
+    radius: 1
+    randomRotation: true
+    maxDecals: 3
+    prob: 0.5
+    zIndex: 1
+    color: '#9900007F'
+    cleanable: true
+    deleteSpawnerAfterSpawn: true
+
+- type: entity
+  parent: DecalSpawnerBase
+  id: DecalSpawnerGraffiti
+  suffix: Graffiti
+  components:
+  - type: RandomDecalSpawner
+    decals:
+    - Blasto
+    - Clandestine
+    - Cyber
+    - Diablo
+    - Donk
+    - Gene
+    - Gib
+    - Max
+    - Newton
+    - North
+    - Omni
+    - Osiron
+    - Prima
+    - Psyke
+    - Sirius
+    - Tunnel
+    - Waffle
+    - amyjon
+    - beepsky
+    - biohazard
+    - blueprint
+    - bottle
+    - carp
+    - cat
+    - clown
+    - corgi
+    - credit
+    - cyka
+    - danger
+    - disk
+    - dwarf
+    - end
+    - engie
+    - face
+    - fireaxe
+    - firedanger
+    - ghost
+    - guy
+    - heart
+    - like
+    - matt
+    - peace
+    - prolizard
+    - radiation
+    - revolution
+    - safe
+    - scroll
+    - shotgun
+    - skull
+    - snake
+    - star
+    - stickman
+    - taser
+    - toilet
+    - toolbox
+    - uboa
+    radius: 0.5
+    randomRotation: true
+    maxDecals: 1
+    zIndex: 2
+    randomColorList:
+    - aqua
+    - betterviolet
+    - blue
+    - chartreuse
+    - cyan
+    - deeppink
+    - fuchsia
+    - green
+    - indigo
+    - lime
+    - pink
+    - red
+    - silver
+    - yellow
+    cleanable: true
+    deleteSpawnerAfterSpawn: true
index f5730ab00cdaeefb953753bbc696186a370e075a..6056ac98d61176bd1c08c35cadbb6b76a0a98d36 100644 (file)
       prob: 0.90
     - id: SolarPanelDamageVariationPass
     - id: SolarPanelEmptyVariationPass
+    - id: BasicDecalDirtVariationPass
+    - id: BasicDecalGraffitiVariationPass
+    - id: BasicDecalBrunsVariationPass
+      prob: 0.50
+      orGroup: monospaceDecals
+    - id: BasicDecalDirtMonospaceVariationPass
+      prob: 0.50
+      orGroup: monospaceDecals
index d080965697a00c7b87180d1661ee65798a73f18e..de7a0d7fab7c29766a43013d781e2b4d20d9afdc 100644 (file)
     entities:
     - id: RandomSpawner
 
+- type: entity
+  id: BasicDecalDirtVariationPass
+  parent: BaseVariationPass
+  components:
+  - type: EntitySpawnVariationPass
+    tilesPerEntityAverage: 80
+    tilesPerEntityStdDev: 5
+    entities:
+    - id: DecalSpawnerDirtWide
+
+- type: entity
+  id: BasicDecalGraffitiVariationPass
+  parent: BaseVariationPass
+  components:
+  - type: EntitySpawnVariationPass
+    tilesPerEntityAverage: 120
+    tilesPerEntityStdDev: 5
+    entities:
+    - id: DecalSpawnerGraffiti
+
+- type: entity
+  id: BasicDecalBrunsVariationPass
+  parent: BaseVariationPass
+  components:
+  - type: EntitySpawnVariationPass
+    tilesPerEntityAverage: 120
+    tilesPerEntityStdDev: 10
+    entities:
+    - id: DecalSpawnerBurns
+
+- type: entity
+  id: BasicDecalDirtMonospaceVariationPass
+  parent: BaseVariationPass
+  components:
+  - type: EntitySpawnVariationPass
+    tilesPerEntityAverage: 80
+    tilesPerEntityStdDev: 10
+    entities:
+    - id: DecalSpawnerDirtMonospace
+
 - type: weightedRandomFillSolution
   id: RandomFillTrashPuddle
   fills:
diff --git a/Resources/Textures/Markers/cross.rsi/decal.png b/Resources/Textures/Markers/cross.rsi/decal.png
new file mode 100644 (file)
index 0000000..0db5120
Binary files /dev/null and b/Resources/Textures/Markers/cross.rsi/decal.png differ
index 8ead41b4fbcf06f0cfcf0c91e74159ba93ea0734..9c46093c755e7a4c016a81f5aba5670092a08fd0 100644 (file)
@@ -1,7 +1,7 @@
 {
   "version": 1,
   "license": "CC-BY-SA-3.0",
-  "copyright": "Taken from https://github.com/vgstation-coders/vgstation13/blob/e71d6c4fba5a51f99b81c295dcaec4fc2f58fb19/icons/mob/screen1.dmi - modified to add 'timed'",
+  "copyright": "Taken from https://github.com/vgstation-coders/vgstation13/blob/e71d6c4fba5a51f99b81c295dcaec4fc2f58fb19/icons/mob/screen1.dmi - modified to add 'timed'. 'decal' by Southbridge.",
   "size": {
     "x": 32,
     "y": 32
@@ -24,6 +24,9 @@
     },
     {
       "name": "timed"
+    },
+    {
+      "name": "decal"
     }
   ]
 }