using Invector.vCharacterController.AI.FSMBehaviour; using Lean.Pool; using UnityEngine; namespace DemonBoss.Magic { /// /// StateAction for Magic Shield spell - boss casts magical shield for 5 seconds /// During casting boss stands still, after completion returns to Combat /// [CreateAssetMenu(menuName = "Invector/FSM/Decisions/DemonBoss/Cast Shield")] public class SA_CastShield : vStateAction { public override string categoryName => "DemonBoss/Magic"; public override string defaultName => "Cast Shield"; [Header("Shield Configuration")] [Tooltip("Prefab with magical shield particle effect")] public GameObject shieldFXPrefab; [Tooltip("Transform where shield should appear (usually boss center)")] public Transform shieldSpawnPoint; [Tooltip("Shield duration in seconds")] public float shieldDuration = 5f; [Tooltip("Animator trigger name for shield casting animation")] public string animatorTrigger = "CastShield"; [Header("Debug")] [Tooltip("Enable debug logging")] public bool enableDebug = false; private GameObject spawnedShield; private float shieldStartTime; private bool shieldActive = false; /// /// Main action execution method called by FSM /// public override void DoAction(vIFSMBehaviourController fsmBehaviour, vFSMComponentExecutionType executionType = vFSMComponentExecutionType.OnStateUpdate) { if (executionType == vFSMComponentExecutionType.OnStateEnter) { OnStateEnter(fsmBehaviour); } else if (executionType == vFSMComponentExecutionType.OnStateUpdate) { OnStateUpdate(fsmBehaviour); } else if (executionType == vFSMComponentExecutionType.OnStateExit) { OnStateExit(fsmBehaviour); } } /// /// Called when entering state - starts shield casting /// private void OnStateEnter(vIFSMBehaviourController fsmBehaviour) { if (enableDebug) Debug.Log("[SA_CastShield] Entering shield casting state"); var aiController = fsmBehaviour as Invector.vCharacterController.AI.vIControlAI; if (aiController != null) { aiController.Stop(); if (enableDebug) Debug.Log("[SA_CastShield] AI stopped"); } var animator = fsmBehaviour.transform.GetComponent(); if (animator != null && !string.IsNullOrEmpty(animatorTrigger)) { animator.SetTrigger(animatorTrigger); if (enableDebug) Debug.Log($"[SA_CastShield] Set trigger: {animatorTrigger}"); } SpawnShieldEffect(fsmBehaviour); shieldStartTime = Time.time; shieldActive = true; } /// /// Called every frame during state duration /// private void OnStateUpdate(vIFSMBehaviourController fsmBehaviour) { if (shieldActive && Time.time - shieldStartTime >= shieldDuration) { if (enableDebug) Debug.Log("[SA_CastShield] Shield time passed, finishing state"); FinishShield(fsmBehaviour); } } /// /// Called when exiting state - cleanup /// private void OnStateExit(vIFSMBehaviourController fsmBehaviour) { if (enableDebug) Debug.Log("[SA_CastShield] Exiting shield state"); if (shieldActive) { CleanupShield(); } var aiController = fsmBehaviour as Invector.vCharacterController.AI.vIControlAI; if (aiController != null) { if (enableDebug) Debug.Log("[SA_CastShield] AI resumed"); } } /// /// Spawns magical shield particle effect /// private void SpawnShieldEffect(vIFSMBehaviourController fsmBehaviour) { if (shieldFXPrefab == null) { Debug.LogWarning("[SA_CastShield] Missing shieldFXPrefab!"); return; } Vector3 spawnPosition = shieldSpawnPoint != null ? shieldSpawnPoint.position : fsmBehaviour.transform.position; spawnedShield = LeanPool.Spawn(shieldFXPrefab, spawnPosition, shieldSpawnPoint != null ? shieldSpawnPoint.rotation : fsmBehaviour.transform.rotation); if (enableDebug) Debug.Log($"[SA_CastShield] Shield spawned at position: {spawnPosition}"); if (spawnedShield != null && shieldSpawnPoint != null) { spawnedShield.transform.SetParent(shieldSpawnPoint); } } /// /// Finishes shield operation and transitions to next state /// private void FinishShield(vIFSMBehaviourController fsmBehaviour) { shieldActive = false; CleanupShield(); DEC_CheckCooldown.SetCooldownStatic(fsmBehaviour, "Shield", 15f); // End state - FSM will transition to next state // FYI: In Invector FSM, state completion is handled automatically } /// /// Cleans up spawned shield /// private void CleanupShield() { if (spawnedShield != null) { LeanPool.Despawn(spawnedShield); spawnedShield = null; if (enableDebug) Debug.Log("[SA_CastShield] Shield despawned"); } } /// /// Checks if shield is currently active /// public bool IsShieldActive() { return shieldActive; } /// /// Returns remaining shield time /// public float GetRemainingShieldTime() { if (!shieldActive) return 0f; return Mathf.Max(0f, shieldDuration - (Time.time - shieldStartTime)); } } }