GameLogic/ArenaTrigger.cs
using Sandbox;

public sealed class ArenaTrigger : Component, Component.ITriggerListener
{
	[Property, Title( "Délai de réarmement au camp (sec)" )] 
	public float ArmDelay { get; set; } = 2.0f;

	private TimeSince _timeSinceBufferEntered = 10f;
	private bool _isArmed = false;

	protected override void OnEnabled()
	{
		GameManager.OnPhaseChanged += HandlePhaseChanged;
	}

	protected override void OnDisabled()
	{
		GameManager.OnPhaseChanged -= HandlePhaseChanged;
	}

	private void HandlePhaseChanged( GamePhase newPhase )
	{
		if ( newPhase == GamePhase.BufferZone )
		{
			// Désarmé dès le retour au camp pour ignorer la téléportation
			_isArmed = false;
			_timeSinceBufferEntered = 0f;
		}
		else
		{
			// Désactivé pendant les combats, intros et récaps
			_isArmed = false;
		}
	}

	protected override void OnUpdate()
	{
		// Ne s'arme que si le joueur est au camp depuis plus de 2 secondes
		if ( !_isArmed && GameManager.Instance?.CurrentPhase == GamePhase.BufferZone )
		{
			if ( _timeSinceBufferEntered >= ArmDelay )
			{
				_isArmed = true;
				Log.Info( "🟢 [SAS] Le passage vers l'arène est paré. Franchis la ligne pour lancer le combat." );
			}
		}
	}

	public void OnTriggerEnter( Collider other )
	{
		// Ignore tant qu'il n'est pas armé ou si la phase n'est pas la zone tampon
		if ( !_isArmed ) return;
		if ( GameManager.Instance == null || GameManager.Instance.CurrentPhase != GamePhase.BufferZone ) return;

		var player = other.GameObject.Components.Get<PlayerController>( FindMode.EverythingInSelfAndAncestors );
		if ( player != null )
		{
			_isArmed = false; // Désarmement immédiat pour éviter tout double-déclenchement
			Log.Info( "⚔️ [SAS] Le joueur s'avance dans le couloir ! Lancement de la manche..." );
			GameManager.Instance.TriggerEnterArena();
		}
	}

	public void OnTriggerExit( Collider other ) { }
}