SpaceNinjaSystem.cs 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. using Content.Server.Communications;
  2. using Content.Server.Chat.Managers;
  3. using Content.Server.CriminalRecords.Systems;
  4. using Content.Server.GameTicking.Rules.Components;
  5. using Content.Server.Objectives.Components;
  6. using Content.Server.Objectives.Systems;
  7. using Content.Server.Power.Components;
  8. using Content.Server.Power.EntitySystems;
  9. using Content.Server.PowerCell;
  10. using Content.Server.Research.Systems;
  11. using Content.Server.Roles;
  12. using Content.Shared.Alert;
  13. using Content.Shared.Doors.Components;
  14. using Content.Shared.IdentityManagement;
  15. using Content.Shared.Mind;
  16. using Content.Shared.Ninja.Components;
  17. using Content.Shared.Ninja.Systems;
  18. using Content.Shared.Popups;
  19. using Content.Shared.Rounding;
  20. using Robust.Shared.Audio;
  21. using Robust.Shared.Player;
  22. using System.Diagnostics.CodeAnalysis;
  23. using Robust.Shared.Audio.Systems;
  24. namespace Content.Server.Ninja.Systems;
  25. /// <summary>
  26. /// Main ninja system that handles ninja setup, provides helper methods for the rest of the code to use.
  27. /// </summary>
  28. public sealed class SpaceNinjaSystem : SharedSpaceNinjaSystem
  29. {
  30. [Dependency] private readonly AlertsSystem _alerts = default!;
  31. [Dependency] private readonly BatterySystem _battery = default!;
  32. [Dependency] private readonly CodeConditionSystem _codeCondition = default!;
  33. [Dependency] private readonly PowerCellSystem _powerCell = default!;
  34. [Dependency] private readonly SharedMindSystem _mind = default!;
  35. public override void Initialize()
  36. {
  37. base.Initialize();
  38. SubscribeLocalEvent<SpaceNinjaComponent, EmaggedSomethingEvent>(OnDoorjack);
  39. SubscribeLocalEvent<SpaceNinjaComponent, ResearchStolenEvent>(OnResearchStolen);
  40. SubscribeLocalEvent<SpaceNinjaComponent, ThreatCalledInEvent>(OnThreatCalledIn);
  41. SubscribeLocalEvent<SpaceNinjaComponent, CriminalRecordsHackedEvent>(OnCriminalRecordsHacked);
  42. }
  43. public override void Update(float frameTime)
  44. {
  45. var query = EntityQueryEnumerator<SpaceNinjaComponent>();
  46. while (query.MoveNext(out var uid, out var ninja))
  47. {
  48. SetSuitPowerAlert((uid, ninja));
  49. }
  50. }
  51. /// <summary>
  52. /// Download the given set of nodes, returning how many new nodes were downloaded.
  53. /// </summary>
  54. private int Download(EntityUid uid, List<string> ids)
  55. {
  56. if (!_mind.TryGetObjectiveComp<StealResearchConditionComponent>(uid, out var obj))
  57. return 0;
  58. var oldCount = obj.DownloadedNodes.Count;
  59. obj.DownloadedNodes.UnionWith(ids);
  60. var newCount = obj.DownloadedNodes.Count;
  61. return newCount - oldCount;
  62. }
  63. // TODO: can probably copy paste borg code here
  64. /// <summary>
  65. /// Update the alert for the ninja's suit power indicator.
  66. /// </summary>
  67. public void SetSuitPowerAlert(Entity<SpaceNinjaComponent> ent)
  68. {
  69. var (uid, comp) = ent;
  70. if (comp.Deleted || comp.Suit == null)
  71. {
  72. _alerts.ClearAlert(uid, comp.SuitPowerAlert);
  73. return;
  74. }
  75. if (GetNinjaBattery(uid, out _, out var battery))
  76. {
  77. var severity = ContentHelpers.RoundToLevels(MathF.Max(0f, battery.CurrentCharge), battery.MaxCharge, 8);
  78. _alerts.ShowAlert(uid, comp.SuitPowerAlert, (short) severity);
  79. }
  80. else
  81. {
  82. _alerts.ClearAlert(uid, comp.SuitPowerAlert);
  83. }
  84. }
  85. /// <summary>
  86. /// Get the battery component in a ninja's suit, if it's worn.
  87. /// </summary>
  88. public bool GetNinjaBattery(EntityUid user, [NotNullWhen(true)] out EntityUid? uid, [NotNullWhen(true)] out BatteryComponent? battery)
  89. {
  90. if (TryComp<SpaceNinjaComponent>(user, out var ninja)
  91. && ninja.Suit != null
  92. && _powerCell.TryGetBatteryFromSlot(ninja.Suit.Value, out uid, out battery))
  93. {
  94. return true;
  95. }
  96. uid = null;
  97. battery = null;
  98. return false;
  99. }
  100. /// <inheritdoc/>
  101. public override bool TryUseCharge(EntityUid user, float charge)
  102. {
  103. return GetNinjaBattery(user, out var uid, out var battery) && _battery.TryUseCharge(uid.Value, charge, battery);
  104. }
  105. /// <summary>
  106. /// Increment greentext when emagging a door.
  107. /// </summary>
  108. private void OnDoorjack(EntityUid uid, SpaceNinjaComponent comp, ref EmaggedSomethingEvent args)
  109. {
  110. // incase someone lets ninja emag non-doors double check it here
  111. if (!HasComp<DoorComponent>(args.Target))
  112. return;
  113. // this popup is serverside since door emag logic is serverside (power funnies)
  114. Popup.PopupEntity(Loc.GetString("ninja-doorjack-success", ("target", Identity.Entity(args.Target, EntityManager))), uid, uid, PopupType.Medium);
  115. // handle greentext
  116. if (_mind.TryGetObjectiveComp<DoorjackConditionComponent>(uid, out var obj))
  117. obj.DoorsJacked++;
  118. }
  119. /// <summary>
  120. /// Add to greentext when stealing technologies.
  121. /// </summary>
  122. private void OnResearchStolen(EntityUid uid, SpaceNinjaComponent comp, ref ResearchStolenEvent args)
  123. {
  124. var gained = Download(uid, args.Techs);
  125. var str = gained == 0
  126. ? Loc.GetString("ninja-research-steal-fail")
  127. : Loc.GetString("ninja-research-steal-success", ("count", gained), ("server", args.Target));
  128. Popup.PopupEntity(str, uid, uid, PopupType.Medium);
  129. }
  130. private void OnThreatCalledIn(Entity<SpaceNinjaComponent> ent, ref ThreatCalledInEvent args)
  131. {
  132. _codeCondition.SetCompleted(ent.Owner, ent.Comp.TerrorObjective);
  133. }
  134. private void OnCriminalRecordsHacked(Entity<SpaceNinjaComponent> ent, ref CriminalRecordsHackedEvent args)
  135. {
  136. _codeCondition.SetCompleted(ent.Owner, ent.Comp.MassArrestObjective);
  137. }
  138. /// <summary>
  139. /// Called by <see cref="SpiderChargeSystem"/> when it detonates.
  140. /// </summary>
  141. public void DetonatedSpiderCharge(Entity<SpaceNinjaComponent> ent)
  142. {
  143. _codeCondition.SetCompleted(ent.Owner, ent.Comp.SpiderChargeObjective);
  144. }
  145. }