better fluid spreading (#14529)
This commit is contained in:
@@ -3,13 +3,13 @@ using System.Linq;
|
||||
using Content.Server.Fluids.Components;
|
||||
using Content.Shared;
|
||||
using Content.Shared.Directions;
|
||||
using Content.Shared.Maps;
|
||||
using Content.Shared.Physics;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Map.Components;
|
||||
using Robust.Shared.Physics;
|
||||
using Robust.Shared.Utility;
|
||||
using Robust.Shared.Physics.Components;
|
||||
using Robust.Shared.Physics.Systems;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Server.Fluids.EntitySystems;
|
||||
@@ -23,6 +23,8 @@ public sealed class FluidSpreaderSystem : EntitySystem
|
||||
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
||||
[Dependency] private readonly IMapManager _mapManager = default!;
|
||||
[Dependency] private readonly PuddleSystem _puddleSystem = default!;
|
||||
[Dependency] private readonly SharedTransformSystem _transform = default!;
|
||||
[Dependency] private readonly SharedPhysicsSystem _physics = default!;
|
||||
|
||||
/// <summary>
|
||||
/// Adds an overflow component to the map data component tracking overflowing puddles
|
||||
@@ -72,20 +74,19 @@ public sealed class FluidSpreaderSystem : EntitySystem
|
||||
puddles.Clear();
|
||||
var pos = transform.Coordinates;
|
||||
|
||||
var totalVolume = _puddleSystem.CurrentVolume(puddle.Owner, puddle);
|
||||
var totalVolume = _puddleSystem.CurrentVolume(puddleUid, puddle);
|
||||
exploreDirections.Shuffle();
|
||||
foreach (var direction in exploreDirections)
|
||||
{
|
||||
var newPos = pos.Offset(direction);
|
||||
if (CheckTile(puddle.Owner, puddle, newPos, mapGrid,
|
||||
out var puddleComponent))
|
||||
if (CheckTile(puddleUid, puddle, newPos, mapGrid, puddleQuery, out var uid, out var component))
|
||||
{
|
||||
puddles.Add(puddleComponent);
|
||||
totalVolume += _puddleSystem.CurrentVolume(puddleComponent.Owner, puddleComponent);
|
||||
puddles.Add(component);
|
||||
totalVolume += _puddleSystem.CurrentVolume(uid.Value, component);
|
||||
}
|
||||
}
|
||||
|
||||
_puddleSystem.EqualizePuddles(puddle.Owner, puddles, totalVolume, newIteration, puddle);
|
||||
_puddleSystem.EqualizePuddles(puddleUid, puddles, totalVolume, newIteration, puddle);
|
||||
}
|
||||
|
||||
fluidMapData.Puddles.Clear();
|
||||
@@ -100,49 +101,57 @@ public sealed class FluidSpreaderSystem : EntitySystem
|
||||
/// </summary>
|
||||
/// <param name="srcUid">Entity Uid of original puddle</param>
|
||||
/// <param name="srcPuddle">PuddleComponent attached to srcUid</param>
|
||||
/// <param name="pos">at which to check tile</param>
|
||||
/// <param name="dstPos">at which to check tile</param>
|
||||
/// <param name="mapGrid">helper param needed to extract entities</param>
|
||||
/// <param name="puddle">either found or newly created PuddleComponent.</param>
|
||||
/// <param name="newPuddleUid">either found or newly created PuddleComponent.</param>
|
||||
/// <returns>true if tile is empty or occupied by a non-overflowing puddle (or a puddle close to being overflowing)</returns>
|
||||
private bool CheckTile(EntityUid srcUid, PuddleComponent srcPuddle, EntityCoordinates pos, MapGridComponent mapGrid,
|
||||
[NotNullWhen(true)] out PuddleComponent? puddle)
|
||||
private bool CheckTile(EntityUid srcUid, PuddleComponent srcPuddle, EntityCoordinates dstPos,
|
||||
MapGridComponent mapGrid, EntityQuery<PuddleComponent> puddleQuery,
|
||||
[NotNullWhen(true)] out EntityUid? newPuddleUid, [NotNullWhen(true)] out PuddleComponent? newPuddleComp)
|
||||
{
|
||||
if (!mapGrid.TryGetTileRef(pos, out var tileRef)
|
||||
if (!mapGrid.TryGetTileRef(dstPos, out var tileRef)
|
||||
|| tileRef.Tile.IsEmpty)
|
||||
{
|
||||
puddle = null;
|
||||
newPuddleUid = null;
|
||||
newPuddleComp = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
// check if puddle can spread there at all
|
||||
var dstMap = dstPos.ToMap(EntityManager, _transform);
|
||||
var dst = dstMap.Position;
|
||||
var src = Transform(srcUid).MapPosition.Position;
|
||||
var dir = src - dst;
|
||||
var ray = new CollisionRay(dst, dir.Normalized, (int) (CollisionGroup.Impassable | CollisionGroup.HighImpassable));
|
||||
var mapId = dstMap.MapId;
|
||||
var results = _physics.IntersectRay(mapId, ray, dir.Length, returnOnFirstHit: true);
|
||||
if (results.Any())
|
||||
{
|
||||
newPuddleUid = null;
|
||||
newPuddleComp = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
var puddleCurrentVolume = _puddleSystem.CurrentVolume(srcUid, srcPuddle);
|
||||
|
||||
foreach (var entity in mapGrid.GetAnchoredEntities(pos))
|
||||
foreach (var entity in dstPos.GetEntitiesInTile())
|
||||
{
|
||||
// If this is valid puddle check if we spread to it.
|
||||
if (TryComp(entity, out PuddleComponent? existingPuddle))
|
||||
if (puddleQuery.TryGetComponent(entity, out var existingPuddle))
|
||||
{
|
||||
// If current puddle has more volume than current we skip that field
|
||||
if (_puddleSystem.CurrentVolume(existingPuddle.Owner, existingPuddle) >= puddleCurrentVolume)
|
||||
if (_puddleSystem.CurrentVolume(entity, existingPuddle) >= puddleCurrentVolume)
|
||||
{
|
||||
puddle = null;
|
||||
newPuddleUid = null;
|
||||
newPuddleComp = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
puddle = existingPuddle;
|
||||
return true;
|
||||
}
|
||||
|
||||
// if not puddle is this tile blocked by an object like wall or door
|
||||
if (TryComp(entity, out PhysicsComponent? physComponent)
|
||||
&& physComponent.CanCollide
|
||||
&& (physComponent.CollisionLayer & (int) CollisionGroup.MobMask) != 0)
|
||||
{
|
||||
puddle = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
puddle = _puddleSystem.SpawnPuddle(srcUid, pos, srcPuddle);
|
||||
newPuddleUid = entity;
|
||||
newPuddleComp = existingPuddle;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
_puddleSystem.SpawnPuddle(srcUid, dstPos, srcPuddle, out var uid, out var comp);
|
||||
newPuddleUid = uid;
|
||||
newPuddleComp = comp;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -266,17 +266,15 @@ namespace Content.Server.Fluids.EntitySystems
|
||||
return CurrentVolume(uid, puddle) > puddle.OverflowVolume;
|
||||
}
|
||||
|
||||
public PuddleComponent SpawnPuddle(EntityUid srcUid, EntityCoordinates pos, PuddleComponent? srcPuddleComponent = null)
|
||||
public void SpawnPuddle(EntityUid srcUid, EntityCoordinates pos, PuddleComponent srcPuddleComponent, out EntityUid uid, out PuddleComponent component)
|
||||
{
|
||||
MetaDataComponent? metadata = null;
|
||||
Resolve(srcUid, ref srcPuddleComponent, ref metadata);
|
||||
Resolve(srcUid, ref metadata);
|
||||
|
||||
var prototype = metadata?.EntityPrototype?.ID ?? "PuddleSmear"; // TODO Spawn a entity based on another entity
|
||||
|
||||
var destUid = EntityManager.SpawnEntity(prototype, pos);
|
||||
var destPuddle = EntityManager.EnsureComponent<PuddleComponent>(destUid);
|
||||
|
||||
return destPuddle;
|
||||
uid = EntityManager.SpawnEntity(prototype, pos);
|
||||
component = EntityManager.EnsureComponent<PuddleComponent>(uid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user