1
0

SharedWiresSystem.cs 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. using Content.Shared.Administration.Logs;
  2. using Content.Shared.Database;
  3. using Content.Shared.Examine;
  4. using Content.Shared.Interaction;
  5. using Content.Shared.Tools.Systems;
  6. using Content.Shared.UserInterface;
  7. using Robust.Shared.Audio.Systems;
  8. namespace Content.Shared.Wires;
  9. public abstract class SharedWiresSystem : EntitySystem
  10. {
  11. [Dependency] protected readonly ISharedAdminLogManager AdminLogger = default!;
  12. [Dependency] private readonly ActivatableUISystem _activatableUI = default!;
  13. [Dependency] protected readonly SharedAppearanceSystem Appearance = default!;
  14. [Dependency] protected readonly SharedAudioSystem Audio = default!;
  15. [Dependency] protected readonly SharedToolSystem Tool = default!;
  16. public override void Initialize()
  17. {
  18. base.Initialize();
  19. SubscribeLocalEvent<WiresPanelComponent, ComponentStartup>(OnStartup);
  20. SubscribeLocalEvent<WiresPanelComponent, WirePanelDoAfterEvent>(OnPanelDoAfter);
  21. SubscribeLocalEvent<WiresPanelComponent, InteractUsingEvent>(OnInteractUsing);
  22. SubscribeLocalEvent<WiresPanelComponent, ExaminedEvent>(OnExamine);
  23. SubscribeLocalEvent<ActivatableUIRequiresPanelComponent, ActivatableUIOpenAttemptEvent>(OnAttemptOpenActivatableUI);
  24. SubscribeLocalEvent<ActivatableUIRequiresPanelComponent, PanelChangedEvent>(OnActivatableUIPanelChanged);
  25. }
  26. private void OnStartup(Entity<WiresPanelComponent> ent, ref ComponentStartup args)
  27. {
  28. UpdateAppearance(ent, ent);
  29. }
  30. private void OnPanelDoAfter(EntityUid uid, WiresPanelComponent panel, WirePanelDoAfterEvent args)
  31. {
  32. if (args.Cancelled)
  33. return;
  34. if (!TogglePanel(uid, panel, !panel.Open, args.User))
  35. return;
  36. AdminLogger.Add(LogType.Action, LogImpact.Low, $"{ToPrettyString(args.User):user} screwed {ToPrettyString(uid):target}'s maintenance panel {(panel.Open ? "open" : "closed")}");
  37. var sound = panel.Open ? panel.ScrewdriverOpenSound : panel.ScrewdriverCloseSound;
  38. Audio.PlayPredicted(sound, uid, args.User);
  39. args.Handled = true;
  40. }
  41. private void OnInteractUsing(Entity<WiresPanelComponent> ent, ref InteractUsingEvent args)
  42. {
  43. if (!Tool.HasQuality(args.Used, ent.Comp.OpeningTool))
  44. return;
  45. if (!CanTogglePanel(ent, args.User))
  46. return;
  47. if (!Tool.UseTool(
  48. args.Used,
  49. args.User,
  50. ent,
  51. (float) ent.Comp.OpenDelay.TotalSeconds,
  52. ent.Comp.OpeningTool,
  53. new WirePanelDoAfterEvent()))
  54. {
  55. return;
  56. }
  57. AdminLogger.Add(LogType.Action, LogImpact.Low,
  58. $"{ToPrettyString(args.User):user} is screwing {ToPrettyString(ent):target}'s {(ent.Comp.Open ? "open" : "closed")} maintenance panel at {Transform(ent).Coordinates:targetlocation}");
  59. args.Handled = true;
  60. }
  61. private void OnExamine(EntityUid uid, WiresPanelComponent component, ExaminedEvent args)
  62. {
  63. using (args.PushGroup(nameof(WiresPanelComponent)))
  64. {
  65. if (!component.Open)
  66. {
  67. if (!string.IsNullOrEmpty(component.ExamineTextClosed))
  68. args.PushMarkup(Loc.GetString(component.ExamineTextClosed));
  69. }
  70. else
  71. {
  72. if (!string.IsNullOrEmpty(component.ExamineTextOpen))
  73. args.PushMarkup(Loc.GetString(component.ExamineTextOpen));
  74. if (TryComp<WiresPanelSecurityComponent>(uid, out var wiresPanelSecurity) &&
  75. wiresPanelSecurity.Examine != null)
  76. {
  77. args.PushMarkup(Loc.GetString(wiresPanelSecurity.Examine));
  78. }
  79. }
  80. }
  81. }
  82. public void ChangePanelVisibility(EntityUid uid, WiresPanelComponent component, bool visible)
  83. {
  84. component.Visible = visible;
  85. UpdateAppearance(uid, component);
  86. Dirty(uid, component);
  87. }
  88. protected void UpdateAppearance(EntityUid uid, WiresPanelComponent panel)
  89. {
  90. if (TryComp<AppearanceComponent>(uid, out var appearance))
  91. Appearance.SetData(uid, WiresVisuals.MaintenancePanelState, panel.Open && panel.Visible, appearance);
  92. }
  93. public bool TogglePanel(EntityUid uid, WiresPanelComponent component, bool open, EntityUid? user = null)
  94. {
  95. if (!CanTogglePanel((uid, component), user))
  96. return false;
  97. component.Open = open;
  98. UpdateAppearance(uid, component);
  99. Dirty(uid, component);
  100. var ev = new PanelChangedEvent(component.Open);
  101. RaiseLocalEvent(uid, ref ev);
  102. return true;
  103. }
  104. public bool CanTogglePanel(Entity<WiresPanelComponent> ent, EntityUid? user)
  105. {
  106. var attempt = new AttemptChangePanelEvent(ent.Comp.Open, user);
  107. RaiseLocalEvent(ent, ref attempt);
  108. return !attempt.Cancelled;
  109. }
  110. public bool IsPanelOpen(Entity<WiresPanelComponent?> entity, EntityUid? tool = null)
  111. {
  112. if (!Resolve(entity, ref entity.Comp, false))
  113. return true;
  114. if (tool != null)
  115. {
  116. var ev = new PanelOverrideEvent();
  117. RaiseLocalEvent(tool.Value, ref ev);
  118. if (ev.Allowed)
  119. return true;
  120. }
  121. // Listen, i don't know what the fuck this component does. it's stapled on shit for airlocks
  122. // but it looks like an almost direct duplication of WiresPanelComponent except with a shittier API.
  123. if (TryComp<WiresPanelSecurityComponent>(entity, out var wiresPanelSecurity) &&
  124. !wiresPanelSecurity.WiresAccessible)
  125. return false;
  126. return entity.Comp.Open;
  127. }
  128. private void OnAttemptOpenActivatableUI(EntityUid uid, ActivatableUIRequiresPanelComponent component, ActivatableUIOpenAttemptEvent args)
  129. {
  130. if (args.Cancelled || !TryComp<WiresPanelComponent>(uid, out var wires))
  131. return;
  132. if (component.RequireOpen != wires.Open)
  133. args.Cancel();
  134. }
  135. private void OnActivatableUIPanelChanged(EntityUid uid, ActivatableUIRequiresPanelComponent component, ref PanelChangedEvent args)
  136. {
  137. if (args.Open == component.RequireOpen)
  138. return;
  139. _activatableUI.CloseAll(uid);
  140. }
  141. }
  142. /// <summary>
  143. /// Raised directed on a tool to try and override panel visibility.
  144. /// </summary>
  145. [ByRefEvent]
  146. public record struct PanelOverrideEvent()
  147. {
  148. public bool Allowed = true;
  149. }