diff --git a/Content.Server/Singularity/EntitySystems/EventHorizonSystem.cs b/Content.Server/Singularity/EntitySystems/EventHorizonSystem.cs index 6e3d9e9251..3bf820535f 100644 --- a/Content.Server/Singularity/EntitySystems/EventHorizonSystem.cs +++ b/Content.Server/Singularity/EntitySystems/EventHorizonSystem.cs @@ -11,7 +11,9 @@ using Content.Shared.Tag; using Robust.Shared.Containers; using Robust.Shared.Map; using Robust.Shared.Map.Components; +using Robust.Shared.Physics.Components; using Robust.Shared.Physics.Events; +using Robust.Shared.Physics.Systems; using Robust.Shared.Timing; namespace Content.Server.Singularity.EntitySystems; @@ -28,16 +30,20 @@ public sealed class EventHorizonSystem : SharedEventHorizonSystem [Dependency] private readonly IMapManager _mapMan = default!; [Dependency] private readonly IAdminLogManager _adminLogger = default!; [Dependency] private readonly SharedContainerSystem _containerSystem = default!; + [Dependency] private readonly SharedPhysicsSystem _physics = default!; [Dependency] private readonly SharedTransformSystem _xformSystem = default!; [Dependency] private readonly TagSystem _tagSystem = default!; #endregion Dependencies + private EntityQuery _physicsQuery; + public override void Initialize() { base.Initialize(); + _physicsQuery = GetEntityQuery(); + SubscribeLocalEvent(PreventConsume); - SubscribeLocalEvent(PreventConsume); SubscribeLocalEvent(PreventConsume); SubscribeLocalEvent(OnHorizonMapInit); SubscribeLocalEvent(OnStartCollide); @@ -159,24 +165,19 @@ public sealed class EventHorizonSystem : SharedEventHorizonSystem /// Attempts to consume all entities within a given distance of an entity; /// Excludes the center entity. /// - public void ConsumeEntitiesInRange(EntityUid uid, float range, TransformComponent? xform = null, EventHorizonComponent? eventHorizon = null) + public void ConsumeEntitiesInRange(EntityUid uid, float range, PhysicsComponent? body = null, EventHorizonComponent? eventHorizon = null) { - if (!Resolve(uid, ref xform, ref eventHorizon)) + if (!Resolve(uid, ref body, ref eventHorizon)) return; - var range2 = range * range; - var xformQuery = EntityManager.GetEntityQuery(); - var epicenter = _xformSystem.GetWorldPosition(xform, xformQuery); - foreach (var entity in _lookup.GetEntitiesInRange(_xformSystem.GetMapCoordinates(uid, xform), range, flags: LookupFlags.Uncontained)) + // TODO: Should be sundries + static-sundries but apparently this is load-bearing for SpawnAndDeleteAllEntitiesInTheSameSpot so go figure. + foreach (var entity in _lookup.GetEntitiesInRange(uid, range, flags: LookupFlags.Uncontained)) { if (entity == uid) continue; - if (!xformQuery.TryGetComponent(entity, out var entityXform)) - continue; - // 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) + // See TODO above + if (_physicsQuery.TryComp(entity, out var otherBody) && !_physics.IsHardCollidable((uid, null, body), (entity, null, otherBody))) continue; AttemptConsumeEntity(uid, entity, eventHorizon); @@ -318,11 +319,11 @@ public sealed class EventHorizonSystem : SharedEventHorizonSystem /// public void ConsumeEverythingInRange(EntityUid uid, float range, TransformComponent? xform = null, EventHorizonComponent? eventHorizon = null) { - if (!Resolve(uid, ref xform, ref eventHorizon)) + if (!Resolve(uid, ref eventHorizon)) return; if (eventHorizon.ConsumeEntities) - ConsumeEntitiesInRange(uid, range, xform, eventHorizon); + ConsumeEntitiesInRange(uid, range, null, eventHorizon); if (eventHorizon.ConsumeTiles) ConsumeTilesInRange(uid, range, xform, eventHorizon); } diff --git a/Content.Server/Singularity/EntitySystems/GravityWellSystem.cs b/Content.Server/Singularity/EntitySystems/GravityWellSystem.cs index 8c884d023c..7dcf3ef1ae 100644 --- a/Content.Server/Singularity/EntitySystems/GravityWellSystem.cs +++ b/Content.Server/Singularity/EntitySystems/GravityWellSystem.cs @@ -2,6 +2,7 @@ using System.Numerics; using Content.Server.Singularity.Components; using Content.Shared.Atmos.Components; using Content.Shared.Ghost; +using Content.Shared.Physics; using Content.Shared.Singularity.EntitySystems; using Robust.Shared.Map; using Robust.Shared.Map.Components; @@ -33,9 +34,18 @@ public sealed class GravityWellSystem : SharedGravityWellSystem /// public const float MinGravPulseRange = 0.00001f; + private EntityQuery _wellQuery; + private EntityQuery _mapQuery; + private EntityQuery _gridQuery; + private EntityQuery _physicsQuery; + public override void Initialize() { base.Initialize(); + _wellQuery = GetEntityQuery(); + _mapQuery = GetEntityQuery(); + _gridQuery = GetEntityQuery(); + _physicsQuery = GetEntityQuery(); SubscribeLocalEvent(OnGravityWellStartup); var vvHandle = _vvManager.GetTypeHandler(); @@ -111,11 +121,15 @@ public sealed class GravityWellSystem : SharedGravityWellSystem /// The entity to check. private bool CanGravPulseAffect(EntityUid entity) { - return !( - EntityManager.HasComponent(entity) || - EntityManager.HasComponent(entity) || - EntityManager.HasComponent(entity) || - EntityManager.HasComponent(entity) + if (_physicsQuery.TryComp(entity, out var physics)) + { + if (physics.CollisionLayer == (int) CollisionGroup.GhostImpassable) + return false; + } + + return !(_gridQuery.HasComp(entity) || + _mapQuery.HasComp(entity) || + _wellQuery.HasComp(entity) ); } diff --git a/Content.Shared/Physics/CollisionGroup.cs b/Content.Shared/Physics/CollisionGroup.cs index 9f8c5ad9be..0a11f93dbc 100644 --- a/Content.Shared/Physics/CollisionGroup.cs +++ b/Content.Shared/Physics/CollisionGroup.cs @@ -22,13 +22,17 @@ public enum CollisionGroup GhostImpassable = 1 << 5, // 32 Things impassible by ghosts/observers, ie blessed tiles or forcefields BulletImpassable = 1 << 6, // 64 Can be hit by bullets InteractImpassable = 1 << 7, // 128 Blocks interaction/InRangeUnobstructed + // Y dis door passable when all the others impassable / collision. DoorPassable = 1 << 8, // 256 Allows door to close over top, Like blast doors over conveyors for disposals rooms/cargo. MapGrid = MapGridHelpers.CollisionGroup, // Map grids, like shuttles. This is the actual grid itself, not the walls or other entities connected to the grid. // 32 possible groups + // Why dis exist AllMask = -1, + SingularityLayer = Opaque | Impassable | MidImpassable | HighImpassable | LowImpassable | BulletImpassable | InteractImpassable | DoorPassable, + // Humanoids, etc. MobMask = Impassable | HighImpassable | MidImpassable | LowImpassable, MobLayer = Opaque | BulletImpassable, diff --git a/Resources/Prototypes/Entities/Mobs/Player/narsie.yml b/Resources/Prototypes/Entities/Mobs/Player/narsie.yml index 7030572cf4..5d07409b5f 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/narsie.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/narsie.yml @@ -52,18 +52,18 @@ restitution: 0.8 density: 99999 mask: - - AllMask + - SingularityLayer layer: - - AllMask + - SingularityLayer EventHorizonConsumer: shape: !type:PhysShapeCircle radius: 5 hard: false mask: - - AllMask + - SingularityLayer layer: - - AllMask + - SingularityLayer - type: Input context: "ghost" - type: MovementIgnoreGravity diff --git a/Resources/Prototypes/Entities/Mobs/Player/observer.yml b/Resources/Prototypes/Entities/Mobs/Player/observer.yml index 52994a72c6..5ceac9e773 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/observer.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/observer.yml @@ -24,7 +24,7 @@ !type:PhysShapeCircle radius: 0.35 density: 15 - mask: + layer: - GhostImpassable - type: entity diff --git a/Resources/Prototypes/Entities/Mobs/Player/ratvar.yml b/Resources/Prototypes/Entities/Mobs/Player/ratvar.yml index 958c98f483..530f5e1037 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/ratvar.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/ratvar.yml @@ -49,18 +49,18 @@ restitution: 0.8 density: 1 mask: - - AllMask + - SingularityLayer layer: - - AllMask + - SingularityLayer EventHorizonConsumer: shape: !type:PhysShapeCircle radius: 5 hard: false mask: - - AllMask + - SingularityLayer layer: - - AllMask + - SingularityLayer - type: Input context: "ghost" - type: MovementIgnoreGravity diff --git a/Resources/Prototypes/Entities/Structures/Power/Generation/Singularity/singularity.yml b/Resources/Prototypes/Entities/Structures/Power/Generation/Singularity/singularity.yml index 25d219ab94..bf2c6cfcc0 100644 --- a/Resources/Prototypes/Entities/Structures/Power/Generation/Singularity/singularity.yml +++ b/Resources/Prototypes/Entities/Structures/Power/Generation/Singularity/singularity.yml @@ -31,18 +31,18 @@ restitution: 0.8 density: 99999 mask: - - AllMask + - SingularityLayer layer: - - AllMask + - SingularityLayer EventHorizonConsumer: shape: !type:PhysShapeCircle radius: 0.35 hard: false mask: - - AllMask + - SingularityLayer layer: - - AllMask + - SingularityLayer - type: Singularity energy: 180 level: 1