Utility/Effects.cs

Utility class for spawning and playing local particle prefab Scene-System effects. It looks up a prefab by path, clones it into the scene at a position/rotation, and optionally auto-destroys the clone after a lifetime.

File Access
using Sandbox;

namespace BrickJam;

/// <summary>
/// Spawns the Scene-System <see cref="ParticleEffect"/> prefabs (under <c>prefabs/particles/</c>) that
/// replace the legacy <c>.vpcf</c> particles. Effects are purely cosmetic, so they're cloned locally
/// (non-networked); use <see cref="MansionGame.PlayEffect"/> to broadcast a one-shot to every client.
/// </summary>
public static class Effects
{
	/// <summary>Clone a particle prefab at a transform. Returns the GameObject (caller owns its lifetime).</summary>
	public static GameObject Spawn( string prefabPath, Vector3 position, Rotation rotation )
	{
		var prefab = ResourceLibrary.Get<PrefabFile>( prefabPath );
		if ( prefab is null )
		{
			Log.Warning( $"[Effects] particle prefab not found: {prefabPath}" );
			return null;
		}

		return SceneUtility.GetPrefabScene( prefab )?.Clone( new Transform( position, rotation ) );
	}

	/// <summary>Play a one-shot particle prefab locally and auto-destroy it after <paramref name="lifetime"/>.</summary>
	public static async void Play( string prefabPath, Vector3 position, Rotation rotation, float lifetime = 4f )
	{
		var go = Spawn( prefabPath, position, rotation );
		if ( go is null )
			return;

		await GameTask.DelayRealtimeSeconds( lifetime );

		if ( go.IsValid() )
			go.Destroy();
	}

	public static void Play( string prefabPath, Vector3 position ) => Play( prefabPath, position, Rotation.Identity );
}