Explosion refactor (#5230)
* Explosions * fix yaml typo and prevent silly UI inputs * oop * Use modified contains() checks And remove IEnumerable * Buff nuke, nerf meteors * optimize the entity lookup stuff a bit * fix tile (0,0) error forgot to do an initial Enumerator.MoveNext(), so the first tile was always the "null" tile. * remove celebration * byte -> int * remove diag edge tile dict * fix one bug but there is another * fix the other bug turns out dividing a ushort leads to rounding errors. Why TF is the grid tile size even a ushort in the first place. * improve edge map * fix minor bug If the initial-explosion tile had an airtight entity on it, the tile was processed twice. * some reviews (transform queries, eye.mapid, and tilesizes in overlays) * Apply suggestions from code review Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> * is map paused * GetAllTiles ignores space by default * WriteLine -> WriteError * First -> FirstOrDefault() * default prototype const string * entity query * misc review changes * grid edge max distance * fix fire texture defn bad use of type serializer and ioc-resolves * Remove ExplosionLaunched And allow nukes to throw items towards the outer part of an explosion * no hot-reload disclaimer * replace prototype id string with int index * optimise damage a tiiiiny bit. * entity queries * comments * misc mirror comments * cvars * admin logs * move intensity-per-state to prototype * update tile event to ECS event * git mv * Tweak rpg & minibomb also fix merge bug * you don't exist anymore go away * Fix build Co-authored-by: moonheart08 <moonheart08@users.noreply.github.com> Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com>
This commit is contained in:
119
Content.Client/Explosion/ExplosionOverlay.cs
Normal file
119
Content.Client/Explosion/ExplosionOverlay.cs
Normal file
@@ -0,0 +1,119 @@
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Shared.Enums;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Random;
|
||||
|
||||
namespace Content.Client.Explosion;
|
||||
|
||||
[UsedImplicitly]
|
||||
public sealed class ExplosionOverlay : Overlay
|
||||
{
|
||||
/// <summary>
|
||||
/// The explosion that needs to be drawn. This explosion is currently being processed by the server and
|
||||
/// expanding outwards.
|
||||
/// </summary>
|
||||
internal Explosion? ActiveExplosion;
|
||||
|
||||
/// <summary>
|
||||
/// This index specifies what parts of the currently expanding explosion should be drawn.
|
||||
/// </summary>
|
||||
public int Index;
|
||||
|
||||
/// <summary>
|
||||
/// These explosions have finished expanding, but we will draw for a few more frames. This is important for
|
||||
/// small explosions, as otherwise they disappear far too quickly.
|
||||
/// </summary>
|
||||
internal List<Explosion> CompletedExplosions = new ();
|
||||
|
||||
[Dependency] private readonly IRobustRandom _robustRandom = default!;
|
||||
[Dependency] private readonly IMapManager _mapManager = default!;
|
||||
[Dependency] private readonly IEntityManager _entMan = default!;
|
||||
|
||||
public override OverlaySpace Space => OverlaySpace.WorldSpaceBelowFOV;
|
||||
|
||||
private ShaderInstance _shader;
|
||||
|
||||
public ExplosionOverlay()
|
||||
{
|
||||
IoCManager.InjectDependencies(this);
|
||||
_shader = IoCManager.Resolve<IPrototypeManager>().Index<ShaderPrototype>("unshaded").Instance();
|
||||
}
|
||||
|
||||
protected override void Draw(in OverlayDrawArgs args)
|
||||
{
|
||||
var drawHandle = args.WorldHandle;
|
||||
drawHandle.UseShader(_shader);
|
||||
|
||||
var xforms = _entMan.GetEntityQuery<TransformComponent>();
|
||||
|
||||
if (ActiveExplosion != null && ActiveExplosion.Map == args.Viewport.Eye?.Position.MapId)
|
||||
{
|
||||
DrawExplosion(drawHandle, args.WorldBounds, ActiveExplosion, Index, xforms);
|
||||
}
|
||||
|
||||
foreach (var exp in CompletedExplosions)
|
||||
{
|
||||
if (exp.Map == args.Viewport.Eye?.Position.MapId)
|
||||
DrawExplosion(drawHandle, args.WorldBounds, exp, exp.Intensity.Count, xforms);
|
||||
}
|
||||
|
||||
drawHandle.SetTransform(Matrix3.Identity);
|
||||
}
|
||||
|
||||
private void DrawExplosion(DrawingHandleWorld drawHandle, Box2Rotated worldBounds, Explosion exp, int index, EntityQuery<TransformComponent> xforms)
|
||||
{
|
||||
Box2 gridBounds;
|
||||
foreach (var (gridId, tiles) in exp.Tiles)
|
||||
{
|
||||
if (!_mapManager.TryGetGrid(gridId, out var grid))
|
||||
continue;
|
||||
|
||||
var xform = xforms.GetComponent(grid.GridEntityId);
|
||||
var (_, _, worldMatrix, invWorldMatrix) = xform.GetWorldPositionRotationMatrixWithInv(xforms);
|
||||
|
||||
gridBounds = invWorldMatrix.TransformBox(worldBounds);
|
||||
drawHandle.SetTransform(worldMatrix);
|
||||
|
||||
DrawTiles(drawHandle, gridBounds, index, tiles, exp, grid.TileSize);
|
||||
}
|
||||
|
||||
if (exp.SpaceTiles == null)
|
||||
return;
|
||||
|
||||
gridBounds = Matrix3.Invert(exp.SpaceMatrix).TransformBox(worldBounds);
|
||||
drawHandle.SetTransform(exp.SpaceMatrix);
|
||||
|
||||
DrawTiles(drawHandle, gridBounds, index, exp.SpaceTiles, exp, exp.SpaceTileSize);
|
||||
}
|
||||
|
||||
private void DrawTiles(
|
||||
DrawingHandleWorld drawHandle,
|
||||
Box2 gridBounds,
|
||||
int index,
|
||||
Dictionary<int, List<Vector2i>> tileSets,
|
||||
Explosion exp,
|
||||
ushort tileSize)
|
||||
{
|
||||
for (var j = 0; j < index; j++)
|
||||
{
|
||||
if (!tileSets.TryGetValue(j, out var tiles))
|
||||
continue;
|
||||
|
||||
var frameIndex = (int) Math.Min(exp.Intensity[j] / exp.IntensityPerState, exp.FireFrames.Count - 1);
|
||||
var frames = exp.FireFrames[frameIndex];
|
||||
|
||||
foreach (var tile in tiles)
|
||||
{
|
||||
Vector2 centre = ((Vector2) tile + 0.5f) * tileSize;
|
||||
|
||||
if (!gridBounds.Contains(centre))
|
||||
continue;
|
||||
|
||||
var texture = _robustRandom.Pick(frames);
|
||||
drawHandle.DrawTextureRect(texture, Box2.CenteredAround(centre, (tileSize, tileSize)), exp.FireColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user