ToolOpenableSystem.cs 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. using Content.Shared.IdentityManagement;
  2. using Content.Shared.Tools.Components;
  3. using Content.Shared.Tools.Systems;
  4. using Content.Shared.Interaction;
  5. using Content.Shared.Examine;
  6. using Content.Shared.Verbs;
  7. namespace Content.Shared.Tools.EntitySystems;
  8. public sealed class ToolOpenableSystem : EntitySystem
  9. {
  10. [Dependency] private readonly SharedToolSystem _tool = default!;
  11. [Dependency] private readonly SharedAppearanceSystem _appearance = default!;
  12. public override void Initialize()
  13. {
  14. base.Initialize();
  15. SubscribeLocalEvent<ToolOpenableComponent, ComponentInit>(OnInit);
  16. SubscribeLocalEvent<ToolOpenableComponent, ToolOpenableDoAfterEventToggleOpen>(OnOpenableStateToggled);
  17. SubscribeLocalEvent<ToolOpenableComponent, InteractUsingEvent>(OnInteractUsing);
  18. SubscribeLocalEvent<ToolOpenableComponent, ExaminedEvent>(OnExamine);
  19. SubscribeLocalEvent<ToolOpenableComponent, GetVerbsEvent<InteractionVerb>>(OnGetVerb);
  20. }
  21. private void OnInit(Entity<ToolOpenableComponent> entity, ref ComponentInit args)
  22. {
  23. UpdateAppearance(entity);
  24. Dirty(entity);
  25. }
  26. private void OnInteractUsing(Entity<ToolOpenableComponent> entity, ref InteractUsingEvent args)
  27. {
  28. if (args.Handled)
  29. return;
  30. if (TryOpenClose(entity, args.Used, args.User))
  31. args.Handled = true;
  32. }
  33. /// <summary>
  34. /// Try to open or close what is openable.
  35. /// </summary>
  36. /// <returns> Returns false if you can't interact with the openable thing with the given item. </returns>
  37. private bool TryOpenClose(Entity<ToolOpenableComponent> entity, EntityUid? toolToToggle, EntityUid user)
  38. {
  39. var neededToolQuantity = entity.Comp.IsOpen ? entity.Comp.CloseToolQualityNeeded : entity.Comp.OpenToolQualityNeeded;
  40. var time = entity.Comp.IsOpen ? entity.Comp.CloseTime : entity.Comp.OpenTime;
  41. var evt = new ToolOpenableDoAfterEventToggleOpen();
  42. // If neededToolQuantity is null it can only be open be opened with the verbs.
  43. if (toolToToggle == null || neededToolQuantity == null)
  44. return false;
  45. return _tool.UseTool(toolToToggle.Value, user, entity, time, neededToolQuantity, evt);
  46. }
  47. private void OnOpenableStateToggled(Entity<ToolOpenableComponent> entity, ref ToolOpenableDoAfterEventToggleOpen args)
  48. {
  49. if (args.Cancelled)
  50. return;
  51. ToggleState(entity);
  52. }
  53. /// <summary>
  54. /// Toggle the state and update appearance.
  55. /// </summary>
  56. private void ToggleState(Entity<ToolOpenableComponent> entity)
  57. {
  58. entity.Comp.IsOpen = !entity.Comp.IsOpen;
  59. UpdateAppearance(entity);
  60. Dirty(entity);
  61. }
  62. #region Helper functions
  63. private string GetName(Entity<ToolOpenableComponent> entity)
  64. {
  65. if (entity.Comp.Name == null)
  66. return Identity.Name(entity, EntityManager);
  67. return Loc.GetString(entity.Comp.Name);
  68. }
  69. public bool IsOpen(EntityUid uid, ToolOpenableComponent? component = null)
  70. {
  71. if (!Resolve(uid, ref component, false))
  72. return true;
  73. return component.IsOpen;
  74. }
  75. private void UpdateAppearance(Entity<ToolOpenableComponent> entity)
  76. {
  77. _appearance.SetData(entity, ToolOpenableVisuals.ToolOpenableVisualState, entity.Comp.IsOpen ? ToolOpenableVisualState.Open : ToolOpenableVisualState.Closed);
  78. }
  79. #endregion
  80. #region User interface functions
  81. private void OnExamine(Entity<ToolOpenableComponent> entity, ref ExaminedEvent args)
  82. {
  83. if (!args.IsInDetailsRange)
  84. return;
  85. string msg;
  86. var name = GetName(entity);
  87. if (entity.Comp.IsOpen)
  88. msg = Loc.GetString("tool-openable-component-examine-opened", ("name", name));
  89. else
  90. msg = Loc.GetString("tool-openable-component-examine-closed", ("name", name));
  91. args.PushMarkup(msg);
  92. }
  93. private void OnGetVerb(Entity<ToolOpenableComponent> entity, ref GetVerbsEvent<InteractionVerb> args)
  94. {
  95. if (!args.CanInteract || !args.CanAccess || !entity.Comp.HasVerbs)
  96. return;
  97. var user = args.User;
  98. var item = args.Using;
  99. var name = GetName(entity);
  100. var toggleVerb = new InteractionVerb
  101. {
  102. IconEntity = GetNetEntity(item)
  103. };
  104. if (entity.Comp.IsOpen)
  105. {
  106. toggleVerb.Text = toggleVerb.Message = Loc.GetString("tool-openable-component-verb-close");
  107. var neededQual = entity.Comp.CloseToolQualityNeeded;
  108. // If neededQual is null you don't need a tool to open / close.
  109. if (neededQual != null &&
  110. (item == null || !_tool.HasQuality(item.Value, neededQual)))
  111. {
  112. toggleVerb.Disabled = true;
  113. toggleVerb.Message = Loc.GetString("tool-openable-component-verb-cant-close", ("name", name));
  114. }
  115. if (neededQual == null)
  116. toggleVerb.Act = () => ToggleState(entity);
  117. else
  118. toggleVerb.Act = () => TryOpenClose(entity, item, user);
  119. args.Verbs.Add(toggleVerb);
  120. }
  121. else
  122. {
  123. // The open verb should only appear when holding the correct tool or if no tool is needed.
  124. toggleVerb.Text = toggleVerb.Message = Loc.GetString("tool-openable-component-verb-open");
  125. var neededQual = entity.Comp.OpenToolQualityNeeded;
  126. if (neededQual == null)
  127. {
  128. toggleVerb.Act = () => ToggleState(entity);
  129. args.Verbs.Add(toggleVerb);
  130. }
  131. else if (item != null && _tool.HasQuality(item.Value, neededQual))
  132. {
  133. toggleVerb.Act = () => TryOpenClose(entity, item, user);
  134. args.Verbs.Add(toggleVerb);
  135. }
  136. }
  137. }
  138. #endregion
  139. }