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/Actions/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("Shield duration in seconds")] public float shieldDuration = 5f; [Tooltip("Animator bool parameter name for blocking state")] public string animatorBlockingBool = "IsBlocking"; [Header("Debug")] [Tooltip("Enable debug logging")] public bool enableDebug = false; private GameObject spawnedShield; private Animator npcAnimator; private Transform npcTransform; 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"); // Store NPC references npcTransform = fsmBehaviour.transform; npcAnimator = npcTransform.GetComponent(); var aiController = fsmBehaviour as Invector.vCharacterController.AI.vIControlAI; if (aiController != null) { aiController.Stop(); if (enableDebug) Debug.Log("[SA_CastShield] AI stopped"); } if (npcAnimator != null && !string.IsNullOrEmpty(animatorBlockingBool)) { npcAnimator.SetBool(animatorBlockingBool, true); if (enableDebug) Debug.Log($"[SA_CastShield] Set bool: {animatorBlockingBool} = true"); } 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 (npcAnimator != null && !string.IsNullOrEmpty(animatorBlockingBool)) { npcAnimator.SetBool(animatorBlockingBool, false); if (enableDebug) Debug.Log($"[SA_CastShield] Set bool: {animatorBlockingBool} = false"); } 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; } // Spawn shield at NPC's position and rotation Vector3 spawnPosition = npcTransform.position; Quaternion spawnRotation = npcTransform.rotation; spawnedShield = LeanPool.Spawn(shieldFXPrefab, spawnPosition, spawnRotation); if (enableDebug) Debug.Log($"[SA_CastShield] Shield spawned at NPC position: {spawnPosition}"); } /// /// 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)); } } }