ExplosionOverlay.cs 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. using System.Numerics;
  2. using Content.Shared.Explosion.Components;
  3. using JetBrains.Annotations;
  4. using Robust.Client.Graphics;
  5. using Robust.Shared.Enums;
  6. using Robust.Shared.Map;
  7. using Robust.Shared.Map.Components;
  8. using Robust.Shared.Prototypes;
  9. using Robust.Shared.Random;
  10. namespace Content.Client.Explosion;
  11. [UsedImplicitly]
  12. public sealed class ExplosionOverlay : Overlay
  13. {
  14. [Dependency] private readonly IRobustRandom _robustRandom = default!;
  15. [Dependency] private readonly IEntityManager _entMan = default!;
  16. [Dependency] private readonly IPrototypeManager _proto = default!;
  17. private readonly SharedTransformSystem _transformSystem;
  18. private SharedAppearanceSystem _appearance;
  19. public override OverlaySpace Space => OverlaySpace.WorldSpaceBelowFOV;
  20. private ShaderInstance _shader;
  21. public ExplosionOverlay(SharedAppearanceSystem appearanceSystem)
  22. {
  23. IoCManager.InjectDependencies(this);
  24. _shader = _proto.Index<ShaderPrototype>("unshaded").Instance();
  25. _transformSystem = _entMan.System<SharedTransformSystem>();
  26. _appearance = appearanceSystem;
  27. }
  28. protected override void Draw(in OverlayDrawArgs args)
  29. {
  30. var drawHandle = args.WorldHandle;
  31. drawHandle.UseShader(_shader);
  32. var xforms = _entMan.GetEntityQuery<TransformComponent>();
  33. var query = _entMan.EntityQueryEnumerator<ExplosionVisualsComponent, ExplosionVisualsTexturesComponent>();
  34. while (query.MoveNext(out var uid, out var visuals, out var textures))
  35. {
  36. if (visuals.Epicenter.MapId != args.MapId)
  37. continue;
  38. if (!_appearance.TryGetData(uid, ExplosionAppearanceData.Progress, out int index))
  39. continue;
  40. index = Math.Min(index, visuals.Intensity.Count - 1);
  41. DrawExplosion(drawHandle, args.WorldBounds, visuals, index, xforms, textures);
  42. }
  43. drawHandle.SetTransform(Matrix3x2.Identity);
  44. drawHandle.UseShader(null);
  45. }
  46. private void DrawExplosion(
  47. DrawingHandleWorld drawHandle,
  48. Box2Rotated worldBounds,
  49. ExplosionVisualsComponent visuals,
  50. int index,
  51. EntityQuery<TransformComponent> xforms,
  52. ExplosionVisualsTexturesComponent textures)
  53. {
  54. Box2 gridBounds;
  55. foreach (var (gridId, tiles) in visuals.Tiles)
  56. {
  57. if (!_entMan.TryGetComponent(gridId, out MapGridComponent? grid))
  58. continue;
  59. var xform = xforms.GetComponent(gridId);
  60. var (_, _, worldMatrix, invWorldMatrix) = _transformSystem.GetWorldPositionRotationMatrixWithInv(xform, xforms);
  61. gridBounds = invWorldMatrix.TransformBox(worldBounds).Enlarged(grid.TileSize * 2);
  62. drawHandle.SetTransform(worldMatrix);
  63. DrawTiles(drawHandle, gridBounds, index, tiles, visuals, grid.TileSize, textures);
  64. }
  65. if (visuals.SpaceTiles == null)
  66. return;
  67. Matrix3x2.Invert(visuals.SpaceMatrix, out var invSpace);
  68. gridBounds = invSpace.TransformBox(worldBounds).Enlarged(2);
  69. drawHandle.SetTransform(visuals.SpaceMatrix);
  70. DrawTiles(drawHandle, gridBounds, index, visuals.SpaceTiles, visuals, visuals.SpaceTileSize, textures);
  71. }
  72. private void DrawTiles(
  73. DrawingHandleWorld drawHandle,
  74. Box2 gridBounds,
  75. int index,
  76. Dictionary<int, List<Vector2i>> tileSets,
  77. ExplosionVisualsComponent visuals,
  78. ushort tileSize,
  79. ExplosionVisualsTexturesComponent textures)
  80. {
  81. for (var j = 0; j <= index; j++)
  82. {
  83. if (!tileSets.TryGetValue(j, out var tiles))
  84. continue;
  85. var frameIndex = (int) Math.Min(visuals.Intensity[j] / textures.IntensityPerState, textures.FireFrames.Count - 1);
  86. var frames = textures.FireFrames[frameIndex];
  87. foreach (var tile in tiles)
  88. {
  89. var centre = (tile + Vector2Helpers.Half) * tileSize;
  90. if (!gridBounds.Contains(centre))
  91. continue;
  92. var texture = _robustRandom.Pick(frames);
  93. drawHandle.DrawTextureRect(texture, Box2.CenteredAround(centre, new Vector2(tileSize, tileSize)), textures.FireColor);
  94. }
  95. }
  96. }
  97. }