Fixes singularity collision and consume range (#13424)
Co-authored-by: keronshb <keronshb@live.com>
This commit is contained in:
@@ -390,11 +390,11 @@ public sealed class ContainmentFieldGeneratorSystem : EntitySystem
|
|||||||
/// <param name="uid">The entity the singularity is trying to eat.</param>
|
/// <param name="uid">The entity the singularity is trying to eat.</param>
|
||||||
/// <param name="comp">The containment field generator the singularity is trying to eat.</param>
|
/// <param name="comp">The containment field generator the singularity is trying to eat.</param>
|
||||||
/// <param name="args">The event arguments.</param>
|
/// <param name="args">The event arguments.</param>
|
||||||
private void PreventBreach(EntityUid uid, ContainmentFieldGeneratorComponent comp, EventHorizonAttemptConsumeEntityEvent args)
|
private void PreventBreach(EntityUid uid, ContainmentFieldGeneratorComponent comp, ref EventHorizonAttemptConsumeEntityEvent args)
|
||||||
{
|
{
|
||||||
if (args.Cancelled)
|
if (args.Cancelled)
|
||||||
return;
|
return;
|
||||||
if (comp.IsConnected && !args.EventHorizon.CanBreachContainment)
|
if (comp.IsConnected && !args.EventHorizon.CanBreachContainment)
|
||||||
args.Cancel();
|
args.Cancelled = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,9 +41,9 @@ public sealed class ContainmentFieldSystem : EntitySystem
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandleEventHorizon(EntityUid uid, ContainmentFieldComponent component, EventHorizonAttemptConsumeEntityEvent args)
|
private void HandleEventHorizon(EntityUid uid, ContainmentFieldComponent component, ref EventHorizonAttemptConsumeEntityEvent args)
|
||||||
{
|
{
|
||||||
if(!args.Cancelled && !args.EventHorizon.CanBreachContainment)
|
if(!args.Cancelled && !args.EventHorizon.CanBreachContainment)
|
||||||
args.Cancel();
|
args.Cancelled = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +1,19 @@
|
|||||||
using System.Numerics;
|
|
||||||
using Content.Server.Administration.Logs;
|
using Content.Server.Administration.Logs;
|
||||||
|
using Content.Server.Ghost.Components;
|
||||||
|
using Content.Server.Mind.Components;
|
||||||
|
using Content.Server.Station.Components;
|
||||||
|
using Content.Server.Singularity.Events;
|
||||||
|
using Content.Shared.Database;
|
||||||
|
using Content.Shared.Singularity.Components;
|
||||||
|
using Content.Shared.Singularity.EntitySystems;
|
||||||
|
using Content.Shared.Tag;
|
||||||
using Robust.Shared.Containers;
|
using Robust.Shared.Containers;
|
||||||
using Robust.Shared.Timing;
|
using Robust.Shared.Timing;
|
||||||
using Robust.Shared.Map;
|
using Robust.Shared.Map;
|
||||||
using Robust.Shared.Map.Components;
|
using Robust.Shared.Map.Components;
|
||||||
using Robust.Shared.Physics.Events;
|
using Robust.Shared.Physics.Events;
|
||||||
|
using System.Numerics;
|
||||||
|
|
||||||
using Content.Shared.Singularity.Components;
|
|
||||||
using Content.Shared.Singularity.EntitySystems;
|
|
||||||
|
|
||||||
using Content.Server.Ghost.Components;
|
|
||||||
using Content.Server.Mind.Components;
|
|
||||||
using Content.Server.Station.Components;
|
|
||||||
using Content.Server.Singularity.Components;
|
|
||||||
using Content.Server.Singularity.Events;
|
|
||||||
using Content.Shared.Database;
|
|
||||||
using Content.Shared.Tag;
|
|
||||||
|
|
||||||
namespace Content.Server.Singularity.EntitySystems;
|
namespace Content.Server.Singularity.EntitySystems;
|
||||||
|
|
||||||
@@ -31,19 +29,10 @@ public sealed class EventHorizonSystem : SharedEventHorizonSystem
|
|||||||
[Dependency] private readonly IMapManager _mapMan = default!;
|
[Dependency] private readonly IMapManager _mapMan = default!;
|
||||||
[Dependency] private readonly IAdminLogManager _adminLogger = default!;
|
[Dependency] private readonly IAdminLogManager _adminLogger = default!;
|
||||||
[Dependency] private readonly SharedContainerSystem _containerSystem = default!;
|
[Dependency] private readonly SharedContainerSystem _containerSystem = default!;
|
||||||
|
[Dependency] private readonly SharedTransformSystem _xformSystem = default!;
|
||||||
[Dependency] private readonly TagSystem _tagSystem = default!;
|
[Dependency] private readonly TagSystem _tagSystem = default!;
|
||||||
#endregion Dependencies
|
#endregion Dependencies
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The maximum number of nested containers an event horizon is allowed to eat through in an attempt to get to the map.
|
|
||||||
/// </summary>
|
|
||||||
private const int MaxEventHorizonUnnestingIterations = 100;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The maximum number of nested containers an immune entity in a container being consumed by an event horizon is allowed to search through before it gives up and just jumps to the map.
|
|
||||||
/// </summary>
|
|
||||||
private const int MaxEventHorizonDumpSearchIterations = 100;
|
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
base.Initialize();
|
base.Initialize();
|
||||||
@@ -74,26 +63,20 @@ public sealed class EventHorizonSystem : SharedEventHorizonSystem
|
|||||||
/// Updates the cooldowns of all event horizons.
|
/// Updates the cooldowns of all event horizons.
|
||||||
/// If an event horizon are off cooldown this makes it consume everything within range and resets their cooldown.
|
/// If an event horizon are off cooldown this makes it consume everything within range and resets their cooldown.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="frameTime">The amount of time that has elapsed since the last cooldown update.</param>
|
|
||||||
public override void Update(float frameTime)
|
public override void Update(float frameTime)
|
||||||
{
|
{
|
||||||
if(!_timing.IsFirstTimePredicted)
|
var query = EntityQueryEnumerator<EventHorizonComponent, TransformComponent>();
|
||||||
return;
|
while (query.MoveNext(out var uid, out var eventHorizon, out var xform))
|
||||||
|
|
||||||
foreach(var (eventHorizon, xform) in EntityManager.EntityQuery<EventHorizonComponent, TransformComponent>())
|
|
||||||
{
|
{
|
||||||
var curTime = _timing.CurTime;
|
var curTime = _timing.CurTime;
|
||||||
if (eventHorizon.NextConsumeWaveTime <= curTime)
|
if (eventHorizon.NextConsumeWaveTime <= curTime)
|
||||||
Update(eventHorizon.Owner, eventHorizon, xform);
|
Update(uid, eventHorizon, xform);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Makes an event horizon consume everything nearby and resets the cooldown it for the next automated wave.
|
/// Makes an event horizon consume everything nearby and resets the cooldown it for the next automated wave.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="uid">The uid of the event horizon consuming everything nearby.</param>
|
|
||||||
/// <param name="eventHorizon">The event horizon we want to consume nearby things.</param>
|
|
||||||
/// <param name="xform">The transform of the event horizon.</param>
|
|
||||||
public void Update(EntityUid uid, EventHorizonComponent? eventHorizon = null, TransformComponent? xform = null)
|
public void Update(EntityUid uid, EventHorizonComponent? eventHorizon = null, TransformComponent? xform = null)
|
||||||
{
|
{
|
||||||
if (!Resolve(uid, ref eventHorizon))
|
if (!Resolve(uid, ref eventHorizon))
|
||||||
@@ -108,14 +91,15 @@ public sealed class EventHorizonSystem : SharedEventHorizonSystem
|
|||||||
|
|
||||||
// Handle singularities some admin smited into a locker.
|
// Handle singularities some admin smited into a locker.
|
||||||
if (_containerSystem.TryGetContainingContainer(uid, out var container, transform: xform)
|
if (_containerSystem.TryGetContainingContainer(uid, out var container, transform: xform)
|
||||||
&& !AttemptConsumeEntity(container.Owner, eventHorizon))
|
&& !AttemptConsumeEntity(uid, container.Owner, eventHorizon))
|
||||||
{
|
{
|
||||||
|
// Locker is indestructible. Consume everything else in the locker instead of magically teleporting out.
|
||||||
ConsumeEntitiesInContainer(uid, container, eventHorizon, container);
|
ConsumeEntitiesInContainer(uid, container, eventHorizon, container);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (eventHorizon.Radius > 0.0f)
|
if (eventHorizon.Radius > 0.0f)
|
||||||
ConsumeEverythingInRange(xform.Owner, eventHorizon.Radius, xform, eventHorizon);
|
ConsumeEverythingInRange(uid, eventHorizon.Radius, xform, eventHorizon);
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Consume
|
#region Consume
|
||||||
@@ -125,48 +109,42 @@ public sealed class EventHorizonSystem : SharedEventHorizonSystem
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Makes an event horizon consume a given entity.
|
/// Makes an event horizon consume a given entity.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="uid">The entity to consume.</param>
|
public void ConsumeEntity(EntityUid hungry, EntityUid morsel, EventHorizonComponent eventHorizon, IContainer? outerContainer = null)
|
||||||
/// <param name="eventHorizon">The event horizon consuming the given entity.</param>
|
|
||||||
/// <param name="outerContainer">The innermost container of the entity to consume that isn't also being consumed by the event horizon.</param>
|
|
||||||
public void ConsumeEntity(EntityUid uid, EventHorizonComponent eventHorizon, IContainer? outerContainer = null)
|
|
||||||
{
|
{
|
||||||
var eventHorizonOwner = eventHorizon.Owner;
|
if (!EntityManager.IsQueuedForDeletion(morsel) // I saw it log twice a few times for some reason?
|
||||||
|
&& (HasComp<MindContainerComponent>(morsel)
|
||||||
|
|| _tagSystem.HasTag(morsel, "HighRiskItem")
|
||||||
|
|| HasComp<ContainmentFieldGeneratorComponent>(morsel)))
|
||||||
|
{
|
||||||
|
_adminLogger.Add(LogType.EntityDelete, LogImpact.Extreme, $"{ToPrettyString(morsel)} entered the event horizon of {ToPrettyString(hungry)} and was deleted");
|
||||||
|
}
|
||||||
|
|
||||||
if (!EntityManager.IsQueuedForDeletion(uid) && // I saw it log twice a few times for some reason?
|
EntityManager.QueueDeleteEntity(morsel);
|
||||||
(HasComp<MindContainerComponent>(uid) ||
|
var evSelf = new EntityConsumedByEventHorizonEvent(morsel, hungry, eventHorizon, outerContainer);
|
||||||
_tagSystem.HasTag(uid, "HighRiskItem") ||
|
var evEaten = new EventHorizonConsumedEntityEvent(morsel, hungry, eventHorizon, outerContainer);
|
||||||
HasComp<ContainmentFieldGeneratorComponent>(uid)))
|
RaiseLocalEvent(hungry, ref evSelf);
|
||||||
_adminLogger.Add(LogType.EntityDelete, LogImpact.Extreme, $"{ToPrettyString(uid)} entered the event horizon of {ToPrettyString(eventHorizonOwner)} and was deleted");
|
RaiseLocalEvent(morsel, ref evEaten);
|
||||||
|
|
||||||
EntityManager.QueueDeleteEntity(uid);
|
|
||||||
RaiseLocalEvent(eventHorizonOwner, new EntityConsumedByEventHorizonEvent(uid, eventHorizon, outerContainer));
|
|
||||||
RaiseLocalEvent(uid, new EventHorizonConsumedEntityEvent(uid, eventHorizon, outerContainer));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Makes an event horizon attempt to consume a given entity.
|
/// Makes an event horizon attempt to consume a given entity.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="uid">The entity to attempt to consume.</param>
|
public bool AttemptConsumeEntity(EntityUid hungry, EntityUid morsel, EventHorizonComponent eventHorizon, IContainer? outerContainer = null)
|
||||||
/// <param name="eventHorizon">The event horizon attempting to consume the given entity.</param>
|
|
||||||
/// <param name="outerContainer">The innermost container of the entity to consume that isn't also being consumed by the event horizon.</param>
|
|
||||||
public bool AttemptConsumeEntity(EntityUid uid, EventHorizonComponent eventHorizon, IContainer? outerContainer = null)
|
|
||||||
{
|
{
|
||||||
if(!CanConsumeEntity(uid, eventHorizon))
|
if (!CanConsumeEntity(hungry, morsel, eventHorizon))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
ConsumeEntity(uid, eventHorizon, outerContainer);
|
ConsumeEntity(hungry, morsel, eventHorizon, outerContainer);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Checks whether an event horizon can consume a given entity.
|
/// Checks whether an event horizon can consume a given entity.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="uid">The entity to check for consumability.</param>
|
public bool CanConsumeEntity(EntityUid hungry, EntityUid uid, EventHorizonComponent eventHorizon)
|
||||||
/// <param name="eventHorizon">The event horizon checking whether it can consume the entity.</param>
|
|
||||||
public bool CanConsumeEntity(EntityUid uid, EventHorizonComponent eventHorizon)
|
|
||||||
{
|
{
|
||||||
var ev = new EventHorizonAttemptConsumeEntityEvent(uid, eventHorizon);
|
var ev = new EventHorizonAttemptConsumeEntityEvent(uid, hungry, eventHorizon);
|
||||||
RaiseLocalEvent(uid, ev);
|
RaiseLocalEvent(uid, ref ev);
|
||||||
return !ev.Cancelled;
|
return !ev.Cancelled;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,21 +152,27 @@ public sealed class EventHorizonSystem : SharedEventHorizonSystem
|
|||||||
/// Attempts to consume all entities within a given distance of an entity;
|
/// Attempts to consume all entities within a given distance of an entity;
|
||||||
/// Excludes the center entity.
|
/// Excludes the center entity.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="uid">The entity uid in the center of the region to consume all entities within.</param>
|
|
||||||
/// <param name="range">The distance of the center entity within which to consume all entities.</param>
|
|
||||||
/// <param name="xform">The transform component attached to the center entity.</param>
|
|
||||||
/// <param name="eventHorizon">The event horizon component attached to the center entity.</param>
|
|
||||||
public void ConsumeEntitiesInRange(EntityUid uid, float range, TransformComponent? xform = null, EventHorizonComponent? eventHorizon = null)
|
public void ConsumeEntitiesInRange(EntityUid uid, float range, TransformComponent? xform = null, EventHorizonComponent? eventHorizon = null)
|
||||||
{
|
{
|
||||||
if (!Resolve(uid, ref xform, ref eventHorizon))
|
if (!Resolve(uid, ref xform, ref eventHorizon))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
var range2 = range * range;
|
||||||
|
var xformQuery = EntityManager.GetEntityQuery<TransformComponent>();
|
||||||
|
var epicenter = _xformSystem.GetWorldPosition(xform, xformQuery);
|
||||||
foreach (var entity in _lookup.GetEntitiesInRange(xform.MapPosition, range, flags: LookupFlags.Uncontained))
|
foreach (var entity in _lookup.GetEntitiesInRange(xform.MapPosition, range, flags: LookupFlags.Uncontained))
|
||||||
{
|
{
|
||||||
if (entity == uid)
|
if (entity == uid)
|
||||||
continue;
|
continue;
|
||||||
|
if (!xformQuery.TryGetComponent(entity, out var entityXform))
|
||||||
|
continue;
|
||||||
|
|
||||||
AttemptConsumeEntity(entity, eventHorizon);
|
// GetEntitiesInRange gets everything in a _square_ centered on the given position, but we are a _circle_. If we don't have this check and the station is rotated it is possible for the singularity to reach _outside of the containment field_ and eat the emitters.
|
||||||
|
var displacement = _xformSystem.GetWorldPosition(entityXform, xformQuery) - epicenter;
|
||||||
|
if (displacement.LengthSquared() > range2)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
AttemptConsumeEntity(uid, entity, eventHorizon);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -197,22 +181,19 @@ public sealed class EventHorizonSystem : SharedEventHorizonSystem
|
|||||||
/// Excludes the event horizon itself.
|
/// Excludes the event horizon itself.
|
||||||
/// All immune entities within the container will be dumped to a given container or the map/grid if that is impossible.
|
/// All immune entities within the container will be dumped to a given container or the map/grid if that is impossible.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="uid">The uid of the event horizon. The single entity that is immune-by-default.</param>
|
public void ConsumeEntitiesInContainer(EntityUid hungry, IContainer container, EventHorizonComponent eventHorizon, IContainer? outerContainer = null)
|
||||||
/// <param name="container">The container within which to consume all entities.</param>
|
{
|
||||||
/// <param name="eventHorizon">The state of the event horizon.</param>
|
|
||||||
/// <param name="outerContainer">The location any immune entities within the container should be dumped to.</param>
|
|
||||||
public void ConsumeEntitiesInContainer(EntityUid uid, IContainer container, EventHorizonComponent eventHorizon, IContainer? outerContainer = null) {
|
|
||||||
// Removing the immune entities from the container needs to be deferred until after iteration or the iterator raises an error.
|
// Removing the immune entities from the container needs to be deferred until after iteration or the iterator raises an error.
|
||||||
List<EntityUid> immune = new();
|
List<EntityUid> immune = new();
|
||||||
|
|
||||||
foreach (var entity in container.ContainedEntities)
|
foreach (var entity in container.ContainedEntities)
|
||||||
{
|
{
|
||||||
if (entity == uid || !AttemptConsumeEntity(entity, eventHorizon, outerContainer))
|
if (entity == hungry || !AttemptConsumeEntity(hungry, entity, eventHorizon, outerContainer))
|
||||||
immune.Add(entity); // The first check keeps singularities an admin smited into a locker from consuming themselves.
|
immune.Add(entity); // The first check keeps singularities an admin smited into a locker from consuming themselves.
|
||||||
// The second check keeps things that have been rendered immune to singularities from being deleted by a singularity eating their container.
|
// The second check keeps things that have been rendered immune to singularities from being deleted by a singularity eating their container.
|
||||||
}
|
}
|
||||||
|
|
||||||
if (outerContainer == container)
|
if (outerContainer == container || immune.Count <= 0)
|
||||||
return; // The container we are intended to drop immune things to is the same container we are consuming everything in
|
return; // The container we are intended to drop immune things to is the same container we are consuming everything in
|
||||||
// it's a safe bet that we aren't consuming the container entity so there's no reason to eject anything from this container.
|
// it's a safe bet that we aren't consuming the container entity so there's no reason to eject anything from this container.
|
||||||
|
|
||||||
@@ -231,7 +212,7 @@ public sealed class EventHorizonSystem : SharedEventHorizonSystem
|
|||||||
|
|
||||||
// If we couldn't or there was no container to insert into just dump them to the map/grid.
|
// If we couldn't or there was no container to insert into just dump them to the map/grid.
|
||||||
if (target_container == null)
|
if (target_container == null)
|
||||||
Transform(entity).AttachToGridOrMap();
|
_xformSystem.AttachToGridOrMap(entity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -242,51 +223,47 @@ public sealed class EventHorizonSystem : SharedEventHorizonSystem
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Makes an event horizon consume a specific tile on a grid.
|
/// Makes an event horizon consume a specific tile on a grid.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="tile">The tile to consume.</param>
|
public void ConsumeTile(EntityUid hungry, TileRef tile, EventHorizonComponent eventHorizon)
|
||||||
/// <param name="eventHorizon">The event horizon which is consuming the tile on the grid.</param>
|
{
|
||||||
public void ConsumeTile(TileRef tile, EventHorizonComponent eventHorizon)
|
ConsumeTiles(hungry, new List<(Vector2i, Tile)>(new[] { (tile.GridIndices, Tile.Empty) }), tile.GridUid, _mapMan.GetGrid(tile.GridUid), eventHorizon);
|
||||||
=> ConsumeTiles(new List<(Vector2i, Tile)>(new []{(tile.GridIndices, Tile.Empty)}), _mapMan.GetGrid(tile.GridUid), eventHorizon);
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Makes an event horizon attempt to consume a specific tile on a grid.
|
/// Makes an event horizon attempt to consume a specific tile on a grid.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="tile">The tile to attempt to consume.</param>
|
public void AttemptConsumeTile(EntityUid hungry, TileRef tile, EventHorizonComponent eventHorizon)
|
||||||
/// <param name="eventHorizon">The event horizon which is attempting to consume the tile on the grid.</param>
|
{
|
||||||
public void AttemptConsumeTile(TileRef tile, EventHorizonComponent eventHorizon)
|
AttemptConsumeTiles(hungry, new TileRef[1] { tile }, tile.GridUid, _mapMan.GetGrid(tile.GridUid), eventHorizon);
|
||||||
=> AttemptConsumeTiles(new TileRef[1]{tile}, _mapMan.GetGrid(tile.GridUid), eventHorizon);
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Makes an event horizon consume a set of tiles on a grid.
|
/// Makes an event horizon consume a set of tiles on a grid.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="tiles">The tiles to consume.</param>
|
public void ConsumeTiles(EntityUid hungry, List<(Vector2i, Tile)> tiles, EntityUid gridId, MapGridComponent grid, EventHorizonComponent eventHorizon)
|
||||||
/// <param name="grid">The grid hosting the tiles to consume.</param>
|
|
||||||
/// <param name="eventHorizon">The event horizon which is consuming the tiles on the grid.</param>
|
|
||||||
public void ConsumeTiles(List<(Vector2i, Tile)> tiles, MapGridComponent grid, EventHorizonComponent eventHorizon)
|
|
||||||
{
|
{
|
||||||
if (tiles.Count <= 0)
|
if (tiles.Count <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
RaiseLocalEvent(eventHorizon.Owner, new TilesConsumedByEventHorizonEvent(tiles, grid, eventHorizon));
|
var ev = new TilesConsumedByEventHorizonEvent(tiles, gridId, grid, hungry, eventHorizon);
|
||||||
|
RaiseLocalEvent(hungry, ref ev);
|
||||||
grid.SetTiles(tiles);
|
grid.SetTiles(tiles);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Makes an event horizon attempt to consume a set of tiles on a grid.
|
/// Makes an event horizon attempt to consume a set of tiles on a grid.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="tiles">The tiles to attempt to consume.</param>
|
public int AttemptConsumeTiles(EntityUid hungry, IEnumerable<TileRef> tiles, EntityUid gridId, MapGridComponent grid, EventHorizonComponent eventHorizon)
|
||||||
/// <param name="grid">The grid hosting the tiles to attempt to consume.</param>
|
|
||||||
/// <param name="eventHorizon">The event horizon which is attempting to consume the tiles on the grid.</param>
|
|
||||||
public int AttemptConsumeTiles(IEnumerable<TileRef> tiles, MapGridComponent grid, EventHorizonComponent eventHorizon)
|
|
||||||
{
|
{
|
||||||
var toConsume = new List<(Vector2i, Tile)>();
|
var toConsume = new List<(Vector2i, Tile)>();
|
||||||
foreach(var tile in tiles) {
|
foreach (var tile in tiles)
|
||||||
if (CanConsumeTile(tile, grid, eventHorizon))
|
{
|
||||||
|
if (CanConsumeTile(hungry, tile, grid, eventHorizon))
|
||||||
toConsume.Add((tile.GridIndices, Tile.Empty));
|
toConsume.Add((tile.GridIndices, Tile.Empty));
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = toConsume.Count;
|
var result = toConsume.Count;
|
||||||
if (toConsume.Count > 0)
|
if (toConsume.Count > 0)
|
||||||
ConsumeTiles(toConsume, grid, eventHorizon);
|
ConsumeTiles(hungry, toConsume, gridId, grid, eventHorizon);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -294,14 +271,11 @@ public sealed class EventHorizonSystem : SharedEventHorizonSystem
|
|||||||
/// Checks whether an event horizon can consume a given tile.
|
/// Checks whether an event horizon can consume a given tile.
|
||||||
/// This is only possible if it can also consume all entities anchored to the tile.
|
/// This is only possible if it can also consume all entities anchored to the tile.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="tile">The tile to check for consumability.</param>
|
public bool CanConsumeTile(EntityUid hungry, TileRef tile, MapGridComponent grid, EventHorizonComponent eventHorizon)
|
||||||
/// <param name="grid">The grid hosting the tile to check.</param>
|
|
||||||
/// <param name="eventHorizon">The event horizon which is checking to see if it can consume the tile on the grid.</param>
|
|
||||||
public bool CanConsumeTile(TileRef tile, MapGridComponent grid, EventHorizonComponent eventHorizon)
|
|
||||||
{
|
{
|
||||||
foreach (var blockingEntity in grid.GetAnchoredEntities(tile.GridIndices))
|
foreach (var blockingEntity in grid.GetAnchoredEntities(tile.GridIndices))
|
||||||
{
|
{
|
||||||
if(!CanConsumeEntity(blockingEntity, eventHorizon))
|
if (!CanConsumeEntity(hungry, blockingEntity, eventHorizon))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -311,10 +285,6 @@ public sealed class EventHorizonSystem : SharedEventHorizonSystem
|
|||||||
/// Consumes all tiles within a given distance of an entity.
|
/// Consumes all tiles within a given distance of an entity.
|
||||||
/// Some entities are immune to consumption.
|
/// Some entities are immune to consumption.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="uid">The entity uid in the center of the region to consume all tiles within.</param>
|
|
||||||
/// <param name="range">The distance of the center entity within which to consume all tiles.</param>
|
|
||||||
/// <param name="xform">The transform component attached to the center entity.</param>
|
|
||||||
/// <param name="eventHorizon">The event horizon component attached to the center entity.</param>
|
|
||||||
public void ConsumeTilesInRange(EntityUid uid, float range, TransformComponent? xform, EventHorizonComponent? eventHorizon)
|
public void ConsumeTilesInRange(EntityUid uid, float range, TransformComponent? xform, EventHorizonComponent? eventHorizon)
|
||||||
{
|
{
|
||||||
if (!Resolve(uid, ref xform) || !Resolve(uid, ref eventHorizon))
|
if (!Resolve(uid, ref xform) || !Resolve(uid, ref eventHorizon))
|
||||||
@@ -324,8 +294,8 @@ public sealed class EventHorizonSystem : SharedEventHorizonSystem
|
|||||||
var box = Box2.CenteredAround(mapPos.Position, new Vector2(range, range));
|
var box = Box2.CenteredAround(mapPos.Position, new Vector2(range, range));
|
||||||
var circle = new Circle(mapPos.Position, range);
|
var circle = new Circle(mapPos.Position, range);
|
||||||
foreach (var grid in _mapMan.FindGridsIntersecting(mapPos.MapId, box))
|
foreach (var grid in _mapMan.FindGridsIntersecting(mapPos.MapId, box))
|
||||||
{
|
{ // TODO: Remover grid.Owner when this iterator returns entityuids as well.
|
||||||
AttemptConsumeTiles(grid.GetTilesIntersecting(circle), grid, eventHorizon);
|
AttemptConsumeTiles(uid, grid.GetTilesIntersecting(circle), grid.Owner, grid, eventHorizon);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -335,10 +305,6 @@ public sealed class EventHorizonSystem : SharedEventHorizonSystem
|
|||||||
/// Consumes most entities and tiles within a given distance of an entity.
|
/// Consumes most entities and tiles within a given distance of an entity.
|
||||||
/// Some entities are immune to consumption.
|
/// Some entities are immune to consumption.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="uid">The entity uid in the center of the region to consume everything within.</param>
|
|
||||||
/// <param name="range">The distance of the center entity within which to consume everything.</param>
|
|
||||||
/// <param name="xform">The transform component attached to the center entity.</param>
|
|
||||||
/// <param name="eventHorizon">The event horizon component attached to the center entity.</param>
|
|
||||||
public void ConsumeEverythingInRange(EntityUid uid, float range, TransformComponent? xform = null, EventHorizonComponent? eventHorizon = null)
|
public void ConsumeEverythingInRange(EntityUid uid, float range, TransformComponent? xform = null, EventHorizonComponent? eventHorizon = null)
|
||||||
{
|
{
|
||||||
if (!Resolve(uid, ref xform, ref eventHorizon))
|
if (!Resolve(uid, ref xform, ref eventHorizon))
|
||||||
@@ -357,9 +323,6 @@ public sealed class EventHorizonSystem : SharedEventHorizonSystem
|
|||||||
/// The value is specifically how long the subsystem should wait between scans.
|
/// The value is specifically how long the subsystem should wait between scans.
|
||||||
/// If the new scanning period would have already prompted a scan given the previous scan time one is prompted immediately.
|
/// If the new scanning period would have already prompted a scan given the previous scan time one is prompted immediately.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="uid">The uid of the event horizon to set the consume wave period for.</param>
|
|
||||||
/// <param name="value">The amount of time that this subsystem should wait between scans.</param>
|
|
||||||
/// <param name="eventHorizon">The state of the event horizon to set the consume wave period for.</param>
|
|
||||||
public void SetConsumePeriod(EntityUid uid, TimeSpan value, EventHorizonComponent? eventHorizon = null)
|
public void SetConsumePeriod(EntityUid uid, TimeSpan value, EventHorizonComponent? eventHorizon = null)
|
||||||
{
|
{
|
||||||
if (!Resolve(uid, ref eventHorizon))
|
if (!Resolve(uid, ref eventHorizon))
|
||||||
@@ -383,60 +346,49 @@ public sealed class EventHorizonSystem : SharedEventHorizonSystem
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Prevents a singularity from colliding with anything it is incapable of consuming.
|
/// Prevents a singularity from colliding with anything it is incapable of consuming.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="uid">The event horizon entity that is trying to collide with something.</param>
|
|
||||||
/// <param name="comp">The event horizon that is trying to collide with something.</param>
|
|
||||||
/// <param name="args">The event arguments.</param>
|
|
||||||
protected override bool PreventCollide(EntityUid uid, EventHorizonComponent comp, ref PreventCollideEvent args)
|
protected override bool PreventCollide(EntityUid uid, EventHorizonComponent comp, ref PreventCollideEvent args)
|
||||||
{
|
{
|
||||||
if (base.PreventCollide(uid, comp, ref args) || args.Cancelled)
|
if (base.PreventCollide(uid, comp, ref args) || args.Cancelled)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
args.Cancelled = !CanConsumeEntity(args.OtherEntity, comp);
|
// If we can eat it we don't want to bounce off of it. If we can't eat it we want to bounce off of it (containment fields).
|
||||||
|
args.Cancelled = args.OurFixture.Hard && CanConsumeEntity(uid, args.OtherEntity, comp);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A generic event handler that prevents singularities from consuming entities with a component of a given type if registered.
|
/// A generic event handler that prevents singularities from consuming entities with a component of a given type if registered.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="uid">The entity the singularity is trying to eat.</param>
|
public static void PreventConsume<TComp>(EntityUid uid, TComp comp, ref EventHorizonAttemptConsumeEntityEvent args)
|
||||||
/// <param name="comp">The component the singularity is trying to eat.</param>
|
|
||||||
/// <param name="args">The event arguments.</param>
|
|
||||||
public void PreventConsume<TComp>(EntityUid uid, TComp comp, EventHorizonAttemptConsumeEntityEvent args)
|
|
||||||
{
|
{
|
||||||
if (!args.Cancelled)
|
if (!args.Cancelled)
|
||||||
args.Cancel();
|
args.Cancelled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A generic event handler that prevents singularities from breaching containment.
|
/// A generic event handler that prevents singularities from breaching containment.
|
||||||
/// In this case 'breaching containment' means consuming an entity with a component of the given type unless the event horizon is set to breach containment anyway.
|
/// In this case 'breaching containment' means consuming an entity with a component of the given type unless the event horizon is set to breach containment anyway.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="uid">The entity the singularity is trying to eat.</param>
|
public static void PreventBreach<TComp>(EntityUid uid, TComp comp, ref EventHorizonAttemptConsumeEntityEvent args)
|
||||||
/// <param name="comp">The component the singularity is trying to eat.</param>
|
|
||||||
/// <param name="args">The event arguments.</param>
|
|
||||||
public void PreventBreach<TComp>(EntityUid uid, TComp comp, EventHorizonAttemptConsumeEntityEvent args)
|
|
||||||
{
|
{
|
||||||
if (args.Cancelled)
|
if (args.Cancelled)
|
||||||
return;
|
return;
|
||||||
if (!args.EventHorizon.CanBreachContainment)
|
if (!args.EventHorizon.CanBreachContainment)
|
||||||
PreventConsume(uid, comp, args);
|
PreventConsume(uid, comp, ref args);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handles event horizons consuming any entities they bump into.
|
/// Handles event horizons consuming any entities they bump into.
|
||||||
/// The event horizon will not consume any entities if it itself has been consumed by an event horizon.
|
/// The event horizon will not consume any entities if it itself has been consumed by an event horizon.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="uid">The event horizon entity.</param>
|
|
||||||
/// <param name="comp">The event horizon.</param>
|
|
||||||
/// <param name="args">The event arguments.</param>
|
|
||||||
private void OnStartCollide(EntityUid uid, EventHorizonComponent comp, ref StartCollideEvent args)
|
private void OnStartCollide(EntityUid uid, EventHorizonComponent comp, ref StartCollideEvent args)
|
||||||
{
|
{
|
||||||
if (comp.BeingConsumedByAnotherEventHorizon)
|
if (comp.BeingConsumedByAnotherEventHorizon)
|
||||||
return;
|
return;
|
||||||
if (args.OurFixture.ID != comp.HorizonFixtureId)
|
if (args.OurFixture.ID != comp.ConsumerFixtureId)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
AttemptConsumeEntity(args.OtherEntity, comp);
|
AttemptConsumeEntity(uid, args.OtherEntity, comp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -444,40 +396,31 @@ public sealed class EventHorizonSystem : SharedEventHorizonSystem
|
|||||||
/// Specifically prevents event horizons from consuming themselves.
|
/// Specifically prevents event horizons from consuming themselves.
|
||||||
/// Also ensures that if this event horizon has already been consumed by another event horizon it cannot be consumed again.
|
/// Also ensures that if this event horizon has already been consumed by another event horizon it cannot be consumed again.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="uid">The event horizon entity.</param>
|
private void OnAnotherEventHorizonAttemptConsumeThisEventHorizon(EntityUid uid, EventHorizonComponent comp, ref EventHorizonAttemptConsumeEntityEvent args)
|
||||||
/// <param name="comp">The event horizon.</param>
|
|
||||||
/// <param name="args">The event arguments.</param>
|
|
||||||
private void OnAnotherEventHorizonAttemptConsumeThisEventHorizon(EntityUid uid, EventHorizonComponent comp, EventHorizonAttemptConsumeEntityEvent args)
|
|
||||||
{
|
{
|
||||||
if (!args.Cancelled && (args.EventHorizon == comp || comp.BeingConsumedByAnotherEventHorizon))
|
if (!args.Cancelled && (args.EventHorizon == comp || comp.BeingConsumedByAnotherEventHorizon))
|
||||||
args.Cancel();
|
args.Cancelled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Prevents two singularities from annihilating one another.
|
/// Prevents two singularities from annihilating one another.
|
||||||
/// Specifically ensures if this event horizon is consumed by another event horizon it knows that it has been consumed.
|
/// Specifically ensures if this event horizon is consumed by another event horizon it knows that it has been consumed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="uid">The event horizon entity.</param>
|
private void OnAnotherEventHorizonConsumedThisEventHorizon(EntityUid uid, EventHorizonComponent comp, ref EventHorizonConsumedEntityEvent args)
|
||||||
/// <param name="comp">The event horizon.</param>
|
|
||||||
/// <param name="args">The event arguments.</param>
|
|
||||||
private void OnAnotherEventHorizonConsumedThisEventHorizon(EntityUid uid, EventHorizonComponent comp, EventHorizonConsumedEntityEvent args)
|
|
||||||
{
|
{
|
||||||
comp.BeingConsumedByAnotherEventHorizon = true;
|
comp.BeingConsumedByAnotherEventHorizon = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handles event horizons deciding to escape containers they are inserted into.
|
/// Handles event horizons deciding to escape containers they are inserted into.
|
||||||
/// Delegates the actual escape to <see cref="EventHorizonSystem.OnEventHorizonContained(EventHorizonContainedEvent)" /> on a delay.
|
/// Delegates the actual escape to <see cref="OnEventHorizonContained(EventHorizonContainedEvent)" /> on a delay.
|
||||||
/// This ensures that the escape is handled after all other handlers for the insertion event and satisfies the assertion that
|
/// This ensures that the escape is handled after all other handlers for the insertion event and satisfies the assertion that
|
||||||
/// the inserted entity SHALL be inside of the specified container after all handles to the entity event
|
/// the inserted entity SHALL be inside of the specified container after all handles to the entity event
|
||||||
/// <see cref="EntGotInsertedIntoContainerMessage" /> are processed.
|
/// <see cref="EntGotInsertedIntoContainerMessage" /> are processed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="uid">The uid of the event horizon.</param>]
|
private void OnEventHorizonContained(EntityUid uid, EventHorizonComponent comp, EntGotInsertedIntoContainerMessage args)
|
||||||
/// <param name="comp">The state of the event horizon.</param>]
|
{
|
||||||
/// <param name="args">The arguments of the insertion.</param>]
|
|
||||||
private void OnEventHorizonContained(EntityUid uid, EventHorizonComponent comp, EntGotInsertedIntoContainerMessage args) {
|
|
||||||
// Delegates processing an event until all queued events have been processed.
|
// Delegates processing an event until all queued events have been processed.
|
||||||
// As of 1:44 AM, Sunday, Dec. 4, 2022 this is the one use for this in the codebase.
|
|
||||||
QueueLocalEvent(new EventHorizonContainedEvent(uid, comp, args));
|
QueueLocalEvent(new EventHorizonContainedEvent(uid, comp, args));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -487,29 +430,29 @@ public sealed class EventHorizonSystem : SharedEventHorizonSystem
|
|||||||
/// container and drop the the next innermost contaning container.
|
/// container and drop the the next innermost contaning container.
|
||||||
/// This loops until the event horizon has escaped to the map or wound up in an indestructible container.
|
/// This loops until the event horizon has escaped to the map or wound up in an indestructible container.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="args">The arguments for this event.</param>]
|
private void OnEventHorizonContained(EventHorizonContainedEvent args)
|
||||||
private void OnEventHorizonContained(EventHorizonContainedEvent args) {
|
{
|
||||||
var uid = args.Entity;
|
var uid = args.Entity;
|
||||||
var comp = args.EventHorizon;
|
|
||||||
if (!EntityManager.EntityExists(uid))
|
if (!EntityManager.EntityExists(uid))
|
||||||
return;
|
return;
|
||||||
|
var comp = args.EventHorizon;
|
||||||
if (comp.BeingConsumedByAnotherEventHorizon)
|
if (comp.BeingConsumedByAnotherEventHorizon)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var containerEntity = args.Args.Container.Owner;
|
var containerEntity = args.Args.Container.Owner;
|
||||||
if(!(EntityManager.EntityExists(containerEntity) && AttemptConsumeEntity(containerEntity, comp))) {
|
if (!EntityManager.EntityExists(containerEntity))
|
||||||
|
return;
|
||||||
|
if (AttemptConsumeEntity(uid, containerEntity, comp))
|
||||||
|
return; // If we consume the entity we also consume everything in the containers it has.
|
||||||
|
|
||||||
ConsumeEntitiesInContainer(uid, args.Args.Container, comp, args.Args.Container);
|
ConsumeEntitiesInContainer(uid, args.Args.Container, comp, args.Args.Container);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Recursively consumes all entities within a container that is consumed by the singularity.
|
/// Recursively consumes all entities within a container that is consumed by the singularity.
|
||||||
/// If an entity within a consumed container cannot be consumed itself it is removed from the container.
|
/// If an entity within a consumed container cannot be consumed itself it is removed from the container.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="uid">The uid of the container being consumed.</param>
|
private void OnContainerConsumed(EntityUid uid, ContainerManagerComponent comp, ref EventHorizonConsumedEntityEvent args)
|
||||||
/// <param name="comp">The state of the container being consumed.</param>
|
|
||||||
/// <param name="args">The event arguments.</param>
|
|
||||||
private void OnContainerConsumed(EntityUid uid, ContainerManagerComponent comp, EventHorizonConsumedEntityEvent args)
|
|
||||||
{
|
{
|
||||||
var drop_container = args.Container;
|
var drop_container = args.Container;
|
||||||
if (drop_container is null)
|
if (drop_container is null)
|
||||||
@@ -517,7 +460,7 @@ public sealed class EventHorizonSystem : SharedEventHorizonSystem
|
|||||||
|
|
||||||
foreach (var container in comp.GetAllContainers())
|
foreach (var container in comp.GetAllContainers())
|
||||||
{
|
{
|
||||||
ConsumeEntitiesInContainer(args.EventHorizon.Owner, container, args.EventHorizon, drop_container);
|
ConsumeEntitiesInContainer(args.EventHorizonUid, container, args.EventHorizon, drop_container);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endregion Event Handlers
|
#endregion Event Handlers
|
||||||
|
|||||||
@@ -256,7 +256,7 @@ public sealed class SingularitySystem : SharedSingularitySystem
|
|||||||
/// <param name="uid">The entity UID of the singularity that is consuming the entity.</param>
|
/// <param name="uid">The entity UID of the singularity that is consuming the entity.</param>
|
||||||
/// <param name="comp">The component of the singularity that is consuming the entity.</param>
|
/// <param name="comp">The component of the singularity that is consuming the entity.</param>
|
||||||
/// <param name="args">The event arguments.</param>
|
/// <param name="args">The event arguments.</param>
|
||||||
public void OnConsumedEntity(EntityUid uid, SingularityComponent comp, EntityConsumedByEventHorizonEvent args)
|
public void OnConsumedEntity(EntityUid uid, SingularityComponent comp, ref EntityConsumedByEventHorizonEvent args)
|
||||||
{
|
{
|
||||||
AdjustEnergy(uid, BaseEntityEnergy, singularity: comp);
|
AdjustEnergy(uid, BaseEntityEnergy, singularity: comp);
|
||||||
}
|
}
|
||||||
@@ -267,21 +267,21 @@ public sealed class SingularitySystem : SharedSingularitySystem
|
|||||||
/// <param name="uid">The entity UID of the singularity that is consuming the tiles.</param>
|
/// <param name="uid">The entity UID of the singularity that is consuming the tiles.</param>
|
||||||
/// <param name="comp">The component of the singularity that is consuming the tiles.</param>
|
/// <param name="comp">The component of the singularity that is consuming the tiles.</param>
|
||||||
/// <param name="args">The event arguments.</param>
|
/// <param name="args">The event arguments.</param>
|
||||||
public void OnConsumedTiles(EntityUid uid, SingularityComponent comp, TilesConsumedByEventHorizonEvent args)
|
public void OnConsumedTiles(EntityUid uid, SingularityComponent comp, ref TilesConsumedByEventHorizonEvent args)
|
||||||
{
|
{
|
||||||
AdjustEnergy(uid, args.Tiles.Count * BaseTileEnergy, singularity: comp);
|
AdjustEnergy(uid, args.Tiles.Count * BaseTileEnergy, singularity: comp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds the energy of this singularity to singularities consume it.
|
/// Adds the energy of this singularity to singularities that consume it.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="uid">The entity UID of the singularity that is being consumed.</param>
|
/// <param name="uid">The entity UID of the singularity that is being consumed.</param>
|
||||||
/// <param name="comp">The component of the singularity that is being consumed.</param>
|
/// <param name="comp">The component of the singularity that is being consumed.</param>
|
||||||
/// <param name="args">The event arguments.</param>
|
/// <param name="args">The event arguments.</param>
|
||||||
private void OnConsumed(EntityUid uid, SingularityComponent comp, EventHorizonConsumedEntityEvent args)
|
private void OnConsumed(EntityUid uid, SingularityComponent comp, ref EventHorizonConsumedEntityEvent args)
|
||||||
{
|
{
|
||||||
// Should be slightly more efficient than checking literally everything we consume for a singularity component and doing the reverse.
|
// Should be slightly more efficient than checking literally everything we consume for a singularity component and doing the reverse.
|
||||||
if (EntityManager.TryGetComponent<SingularityComponent>(args.EventHorizon.Owner, out var singulo))
|
if (EntityManager.TryGetComponent<SingularityComponent>(args.EventHorizonUid, out var singulo))
|
||||||
{
|
{
|
||||||
AdjustEnergy(singulo.Owner, comp.Energy, singularity: singulo);
|
AdjustEnergy(singulo.Owner, comp.Energy, singularity: singulo);
|
||||||
SetEnergy(uid, 0.0f, comp);
|
SetEnergy(uid, 0.0f, comp);
|
||||||
@@ -294,10 +294,10 @@ public sealed class SingularitySystem : SharedSingularitySystem
|
|||||||
/// <param name="uid">The entity UID of the singularity food that is being consumed.</param>
|
/// <param name="uid">The entity UID of the singularity food that is being consumed.</param>
|
||||||
/// <param name="comp">The component of the singularity food that is being consumed.</param>
|
/// <param name="comp">The component of the singularity food that is being consumed.</param>
|
||||||
/// <param name="args">The event arguments.</param>
|
/// <param name="args">The event arguments.</param>
|
||||||
public void OnConsumed(EntityUid uid, SinguloFoodComponent comp, EventHorizonConsumedEntityEvent args)
|
public void OnConsumed(EntityUid uid, SinguloFoodComponent comp, ref EventHorizonConsumedEntityEvent args)
|
||||||
{
|
{
|
||||||
if (EntityManager.TryGetComponent<SingularityComponent>(args.EventHorizon.Owner, out var singulo))
|
if (EntityManager.TryGetComponent<SingularityComponent>(args.EventHorizonUid, out var singulo))
|
||||||
AdjustEnergy(args.EventHorizon.Owner, comp.Energy, singularity: singulo);
|
AdjustEnergy(args.EventHorizonUid, comp.Energy, singularity: singulo);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -6,28 +6,28 @@ namespace Content.Server.Singularity.Events;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Event raised on the event horizon entity whenever an event horizon consumes an entity.
|
/// Event raised on the event horizon entity whenever an event horizon consumes an entity.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class EntityConsumedByEventHorizonEvent : EntityEventArgs
|
[ByRefEvent]
|
||||||
|
public readonly record struct EntityConsumedByEventHorizonEvent
|
||||||
|
(EntityUid entity, EntityUid eventHorizonUid, EventHorizonComponent eventHorizon, IContainer? container)
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The entity being consumed by the event horizon.
|
/// The entity being consumed by the event horizon.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly EntityUid Entity;
|
public readonly EntityUid Entity = entity;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The uid of the event horizon consuming the entity.
|
||||||
|
/// </summary>
|
||||||
|
public readonly EntityUid EventHorizonUid = eventHorizonUid;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The event horizon consuming the entity.
|
/// The event horizon consuming the entity.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly EventHorizonComponent EventHorizon;
|
public readonly EventHorizonComponent EventHorizon = eventHorizon;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The innermost container of the entity being consumed by the event horizon that is not also in the process of being consumed by the event horizon.
|
/// The innermost container of the entity being consumed by the event horizon that is not also in the process of being consumed by the event horizon.
|
||||||
/// Used to correctly dump out the contents containers that are consumed by the event horizon.
|
/// Used to correctly dump out the contents containers that are consumed by the event horizon.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly IContainer? Container;
|
public readonly IContainer? Container = container;
|
||||||
|
|
||||||
public EntityConsumedByEventHorizonEvent(EntityUid entity, EventHorizonComponent eventHorizon, IContainer? container = null)
|
|
||||||
{
|
|
||||||
Entity = entity;
|
|
||||||
EventHorizon = eventHorizon;
|
|
||||||
Container = container;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,21 +6,27 @@ namespace Content.Server.Singularity.Events;
|
|||||||
/// Event raised on the target entity whenever an event horizon attempts to consume an entity.
|
/// Event raised on the target entity whenever an event horizon attempts to consume an entity.
|
||||||
/// Can be cancelled to prevent the target entity from being consumed.
|
/// Can be cancelled to prevent the target entity from being consumed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class EventHorizonAttemptConsumeEntityEvent : CancellableEntityEventArgs
|
[ByRefEvent]
|
||||||
|
public record struct EventHorizonAttemptConsumeEntityEvent
|
||||||
|
(EntityUid entity, EntityUid eventHorizonUid, EventHorizonComponent eventHorizon)
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The entity that the event horizon is attempting to consume.
|
/// The entity that the event horizon is attempting to consume.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly EntityUid Entity;
|
public readonly EntityUid Entity = entity;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The uid of the event horizon consuming the entity.
|
||||||
|
/// </summary>
|
||||||
|
public readonly EntityUid EventHorizonUid = eventHorizonUid;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The event horizon consuming the target entity.
|
/// The event horizon consuming the target entity.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly EventHorizonComponent EventHorizon;
|
public readonly EventHorizonComponent EventHorizon = eventHorizon;
|
||||||
|
|
||||||
public EventHorizonAttemptConsumeEntityEvent(EntityUid entity, EventHorizonComponent eventHorizon)
|
/// <summary>
|
||||||
{
|
/// Whether the event horizon has been prevented from consuming the target entity.
|
||||||
Entity = entity;
|
/// </summary>
|
||||||
EventHorizon = eventHorizon;
|
public bool Cancelled = false;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,30 +4,30 @@ using Robust.Shared.Containers;
|
|||||||
namespace Content.Server.Singularity.Events;
|
namespace Content.Server.Singularity.Events;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Event raised on the event horizon entity whenever an event horizon consumes an entity.
|
/// Event raised on the entity being consumed whenever an event horizon consumes an entity.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class EventHorizonConsumedEntityEvent : EntityEventArgs
|
[ByRefEvent]
|
||||||
|
public readonly record struct EventHorizonConsumedEntityEvent
|
||||||
|
(EntityUid entity, EntityUid eventHorizonUid, EventHorizonComponent eventHorizon, IContainer? container)
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The entity being consumed by the event horizon.
|
/// The entity being consumed by the event horizon.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly EntityUid Entity;
|
public readonly EntityUid Entity = entity;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The uid of the event horizon consuming the entity.
|
||||||
|
/// </summary>
|
||||||
|
public readonly EntityUid EventHorizonUid = eventHorizonUid;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The event horizon consuming the target entity.
|
/// The event horizon consuming the target entity.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly EventHorizonComponent EventHorizon;
|
public readonly EventHorizonComponent EventHorizon = eventHorizon;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The innermost container of the entity being consumed by the event horizon that is not also in the process of being consumed by the event horizon.
|
/// The innermost container of the entity being consumed by the event horizon that is not also in the process of being consumed by the event horizon.
|
||||||
/// Used to correctly dump out the contents containers that are consumed by the event horizon.
|
/// Used to correctly dump out the contents containers that are consumed by the event horizon.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly IContainer? Container;
|
public readonly IContainer? Container = container;
|
||||||
|
|
||||||
public EventHorizonConsumedEntityEvent(EntityUid entity, EventHorizonComponent eventHorizon, IContainer? container = null)
|
|
||||||
{
|
|
||||||
Entity = entity;
|
|
||||||
EventHorizon = eventHorizon;
|
|
||||||
Container = container;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,8 +6,10 @@ namespace Content.Shared.Singularity.EntitySystems;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// An event queued when an event horizon is contained (put into a container).
|
/// An event queued when an event horizon is contained (put into a container).
|
||||||
/// Exists to delay the event horizon eating its way out of the container until events relating to the insertion have been processed.
|
/// Exists to delay the event horizon eating its way out of the container until events relating to the insertion have been processed.
|
||||||
|
/// Needs to be a class because ref structs can't be put into the queue.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class EventHorizonContainedEvent : EntityEventArgs {
|
public sealed class EventHorizonContainedEvent : EntityEventArgs
|
||||||
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The uid of the event horizon that has been contained.
|
/// The uid of the event horizon that has been contained.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -23,7 +25,8 @@ public sealed class EventHorizonContainedEvent : EntityEventArgs {
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly EntGotInsertedIntoContainerMessage Args;
|
public readonly EntGotInsertedIntoContainerMessage Args;
|
||||||
|
|
||||||
public EventHorizonContainedEvent(EntityUid entity, EventHorizonComponent eventHorizon, EntGotInsertedIntoContainerMessage args) {
|
public EventHorizonContainedEvent(EntityUid entity, EventHorizonComponent eventHorizon, EntGotInsertedIntoContainerMessage args)
|
||||||
|
{
|
||||||
Entity = entity;
|
Entity = entity;
|
||||||
EventHorizon = eventHorizon;
|
EventHorizon = eventHorizon;
|
||||||
Args = args;
|
Args = args;
|
||||||
|
|||||||
@@ -8,28 +8,33 @@ namespace Content.Server.Singularity.Events;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Event raised on the event horizon entity whenever an event horizon consumes an entity.
|
/// Event raised on the event horizon entity whenever an event horizon consumes an entity.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class TilesConsumedByEventHorizonEvent : EntityEventArgs
|
[ByRefEvent]
|
||||||
|
public readonly record struct TilesConsumedByEventHorizonEvent
|
||||||
|
(IReadOnlyList<(Vector2i, Tile)> tiles, EntityUid mapGridUid, MapGridComponent mapGrid, EntityUid eventHorizonUid, EventHorizonComponent eventHorizon)
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The tiles that the event horizon is consuming.
|
/// The tiles that the event horizon is consuming.
|
||||||
/// Ripped directly from the relevant proc so the second element of each element will be what the tiles are going to be after the grid is updated; usually <see cref="Tile.Empty"/>.
|
/// Ripped directly from the relevant proc so the second element of each element will be what the tiles are going to be after the grid is updated; usually <see cref="Tile.Empty"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly IReadOnlyList<(Vector2i, Tile)> Tiles;
|
public readonly IReadOnlyList<(Vector2i, Tile)> Tiles = tiles;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The uid of the map grid the event horizon is consuming part of.
|
||||||
|
/// </summary>
|
||||||
|
public readonly EntityUid MapGridUid = mapGridUid;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The mapgrid that the event horizon is consuming tiles of.
|
/// The mapgrid that the event horizon is consuming tiles of.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly MapGridComponent MapGrid;
|
public readonly MapGridComponent MapGrid = mapGrid;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The uid of the event horizon consuming the entity.
|
||||||
|
/// </summary>
|
||||||
|
public readonly EntityUid EventHorizonUid = eventHorizonUid;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The event horizon consuming the tiles.
|
/// The event horizon consuming the tiles.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly EventHorizonComponent EventHorizon;
|
public readonly EventHorizonComponent EventHorizon = eventHorizon;
|
||||||
|
|
||||||
public TilesConsumedByEventHorizonEvent(IReadOnlyList<(Vector2i, Tile)> tiles, MapGridComponent mapGrid, EventHorizonComponent eventHorizon)
|
|
||||||
{
|
|
||||||
Tiles = tiles;
|
|
||||||
MapGrid = mapGrid;
|
|
||||||
EventHorizon = eventHorizon;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ namespace Content.Shared.Singularity.Components;
|
|||||||
/// Also makes the associated entity destroy other entities upon contact.
|
/// Also makes the associated entity destroy other entities upon contact.
|
||||||
/// Primarily managed by <see cref="SharedEventHorizonSystem"/> and its server/client versions.
|
/// Primarily managed by <see cref="SharedEventHorizonSystem"/> and its server/client versions.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[Access(friends: typeof(SharedEventHorizonSystem))]
|
||||||
[RegisterComponent, NetworkedComponent]
|
[RegisterComponent, NetworkedComponent]
|
||||||
public sealed class EventHorizonComponent : Component
|
public sealed class EventHorizonComponent : Component
|
||||||
{
|
{
|
||||||
@@ -17,7 +18,6 @@ public sealed class EventHorizonComponent : Component
|
|||||||
/// If you want to set this go through <see cref="SharedEventHorizonSystem.SetRadius"/>.
|
/// If you want to set this go through <see cref="SharedEventHorizonSystem.SetRadius"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField("radius")]
|
[DataField("radius")]
|
||||||
[Access(friends:typeof(SharedEventHorizonSystem))]
|
|
||||||
public float Radius;
|
public float Radius;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -25,7 +25,7 @@ public sealed class EventHorizonComponent : Component
|
|||||||
/// If you want to set this go through <see cref="SharedEventHorizonSystem.SetCanBreachContainment"/>.
|
/// If you want to set this go through <see cref="SharedEventHorizonSystem.SetCanBreachContainment"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField("canBreachContainment")]
|
[DataField("canBreachContainment")]
|
||||||
[Access(friends:typeof(SharedEventHorizonSystem))]
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
public bool CanBreachContainment = false;
|
public bool CanBreachContainment = false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -33,9 +33,18 @@ public sealed class EventHorizonComponent : Component
|
|||||||
/// Can be set to null, in which case no such fixture is used.
|
/// Can be set to null, in which case no such fixture is used.
|
||||||
/// If you want to set this go through <see cref="SharedEventHorizonSystem.SetHorizonFixtureId"/>.
|
/// If you want to set this go through <see cref="SharedEventHorizonSystem.SetHorizonFixtureId"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField("horizonFixtureId")]
|
[DataField("consumerFixtureId")]
|
||||||
[Access(friends:typeof(SharedEventHorizonSystem))]
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
public string? HorizonFixtureId = "EventHorizon";
|
public string? ConsumerFixtureId = "EventHorizonConsumer";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The ID of the fixture used to detect if the event horizon has collided with any physics objects.
|
||||||
|
/// Can be set to null, in which case no such fixture is used.
|
||||||
|
/// If you want to set this go through <see cref="SharedEventHorizonSystem.SetHorizonFixtureId"/>.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("colliderFixtureId")]
|
||||||
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public string? ColliderFixtureId = "EventHorizonCollider";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether the entity this event horizon is attached to is being consumed by another event horizon.
|
/// Whether the entity this event horizon is attached to is being consumed by another event horizon.
|
||||||
@@ -49,22 +58,19 @@ public sealed class EventHorizonComponent : Component
|
|||||||
/// The amount of time that should elapse between this event horizon consuming everything it overlaps with.
|
/// The amount of time that should elapse between this event horizon consuming everything it overlaps with.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField("consumePeriod")]
|
[DataField("consumePeriod")]
|
||||||
[ViewVariables(VVAccess.ReadOnly)]
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
[Access(typeof(SharedEventHorizonSystem))]
|
|
||||||
public TimeSpan TargetConsumePeriod { get; set; } = TimeSpan.FromSeconds(0.5);
|
public TimeSpan TargetConsumePeriod { get; set; } = TimeSpan.FromSeconds(0.5);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The last time at which this consumed everything it overlapped with.
|
/// The last time at which this consumed everything it overlapped with.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ViewVariables(VVAccess.ReadOnly)]
|
[ViewVariables(VVAccess.ReadOnly)]
|
||||||
[Access(typeof(SharedEventHorizonSystem))]
|
|
||||||
public TimeSpan LastConsumeWaveTime { get; set; } = default!;
|
public TimeSpan LastConsumeWaveTime { get; set; } = default!;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The next time at which this consumed everything it overlapped with.
|
/// The next time at which this consumed everything it overlapped with.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ViewVariables(VVAccess.ReadOnly)]
|
[ViewVariables(VVAccess.ReadOnly)]
|
||||||
[Access(typeof(SharedEventHorizonSystem))]
|
|
||||||
public TimeSpan NextConsumeWaveTime { get; set; } = default!;
|
public TimeSpan NextConsumeWaveTime { get; set; } = default!;
|
||||||
|
|
||||||
#endregion Update Timing
|
#endregion Update Timing
|
||||||
|
|||||||
@@ -18,8 +18,8 @@ public sealed class SingularityComponent : Component
|
|||||||
/// Used as a scaling factor for things like visual size, event horizon radius, gravity well radius, radiation output, etc.
|
/// Used as a scaling factor for things like visual size, event horizon radius, gravity well radius, radiation output, etc.
|
||||||
/// If you want to set this use <see cref="SharedSingularitySystem.SetLevel"/>().
|
/// If you want to set this use <see cref="SharedSingularitySystem.SetLevel"/>().
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField("level")]
|
|
||||||
[Access(friends: typeof(SharedSingularitySystem), Other = AccessPermissions.Read, Self = AccessPermissions.Read)]
|
[Access(friends: typeof(SharedSingularitySystem), Other = AccessPermissions.Read, Self = AccessPermissions.Read)]
|
||||||
|
[DataField("level")]
|
||||||
public byte Level = 1;
|
public byte Level = 1;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -27,8 +27,8 @@ public sealed class SingularityComponent : Component
|
|||||||
/// Has to be on shared in case someone attaches a RadiationPulseComponent to the singularity.
|
/// Has to be on shared in case someone attaches a RadiationPulseComponent to the singularity.
|
||||||
/// If you want to set this use <see cref="SharedSingularitySystem.SetRadsPerLevel"/>().
|
/// If you want to set this use <see cref="SharedSingularitySystem.SetRadsPerLevel"/>().
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField("radsPerLevel")]
|
|
||||||
[Access(friends: typeof(SharedSingularitySystem), Other = AccessPermissions.Read, Self = AccessPermissions.Read)]
|
[Access(friends: typeof(SharedSingularitySystem), Other = AccessPermissions.Read, Self = AccessPermissions.Read)]
|
||||||
|
[DataField("radsPerLevel")]
|
||||||
[ViewVariables(VVAccess.ReadWrite)]
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
public float RadsPerLevel = 2f;
|
public float RadsPerLevel = 2f;
|
||||||
|
|
||||||
@@ -88,7 +88,7 @@ public sealed class SingularityComponent : Component
|
|||||||
/// The amount of time that should elapse between automated updates to this singularity.
|
/// The amount of time that should elapse between automated updates to this singularity.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField("updatePeriod")]
|
[DataField("updatePeriod")]
|
||||||
[ViewVariables(VVAccess.ReadOnly)]
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
public TimeSpan TargetUpdatePeriod = TimeSpan.FromSeconds(1.0);
|
public TimeSpan TargetUpdatePeriod = TimeSpan.FromSeconds(1.0);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -31,7 +31,8 @@ public abstract class SharedEventHorizonSystem : EntitySystem
|
|||||||
var vvHandle = Vvm.GetTypeHandler<EventHorizonComponent>();
|
var vvHandle = Vvm.GetTypeHandler<EventHorizonComponent>();
|
||||||
vvHandle.AddPath(nameof(EventHorizonComponent.Radius), (_, comp) => comp.Radius, (uid, value, comp) => SetRadius(uid, value, eventHorizon: comp));
|
vvHandle.AddPath(nameof(EventHorizonComponent.Radius), (_, comp) => comp.Radius, (uid, value, comp) => SetRadius(uid, value, eventHorizon: comp));
|
||||||
vvHandle.AddPath(nameof(EventHorizonComponent.CanBreachContainment), (_, comp) => comp.CanBreachContainment, (uid, value, comp) => SetCanBreachContainment(uid, value, eventHorizon: comp));
|
vvHandle.AddPath(nameof(EventHorizonComponent.CanBreachContainment), (_, comp) => comp.CanBreachContainment, (uid, value, comp) => SetCanBreachContainment(uid, value, eventHorizon: comp));
|
||||||
vvHandle.AddPath(nameof(EventHorizonComponent.HorizonFixtureId), (_, comp) => comp.HorizonFixtureId, (uid, value, comp) => SetHorizonFixtureId(uid, value, eventHorizon: comp));
|
vvHandle.AddPath(nameof(EventHorizonComponent.ColliderFixtureId), (_, comp) => comp.ColliderFixtureId, (uid, value, comp) => SetColliderFixtureId(uid, value, eventHorizon: comp));
|
||||||
|
vvHandle.AddPath(nameof(EventHorizonComponent.ConsumerFixtureId), (_, comp) => comp.ConsumerFixtureId, (uid, value, comp) => SetConsumerFixtureId(uid, value, eventHorizon: comp));
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Shutdown()
|
public override void Shutdown()
|
||||||
@@ -39,7 +40,8 @@ public abstract class SharedEventHorizonSystem : EntitySystem
|
|||||||
var vvHandle = Vvm.GetTypeHandler<EventHorizonComponent>();
|
var vvHandle = Vvm.GetTypeHandler<EventHorizonComponent>();
|
||||||
vvHandle.RemovePath(nameof(EventHorizonComponent.Radius));
|
vvHandle.RemovePath(nameof(EventHorizonComponent.Radius));
|
||||||
vvHandle.RemovePath(nameof(EventHorizonComponent.CanBreachContainment));
|
vvHandle.RemovePath(nameof(EventHorizonComponent.CanBreachContainment));
|
||||||
vvHandle.RemovePath(nameof(EventHorizonComponent.HorizonFixtureId));
|
vvHandle.RemovePath(nameof(EventHorizonComponent.ColliderFixtureId));
|
||||||
|
vvHandle.RemovePath(nameof(EventHorizonComponent.ConsumerFixtureId));
|
||||||
|
|
||||||
base.Shutdown();
|
base.Shutdown();
|
||||||
}
|
}
|
||||||
@@ -100,16 +102,39 @@ public abstract class SharedEventHorizonSystem : EntitySystem
|
|||||||
/// <param name="value">The new fixture ID to associate the event horizon with.</param>
|
/// <param name="value">The new fixture ID to associate the event horizon with.</param>
|
||||||
/// <param name="updateFixture">Whether to update the associated fixture upon changing whether the event horizon can breach containment.</param>
|
/// <param name="updateFixture">Whether to update the associated fixture upon changing whether the event horizon can breach containment.</param>
|
||||||
/// <param name="eventHorizon">The state of the event horizon with the fixture ID to change.</param>
|
/// <param name="eventHorizon">The state of the event horizon with the fixture ID to change.</param>
|
||||||
public void SetHorizonFixtureId(EntityUid uid, string? value, bool updateFixture = true, EventHorizonComponent? eventHorizon = null)
|
public void SetColliderFixtureId(EntityUid uid, string? value, bool updateFixture = true, EventHorizonComponent? eventHorizon = null)
|
||||||
{
|
{
|
||||||
if (!Resolve(uid, ref eventHorizon))
|
if (!Resolve(uid, ref eventHorizon))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var oldValue = eventHorizon.HorizonFixtureId;
|
var oldValue = eventHorizon.ColliderFixtureId;
|
||||||
if (value == oldValue)
|
if (value == oldValue)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
eventHorizon.HorizonFixtureId = value;
|
eventHorizon.ColliderFixtureId = value;
|
||||||
|
Dirty(eventHorizon);
|
||||||
|
if (updateFixture)
|
||||||
|
UpdateEventHorizonFixture(uid, eventHorizon: eventHorizon);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Setter for <see cref="EventHorizonComponent.HorizonFixtureId"/>
|
||||||
|
/// May also update the fixture associated with the event horizon.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="uid">The uid of the event horizon with the fixture ID to change.</param>
|
||||||
|
/// <param name="value">The new fixture ID to associate the event horizon with.</param>
|
||||||
|
/// <param name="updateFixture">Whether to update the associated fixture upon changing whether the event horizon can breach containment.</param>
|
||||||
|
/// <param name="eventHorizon">The state of the event horizon with the fixture ID to change.</param>
|
||||||
|
public void SetConsumerFixtureId(EntityUid uid, string? value, bool updateFixture = true, EventHorizonComponent? eventHorizon = null)
|
||||||
|
{
|
||||||
|
if (!Resolve(uid, ref eventHorizon))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var oldValue = eventHorizon.ConsumerFixtureId;
|
||||||
|
if (value == oldValue)
|
||||||
|
return;
|
||||||
|
|
||||||
|
eventHorizon.ConsumerFixtureId = value;
|
||||||
Dirty(eventHorizon);
|
Dirty(eventHorizon);
|
||||||
if (updateFixture)
|
if (updateFixture)
|
||||||
UpdateEventHorizonFixture(uid, eventHorizon: eventHorizon);
|
UpdateEventHorizonFixture(uid, eventHorizon: eventHorizon);
|
||||||
@@ -118,27 +143,42 @@ public abstract class SharedEventHorizonSystem : EntitySystem
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Updates the state of the fixture associated with the event horizon.
|
/// Updates the state of the fixture associated with the event horizon.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="eventHorizon">The uid of the event horizon associated with the fixture to update.</param>
|
/// <param name="uid">The uid of the event horizon associated with the fixture to update.</param>
|
||||||
/// <param name="physics">The physics component containing the fixture to update.</param>
|
/// <param name="fixtures">The fixture manager component containing the fixture to update.</param>
|
||||||
/// <param name="eventHorizon">The state of the event horizon associated with the fixture to update.</param>
|
/// <param name="eventHorizon">The state of the event horizon associated with the fixture to update.</param>
|
||||||
public void UpdateEventHorizonFixture(EntityUid uid, PhysicsComponent? physics = null, EventHorizonComponent? eventHorizon = null)
|
public void UpdateEventHorizonFixture(EntityUid uid, FixturesComponent? fixtures = null, EventHorizonComponent? eventHorizon = null)
|
||||||
{
|
{
|
||||||
if (!Resolve(uid, ref eventHorizon))
|
if (!Resolve(uid, ref eventHorizon))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var fixtureId = eventHorizon.HorizonFixtureId;
|
var consumerId = eventHorizon.ConsumerFixtureId;
|
||||||
FixturesComponent? manager = null;
|
var colliderId = eventHorizon.ColliderFixtureId;
|
||||||
|
if (consumerId == null || colliderId == null
|
||||||
if (fixtureId == null || !Resolve(uid, ref manager, ref physics, logMissing: false))
|
|| !Resolve(uid, ref fixtures, logMissing: false))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var fixture = _fixtures.GetFixtureOrNull(uid, fixtureId, manager);
|
// Update both fixtures the event horizon is associated with:
|
||||||
if (fixture == null)
|
if (consumerId != null)
|
||||||
return;
|
{
|
||||||
|
var consumer = _fixtures.GetFixtureOrNull(uid, consumerId, fixtures);
|
||||||
|
if (consumer != null)
|
||||||
|
{
|
||||||
|
_physics.SetRadius(uid, consumer, consumer.Shape, eventHorizon.Radius, fixtures);
|
||||||
|
_physics.SetHard(uid, consumer, false, fixtures);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var shape = (PhysShapeCircle)fixture.Shape;
|
if (colliderId != null)
|
||||||
_physics.SetRadius(uid, fixture, shape, eventHorizon.Radius, manager: manager, body: physics);
|
{
|
||||||
_physics.SetHard(uid, fixture, true, manager);
|
var collider = _fixtures.GetFixtureOrNull(uid, colliderId, fixtures);
|
||||||
|
if (collider != null)
|
||||||
|
{
|
||||||
|
_physics.SetRadius(uid, collider, collider.Shape, eventHorizon.Radius, fixtures);
|
||||||
|
_physics.SetHard(uid, collider, true, fixtures);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EntityManager.Dirty(uid, fixtures);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion Getters/Setters
|
#endregion Getters/Setters
|
||||||
|
|||||||
@@ -14,20 +14,31 @@
|
|||||||
- type: EventHorizon # To make the singularity consume things.
|
- type: EventHorizon # To make the singularity consume things.
|
||||||
radius: 0.5
|
radius: 0.5
|
||||||
canBreachContainment: false
|
canBreachContainment: false
|
||||||
horizonFixtureId: EventHorizon
|
colliderFixtureId: EventHorizonCollider
|
||||||
|
consumerFixtureId: EventHorizonConsumer
|
||||||
- type: GravityWell # To make the singularity attract things.
|
- type: GravityWell # To make the singularity attract things.
|
||||||
- type: Fixtures
|
- type: Fixtures
|
||||||
fixtures:
|
fixtures:
|
||||||
EventHorizon:
|
EventHorizonCollider:
|
||||||
shape:
|
shape:
|
||||||
!type:PhysShapeCircle
|
!type:PhysShapeCircle
|
||||||
radius: 0.35
|
radius: 0.35
|
||||||
|
hard: true
|
||||||
restitution: 0.8
|
restitution: 0.8
|
||||||
density: 99999
|
density: 99999
|
||||||
mask:
|
mask:
|
||||||
- AllMask
|
- AllMask
|
||||||
layer:
|
layer:
|
||||||
- AllMask
|
- AllMask
|
||||||
|
EventHorizonConsumer:
|
||||||
|
shape:
|
||||||
|
!type:PhysShapeCircle
|
||||||
|
radius: 0.35
|
||||||
|
hard: false
|
||||||
|
mask:
|
||||||
|
- AllMask
|
||||||
|
layer:
|
||||||
|
- AllMask
|
||||||
- type: Singularity
|
- type: Singularity
|
||||||
energy: 180
|
energy: 180
|
||||||
level: 1
|
level: 1
|
||||||
@@ -80,4 +91,3 @@
|
|||||||
sprite: Structures/Power/Generation/Singularity/singularity_6.rsi
|
sprite: Structures/Power/Generation/Singularity/singularity_6.rsi
|
||||||
state: singularity_6
|
state: singularity_6
|
||||||
scale: .9,.9
|
scale: .9,.9
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user