BlindableSystem.cs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. using Content.Shared.Eye.Blinding.Components;
  2. using Content.Shared.Inventory;
  3. using Content.Shared.Rejuvenate;
  4. using JetBrains.Annotations;
  5. namespace Content.Shared.Eye.Blinding.Systems;
  6. public sealed class BlindableSystem : EntitySystem
  7. {
  8. [Dependency] private readonly BlurryVisionSystem _blurriness = default!;
  9. [Dependency] private readonly EyeClosingSystem _eyelids = default!;
  10. public override void Initialize()
  11. {
  12. base.Initialize();
  13. SubscribeLocalEvent<BlindableComponent, RejuvenateEvent>(OnRejuvenate);
  14. SubscribeLocalEvent<BlindableComponent, EyeDamageChangedEvent>(OnDamageChanged);
  15. }
  16. private void OnRejuvenate(Entity<BlindableComponent> ent, ref RejuvenateEvent args)
  17. {
  18. AdjustEyeDamage((ent.Owner, ent.Comp), -ent.Comp.EyeDamage);
  19. }
  20. private void OnDamageChanged(Entity<BlindableComponent> ent, ref EyeDamageChangedEvent args)
  21. {
  22. _blurriness.UpdateBlurMagnitude((ent.Owner, ent.Comp));
  23. _eyelids.UpdateEyesClosable((ent.Owner, ent.Comp));
  24. }
  25. [PublicAPI]
  26. public void UpdateIsBlind(Entity<BlindableComponent?> blindable)
  27. {
  28. if (!Resolve(blindable, ref blindable.Comp, false))
  29. return;
  30. var old = blindable.Comp.IsBlind;
  31. // Don't bother raising an event if the eye is too damaged.
  32. if (blindable.Comp.EyeDamage >= blindable.Comp.MaxDamage)
  33. {
  34. blindable.Comp.IsBlind = true;
  35. }
  36. else
  37. {
  38. var ev = new CanSeeAttemptEvent();
  39. RaiseLocalEvent(blindable.Owner, ev);
  40. blindable.Comp.IsBlind = ev.Blind;
  41. }
  42. if (old == blindable.Comp.IsBlind)
  43. return;
  44. var changeEv = new BlindnessChangedEvent(blindable.Comp.IsBlind);
  45. RaiseLocalEvent(blindable.Owner, ref changeEv);
  46. Dirty(blindable);
  47. }
  48. public void AdjustEyeDamage(Entity<BlindableComponent?> blindable, int amount)
  49. {
  50. if (!Resolve(blindable, ref blindable.Comp, false) || amount == 0)
  51. return;
  52. blindable.Comp.EyeDamage += amount;
  53. UpdateEyeDamage(blindable, true);
  54. }
  55. private void UpdateEyeDamage(Entity<BlindableComponent?> blindable, bool isDamageChanged)
  56. {
  57. if (!Resolve(blindable, ref blindable.Comp, false))
  58. return;
  59. var previousDamage = blindable.Comp.EyeDamage;
  60. blindable.Comp.EyeDamage = Math.Clamp(blindable.Comp.EyeDamage, blindable.Comp.MinDamage, blindable.Comp.MaxDamage);
  61. Dirty(blindable);
  62. if (!isDamageChanged && previousDamage == blindable.Comp.EyeDamage)
  63. return;
  64. UpdateIsBlind(blindable);
  65. var ev = new EyeDamageChangedEvent(blindable.Comp.EyeDamage);
  66. RaiseLocalEvent(blindable.Owner, ref ev);
  67. }
  68. public void SetMinDamage(Entity<BlindableComponent?> blindable, int amount)
  69. {
  70. if (!Resolve(blindable, ref blindable.Comp, false))
  71. return;
  72. blindable.Comp.MinDamage = amount;
  73. UpdateEyeDamage(blindable, false);
  74. }
  75. }
  76. /// <summary>
  77. /// This event is raised when an entity's blindness changes
  78. /// </summary>
  79. [ByRefEvent]
  80. public record struct BlindnessChangedEvent(bool Blind);
  81. /// <summary>
  82. /// This event is raised when an entity's eye damage changes
  83. /// </summary>
  84. [ByRefEvent]
  85. public record struct EyeDamageChangedEvent(int Damage);
  86. /// <summary>
  87. /// Raised directed at an entity to see whether the entity is currently blind or not.
  88. /// </summary>
  89. public sealed class CanSeeAttemptEvent : CancellableEntityEventArgs, IInventoryRelayEvent
  90. {
  91. public bool Blind => Cancelled;
  92. public SlotFlags TargetSlots => SlotFlags.EYES | SlotFlags.MASK | SlotFlags.HEAD;
  93. }
  94. public sealed class GetEyeProtectionEvent : EntityEventArgs, IInventoryRelayEvent
  95. {
  96. /// <summary>
  97. /// Time to subtract from any temporary blindness sources.
  98. /// </summary>
  99. public TimeSpan Protection;
  100. public SlotFlags TargetSlots => SlotFlags.EYES | SlotFlags.MASK | SlotFlags.HEAD;
  101. }