BluespaceAnomalySystem.cs 4.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. using System.Linq;
  2. using System.Numerics;
  3. using Content.Server.Anomaly.Components;
  4. using Content.Shared.Administration.Logs;
  5. using Content.Shared.Anomaly.Components;
  6. using Content.Shared.Database;
  7. using Content.Shared.Mobs.Components;
  8. using Content.Shared.Teleportation.Components;
  9. using Robust.Shared.Audio.Systems;
  10. using Robust.Shared.Collections;
  11. using Robust.Shared.Random;
  12. namespace Content.Server.Anomaly.Effects;
  13. public sealed class BluespaceAnomalySystem : EntitySystem
  14. {
  15. [Dependency] private readonly IRobustRandom _random = default!;
  16. [Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
  17. [Dependency] private readonly SharedAudioSystem _audio = default!;
  18. [Dependency] private readonly EntityLookupSystem _lookup = default!;
  19. [Dependency] private readonly SharedTransformSystem _xform = default!;
  20. /// <inheritdoc/>
  21. public override void Initialize()
  22. {
  23. SubscribeLocalEvent<BluespaceAnomalyComponent, AnomalyPulseEvent>(OnPulse);
  24. SubscribeLocalEvent<BluespaceAnomalyComponent, AnomalySupercriticalEvent>(OnSupercritical);
  25. SubscribeLocalEvent<BluespaceAnomalyComponent, AnomalySeverityChangedEvent>(OnSeverityChanged);
  26. }
  27. private void OnPulse(EntityUid uid, BluespaceAnomalyComponent component, ref AnomalyPulseEvent args)
  28. {
  29. var xformQuery = GetEntityQuery<TransformComponent>();
  30. var xform = xformQuery.GetComponent(uid);
  31. var range = component.MaxShuffleRadius * args.Severity * args.PowerModifier;
  32. // get a list of all entities in range with the MobStateComponent
  33. // we filter out those inside a container
  34. // otherwise borg brains get removed from their body, or PAIs from a PDA
  35. var mobs = new HashSet<Entity<MobStateComponent>>();
  36. _lookup.GetEntitiesInRange(xform.Coordinates, range, mobs, flags: LookupFlags.Uncontained);
  37. var allEnts = new ValueList<EntityUid>(mobs.Select(m => m.Owner)) { uid };
  38. var coords = new ValueList<Vector2>();
  39. foreach (var ent in allEnts)
  40. {
  41. if (xformQuery.TryGetComponent(ent, out var allXform))
  42. coords.Add(_xform.GetWorldPosition(allXform));
  43. }
  44. _random.Shuffle(coords);
  45. for (var i = 0; i < allEnts.Count; i++)
  46. {
  47. _adminLogger.Add(LogType.Teleport, $"{ToPrettyString(allEnts[i])} has been shuffled to {coords[i]} by the {ToPrettyString(uid)} at {xform.Coordinates}");
  48. _xform.SetWorldPosition(allEnts[i], coords[i]);
  49. }
  50. }
  51. private void OnSupercritical(EntityUid uid, BluespaceAnomalyComponent component, ref AnomalySupercriticalEvent args)
  52. {
  53. var xform = Transform(uid);
  54. var mapPos = _xform.GetWorldPosition(xform);
  55. var radius = component.SupercriticalTeleportRadius * args.PowerModifier;
  56. var gridBounds = new Box2(mapPos - new Vector2(radius, radius), mapPos + new Vector2(radius, radius));
  57. var mobs = new HashSet<Entity<MobStateComponent>>();
  58. _lookup.GetEntitiesInRange(xform.Coordinates, component.MaxShuffleRadius, mobs, flags: LookupFlags.Uncontained);
  59. foreach (var comp in mobs)
  60. {
  61. var ent = comp.Owner;
  62. var randomX = _random.NextFloat(gridBounds.Left, gridBounds.Right);
  63. var randomY = _random.NextFloat(gridBounds.Bottom, gridBounds.Top);
  64. var pos = new Vector2(randomX, randomY);
  65. _adminLogger.Add(LogType.Teleport, $"{ToPrettyString(ent)} has been teleported to {pos} by the supercritical {ToPrettyString(uid)} at {mapPos}");
  66. _xform.SetWorldPosition(ent, pos);
  67. _audio.PlayPvs(component.TeleportSound, ent);
  68. }
  69. }
  70. private void OnSeverityChanged(EntityUid uid, BluespaceAnomalyComponent component, ref AnomalySeverityChangedEvent args)
  71. {
  72. if (!TryComp<PortalComponent>(uid, out var portal))
  73. return;
  74. portal.MaxRandomRadius = (component.MaxPortalRadius - component.MinPortalRadius) * args.Severity + component.MinPortalRadius;
  75. }
  76. }