'use client'; import { useState, useEffect, useMemo } from 'react'; import { useShallow } from 'zustand/react/shallow'; import { useCombatStore, useManaStore, usePrestigeStore, fmt, computeMaxMana, computeRegen } from '@/lib/game/stores'; import { computeDisciplineEffects } from '@/lib/game/effects/discipline-effects'; import { getUnifiedEffects } from '@/lib/game/effects'; import { useCraftingStore } from '@/lib/game/stores/craftingStore'; import { getGuardianForFloor, isGuardianFloor } from '@/lib/game/data/guardian-encounters'; import { getRoomsForFloor, generateSpireFloorState } from '@/lib/game/utils/spire-utils'; import { SpireHeader } from './SpireHeader'; import { RoomDisplay } from './RoomDisplay'; import { SpireCombatControls } from './SpireCombatControls'; import { SpireActivityLog } from './SpireActivityLog'; import { SpireManaDisplay } from './SpireManaDisplay'; // ─── Derived Stats Hook ────────────────────────────────────────────────────── function useSpireStats(prestigeUpgrades: Record, equippedInstances: Record, equipmentInstances: Record) { const disciplineEffects = computeDisciplineEffects(); const upgradeEffects = getUnifiedEffects({ skillUpgrades: {}, skillTiers: {}, equippedInstances, equipmentInstances, }); const maxMana = computeMaxMana({ skills: {}, prestigeUpgrades, skillUpgrades: {}, skillTiers: {}, }, upgradeEffects, disciplineEffects); const baseRegen = computeRegen({ skills: {}, prestigeUpgrades, skillUpgrades: {}, skillTiers: {}, attunements: {}, }, upgradeEffects, disciplineEffects); return { maxMana, baseRegen }; } // ─── Main Component ─────────────────────────────────────────────────────────── export function SpireCombatPage() { const [mounted, setMounted] = useState(false); const [roomsCleared, setRoomsCleared] = useState(0); const { currentFloor, floorHP, floorMaxHP, castProgress, isDescending, currentRoom, activityLog, setCurrentRoom, setFloorHP, setClearedFloor, climbDownFloor, exitSpireMode, startClimbUp, startClimbDown, addActivityLog, setAction, } = useCombatStore(useShallow((s) => ({ currentFloor: s.currentFloor, floorHP: s.floorHP, floorMaxHP: s.floorMaxHP, castProgress: s.castProgress, isDescending: s.isDescending, currentRoom: s.currentRoom, activityLog: s.activityLog, setCurrentRoom: s.setCurrentRoom, setFloorHP: s.setFloorHP, setClearedFloor: s.setClearedFloor, climbDownFloor: s.climbDownFloor, exitSpireMode: s.exitSpireMode, startClimbUp: s.startClimbUp, startClimbDown: s.startClimbDown, addActivityLog: s.addActivityLog, setAction: s.setAction, }))); const { rawMana, elements } = useManaStore(useShallow((s) => ({ rawMana: s.rawMana, elements: s.elements, }))); const { prestigeUpgrades, insight } = usePrestigeStore(useShallow((s) => ({ prestigeUpgrades: s.prestigeUpgrades, insight: s.insight, }))); const equippedInstances = useCraftingStore((s) => s.equippedInstances); const equipmentInstances = useCraftingStore((s) => s.equipmentInstances); const { maxMana, baseRegen } = useSpireStats(prestigeUpgrades, equippedInstances, equipmentInstances); const totalRooms = useMemo(() => getRoomsForFloor(currentFloor), [currentFloor]); useEffect(() => { // eslint-disable-next-line react-hooks/set-state-in-effect setMounted(true); setRoomsCleared(0); const newRoom = generateSpireFloorState(currentFloor, 0, totalRooms); setCurrentRoom(newRoom); setAction('climb'); }, [currentFloor, totalRooms, setCurrentRoom, setAction]); const _handleRoomCleared = () => { const nextRoomIndex = roomsCleared + 1; if (nextRoomIndex >= totalRooms) { const wasGuardian = isGuardianFloor(currentFloor); setClearedFloor(currentFloor, true); if (wasGuardian) { const guardian = getGuardianForFloor(currentFloor); if (guardian) { addActivityLog('enemy_defeated', `⚔️ ${guardian.name} defeated!`, { enemyName: guardian.name, floor: currentFloor, }); } } addActivityLog('floor_cleared', `🏰 Floor ${currentFloor} cleared!`, { floor: currentFloor, }); const newFloor = currentFloor + 1; const newTotalRooms = getRoomsForFloor(newFloor); const newRoom = generateSpireFloorState(newFloor, 0, newTotalRooms); setCurrentRoom(newRoom); setFloorHP(floorMaxHP); setClearedFloor(currentFloor, true); setRoomsCleared(0); } else { const newRoom = generateSpireFloorState(currentFloor, nextRoomIndex, totalRooms); setCurrentRoom(newRoom); setRoomsCleared(nextRoomIndex); } }; const handleClimbUp = () => { startClimbUp(); addActivityLog('floor_transition', `⬆️ Climbing to floor ${currentFloor + 1}...`); }; const handleClimbDown = () => { if (currentFloor <= 1) return; startClimbDown(); climbDownFloor(); setRoomsCleared(0); addActivityLog('floor_transition', `⬇️ Descending to floor ${currentFloor - 1}...`); }; const handleExitSpire = () => { exitSpireMode(); addActivityLog('floor_transition', '🚪 Exited the Spire.'); }; if (!mounted) { return (
Loading spire...
); } return (

🏔️ SPIRE

Floor {currentFloor} · Insight: {fmt(insight)}
); }