SharedGunSystem.Interactions.cs 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. using Content.Shared.Actions;
  2. using Content.Shared.Examine;
  3. using Content.Shared.Hands;
  4. using Content.Shared.Verbs;
  5. using Content.Shared.Weapons.Ranged.Components;
  6. using Robust.Shared.Utility;
  7. namespace Content.Shared.Weapons.Ranged.Systems;
  8. public abstract partial class SharedGunSystem
  9. {
  10. private void OnExamine(EntityUid uid, GunComponent component, ExaminedEvent args)
  11. {
  12. if (!args.IsInDetailsRange || !component.ShowExamineText)
  13. return;
  14. using (args.PushGroup(nameof(GunComponent)))
  15. {
  16. args.PushMarkup(Loc.GetString("gun-selected-mode-examine", ("color", ModeExamineColor),
  17. ("mode", GetLocSelector(component.SelectedMode))));
  18. args.PushMarkup(Loc.GetString("gun-fire-rate-examine", ("color", FireRateExamineColor),
  19. ("fireRate", $"{component.FireRateModified:0.0}")));
  20. }
  21. }
  22. private string GetLocSelector(SelectiveFire mode)
  23. {
  24. return Loc.GetString($"gun-{mode.ToString()}");
  25. }
  26. private void OnAltVerb(EntityUid uid, GunComponent component, GetVerbsEvent<AlternativeVerb> args)
  27. {
  28. if (!args.CanAccess || !args.CanInteract || component.SelectedMode == component.AvailableModes)
  29. return;
  30. var nextMode = GetNextMode(component);
  31. AlternativeVerb verb = new()
  32. {
  33. Act = () => SelectFire(uid, component, nextMode, args.User),
  34. Text = Loc.GetString("gun-selector-verb", ("mode", GetLocSelector(nextMode))),
  35. Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/VerbIcons/fold.svg.192dpi.png")),
  36. };
  37. args.Verbs.Add(verb);
  38. }
  39. private SelectiveFire GetNextMode(GunComponent component)
  40. {
  41. var modes = new List<SelectiveFire>();
  42. foreach (var mode in Enum.GetValues<SelectiveFire>())
  43. {
  44. if ((mode & component.AvailableModes) == 0x0)
  45. continue;
  46. modes.Add(mode);
  47. }
  48. var index = modes.IndexOf(component.SelectedMode);
  49. return modes[(index + 1) % modes.Count];
  50. }
  51. private void SelectFire(EntityUid uid, GunComponent component, SelectiveFire fire, EntityUid? user = null)
  52. {
  53. if (component.SelectedMode == fire)
  54. return;
  55. DebugTools.Assert((component.AvailableModes & fire) != 0x0);
  56. component.SelectedMode = fire;
  57. if (!Paused(uid))
  58. {
  59. var curTime = Timing.CurTime;
  60. var cooldown = TimeSpan.FromSeconds(InteractNextFire);
  61. if (component.NextFire < curTime)
  62. component.NextFire = curTime + cooldown;
  63. else
  64. component.NextFire += cooldown;
  65. }
  66. Audio.PlayPredicted(component.SoundMode, uid, user);
  67. Popup(Loc.GetString("gun-selected-mode", ("mode", GetLocSelector(fire))), uid, user);
  68. Dirty(uid, component);
  69. }
  70. /// <summary>
  71. /// Cycles the gun's <see cref="SelectiveFire"/> to the next available one.
  72. /// </summary>
  73. public void CycleFire(EntityUid uid, GunComponent component, EntityUid? user = null)
  74. {
  75. // Noop
  76. if (component.SelectedMode == component.AvailableModes)
  77. return;
  78. DebugTools.Assert((component.AvailableModes & component.SelectedMode) == component.SelectedMode);
  79. var nextMode = GetNextMode(component);
  80. SelectFire(uid, component, nextMode, user);
  81. }
  82. // TODO: Actions need doing for guns anyway.
  83. private sealed partial class CycleModeEvent : InstantActionEvent
  84. {
  85. public SelectiveFire Mode = default;
  86. }
  87. private void OnCycleMode(EntityUid uid, GunComponent component, CycleModeEvent args)
  88. {
  89. SelectFire(uid, component, args.Mode, args.Performer);
  90. }
  91. private void OnGunSelected(EntityUid uid, GunComponent component, HandSelectedEvent args)
  92. {
  93. if (Timing.ApplyingState)
  94. return;
  95. if (component.FireRateModified <= 0)
  96. return;
  97. var fireDelay = 1f / component.FireRateModified;
  98. if (fireDelay.Equals(0f))
  99. return;
  100. if (!component.ResetOnHandSelected)
  101. return;
  102. if (Paused(uid))
  103. return;
  104. // If someone swaps to this weapon then reset its cd.
  105. var curTime = Timing.CurTime;
  106. var minimum = curTime + TimeSpan.FromSeconds(fireDelay);
  107. if (minimum < component.NextFire)
  108. return;
  109. component.NextFire = minimum;
  110. Dirty(uid, component);
  111. }
  112. }