Co-authored-by: Michal Pikulski <michal@foolhardyhorizons.com> Co-authored-by: Michal Pikulski <michal.a.pikulski@gmail.com> Reviewed-on: #77
233 lines
6.8 KiB
C#
233 lines
6.8 KiB
C#
using System;
|
|
using Core;
|
|
using UnityEngine;
|
|
|
|
namespace Minigames.Airplane.Abilities
|
|
{
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
[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
|
|
|
|
/// <summary>
|
|
/// Base constructor for abilities. Called by subclasses.
|
|
/// </summary>
|
|
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<BaseAirplaneAbility> OnAbilityActivated;
|
|
public event Action<BaseAirplaneAbility> OnAbilityDeactivated;
|
|
public event Action<float, float> OnCooldownChanged; // (remaining, total)
|
|
|
|
#endregion
|
|
|
|
#region Lifecycle
|
|
|
|
/// <summary>
|
|
/// Initialize ability with airplane reference.
|
|
/// Called when airplane is spawned.
|
|
/// </summary>
|
|
public virtual void Initialize(Core.AirplaneController airplane)
|
|
{
|
|
currentAirplane = airplane;
|
|
isActive = false;
|
|
isOnCooldown = false;
|
|
cooldownTimer = 0f;
|
|
|
|
if (showDebugLogs)
|
|
{
|
|
Logging.Debug($"[{abilityName}] Initialized with airplane");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Update cooldown timer. Called every frame by ability manager.
|
|
/// </summary>
|
|
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);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Cleanup when airplane is destroyed or flight ends.
|
|
/// </summary>
|
|
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)
|
|
|
|
/// <summary>
|
|
/// Execute the ability effect.
|
|
/// Override to implement specific ability behavior.
|
|
/// </summary>
|
|
public abstract void Execute();
|
|
|
|
/// <summary>
|
|
/// Stop the ability effect (for sustained abilities).
|
|
/// Override if ability can be deactivated.
|
|
/// </summary>
|
|
public virtual void Deactivate()
|
|
{
|
|
if (!isActive) return;
|
|
|
|
isActive = false;
|
|
OnAbilityDeactivated?.Invoke(this);
|
|
|
|
if (showDebugLogs)
|
|
{
|
|
Logging.Debug($"[{abilityName}] Deactivated");
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Protected Helpers
|
|
|
|
/// <summary>
|
|
/// Start ability activation (called by subclasses).
|
|
/// </summary>
|
|
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");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Start cooldown timer (called by subclasses after execution).
|
|
/// </summary>
|
|
protected virtual void StartCooldown()
|
|
{
|
|
isOnCooldown = true;
|
|
cooldownTimer = cooldownDuration;
|
|
OnCooldownChanged?.Invoke(cooldownTimer, cooldownDuration);
|
|
|
|
if (showDebugLogs)
|
|
{
|
|
Logging.Debug($"[{abilityName}] Cooldown started: {cooldownDuration}s");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Check if airplane reference is valid.
|
|
/// </summary>
|
|
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
|
|
}
|
|
}
|
|
|