Working airplane ability revamp

This commit is contained in:
Michal Pikulski
2025-12-18 12:05:29 +01:00
parent ca56e748ba
commit dece09c45a
12 changed files with 407 additions and 99 deletions

View File

@@ -1,5 +1,4 @@
using AppleHills.Core.Settings;
using Core;
using Core;
using Core.Settings;
using Minigames.Airplane.Data;
@@ -38,7 +37,9 @@ namespace Minigames.Airplane.Abilities
config.abilityIcon,
config.cooldownDuration,
config.jetSpeed,
config.jetAngle
config.jetAngle,
config.maxActiveDuration,
config.cooldownMultiplier
);
}
@@ -61,7 +62,8 @@ namespace Minigames.Airplane.Abilities
config.abilityIcon,
config.cooldownDuration,
config.dropForce,
config.dropDistance,
config.maxActiveDuration,
config.cooldownMultiplier,
config.zeroHorizontalVelocity
);
}

View File

@@ -21,6 +21,10 @@ namespace Minigames.Airplane.Abilities
protected readonly bool canReuse;
protected bool showDebugLogs;
// Active duration configuration
protected readonly float maxActiveDuration;
protected readonly bool hasActiveDuration;
#endregion
#region Constructor
@@ -28,13 +32,15 @@ namespace Minigames.Airplane.Abilities
/// <summary>
/// Base constructor for abilities. Called by subclasses.
/// </summary>
protected BaseAirplaneAbility(string name, Sprite icon, float cooldown, bool reusable = true)
protected BaseAirplaneAbility(string name, Sprite icon, float cooldown, bool reusable = true, float activeDuration = 0f)
{
abilityName = name;
abilityIcon = icon;
cooldownDuration = cooldown;
canReuse = reusable;
showDebugLogs = false;
maxActiveDuration = activeDuration;
hasActiveDuration = activeDuration > 0f;
}
#endregion
@@ -45,6 +51,8 @@ namespace Minigames.Airplane.Abilities
public Sprite AbilityIcon => abilityIcon;
public float CooldownDuration => cooldownDuration;
public bool CanReuse => canReuse;
public bool HasActiveDuration => hasActiveDuration;
public float MaxActiveDuration => maxActiveDuration;
#endregion
@@ -54,12 +62,22 @@ namespace Minigames.Airplane.Abilities
protected bool isActive;
protected bool isOnCooldown;
protected float cooldownTimer;
protected float initialCooldownDuration; // Track initial cooldown for fill calculation
// Active duration tracking
protected float activeDurationTimer;
protected float activeDurationUsed; // Track how long ability was active
public bool IsActive => isActive;
public bool IsOnCooldown => isOnCooldown;
public float CooldownRemaining => cooldownTimer;
public float InitialCooldownDuration => initialCooldownDuration;
public bool CanActivate => !isOnCooldown && !isActive && currentAirplane != null && currentAirplane.IsFlying;
// Active duration state
public float ActiveDurationRemaining => activeDurationTimer;
public float ActiveProgress => hasActiveDuration && maxActiveDuration > 0f ? activeDurationTimer / maxActiveDuration : 0f;
#endregion
#region Events
@@ -67,6 +85,7 @@ namespace Minigames.Airplane.Abilities
public event Action<BaseAirplaneAbility> OnAbilityActivated;
public event Action<BaseAirplaneAbility> OnAbilityDeactivated;
public event Action<float, float> OnCooldownChanged; // (remaining, total)
public event Action<float, float> OnActiveDurationChanged; // (remaining, total)
#endregion
@@ -82,6 +101,9 @@ namespace Minigames.Airplane.Abilities
isActive = false;
isOnCooldown = false;
cooldownTimer = 0f;
initialCooldownDuration = 0f;
activeDurationTimer = 0f;
activeDurationUsed = 0f;
if (showDebugLogs)
{
@@ -109,10 +131,37 @@ namespace Minigames.Airplane.Abilities
}
}
OnCooldownChanged?.Invoke(cooldownTimer, cooldownDuration);
OnCooldownChanged?.Invoke(cooldownTimer, initialCooldownDuration);
}
}
/// <summary>
/// Update active duration timer. Called every frame by ability manager when ability is active.
/// Auto-deactivates when duration expires.
/// </summary>
public virtual void UpdateActiveDuration(float deltaTime)
{
if (!isActive || !hasActiveDuration) return;
activeDurationTimer -= deltaTime;
activeDurationUsed += deltaTime;
if (activeDurationTimer <= 0f)
{
activeDurationTimer = 0f;
if (showDebugLogs)
{
Logging.Debug($"[{abilityName}] Active duration expired, auto-deactivating");
}
// Auto-deactivate when duration expires
Deactivate();
}
OnActiveDurationChanged?.Invoke(activeDurationTimer, maxActiveDuration);
}
/// <summary>
/// Cleanup when airplane is destroyed or flight ends.
/// </summary>
@@ -127,6 +176,9 @@ namespace Minigames.Airplane.Abilities
isActive = false;
isOnCooldown = false;
cooldownTimer = 0f;
initialCooldownDuration = 0f;
activeDurationTimer = 0f;
activeDurationUsed = 0f;
if (showDebugLogs)
{
@@ -155,12 +207,26 @@ namespace Minigames.Airplane.Abilities
isActive = false;
OnAbilityDeactivated?.Invoke(this);
// Calculate and start dynamic cooldown
float dynamicCooldown = CalculateDynamicCooldown();
StartCooldown(dynamicCooldown);
if (showDebugLogs)
{
Logging.Debug($"[{abilityName}] Deactivated");
}
}
/// <summary>
/// Calculate cooldown duration based on ability usage.
/// Override in subclasses for custom dynamic cooldown logic.
/// Default: returns base cooldown duration.
/// </summary>
protected virtual float CalculateDynamicCooldown()
{
return cooldownDuration;
}
#endregion
#region Protected Helpers
@@ -180,6 +246,14 @@ namespace Minigames.Airplane.Abilities
}
isActive = true;
// Reset active duration timer if ability has active duration
if (hasActiveDuration)
{
activeDurationTimer = maxActiveDuration;
activeDurationUsed = 0f;
}
OnAbilityActivated?.Invoke(this);
if (showDebugLogs)
@@ -191,15 +265,16 @@ namespace Minigames.Airplane.Abilities
/// <summary>
/// Start cooldown timer (called by subclasses after execution).
/// </summary>
protected virtual void StartCooldown()
protected virtual void StartCooldown(float? customCooldown = null)
{
isOnCooldown = true;
cooldownTimer = cooldownDuration;
OnCooldownChanged?.Invoke(cooldownTimer, cooldownDuration);
cooldownTimer = customCooldown ?? cooldownDuration;
initialCooldownDuration = cooldownTimer; // Store the initial cooldown value
OnCooldownChanged?.Invoke(cooldownTimer, initialCooldownDuration);
if (showDebugLogs)
{
Logging.Debug($"[{abilityName}] Cooldown started: {cooldownDuration}s");
Logging.Debug($"[{abilityName}] Cooldown started: {cooldownTimer}s");
}
}

View File

@@ -1,4 +1,4 @@
using Core;
using Core;
using UnityEngine;
namespace Minigames.Airplane.Abilities
@@ -23,7 +23,7 @@ namespace Minigames.Airplane.Abilities
/// Create bobbing ability with configuration from settings.
/// </summary>
public BobbingAbility(string name, Sprite icon, float cooldown, Vector2 force)
: base(name, icon, cooldown)
: base(name, icon, cooldown, reusable: true, activeDuration: 0f)
{
bobForce = force;
}
@@ -52,9 +52,8 @@ namespace Minigames.Airplane.Abilities
}
}
// Instant ability - deactivate immediately and start cooldown
// Instant ability - deactivate immediately (base.Deactivate starts cooldown)
base.Deactivate();
StartCooldown();
}
#endregion

View File

@@ -1,12 +1,12 @@
using System.Collections;
using Core;
using Core;
using UnityEngine;
namespace Minigames.Airplane.Abilities
{
/// <summary>
/// Drop Plane Ability: Swipe down to drop straight down.
/// Sustained ability - drops for fixed duration/distance.
/// Drop Plane Ability: Press to drop straight down with strong downward force.
/// Sustained ability - active for up to N seconds, can be interrupted early.
/// Cooldown is proportional to usage time (full duration = N*2 cooldown).
/// Good for precision strikes on targets.
/// Configuration loaded from settings at runtime.
/// </summary>
@@ -15,8 +15,8 @@ namespace Minigames.Airplane.Abilities
#region Configuration
private readonly float dropForce;
private readonly float dropDistance;
private readonly bool zeroHorizontalVelocity;
private readonly float cooldownMultiplier;
#endregion
@@ -25,12 +25,12 @@ namespace Minigames.Airplane.Abilities
/// <summary>
/// Create drop ability with configuration from settings.
/// </summary>
public DropAbility(string name, Sprite icon, float cooldown, float force, float distance, bool zeroHorizontal = true)
: base(name, icon, cooldown)
public DropAbility(string name, Sprite icon, float cooldown, float force, float maxActiveDuration, float cooldownMult, bool zeroHorizontal = true)
: base(name, icon, cooldown, reusable: true, activeDuration: maxActiveDuration)
{
dropForce = force;
dropDistance = distance;
zeroHorizontalVelocity = zeroHorizontal;
cooldownMultiplier = cooldownMult;
}
#endregion
@@ -38,8 +38,6 @@ namespace Minigames.Airplane.Abilities
#region State
private float originalXVelocity;
private Vector3 dropStartPosition;
private Coroutine dropCoroutine;
#endregion
@@ -66,17 +64,11 @@ namespace Minigames.Airplane.Abilities
// Apply strong downward force
rb.AddForce(Vector2.down * dropForce, ForceMode2D.Impulse);
// Track drop distance
dropStartPosition = currentAirplane.transform.position;
// Start monitoring drop distance
dropCoroutine = currentAirplane.StartCoroutine(MonitorDropDistance());
}
if (showDebugLogs)
{
Logging.Debug($"[DropAbility] Activated - Force: {dropForce}, Distance: {dropDistance}");
Logging.Debug($"[DropAbility] Activated - Force: {dropForce}, Max Duration: {maxActiveDuration}s");
}
}
@@ -84,13 +76,6 @@ namespace Minigames.Airplane.Abilities
{
if (!isActive) return;
// Stop monitoring
if (dropCoroutine != null && currentAirplane != null)
{
currentAirplane.StopCoroutine(dropCoroutine);
dropCoroutine = null;
}
// Restore horizontal velocity (optional)
if (currentAirplane != null)
{
@@ -102,36 +87,32 @@ namespace Minigames.Airplane.Abilities
}
}
base.Deactivate();
if (showDebugLogs)
{
Logging.Debug($"[DropAbility] Deactivating after {activeDurationUsed:F2}s usage");
}
// Start cooldown
StartCooldown();
// Base.Deactivate() will call CalculateDynamicCooldown and start cooldown
base.Deactivate();
}
/// <summary>
/// Calculate dynamic cooldown based on usage time.
/// Full duration (maxActiveDuration) = maxActiveDuration * cooldownMultiplier cooldown.
/// Partial usage = proportional cooldown.
/// </summary>
protected override float CalculateDynamicCooldown()
{
// Calculate proportional cooldown: usedTime * multiplier
// Example: 3s max, 2x multiplier -> full use = 6s cooldown, 1.5s use = 3s cooldown
float dynamicCooldown = activeDurationUsed * cooldownMultiplier;
if (showDebugLogs)
{
Logging.Debug("[DropAbility] Deactivated, cooldown started");
}
}
#endregion
#region Drop Monitoring
private IEnumerator MonitorDropDistance()
{
while (isActive && currentAirplane != null)
{
float distanceDropped = Mathf.Abs(dropStartPosition.y - currentAirplane.transform.position.y);
if (distanceDropped >= dropDistance)
{
// Drop distance reached - deactivate
Deactivate();
yield break;
}
yield return null;
Logging.Debug($"[DropAbility] CalculateDynamicCooldown: used={activeDurationUsed:F2}s, multiplier={cooldownMultiplier}, result={dynamicCooldown:F2}s");
}
return dynamicCooldown;
}
#endregion

View File

@@ -13,6 +13,7 @@ namespace Minigames.Airplane.Abilities
private readonly float jetSpeed;
private readonly float jetAngle;
private readonly float cooldownMultiplier;
#endregion
@@ -21,11 +22,12 @@ namespace Minigames.Airplane.Abilities
/// <summary>
/// Create jet ability with configuration from settings.
/// </summary>
public JetAbility(string name, Sprite icon, float cooldown, float speed, float angle)
: base(name, icon, cooldown)
public JetAbility(string name, Sprite icon, float cooldown, float speed, float angle, float maxActiveDuration, float cooldownMult)
: base(name, icon, cooldown, reusable: true, activeDuration: maxActiveDuration)
{
jetSpeed = speed;
jetAngle = angle;
cooldownMultiplier = cooldownMult;
}
#endregion
@@ -87,15 +89,32 @@ namespace Minigames.Airplane.Abilities
currentAirplane.RotateToVelocity = originalRotateToVelocity;
}
base.Deactivate();
if (showDebugLogs)
{
Logging.Debug($"[JetAbility] Deactivating after {activeDurationUsed:F2}s usage");
}
// Start cooldown after deactivation
StartCooldown();
// Base.Deactivate() will call CalculateDynamicCooldown and start cooldown
base.Deactivate();
}
/// <summary>
/// Calculate dynamic cooldown based on usage time.
/// Full duration (maxActiveDuration) = maxActiveDuration * cooldownMultiplier cooldown.
/// Partial usage = proportional cooldown.
/// </summary>
protected override float CalculateDynamicCooldown()
{
// Calculate proportional cooldown: usedTime * multiplier
// Example: 5s max, 2x multiplier -> full use = 10s cooldown, 2.5s use = 5s cooldown
float dynamicCooldown = activeDurationUsed * cooldownMultiplier;
if (showDebugLogs)
{
Logging.Debug("[JetAbility] Deactivated, cooldown started");
Logging.Debug($"[JetAbility] CalculateDynamicCooldown: used={activeDurationUsed:F2}s, multiplier={cooldownMultiplier}, result={dynamicCooldown:F2}s");
}
return dynamicCooldown;
}
#endregion