'use client'; 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 type { GameStore } from '@/lib/game/store'; import { ELEMENTS, GUARDIANS, SPELLS_DEF } from '@/lib/game/constants'; import { getEnemyName, calcDamage } from '@/lib/game/store'; 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/store'; // 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 { store: GameStore; simpleMode?: boolean; } // Check if player can enter spire mode const canEnterSpireMode = (store: GameStore): boolean => { return !store.spireMode; }; export function SpireTab({ store, simpleMode = false }: SpireTabProps) { // Derived data const floorElem = getFloorElement(store.currentFloor); const floorElemDef = ELEMENTS[floorElem]; const isGuardianFloor = !!GUARDIANS[store.currentFloor]; const currentGuardian = GUARDIANS[store.currentFloor]; const climbDirection = store.climbDirection || 'up'; const clearedFloors = store.clearedFloors || {}; const currentRoom = store.currentRoom; const isFloorCleared = clearedFloors[store.currentFloor]; const roomType = currentRoom?.roomType || 'combat'; const roomConfig = ROOM_TYPE_CONFIG[roomType] || ROOM_TYPE_CONFIG.combat; const activeEquipmentSpells = getActiveEquipmentSpells(store.equippedInstances, store.equipmentInstances); const upgradeEffects = getUnifiedEffects(store); const totalDPS = getTotalDPS(store, upgradeEffects, floorElem); const studySpeedMult = 1; // 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, store.rawMana, store.elements); }; // Climb handler const handleClimb = (direction: 'up' | 'down') => { if (direction === 'up') { store.startClimbUp(); } else { store.startClimbDown(); } }; 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 = store.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 ? '✓' : '✗'}
⚔️ {fmt(calcDamage(store, spellId))} dmg • {formatSpellCost(spellDef.cost)} {' '}• ⚡ {fmt(Math.floor(calcDamage(store, spellId) * (spellDef.castSpeed || 1)))} dmg/hr
{store.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 && store.golemancy.summonedGolems.length > 0 && (
Active Golems ({store.golemancy.summonedGolems.length})
{store.golemancy.summonedGolems.map((summoned) => { const golemDef = getGolemDef(summoned.golemId); if (!golemDef) return null; const elemColor = ELEMENTS[golemDef.baseManaType]?.color || '#888'; const damage = getGolemDamage(summoned.golemId, store.skills); const attackSpeed = getGolemAttackSpeed(summoned.golemId, store.skills); return (
{golemDef.name}
{golemDef.isAoe && AOE {golemDef.aoeTargets}}
⚔️ {damage} DMG • ⚡ {attackSpeed.toFixed(1)}/hr
{store.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 && store.currentStudyTarget && (
Study: {getSkillName(store.currentStudyTarget.id)}
{store.parallelStudyTarget && (
Parallel: {getSkillName(store.parallelStudyTarget.id)} (50% speed)
)} )} {/* Crafting Progress - Normal mode only */} {!simpleMode && (store.designProgress || store.preparationProgress || store.applicationProgress) && ( {store.designProgress && (
Design Progress
)} {store.preparationProgress && (
Preparation Progress
)} {store.applicationProgress && (
Application Progress
)} )}
); } SpireTab.displayName = "SpireTab"; function getSkillName(skillId: string): string { const { SKILLS_DEF } = require('@/lib/game/constants'); return SKILLS_DEF[skillId]?.name || skillId; } function fmt(value: number): string { if (value >= 1e12) return (value / 1e12).toFixed(2) + 't'; if (value >= 1e9) return (value / 1e9).toFixed(2) + 'b'; if (value >= 1e6) return (value / 1e6).toFixed(2) + 'm'; if (value >= 1e3) return (value / 1e3).toFixed(2) + 'k'; return value.toFixed(0); } function getGolemDef(golemId: string) { const { GOLEMS_DEF } = require('@/lib/game/data/golems'); return GOLEMS_DEF[golemId]; } function getGolemDamage(golemId: string, skills: any) { const { getGolemDamage } = require('@/lib/game/data/golems'); return getGolemDamage(golemId, skills); } function getGolemAttackSpeed(golemId: string, skills: any) { const { getGolemAttackSpeed } = require('@/lib/game/data/golems'); return getGolemAttackSpeed(golemId, skills); }