using Content.Server.Fluids.EntitySystems;
+using Content.Server.Spreader;
using Content.Shared.Audio;
using Content.Shared.Coordinates.Helpers;
using Content.Shared.Database;
var transform = reagentArgs.EntityManager.GetComponent<TransformComponent>(reagentArgs.TargetEntity);
var mapManager = IoCManager.Resolve<IMapManager>();
var mapSys = reagentArgs.EntityManager.System<MapSystem>();
- var sys = reagentArgs.EntityManager.System<TransformSystem>();
+ var spreaderSys = args.EntityManager.System<SpreaderSystem>();
+ var sys = args.EntityManager.System<TransformSystem>();
var mapCoords = sys.GetMapCoordinates(reagentArgs.TargetEntity, xform: transform);
if (!mapManager.TryFindGridAt(mapCoords, out var gridUid, out var grid) ||
- !mapSys.TryGetTileRef(gridUid, grid, transform.Coordinates, out var tileRef) ||
- tileRef.Tile.IsSpace())
+ !mapSys.TryGetTileRef(gridUid, grid, transform.Coordinates, out var tileRef))
{
return;
}
+ if (spreaderSys.RequiresFloorToSpread(_prototypeId) && tileRef.Tile.IsSpace())
+ return;
+
var coords = mapSys.MapToGrid(gridUid, mapCoords);
var ent = reagentArgs.EntityManager.SpawnEntity(_prototypeId, coords.SnapToGrid());
using Content.Shared.Explosion.Components;
using Content.Shared.Explosion.EntitySystems;
using Content.Server.Fluids.EntitySystems;
+using Content.Server.Spreader;
using Content.Shared.Chemistry.Components;
using Content.Shared.Coordinates.Helpers;
using Content.Shared.Maps;
[Dependency] private readonly IMapManager _mapMan = default!;
[Dependency] private readonly SmokeSystem _smoke = default!;
[Dependency] private readonly TransformSystem _transform = default!;
+ [Dependency] private readonly SpreaderSystem _spreader = default!;
public override void Initialize()
{
var mapCoords = _transform.GetMapCoordinates(uid, xform);
if (!_mapMan.TryFindGridAt(mapCoords, out _, out var grid) ||
!grid.TryGetTileRef(xform.Coordinates, out var tileRef) ||
- tileRef.Tile.IsSpace())
+ tileRef.Tile.IsEmpty)
{
return;
}
+ if (_spreader.RequiresFloorToSpread(comp.SmokePrototype.ToString()) && tileRef.Tile.IsSpace())
+ return;
+
var coords = grid.MapToGrid(mapCoords);
var ent = Spawn(comp.SmokePrototype, coords.SnapToGrid());
if (!TryComp<SmokeComponent>(ent, out var smoke))
using Content.Server.Atmos.EntitySystems;
using Content.Server.Shuttles.Components;
using Content.Shared.Atmos;
+using Content.Shared.Maps;
using Content.Shared.Spreader;
using Content.Shared.Tag;
using Robust.Shared.Collections;
/// </summary>
public void GetNeighbors(EntityUid uid, TransformComponent comp, ProtoId<EdgeSpreaderPrototype> prototype, out ValueList<(MapGridComponent, TileRef)> freeTiles, out ValueList<Vector2i> occupiedTiles, out ValueList<EntityUid> neighbors)
{
- // TODO remove occupiedTiles -- its currently unused and just slows this method down.
- DebugTools.Assert(_prototype.HasIndex(prototype));
freeTiles = [];
occupiedTiles = [];
neighbors = [];
+ // TODO remove occupiedTiles -- its currently unused and just slows this method down.
+ if (!_prototype.TryIndex(prototype, out var spreaderPrototype))
+ return;
if (!TryComp<MapGridComponent>(comp.GridUid, out var grid))
return;
if (!_map.TryGetTileRef(neighborEnt, neighborGrid, neighborPos, out var tileRef) || tileRef.Tile.IsEmpty)
continue;
+ if (spreaderPrototype.PreventSpreadOnSpaced && tileRef.Tile.IsSpace())
+ continue;
+
var directionEnumerator = _map.GetAnchoredEntitiesEnumerator(neighborEnt, neighborGrid, neighborPos);
var occupied = false;
}
}
}
+
+ public bool RequiresFloorToSpread(EntProtoId<EdgeSpreaderComponent> spreader)
+ {
+ if (!_prototype.Index(spreader).TryGetComponent<EdgeSpreaderComponent>(out var spreaderComp, EntityManager.ComponentFactory))
+ return false;
+
+ return _prototype.Index(spreaderComp.Id).PreventSpreadOnSpaced;
+ }
}
{
[IdDataField] public string ID { get; } = string.Empty;
[DataField(required:true)] public int UpdatesPerSecond;
+
+ /// <summary>
+ /// If true, this spreader can't spread onto spaced tiles like lattice.
+ /// </summary>
+ [DataField]
+ public bool PreventSpreadOnSpaced = true;
}
--- /dev/null
+using Content.Shared.Maps;
+using Robust.Shared.GameStates;
+using Robust.Shared.Prototypes;
+
+namespace Content.Shared.Tiles;
+
+/// <summary>
+/// Replaces floor tiles around this entity when it spawns
+/// </summary>
+[RegisterComponent, NetworkedComponent, Access(typeof(ReplaceFloorOnSpawnSystem))]
+public sealed partial class ReplaceFloorOnSpawnComponent : Component
+{
+ /// <summary>
+ /// The floor tiles that will be replaced. If null, will replace all.
+ /// </summary>
+ [DataField]
+ public List<ProtoId<ContentTileDefinition>>? ReplaceableTiles = new();
+
+ /// <summary>
+ /// The tiles that it will replace. Randomly picked from the list.
+ /// </summary>
+ [DataField]
+ public List<ProtoId<ContentTileDefinition>> ReplacementTiles = new();
+
+ /// <summary>
+ /// Whether or not there has to be a tile in the location to be replaced.
+ /// </summary>
+ [DataField]
+ public bool ReplaceSpace = true;
+
+ /// <summary>
+ /// List of offsets from the base tile, used to determine which tiles will be replaced.
+ /// </summary>
+ [DataField]
+ public List<Vector2i> Offsets = new() { Vector2i.Up, Vector2i.Down, Vector2i.Left, Vector2i.Right, Vector2i.Zero };
+}
--- /dev/null
+using Robust.Shared.Map;
+using Robust.Shared.Map.Components;
+using Robust.Shared.Prototypes;
+using Robust.Shared.Random;
+
+namespace Content.Shared.Tiles;
+
+public sealed class ReplaceFloorOnSpawnSystem : EntitySystem
+{
+ [Dependency] private readonly ITileDefinitionManager _tile = default!;
+ [Dependency] private readonly IPrototypeManager _prototype = default!;
+ [Dependency] private readonly IRobustRandom _random = default!;
+ [Dependency] private readonly SharedMapSystem _map = default!;
+
+ /// <inheritdoc/>
+ public override void Initialize()
+ {
+ SubscribeLocalEvent<ReplaceFloorOnSpawnComponent, MapInitEvent>(OnMapInit);
+ }
+
+ private void OnMapInit(Entity<ReplaceFloorOnSpawnComponent> ent, ref MapInitEvent args)
+ {
+ var xform = Transform(ent);
+ if (xform.GridUid is not { } grid || !TryComp<MapGridComponent>(grid, out var gridComp))
+ return;
+
+ if (ent.Comp.ReplaceableTiles != null && ent.Comp.ReplaceableTiles.Count == 0)
+ return;
+
+ var tileIndices = _map.LocalToTile(grid, gridComp, xform.Coordinates);
+
+ foreach (var offset in ent.Comp.Offsets)
+ {
+ var actualIndices = tileIndices + offset;
+
+ if (!_map.TryGetTileRef(grid, gridComp, actualIndices, out var tile))
+ continue;
+
+ if (ent.Comp.ReplaceableTiles != null &&
+ !tile.Tile.IsEmpty &&
+ !ent.Comp.ReplaceableTiles.Contains(_tile[tile.Tile.TypeId].ID))
+ continue;
+
+ var tileToSet = _random.Pick(ent.Comp.ReplacementTiles);
+ _map.SetTile(grid, gridComp, tile.GridIndices, new Tile(_prototype.Index(tileToSet).TileId));
+ }
+ }
+}
tiles-silver-tile = silver tile
tiles-glass-floor = glass floor
tiles-reinforced-glass-floor = reinforced glass floor
+tiles-metal-foam = metal foam floor
tiles-green-circuit-floor = green circuit floor
tiles-blue-circuit-floor = blue circuit floor
tiles-snow = snow
tiles-jungle-astro-grass = jungle astro-grass
tiles-astro-ice = astro-ice
tiles-astro-snow = astro-snow
-tiles-wood-large = large wood
\ No newline at end of file
+tiles-wood-large = large wood
category: cargoproduct-category-name-engineering
group: market
+- type: cargoProduct
+ id: EngineeringFoamGrenade
+ icon:
+ sprite: Objects/Weapons/Grenades/metalfoam.rsi
+ state: icon
+ product: CrateEngineeringFoamGrenade
+ cost: 2500
+ category: cargoproduct-category-name-engineering
+ group: market
+
- type: cargoProduct
id: EngineeringCableBulk
icon:
- id: CableHVStack
amount: 3
+- type: entity
+ id: CrateEngineeringFoamGrenade
+ parent: CrateEngineeringSecure
+ name: sealant grenade crate
+ description: 5 metal foam sealant grenades.
+ components:
+ - type: StorageFill
+ contents:
+ - id: MetalFoamGrenade
+ amount: 5
+
- type: entity
id: CrateEngineeringCableBulk
parent: CrateElectrical
state: m_foam-north
- map: [ "enum.EdgeLayer.West" ]
state: m_foam-west
+ - type: EdgeSpreader
+ id: MetalFoam
- type: FoamVisuals
animationTime: 0.6
animationState: m_foam-dissolve
- type: RCDDeconstructable
cost: 2
delay: 2
- fx: EffectRCDDeconstruct2
+ fx: EffectRCDDeconstruct2
- type: Clickable
- type: InteractionOutline
- type: Sprite
- type: Transform
anchored: true
- type: Airtight
+ - type: ReplaceFloorOnSpawn
+ replaceableTiles:
+ - Plating
+ - Lattice
+ - TrainLattice
+ replacementTiles:
+ - FloorMetalFoam
- type: Damageable
damageContainer: Inorganic
damageModifierSet: Metallic
- ReagentId: TearGas
Quantity: 50
+- type: entity
+ parent: SmokeGrenade
+ id: MetalFoamGrenade
+ name: metal foam grenade
+ description: An emergency tool used for patching up holes. Almost as good as real walls.
+ components:
+ - type: Sprite
+ sprite: Objects/Weapons/Grenades/metalfoam.rsi
+ - type: SmokeOnTrigger
+ duration: 10
+ spreadAmount: 13
+ smokePrototype: AluminiumMetalFoam
+ - type: StaticPrice
+ price: 350
+
# Non-explosive "dummy" grenades to use as a distraction.
- type: entity
collection: FootstepHull
itemDrop: FloorTileItemBrassFilled
heatCapacity: 10000
-
+
- type: tile
id: FloorBrassReebe
name: tiles-brass-floor-reebe
itemDrop: SheetRGlass1
heatCapacity: 10000
+- type: tile
+ id: FloorMetalFoam
+ name: tiles-metal-foam
+ sprite: /Textures/Tiles/foammetal.png
+ variants: 1
+ placementVariants:
+ - 1.0
+ baseTurf: Plating
+ isSubfloor: false
+ deconstructTools: [ Prying ]
+ footstepSounds:
+ collection: FootstepHull
+ itemDrop: SheetSteel1
+ heatCapacity: 10000
+
# Circuits
- type: tile
id: FloorGreenCircuit
- type: edgeSpreader
id: Smoke
updatesPerSecond: 8
+
+- type: edgeSpreader
+ id: MetalFoam
+ updatesPerSecond: 16
+ preventSpreadOnSpaced: false
--- /dev/null
+{
+ "version": 1,
+ "license": "CC-BY-SA-3.0",
+ "copyright": "Created by EmoGarbage404",
+ "size": {
+ "x": 32,
+ "y": 32
+ },
+ "states": [
+ {
+ "name": "icon"
+ },
+ {
+ "name": "primed",
+ "delays": [
+ [
+ 0.2,
+ 0.1
+ ]
+ ]
+ },
+ {
+ "name": "equipped-BELT",
+ "directions": 4
+ }
+ ]
+}
copyright: "Modified by github user @Flareguy from plating.png, using damaged plating sprites from /tg/station at commit https://github.com/tgstation/tgstation/blob/6665eec76c98a4f3f89bebcd10b34b47dcc0b8ae/icons/turf/floors.dmi"
source: "https://github.com/space-wizards/space-station-14/pull/21711"
-- files: [ "asteroid_red.png", "asteroid_tile.png", "elevator_shaft.png", "freezer.png", "green_circuit.png", "lino.png", "mono.png", "rock_vault.png", "showroom.png"]
+- files: [ "asteroid_red.png", "asteroid_tile.png", "elevator_shaft.png", "freezer.png", "foammetal.png", "green_circuit.png", "lino.png", "mono.png", "rock_vault.png", "showroom.png"]
license: "CC-BY-SA-3.0"
copyright: "vgstation13 at roughly commit e4d3ea7f69d21c3667be12b114fa935c4640cb05, asteroid_red and asteroid_tile taken from commit /vg/station at commit 02b9f6894af4419c9f7e699a22c402b086d8067e."
source: "https://github.com/vgstation-coders/vgstation13"
-
+
- files: [ "asteroid.png", "asteroid_dug.png", "asteroid0.png"]
license: "CC-BY-SA-3.0"
copyright: "Taken from /tg/station at commit 6665eec76c98a4f3f89bebcd10b34b47dcc0b8ae."
license: "CC-BY-SA-3.0"
copyright: "Modified from plating.png by github user @Flareguy"
source: "https://github.com/space-wizards/space-station-14/"
-
+
- files: ["rglass.png"]
license: "CC-BY-SA-3.0"
copyright: "tgstation commit 8abb19545828230d92ba18827feeb42a67a55d49, rglass modified by github user @notquitehadouken."
license: "CC-BY-SA-3.0"
copyright: "Fortuna commit 2a9408a47e2f83d945335e4feeeeafb552173e6f, grasslight and dirt by Peptide based on grassdark.png and dirt."
source: "https://github.com/FortunaSS13/Fortuna"
-
+
- files: ["steel_maint.png", "grating_maint.png", "wood_tile.png"]
license: "CC-BY-SA-3.0"
copyright: "by brainfood for space-station-14, ."
license: "CC-BY-SA-3.0"
copyright: "taken at https://github.com/ParadiseSS13/Paradise/blob/8b7f4c8b69c74c6de5a755272eb8d3520f3d87c7/icons/turf/floors.dmi"
source: "https://github.com/ParadiseSS13/Paradise"
-
+
- files: ["chromite.png"]
license: "CC-BY-NC-SA-3.0"
copyright: "taken at commit 0587dd16e28108bdf0b0a28e2caae4319845e861, and recolored by TheShuEd"