ToggleableGhostRoleSystem.cs 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. using Content.Server.Ghost.Roles.Components;
  2. using Content.Shared.Examine;
  3. using Content.Shared.Interaction.Events;
  4. using Content.Shared.Mind;
  5. using Content.Shared.Mind.Components;
  6. using Content.Shared.Popups;
  7. using Content.Shared.Verbs;
  8. namespace Content.Server.Ghost.Roles;
  9. /// <summary>
  10. /// This handles logic and interaction related to <see cref="ToggleableGhostRoleComponent"/>
  11. /// </summary>
  12. public sealed class ToggleableGhostRoleSystem : EntitySystem
  13. {
  14. [Dependency] private readonly SharedAppearanceSystem _appearance = default!;
  15. [Dependency] private readonly SharedPopupSystem _popup = default!;
  16. [Dependency] private readonly SharedMindSystem _mind = default!;
  17. /// <inheritdoc/>
  18. public override void Initialize()
  19. {
  20. SubscribeLocalEvent<ToggleableGhostRoleComponent, UseInHandEvent>(OnUseInHand);
  21. SubscribeLocalEvent<ToggleableGhostRoleComponent, ExaminedEvent>(OnExamined);
  22. SubscribeLocalEvent<ToggleableGhostRoleComponent, MindAddedMessage>(OnMindAdded);
  23. SubscribeLocalEvent<ToggleableGhostRoleComponent, MindRemovedMessage>(OnMindRemoved);
  24. SubscribeLocalEvent<ToggleableGhostRoleComponent, GetVerbsEvent<ActivationVerb>>(AddWipeVerb);
  25. }
  26. private void OnUseInHand(EntityUid uid, ToggleableGhostRoleComponent component, UseInHandEvent args)
  27. {
  28. if (args.Handled)
  29. return;
  30. args.Handled = true;
  31. // check if a mind is present
  32. if (TryComp<MindContainerComponent>(uid, out var mind) && mind.HasMind)
  33. {
  34. _popup.PopupEntity(Loc.GetString(component.ExamineTextMindPresent), uid, args.User, PopupType.Large);
  35. return;
  36. }
  37. if (HasComp<GhostTakeoverAvailableComponent>(uid))
  38. {
  39. _popup.PopupEntity(Loc.GetString(component.ExamineTextMindSearching), uid, args.User);
  40. return;
  41. }
  42. _popup.PopupEntity(Loc.GetString(component.BeginSearchingText), uid, args.User);
  43. UpdateAppearance(uid, ToggleableGhostRoleStatus.Searching);
  44. var ghostRole = EnsureComp<GhostRoleComponent>(uid);
  45. EnsureComp<GhostTakeoverAvailableComponent>(uid);
  46. //GhostRoleComponent inherits custom settings from the ToggleableGhostRoleComponent
  47. ghostRole.RoleName = Loc.GetString(component.RoleName);
  48. ghostRole.RoleDescription = Loc.GetString(component.RoleDescription);
  49. ghostRole.RoleRules = Loc.GetString(component.RoleRules);
  50. ghostRole.JobProto = component.JobProto;
  51. ghostRole.MindRoles = component.MindRoles;
  52. }
  53. private void OnExamined(EntityUid uid, ToggleableGhostRoleComponent component, ExaminedEvent args)
  54. {
  55. if (!args.IsInDetailsRange)
  56. return;
  57. if (TryComp<MindContainerComponent>(uid, out var mind) && mind.HasMind)
  58. {
  59. args.PushMarkup(Loc.GetString(component.ExamineTextMindPresent));
  60. }
  61. else if (HasComp<GhostTakeoverAvailableComponent>(uid))
  62. {
  63. args.PushMarkup(Loc.GetString(component.ExamineTextMindSearching));
  64. }
  65. else
  66. {
  67. args.PushMarkup(Loc.GetString(component.ExamineTextNoMind));
  68. }
  69. }
  70. private void OnMindAdded(EntityUid uid, ToggleableGhostRoleComponent pai, MindAddedMessage args)
  71. {
  72. // Mind was added, shutdown the ghost role stuff so it won't get in the way
  73. RemCompDeferred<GhostTakeoverAvailableComponent>(uid);
  74. UpdateAppearance(uid, ToggleableGhostRoleStatus.On);
  75. }
  76. private void OnMindRemoved(EntityUid uid, ToggleableGhostRoleComponent component, MindRemovedMessage args)
  77. {
  78. // Mind was removed, prepare for re-toggle of the role
  79. RemCompDeferred<GhostRoleComponent>(uid);
  80. UpdateAppearance(uid, ToggleableGhostRoleStatus.Off);
  81. }
  82. private void UpdateAppearance(EntityUid uid, ToggleableGhostRoleStatus status)
  83. {
  84. _appearance.SetData(uid, ToggleableGhostRoleVisuals.Status, status);
  85. }
  86. private void AddWipeVerb(EntityUid uid, ToggleableGhostRoleComponent component, GetVerbsEvent<ActivationVerb> args)
  87. {
  88. if (args.Hands == null || !args.CanAccess || !args.CanInteract)
  89. return;
  90. if (TryComp<MindContainerComponent>(uid, out var mind) && mind.HasMind)
  91. {
  92. ActivationVerb verb = new()
  93. {
  94. Text = Loc.GetString(component.WipeVerbText),
  95. Act = () =>
  96. {
  97. if (!_mind.TryGetMind(uid, out var mindId, out var mind))
  98. return;
  99. // Wiping device :(
  100. // The shutdown of the Mind should cause automatic reset of the pAI during OnMindRemoved
  101. _mind.TransferTo(mindId, null, mind: mind);
  102. _popup.PopupEntity(Loc.GetString(component.WipeVerbPopup), uid, args.User, PopupType.Large);
  103. }
  104. };
  105. args.Verbs.Add(verb);
  106. }
  107. else if (HasComp<GhostTakeoverAvailableComponent>(uid))
  108. {
  109. ActivationVerb verb = new()
  110. {
  111. Text = Loc.GetString(component.StopSearchVerbText),
  112. Act = () =>
  113. {
  114. if (component.Deleted || !HasComp<GhostTakeoverAvailableComponent>(uid))
  115. return;
  116. RemCompDeferred<GhostTakeoverAvailableComponent>(uid);
  117. RemCompDeferred<GhostRoleComponent>(uid);
  118. _popup.PopupEntity(Loc.GetString(component.StopSearchVerbPopup), uid, args.User);
  119. UpdateAppearance(uid, ToggleableGhostRoleStatus.Off);
  120. }
  121. };
  122. args.Verbs.Add(verb);
  123. }
  124. }
  125. /// <summary>
  126. /// If there is a player present, kicks it out.
  127. /// If not, prevents future ghosts taking it.
  128. /// No popups are made, but appearance is updated.
  129. /// </summary>
  130. public void Wipe(EntityUid uid)
  131. {
  132. if (TryComp<MindContainerComponent>(uid, out var mindContainer) &&
  133. mindContainer.HasMind &&
  134. _mind.TryGetMind(uid, out var mindId, out var mind))
  135. {
  136. _mind.TransferTo(mindId, null, mind: mind);
  137. }
  138. if (!HasComp<GhostTakeoverAvailableComponent>(uid))
  139. return;
  140. RemCompDeferred<GhostTakeoverAvailableComponent>(uid);
  141. RemCompDeferred<GhostRoleComponent>(uid);
  142. UpdateAppearance(uid, ToggleableGhostRoleStatus.Off);
  143. }
  144. }