using Invector.vCharacterController.AI.FSMBehaviour; using UnityEngine; namespace DemonBoss.Magic { /// /// Decision node checking cooldown for different boss abilities /// Stores Time.time in FSM timers and checks if required cooldown time has passed /// [CreateAssetMenu(menuName = "Invector/FSM/Decisions/DemonBoss/Check Cooldown")] public class DEC_CheckCooldown : vStateDecision { public override string categoryName => "DemonBoss/Magic"; public override string defaultName => "Check Cooldown"; [Header("Cooldown Configuration")] [Tooltip("Unique key for this ability (e.g. 'Shield', 'Turret', 'Meteor')")] public string cooldownKey = "Shield"; [Tooltip("Cooldown time in seconds")] public float cooldownTime = 10f; [Tooltip("Whether ability should be available immediately at fight start")] public bool availableAtStart = true; [Header("Debug")] [Tooltip("Enable debug logging")] public bool enableDebug = false; /// /// Main method checking if ability is available /// /// True if cooldown has passed and ability can be used public override bool Decide(vIFSMBehaviourController fsmBehaviour) { if (fsmBehaviour == null) { if (enableDebug) Debug.LogWarning($"[DEC_CheckCooldown] No FSM Behaviour for key: {cooldownKey}"); return false; } string timerKey = "cooldown_" + cooldownKey; if (!fsmBehaviour.HasTimer(timerKey)) { if (availableAtStart) { if (enableDebug) Debug.Log($"[DEC_CheckCooldown] First use for {cooldownKey} - available"); return true; } else { SetCooldown(fsmBehaviour, cooldownTime); if (enableDebug) Debug.Log($"[DEC_CheckCooldown] First use for {cooldownKey} - setting cooldown"); return false; } } float lastUsedTime = fsmBehaviour.GetTimer(timerKey); float timeSinceLastUse = Time.time - lastUsedTime; bool isAvailable = timeSinceLastUse >= cooldownTime; if (enableDebug) { if (isAvailable) { Debug.Log($"[DEC_CheckCooldown] {cooldownKey} available - {timeSinceLastUse:F1}s passed of required {cooldownTime}s"); } else { float remainingTime = cooldownTime - timeSinceLastUse; Debug.Log($"[DEC_CheckCooldown] {cooldownKey} on cooldown - {remainingTime:F1}s remaining"); } } return isAvailable; } /// /// Sets cooldown for ability - call this after using ability /// public void SetCooldown(vIFSMBehaviourController fsmBehaviour) { SetCooldown(fsmBehaviour, cooldownTime); } /// /// Sets cooldown with custom time /// /// FSM behaviour reference /// Custom cooldown time public void SetCooldown(vIFSMBehaviourController fsmBehaviour, float customCooldownTime) { if (fsmBehaviour == null) { if (enableDebug) Debug.LogWarning($"[DEC_CheckCooldown] Cannot set cooldown - no FSM Behaviour"); return; } string timerKey = "cooldown_" + cooldownKey; fsmBehaviour.SetTimer(timerKey, Time.time); if (enableDebug) { Debug.Log($"[DEC_CheckCooldown] Set cooldown for {cooldownKey}: {customCooldownTime}s"); } } /// /// Resets cooldown - ability becomes immediately available /// public void ResetCooldown(vIFSMBehaviourController fsmBehaviour) { if (fsmBehaviour == null) { if (enableDebug) Debug.LogWarning($"[DEC_CheckCooldown] Cannot reset cooldown - no FSM Behaviour"); return; } string timerKey = "cooldown_" + cooldownKey; float pastTime = Time.time - cooldownTime - 1f; fsmBehaviour.SetTimer(timerKey, pastTime); if (enableDebug) Debug.Log($"[DEC_CheckCooldown] Reset cooldown for {cooldownKey}"); } /// /// Returns remaining cooldown time in seconds /// /// Remaining cooldown time (0 if available) public float GetRemainingCooldown(vIFSMBehaviourController fsmBehaviour) { if (fsmBehaviour == null) return 0f; string timerKey = "cooldown_" + cooldownKey; if (!fsmBehaviour.HasTimer(timerKey)) { return availableAtStart ? 0f : cooldownTime; } float lastUsedTime = fsmBehaviour.GetTimer(timerKey); float timeSinceLastUse = Time.time - lastUsedTime; return Mathf.Max(0f, cooldownTime - timeSinceLastUse); } /// /// Checks if ability is available without running main Decision logic /// /// True if ability is available public bool IsAvailable(vIFSMBehaviourController fsmBehaviour) { return GetRemainingCooldown(fsmBehaviour) <= 0f; } /// /// Returns cooldown progress percentage (0-1) /// /// Progress percentage: 0 = just used, 1 = fully recharged public float GetCooldownProgress(vIFSMBehaviourController fsmBehaviour) { if (cooldownTime <= 0f) return 1f; float remainingTime = GetRemainingCooldown(fsmBehaviour); return 1f - (remainingTime / cooldownTime); } /// /// Helper method for setting cooldown from external code (e.g. from StateAction) /// /// FSM reference /// Ability key /// Cooldown time public static void SetCooldownStatic(vIFSMBehaviourController fsmBehaviour, string key, float cooldown) { if (fsmBehaviour == null) return; string timerKey = "cooldown_" + key; fsmBehaviour.SetTimer(timerKey, Time.time); } /// /// Helper method for checking cooldown from external code /// /// FSM reference /// Ability key /// Cooldown time /// True if available public static bool CheckCooldownStatic(vIFSMBehaviourController fsmBehaviour, string key, float cooldown) { if (fsmBehaviour == null) return false; string timerKey = "cooldown_" + key; if (!fsmBehaviour.HasTimer(timerKey)) return true; float lastUsedTime = fsmBehaviour.GetTimer(timerKey); return (Time.time - lastUsedTime) >= cooldown; } } }