SlowOnDamageSystem.cs 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. using Content.Shared.Clothing;
  2. using Content.Shared.Damage.Components;
  3. using Content.Shared.Examine;
  4. using Content.Shared.FixedPoint;
  5. using Content.Shared.Inventory;
  6. using Content.Shared.Movement.Systems;
  7. namespace Content.Shared.Damage
  8. {
  9. public sealed class SlowOnDamageSystem : EntitySystem
  10. {
  11. [Dependency] private readonly MovementSpeedModifierSystem _movementSpeedModifierSystem = default!;
  12. public override void Initialize()
  13. {
  14. base.Initialize();
  15. SubscribeLocalEvent<SlowOnDamageComponent, DamageChangedEvent>(OnDamageChanged);
  16. SubscribeLocalEvent<SlowOnDamageComponent, RefreshMovementSpeedModifiersEvent>(OnRefreshMovespeed);
  17. SubscribeLocalEvent<ClothingSlowOnDamageModifierComponent, InventoryRelayedEvent<ModifySlowOnDamageSpeedEvent>>(OnModifySpeed);
  18. SubscribeLocalEvent<ClothingSlowOnDamageModifierComponent, ExaminedEvent>(OnExamined);
  19. SubscribeLocalEvent<ClothingSlowOnDamageModifierComponent, ClothingGotEquippedEvent>(OnGotEquipped);
  20. SubscribeLocalEvent<ClothingSlowOnDamageModifierComponent, ClothingGotUnequippedEvent>(OnGotUnequipped);
  21. SubscribeLocalEvent<IgnoreSlowOnDamageComponent, ComponentStartup>(OnIgnoreStartup);
  22. SubscribeLocalEvent<IgnoreSlowOnDamageComponent, ComponentShutdown>(OnIgnoreShutdown);
  23. SubscribeLocalEvent<IgnoreSlowOnDamageComponent, ModifySlowOnDamageSpeedEvent>(OnIgnoreModifySpeed);
  24. }
  25. private void OnRefreshMovespeed(EntityUid uid, SlowOnDamageComponent component, RefreshMovementSpeedModifiersEvent args)
  26. {
  27. if (!EntityManager.TryGetComponent<DamageableComponent>(uid, out var damage))
  28. return;
  29. if (damage.TotalDamage == FixedPoint2.Zero)
  30. return;
  31. // Get closest threshold
  32. FixedPoint2 closest = FixedPoint2.Zero;
  33. var total = damage.TotalDamage;
  34. foreach (var thres in component.SpeedModifierThresholds)
  35. {
  36. if (total >= thres.Key && thres.Key > closest)
  37. closest = thres.Key;
  38. }
  39. if (closest != FixedPoint2.Zero)
  40. {
  41. var speed = component.SpeedModifierThresholds[closest];
  42. var ev = new ModifySlowOnDamageSpeedEvent(speed);
  43. RaiseLocalEvent(uid, ref ev);
  44. args.ModifySpeed(ev.Speed, ev.Speed);
  45. }
  46. }
  47. private void OnDamageChanged(EntityUid uid, SlowOnDamageComponent component, DamageChangedEvent args)
  48. {
  49. // We -could- only refresh if it crossed a threshold but that would kind of be a lot of duplicated
  50. // code and this isn't a super hot path anyway since basically only humans have this
  51. _movementSpeedModifierSystem.RefreshMovementSpeedModifiers(uid);
  52. }
  53. private void OnModifySpeed(Entity<ClothingSlowOnDamageModifierComponent> ent, ref InventoryRelayedEvent<ModifySlowOnDamageSpeedEvent> args)
  54. {
  55. var dif = 1 - args.Args.Speed;
  56. if (dif <= 0)
  57. return;
  58. // reduces the slowness modifier by the given coefficient
  59. args.Args.Speed += dif * ent.Comp.Modifier;
  60. }
  61. private void OnExamined(Entity<ClothingSlowOnDamageModifierComponent> ent, ref ExaminedEvent args)
  62. {
  63. var msg = Loc.GetString("slow-on-damage-modifier-examine", ("mod", (1 - ent.Comp.Modifier) * 100));
  64. args.PushMarkup(msg);
  65. }
  66. private void OnGotEquipped(Entity<ClothingSlowOnDamageModifierComponent> ent, ref ClothingGotEquippedEvent args)
  67. {
  68. _movementSpeedModifierSystem.RefreshMovementSpeedModifiers(args.Wearer);
  69. }
  70. private void OnGotUnequipped(Entity<ClothingSlowOnDamageModifierComponent> ent, ref ClothingGotUnequippedEvent args)
  71. {
  72. _movementSpeedModifierSystem.RefreshMovementSpeedModifiers(args.Wearer);
  73. }
  74. private void OnIgnoreStartup(Entity<IgnoreSlowOnDamageComponent> ent, ref ComponentStartup args)
  75. {
  76. _movementSpeedModifierSystem.RefreshMovementSpeedModifiers(ent);
  77. }
  78. private void OnIgnoreShutdown(Entity<IgnoreSlowOnDamageComponent> ent, ref ComponentShutdown args)
  79. {
  80. _movementSpeedModifierSystem.RefreshMovementSpeedModifiers(ent);
  81. }
  82. private void OnIgnoreModifySpeed(Entity<IgnoreSlowOnDamageComponent> ent, ref ModifySlowOnDamageSpeedEvent args)
  83. {
  84. args.Speed = 1f;
  85. }
  86. }
  87. [ByRefEvent]
  88. public record struct ModifySlowOnDamageSpeedEvent(float Speed) : IInventoryRelayEvent
  89. {
  90. public SlotFlags TargetSlots => SlotFlags.WITHOUT_POCKET;
  91. }
  92. }