'use client'; import { useMemo, type ReactNode } from 'react'; import { useManaStore } from '@/lib/game/stores/manaStore'; import { usePrestigeStore } from '@/lib/game/stores/prestigeStore'; import { useUIStore } from '@/lib/game/stores/uiStore'; import { useCombatStore } from '@/lib/game/stores/combatStore'; import { useGameStore } from '@/lib/game/stores/gameStore'; import { computeEffects } from '@/lib/game/effects/upgrade-effects'; import { hasSpecial, SPECIAL_EFFECTS } from '@/lib/game/effects/special-effects'; import { computeMaxMana, computeRegen, computeClickMana, getMeditationBonus, canAffordSpellCost, calcDamage, getFloorElement, getBoonBonuses, getIncursionStrength, } from '@/lib/game/utils'; import { ELEMENTS, GUARDIANS, SPELLS_DEF, } from '@/lib/game/constants'; import type { ElementDef, GuardianDef, SpellDef, GameAction } from '@/lib/game/types'; import type { UnifiedStore, GameContextValue } from './types'; import { GameContext } from './context-create'; function createUnifiedStore( gameStore: ReturnType, manaState: ReturnType, prestigeState: ReturnType, uiState: ReturnType, combatState: ReturnType ): UnifiedStore { return { // From gameStore day: gameStore.day, hour: gameStore.hour, incursionStrength: gameStore.incursionStrength, containmentWards: gameStore.containmentWards, initialized: gameStore.initialized, tick: gameStore.tick, resetGame: gameStore.resetGame, gatherMana: gameStore.gatherMana, startNewLoop: gameStore.startNewLoop, // From manaStore rawMana: manaState.rawMana, meditateTicks: manaState.meditateTicks, totalManaGathered: manaState.totalManaGathered, elements: manaState.elements, setRawMana: manaState.setRawMana, addRawMana: manaState.addRawMana, spendRawMana: manaState.spendRawMana, convertMana: manaState.convertMana, unlockElement: manaState.unlockElement, craftComposite: manaState.craftComposite, // From prestigeStore loopCount: prestigeState.loopCount, insight: prestigeState.insight, totalInsight: prestigeState.totalInsight, loopInsight: prestigeState.loopInsight, prestigeUpgrades: prestigeState.prestigeUpgrades, memorySlots: prestigeState.memorySlots, pactSlots: prestigeState.pactSlots, memories: prestigeState.memories, defeatedGuardians: prestigeState.defeatedGuardians, signedPacts: prestigeState.signedPacts, pactRitualFloor: prestigeState.pactRitualFloor, pactRitualProgress: prestigeState.pactRitualProgress, doPrestige: prestigeState.doPrestige, addMemory: prestigeState.addMemory, removeMemory: prestigeState.removeMemory, clearMemories: prestigeState.clearMemories, startPactRitual: prestigeState.startPactRitual, cancelPactRitual: prestigeState.cancelPactRitual, removePact: prestigeState.removePact, defeatGuardian: prestigeState.defeatGuardian, // From combatStore currentFloor: combatState.currentFloor, floorHP: combatState.floorHP, floorMaxHP: combatState.floorMaxHP, maxFloorReached: combatState.maxFloorReached, activeSpell: combatState.activeSpell, currentAction: combatState.currentAction, castProgress: combatState.castProgress, spells: combatState.spells, setAction: combatState.setAction, setSpell: combatState.setSpell, learnSpell: combatState.learnSpell, advanceFloor: combatState.advanceFloor, // From uiStore log: uiState.logs, paused: uiState.paused, gameOver: uiState.gameOver, victory: uiState.victory, addLog: uiState.addLog, togglePause: uiState.togglePause, setPaused: uiState.setPaused, setGameOver: uiState.setGameOver, }; } export function GameProvider({ children }: { children: ReactNode }) { // Get all individual stores const gameStore = useGameStore(); const manaState = useManaStore(); const prestigeState = usePrestigeStore(); const uiState = useUIStore(); const combatState = useCombatStore(); // Create unified store object for backward compatibility const unifiedStore = useMemo( () => createUnifiedStore(gameStore, manaState, prestigeState, uiState, combatState), [gameStore, manaState, prestigeState, uiState, combatState] ); // Computed effects from upgrades const upgradeEffects = useMemo( () => computeEffects({}, {}), [] ); // Create a minimal state object for compute functions const stateForCompute = useMemo(() => ({ prestigeUpgrades: prestigeState.prestigeUpgrades, signedPacts: prestigeState.signedPacts, rawMana: manaState.rawMana, meditateTicks: manaState.meditateTicks, incursionStrength: gameStore.incursionStrength, }), [prestigeState, manaState, gameStore.incursionStrength]); // Derived stats const maxMana = useMemo( () => computeMaxMana(stateForCompute, upgradeEffects), [stateForCompute, upgradeEffects] ); const baseRegen = useMemo( () => computeRegen(stateForCompute, upgradeEffects), [stateForCompute, upgradeEffects] ); const clickMana = useMemo(() => computeClickMana(stateForCompute), [stateForCompute]); // Floor element from combat store const floorElem = useMemo(() => getFloorElement(combatState.currentFloor), [combatState.currentFloor]); const floorElemDef = ELEMENTS[floorElem]; const isGuardianFloor = !!GUARDIANS[combatState.currentFloor]; const currentGuardian = GUARDIANS[combatState.currentFloor]; const activeSpellDef = SPELLS_DEF[combatState.activeSpell]; const meditationMultiplier = useMemo( () => getMeditationBonus(manaState.meditateTicks, {}, upgradeEffects.meditationEfficiency), [manaState.meditateTicks, upgradeEffects.meditationEfficiency] ); const incursionStrength = useMemo( () => getIncursionStrength(gameStore.day, gameStore.hour), [gameStore.day, gameStore.hour] ); const studySpeedMult = 1; const studyCostMult = 1; // Effective regen calculations const effectiveRegenWithSpecials = baseRegen * (1 - incursionStrength); const manaCascadeBonus = hasSpecial(upgradeEffects, SPECIAL_EFFECTS.MANA_CASCADE) ? Math.floor(maxMana / 100) * 0.1 : 0; const manaWaterfallBonus = hasSpecial(upgradeEffects, SPECIAL_EFFECTS.MANA_WATERFALL) ? Math.floor(maxMana / 100) * 0.25 : 0; const effectiveRegen = (effectiveRegenWithSpecials + manaCascadeBonus + manaWaterfallBonus) * meditationMultiplier; // Has special flags for UI const hasManaWaterfall = hasSpecial(upgradeEffects, SPECIAL_EFFECTS.MANA_WATERFALL); const hasFlowSurge = hasSpecial(upgradeEffects, SPECIAL_EFFECTS.FLOW_SURGE); const hasManaOverflow = hasSpecial(upgradeEffects, SPECIAL_EFFECTS.MANA_OVERFLOW); const hasEternalFlow = hasSpecial(upgradeEffects, SPECIAL_EFFECTS.ETERNAL_FLOW); // Active boons const activeBoons = useMemo( () => getBoonBonuses(prestigeState.signedPacts), [prestigeState.signedPacts] ); // DPS calculation - based on active spell, attack speed, and damage const dps = useMemo(() => { if (!activeSpellDef) return 0; const baseDmg = calcDamage( { signedPacts: prestigeState.signedPacts }, combatState.activeSpell, floorElem ); const dmgWithEffects = baseDmg * upgradeEffects.baseDamageMultiplier + upgradeEffects.baseDamageBonus; const attackSpeed = (1 + 0 * 0.05) * upgradeEffects.attackSpeedMultiplier; const castSpeed = activeSpellDef.castSpeed || 1; return dmgWithEffects * attackSpeed * castSpeed; }, [activeSpellDef, prestigeState.signedPacts, floorElem, upgradeEffects, combatState.activeSpell]); // Helper functions const canCastSpell = (spellId: string): boolean => { const spell = SPELLS_DEF[spellId]; if (!spell) return false; return canAffordSpellCost(spell.cost, manaState.rawMana, manaState.elements); }; const value: GameContextValue = { store: unifiedStore, manaStore: manaState, prestigeStore: prestigeState, uiStore: uiState, combatStore: combatState, upgradeEffects, maxMana, baseRegen, clickMana, floorElem, floorElemDef, isGuardianFloor, currentGuardian, activeSpellDef, meditationMultiplier, incursionStrength, studySpeedMult, studyCostMult, effectiveRegenWithSpecials, manaCascadeBonus, manaWaterfallBonus, effectiveRegen, hasManaWaterfall, hasFlowSurge, hasManaOverflow, hasEternalFlow, dps, activeBoons, canCastSpell, hasSpecial, SPECIAL_EFFECTS, }; return {children}; } GameProvider.displayName = "GameProvider";