DrunkOverlay.cs 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. using Content.Shared.Drunk;
  2. using Content.Shared.StatusEffect;
  3. using Robust.Client.Graphics;
  4. using Robust.Client.Player;
  5. using Robust.Shared.Enums;
  6. using Robust.Shared.Prototypes;
  7. using Robust.Shared.Timing;
  8. namespace Content.Client.Drunk;
  9. public sealed class DrunkOverlay : Overlay
  10. {
  11. [Dependency] private readonly IEntityManager _entityManager = default!;
  12. [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
  13. [Dependency] private readonly IPlayerManager _playerManager = default!;
  14. [Dependency] private readonly IEntitySystemManager _sysMan = default!;
  15. [Dependency] private readonly IGameTiming _timing = default!;
  16. public override OverlaySpace Space => OverlaySpace.WorldSpace;
  17. public override bool RequestScreenTexture => true;
  18. private readonly ShaderInstance _drunkShader;
  19. public float CurrentBoozePower = 0.0f;
  20. private const float VisualThreshold = 10.0f;
  21. private const float PowerDivisor = 250.0f;
  22. private float _visualScale = 0;
  23. public DrunkOverlay()
  24. {
  25. IoCManager.InjectDependencies(this);
  26. _drunkShader = _prototypeManager.Index<ShaderPrototype>("Drunk").InstanceUnique();
  27. }
  28. protected override void FrameUpdate(FrameEventArgs args)
  29. {
  30. var playerEntity = _playerManager.LocalEntity;
  31. if (playerEntity == null)
  32. return;
  33. if (!_entityManager.HasComponent<DrunkComponent>(playerEntity)
  34. || !_entityManager.TryGetComponent<StatusEffectsComponent>(playerEntity, out var status))
  35. return;
  36. var statusSys = _sysMan.GetEntitySystem<StatusEffectsSystem>();
  37. if (!statusSys.TryGetTime(playerEntity.Value, SharedDrunkSystem.DrunkKey, out var time, status))
  38. return;
  39. var curTime = _timing.CurTime;
  40. var timeLeft = (float) (time.Value.Item2 - curTime).TotalSeconds;
  41. CurrentBoozePower += 8f * (0.5f*timeLeft - CurrentBoozePower) * args.DeltaSeconds / (timeLeft+1);
  42. }
  43. protected override bool BeforeDraw(in OverlayDrawArgs args)
  44. {
  45. if (!_entityManager.TryGetComponent(_playerManager.LocalEntity, out EyeComponent? eyeComp))
  46. return false;
  47. if (args.Viewport.Eye != eyeComp.Eye)
  48. return false;
  49. _visualScale = BoozePowerToVisual(CurrentBoozePower);
  50. return _visualScale > 0;
  51. }
  52. protected override void Draw(in OverlayDrawArgs args)
  53. {
  54. if (ScreenTexture == null)
  55. return;
  56. var handle = args.WorldHandle;
  57. _drunkShader.SetParameter("SCREEN_TEXTURE", ScreenTexture);
  58. _drunkShader.SetParameter("boozePower", _visualScale);
  59. handle.UseShader(_drunkShader);
  60. handle.DrawRect(args.WorldBounds, Color.White);
  61. handle.UseShader(null);
  62. }
  63. /// <summary>
  64. /// Converts the # of seconds the drunk effect lasts for (booze power) to a percentage
  65. /// used by the actual shader.
  66. /// </summary>
  67. /// <param name="boozePower"></param>
  68. private float BoozePowerToVisual(float boozePower)
  69. {
  70. // Clamp booze power when it's low, to prevent really jittery effects
  71. if (boozePower < 50f)
  72. {
  73. return 0;
  74. }
  75. else
  76. {
  77. return Math.Clamp((boozePower - VisualThreshold) / PowerDivisor, 0.0f, 1.0f);
  78. }
  79. }
  80. }