1
0

EmpSystem.cs 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. using Content.Server.Explosion.EntitySystems;
  2. using Content.Server.Power.EntitySystems;
  3. using Content.Server.Radio;
  4. using Content.Server.SurveillanceCamera;
  5. using Content.Shared.Emp;
  6. using Content.Shared.Examine;
  7. using Robust.Server.GameObjects;
  8. using Robust.Shared.Map;
  9. namespace Content.Server.Emp;
  10. public sealed class EmpSystem : SharedEmpSystem
  11. {
  12. [Dependency] private readonly EntityLookupSystem _lookup = default!;
  13. [Dependency] private readonly TransformSystem _transform = default!;
  14. public const string EmpPulseEffectPrototype = "EffectEmpPulse";
  15. public override void Initialize()
  16. {
  17. base.Initialize();
  18. SubscribeLocalEvent<EmpDisabledComponent, ExaminedEvent>(OnExamine);
  19. SubscribeLocalEvent<EmpOnTriggerComponent, TriggerEvent>(HandleEmpTrigger);
  20. SubscribeLocalEvent<EmpDisabledComponent, RadioSendAttemptEvent>(OnRadioSendAttempt);
  21. SubscribeLocalEvent<EmpDisabledComponent, RadioReceiveAttemptEvent>(OnRadioReceiveAttempt);
  22. SubscribeLocalEvent<EmpDisabledComponent, ApcToggleMainBreakerAttemptEvent>(OnApcToggleMainBreaker);
  23. SubscribeLocalEvent<EmpDisabledComponent, SurveillanceCameraSetActiveAttemptEvent>(OnCameraSetActive);
  24. }
  25. /// <summary>
  26. /// Triggers an EMP pulse at the given location, by first raising an <see cref="EmpAttemptEvent"/>, then a raising <see cref="EmpPulseEvent"/> on all entities in range.
  27. /// </summary>
  28. /// <param name="coordinates">The location to trigger the EMP pulse at.</param>
  29. /// <param name="range">The range of the EMP pulse.</param>
  30. /// <param name="energyConsumption">The amount of energy consumed by the EMP pulse.</param>
  31. /// <param name="duration">The duration of the EMP effects.</param>
  32. public void EmpPulse(MapCoordinates coordinates, float range, float energyConsumption, float duration)
  33. {
  34. foreach (var uid in _lookup.GetEntitiesInRange(coordinates, range))
  35. {
  36. TryEmpEffects(uid, energyConsumption, duration);
  37. }
  38. Spawn(EmpPulseEffectPrototype, coordinates);
  39. }
  40. /// <summary>
  41. /// Attempts to apply the effects of an EMP pulse onto an entity by first raising an <see cref="EmpAttemptEvent"/>, followed by raising a <see cref="EmpPulseEvent"/> on it.
  42. /// </summary>
  43. /// <param name="uid">The entity to apply the EMP effects on.</param>
  44. /// <param name="energyConsumption">The amount of energy consumed by the EMP.</param>
  45. /// <param name="duration">The duration of the EMP effects.</param>
  46. public void TryEmpEffects(EntityUid uid, float energyConsumption, float duration)
  47. {
  48. var attemptEv = new EmpAttemptEvent();
  49. RaiseLocalEvent(uid, attemptEv);
  50. if (attemptEv.Cancelled)
  51. return;
  52. DoEmpEffects(uid, energyConsumption, duration);
  53. }
  54. /// <summary>
  55. /// Applies the effects of an EMP pulse onto an entity by raising a <see cref="EmpPulseEvent"/> on it.
  56. /// </summary>
  57. /// <param name="uid">The entity to apply the EMP effects on.</param>
  58. /// <param name="energyConsumption">The amount of energy consumed by the EMP.</param>
  59. /// <param name="duration">The duration of the EMP effects.</param>
  60. public void DoEmpEffects(EntityUid uid, float energyConsumption, float duration)
  61. {
  62. var ev = new EmpPulseEvent(energyConsumption, false, false, TimeSpan.FromSeconds(duration));
  63. RaiseLocalEvent(uid, ref ev);
  64. if (ev.Affected)
  65. {
  66. Spawn(EmpDisabledEffectPrototype, Transform(uid).Coordinates);
  67. }
  68. if (ev.Disabled)
  69. {
  70. var disabled = EnsureComp<EmpDisabledComponent>(uid);
  71. disabled.DisabledUntil = Timing.CurTime + TimeSpan.FromSeconds(duration);
  72. }
  73. }
  74. public override void Update(float frameTime)
  75. {
  76. base.Update(frameTime);
  77. var query = EntityQueryEnumerator<EmpDisabledComponent>();
  78. while (query.MoveNext(out var uid, out var comp))
  79. {
  80. if (comp.DisabledUntil < Timing.CurTime)
  81. {
  82. RemComp<EmpDisabledComponent>(uid);
  83. var ev = new EmpDisabledRemoved();
  84. RaiseLocalEvent(uid, ref ev);
  85. }
  86. }
  87. }
  88. private void OnExamine(EntityUid uid, EmpDisabledComponent component, ExaminedEvent args)
  89. {
  90. args.PushMarkup(Loc.GetString("emp-disabled-comp-on-examine"));
  91. }
  92. private void HandleEmpTrigger(EntityUid uid, EmpOnTriggerComponent comp, TriggerEvent args)
  93. {
  94. EmpPulse(_transform.GetMapCoordinates(uid), comp.Range, comp.EnergyConsumption, comp.DisableDuration);
  95. args.Handled = true;
  96. }
  97. private void OnRadioSendAttempt(EntityUid uid, EmpDisabledComponent component, ref RadioSendAttemptEvent args)
  98. {
  99. args.Cancelled = true;
  100. }
  101. private void OnRadioReceiveAttempt(EntityUid uid, EmpDisabledComponent component, ref RadioReceiveAttemptEvent args)
  102. {
  103. args.Cancelled = true;
  104. }
  105. private void OnApcToggleMainBreaker(EntityUid uid, EmpDisabledComponent component, ref ApcToggleMainBreakerAttemptEvent args)
  106. {
  107. args.Cancelled = true;
  108. }
  109. private void OnCameraSetActive(EntityUid uid, EmpDisabledComponent component, ref SurveillanceCameraSetActiveAttemptEvent args)
  110. {
  111. args.Cancelled = true;
  112. }
  113. }
  114. /// <summary>
  115. /// Raised on an entity before <see cref="EmpPulseEvent"/>. Cancel this to prevent the emp event being raised.
  116. /// </summary>
  117. public sealed partial class EmpAttemptEvent : CancellableEntityEventArgs
  118. {
  119. }
  120. [ByRefEvent]
  121. public record struct EmpPulseEvent(float EnergyConsumption, bool Affected, bool Disabled, TimeSpan Duration);
  122. [ByRefEvent]
  123. public record struct EmpDisabledRemoved();