'use client'; import { useMemo } from 'react'; import { Button } from '@/components/ui/button'; import { Card, CardContent } from '@/components/ui/card'; import { Mountain } from 'lucide-react'; import type { ActivityLogEntry } from '@/lib/game/types'; import { ELEMENTS, GUARDIANS, SPELLS_DEF, SKILLS_DEF } from '@/lib/game/constants'; import { calcDamage } from '@/lib/game/stores'; import { getEnemyName } from '@/lib/game/store-modules/enemy-utils'; import { getActiveEquipmentSpells, getTotalDPS } from '@/lib/game/computed-stats'; import { getUnifiedEffects } from '@/lib/game/effects'; import { formatSpellCost, getSpellCostColor } from '@/lib/game/formatting'; import { canAffordSpellCost, getFloorElement } from '@/lib/game/stores'; import { useGameStore, useManaStore, useSkillStore, useCombatStore, usePrestigeStore } from '@/lib/game/stores'; import { GOLEMS_DEF, getGolemDamage, getGolemAttackSpeed } from '@/lib/game/data/golems'; // Extracted components import { SpireHeader } from './SpireHeader'; import { GuardianPanel } from './GuardianPanel'; import { RoomDisplay } from './RoomDisplay'; import { FloorControls } from './FloorControls'; import { CombatStatsPanel } from './CombatStatsPanel'; import { ActivityLog } from './ActivityLog'; // Room type configurations const ROOM_TYPE_CONFIG: Record = { combat: { label: 'Combat', icon: '⚔️', color: '#EF4444' }, swarm: { label: 'Swarm', icon: '🐝', color: '#F59E0B' }, speed: { label: 'Speed', icon: '💨', color: '#3B82F6' }, guardian: { label: 'Guardian', icon: '🛡️', color: '#EF4444' }, puzzle: { label: 'Puzzle', icon: '🧩', color: '#8B5CF6' }, }; interface SpireTabProps { simpleMode?: boolean; } // Check if player can enter spire mode const canEnterSpireMode = (spireMode: boolean): boolean => { return !spireMode; }; export function SpireTab({ simpleMode = false }: SpireTabProps) { // Get state from modular stores const currentFloor = useCombatStore((s) => s.currentFloor); const floorHP = useCombatStore((s) => s.floorHP); const floorMaxHP = useCombatStore((s) => s.floorMaxHP); const maxFloorReached = useCombatStore((s) => s.maxFloorReached); const currentAction = useCombatStore((s) => s.currentAction); const castProgress = useCombatStore((s) => s.castProgress); const activeSpell = useCombatStore((s) => s.activeSpell); const startClimbUp = useCombatStore((s) => s.startClimbUp); const startClimbDown = useCombatStore((s) => s.startClimbDown); const enterSpireMode = useGameStore((s) => s.enterSpireMode); const spireMode = useGameStore((s) => s.spireMode); const climbDirection = useGameStore((s) => s.climbDirection) || 'up'; const clearedFloors = useGameStore((s) => s.clearedFloors || {}); const currentRoom = useGameStore((s) => s.currentRoom); const equipmentSpellStates = useGameStore((s) => s.equipmentSpellStates); const golemancy = useGameStore((s) => s.golemancy); const activityLog = useGameStore((s) => s.activityLog); const currentStudyTarget = useGameStore((s) => s.currentStudyTarget); const parallelStudyTarget = useGameStore((s) => s.parallelStudyTarget); const signedPacts = usePrestigeStore((s) => s.signedPacts); const skills = useSkillStore((s) => s.skills); const skillUpgrades = useSkillStore((s) => s.skillUpgrades); const skillTiers = useSkillStore((s) => s.skillTiers); const rawMana = useManaStore((s) => s.rawMana); const elements = useManaStore((s) => s.elements); const equippedInstances = useGameStore((s) => s.equippedInstances); const equipmentInstances = useGameStore((s) => s.equipmentInstances); const designProgress = useGameStore((s) => s.designProgress); const designProgress2 = useGameStore((s) => s.designProgress2); const preparationProgress = useGameStore((s) => s.preparationProgress); const applicationProgress = useGameStore((s) => s.applicationProgress); const equipmentCraftingProgress = useGameStore((s) => s.equipmentCraftingProgress); // Derived data const floorElem = getFloorElement(currentFloor); const floorElemDef = ELEMENTS[floorElem]; const isGuardianFloor = !!GUARDIANS[currentFloor]; const currentGuardian = GUARDIANS[currentFloor]; const isFloorCleared = clearedFloors[currentFloor]; const roomType = currentRoom?.roomType || 'combat'; const roomConfig = ROOM_TYPE_CONFIG[roomType] || ROOM_TYPE_CONFIG.combat; const activeEquipmentSpells = useMemo( () => getActiveEquipmentSpells(equippedInstances, equipmentInstances), [equippedInstances, equipmentInstances] ); const upgradeEffects = useMemo( () => getUnifiedEffects({ skillUpgrades, skillTiers, equippedInstances, equipmentInstances, }), [skillUpgrades, skillTiers, equippedInstances, equipmentInstances] ); const totalDPS = useMemo( () => getTotalDPS({ skills, signedPacts, skillUpgrades, skillTiers }, upgradeEffects, floorElem), [skills, signedPacts, skillUpgrades, skillTiers, upgradeEffects, floorElem] ); // Enemy display info const primaryEnemy = currentRoom?.enemies?.[0] || null; const swarmEnemies = roomType === 'swarm' && currentRoom?.enemies ? currentRoom.enemies : []; // Spell casting check const canCastSpell = (spellId: string): boolean => { const spell = SPELLS_DEF[spellId]; if (!spell) return false; return canAffordSpellCost(spell.cost, rawMana, elements); }; // Climb handler const handleClimb = (direction: 'up' | 'down') => { if (direction === 'up') { startClimbUp(); } else { startClimbDown(); } }; const getSkillName = (skillId: string): string => { return SKILLS_DEF[skillId]?.name || skillId; }; return (
{/* Enter Spire Mode - Normal mode only */} {!simpleMode && (
Climb the Spire to face guardians and earn pacts
)} {/* Spire Header */} {/* Active Spells Card - Spire Mode only */} {simpleMode && (
Active Spells ({activeEquipmentSpells.length})
{activeEquipmentSpells.length > 0 ? (
{activeEquipmentSpells.map(({ spellId, equipmentId }) => { const spellDef = SPELLS_DEF[spellId]; if (!spellDef) return null; const spellState = equipmentSpellStates?.find( s => s.spellId === spellId && s.sourceEquipment === equipmentId ); const progress = spellState?.castProgress || 0; const canCast = canCastSpell(spellId); return (
{spellDef.name} {spellDef.tier === 0 && Basic} {canCast ? '✓' : '✗'}
⚔️ {calcDamage({ skills, signedPacts, skillUpgrades, skillTiers }, spellId, floorElem)} dmg • {formatSpellCost(spellDef.cost)} {' '}• ⚡ {Math.floor(calcDamage({ skills, signedPacts, skillUpgrades, skillTiers }, spellId, floorElem) * (spellDef.castSpeed || 1))} dmg/hr
{currentAction === 'climb' && (
Cast {(progress * 100).toFixed(0)}%
)}
); })}
) : (
No spells on equipped weapons. Enchant a staff with spell effects in the Crafting tab.
)} )} {/* Summoned Golems */} {simpleMode && golemancy.summonedGolems.length > 0 && (
Active Golems ({golemancy.summonedGolems.length})
{golemancy.summonedGolems.map((summoned) => { const golemDef = GOLEMS_DEF[summoned.golemId]; if (!golemDef) return null; const elemColor = ELEMENTS[golemDef.baseManaType]?.color || '#888'; const damage = getGolemDamage(summoned.golemId, skills); const attackSpeed = getGolemAttackSpeed(summoned.golemId, skills); return (
{golemDef.name}
{golemDef.isAoe && AOE {golemDef.aoeTargets}}
⚔️ {damage} DMG • ⚡ {attackSpeed.toFixed(1)}/hr
{currentAction === 'climb' && summoned.attackProgress > 0 && (
Attack {(summoned.attackProgress * 100).toFixed(0)}%
)}
); })}
)} {/* Guardian Panel */} {isGuardianFloor && simpleMode && ( )} {/* Room Display */} {simpleMode && ( )} {/* Floor Controls */} {simpleMode && ( )} {/* Combat Stats Panel */} {simpleMode && ( )} {/* Activity Log - Spire Mode only */} {simpleMode && } {/* Study Progress - Normal mode only */} {!simpleMode && currentStudyTarget && (
Study: {getSkillName(currentStudyTarget.id)}
{parallelStudyTarget && (
Parallel: {getSkillName(parallelStudyTarget.id)} (50% speed)
)} )} {/* Crafting Progress - Normal mode only */} {!simpleMode && (designProgress || preparationProgress || applicationProgress) && ( {designProgress && (
Design Progress
)} {preparationProgress && (
Preparation Progress
)} {applicationProgress && (
Application Progress
)} )}
); } SpireTab.displayName = "SpireTab";