// ─── Dynamic Computations ────────────────────────────────────────────────── // Dynamic computation functions that depend on special effects import type { ComputedEffects } from './upgrade-effects.types'; import { SPECIAL_EFFECTS, hasSpecial } from './special-effects'; /** * Compute regen with special effects that depend on dynamic values */ export function computeDynamicRegen( effects: ComputedEffects, baseRegen: number, maxMana: number, currentMana: number, incursionStrength: number ): number { let regen = baseRegen; // Mana Cascade: +0.1 regen per 100 max mana if (hasSpecial(effects, SPECIAL_EFFECTS.MANA_CASCADE)) { regen += Math.floor(maxMana / 100) * 0.1; } // Mana Waterfall: +0.25 regen per 100 max mana (upgraded cascade) if (hasSpecial(effects, SPECIAL_EFFECTS.MANA_WATERFALL)) { regen += Math.floor(maxMana / 100) * 0.25; } // Mana Torrent: +50% regen when above 75% mana if (hasSpecial(effects, SPECIAL_EFFECTS.MANA_TORRENT) && currentMana > maxMana * 0.75) { regen *= 1.5; } // Desperate Wells / Despair Wells: +50% regen when below 25% mana if ((hasSpecial(effects, SPECIAL_EFFECTS.DESPERATE_WELLS) || hasSpecial(effects, SPECIAL_EFFECTS.DESPAIR_WELLS)) && currentMana < maxMana * 0.25) { regen *= 1.5; } // Panic Reserve: +100% regen when below 10% mana if (hasSpecial(effects, SPECIAL_EFFECTS.PANIC_RESERVE) && currentMana < maxMana * 0.1) { regen *= 2.0; } // Deep Reserve: +0.5 regen per 100 max mana if (hasSpecial(effects, SPECIAL_EFFECTS.DEEP_RESERVE)) { regen += Math.floor(maxMana / 100) * 0.5; } // Mana Core: 0.5% of max mana added as regen if (hasSpecial(effects, SPECIAL_EFFECTS.MANA_CORE)) { regen += maxMana * 0.005; } // Mana Tide: Regen pulses ±50% (sinusoidal based on time) if (hasSpecial(effects, SPECIAL_EFFECTS.MANA_TIDE)) { regen *= (1.0 + 0.5 * Math.sin(Date.now() / 10000)); } // Eternal Flow: Regen immune to ALL penalties if (hasSpecial(effects, SPECIAL_EFFECTS.ETERNAL_FLOW)) { return regen * effects.regenMultiplier; } // Steady Stream: Regen immune to incursion (skip incursion penalty only) if (hasSpecial(effects, SPECIAL_EFFECTS.STEADY_STREAM)) { // incursion penalty is skipped, but regenMultiplier still applies below } else { // Apply incursion penalty regen *= (1 - incursionStrength); } return regen * effects.regenMultiplier; } /** * Compute click mana with special effects */ export function computeDynamicClickMana( effects: ComputedEffects, baseClickMana: number ): number { let clickMana = baseClickMana; // Mana Echo: 10% chance to gain double mana from clicks // Note: The chance is handled in the click handler, this just returns the base // The click handler should check hasSpecial and apply the 10% chance // Mana Genesis: Generate 1% of max mana per hour passively // This is handled in the game loop (store.ts), not here // Mana Heart: +10% max mana per loop (permanent) // This is applied during loop reset in store.ts return Math.floor((clickMana + effects.clickManaBonus) * effects.clickManaMultiplier); } /** * Compute damage with special effects */ export function computeDynamicDamage( effects: ComputedEffects, baseDamage: number, floorHPPct: number, currentMana: number, maxMana: number ): number { let damage = baseDamage * effects.baseDamageMultiplier; // Overpower: +50% damage when mana above 80% if (hasSpecial(effects, SPECIAL_EFFECTS.OVERPOWER) && currentMana >= maxMana * 0.8) { damage *= 1.5; } // Berserker: +50% damage when below 50% mana if (hasSpecial(effects, SPECIAL_EFFECTS.BERSERKER) && currentMana < maxMana * 0.5) { damage *= 1.5; } // Combo Master: Every 5th attack deals 3x damage // Note: The hit counter is tracked in game state, this just returns the multiplier // The combat handler should check hasSpecial and the hit count return damage + effects.baseDamageBonus; }