'use client'; import { useEffect, useState } from 'react'; import { useGameStore, useGameLoop, fmt, fmtDec, getFloorElement, computeMaxMana, computeRegen, computeClickMana, getMeditationBonus, getIncursionStrength, canAffordSpellCost } from '@/lib/game/store'; import { getActiveEquipmentSpells, getTotalDPS } from '@/lib/game/computed-stats'; import { getDamageBreakdown } from '@/lib/game/computed-stats'; import { ELEMENTS, GUARDIANS, SPELLS_DEF, PRESTIGE_DEF, getStudySpeedMultiplier, getStudyCostMultiplier } from '@/lib/game/constants'; import { SKILL_EVOLUTION_PATHS, getTierMultiplier } from '@/lib/game/skill-evolution'; import { getUnifiedEffects, hasSpecial, SPECIAL_EFFECTS } from '@/lib/game/effects'; import { formatHour } from '@/lib/game/formatting'; import { Button } from '@/components/ui/button'; import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Badge } from '@/components/ui/badge'; import { RotateCcw } from 'lucide-react'; import { CraftingTab, SpireTab, SpellsTab, LabTab, SkillsTab, StatsTab, EquipmentTab, AttunementsTab, DebugTab, LootTab, AchievementsTab, GolemancyTab } from '@/components/game/tabs'; import { ActionButtons, CalendarDisplay, ManaDisplay, TimeDisplay } from '@/components/game'; // Loot and Achievements moved to separate tabs import { DebugName } from '@/lib/game/debug-context'; export default function ManaLoopGame() { const [activeTab, setActiveTab] = useState('spire'); const [isGathering, setIsGathering] = useState(false); // Game store const store = useGameStore(); const gameLoop = useGameLoop(); // Computed effects from upgrades and equipment const upgradeEffects = getUnifiedEffects(store); // Derived stats const maxMana = computeMaxMana(store, upgradeEffects); const baseRegen = computeRegen(store, upgradeEffects); const clickMana = computeClickMana(store); const floorElem = getFloorElement(store.currentFloor); const floorElemDef = ELEMENTS[floorElem]; const isGuardianFloor = !!GUARDIANS[store.currentFloor]; const currentGuardian = GUARDIANS[store.currentFloor]; const meditationMultiplier = getMeditationBonus(store.meditateTicks, store.skills, upgradeEffects.meditationEfficiency); const incursionStrength = getIncursionStrength(store.day, store.hour); const studySpeedMult = getStudySpeedMultiplier(store.skills); const studyCostMult = getStudyCostMultiplier(store.skills); // Effective regen with incursion penalty const effectiveRegenWithSpecials = baseRegen * (1 - incursionStrength); // Mana Cascade bonus const manaCascadeBonus = hasSpecial(upgradeEffects, SPECIAL_EFFECTS.MANA_CASCADE) ? Math.floor(maxMana / 100) * 0.1 : 0; // Effective regen const effectiveRegen = (effectiveRegenWithSpecials + manaCascadeBonus) * meditationMultiplier; // Get all active spells from equipment const activeEquipmentSpells = getActiveEquipmentSpells(store.equippedInstances, store.equipmentInstances); // Compute total DPS const totalDPS = getTotalDPS(store, upgradeEffects, floorElem); // Auto-gather while holding useEffect(() => { if (!isGathering) return; let lastGatherTime = 0; const minGatherInterval = 100; let animationFrameId: number; const gatherLoop = (timestamp: number) => { if (timestamp - lastGatherTime >= minGatherInterval) { store.gatherMana(); lastGatherTime = timestamp; } animationFrameId = requestAnimationFrame(gatherLoop); }; animationFrameId = requestAnimationFrame(gatherLoop); return () => cancelAnimationFrame(animationFrameId); }, [isGathering, store]); // Handle gather button events const handleGatherStart = () => { setIsGathering(true); store.gatherMana(); }; const handleGatherEnd = () => { setIsGathering(false); }; // Start game loop useEffect(() => { const cleanup = gameLoop.start(); return cleanup; }, [gameLoop]); // Check if spell can be cast const canCastSpell = (spellId: string): boolean => { const spell = SPELLS_DEF[spellId]; if (!spell) return false; return canAffordSpellCost(spell.cost, store.rawMana, store.elements); }; // Game Over Screen if (store.gameOver) { return (
{store.victory ? 'The Awakened One falls! Your power echoes through eternity.' : 'The time loop resets... but you remember.'}