BurningVfx.cs
using Sandbox;
using SpriteTools;

public class BurningVfx : Component
{
	[Property] public SpriteRendererLayer Sprite { get; set; }

	public Enemy Enemy { get; set; }

	private TimeSince _timeSince;
	private float _timeOffset;
	private float _ySpeed;

	public int NumStacks { get; private set; }

	public float ScaleModifier { get; set; }

	protected override void OnAwake()
	{
		base.OnAwake();

		_timeSince = 0f;
		_timeOffset = Game.Random.Float( 0f, 10f );
		_ySpeed = Game.Random.Float( 7f, 16f );

		LocalRotation = new Angles( 0f, -90f, 0f );
		LocalPosition = new Vector3( 0f, 0f, 0.1f );
		Sprite.LocalScale = new Vector3( 1f ) * Globals.SPRITE_SCALE;
		Sprite.Tint = Color.White.WithAlpha( 0f );

		ScaleModifier = 1.5f;

		NumStacks = 0;
	}

	protected override void OnUpdate()
	{
		float speed = Utils.Map( NumStacks, 0, 7, 0.75f, 7f );

		bool flip = Utils.FastSin( _timeOffset + _timeSince * 4f * speed ) < 0f;
		Sprite.SpriteFlags = flip ? SpriteFlags.HorizontalFlip : SpriteFlags.None;

		float scaleFactor = Utils.Map( Enemy.Scale, 0.85f, 2.5f, 0.9f, 1.9f ) * Utils.Map(NumStacks, 0, 7, 0.85f, 1.15f, EasingType.ExpoOut);
		Sprite.LocalScale = new Vector3( (1f + Utils.FastSin( _timeOffset + _timeSince * _ySpeed * speed ) * 0.1f), 1f + Utils.FastSin( _timeOffset + _timeSince * 14f * speed ) * 0.08f, 1f ) * scaleFactor * Globals.SPRITE_SCALE * ScaleModifier;
		Sprite.Tint = Color.White.WithAlpha(0.5f + Utils.FastSin( _timeOffset + _timeSince * 20f * speed ) * 0.2f) * Utils.Map( Enemy.DeathProgress, 0f, 1f, 1f, 0f ) * Enemy.VfxOpacity;

		Sprite.LocalPosition = Sprite.LocalPosition.WithY( Enemy.Sprite.LocalPosition.y );

		ScaleModifier = Utils.DynamicEaseTo( ScaleModifier, 1f, 0.125f, Time.Delta );
	}

	public void SetStacks(int stacks )
	{
		if ( stacks > NumStacks )
			ScaleModifier = 1.6f;
		else if ( stacks < NumStacks )
			ScaleModifier = 0.2f;

		NumStacks = stacks;
	}
}