ProjectileAnomalySystem.cs 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. using System.Linq;
  2. using System.Numerics;
  3. using Content.Server.Anomaly.Components;
  4. using Content.Server.Weapons.Ranged.Systems;
  5. using Content.Shared.Anomaly.Components;
  6. using Content.Shared.Mobs.Components;
  7. using Content.Shared.Projectiles;
  8. using Robust.Server.GameObjects;
  9. using Robust.Shared.Map;
  10. using Robust.Shared.Physics;
  11. using Robust.Shared.Random;
  12. namespace Content.Server.Anomaly.Effects;
  13. /// <summary>
  14. /// This handles <see cref="ProjectileAnomalyComponent"/> and the events from <seealso cref="AnomalySystem"/>
  15. /// </summary>
  16. public sealed class ProjectileAnomalySystem : EntitySystem
  17. {
  18. [Dependency] private readonly TransformSystem _xform = default!;
  19. [Dependency] private readonly EntityLookupSystem _lookup = default!;
  20. [Dependency] private readonly IRobustRandom _random = default!;
  21. [Dependency] private readonly IMapManager _mapManager = default!;
  22. [Dependency] private readonly GunSystem _gunSystem = default!;
  23. public override void Initialize()
  24. {
  25. SubscribeLocalEvent<ProjectileAnomalyComponent, AnomalyPulseEvent>(OnPulse);
  26. SubscribeLocalEvent<ProjectileAnomalyComponent, AnomalySupercriticalEvent>(OnSupercritical);
  27. }
  28. private void OnPulse(EntityUid uid, ProjectileAnomalyComponent component, ref AnomalyPulseEvent args)
  29. {
  30. ShootProjectilesAtEntities(uid, component, args.Severity * args.PowerModifier);
  31. }
  32. private void OnSupercritical(EntityUid uid, ProjectileAnomalyComponent component, ref AnomalySupercriticalEvent args)
  33. {
  34. ShootProjectilesAtEntities(uid, component, args.PowerModifier);
  35. }
  36. private void ShootProjectilesAtEntities(EntityUid uid, ProjectileAnomalyComponent component, float severity)
  37. {
  38. var projectileCount = (int) MathF.Round(MathHelper.Lerp(component.MinProjectiles, component.MaxProjectiles, severity));
  39. var xformQuery = GetEntityQuery<TransformComponent>();
  40. var mobQuery = GetEntityQuery<MobStateComponent>();
  41. var xform = xformQuery.GetComponent(uid);
  42. var inRange = _lookup.GetEntitiesInRange(uid, component.ProjectileRange * severity, LookupFlags.Dynamic).ToList();
  43. _random.Shuffle(inRange);
  44. var priority = new List<EntityUid>();
  45. foreach (var entity in inRange)
  46. {
  47. if (mobQuery.HasComponent(entity))
  48. priority.Add(entity);
  49. }
  50. Log.Debug($"shots: {projectileCount}");
  51. while (projectileCount > 0)
  52. {
  53. Log.Debug($"{projectileCount}");
  54. var target = priority.Any()
  55. ? _random.PickAndTake(priority)
  56. : _random.Pick(inRange);
  57. var targetCoords = xformQuery.GetComponent(target).Coordinates.Offset(_random.NextVector2(0.5f));
  58. ShootProjectile(
  59. uid, component,
  60. xform.Coordinates,
  61. targetCoords,
  62. severity);
  63. projectileCount--;
  64. }
  65. }
  66. private void ShootProjectile(
  67. EntityUid uid,
  68. ProjectileAnomalyComponent component,
  69. EntityCoordinates coords,
  70. EntityCoordinates targetCoords,
  71. float severity)
  72. {
  73. var mapPos = coords.ToMap(EntityManager, _xform);
  74. var spawnCoords = _mapManager.TryFindGridAt(mapPos, out var gridUid, out _)
  75. ? coords.WithEntityId(gridUid, EntityManager)
  76. : new(_mapManager.GetMapEntityId(mapPos.MapId), mapPos.Position);
  77. var ent = Spawn(component.ProjectilePrototype, spawnCoords);
  78. var direction = targetCoords.ToMapPos(EntityManager, _xform) - mapPos.Position;
  79. if (!TryComp<ProjectileComponent>(ent, out var comp))
  80. return;
  81. comp.Damage *= severity;
  82. _gunSystem.ShootProjectile(ent, direction, Vector2.Zero, uid, uid, component.ProjectileSpeed);
  83. }
  84. }