GameLoop/ArenaGameManager.cs
/// <summary>
/// Arena game manager — gives every spawning player a Peach Launcher instead
/// of the default sandbox loadout (physgun, toolgun, camera).
///
/// SETUP
/// ──────
/// Add this component to the same GameObject as GameManager in your arena scene,
/// or place it anywhere in the scene as a standalone component.
///
/// Assign PeachLauncherPrefab in the inspector:
///   → weapons/peach_launcher/peach_launcher.prefab
///
/// Make sure your scene has SpawnPoint components so FindSpawnLocation() works.
/// </summary>
[Title( "Arena Game Manager" )]
[Category( "Game / Peach" )]
public sealed class ArenaGameManager : Component, Global.IPlayerEvents
{
	[Property] public GameObject PeachLauncherPrefab { get; set; }

	// ── IPlayerEvents ──────────────────────────────────────────────────────────

	void Global.IPlayerEvents.OnPlayerSpawned( Player player )
	{
		if ( !Networking.IsHost ) return;
		if ( !player.IsValid() ) return;

		GivePeachLauncher( player );
	}

	// ── Loadout ────────────────────────────────────────────────────────────────

	private void GivePeachLauncher( Player player )
	{
		var inventory = player.Components.Get<PlayerInventory>();
		if ( !inventory.IsValid() )
		{
			Log.Warning( "ArenaGameManager: Player has no PlayerInventory!" );
			return;
		}

		if ( !PeachLauncherPrefab.IsValid() )
		{
			Log.Warning( "ArenaGameManager: PeachLauncherPrefab is not assigned!" );
			return;
		}

		// Clear whatever the loadout system restored (physgun, toolgun etc.)
		// Give a frame for PlayerLoadout.OnPlayerSpawned to have run first,
		// then we override it.
		_ = GivePeachLauncherAsync( player, inventory );
	}

	private async Task GivePeachLauncherAsync( Player player, PlayerInventory inventory )
	{
		// Yield so PlayerLoadout's OnPlayerSpawned (which also listens to
		// Global.IPlayerEvents.OnPlayerSpawned) can run first and give its
		// weapons — then we clear and replace.
		await Task.Yield();

		if ( !player.IsValid() || !inventory.IsValid() ) return;

		// Remove whatever the loadout gave
		foreach ( var weapon in inventory.Weapons.ToList() )
			weapon.DestroyGameObject();

		await Task.Yield();

		// Give the peach launcher in slot 0
		inventory.Pickup( PeachLauncherPrefab, 0, false );
		inventory.SwitchWeapon( inventory.GetSlot( 0 ) );
	}
}