using System; using Core; using UnityEngine; namespace Minigames.Airplane.Abilities { /// /// Abstract base class for airplane special abilities. /// Each ability defines its own execution logic, input handling, and cooldown. /// Subclasses override Execute() to implement specific ability behavior. /// Created from settings configuration at runtime. /// [System.Serializable] public abstract class BaseAirplaneAbility { #region Configuration protected readonly string abilityName; protected readonly Sprite abilityIcon; protected readonly float cooldownDuration; protected readonly bool canReuse; protected bool showDebugLogs; #endregion #region Constructor /// /// Base constructor for abilities. Called by subclasses. /// protected BaseAirplaneAbility(string name, Sprite icon, float cooldown, bool reusable = true) { abilityName = name; abilityIcon = icon; cooldownDuration = cooldown; canReuse = reusable; showDebugLogs = false; } #endregion #region Properties public string AbilityName => abilityName; public Sprite AbilityIcon => abilityIcon; public float CooldownDuration => cooldownDuration; public bool CanReuse => canReuse; #endregion #region State (Runtime) protected Core.AirplaneController currentAirplane; protected bool isActive; protected bool isOnCooldown; protected float cooldownTimer; public bool IsActive => isActive; public bool IsOnCooldown => isOnCooldown; public float CooldownRemaining => cooldownTimer; public bool CanActivate => !isOnCooldown && !isActive && currentAirplane != null && currentAirplane.IsFlying; #endregion #region Events public event Action OnAbilityActivated; public event Action OnAbilityDeactivated; public event Action OnCooldownChanged; // (remaining, total) #endregion #region Lifecycle /// /// Initialize ability with airplane reference. /// Called when airplane is spawned. /// public virtual void Initialize(Core.AirplaneController airplane) { currentAirplane = airplane; isActive = false; isOnCooldown = false; cooldownTimer = 0f; if (showDebugLogs) { Logging.Debug($"[{abilityName}] Initialized with airplane"); } } /// /// Update cooldown timer. Called every frame by ability manager. /// public virtual void UpdateCooldown(float deltaTime) { if (isOnCooldown) { cooldownTimer -= deltaTime; if (cooldownTimer <= 0f) { cooldownTimer = 0f; isOnCooldown = false; if (showDebugLogs) { Logging.Debug($"[{abilityName}] Cooldown complete"); } } OnCooldownChanged?.Invoke(cooldownTimer, cooldownDuration); } } /// /// Cleanup when airplane is destroyed or flight ends. /// public virtual void Cleanup() { if (isActive) { Deactivate(); } currentAirplane = null; isActive = false; isOnCooldown = false; cooldownTimer = 0f; if (showDebugLogs) { Logging.Debug($"[{abilityName}] Cleaned up"); } } #endregion #region Abstract Methods (Must Override) /// /// Execute the ability effect. /// Override to implement specific ability behavior. /// public abstract void Execute(); /// /// Stop the ability effect (for sustained abilities). /// Override if ability can be deactivated. /// public virtual void Deactivate() { if (!isActive) return; isActive = false; OnAbilityDeactivated?.Invoke(this); if (showDebugLogs) { Logging.Debug($"[{abilityName}] Deactivated"); } } #endregion #region Protected Helpers /// /// Start ability activation (called by subclasses). /// protected virtual void StartActivation() { if (!CanActivate) { if (showDebugLogs) { Logging.Warning($"[{abilityName}] Cannot activate - IsOnCooldown: {isOnCooldown}, IsActive: {isActive}, CanFly: {currentAirplane?.IsFlying}"); } return; } isActive = true; OnAbilityActivated?.Invoke(this); if (showDebugLogs) { Logging.Debug($"[{abilityName}] Activated"); } } /// /// Start cooldown timer (called by subclasses after execution). /// protected virtual void StartCooldown() { isOnCooldown = true; cooldownTimer = cooldownDuration; OnCooldownChanged?.Invoke(cooldownTimer, cooldownDuration); if (showDebugLogs) { Logging.Debug($"[{abilityName}] Cooldown started: {cooldownDuration}s"); } } /// /// Check if airplane reference is valid. /// protected bool ValidateAirplane() { if (currentAirplane == null) { Logging.Warning($"[{abilityName}] Cannot execute - airplane reference is null!"); return false; } if (!currentAirplane.IsFlying) { if (showDebugLogs) { Logging.Debug($"[{abilityName}] Cannot execute - airplane is not flying!"); } return false; } return true; } #endregion } }