DamageNumbers.cs
using Sandbox;
using Sandbox.Utility;
using System.Drawing;
public class DamageNumberData
{
public int amount;
public Vector2 pos;
public RealTimeSince timeSince;
public Color color;
public Vector2 velocity;
}
public class DamageNumbers : Component
{
[RequireComponent] public CameraComponent Camera { get; set; }
IDisposable renderHook;
protected override void OnEnabled()
{
renderHook?.Dispose();
//renderHook = Camera.AddHookAfterUI( "DamageNumbers", 700, RenderEffect );
}
protected override void OnDisabled()
{
renderHook?.Dispose();
renderHook = null;
}
static List<DamageNumberData> Numbers = new();
public static void Add( float amount, Vector2 pos, Color color )
{
if ( amount < 1f )
{
amount = MathF.Ceiling( amount );
}
else
{
float fractional = amount - MathF.Floor( amount );
if ( fractional > 0f && Game.Random.Float( 0f, 1f ) > fractional )
amount = MathF.Floor( amount );
else
amount = MathF.Ceiling( amount );
}
Numbers.Add( new DamageNumberData() {
amount = (int)amount,
pos = pos,
timeSince = 0,
color = color,
velocity = new Vector2(Game.Random.Float(-3f, 3f), Game.Random.Float(7f, 10f)),
} );
}
protected override void OnUpdate()
{
var dt = Time.Delta;
for ( int i = Numbers.Count - 1; i >= 0; i-- )
{
var data = Numbers[i];
if ( data.timeSince >= TimeToLive )
{
Numbers.RemoveAt( i );
}
else
{
data.pos += (data.velocity + Vector2.Down * 3f) * dt;
data.velocity *= (1f - dt * 4f);
}
}
}
public const float TimeToLive = 1f;
//public float RiseAmount => 64.0f;
public void RenderEffect( SceneCamera camera )
{
foreach ( var data in Numbers )
{
var screenPos = camera.ToScreen( (Vector3)data.pos ) + new Vector2( -60f, -60f );
// Piss around with different Easing methods
//var ease = Easing.ExpoOut( data.timeSince / TimeToLive );
//screenPos += Vector2.Up * ease * -64f + new Vector2(-60f, -60f);
var color = data.color.WithAlpha( 1.0f - Easing.EaseInOut( data.timeSince / TimeToLive ) );
float fontSize = Utils.Map( data.amount, 1f, 20f, 32f, 40f) * Utils.Map( data.amount, 20f, 150f, 1f, 1.4f, EasingType.QuadIn );
var bgColor = Color.Black.WithAlpha( 1.0f - Easing.EaseInOut( data.timeSince / TimeToLive ) );
Graphics.DrawText( new Rect( screenPos + new Vector2(-3f, 3f), 120f ), data.amount.ToString(), bgColor, "Poppins", (int)fontSize, 800, TextFlag.Center );
Graphics.DrawText( new Rect( screenPos, 120f ), data.amount.ToString(), color, "Poppins", (int)fontSize, 800, TextFlag.Center );
}
}
}