DiamondDebris.Rotation.cs
using System;
using Sandbox;
using static Diamonds.DiamondBoard;

namespace Diamonds;

public sealed partial class DiamondDebris
{
	/// <summary>Emit a small spray from one or two open corners after syncing the debris world.</summary>
	public void EmitRotationSparks( Piece piece )
	{
		if ( physicsScene is null || currentBoard is null || currentBoard.Paused ) return;
		var corners = new List<(Vector2 Position, Vector2 Outward, int Color)>();
		Vector2[] offsets = [new( 0, -Height / 2 ), new( Width / 2, 0 ), new( 0, Height / 2 ), new( -Width / 2, 0 )];
		foreach ( var cell in CellsOf( piece ) )
		foreach ( var offset in offsets )
		{
			var origin = new Vector2( LaneX( cell.Lane ), cell.Y ) + offset;
			// Reject buried corners and corners pressed against the floor or stack.
			if ( HasRoom( origin + offset.Normal * 5, 2.2f ) )
				corners.Add( (origin, offset.Normal, cell.ColorIndex) );
		}
		int cornerCount = Math.Min( corners.Count, random.Next( 1, 3 ) );
		int remaining = random.Next( 3, 7 );
		for ( int corner = 0; corner < cornerCount; corner++ )
		{
			int index = random.Next( corners.Count );
			var source = corners[index];
			corners.RemoveAt( index );
			int count = corner == cornerCount - 1 ? remaining : (remaining + 1) / 2;
			remaining -= count;
			for ( int spark = 0; spark < count; spark++ )
			{
				float radius = Range( 0.7f, 1.3f );
				for ( int attempt = 0; attempt < 8; attempt++ )
				{
					float angle = Range( -0.65f, 0.65f );
					var direction = source.Outward * MathF.Cos( angle )
						+ new Vector2( -source.Outward.y, source.Outward.x ) * MathF.Sin( angle );
					var position = source.Position + direction * Range( 4, 7 );
					if ( !HasRoom( position, radius + 0.5f ) ) continue;
					AddSpark( position, direction * Range( 35, 70 ), radius, source.Color );
					break;
				}
			}
		}
	}
}