diff --git a/Content.Server/Explosion/EntitySystems/ExplosionSystem.Processing.cs b/Content.Server/Explosion/EntitySystems/ExplosionSystem.Processing.cs index 7f03e68aa4..3499d66443 100644 --- a/Content.Server/Explosion/EntitySystems/ExplosionSystem.Processing.cs +++ b/Content.Server/Explosion/EntitySystems/ExplosionSystem.Processing.cs @@ -8,7 +8,9 @@ using Content.Shared.Explosion; using Content.Shared.FixedPoint; using Content.Shared.Maps; using Content.Shared.Physics; +using Content.Shared.Projectiles; using Content.Shared.Spawners.Components; +using Content.Shared.Tag; using Robust.Shared.Map; using Robust.Shared.Map.Components; using Robust.Shared.Physics; @@ -199,7 +201,8 @@ public sealed partial class ExplosionSystem : EntitySystem EntityQuery xformQuery, EntityQuery damageQuery, EntityQuery physicsQuery, - LookupFlags flags) + EntityQuery tagQuery, + EntityQuery projectileQuery) { var gridBox = new Box2(tile * grid.TileSize, (tile + 1) * grid.TileSize); @@ -217,7 +220,7 @@ public sealed partial class ExplosionSystem : EntitySystem // process those entities foreach (var xform in list) { - ProcessEntity(xform.Owner, epicenter, damage, throwForce, id, damageQuery, physicsQuery, xform); + ProcessEntity(xform.Owner, epicenter, damage, throwForce, id, xform, damageQuery, physicsQuery, xformQuery, tagQuery, projectileQuery); } // process anchored entities @@ -226,7 +229,7 @@ public sealed partial class ExplosionSystem : EntitySystem foreach (var entity in anchoredList) { processed.Add(entity); - ProcessEntity(entity, epicenter, damage, throwForce, id, damageQuery, physicsQuery); + ProcessEntity(entity, epicenter, damage, throwForce, id, null, damageQuery, physicsQuery, xformQuery, tagQuery, projectileQuery); } // Walls and reinforced walls will break into girders. These girders will also be considered turf-blocking for @@ -260,7 +263,7 @@ public sealed partial class ExplosionSystem : EntitySystem { // Here we only throw, no dealing damage. Containers n such might drop their entities after being destroyed, but // they should handle their own damage pass-through, with their own damage reduction calculation. - ProcessEntity(xform.Owner, epicenter, null, throwForce, id, damageQuery, physicsQuery, xform); + ProcessEntity(xform.Owner, epicenter, null, throwForce, id, xform, damageQuery, physicsQuery, xformQuery, tagQuery, projectileQuery); } return !tileBlocked; @@ -299,7 +302,8 @@ public sealed partial class ExplosionSystem : EntitySystem EntityQuery xformQuery, EntityQuery damageQuery, EntityQuery physicsQuery, - LookupFlags flags) + EntityQuery tagQuery, + EntityQuery projectileQuery) { var gridBox = Box2.FromDimensions(tile * DefaultTileSize, (DefaultTileSize, DefaultTileSize)); var worldBox = spaceMatrix.TransformBox(gridBox); @@ -315,7 +319,7 @@ public sealed partial class ExplosionSystem : EntitySystem foreach (var xform in state.Item1) { processed.Add(xform.Owner); - ProcessEntity(xform.Owner, epicenter, damage, throwForce, id, damageQuery, physicsQuery, xform); + ProcessEntity(xform.Owner, epicenter, damage, throwForce, id, xform, damageQuery, physicsQuery, xformQuery, tagQuery, projectileQuery); } if (throwForce <= 0) @@ -329,7 +333,7 @@ public sealed partial class ExplosionSystem : EntitySystem foreach (var xform in list) { - ProcessEntity(xform.Owner, epicenter, null, throwForce, id, damageQuery, physicsQuery, xform); + ProcessEntity(xform.Owner, epicenter, null, throwForce, id, xform, damageQuery, physicsQuery, xformQuery, tagQuery, projectileQuery); } } @@ -375,9 +379,12 @@ public sealed partial class ExplosionSystem : EntitySystem DamageSpecifier? damage, float throwForce, string id, + TransformComponent? xform, EntityQuery damageQuery, EntityQuery physicsQuery, - TransformComponent? xform = null) + EntityQuery transformQuery, + EntityQuery tagQuery, + EntityQuery projectileQuery) { // damage if (damage != null && damageQuery.TryGetComponent(uid, out var damageable)) @@ -413,15 +420,22 @@ public sealed partial class ExplosionSystem : EntitySystem } // throw - if (xform != null + if (xform != null // null implies anchored && !xform.Anchored && throwForce > 0 && !EntityManager.IsQueuedForDeletion(uid) && physicsQuery.TryGetComponent(uid, out var physics) && physics.BodyType == BodyType.Dynamic) { - // TODO purge throw helpers and pass in physics component - _throwingSystem.TryThrow(uid, xform.WorldPosition - epicenter.Position, throwForce); + var pos = _transformSystem.GetWorldPosition(xform, transformQuery); + _throwingSystem.TryThrow( + uid, + pos - epicenter.Position, + physics, + xform, + projectileQuery, + tagQuery, + throwForce); } // TODO EXPLOSION puddle / flammable ignite? @@ -567,14 +581,14 @@ sealed class Explosion private readonly EntityQuery _xformQuery; private readonly EntityQuery _physicsQuery; private readonly EntityQuery _damageQuery; + private readonly EntityQuery _projectileQuery; + private readonly EntityQuery _tagQuery; /// /// Total area that the explosion covers. /// public readonly int Area; - private readonly LookupFlags _flags = LookupFlags.None; - /// /// factor used to scale the tile break chances. /// @@ -625,14 +639,11 @@ sealed class Explosion _canCreateVacuum = canCreateVacuum; _entMan = entMan; - // yeah this should be a cvar, but this is only temporary anyways - // see lookup todo - if (Area > 100) - _flags |= LookupFlags.Approximate; - _xformQuery = entMan.GetEntityQuery(); _physicsQuery = entMan.GetEntityQuery(); _damageQuery = entMan.GetEntityQuery(); + _tagQuery = entMan.GetEntityQuery(); + _projectileQuery = entMan.GetEntityQuery(); if (spaceData != null) { @@ -773,7 +784,8 @@ sealed class Explosion _xformQuery, _damageQuery, _physicsQuery, - _flags); + _tagQuery, + _projectileQuery); // If the floor is not blocked by some dense object, damage the floor tiles. if (canDamageFloor) @@ -794,7 +806,8 @@ sealed class Explosion _xformQuery, _damageQuery, _physicsQuery, - _flags); + _tagQuery, + _projectileQuery); } if (!MoveNext()) diff --git a/Content.Shared/Throwing/ThrowingSystem.cs b/Content.Shared/Throwing/ThrowingSystem.cs index 1b7cfd7d6f..5b8f6b335a 100644 --- a/Content.Shared/Throwing/ThrowingSystem.cs +++ b/Content.Shared/Throwing/ThrowingSystem.cs @@ -1,6 +1,7 @@ using Content.Shared.Gravity; using Content.Shared.Interaction; using Content.Shared.Movement.Components; +using Content.Shared.Projectiles; using Content.Shared.Tag; using Robust.Shared.Physics; using Robust.Shared.Physics.Components; @@ -32,22 +33,49 @@ public sealed class ThrowingSystem : EntitySystem /// A vector pointing from the entity to its destination. /// How much the direction vector should be multiplied for velocity. /// The ratio of impulse applied to the thrower - defaults to 10 because otherwise it's not enough to properly recover from getting spaced - public void TryThrow( - EntityUid uid, + public void TryThrow(EntityUid uid, Vector2 direction, float strength = 1.0f, EntityUid? user = null, - float pushbackRatio = 5.0f, - PhysicsComponent? physics = null, - TransformComponent? transform = null, - EntityQuery? physicsQuery = null, - EntityQuery? xformQuery = null) + float pushbackRatio = 5.0f) { - if (strength <= 0 || direction == Vector2.Infinity || direction == Vector2.NaN || direction == Vector2.Zero) + var physicsQuery = GetEntityQuery(); + if (!physicsQuery.TryGetComponent(uid, out var physics)) return; - physicsQuery ??= GetEntityQuery(); - if (physics == null && !physicsQuery.Value.TryGetComponent(uid, out physics)) + var projectileQuery = GetEntityQuery(); + var tagQuery = GetEntityQuery(); + + TryThrow( + uid, + direction, + physics, + Transform(uid), + projectileQuery, + tagQuery, + strength, + user, + pushbackRatio); + } + + /// + /// Tries to throw the entity if it has a physics component, otherwise does nothing. + /// + /// The entity being thrown. + /// A vector pointing from the entity to its destination. + /// How much the direction vector should be multiplied for velocity. + /// The ratio of impulse applied to the thrower - defaults to 10 because otherwise it's not enough to properly recover from getting spaced + public void TryThrow(EntityUid uid, + Vector2 direction, + PhysicsComponent physics, + TransformComponent transform, + EntityQuery projectileQuery, + EntityQuery tagQuery, + float strength = 1.0f, + EntityUid? user = null, + float pushbackRatio = 5.0f) + { + if (strength <= 0 || direction == Vector2.Infinity || direction == Vector2.NaN || direction == Vector2.Zero) return; if ((physics.BodyType & (BodyType.Dynamic | BodyType.KinematicController)) == 0x0) @@ -56,20 +84,17 @@ public sealed class ThrowingSystem : EntitySystem return; } + if (projectileQuery.HasComponent(uid)) + return; + var comp = EnsureComp(uid); comp.Thrower = user; + // Give it a l'il spin. - if (!_tagSystem.HasTag(uid, "NoSpinOnThrow")) + if (!tagQuery.TryGetComponent(uid, out var tag) || !_tagSystem.HasTag(tag, "NoSpinOnThrow")) _physics.ApplyAngularImpulse(uid, ThrowAngularImpulse, body: physics); else - { - if (transform == null) - { - xformQuery ??= GetEntityQuery(); - transform = xformQuery.Value.GetComponent(uid); - } transform.LocalRotation = direction.ToWorldAngle() - Math.PI; - } if (user != null) _interactionSystem.ThrownInteraction(user.Value, uid); @@ -100,7 +125,7 @@ public sealed class ThrowingSystem : EntitySystem // Give thrower an impulse in the other direction if (user != null && pushbackRatio > 0.0f && - physicsQuery.Value.TryGetComponent(user.Value, out var userPhysics) && + TryComp(user.Value, out PhysicsComponent? userPhysics) && _gravity.IsWeightless(user.Value, userPhysics)) { var msg = new ThrowPushbackAttemptEvent();