'use client'; import { useEffect, useState, lazy, Suspense } from 'react'; import { useShallow } from 'zustand/react/shallow'; // Import from new modular stores import { useGameStore, useUIStore, useManaStore, useCombatStore, usePrestigeStore, useCraftingStore, useDisciplineStore, fmt, computeMaxMana, computeRegen, computeClickMana, getMeditationBonus, getIncursionStrength, } from '@/lib/game/stores'; import { computeDisciplineEffects } from '@/lib/game/effects/discipline-effects'; import { useGameLoop } from '@/lib/game/stores/gameHooks'; import { getUnifiedEffects } from '@/lib/game/effects'; import { SPELLS_DEF } from '@/lib/game/constants'; import { TimeDisplay } from '@/components/game'; import { hasSpecial, SPECIAL_EFFECTS } from '@/lib/game/effects'; import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; import { Badge } from '@/components/ui/badge'; import { ScrollArea } from '@/components/ui/scroll-area'; import { TooltipProvider } from '@/components/ui/tooltip'; import { ErrorBoundary } from '@/components/ErrorBoundary'; import { DebugName } from '@/components/game/debug/debug-context'; // Import extracted components import { GameOverScreen } from './components/GameOverScreen'; import { LeftPanel } from './components/LeftPanel'; // Lazy load tab components const DisciplinesTab = lazy(() => import('@/components/game/tabs').then(module => ({ default: module.DisciplinesTab }))); const SpellsTab = lazy(() => import('@/components/game/tabs').then(module => ({ default: module.SpellsTab }))); const StatsTab = lazy(() => import('@/components/game/tabs').then(module => ({ default: module.StatsTab }))); const DebugTab = lazy(() => import('@/components/game/tabs').then(module => ({ default: module.DebugTab }))); const AchievementsTab = lazy(() => import('@/components/game/tabs').then(module => ({ default: module.AchievementsTab }))); const AttunementsTab = lazy(() => import('@/components/game/tabs').then(module => ({ default: module.AttunementsTab }))); const PrestigeTab = lazy(() => import('@/components/game/tabs').then(module => ({ default: module.PrestigeTab }))); const EquipmentTab = lazy(() => import('@/components/game/tabs').then(module => ({ default: module.EquipmentTab }))); const GolemancyTab = lazy(() => import('@/components/game/tabs').then(module => ({ default: module.GolemancyTab }))); const GuardianPactsTab = lazy(() => import('@/components/game/tabs').then(module => ({ default: module.GuardianPactsTab }))); const SpireSummaryTab = lazy(() => import('@/components/game/tabs').then(module => ({ default: module.SpireSummaryTab }))); const CraftingTab = lazy(() => import('@/components/game/tabs').then(module => ({ default: module.CraftingTab }))); const TabLoadingFallback = () =>
Loading...
; // ============================================================================ // Grimoire Tab Component // ============================================================================ function GrimoireTab() { const [grimoireSpells, setGrimoireSpells] = useState(() => { if (typeof window !== 'undefined' && SPELLS_DEF) { return Object.values(SPELLS_DEF).filter((s: any) => s.grimoire); } return []; }); const loaded = typeof window !== 'undefined'; if (!loaded) { return
Loading grimoire...
; } if (grimoireSpells.length === 0) { return (
No grimoire spells available yet. Defeat guardians to unlock spells.
); } const availablePages = Math.ceil(grimoireSpells.length / 12); return (

A vast tome of arcane knowledge. Study carefully — each spell costs insight to transcribe into your repertoire.

Available pages: {availablePages}. Spells in grimoire: {grimoireSpells.length}.

{grimoireSpells.map((spell: any) => (
{spell.name} {spell.element}

{spell.desc}

Cost: {spell.cost.amount} { spell.cost.type === 'element' ? spell.cost.element : 'raw mana' }
Power: {spell.power}
{spell.effect &&
Effect: {spell.effect}
}
))}
); } // ============================================================================ // Main Game Component // ============================================================================ export default function ManaLoopGame() { const [selectedManaType, setSelectedManaType] = useState(''); const [activeTab, setActiveTab] = useState('spells'); // ALL hooks must be called before any conditional returns useGameLoop(); // Use useShallow to combine multi-field subscriptions and reduce re-renders const { day, hour, initGame } = useGameStore(useShallow(s => ({ day: s.day, hour: s.hour, initGame: s.initGame }))); const { prestigeUpgrades, insight, loopInsight } = usePrestigeStore(useShallow(s => ({ prestigeUpgrades: s.prestigeUpgrades, insight: s.insight, loopInsight: s.loopInsight }))); const { rawMana, meditateTicks } = useManaStore(useShallow(s => ({ rawMana: s.rawMana, meditateTicks: s.meditateTicks }))); const spireMode = useCombatStore((s) => s.spireMode); const gameOver = useUIStore((s) => s.gameOver); // Get equipment state from crafting store const equippedInstances = useCraftingStore((s) => s.equippedInstances); const equipmentInstances = useCraftingStore((s) => s.equipmentInstances); // Derived state const upgradeEffects = getUnifiedEffects({ skillUpgrades: {}, skillTiers: {}, equippedInstances, equipmentInstances }); // Compute discipline bonuses from active disciplines const disciplineStoreState = useDisciplineStore(); const disciplineEffects = computeDisciplineEffects(disciplineStoreState as any); const maxMana = computeMaxMana({ skills: {}, prestigeUpgrades, skillUpgrades: {}, skillTiers: {} }, upgradeEffects as any, disciplineEffects); const baseRegen = computeRegen({ skills: {}, prestigeUpgrades, skillUpgrades: {}, skillTiers: {}, attunements: {}, }, upgradeEffects as any, disciplineEffects); const clickMana = computeClickMana({ skills: {}, }, disciplineEffects); const meditationMultiplier = getMeditationBonus(meditateTicks, {}, (upgradeEffects as any).meditationEfficiency); const incursionStrength = getIncursionStrength(day, hour); // Effective regen with incursion penalty const effectiveRegenWithSpecials = baseRegen * (1 - incursionStrength); // Mana Cascade bonus const manaCascadeBonus = hasSpecial(upgradeEffects as any, SPECIAL_EFFECTS.MANA_CASCADE) ? Math.floor(maxMana / 100) * 0.1 : 0; // Mana Waterfall bonus const manaWaterfallBonus = hasSpecial(upgradeEffects as any, SPECIAL_EFFECTS.MANA_WATERFALL) ? Math.floor(maxMana / 100) * 0.25 : 0; // Effective regen const effectiveRegen = (effectiveRegenWithSpecials + manaCascadeBonus + manaWaterfallBonus) * meditationMultiplier; // Initialize game on mount useEffect(() => { initGame(); }, [initGame]); const [mounted, setMounted] = useState(false); useEffect(() => { setMounted(true); }, []); // eslint-disable-line react-hooks/set-state-in-effect // React to spireMode changes from combat store useEffect(() => { if (spireMode) { setActiveTab('spells'); // eslint-disable-line react-hooks/set-state-in-effect } }, [spireMode]); // Conditional returns AFTER all hooks if (gameOver) { return ; } if (!mounted) return
Loading...
; return (
{/* Header */}

MANA LOOP

{/* Main Content */}
🔮 Spells 📊 Stats 📚 Disciplines 📖 Grimoire 🐛 Debug ⚗️ Attunements 🏆 Achievements ✨ Prestige ⚔️ Equipment 🗿 Golemancy 📜 Pacts 🏔️ Spire ⚒️ Crafting spells tab failed to load.
}> }> stats tab failed to load.
}> }>
disciplines tab failed to load.}> }> debug tab failed to load.}> }> attunements tab failed to load.}> }> achievements tab failed to load.}> }> prestige tab failed to load.}> }> equipment tab failed to load.}> }> golemancy tab failed to load.}> }> pacts tab failed to load.}> }> spire tab failed to load.}> }> crafting tab failed to load.}> }> ); }