1
0

SharedPinpointerSystem.cs 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. using Content.Shared.Administration.Logs;
  2. using Content.Shared.Database;
  3. using Content.Shared.Emag.Systems;
  4. using Content.Shared.Examine;
  5. using Content.Shared.IdentityManagement;
  6. using Content.Shared.Interaction;
  7. namespace Content.Shared.Pinpointer;
  8. public abstract class SharedPinpointerSystem : EntitySystem
  9. {
  10. [Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
  11. [Dependency] private readonly EmagSystem _emag = default!;
  12. public override void Initialize()
  13. {
  14. base.Initialize();
  15. SubscribeLocalEvent<PinpointerComponent, GotEmaggedEvent>(OnEmagged);
  16. SubscribeLocalEvent<PinpointerComponent, AfterInteractEvent>(OnAfterInteract);
  17. SubscribeLocalEvent<PinpointerComponent, ExaminedEvent>(OnExamined);
  18. }
  19. /// <summary>
  20. /// Set the target if capable
  21. /// </summary>
  22. private void OnAfterInteract(EntityUid uid, PinpointerComponent component, AfterInteractEvent args)
  23. {
  24. if (!args.CanReach || args.Target is not { } target)
  25. return;
  26. if (!component.CanRetarget || component.IsActive)
  27. return;
  28. // TODO add doafter once the freeze is lifted
  29. args.Handled = true;
  30. component.Target = args.Target;
  31. _adminLogger.Add(LogType.Action, LogImpact.Low, $"{ToPrettyString(args.User):player} set target of {ToPrettyString(uid):pinpointer} to {ToPrettyString(component.Target.Value):target}");
  32. if (component.UpdateTargetName)
  33. component.TargetName = component.Target == null ? null : Identity.Name(component.Target.Value, EntityManager);
  34. }
  35. /// <summary>
  36. /// Set pinpointers target to track
  37. /// </summary>
  38. public virtual void SetTarget(EntityUid uid, EntityUid? target, PinpointerComponent? pinpointer = null)
  39. {
  40. if (!Resolve(uid, ref pinpointer))
  41. return;
  42. if (pinpointer.Target == target)
  43. return;
  44. pinpointer.Target = target;
  45. if (pinpointer.UpdateTargetName)
  46. pinpointer.TargetName = target == null ? null : Identity.Name(target.Value, EntityManager);
  47. if (pinpointer.IsActive)
  48. UpdateDirectionToTarget(uid, pinpointer);
  49. }
  50. /// <summary>
  51. /// Update direction from pinpointer to selected target (if it was set)
  52. /// </summary>
  53. protected virtual void UpdateDirectionToTarget(EntityUid uid, PinpointerComponent? pinpointer = null)
  54. {
  55. }
  56. private void OnExamined(EntityUid uid, PinpointerComponent component, ExaminedEvent args)
  57. {
  58. if (!args.IsInDetailsRange || component.TargetName == null)
  59. return;
  60. args.PushMarkup(Loc.GetString("examine-pinpointer-linked", ("target", component.TargetName)));
  61. }
  62. /// <summary>
  63. /// Manually set distance from pinpointer to target
  64. /// </summary>
  65. public void SetDistance(EntityUid uid, Distance distance, PinpointerComponent? pinpointer = null)
  66. {
  67. if (!Resolve(uid, ref pinpointer))
  68. return;
  69. if (distance == pinpointer.DistanceToTarget)
  70. return;
  71. pinpointer.DistanceToTarget = distance;
  72. Dirty(uid, pinpointer);
  73. }
  74. /// <summary>
  75. /// Try to manually set pinpointer arrow direction.
  76. /// If difference between current angle and new angle is smaller than
  77. /// pinpointer precision, new value will be ignored and it will return false.
  78. /// </summary>
  79. public bool TrySetArrowAngle(EntityUid uid, Angle arrowAngle, PinpointerComponent? pinpointer = null)
  80. {
  81. if (!Resolve(uid, ref pinpointer))
  82. return false;
  83. if (pinpointer.ArrowAngle.EqualsApprox(arrowAngle, pinpointer.Precision))
  84. return false;
  85. pinpointer.ArrowAngle = arrowAngle;
  86. Dirty(uid, pinpointer);
  87. return true;
  88. }
  89. /// <summary>
  90. /// Activate/deactivate pinpointer screen. If it has target it will start tracking it.
  91. /// </summary>
  92. public void SetActive(EntityUid uid, bool isActive, PinpointerComponent? pinpointer = null)
  93. {
  94. if (!Resolve(uid, ref pinpointer))
  95. return;
  96. if (isActive == pinpointer.IsActive)
  97. return;
  98. pinpointer.IsActive = isActive;
  99. Dirty(uid, pinpointer);
  100. }
  101. /// <summary>
  102. /// Toggle Pinpointer screen. If it has target it will start tracking it.
  103. /// </summary>
  104. /// <returns>True if pinpointer was activated, false otherwise</returns>
  105. public virtual bool TogglePinpointer(EntityUid uid, PinpointerComponent? pinpointer = null)
  106. {
  107. if (!Resolve(uid, ref pinpointer))
  108. return false;
  109. var isActive = !pinpointer.IsActive;
  110. SetActive(uid, isActive, pinpointer);
  111. return isActive;
  112. }
  113. private void OnEmagged(EntityUid uid, PinpointerComponent component, ref GotEmaggedEvent args)
  114. {
  115. if (!_emag.CompareFlag(args.Type, EmagType.Interaction))
  116. return;
  117. if (_emag.CheckFlag(uid, EmagType.Interaction))
  118. return;
  119. if (component.CanRetarget)
  120. return;
  121. args.Handled = true;
  122. component.CanRetarget = true;
  123. }
  124. }