Spreaders travels across connected grids and SpreaderIgnore tag (#15419)
This commit is contained in:
@@ -86,14 +86,6 @@ public sealed partial class PuddleSystem : SharedPuddleSystem
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var xform = Transform(uid);
|
|
||||||
|
|
||||||
if (!TryComp<MapGridComponent>(xform.GridUid, out var grid))
|
|
||||||
{
|
|
||||||
RemCompDeferred<EdgeSpreaderComponent>(uid);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var puddleQuery = GetEntityQuery<PuddleComponent>();
|
var puddleQuery = GetEntityQuery<PuddleComponent>();
|
||||||
|
|
||||||
// For overflows, we never go to a fully evaporative tile just to avoid continuously having to mop it.
|
// For overflows, we never go to a fully evaporative tile just to avoid continuously having to mop it.
|
||||||
@@ -152,10 +144,10 @@ public sealed partial class PuddleSystem : SharedPuddleSystem
|
|||||||
spillCount = Math.Min(args.NeighborFreeTiles.Count, spillCount);
|
spillCount = Math.Min(args.NeighborFreeTiles.Count, spillCount);
|
||||||
var spillAmount = overflow.Volume / spillCount;
|
var spillAmount = overflow.Volume / spillCount;
|
||||||
|
|
||||||
foreach (var tile in args.NeighborFreeTiles)
|
foreach (var neighbor in args.NeighborFreeTiles)
|
||||||
{
|
{
|
||||||
var split = overflow.SplitSolution(spillAmount);
|
var split = overflow.SplitSolution(spillAmount);
|
||||||
TrySpillAt(grid.GridTileToLocal(tile), split, out _, false);
|
TrySpillAt(neighbor.Grid.GridTileToLocal(neighbor.Tile), split, out _, false);
|
||||||
args.Updates--;
|
args.Updates--;
|
||||||
|
|
||||||
if (args.Updates <= 0)
|
if (args.Updates <= 0)
|
||||||
|
|||||||
@@ -73,7 +73,6 @@ public sealed class SmokeSystem : EntitySystem
|
|||||||
private void OnSmokeSpread(EntityUid uid, SmokeComponent component, ref SpreadNeighborsEvent args)
|
private void OnSmokeSpread(EntityUid uid, SmokeComponent component, ref SpreadNeighborsEvent args)
|
||||||
{
|
{
|
||||||
if (component.SpreadAmount == 0 ||
|
if (component.SpreadAmount == 0 ||
|
||||||
args.Grid == null ||
|
|
||||||
!_solutionSystem.TryGetSolution(uid, SmokeComponent.SolutionName, out var solution) ||
|
!_solutionSystem.TryGetSolution(uid, SmokeComponent.SolutionName, out var solution) ||
|
||||||
args.NeighborFreeTiles.Count == 0)
|
args.NeighborFreeTiles.Count == 0)
|
||||||
{
|
{
|
||||||
@@ -94,9 +93,9 @@ public sealed class SmokeSystem : EntitySystem
|
|||||||
var smokePerSpread = component.SpreadAmount / args.NeighborFreeTiles.Count;
|
var smokePerSpread = component.SpreadAmount / args.NeighborFreeTiles.Count;
|
||||||
component.SpreadAmount -= smokePerSpread;
|
component.SpreadAmount -= smokePerSpread;
|
||||||
|
|
||||||
foreach (var tile in args.NeighborFreeTiles)
|
foreach (var neighbor in args.NeighborFreeTiles)
|
||||||
{
|
{
|
||||||
var coords = args.Grid.GridTileToLocal(tile);
|
var coords = neighbor.Grid.GridTileToLocal(neighbor.Tile);
|
||||||
var ent = Spawn(prototype.ID, coords.SnapToGrid());
|
var ent = Spawn(prototype.ID, coords.SnapToGrid());
|
||||||
var neighborSmoke = EnsureComp<SmokeComponent>(ent);
|
var neighborSmoke = EnsureComp<SmokeComponent>(ent);
|
||||||
neighborSmoke.SpreadAmount = Math.Max(0, smokePerSpread - 1);
|
neighborSmoke.SpreadAmount = Math.Max(0, smokePerSpread - 1);
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ public sealed class KudzuSystem : EntitySystem
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args.NeighborFreeTiles.Count == 0 || args.Grid == null)
|
if (args.NeighborFreeTiles.Count == 0)
|
||||||
{
|
{
|
||||||
RemCompDeferred<EdgeSpreaderComponent>(uid);
|
RemCompDeferred<EdgeSpreaderComponent>(uid);
|
||||||
return;
|
return;
|
||||||
@@ -47,7 +47,7 @@ public sealed class KudzuSystem : EntitySystem
|
|||||||
|
|
||||||
foreach (var neighbor in args.NeighborFreeTiles)
|
foreach (var neighbor in args.NeighborFreeTiles)
|
||||||
{
|
{
|
||||||
var neighborUid = Spawn(prototype, args.Grid.GridTileToLocal(neighbor));
|
var neighborUid = Spawn(prototype, neighbor.Grid.GridTileToLocal(neighbor.Tile));
|
||||||
EnsureComp<EdgeSpreaderComponent>(neighborUid);
|
EnsureComp<EdgeSpreaderComponent>(neighborUid);
|
||||||
args.Updates--;
|
args.Updates--;
|
||||||
|
|
||||||
|
|||||||
@@ -10,9 +10,7 @@ namespace Content.Server.Spreader;
|
|||||||
[ByRefEvent]
|
[ByRefEvent]
|
||||||
public record struct SpreadNeighborsEvent
|
public record struct SpreadNeighborsEvent
|
||||||
{
|
{
|
||||||
public MapGridComponent? Grid;
|
public ValueList<(MapGridComponent Grid, Vector2i Tile)> NeighborFreeTiles;
|
||||||
public ValueList<Vector2i> NeighborFreeTiles;
|
|
||||||
public ValueList<Vector2i> NeighborOccupiedTiles;
|
|
||||||
public ValueList<EntityUid> Neighbors;
|
public ValueList<EntityUid> Neighbors;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -2,8 +2,10 @@ using Content.Server.Atmos.Components;
|
|||||||
using Content.Server.Atmos.EntitySystems;
|
using Content.Server.Atmos.EntitySystems;
|
||||||
using Content.Server.NodeContainer;
|
using Content.Server.NodeContainer;
|
||||||
using Content.Server.NodeContainer.NodeGroups;
|
using Content.Server.NodeContainer.NodeGroups;
|
||||||
|
using Content.Server.Shuttles.Components;
|
||||||
using Content.Shared.Atmos;
|
using Content.Shared.Atmos;
|
||||||
using Content.Shared.Spreader;
|
using Content.Shared.Spreader;
|
||||||
|
using Content.Shared.Tag;
|
||||||
using Robust.Shared.Collections;
|
using Robust.Shared.Collections;
|
||||||
using Robust.Shared.Map;
|
using Robust.Shared.Map;
|
||||||
using Robust.Shared.Map.Components;
|
using Robust.Shared.Map.Components;
|
||||||
@@ -27,6 +29,8 @@ public sealed class SpreaderSystem : EntitySystem
|
|||||||
|
|
||||||
private readonly List<string> _spreaderGroups = new();
|
private readonly List<string> _spreaderGroups = new();
|
||||||
|
|
||||||
|
private const string IgnoredTag = "SpreaderIgnore";
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
@@ -178,15 +182,11 @@ public sealed class SpreaderSystem : EntitySystem
|
|||||||
|
|
||||||
private void Spread(EntityUid uid, SpreaderNode node, INodeGroup group, ref int updates)
|
private void Spread(EntityUid uid, SpreaderNode node, INodeGroup group, ref int updates)
|
||||||
{
|
{
|
||||||
GetNeighbors(uid, node.Name, out var freeTiles, out var occupiedTiles, out var neighbors);
|
GetNeighbors(uid, node.Name, out var freeTiles, out _, out var neighbors);
|
||||||
|
|
||||||
TryComp<MapGridComponent>(Transform(uid).GridUid, out var grid);
|
|
||||||
|
|
||||||
var ev = new SpreadNeighborsEvent()
|
var ev = new SpreadNeighborsEvent()
|
||||||
{
|
{
|
||||||
Grid = grid,
|
|
||||||
NeighborFreeTiles = freeTiles,
|
NeighborFreeTiles = freeTiles,
|
||||||
NeighborOccupiedTiles = occupiedTiles,
|
|
||||||
Neighbors = neighbors,
|
Neighbors = neighbors,
|
||||||
Updates = updates,
|
Updates = updates,
|
||||||
};
|
};
|
||||||
@@ -198,9 +198,9 @@ public sealed class SpreaderSystem : EntitySystem
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the neighboring node data for the specified entity and the specified node group.
|
/// Gets the neighboring node data for the specified entity and the specified node group.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void GetNeighbors(EntityUid uid, string groupName, out ValueList<Vector2i> freeTiles, out ValueList<Vector2i> occupiedTiles, out ValueList<EntityUid> neighbors)
|
public void GetNeighbors(EntityUid uid, string groupName, out ValueList<(MapGridComponent Grid, Vector2i Tile)> freeTiles, out ValueList<Vector2i> occupiedTiles, out ValueList<EntityUid> neighbors)
|
||||||
{
|
{
|
||||||
freeTiles = new ValueList<Vector2i>();
|
freeTiles = new ValueList<(MapGridComponent Grid, Vector2i Tile)>();
|
||||||
occupiedTiles = new ValueList<Vector2i>();
|
occupiedTiles = new ValueList<Vector2i>();
|
||||||
neighbors = new ValueList<EntityUid>();
|
neighbors = new ValueList<EntityUid>();
|
||||||
|
|
||||||
@@ -213,47 +213,82 @@ public sealed class SpreaderSystem : EntitySystem
|
|||||||
var tile = grid.TileIndicesFor(transform.Coordinates);
|
var tile = grid.TileIndicesFor(transform.Coordinates);
|
||||||
var nodeQuery = GetEntityQuery<NodeContainerComponent>();
|
var nodeQuery = GetEntityQuery<NodeContainerComponent>();
|
||||||
var airtightQuery = GetEntityQuery<AirtightComponent>();
|
var airtightQuery = GetEntityQuery<AirtightComponent>();
|
||||||
|
var dockQuery = GetEntityQuery<DockingComponent>();
|
||||||
|
var xformQuery = GetEntityQuery<TransformComponent>();
|
||||||
|
var tagQuery = GetEntityQuery<TagComponent>();
|
||||||
|
var blockedAtmosDirs = AtmosDirection.Invalid;
|
||||||
|
|
||||||
|
// Due to docking ports they may not necessarily be opposite directions.
|
||||||
|
var neighborTiles = new ValueList<(MapGridComponent grid, Vector2i Indices, AtmosDirection OtherDir, AtmosDirection OurDir)>();
|
||||||
|
|
||||||
|
// Check if anything on our own tile blocking that direction.
|
||||||
|
var ourEnts = grid.GetAnchoredEntitiesEnumerator(tile);
|
||||||
|
|
||||||
|
while (ourEnts.MoveNext(out var ent))
|
||||||
|
{
|
||||||
|
// Spread via docks in a special-case.
|
||||||
|
if (dockQuery.TryGetComponent(ent, out var dock) &&
|
||||||
|
dock.Docked &&
|
||||||
|
xformQuery.TryGetComponent(ent, out var xform) &&
|
||||||
|
xformQuery.TryGetComponent(dock.DockedWith, out var dockedXform) &&
|
||||||
|
TryComp<MapGridComponent>(dockedXform.GridUid, out var dockedGrid))
|
||||||
|
{
|
||||||
|
neighborTiles.Add((dockedGrid, dockedGrid.CoordinatesToTile(dockedXform.Coordinates), xform.LocalRotation.ToAtmosDirection(), dockedXform.LocalRotation.ToAtmosDirection()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we're on a blocked tile work out which directions we can go.
|
||||||
|
if (!airtightQuery.TryGetComponent(ent, out var airtight) || !airtight.AirBlocked ||
|
||||||
|
tagQuery.TryGetComponent(ent, out var tags) && tags.Tags.Contains(IgnoredTag))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var value in new[] { AtmosDirection.North, AtmosDirection.East, AtmosDirection.South, AtmosDirection.West})
|
||||||
|
{
|
||||||
|
if ((value & airtight.AirBlockedDirection) == 0x0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
blockedAtmosDirs |= value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the normal neighbors.
|
||||||
for (var i = 0; i < 4; i++)
|
for (var i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
var direction = (Direction) (i * 2);
|
var direction = (Direction) (i * 2);
|
||||||
|
var atmosDir = direction.ToAtmosDirection();
|
||||||
var neighborPos = SharedMapSystem.GetDirection(tile, direction);
|
var neighborPos = SharedMapSystem.GetDirection(tile, direction);
|
||||||
|
neighborTiles.Add((grid, neighborPos, atmosDir, atmosDir.GetOpposite()));
|
||||||
|
}
|
||||||
|
|
||||||
if (!grid.TryGetTileRef(neighborPos, out var tileRef) || tileRef.Tile.IsEmpty)
|
foreach (var (neighborGrid, neighborPos, ourAtmosDir, otherAtmosDir) in neighborTiles)
|
||||||
|
{
|
||||||
|
// This tile is blocked to that direction.
|
||||||
|
if ((blockedAtmosDirs & ourAtmosDir) != 0x0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!neighborGrid.TryGetTileRef(neighborPos, out var tileRef) || tileRef.Tile.IsEmpty)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var directionEnumerator =
|
var directionEnumerator =
|
||||||
grid.GetAnchoredEntitiesEnumerator(neighborPos);
|
neighborGrid.GetAnchoredEntitiesEnumerator(neighborPos);
|
||||||
var occupied = false;
|
var occupied = false;
|
||||||
|
|
||||||
while (directionEnumerator.MoveNext(out var ent))
|
while (directionEnumerator.MoveNext(out var ent))
|
||||||
{
|
{
|
||||||
if (airtightQuery.TryGetComponent(ent, out var airtight) && airtight.AirBlocked)
|
if (!airtightQuery.TryGetComponent(ent, out var airtight) || !airtight.AirBlocked ||
|
||||||
|
tagQuery.TryGetComponent(ent, out var tags) && tags.Tags.Contains(IgnoredTag))
|
||||||
{
|
{
|
||||||
// Check if air direction matters.
|
continue;
|
||||||
var blocked = false;
|
|
||||||
|
|
||||||
foreach (var value in new[] { AtmosDirection.North, AtmosDirection.East})
|
|
||||||
{
|
|
||||||
if ((value & airtight.AirBlockedDirection) == 0x0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
var airDirection = value.ToDirection();
|
|
||||||
var oppositeDirection = value.ToDirection().GetOpposite();
|
|
||||||
|
|
||||||
if (direction != airDirection && direction != oppositeDirection)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
blocked = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!blocked)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
occupied = true;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((airtight.AirBlockedDirection & otherAtmosDir) == 0x0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
occupied = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (occupied)
|
if (occupied)
|
||||||
@@ -261,7 +296,7 @@ public sealed class SpreaderSystem : EntitySystem
|
|||||||
|
|
||||||
var oldCount = occupiedTiles.Count;
|
var oldCount = occupiedTiles.Count;
|
||||||
directionEnumerator =
|
directionEnumerator =
|
||||||
grid.GetAnchoredEntitiesEnumerator(neighborPos);
|
neighborGrid.GetAnchoredEntitiesEnumerator(neighborPos);
|
||||||
|
|
||||||
while (directionEnumerator.MoveNext(out var ent))
|
while (directionEnumerator.MoveNext(out var ent))
|
||||||
{
|
{
|
||||||
@@ -277,7 +312,7 @@ public sealed class SpreaderSystem : EntitySystem
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (oldCount == occupiedTiles.Count)
|
if (oldCount == occupiedTiles.Count)
|
||||||
freeTiles.Add(neighborPos);
|
freeTiles.Add((neighborGrid, neighborPos));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -43,10 +43,7 @@
|
|||||||
path: /Audio/Machines/airlock_deny.ogg
|
path: /Audio/Machines/airlock_deny.ogg
|
||||||
- type: Airtight
|
- type: Airtight
|
||||||
fixVacuum: true
|
fixVacuum: true
|
||||||
airBlockedDirection:
|
noAirWhenFullyAirBlocked: false
|
||||||
- East
|
|
||||||
- West
|
|
||||||
- South
|
|
||||||
- type: Tag
|
- type: Tag
|
||||||
tags:
|
tags:
|
||||||
- ForceNoFixRotations
|
- ForceNoFixRotations
|
||||||
|
|||||||
@@ -22,3 +22,6 @@
|
|||||||
- type: Airtight
|
- type: Airtight
|
||||||
noAirWhenFullyAirBlocked: false
|
noAirWhenFullyAirBlocked: false
|
||||||
- type: Clickable
|
- type: Clickable
|
||||||
|
- type: Tag
|
||||||
|
tags:
|
||||||
|
- SpreaderIgnore
|
||||||
|
|||||||
@@ -607,6 +607,9 @@
|
|||||||
- type: Tag
|
- type: Tag
|
||||||
id: SpeedLoaderRifle
|
id: SpeedLoaderRifle
|
||||||
|
|
||||||
|
- type: Tag
|
||||||
|
id: SpreaderIgnore
|
||||||
|
|
||||||
- type: Tag
|
- type: Tag
|
||||||
id: StringInstrument
|
id: StringInstrument
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user