1
0

CommsHackerSystem.cs 3.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. using Content.Server.Chat.Systems;
  2. using Content.Server.GameTicking;
  3. using Content.Server.Ninja.Systems;
  4. using Content.Shared.Communications;
  5. using Content.Shared.DoAfter;
  6. using Content.Shared.Interaction;
  7. using Content.Shared.Random;
  8. using Content.Shared.Random.Helpers;
  9. using Robust.Shared.Prototypes;
  10. using Robust.Shared.Random;
  11. using Robust.Shared.Serialization;
  12. namespace Content.Server.Communications;
  13. public sealed class CommsHackerSystem : SharedCommsHackerSystem
  14. {
  15. [Dependency] private readonly ChatSystem _chat = default!;
  16. [Dependency] private readonly GameTicker _gameTicker = default!;
  17. [Dependency] private readonly IPrototypeManager _proto = default!;
  18. [Dependency] private readonly IRobustRandom _random = default!;
  19. // TODO: remove when generic check event is used
  20. [Dependency] private readonly NinjaGlovesSystem _gloves = default!;
  21. [Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
  22. public override void Initialize()
  23. {
  24. base.Initialize();
  25. SubscribeLocalEvent<CommsHackerComponent, BeforeInteractHandEvent>(OnBeforeInteractHand);
  26. SubscribeLocalEvent<CommsHackerComponent, TerrorDoAfterEvent>(OnDoAfter);
  27. }
  28. /// <summary>
  29. /// Start the doafter to hack a comms console
  30. /// </summary>
  31. private void OnBeforeInteractHand(EntityUid uid, CommsHackerComponent comp, BeforeInteractHandEvent args)
  32. {
  33. if (args.Handled || !HasComp<CommunicationsConsoleComponent>(args.Target))
  34. return;
  35. // TODO: generic check event
  36. if (!_gloves.AbilityCheck(uid, args, out var target))
  37. return;
  38. var doAfterArgs = new DoAfterArgs(EntityManager, uid, comp.Delay, new TerrorDoAfterEvent(), target: target, used: uid, eventTarget: uid)
  39. {
  40. BreakOnDamage = true,
  41. BreakOnMove = true,
  42. MovementThreshold = 0.5f,
  43. CancelDuplicate = false
  44. };
  45. _doAfter.TryStartDoAfter(doAfterArgs);
  46. args.Handled = true;
  47. }
  48. /// <summary>
  49. /// Call in a random threat and do cleanup.
  50. /// </summary>
  51. private void OnDoAfter(EntityUid uid, CommsHackerComponent comp, TerrorDoAfterEvent args)
  52. {
  53. if (args.Cancelled || args.Handled || args.Target == null)
  54. return;
  55. var threats = _proto.Index<WeightedRandomPrototype>(comp.Threats);
  56. var threat = threats.Pick(_random);
  57. CallInThreat(_proto.Index<NinjaHackingThreatPrototype>(threat));
  58. // prevent calling in multiple threats
  59. RemComp<CommsHackerComponent>(uid);
  60. var ev = new ThreatCalledInEvent(uid, args.Target.Value);
  61. RaiseLocalEvent(args.User, ref ev);
  62. }
  63. /// <summary>
  64. /// Makes announcement and adds game rule of the threat.
  65. /// </summary>
  66. public void CallInThreat(NinjaHackingThreatPrototype ninjaHackingThreat)
  67. {
  68. _gameTicker.StartGameRule(ninjaHackingThreat.Rule, out _);
  69. _chat.DispatchGlobalAnnouncement(Loc.GetString(ninjaHackingThreat.Announcement), playSound: true, colorOverride: Color.Red);
  70. }
  71. }
  72. /// <summary>
  73. /// Raised on the user when a threat is called in on the communications console.
  74. /// </summary>
  75. /// <remarks>
  76. /// If you add <see cref="CommsHackerComponent"/>, make sure to use this event to prevent adding it twice.
  77. /// For example, you could add a marker component after a threat is called in then check if the user doesn't have that marker before adding CommsHackerComponent.
  78. /// </remarks>
  79. [ByRefEvent]
  80. public record struct ThreatCalledInEvent(EntityUid Used, EntityUid Target);