using System;
using UnityEngine;
using Vanguard.Battle;
namespace Vanguard.Battle
{
///
/// Оркестратор кинематографичной проверки триггера:
/// zoom → reveal hold → return; повторный zoom в цепочке.
///
public sealed class TriggerCheckSequence
{
private enum Stage
{
Idle,
Zooming,
Revealing,
Holding,
Returning,
}
private readonly CameraDirector _camera;
private readonly InputLockService _inputLock;
private Stage _stage;
private float _deadline;
private float _zoomDeadline;
private float _revealDeadline;
private float _resolveDeadline;
private bool _chainActive;
private bool _restoreRequested;
private bool _lockHeld;
public TriggerCheckSequence(
CameraDirector camera,
InputLockService inputLock)
{
_camera = camera;
_inputLock = inputLock;
}
public bool IsBusy => _stage != Stage.Idle;
///
/// true — камера ушла на trigger-зону, руку нужно скрыть;
/// false — камера вернулась, руку можно показать.
///
public event Action FocusChanged;
/// Камера закончила зум и стоит на trigger-зоне.
public event Action ZoomCompleted;
/// Карта раскрыта и выдержана пауза — можно резолвить триггер.
public event Action ResolveReady;
public void ShowTrigger(
AnimationConfig config,
Vector3 worldPoint)
{
if (_camera == null)
return;
var wasIdle = _stage == Stage.Idle;
if (!_chainActive)
{
_camera.BeginChain();
_chainActive = true;
}
Acquire();
_restoreRequested = false;
var zoom = config != null
? config.cameraZoomDuration
: 0.35f;
var reveal = config != null
? config.triggerRevealDuration
: 0.35f;
var pause = config != null
? config.triggerRevealHold
: 0.75f;
_camera.ZoomTo(worldPoint, zoom);
_stage = Stage.Zooming;
_zoomDeadline = Time.unscaledTime + zoom;
_revealDeadline = _zoomDeadline + reveal;
_resolveDeadline = _revealDeadline + pause;
if (wasIdle)
OnFocusChanged(true);
}
public void ReturnForChoice(AnimationConfig config)
{
if (!_chainActive)
return;
var duration = config != null
? config.cameraReturnDuration
: 0.4f;
_camera.ReturnToOrigin(duration);
_stage = Stage.Returning;
_deadline = Time.unscaledTime + duration;
}
public void EndChain(AnimationConfig config)
{
if (!_chainActive)
{
Release();
return;
}
var duration = config != null
? config.cameraReturnDuration
: 0.4f;
_restoreRequested = true;
_camera.ReturnToOrigin(duration);
_stage = Stage.Returning;
_deadline = Time.unscaledTime + duration;
}
public void Tick(AnimationConfig config)
{
if (_stage == Stage.Idle)
return;
if (_stage == Stage.Zooming
&& Time.unscaledTime >= _zoomDeadline)
{
_stage = Stage.Revealing;
ZoomCompleted?.Invoke();
}
if (_stage == Stage.Revealing
&& Time.unscaledTime >= _revealDeadline)
{
_stage = Stage.Holding;
}
if (_stage == Stage.Holding
&& Time.unscaledTime >= _resolveDeadline)
{
ResolveReady?.Invoke();
var duration = config != null
? config.cameraReturnDuration
: 0.4f;
_restoreRequested = true;
_camera.ReturnToOrigin(duration);
_stage = Stage.Returning;
_deadline = Time.unscaledTime + duration;
}
if (_stage == Stage.Returning
&& Time.unscaledTime >= _deadline)
{
_stage = Stage.Idle;
Release();
if (_restoreRequested)
{
_restoreRequested = false;
_chainActive = false;
_camera.Restore();
}
OnFocusChanged(false);
}
}
private void Acquire()
{
if (_lockHeld)
return;
_inputLock?.Acquire("trigger-sequence");
_lockHeld = true;
}
private void Release()
{
if (!_lockHeld)
return;
_inputLock?.Release("trigger-sequence");
_lockHeld = false;
}
public void Cancel()
{
var wasIdle = _stage == Stage.Idle;
_stage = Stage.Idle;
_chainActive = false;
Release();
_camera?.Restore();
if (!wasIdle)
OnFocusChanged(false);
}
private void OnFocusChanged(bool focused)
{
FocusChanged?.Invoke(focused);
}
}
}