MobStateSystem.Subscribers.cs 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. using Content.Shared.Bed.Sleep;
  2. using Content.Shared.Buckle.Components;
  3. using Content.Shared.CombatMode.Pacification;
  4. using Content.Shared.Damage.ForceSay;
  5. using Content.Shared.Emoting;
  6. using Content.Shared.Hands;
  7. using Content.Shared.Interaction;
  8. using Content.Shared.Interaction.Events;
  9. using Content.Shared.Inventory.Events;
  10. using Content.Shared.Item;
  11. using Content.Shared.Mobs.Components;
  12. using Content.Shared.Movement.Events;
  13. using Content.Shared.Pointing;
  14. using Content.Shared.Pulling.Events;
  15. using Content.Shared.Speech;
  16. using Content.Shared.Standing;
  17. using Content.Shared.Strip.Components;
  18. using Content.Shared.Throwing;
  19. using Robust.Shared.Physics.Components;
  20. namespace Content.Shared.Mobs.Systems;
  21. public partial class MobStateSystem
  22. {
  23. //General purpose event subscriptions. If you can avoid it register these events inside their own systems
  24. private void SubscribeEvents()
  25. {
  26. SubscribeLocalEvent<MobStateComponent, BeforeGettingStrippedEvent>(OnGettingStripped);
  27. SubscribeLocalEvent<MobStateComponent, ChangeDirectionAttemptEvent>(CheckAct);
  28. SubscribeLocalEvent<MobStateComponent, UseAttemptEvent>(CheckAct);
  29. SubscribeLocalEvent<MobStateComponent, AttackAttemptEvent>(CheckAct);
  30. SubscribeLocalEvent<MobStateComponent, ConsciousAttemptEvent>(CheckConcious);
  31. SubscribeLocalEvent<MobStateComponent, ThrowAttemptEvent>(CheckAct);
  32. SubscribeLocalEvent<MobStateComponent, SpeakAttemptEvent>(OnSpeakAttempt);
  33. SubscribeLocalEvent<MobStateComponent, IsEquippingAttemptEvent>(OnEquipAttempt);
  34. SubscribeLocalEvent<MobStateComponent, EmoteAttemptEvent>(CheckAct);
  35. SubscribeLocalEvent<MobStateComponent, IsUnequippingAttemptEvent>(OnUnequipAttempt);
  36. SubscribeLocalEvent<MobStateComponent, DropAttemptEvent>(CheckAct);
  37. SubscribeLocalEvent<MobStateComponent, PickupAttemptEvent>(CheckAct);
  38. SubscribeLocalEvent<MobStateComponent, StartPullAttemptEvent>(CheckAct);
  39. SubscribeLocalEvent<MobStateComponent, UpdateCanMoveEvent>(CheckAct);
  40. SubscribeLocalEvent<MobStateComponent, StandAttemptEvent>(CheckAct);
  41. SubscribeLocalEvent<MobStateComponent, PointAttemptEvent>(CheckAct);
  42. SubscribeLocalEvent<MobStateComponent, TryingToSleepEvent>(OnSleepAttempt);
  43. SubscribeLocalEvent<MobStateComponent, CombatModeShouldHandInteractEvent>(OnCombatModeShouldHandInteract);
  44. SubscribeLocalEvent<MobStateComponent, AttemptPacifiedAttackEvent>(OnAttemptPacifiedAttack);
  45. SubscribeLocalEvent<MobStateComponent, UnbuckleAttemptEvent>(OnUnbuckleAttempt);
  46. }
  47. private void OnUnbuckleAttempt(Entity<MobStateComponent> ent, ref UnbuckleAttemptEvent args)
  48. {
  49. // TODO is this necessary?
  50. // Shouldn't the interaction have already been blocked by a general interaction check?
  51. if (args.User == ent.Owner && IsIncapacitated(ent))
  52. args.Cancelled = true;
  53. }
  54. private void CheckConcious(Entity<MobStateComponent> ent, ref ConsciousAttemptEvent args)
  55. {
  56. switch (ent.Comp.CurrentState)
  57. {
  58. case MobState.Dead:
  59. case MobState.Critical:
  60. args.Cancelled = true;
  61. break;
  62. }
  63. }
  64. private void OnStateExitSubscribers(EntityUid target, MobStateComponent component, MobState state)
  65. {
  66. switch (state)
  67. {
  68. case MobState.Alive:
  69. //unused
  70. break;
  71. case MobState.Critical:
  72. _standing.Stand(target);
  73. break;
  74. case MobState.Dead:
  75. RemComp<CollisionWakeComponent>(target);
  76. _standing.Stand(target);
  77. break;
  78. case MobState.Invalid:
  79. //unused
  80. break;
  81. default:
  82. throw new NotImplementedException();
  83. }
  84. }
  85. private void OnStateEnteredSubscribers(EntityUid target, MobStateComponent component, MobState state)
  86. {
  87. // All of the state changes here should already be networked, so we do nothing if we are currently applying a
  88. // server state.
  89. if (_timing.ApplyingState)
  90. return;
  91. _blocker.UpdateCanMove(target); //update movement anytime a state changes
  92. switch (state)
  93. {
  94. case MobState.Alive:
  95. _standing.Stand(target);
  96. _appearance.SetData(target, MobStateVisuals.State, MobState.Alive);
  97. break;
  98. case MobState.Critical:
  99. _standing.Down(target);
  100. _appearance.SetData(target, MobStateVisuals.State, MobState.Critical);
  101. break;
  102. case MobState.Dead:
  103. EnsureComp<CollisionWakeComponent>(target);
  104. _standing.Down(target);
  105. _appearance.SetData(target, MobStateVisuals.State, MobState.Dead);
  106. break;
  107. case MobState.Invalid:
  108. //unused;
  109. break;
  110. default:
  111. throw new NotImplementedException();
  112. }
  113. }
  114. #region Event Subscribers
  115. private void OnSleepAttempt(EntityUid target, MobStateComponent component, ref TryingToSleepEvent args)
  116. {
  117. if (IsDead(target, component))
  118. args.Cancelled = true;
  119. }
  120. private void OnGettingStripped(EntityUid target, MobStateComponent component, BeforeGettingStrippedEvent args)
  121. {
  122. // Incapacitated or dead targets get stripped two or three times as fast. Makes stripping corpses less tedious.
  123. if (IsDead(target, component))
  124. args.Multiplier /= 3;
  125. else if (IsCritical(target, component))
  126. args.Multiplier /= 2;
  127. }
  128. private void OnSpeakAttempt(EntityUid uid, MobStateComponent component, SpeakAttemptEvent args)
  129. {
  130. if (HasComp<AllowNextCritSpeechComponent>(uid))
  131. {
  132. RemCompDeferred<AllowNextCritSpeechComponent>(uid);
  133. return;
  134. }
  135. CheckAct(uid, component, args);
  136. }
  137. private void CheckAct(EntityUid target, MobStateComponent component, CancellableEntityEventArgs args)
  138. {
  139. switch (component.CurrentState)
  140. {
  141. case MobState.Dead:
  142. case MobState.Critical:
  143. args.Cancel();
  144. break;
  145. }
  146. }
  147. private void OnEquipAttempt(EntityUid target, MobStateComponent component, IsEquippingAttemptEvent args)
  148. {
  149. // is this a self-equip, or are they being stripped?
  150. if (args.Equipee == target)
  151. CheckAct(target, component, args);
  152. }
  153. private void OnUnequipAttempt(EntityUid target, MobStateComponent component, IsUnequippingAttemptEvent args)
  154. {
  155. // is this a self-equip, or are they being stripped?
  156. if (args.Unequipee == target)
  157. CheckAct(target, component, args);
  158. }
  159. private void OnCombatModeShouldHandInteract(EntityUid uid, MobStateComponent component, ref CombatModeShouldHandInteractEvent args)
  160. {
  161. // Disallow empty-hand-interacting in combat mode
  162. // for non-dead mobs
  163. if (!IsDead(uid, component))
  164. args.Cancelled = true;
  165. }
  166. private void OnAttemptPacifiedAttack(Entity<MobStateComponent> ent, ref AttemptPacifiedAttackEvent args)
  167. {
  168. args.Cancelled = true;
  169. }
  170. #endregion
  171. }