'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 AchievementsTab = lazy(() => import('@/components/game/tabs').then(module => ({ default: module.AchievementsTab })));
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 */}
{/* Main Content */}
🔮 Spells
📊 Stats
📚 Disciplines
📖 Grimoire
🏆 Achievements
spells tab failed to load.
}>
}>
stats tab failed to load. }>
}>
disciplines tab failed to load.}>
}>
achievements tab failed to load.}>
}>
);
}