Files
beyond/Assets/AI/_Demon/DEC_CheckCooldown.cs
2025-11-20 14:34:59 +01:00

205 lines
6.1 KiB
C#

using Invector.vCharacterController.AI.FSMBehaviour;
using UnityEngine;
namespace DemonBoss.Magic
{
/// <summary>
/// Decision node checking cooldown for different boss abilities
/// Stores Time.time in FSM timers and checks if required cooldown time has passed
/// </summary>
[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;
/// <summary>
/// Main method checking if ability is available
/// </summary>
/// <returns>True if cooldown has passed and ability can be used</returns>
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;
}
/// <summary>
/// Sets cooldown for ability - call this after using ability
/// </summary>
public void SetCooldown(vIFSMBehaviourController fsmBehaviour)
{
SetCooldown(fsmBehaviour, cooldownTime);
}
/// <summary>
/// Sets cooldown with custom time
/// </summary>
/// <param name="fsmBehaviour">FSM behaviour reference</param>
/// <param name="customCooldownTime">Custom cooldown time</param>
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");
}
}
/// <summary>
/// Resets cooldown - ability becomes immediately available
/// </summary>
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}");
}
/// <summary>
/// Returns remaining cooldown time in seconds
/// </summary>
/// <returns>Remaining cooldown time (0 if available)</returns>
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);
}
/// <summary>
/// Checks if ability is available without running main Decision logic
/// </summary>
/// <returns>True if ability is available</returns>
public bool IsAvailable(vIFSMBehaviourController fsmBehaviour)
{
return GetRemainingCooldown(fsmBehaviour) <= 0f;
}
/// <summary>
/// Returns cooldown progress percentage (0-1)
/// </summary>
/// <returns>Progress percentage: 0 = just used, 1 = fully recharged</returns>
public float GetCooldownProgress(vIFSMBehaviourController fsmBehaviour)
{
if (cooldownTime <= 0f) return 1f;
float remainingTime = GetRemainingCooldown(fsmBehaviour);
return 1f - (remainingTime / cooldownTime);
}
/// <summary>
/// Helper method for setting cooldown from external code (e.g. from StateAction)
/// </summary>
/// <param name="fsmBehaviour">FSM reference</param>
/// <param name="key">Ability key</param>
/// <param name="cooldown">Cooldown time</param>
public static void SetCooldownStatic(vIFSMBehaviourController fsmBehaviour, string key, float cooldown)
{
if (fsmBehaviour == null) return;
string timerKey = "cooldown_" + key;
fsmBehaviour.SetTimer(timerKey, Time.time);
}
/// <summary>
/// Helper method for checking cooldown from external code
/// </summary>
/// <param name="fsmBehaviour">FSM reference</param>
/// <param name="key">Ability key</param>
/// <param name="cooldown">Cooldown time</param>
/// <returns>True if available</returns>
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;
}
}
}