1
0

GhostSystem.cs 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. using Content.Client.Movement.Systems;
  2. using Content.Shared.Actions;
  3. using Content.Shared.Ghost;
  4. using Robust.Client.Console;
  5. using Robust.Client.GameObjects;
  6. using Robust.Client.Player;
  7. using Robust.Shared.Player;
  8. namespace Content.Client.Ghost
  9. {
  10. public sealed class GhostSystem : SharedGhostSystem
  11. {
  12. [Dependency] private readonly IClientConsoleHost _console = default!;
  13. [Dependency] private readonly IPlayerManager _playerManager = default!;
  14. [Dependency] private readonly SharedActionsSystem _actions = default!;
  15. [Dependency] private readonly PointLightSystem _pointLightSystem = default!;
  16. [Dependency] private readonly ContentEyeSystem _contentEye = default!;
  17. public int AvailableGhostRoleCount { get; private set; }
  18. private bool _ghostVisibility = true;
  19. private bool GhostVisibility
  20. {
  21. get => _ghostVisibility;
  22. set
  23. {
  24. if (_ghostVisibility == value)
  25. {
  26. return;
  27. }
  28. _ghostVisibility = value;
  29. var query = AllEntityQuery<GhostComponent, SpriteComponent>();
  30. while (query.MoveNext(out var uid, out _, out var sprite))
  31. {
  32. sprite.Visible = value || uid == _playerManager.LocalEntity;
  33. }
  34. }
  35. }
  36. public GhostComponent? Player => CompOrNull<GhostComponent>(_playerManager.LocalEntity);
  37. public bool IsGhost => Player != null;
  38. public event Action<GhostComponent>? PlayerRemoved;
  39. public event Action<GhostComponent>? PlayerUpdated;
  40. public event Action<GhostComponent>? PlayerAttached;
  41. public event Action? PlayerDetached;
  42. public event Action<GhostWarpsResponseEvent>? GhostWarpsResponse;
  43. public event Action<GhostUpdateGhostRoleCountEvent>? GhostRoleCountUpdated;
  44. public override void Initialize()
  45. {
  46. base.Initialize();
  47. SubscribeLocalEvent<GhostComponent, ComponentStartup>(OnStartup);
  48. SubscribeLocalEvent<GhostComponent, ComponentRemove>(OnGhostRemove);
  49. SubscribeLocalEvent<GhostComponent, AfterAutoHandleStateEvent>(OnGhostState);
  50. SubscribeLocalEvent<GhostComponent, LocalPlayerAttachedEvent>(OnGhostPlayerAttach);
  51. SubscribeLocalEvent<GhostComponent, LocalPlayerDetachedEvent>(OnGhostPlayerDetach);
  52. SubscribeNetworkEvent<GhostWarpsResponseEvent>(OnGhostWarpsResponse);
  53. SubscribeNetworkEvent<GhostUpdateGhostRoleCountEvent>(OnUpdateGhostRoleCount);
  54. SubscribeLocalEvent<EyeComponent, ToggleLightingActionEvent>(OnToggleLighting);
  55. SubscribeLocalEvent<EyeComponent, ToggleFoVActionEvent>(OnToggleFoV);
  56. SubscribeLocalEvent<GhostComponent, ToggleGhostsActionEvent>(OnToggleGhosts);
  57. }
  58. private void OnStartup(EntityUid uid, GhostComponent component, ComponentStartup args)
  59. {
  60. if (TryComp(uid, out SpriteComponent? sprite))
  61. sprite.Visible = GhostVisibility || uid == _playerManager.LocalEntity;
  62. }
  63. private void OnToggleLighting(EntityUid uid, EyeComponent component, ToggleLightingActionEvent args)
  64. {
  65. if (args.Handled)
  66. return;
  67. TryComp<PointLightComponent>(uid, out var light);
  68. if (!component.DrawLight)
  69. {
  70. // normal lighting
  71. Popup.PopupEntity(Loc.GetString("ghost-gui-toggle-lighting-manager-popup-normal"), args.Performer);
  72. _contentEye.RequestEye(component.DrawFov, true);
  73. }
  74. else if (!light?.Enabled ?? false) // skip this option if we have no PointLightComponent
  75. {
  76. // enable personal light
  77. Popup.PopupEntity(Loc.GetString("ghost-gui-toggle-lighting-manager-popup-personal-light"), args.Performer);
  78. _pointLightSystem.SetEnabled(uid, true, light);
  79. }
  80. else
  81. {
  82. // fullbright mode
  83. Popup.PopupEntity(Loc.GetString("ghost-gui-toggle-lighting-manager-popup-fullbright"), args.Performer);
  84. _contentEye.RequestEye(component.DrawFov, false);
  85. _pointLightSystem.SetEnabled(uid, false, light);
  86. }
  87. args.Handled = true;
  88. }
  89. private void OnToggleFoV(EntityUid uid, EyeComponent component, ToggleFoVActionEvent args)
  90. {
  91. if (args.Handled)
  92. return;
  93. Popup.PopupEntity(Loc.GetString("ghost-gui-toggle-fov-popup"), args.Performer);
  94. _contentEye.RequestToggleFov(uid, component);
  95. args.Handled = true;
  96. }
  97. private void OnToggleGhosts(EntityUid uid, GhostComponent component, ToggleGhostsActionEvent args)
  98. {
  99. if (args.Handled)
  100. return;
  101. var locId = GhostVisibility ? "ghost-gui-toggle-ghost-visibility-popup-off" : "ghost-gui-toggle-ghost-visibility-popup-on";
  102. Popup.PopupEntity(Loc.GetString(locId), args.Performer);
  103. if (uid == _playerManager.LocalEntity)
  104. ToggleGhostVisibility();
  105. args.Handled = true;
  106. }
  107. private void OnGhostRemove(EntityUid uid, GhostComponent component, ComponentRemove args)
  108. {
  109. _actions.RemoveAction(uid, component.ToggleLightingActionEntity);
  110. _actions.RemoveAction(uid, component.ToggleFoVActionEntity);
  111. _actions.RemoveAction(uid, component.ToggleGhostsActionEntity);
  112. _actions.RemoveAction(uid, component.ToggleGhostHearingActionEntity);
  113. if (uid != _playerManager.LocalEntity)
  114. return;
  115. GhostVisibility = false;
  116. PlayerRemoved?.Invoke(component);
  117. }
  118. private void OnGhostPlayerAttach(EntityUid uid, GhostComponent component, LocalPlayerAttachedEvent localPlayerAttachedEvent)
  119. {
  120. GhostVisibility = true;
  121. PlayerAttached?.Invoke(component);
  122. }
  123. private void OnGhostState(EntityUid uid, GhostComponent component, ref AfterAutoHandleStateEvent args)
  124. {
  125. if (TryComp<SpriteComponent>(uid, out var sprite))
  126. sprite.LayerSetColor(0, component.Color);
  127. if (uid != _playerManager.LocalEntity)
  128. return;
  129. PlayerUpdated?.Invoke(component);
  130. }
  131. private void OnGhostPlayerDetach(EntityUid uid, GhostComponent component, LocalPlayerDetachedEvent args)
  132. {
  133. GhostVisibility = false;
  134. PlayerDetached?.Invoke();
  135. }
  136. private void OnGhostWarpsResponse(GhostWarpsResponseEvent msg)
  137. {
  138. if (!IsGhost)
  139. {
  140. return;
  141. }
  142. GhostWarpsResponse?.Invoke(msg);
  143. }
  144. private void OnUpdateGhostRoleCount(GhostUpdateGhostRoleCountEvent msg)
  145. {
  146. AvailableGhostRoleCount = msg.AvailableGhostRoles;
  147. GhostRoleCountUpdated?.Invoke(msg);
  148. }
  149. public void RequestWarps()
  150. {
  151. RaiseNetworkEvent(new GhostWarpsRequestEvent());
  152. }
  153. public void ReturnToBody()
  154. {
  155. var msg = new GhostReturnToBodyRequest();
  156. RaiseNetworkEvent(msg);
  157. }
  158. public void ReturnToLobby()
  159. {
  160. var msg = new GhostReturnToLobbyRequest();
  161. RaiseNetworkEvent(msg);
  162. }
  163. public void OpenGhostRoles()
  164. {
  165. _console.RemoteExecuteCommand(null, "ghostroles");
  166. }
  167. public void ToggleGhostVisibility(bool? visibility = null)
  168. {
  169. GhostVisibility = visibility ?? !GhostVisibility;
  170. }
  171. }
  172. }