TriggerSystem.OnUse.cs 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. using Content.Server.Explosion.Components;
  2. using Content.Shared.Examine;
  3. using Content.Shared.Explosion.Components;
  4. using Content.Shared.Interaction.Events;
  5. using Content.Shared.Popups;
  6. using Content.Shared.Sticky;
  7. using Content.Shared.Verbs;
  8. namespace Content.Server.Explosion.EntitySystems;
  9. public sealed partial class TriggerSystem
  10. {
  11. [Dependency] private readonly SharedPopupSystem _popupSystem = default!;
  12. private void InitializeOnUse()
  13. {
  14. SubscribeLocalEvent<OnUseTimerTriggerComponent, UseInHandEvent>(OnTimerUse);
  15. SubscribeLocalEvent<OnUseTimerTriggerComponent, ExaminedEvent>(OnExamined);
  16. SubscribeLocalEvent<OnUseTimerTriggerComponent, GetVerbsEvent<AlternativeVerb>>(OnGetAltVerbs);
  17. SubscribeLocalEvent<OnUseTimerTriggerComponent, EntityStuckEvent>(OnStuck);
  18. SubscribeLocalEvent<RandomTimerTriggerComponent, MapInitEvent>(OnRandomTimerTriggerMapInit);
  19. }
  20. private void OnStuck(EntityUid uid, OnUseTimerTriggerComponent component, ref EntityStuckEvent args)
  21. {
  22. if (!component.StartOnStick)
  23. return;
  24. StartTimer((uid, component), args.User);
  25. }
  26. private void OnExamined(EntityUid uid, OnUseTimerTriggerComponent component, ExaminedEvent args)
  27. {
  28. if (args.IsInDetailsRange && component.Examinable)
  29. args.PushText(Loc.GetString("examine-trigger-timer", ("time", component.Delay)));
  30. }
  31. /// <summary>
  32. /// Add an alt-click interaction that cycles through delays.
  33. /// </summary>
  34. private void OnGetAltVerbs(EntityUid uid, OnUseTimerTriggerComponent component, GetVerbsEvent<AlternativeVerb> args)
  35. {
  36. if (!args.CanInteract || !args.CanAccess || args.Hands == null)
  37. return;
  38. if (component.UseVerbInstead)
  39. {
  40. args.Verbs.Add(new AlternativeVerb()
  41. {
  42. Text = Loc.GetString("verb-start-detonation"),
  43. Act = () => StartTimer((uid, component), args.User),
  44. Priority = 2
  45. });
  46. }
  47. if (component.AllowToggleStartOnStick)
  48. {
  49. args.Verbs.Add(new AlternativeVerb()
  50. {
  51. Text = Loc.GetString("verb-toggle-start-on-stick"),
  52. Act = () => ToggleStartOnStick(uid, args.User, component)
  53. });
  54. }
  55. if (component.DelayOptions == null || component.DelayOptions.Count == 1)
  56. return;
  57. args.Verbs.Add(new AlternativeVerb()
  58. {
  59. Category = TimerOptions,
  60. Text = Loc.GetString("verb-trigger-timer-cycle"),
  61. Act = () => CycleDelay(component, args.User),
  62. Priority = 1
  63. });
  64. foreach (var option in component.DelayOptions)
  65. {
  66. if (MathHelper.CloseTo(option, component.Delay))
  67. {
  68. args.Verbs.Add(new AlternativeVerb()
  69. {
  70. Category = TimerOptions,
  71. Text = Loc.GetString("verb-trigger-timer-set-current", ("time", option)),
  72. Disabled = true,
  73. Priority = (int) (-100 * option)
  74. });
  75. continue;
  76. }
  77. args.Verbs.Add(new AlternativeVerb()
  78. {
  79. Category = TimerOptions,
  80. Text = Loc.GetString("verb-trigger-timer-set", ("time", option)),
  81. Priority = (int) (-100 * option),
  82. Act = () =>
  83. {
  84. component.Delay = option;
  85. _popupSystem.PopupEntity(Loc.GetString("popup-trigger-timer-set", ("time", option)), args.User, args.User);
  86. },
  87. });
  88. }
  89. }
  90. private void OnRandomTimerTriggerMapInit(Entity<RandomTimerTriggerComponent> ent, ref MapInitEvent args)
  91. {
  92. var (_, comp) = ent;
  93. if (!TryComp<OnUseTimerTriggerComponent>(ent, out var timerTriggerComp))
  94. return;
  95. timerTriggerComp.Delay = _random.NextFloat(comp.Min, comp.Max);
  96. }
  97. private void CycleDelay(OnUseTimerTriggerComponent component, EntityUid user)
  98. {
  99. if (component.DelayOptions == null || component.DelayOptions.Count == 1)
  100. return;
  101. // This is somewhat inefficient, but its good enough. This is run rarely, and the lists should be short.
  102. component.DelayOptions.Sort();
  103. if (component.DelayOptions[^1] <= component.Delay)
  104. {
  105. component.Delay = component.DelayOptions[0];
  106. _popupSystem.PopupEntity(Loc.GetString("popup-trigger-timer-set", ("time", component.Delay)), user, user);
  107. return;
  108. }
  109. foreach (var option in component.DelayOptions)
  110. {
  111. if (option > component.Delay)
  112. {
  113. component.Delay = option;
  114. _popupSystem.PopupEntity(Loc.GetString("popup-trigger-timer-set", ("time", option)), user, user);
  115. return;
  116. }
  117. }
  118. }
  119. private void ToggleStartOnStick(EntityUid grenade, EntityUid user, OnUseTimerTriggerComponent comp)
  120. {
  121. if (comp.StartOnStick)
  122. {
  123. comp.StartOnStick = false;
  124. _popupSystem.PopupEntity(Loc.GetString("popup-start-on-stick-off"), grenade, user);
  125. }
  126. else
  127. {
  128. comp.StartOnStick = true;
  129. _popupSystem.PopupEntity(Loc.GetString("popup-start-on-stick-on"), grenade, user);
  130. }
  131. }
  132. private void OnTimerUse(EntityUid uid, OnUseTimerTriggerComponent component, UseInHandEvent args)
  133. {
  134. if (args.Handled || HasComp<AutomatedTimerComponent>(uid) || component.UseVerbInstead)
  135. return;
  136. if (component.DoPopup)
  137. _popupSystem.PopupEntity(Loc.GetString("trigger-activated", ("device", uid)), args.User, args.User);
  138. StartTimer((uid, component), args.User);
  139. args.Handled = true;
  140. }
  141. public static VerbCategory TimerOptions = new("verb-categories-timer", "/Textures/Interface/VerbIcons/clock.svg.192dpi.png");
  142. }