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); } } }