ListeningSystem.cs 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. using Content.Server.Chat.Systems;
  2. using Content.Server.Speech.Components;
  3. namespace Content.Server.Speech.EntitySystems;
  4. /// <summary>
  5. /// This system redirects local chat messages to listening entities (e.g., radio microphones).
  6. /// </summary>
  7. public sealed class ListeningSystem : EntitySystem
  8. {
  9. [Dependency] private readonly SharedTransformSystem _xforms = default!;
  10. public override void Initialize()
  11. {
  12. base.Initialize();
  13. SubscribeLocalEvent<EntitySpokeEvent>(OnSpeak);
  14. }
  15. private void OnSpeak(EntitySpokeEvent ev)
  16. {
  17. PingListeners(ev.Source, ev.Message, ev.ObfuscatedMessage);
  18. }
  19. public void PingListeners(EntityUid source, string message, string? obfuscatedMessage)
  20. {
  21. // TODO whispering / audio volume? Microphone sensitivity?
  22. // for now, whispering just arbitrarily reduces the listener's max range.
  23. var xformQuery = GetEntityQuery<TransformComponent>();
  24. var sourceXform = xformQuery.GetComponent(source);
  25. var sourcePos = _xforms.GetWorldPosition(sourceXform, xformQuery);
  26. var attemptEv = new ListenAttemptEvent(source);
  27. var ev = new ListenEvent(message, source);
  28. var obfuscatedEv = obfuscatedMessage == null ? null : new ListenEvent(obfuscatedMessage, source);
  29. var query = EntityQueryEnumerator<ActiveListenerComponent, TransformComponent>();
  30. while(query.MoveNext(out var listenerUid, out var listener, out var xform))
  31. {
  32. if (xform.MapID != sourceXform.MapID)
  33. continue;
  34. // range checks
  35. // TODO proper speech occlusion
  36. var distance = (sourcePos - _xforms.GetWorldPosition(xform, xformQuery)).LengthSquared();
  37. if (distance > listener.Range * listener.Range)
  38. continue;
  39. RaiseLocalEvent(listenerUid, attemptEv);
  40. if (attemptEv.Cancelled)
  41. {
  42. attemptEv.Uncancel();
  43. continue;
  44. }
  45. if (obfuscatedEv != null && distance > ChatSystem.WhisperClearRange)
  46. RaiseLocalEvent(listenerUid, obfuscatedEv);
  47. else
  48. RaiseLocalEvent(listenerUid, ev);
  49. }
  50. }
  51. }