using Core; using UnityEngine; namespace Minigames.Airplane.Abilities { /// /// 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. /// public class DropAbility : BaseAirplaneAbility { #region Configuration private readonly float dropForce; private readonly bool zeroHorizontalVelocity; private readonly float cooldownMultiplier; #endregion #region Constructor /// /// Create drop ability with configuration from settings. /// 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; zeroHorizontalVelocity = zeroHorizontal; cooldownMultiplier = cooldownMult; } #endregion #region State private float originalXVelocity; #endregion #region Override Methods public override void Execute() { if (!ValidateAirplane()) return; if (!CanActivate) return; StartActivation(); var rb = currentAirplane.GetComponent(); if (rb != null) { // Store original velocity originalXVelocity = rb.linearVelocity.x; // Zero horizontal velocity if configured if (zeroHorizontalVelocity) { rb.linearVelocity = new Vector2(0f, rb.linearVelocity.y); } // Apply strong downward force rb.AddForce(Vector2.down * dropForce, ForceMode2D.Impulse); } if (showDebugLogs) { Logging.Debug($"[DropAbility] Activated - Force: {dropForce}, Max Duration: {maxActiveDuration}s"); } } public override void Deactivate() { if (!isActive) return; // Restore horizontal velocity (optional) if (currentAirplane != null) { var rb = currentAirplane.GetComponent(); if (rb != null && zeroHorizontalVelocity) { Vector2 currentVel = rb.linearVelocity; rb.linearVelocity = new Vector2(originalXVelocity * 0.5f, currentVel.y); // Resume at reduced speed } } if (showDebugLogs) { Logging.Debug($"[DropAbility] Deactivating after {activeDurationUsed:F2}s usage"); } // Base.Deactivate() will call CalculateDynamicCooldown and start cooldown base.Deactivate(); } /// /// Calculate dynamic cooldown based on usage time. /// Full duration (maxActiveDuration) = maxActiveDuration * cooldownMultiplier cooldown. /// Partial usage = proportional cooldown. /// 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] CalculateDynamicCooldown: used={activeDurationUsed:F2}s, multiplier={cooldownMultiplier}, result={dynamicCooldown:F2}s"); } return dynamicCooldown; } #endregion } }