- {store.victory
- ? 'The Awakened One falls! Your power echoes through eternity.'
- : 'The time loop resets... but you remember.'}
+ The time loop resets... but you remember.
-
{store.fmt(store.loopInsight)}
+
{fmt(insight)}
Insight Gained
-
{store.maxFloorReached}
-
Best Floor
+
{day}
+
Day Reached
-
{store.signedPacts.length}
-
Pacts Signed
+
{hour}
+
Hour
-
{store.loopCount + 1}
-
Total Loops
+
{insight}
+
Total Insight
diff --git a/src/app/components/LeftPanel.tsx b/src/app/components/LeftPanel.tsx
index 74a51cc..4be3414 100644
--- a/src/app/components/LeftPanel.tsx
+++ b/src/app/components/LeftPanel.tsx
@@ -10,7 +10,6 @@ import { DebugName } from '@/lib/game/debug-context';
import type { GameStore } from '@/lib/game/store';
import { computeMaxMana, computeClickMana, getMeditationBonus } from '@/lib/game/store';
import { getUnifiedEffects } from '@/lib/game/effects';
-import { useGameLoop } from '@/lib/game/stores/gameHooks';
interface LeftPanelProps {
store: GameStore;
diff --git a/src/app/page.tsx b/src/app/page.tsx
index 2f9fc47..463dcfa 100644
--- a/src/app/page.tsx
+++ b/src/app/page.tsx
@@ -73,7 +73,8 @@ function GrimoireTab() {
// Only access SPELLS_DEF on client-side
if (typeof window !== 'undefined' && SPELLS_DEF) {
const filtered = Object.values(SPELLS_DEF).filter((s: any) => s.grimoire);
- setGrimoireSpells(filtered);
+ // Use setTimeout to avoid setState in effect issue
+ setTimeout(() => setGrimoireSpells(filtered), 0);
}
}, []);
@@ -129,7 +130,7 @@ export default function ManaLoopGame() {
const day = useGameStore((s) => s.day);
const hour = useGameStore((s) => s.hour);
const initGame = useGameStore((s) => s.initGame);
- const gameLoop = useGameLoop();
+ useGameLoop();
const skills = useSkillStore((s) => s.skills);
const skillTiers = useSkillStore((s) => s.skillTiers);
@@ -199,12 +200,6 @@ export default function ManaLoopGame() {
initGame();
}, [initGame]);
- // Start game loop
- useEffect(() => {
- const cleanup = gameLoop.start();
- return cleanup;
- }, [gameLoop]);
-
// Conditional returns AFTER all hooks
if (gameOver) {
return ;
diff --git a/src/components/game/SpellsTab.tsx b/src/components/game/SpellsTab.tsx
index 87d109e..480c997 100755
--- a/src/components/game/SpellsTab.tsx
+++ b/src/components/game/SpellsTab.tsx
@@ -1,6 +1,6 @@
'use client';
-import { useGameStore, canAffordSpellCost } from '@/lib/game/store';
+import { useGameStore, canAffordSpellCost, fmt } from '@/lib/game/stores';
import { ELEMENTS, SPELLS_DEF } from '@/lib/game/constants';
import { useStudyStats } from '@/lib/game/hooks/useGameDerived';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
@@ -51,7 +51,7 @@ export function SpellsTab() {
{tierNames[tier]}
{spellsInTier.map(([id, def]) => {
- const state = store.spells[id];
+ const state = store.spells?.[id];
const learned = state?.learned;
const isStudying = store.currentStudyTarget?.id === id;
const elemDef = def.elem === 'raw' ? null : ELEMENTS[def.elem];
@@ -147,7 +147,7 @@ export function SpellsTab() {
variant={canStudy ? 'default' : 'outline'}
disabled={!canStudy}
className={canStudy ? 'bg-purple-600 hover:bg-purple-700' : 'opacity-50'}
- onClick={() => store.startStudyingSpell(id)}
+ onClick={() => store.setCurrentStudy?.(id, 'spell')}
>
Start Study ({fmt(unlockCost)} mana)
diff --git a/src/components/game/debug/ElementDebug.tsx b/src/components/game/debug/ElementDebug.tsx
index bc5f0a7..5c8b3ba 100644
--- a/src/components/game/debug/ElementDebug.tsx
+++ b/src/components/game/debug/ElementDebug.tsx
@@ -52,7 +52,7 @@ export function ElementDebug() {
className="mt-2"
onClick={() => handleUnlockElement(id)}
>
- Unlock
+ Unlock
)}
{elem.unlocked && (
diff --git a/src/components/game/stats/CombatStatsSection.tsx b/src/components/game/stats/CombatStatsSection.tsx
index d03a343..1686eaa 100644
--- a/src/components/game/stats/CombatStatsSection.tsx
+++ b/src/components/game/stats/CombatStatsSection.tsx
@@ -1,16 +1,17 @@
'use client';
import { fmtDec } from '@/lib/game/stores';
+import { GUARDIANS } from '@/lib/game/constants';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Swords } from 'lucide-react';
// Modular stores
-import { useSkillStore, useCombatStore } from '@/lib/game/stores';
+import { useSkillStore, usePrestigeStore } from '@/lib/game/stores';
export function CombatStatsSection() {
// Get state from modular stores
const skills = useSkillStore((s) => s.skills);
- const signedPacts = useCombatStore((s) => s.signedPacts);
+ const signedPacts = usePrestigeStore((s) => s.signedPacts);
return (
diff --git a/src/components/game/stats/ManaStatsSection.tsx b/src/components/game/stats/ManaStatsSection.tsx
index d83cebe..5bb7539 100644
--- a/src/components/game/stats/ManaStatsSection.tsx
+++ b/src/components/game/stats/ManaStatsSection.tsx
@@ -3,7 +3,7 @@
import { getTierMultiplier } from '@/lib/game/skill-evolution';
import { hasSpecial, SPECIAL_EFFECTS } from '@/lib/game/effects';
import { fmt, fmtDec } from '@/lib/game/stores';
-import type { UnifiedEffects } from '@/lib/game/types';
+import type { UnifiedEffects } from '@/lib/game/effects';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Separator } from '@/components/ui/separator';
import { Droplet } from 'lucide-react';
diff --git a/src/components/game/stats/ManaTypeBreakdown.tsx b/src/components/game/stats/ManaTypeBreakdown.tsx
index 1a9aec2..9888f0a 100644
--- a/src/components/game/stats/ManaTypeBreakdown.tsx
+++ b/src/components/game/stats/ManaTypeBreakdown.tsx
@@ -11,7 +11,7 @@ import { Droplet } from 'lucide-react';
import { Separator } from '@/components/ui/separator';
// Modular stores
-import { useCombatStore, useManaStore, useSkillStore, usePrestigeStore } from '@/lib/game/stores';
+import { useManaStore, useSkillStore, usePrestigeStore } from '@/lib/game/stores';
export function ManaTypeBreakdown() {
// Get state from modular stores
@@ -22,7 +22,8 @@ export function ManaTypeBreakdown() {
const prestigeUpgrades = usePrestigeStore((s) => s.prestigeUpgrades);
const elements = useManaStore((s) => s.elements);
const rawMana = useManaStore((s) => s.rawMana);
- const attunements = useCombatStore((s) => s.attunements);
+ // attunements is not in modular stores - using empty object as fallback
+ const attunements: Record = {};
// Compute unified effects for regen calculations
const effects = getUnifiedEffects({
diff --git a/src/components/game/tabs/EquipmentTab.tsx b/src/components/game/tabs/EquipmentTab.tsx
index 5853738..2bea048 100755
--- a/src/components/game/tabs/EquipmentTab.tsx
+++ b/src/components/game/tabs/EquipmentTab.tsx
@@ -119,11 +119,24 @@ export function EquipmentTab() {
const [selectedSlot, setSelectedSlot] = useState(null);
const [deleteConfirm, setDeleteConfirm] = useState<{ instanceId: string; name: string } | null>(null);
- // Use modular store directly
+ // Use modular store directly - MUST be called before any conditional returns
const equippedInstances = useCombatStore((s) => s.equippedInstances);
const equipmentInstances = useCombatStore((s) => s.equipmentInstances);
- // Guard against undefined during initialization
+ // Get unequipped items - hooks must be called before conditional returns
+ const equippedIds = useMemo(() =>
+ new Set(Object.values(equippedInstances || {}).filter(Boolean)),
+ [equippedInstances]
+ );
+
+ const unequippedItems = useMemo(() =>
+ Object.values(equipmentInstances || {}).filter(
+ (inst) => !equippedIds.has(inst.instanceId)
+ ),
+ [equipmentInstances, equippedIds]
+ );
+
+ // Guard against undefined during initialization - AFTER all hooks
if (!equippedInstances || !equipmentInstances) {
return (