Delta-v/Content.Server/_DV/Abilities/ShatterLightsAbilitySystem.cs

86 lines
3.4 KiB
C#

using Content.Server.Light.Components;
using Content.Server.Light.EntitySystems;
using Content.Shared._DV.Abilities;
using Content.Shared.Actions;
using Content.Shared.Coordinates;
using Content.Shared.Physics;
using Robust.Server.Audio;
using Robust.Shared.Map;
using Robust.Shared.Physics;
using Robust.Shared.Physics.Systems;
using System.Linq;
using System.Numerics;
namespace Content.Server._DV.Abilities;
public sealed partial class ShatterLightsAbilitySystem : EntitySystem
{
[Dependency] private readonly AudioSystem _audio = default!;
[Dependency] private readonly EntityLookupSystem _lookup = default!;
[Dependency] private readonly PoweredLightSystem _light = default!;
[Dependency] private readonly SharedActionsSystem _actions = default!;
[Dependency] private readonly SharedPhysicsSystem _physics = default!;
[Dependency] private readonly SharedTransformSystem _transform = default!;
private readonly HashSet<Entity<PoweredLightComponent>> _lightsInRange = new();
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<ShatterLightsAbilityComponent, MapInitEvent>(OnMapInit);
SubscribeLocalEvent<ShatterLightsAbilityComponent, ComponentShutdown>(OnShutdown);
SubscribeLocalEvent<ShatterLightsAbilityComponent, ShatterLightsActionEvent>(OnShatterLightsAction);
}
private void OnMapInit(Entity<ShatterLightsAbilityComponent> ent, ref MapInitEvent args)
{
_actions.AddAction(ent, ref ent.Comp.ShatterLightsActionEntity, ent.Comp.ShatterLightsActionId);
_actions.StartUseDelay(ent.Comp.ShatterLightsActionEntity);
}
private void OnShutdown(Entity<ShatterLightsAbilityComponent> entity, ref ComponentShutdown args)
{
_actions.RemoveAction(entity.Owner, entity.Comp.ShatterLightsActionEntity);
}
private void OnShatterLightsAction(Entity<ShatterLightsAbilityComponent> entity, ref ShatterLightsActionEvent args)
{
if (args.Handled)
return;
if (entity.Comp.AbilitySound != null)
_audio.PlayPvs(entity.Comp.AbilitySound, entity);
ShatterLightsAround(entity.Owner, entity.Comp.Radius, entity.Comp.LineOfSight);
SpawnAttachedTo(entity.Comp.Effect, entity.Owner.ToCoordinates());
args.Handled = true;
}
public void ShatterLightsAround(EntityUid center, float range, bool lineOfSight)
{
var pos = _transform.GetWorldPosition(center);
// Get all light entities within the specified radius
_lightsInRange.Clear();
_lookup.GetEntitiesInRange(Transform(center).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);
var ray = new CollisionRay(pos, (lightPos - pos).Normalized(), (int)CollisionGroup.Opaque);
var hit = _physics.IntersectRay(_transform.GetMapId(center), 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);
}
}
}