mirror of
https://github.com/DeltaV-Station/Delta-v.git
synced 2026-10-02 09:07:27 +00:00
87 lines
3.8 KiB
C#
87 lines
3.8 KiB
C#
using System.Linq;
|
|
using System.Numerics;
|
|
using Content.Shared._DV.Projectiles;
|
|
using Content.Shared._DV.Psionics.Components.PsionicPowers;
|
|
using Content.Shared._DV.Psionics.Events.PowerActionEvents;
|
|
using Content.Shared.Coordinates;
|
|
using Content.Shared.Light.Components;
|
|
using Content.Shared.Light.EntitySystems;
|
|
using Content.Shared.Physics;
|
|
using JetBrains.Annotations;
|
|
using Robust.Shared.Audio.Systems;
|
|
using Robust.Shared.Network;
|
|
using Robust.Shared.Physics;
|
|
using Robust.Shared.Physics.Systems;
|
|
|
|
namespace Content.Shared._DV.Psionics.Systems.PsionicPowers;
|
|
|
|
/// <summary>
|
|
/// This system enables a psionic being to break lights around them.
|
|
/// </summary>
|
|
public sealed class PsychokineticScreamPowerSystem : BasePsionicPowerSystem<PsychokineticScreamPowerComponent, PsychokineticScreamPowerActionEvent>
|
|
{
|
|
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
|
[Dependency] private readonly SharedPoweredLightSystem _light = default!;
|
|
[Dependency] private readonly EntityLookupSystem _lookup = default!;
|
|
[Dependency] private readonly SharedPhysicsSystem _physics = default!;
|
|
[Dependency] private readonly SharedTransformSystem _transform = default!;
|
|
|
|
protected override void OnPowerUsed(Entity<PsychokineticScreamPowerComponent> psionic, ref PsychokineticScreamPowerActionEvent args)
|
|
{
|
|
if (psionic.Comp.AbilitySound != null)
|
|
_audio.PlayPredicted(psionic.Comp.AbilitySound, psionic, psionic);
|
|
|
|
ShatterLightsAround(psionic.Owner, psionic.Comp.Radius, psionic.Comp.LineOfSight, psionic.Comp.PenetratingRadius);
|
|
|
|
SpawnAttachedTo(psionic.Comp.Effect, psionic.Owner.ToCoordinates());
|
|
args.Handled = true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Shatter lights around an entity.
|
|
/// This is public because other systems require it.
|
|
/// </summary>
|
|
/// <param name="source">The entity that caused it.</param>
|
|
/// <param name="range">The range where the lights are broken within.</param>
|
|
/// <param name="lineOfSight">Whether line of sight is required.</param>
|
|
/// <param name="penetratingRadius">How far it ignores the line of sight.</param>
|
|
[PublicAPI]
|
|
public void ShatterLightsAround(EntityUid source, float range, bool lineOfSight, float penetratingRadius = 0f)
|
|
{
|
|
var pos = _transform.GetWorldPosition(source);
|
|
|
|
// Get all light entities within the specified radius
|
|
HashSet<Entity<PoweredLightComponent>> lightsInRange = [];
|
|
_lookup.GetEntitiesInRange(Transform(source).Coordinates, range, lightsInRange);
|
|
|
|
foreach (var light in lightsInRange)
|
|
{
|
|
if (lineOfSight) // If LoS is required, test it.
|
|
{
|
|
var lightPos = _transform.GetWorldPosition(light);
|
|
var sqrDistance = Vector2.DistanceSquared(pos, lightPos);
|
|
if (sqrDistance > penetratingRadius * penetratingRadius)
|
|
{
|
|
// If the light is outside the penetrating radius, do a LoS check.
|
|
var ray = new CollisionRay(pos, (lightPos - pos).Normalized(), (int)CollisionGroup.Opaque);
|
|
var hit = _physics.IntersectRay(_transform.GetMapId(source), ray, MathF.Sqrt(sqrDistance) - 0.5f, returnOnFirstHit: true);
|
|
if (hit.Any() && hit.First().Distance != 0)
|
|
continue;
|
|
}
|
|
}
|
|
|
|
// If we reach here, the light is unobstructed and within range, break it.
|
|
_light.TryDestroyBulb(light, light.Comp, source);
|
|
}
|
|
|
|
// Gets all all flare gun pellets in a radius and deletes them.
|
|
HashSet<Entity<FlareGunPelletComponent>> flaresInRange = [];
|
|
_lookup.GetEntitiesInRange(Transform(source).Coordinates, range, flaresInRange);
|
|
|
|
foreach (var flare in flaresInRange)
|
|
{
|
|
PredictedQueueDel(flare);
|
|
}
|
|
}
|
|
}
|