GeigerSystem.cs 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. using Content.Server.Radiation.Components;
  2. using Content.Server.Radiation.Events;
  3. using Content.Shared.Hands;
  4. using Content.Shared.Interaction;
  5. using Content.Shared.Inventory.Events;
  6. using Content.Shared.Radiation.Components;
  7. using Content.Shared.Radiation.Systems;
  8. using Robust.Server.Audio;
  9. using Robust.Server.GameObjects;
  10. using Robust.Server.Player;
  11. namespace Content.Server.Radiation.Systems;
  12. public sealed class GeigerSystem : SharedGeigerSystem
  13. {
  14. [Dependency] private readonly SharedAppearanceSystem _appearance = default!;
  15. [Dependency] private readonly RadiationSystem _radiation = default!;
  16. [Dependency] private readonly AudioSystem _audio = default!;
  17. [Dependency] private readonly IPlayerManager _player = default!;
  18. private static readonly float ApproxEqual = 0.01f;
  19. public override void Initialize()
  20. {
  21. base.Initialize();
  22. SubscribeLocalEvent<GeigerComponent, ActivateInWorldEvent>(OnActivate);
  23. SubscribeLocalEvent<GeigerComponent, GotEquippedEvent>(OnEquipped);
  24. SubscribeLocalEvent<GeigerComponent, GotEquippedHandEvent>(OnEquippedHand);
  25. SubscribeLocalEvent<GeigerComponent, GotUnequippedEvent>(OnUnequipped);
  26. SubscribeLocalEvent<GeigerComponent, GotUnequippedHandEvent>(OnUnequippedHand);
  27. SubscribeLocalEvent<RadiationSystemUpdatedEvent>(OnUpdate);
  28. }
  29. private void OnActivate(Entity<GeigerComponent> geiger, ref ActivateInWorldEvent args)
  30. {
  31. if (args.Handled || !args.Complex || geiger.Comp.AttachedToSuit)
  32. return;
  33. args.Handled = true;
  34. SetEnabled(geiger, !geiger.Comp.IsEnabled);
  35. }
  36. private void OnEquipped(Entity<GeigerComponent> geiger, ref GotEquippedEvent args)
  37. {
  38. if (geiger.Comp.AttachedToSuit)
  39. SetEnabled(geiger, true);
  40. SetUser(geiger, args.Equipee);
  41. }
  42. private void OnEquippedHand(Entity<GeigerComponent> geiger, ref GotEquippedHandEvent args)
  43. {
  44. if (geiger.Comp.AttachedToSuit)
  45. return;
  46. SetUser(geiger, args.User);
  47. }
  48. private void OnUnequipped(Entity<GeigerComponent> geiger, ref GotUnequippedEvent args)
  49. {
  50. if (geiger.Comp.AttachedToSuit)
  51. SetEnabled(geiger, false);
  52. SetUser(geiger, null);
  53. }
  54. private void OnUnequippedHand(Entity<GeigerComponent> geiger, ref GotUnequippedHandEvent args)
  55. {
  56. if (geiger.Comp.AttachedToSuit)
  57. return;
  58. SetUser(geiger, null);
  59. }
  60. private void OnUpdate(RadiationSystemUpdatedEvent ev)
  61. {
  62. // update only active geiger counters
  63. // deactivated shouldn't have rad receiver component
  64. var query = EntityQueryEnumerator<GeigerComponent, RadiationReceiverComponent>();
  65. while (query.MoveNext(out var uid, out var geiger, out var receiver))
  66. {
  67. var rads = receiver.CurrentRadiation;
  68. SetCurrentRadiation(uid, geiger, rads);
  69. }
  70. }
  71. private void SetCurrentRadiation(EntityUid uid, GeigerComponent component, float rads)
  72. {
  73. // check that it's approx equal
  74. if (MathHelper.CloseTo(component.CurrentRadiation, rads, ApproxEqual))
  75. return;
  76. var curLevel = component.DangerLevel;
  77. var newLevel = RadsToLevel(rads);
  78. component.CurrentRadiation = rads;
  79. component.DangerLevel = newLevel;
  80. if (curLevel != newLevel)
  81. {
  82. UpdateAppearance(uid, component);
  83. UpdateSound(uid, component);
  84. }
  85. Dirty(uid, component);
  86. }
  87. private void SetUser(Entity<GeigerComponent> component, EntityUid? user)
  88. {
  89. if (component.Comp.User == user)
  90. return;
  91. component.Comp.User = user;
  92. Dirty(component);
  93. UpdateSound(component, component);
  94. }
  95. private void SetEnabled(Entity<GeigerComponent> geiger, bool isEnabled)
  96. {
  97. var component = geiger.Comp;
  98. if (component.IsEnabled == isEnabled)
  99. return;
  100. component.IsEnabled = isEnabled;
  101. if (!isEnabled)
  102. {
  103. component.CurrentRadiation = 0f;
  104. component.DangerLevel = GeigerDangerLevel.None;
  105. }
  106. _radiation.SetCanReceive(geiger, isEnabled);
  107. UpdateAppearance(geiger, component);
  108. UpdateSound(geiger, component);
  109. Dirty(geiger, component);
  110. }
  111. private void UpdateAppearance(EntityUid uid, GeigerComponent? component = null,
  112. AppearanceComponent? appearance = null)
  113. {
  114. if (!Resolve(uid, ref component, ref appearance, false))
  115. return;
  116. _appearance.SetData(uid, GeigerVisuals.IsEnabled, component.IsEnabled, appearance);
  117. _appearance.SetData(uid, GeigerVisuals.DangerLevel, component.DangerLevel, appearance);
  118. }
  119. private void UpdateSound(EntityUid uid, GeigerComponent? component = null)
  120. {
  121. if (!Resolve(uid, ref component, false))
  122. return;
  123. component.Stream = _audio.Stop(component.Stream);
  124. if (!component.Sounds.TryGetValue(component.DangerLevel, out var sounds))
  125. return;
  126. if (component.User == null)
  127. return;
  128. if (!_player.TryGetSessionByEntity(component.User.Value, out var session))
  129. return;
  130. var sound = _audio.ResolveSound(sounds);
  131. var param = sounds.Params.WithLoop(true).WithVolume(-4f);
  132. component.Stream = _audio.PlayGlobal(sound, session, param)?.Entity;
  133. }
  134. public static GeigerDangerLevel RadsToLevel(float rads)
  135. {
  136. return rads switch
  137. {
  138. < 0.2f => GeigerDangerLevel.None,
  139. < 1f => GeigerDangerLevel.Low,
  140. < 3f => GeigerDangerLevel.Med,
  141. < 6f => GeigerDangerLevel.High,
  142. _ => GeigerDangerLevel.Extreme
  143. };
  144. }
  145. }