// ─── Mana & Regen Utilities ────────────────────────────────────────────────── import type { AttunementState } from '../types'; import type { ComputedEffects } from '../effects/upgrade-effects.types'; import { HOURS_PER_TICK } from '../constants'; import { getTotalAttunementRegen } from '../data/attunements'; export interface DisciplineBonuses { bonuses: Record; multipliers: Record; } // ─── Mana Params ──────────────────────────────────────────────────────────── export interface ManaComputeParams { prestigeUpgrades?: Record; } export interface RegenComputeParams extends ManaComputeParams { attunements: Record; } export interface EffectiveRegenParams extends RegenComputeParams { rawMana: number; incursionStrength: number; } // ─── Max Mana ──────────────────────────────────────────────────────────────── export function computeMaxMana( state: Partial, effects?: ComputedEffects, discipline?: DisciplineBonuses, ): number { const pu = state.prestigeUpgrades || {}; const base = 100 + (pu.manaWell || 0) * 500 + (discipline?.bonuses?.maxManaBonus || 0); if (effects) { return Math.floor((base + effects.maxManaBonus) * effects.maxManaMultiplier); } return base; } // ─── Regen ──────────────────────────────────────────────────────────────────── export function computeRegen( state: Pick, effects?: ComputedEffects, discipline?: DisciplineBonuses, ): number { const pu = state.prestigeUpgrades || {}; const temporalBonus = 1 + (pu.temporalEcho || 0) * 0.1; const base = 2 + ((pu || {}).manaFlow || 0) * 0.5; let regen = base * temporalBonus; // Add attunement raw mana regen const attunementRegen = getTotalAttunementRegen(state.attunements || {}); regen += attunementRegen; // Apply discipline regen bonus if (discipline?.bonuses?.regenBonus) { regen += discipline.bonuses.regenBonus; } // Apply upgrade effects if provided if (effects) { regen = (regen + effects.regenBonus + effects.permanentRegenBonus) * effects.regenMultiplier; } return regen; } // ─── Effective Regen for Display ────────────────────────────────────────────── export function computeEffectiveRegenForDisplay( state: Pick, effects?: ComputedEffects, discipline?: DisciplineBonuses, ): { rawRegen: number; conversionDrain: number; effectiveRegen: number } { const rawRegen = computeRegen(state, effects, discipline); return { rawRegen, conversionDrain: 0, effectiveRegen: rawRegen }; } // ─── Effective Regen (dynamic) ──────────────────────────────────────────────── export function computeEffectiveRegen( state: Pick & { rawMana: number; incursionStrength: number }, effects?: ComputedEffects, discipline?: DisciplineBonuses, ): number { let regen = computeRegen(state, effects, discipline); const incursionStrength = state.incursionStrength || 0; regen *= (1 - incursionStrength); return regen; } // ─── Click Mana ─────────────────────────────────────────────────────────────── export function computeClickMana( discipline?: DisciplineBonuses, ): number { const discClickBonus = discipline?.bonuses?.clickManaBonus || 0; return 1 + discClickBonus; } // ─── Meditation Bonus ───────────────────────────────────────────────────────── export function getMeditationBonus( meditateTicks: number, meditationEfficiency: number = 1, disciplineMeditationCap: number = 0, ): number { const hours = meditateTicks * HOURS_PER_TICK; // Continuous ramp: 1 + (hours / 8) * 4, capped at 2.5 + disciplineMeditationCap const maxMultiplier = 2.5 + disciplineMeditationCap; const bonus = Math.min(1 + (hours / 8) * 4, maxMultiplier); // Apply meditation efficiency from upgrades return bonus * meditationEfficiency; }