'use client'; import { useGameStore, fmt, fmtDec, calcDamage, computePactMultiplier, computePactInsightMultiplier } from '@/lib/game/store'; import { ELEMENTS, GUARDIANS, SPELLS_DEF } from '@/lib/game/constants'; import { SKILL_EVOLUTION_PATHS, getTierMultiplier } from '@/lib/game/skill-evolution'; import { useManaStats, useCombatStats, useStudyStats } from '@/lib/game/hooks/useGameDerived'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Badge } from '@/components/ui/badge'; import { Separator } from '@/components/ui/separator'; import { Droplet, Swords, BookOpen, FlaskConical, RotateCcw, Trophy, Star } from 'lucide-react'; import type { SkillUpgradeChoice } from '@/lib/game/types'; export function StatsTab() { const store = useGameStore(); const { upgradeEffects, maxMana, baseRegen, clickMana, meditationMultiplier, incursionStrength, manaCascadeBonus, effectiveRegen, hasSteadyStream, hasManaTorrent, hasDesperateWells } = useManaStats(); const { activeSpellDef, pactMultiplier, pactInsightMultiplier } = useCombatStats(); const { studySpeedMult, studyCostMult } = useStudyStats(); // Compute element max const elemMax = (() => { const ea = store.skillTiers?.elemAttune || 1; const tieredSkillId = ea > 1 ? `elemAttune_t${ea}` : 'elemAttune'; const level = store.skills[tieredSkillId] || store.skills.elemAttune || 0; const tierMult = getTierMultiplier(tieredSkillId); return 10 + level * 50 * tierMult + (store.prestigeUpgrades.elementalAttune || 0) * 25; })(); // Get all selected skill upgrades const getAllSelectedUpgrades = () => { const upgrades: { skillId: string; upgrade: SkillUpgradeChoice }[] = []; for (const [skillId, selectedIds] of Object.entries(store.skillUpgrades)) { const baseSkillId = skillId.includes('_t') ? skillId.split('_t')[0] : skillId; const path = SKILL_EVOLUTION_PATHS[baseSkillId]; if (!path) continue; for (const tier of path.tiers) { if (tier.skillId === skillId) { for (const upgradeId of selectedIds) { const upgrade = tier.upgrades.find(u => u.id === upgradeId); if (upgrade) { upgrades.push({ skillId, upgrade }); } } } } } return upgrades; }; const selectedUpgrades = getAllSelectedUpgrades(); return (
{/* Mana Stats */} Mana Stats
Base Max Mana: 100
Mana Well Bonus: {(() => { const mw = store.skillTiers?.manaWell || 1; const tieredSkillId = mw > 1 ? `manaWell_t${mw}` : 'manaWell'; const level = store.skills[tieredSkillId] || store.skills.manaWell || 0; const tierMult = getTierMultiplier(tieredSkillId); return `+${fmt(level * 100 * tierMult)} (${level} lvl × 100 × ${tierMult}x tier)`; })()}
Prestige Mana Well: +{fmt((store.prestigeUpgrades.manaWell || 0) * 500)}
{upgradeEffects.maxManaBonus > 0 && (
Upgrade Mana Bonus: +{fmt(upgradeEffects.maxManaBonus)}
)} {upgradeEffects.maxManaMultiplier > 1 && (
Upgrade Mana Multiplier: ×{fmtDec(upgradeEffects.maxManaMultiplier, 2)}
)}
Total Max Mana: {fmt(maxMana)}
Base Regen: 2/hr
Mana Flow Bonus: {(() => { const mf = store.skillTiers?.manaFlow || 1; const tieredSkillId = mf > 1 ? `manaFlow_t${mf}` : 'manaFlow'; const level = store.skills[tieredSkillId] || store.skills.manaFlow || 0; const tierMult = getTierMultiplier(tieredSkillId); return `+${fmtDec(level * 1 * tierMult)}/hr (${level} lvl × 1 × ${tierMult}x tier)`; })()}
Mana Spring Bonus: +{(store.skills.manaSpring || 0) * 2}/hr
Prestige Mana Flow: +{fmtDec((store.prestigeUpgrades.manaFlow || 0) * 0.5)}/hr
Temporal Echo: ×{fmtDec(1 + (store.prestigeUpgrades.temporalEcho || 0) * 0.1, 2)}
Base Regen: {fmtDec(baseRegen, 2)}/hr
{upgradeEffects.regenBonus > 0 && (
Upgrade Regen Bonus: +{fmtDec(upgradeEffects.regenBonus, 2)}/hr
)} {upgradeEffects.permanentRegenBonus > 0 && (
Permanent Regen Bonus: +{fmtDec(upgradeEffects.permanentRegenBonus, 2)}/hr
)} {upgradeEffects.regenMultiplier > 1 && (
Upgrade Regen Multiplier: ×{fmtDec(upgradeEffects.regenMultiplier, 2)}
)}
{/* Skill Upgrade Effects Summary */} {upgradeEffects.activeUpgrades.length > 0 && ( <>
Active Skill Upgrades
{upgradeEffects.activeUpgrades.map((upgrade, idx) => (
{upgrade.name} {upgrade.desc}
))}
)}
Click Mana Value: +{clickMana}
Mana Tap Bonus: +{store.skills.manaTap || 0}
Mana Surge Bonus: +{(store.skills.manaSurge || 0) * 3}
Mana Overflow: ×{fmtDec(1 + (store.skills.manaOverflow || 0) * 0.25, 2)}
Meditation Multiplier: 1.5 ? 'text-purple-400' : 'text-gray-300'}`}> {fmtDec(meditationMultiplier, 2)}x
Effective Regen: {fmtDec(effectiveRegen, 2)}/hr
{incursionStrength > 0 && !hasSteadyStream && (
Incursion Penalty: -{Math.round(incursionStrength * 100)}%
)} {hasSteadyStream && incursionStrength > 0 && (
Steady Stream: Immune to incursion
)} {manaCascadeBonus > 0 && (
Mana Cascade Bonus: +{fmtDec(manaCascadeBonus, 2)}/hr
)} {hasManaTorrent && store.rawMana > maxMana * 0.75 && (
Mana Torrent: +50% regen (high mana)
)} {hasDesperateWells && store.rawMana < maxMana * 0.25 && (
Desperate Wells: +50% regen (low mana)
)}
{/* Combat Stats */} Combat Stats
Active Spell Base Damage: {activeSpellDef?.dmg || 5}
Combat Training Bonus: +{(store.skills.combatTrain || 0) * 5}
Arcane Fury Multiplier: ×{fmtDec(1 + (store.skills.arcaneFury || 0) * 0.1, 2)}
Elemental Mastery: ×{fmtDec(1 + (store.skills.elementalMastery || 0) * 0.15, 2)}
Guardian Bane: ×{fmtDec(1 + (store.skills.guardianBane || 0) * 0.2, 2)} (vs guardians)
Critical Hit Chance: {((store.skills.precision || 0) * 5)}%
Critical Multiplier: 1.5x
Spell Echo Chance: {((store.skills.spellEcho || 0) * 10)}%
Pact Multiplier: ×{fmtDec(pactMultiplier, 2)}
Total Damage: {fmt(calcDamage(store, store.activeSpell))}
{/* Pact Status */} Pact Status
Pact Slots: {store.signedPacts.length} / {1 + (store.prestigeUpgrades.pactCapacity || 0)}
Damage Multiplier: ×{fmtDec(pactMultiplier, 2)}
Insight Multiplier: ×{fmtDec(pactInsightMultiplier, 2)}
{store.signedPacts.length > 1 && ( <>
Interference Mitigation: {Math.min(store.pactInterferenceMitigation || 0, 5) * 10}%
{(store.pactInterferenceMitigation || 0) >= 5 && (
Synergy Bonus: +{((store.pactInterferenceMitigation || 0) - 5) * 10}%
)} )}
Unlocked Mana Types:
{Object.entries(store.elements) .filter(([, state]) => state.unlocked) .map(([id]) => { const elem = ELEMENTS[id]; return ( {elem?.sym} {elem?.name} ); })}
{/* Study Stats */} Study Stats
Study Speed: ×{fmtDec(studySpeedMult, 2)}
Quick Learner Bonus: +{((store.skills.quickLearner || 0) * 10)}%
Study Cost: {Math.round(studyCostMult * 100)}%
Focused Mind Bonus: -{((store.skills.focusedMind || 0) * 5)}%
Progress Retention: {Math.round((1 + (store.skills.knowledgeRetention || 0) * 0.2) * 100)}%
{/* Element Stats */} Element Stats
Element Capacity: {elemMax}
Elem. Attunement Bonus: {(() => { const ea = store.skillTiers?.elemAttune || 1; const tieredSkillId = ea > 1 ? `elemAttune_t${ea}` : 'elemAttune'; const level = store.skills[tieredSkillId] || store.skills.elemAttune || 0; const tierMult = getTierMultiplier(tieredSkillId); return `+${level * 50 * tierMult}`; })()}
Prestige Attunement: +{(store.prestigeUpgrades.elementalAttune || 0) * 25}
Unlocked Elements: {Object.values(store.elements).filter(e => e.unlocked).length} / {Object.keys(ELEMENTS).length}
Elem. Crafting Bonus: ×{fmtDec(1 + (store.skills.elemCrafting || 0) * 0.25, 2)}
Elemental Mana Pools:
{Object.entries(store.elements) .filter(([, state]) => state.unlocked) .map(([id, state]) => { const def = ELEMENTS[id]; return (
{def?.sym}
{state.current}/{state.max}
); })}
{/* Active Upgrades */} Active Skill Upgrades ({selectedUpgrades.length}) {selectedUpgrades.length === 0 ? (
No skill upgrades selected yet. Level skills to 5 or 10 to choose upgrades.
) : (
{selectedUpgrades.map(({ skillId, upgrade }) => (
{upgrade.name} {SKILLS_DEF[skillId]?.name || skillId}
{upgrade.desc}
{upgrade.effect.type === 'multiplier' && (
+{Math.round((upgrade.effect.value! - 1) * 100)}% {upgrade.effect.stat}
)} {upgrade.effect.type === 'bonus' && (
+{upgrade.effect.value} {upgrade.effect.stat}
)} {upgrade.effect.type === 'special' && (
⚡ {upgrade.effect.specialDesc || 'Special effect active'}
)}
))}
)}
{/* Loop Stats */} Loop Stats
{store.loopCount}
Loops Completed
{fmt(store.insight)}
Current Insight
{fmt(store.totalInsight)}
Total Insight
{store.maxFloorReached}
Max Floor
{Object.values(store.spells).filter(s => s.learned).length}
Spells Learned
{Object.values(store.skills).reduce((a, b) => a + b, 0)}
Total Skill Levels
{fmt(store.totalManaGathered)}
Total Mana Gathered
{store.memorySlots}
Memory Slots
); }