diff --git a/src/app/page.tsx b/src/app/page.tsx index 85b8128..3e475b6 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -233,13 +233,13 @@ export default function ManaLoopGame() { }> - + }> - + diff --git a/src/components/game/debug/AttunementDebug.tsx b/src/components/game/debug/AttunementDebug.tsx index d921eca..fbe57c6 100644 --- a/src/components/game/debug/AttunementDebug.tsx +++ b/src/components/game/debug/AttunementDebug.tsx @@ -2,28 +2,25 @@ import { Button } from '@/components/ui/button'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; -import { ATTUNEMENTS_DEF } from '@/lib/game/data/attunements'; import { Sparkles, Unlock } from 'lucide-react'; -import type { GameStore } from '@/lib/game/store'; +import { ATTUNEMENTS_DEF } from '@/lib/game/data/attunements'; +import { useGameStore } from '@/lib/game/store'; -interface AttunementDebugProps { - store: GameStore; -} - -export function AttunementDebug({ store }: AttunementDebugProps) { +export function AttunementDebug() { + const store = useGameStore((s) => s); + const handleUnlockAttunement = (id: string) => { - // Debug action to unlock attunements - if (store.debugUnlockAttunement) { - store.debugUnlockAttunement(id); + if (useGameStore.getState().debugUnlockAttunement) { + useGameStore.getState().debugUnlockAttunement(id); } }; const handleAddAttunementXP = (id: string, amount: number) => { - if (store.debugAddAttunementXP) { - store.debugAddAttunementXP(id, amount); + if (useGameStore.getState().debugAddAttunementXP) { + useGameStore.getState().debugAddAttunementXP(id, amount); } }; - + return ( @@ -49,34 +46,21 @@ export function AttunementDebug({ store }: AttunementDebugProps) { )} -
- {!isActive && ( - - )} - {isActive && ( - <> - - - - )} +
+ +
); diff --git a/src/components/game/debug/ElementDebug.tsx b/src/components/game/debug/ElementDebug.tsx index d13c55f..bc5f0a7 100644 --- a/src/components/game/debug/ElementDebug.tsx +++ b/src/components/game/debug/ElementDebug.tsx @@ -2,29 +2,22 @@ import { Button } from '@/components/ui/button'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; -import { ELEMENTS } from '@/lib/game/constants'; import { Star, Lock } from 'lucide-react'; -import type { GameStore } from '@/lib/game/store'; +import { useGameStore } from '@/lib/game/store'; -interface ElementDebugProps { - store: GameStore; -} - -export function ElementDebug({ store }: ElementDebugProps) { +export function ElementDebug() { + const store = useGameStore((s) => s); + const handleUnlockElement = (element: string) => { - store.unlockElement(element); + useGameStore.getState().unlockElement(element); }; const handleAddElementalMana = (element: string, amount: number) => { - const elem = store.elements[element]; - if (elem?.unlocked) { - // Add directly to element pool - need to implement in store - if (store.debugAddElementalMana) { - store.debugAddElementalMana(element, amount); - } + if (useGameStore.getState().debugAddElementalMana) { + useGameStore.getState().debugAddElementalMana(element, amount); } }; - + return ( @@ -35,47 +28,41 @@ export function ElementDebug({ store }: ElementDebugProps) {
- {Object.entries(ELEMENTS).map(([id, def]) => { - const elem = store.elements[id]; - const isUnlocked = elem?.unlocked; - + {Object.entries(store.elements).map(([id, elem]) => { + const def = ELEMENTS[id]; return ( -
-
- {def.sym} - {!isUnlocked && ( - - )} +
{def?.sym}
+
{def?.name}
+
+ {elem.current}/{elem.max}
-
{def.name}
- {isUnlocked && ( -
- {elem.current.toFixed(0)}/{elem.max} -
- )} - {isUnlocked && ( + {!elem.unlocked && ( + )} + {elem.unlocked && ( + )}
diff --git a/src/components/game/debug/GameStateDebug.tsx b/src/components/game/debug/GameStateDebug.tsx index c35e692..87c3cb5 100644 --- a/src/components/game/debug/GameStateDebug.tsx +++ b/src/components/game/debug/GameStateDebug.tsx @@ -8,23 +8,20 @@ import { Switch } from '@/components/ui/switch'; import { Label } from '@/components/ui/label'; import { RotateCcw, AlertTriangle, Zap, Clock, Settings, Eye, - Plus } from 'lucide-react'; -import type { GameStore } from '@/lib/game/store'; -import { fmt } from '@/lib/game/store'; import { useDebug } from '@/lib/game/debug-context'; +import { useGameStore } from '@/lib/game/store'; -interface GameStateDebugProps { - store: GameStore; -} - -export function GameStateDebug({ store }: GameStateDebugProps) { +export function GameStateDebug() { const [confirmReset, setConfirmReset] = useState(false); const { showComponentNames, toggleComponentNames } = useDebug(); + // Get state from store + const store = useGameStore((s) => s); + const handleReset = () => { if (confirmReset) { - store.resetGame(); + useGameStore.getState().resetGame(); setConfirmReset(false); } else { setConfirmReset(true); @@ -34,17 +31,19 @@ export function GameStateDebug({ store }: GameStateDebugProps) { const handleAddMana = (amount: number) => { // Use gatherMana multiple times to add mana + const state = useGameStore.getState(); for (let i = 0; i < amount; i++) { - store.gatherMana(); + state.gatherMana(); } }; const handleSetTime = (day: number, hour: number) => { - if (store.debugSetTime) { - store.debugSetTime(day, hour); + const state = useGameStore.getState(); + if (state.debugSetTime) { + state.debugSetTime(day, hour); } }; - + return (
{/* Warning Banner */} @@ -127,20 +126,20 @@ export function GameStateDebug({ store }: GameStateDebugProps) {
- Current: {fmt(store.rawMana)} / {fmt(store.getMaxMana())} + Current: {store.rawMana} / {store.getMaxMana?.() || '?'}
@@ -149,7 +148,7 @@ export function GameStateDebug({ store }: GameStateDebugProps) { size="sm" className="w-full bg-blue-600 hover:bg-blue-700" onClick={() => { - const max = store.getMaxMana(); + const max = store.getMaxMana?.() || 100; const current = store.rawMana; for (let i = 0; i < Math.floor(max - current); i++) { store.gatherMana(); @@ -192,7 +191,7 @@ export function GameStateDebug({ store }: GameStateDebugProps) { @@ -217,7 +216,7 @@ export function GameStateDebug({ store }: GameStateDebugProps) { // Unlock all base elements ['fire', 'water', 'air', 'earth', 'light', 'dark', 'death'].forEach(e => { if (!store.elements[e]?.unlocked) { - store.unlockElement(e); + useGameStore.getState().unlockElement(e); } }); }} @@ -228,10 +227,10 @@ export function GameStateDebug({ store }: GameStateDebugProps) { size="sm" variant="outline" onClick={() => { - // Unlock utility elements (only transference remains) + // Unlock utility elements ['transference'].forEach(e => { if (!store.elements[e]?.unlocked) { - store.unlockElement(e); + useGameStore.getState().unlockElement(e); } }); }} @@ -244,7 +243,7 @@ export function GameStateDebug({ store }: GameStateDebugProps) { onClick={() => { // Max floor if (store.debugSetFloor) { - store.debugSetFloor(100); + useGameStore.getState().debugSetFloor(100); } }} > @@ -256,7 +255,7 @@ export function GameStateDebug({ store }: GameStateDebugProps) { onClick={() => { // Reset floor HP if (store.resetFloorHP) { - store.resetFloorHP(); + useGameStore.getState().resetFloorHP(); } }} > diff --git a/src/components/game/debug/GolemDebug.tsx b/src/components/game/debug/GolemDebug.tsx index b913b54..23789c0 100644 --- a/src/components/game/debug/GolemDebug.tsx +++ b/src/components/game/debug/GolemDebug.tsx @@ -2,13 +2,8 @@ import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Bug } from 'lucide-react'; -import type { GameStore } from '@/lib/game/store'; -interface GolemDebugProps { - store: GameStore; -} - -export function GolemDebug({ store }: GolemDebugProps) { +export function GolemDebug() { return ( diff --git a/src/components/game/debug/SkillDebug.tsx b/src/components/game/debug/SkillDebug.tsx index 52277e8..5084956 100644 --- a/src/components/game/debug/SkillDebug.tsx +++ b/src/components/game/debug/SkillDebug.tsx @@ -4,13 +4,11 @@ import { Button } from '@/components/ui/button'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Separator } from '@/components/ui/separator'; import { BookOpen } from 'lucide-react'; -import type { GameStore } from '@/lib/game/store'; +import { useGameStore } from '@/lib/game/store'; -interface SkillDebugProps { - store: GameStore; -} - -export function SkillDebug({ store }: SkillDebugProps) { +export function SkillDebug() { + const store = useGameStore((s) => s); + return ( @@ -32,11 +30,9 @@ export function SkillDebug({ store }: SkillDebugProps) { // Level up all enchanting skills by 1 const enchantSkills = ['enchanting', 'efficientEnchant', 'enchantSpeed','essenceRefining']; enchantSkills.forEach(skillId => { - if (store.skills[skillId] !== undefined) { - store.skills[skillId] = Math.min((store.skills[skillId] || 0) + 1, 10); - } else { - store.skills[skillId] = 1; - } + store.skills[skillId] = Math.min((store.skills[skillId] || 0) + 1, 10); + // Force update + useGameStore.setState({ skills: { ...store.skills } }); }); }} > @@ -51,6 +47,7 @@ export function SkillDebug({ store }: SkillDebugProps) { enchantSkills.forEach(skillId => { store.skills[skillId] = 10; }); + useGameStore.setState({ skills: { ...store.skills } }); }} > Max All Enchanting @@ -68,12 +65,9 @@ export function SkillDebug({ store }: SkillDebugProps) { onClick={() => { const manaSkills = ['manaWell', 'manaFlow', 'manaOverflow', 'fireManaCap', 'waterManaCap', 'airManaCap', 'earthManaCap', 'lightManaCap', 'darkManaCap', 'deathManaCap', 'metalManaCap', 'sandManaCap', 'lightningManaCap', 'transferenceManaCap']; manaSkills.forEach(skillId => { - if (store.skills[skillId] !== undefined) { - store.skills[skillId] = Math.min((store.skills[skillId] || 0) + 1, 10); - } else { - store.skills[skillId] = 1; - } + store.skills[skillId] = Math.min((store.skills[skillId] || 0) + 1, 10); }); + useGameStore.setState({ skills: { ...store.skills } }); }} > +1 All Mana @@ -86,6 +80,7 @@ export function SkillDebug({ store }: SkillDebugProps) { manaSkills.forEach(skillId => { store.skills[skillId] = 10; }); + useGameStore.setState({ skills: { ...store.skills } }); }} > Max All Mana @@ -103,12 +98,9 @@ export function SkillDebug({ store }: SkillDebugProps) { onClick={() => { const studySkills = ['quickLearner', 'focusedMind', 'meditation', 'knowledgeRetention']; studySkills.forEach(skillId => { - if (store.skills[skillId] !== undefined) { - store.skills[skillId] = Math.min((store.skills[skillId] || 0) + 1, 10); - } else { - store.skills[skillId] = 1; - } + store.skills[skillId] = Math.min((store.skills[skillId] || 0) + 1, 10); }); + useGameStore.setState({ skills: { ...store.skills } }); }} > +1 All Study @@ -121,6 +113,7 @@ export function SkillDebug({ store }: SkillDebugProps) { studySkills.forEach(skillId => { store.skills[skillId] = 10; }); + useGameStore.setState({ skills: { ...store.skills } }); }} > Max All Study @@ -138,12 +131,9 @@ export function SkillDebug({ store }: SkillDebugProps) { onClick={() => { const craftSkills = ['effCrafting', 'fieldRepair', 'elemCrafting']; craftSkills.forEach(skillId => { - if (store.skills[skillId] !== undefined) { - store.skills[skillId] = Math.min((store.skills[skillId] || 0) + 1, 10); - } else { - store.skills[skillId] = 1; - } + store.skills[skillId] = Math.min((store.skills[skillId] || 0) + 1, 10); }); + useGameStore.setState({ skills: { ...store.skills } }); }} > +1 All Crafting @@ -156,6 +146,7 @@ export function SkillDebug({ store }: SkillDebugProps) { craftSkills.forEach(skillId => { store.skills[skillId] = 10; }); + useGameStore.setState({ skills: { ...store.skills } }); }} > Max All Crafting @@ -178,13 +169,14 @@ export function SkillDebug({ store }: SkillDebugProps) { 'researchDarkSpells', 'researchLifeDeathSpells', 'researchAdvancedFire', 'researchAdvancedWater', 'researchAdvancedAir', 'researchAdvancedEarth', 'researchAdvancedLight', 'researchAdvancedDark', - 'researchMasterFire', 'researchMasterWater', 'researchMasterEarth', - 'researchDamageEffects', 'researchCombatEffects', - 'researchManaEffects', 'researchAdvancedManaEffects', 'researchUtilityEffects' + 'researchMasterFire', 'researchMasterWater', 'researchMasterEarth', + 'researchDamageEffects', 'researchCombatEffects', 'researchManaEffects', + 'researchAdvancedManaEffects', 'researchUtilityEffects' ]; researchSkills.forEach(skillId => { store.skills[skillId] = 1; }); + useGameStore.setState({ skills: { ...store.skills } }); }} > Unlock All Research @@ -194,9 +186,7 @@ export function SkillDebug({ store }: SkillDebugProps) { variant="outline" onClick={() => { // Add all unlocked effects to unlockedEffects - const effectIds = Object.keys(store.unlockedEffects || {}); - // Add spell effects, mana effects, combat effects, utility effects - const allEffectIds = [ + const effectIds = [ // Spell effects 'spell_manaBolt', 'spell_manaStrike', 'spell_fireball', 'spell_emberShot', 'spell_waterJet', 'spell_iceShard', 'spell_gust', 'spell_windSlash', @@ -229,11 +219,13 @@ export function SkillDebug({ store }: SkillDebugProps) { // Sword enchants 'sword_fire', 'sword_frost', 'sword_lightning', 'sword_void' ]; - allEffectIds.forEach(id => { - if (!store.unlockedEffects.includes(id)) { - store.unlockedEffects.push(id); + const currentEffects = store.unlockedEffects || []; + effectIds.forEach(id => { + if (!currentEffects.includes(id)) { + currentEffects.push(id); } }); + useGameStore.setState({ unlockedEffects: currentEffects }); }} > Unlock All Effects @@ -260,27 +252,22 @@ export function SkillDebug({ store }: SkillDebugProps) { 'spell_manaBolt', 'spell_manaStrike', 'spell_fireball', 'spell_emberShot', 'spell_waterJet', 'spell_iceShard', 'spell_gust', 'spell_windSlash', 'spell_stoneBullet', 'spell_rockSpike', 'spell_lightLance', 'spell_radiance', - 'spell_shadowBolt', 'spell_darkPulse', 'spell_drain', 'spell_inferno', - 'spell_flameWave', 'spell_tidalWave', 'spell_iceStorm', 'spell_hurricane', - 'spell_windBlade', 'spell_earthquake', 'spell_stoneBarrage', 'spell_solarFlare', - 'spell_divineSmite', 'spell_voidRift', 'spell_shadowStorm', 'spell_pyroclasm', - 'spell_tsunami', 'spell_meteorStrike', 'spell_spark', 'spell_lightningBolt', - 'spell_chainLightning', 'spell_stormCall', 'spell_thunderStrike', 'spell_metalShard', - 'spell_ironFist', 'spell_steelTempest', 'spell_furnaceBlast', 'spell_sandBlast', - 'spell_sandstorm', 'spell_desertWind', 'spell_duneCollapse', + 'spell_shadowBolt', 'spell_darkPulse', 'spell_drain', 'mana_cap_50', 'mana_cap_100', 'mana_regen_1', 'mana_regen_2', 'mana_regen_5', 'click_mana_1', 'click_mana_3', 'damage_5', 'damage_10', 'damage_pct_10', 'crit_5', 'attack_speed_10', 'meditate_10', 'study_10', 'insight_5', - 'spell_echo_10', 'guardian_dmg_10', 'overpower_80', - 'weapon_mana_cap_20', 'weapon_mana_cap_50', 'weapon_mana_cap_100', - 'weapon_mana_regen_1', 'weapon_mana_regen_2', 'weapon_mana_regen_5', - 'sword_fire', 'sword_frost', 'sword_lightning', 'sword_void' + 'spell_echo_10', 'guardian_dmg_10', 'overpower_80' ]; + const currentEffects = store.unlockedEffects || []; allEffectIds.forEach(id => { - if (!store.unlockedEffects.includes(id)) { - store.unlockedEffects.push(id); + if (!currentEffects.includes(id)) { + currentEffects.push(id); } }); + useGameStore.setState({ + skills: { ...store.skills }, + unlockedEffects: currentEffects + }); }} > 🚀 Max Everything diff --git a/src/components/game/stats/CombatStatsSection.tsx b/src/components/game/stats/CombatStatsSection.tsx index 47d2be6..d03a343 100644 --- a/src/components/game/stats/CombatStatsSection.tsx +++ b/src/components/game/stats/CombatStatsSection.tsx @@ -1,20 +1,21 @@ 'use client'; -import { GUARDIANS } from '@/lib/game/constants'; -import { fmtDec } from '@/lib/game/store'; -import type { GameStore } from '@/lib/game/types'; +import { fmtDec } from '@/lib/game/stores'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Swords } from 'lucide-react'; -export interface CombatStatsSectionProps { - store: GameStore; -} +// Modular stores +import { useSkillStore, useCombatStore } from '@/lib/game/stores'; + +export function CombatStatsSection() { + // Get state from modular stores + const skills = useSkillStore((s) => s.skills); + const signedPacts = useCombatStore((s) => s.signedPacts); -export function CombatStatsSection({ store }: CombatStatsSectionProps) { return ( - + Combat Stats @@ -24,25 +25,25 @@ export function CombatStatsSection({ store }: CombatStatsSectionProps) {
Combat Training Bonus: - +{(store.skills.combatTrain || 0) * 5} + +{(skills.combatTrain || 0) * 5}
Arcane Fury Multiplier: - ×{fmtDec(1 + (store.skills.arcaneFury || 0) * 0.1, 2)} + ×{fmtDec(1 + (skills.arcaneFury || 0) * 0.1, 2)}
Elemental Mastery: - ×{fmtDec(1 + (store.skills.elementalMastery || 0) * 0.15, 2)} + ×{fmtDec(1 + (skills.elementalMastery || 0) * 0.15, 2)}
Guardian Bane: - ×{fmtDec(1 + (store.skills.guardianBane || 0) * 0.2, 2)} (vs guardians) + ×{fmtDec(1 + (skills.guardianBane || 0) * 0.2, 2)} (vs guardians)
Critical Hit Chance: - {((store.skills.precision || 0) * 5)}% + {(skills.precision || 0) * 5}%
Critical Multiplier: @@ -50,11 +51,10 @@ export function CombatStatsSection({ store }: CombatStatsSectionProps) {
Spell Echo Chance: - {((store.skills.spellEcho || 0) * 10)}% + {(skills.spellEcho || 0) * 10}%
- Pact Multiplier: - ×{fmtDec(store.signedPacts.reduce((m, f) => m * (GUARDIANS[f]?.pact || 1), 1), 2)} + ×{fmtDec(signedPacts.reduce((m, f) => m * (GUARDIANS[f]?.pact || 1), 1), 2)}
diff --git a/src/components/game/stats/ManaStatsSection.tsx b/src/components/game/stats/ManaStatsSection.tsx index 60c04f0..d83cebe 100644 --- a/src/components/game/stats/ManaStatsSection.tsx +++ b/src/components/game/stats/ManaStatsSection.tsx @@ -2,14 +2,16 @@ import { getTierMultiplier } from '@/lib/game/skill-evolution'; import { hasSpecial, SPECIAL_EFFECTS } from '@/lib/game/effects'; -import { fmt, fmtDec } from '@/lib/game/store'; -import type { GameStore, UnifiedEffects } from '@/lib/game/types'; +import { fmt, fmtDec } from '@/lib/game/stores'; +import type { UnifiedEffects } from '@/lib/game/types'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Separator } from '@/components/ui/separator'; import { Droplet } from 'lucide-react'; +// Modular stores +import { useSkillStore, usePrestigeStore, useManaStore } from '@/lib/game/stores'; + export interface ManaStatsSectionProps { - store: GameStore; upgradeEffects: UnifiedEffects; maxMana: number; baseRegen: number; @@ -26,7 +28,6 @@ export interface ManaStatsSectionProps { } export function ManaStatsSection({ - store, upgradeEffects, maxMana, baseRegen, @@ -41,6 +42,12 @@ export function ManaStatsSection({ hasManaOverflow, hasEternalFlow, }: ManaStatsSectionProps) { + // Get state from modular stores + const skills = useSkillStore((s) => s.skills); + const skillTiers = useSkillStore((s) => s.skillTiers); + const prestigeUpgrades = usePrestigeStore((s) => s.prestigeUpgrades); + const rawMana = useManaStore((s) => s.rawMana); + return ( @@ -60,9 +67,9 @@ export function ManaStatsSection({ Mana Well Bonus: {(() => { - const mw = store.skillTiers?.manaWell || 1; + const mw = skillTiers?.manaWell || 1; const tieredSkillId = mw > 1 ? `manaWell_t${mw}` : 'manaWell'; - const level = store.skills[tieredSkillId] || store.skills.manaWell || 0; + const level = skills[tieredSkillId] || skills.manaWell || 0; const tierMult = getTierMultiplier(tieredSkillId); return `+${fmt(level * 100 * tierMult)} (${level} lvl × 100 × ${tierMult}x tier)`; })()} @@ -70,7 +77,7 @@ export function ManaStatsSection({
Prestige Mana Well: - +{fmt((store.prestigeUpgrades.manaWell || 0) * 500)} + +{fmt((prestigeUpgrades.manaWell || 0) * 500)}
{upgradeEffects.maxManaBonus > 0 && (
@@ -98,9 +105,9 @@ export function ManaStatsSection({ Mana Flow Bonus: {(() => { - const mf = store.skillTiers?.manaFlow || 1; + const mf = skillTiers?.manaFlow || 1; const tieredSkillId = mf > 1 ? `manaFlow_t${mf}` : 'manaFlow'; - const level = store.skills[tieredSkillId] || store.skills.manaFlow || 0; + const level = skills[tieredSkillId] || skills.manaFlow || 0; const tierMult = getTierMultiplier(tieredSkillId); return `+${fmtDec(level * 1 * tierMult)}/hr (${level} lvl × 1 × ${tierMult}x tier)`; })()} @@ -108,15 +115,15 @@ export function ManaStatsSection({
Mana Spring Bonus: - +{(store.skills.manaSpring || 0) * 2}/hr + +{(skills.manaSpring || 0) * 2}/hr
Prestige Mana Flow: - +{fmtDec((store.prestigeUpgrades.manaFlow || 0) * 0.5)}/hr + +{fmtDec((prestigeUpgrades.manaFlow || 0) * 0.5)}/hr
Temporal Echo: - ×{fmtDec(1 + (store.prestigeUpgrades.temporalEcho || 0) * 0.1, 2)} + ×{fmtDec(1 + (prestigeUpgrades.temporalEcho || 0) * 0.1, 2)}
Base Regen: @@ -167,26 +174,28 @@ export function ManaStatsSection({
Mana Tap Bonus: - +{store.skills.manaTap || 0} + +{skills.manaTap || 0}
Mana Surge Bonus: - +{(store.skills.manaSurge || 0) * 3} + +{(skills.manaSurge || 0) * 3}
Mana Overflow: - ×{fmtDec(1 + (store.skills.manaOverflow || 0) * 0.25, 2)} + ×{fmtDec(1 + (skills.manaOverflow || 0) * 0.25, 2)}
- Meditation Multiplier: + 1.5 ? 'text-purple-400' : 'text-gray-300'}`}> + Meditation Multiplier: + 1.5 ? 'text-purple-400' : 'text-gray-300'}`}> {fmtDec(meditationMultiplier, 2)}x
- Effective Regen: + Effective Regen: {fmtDec(effectiveRegen, 2)}/hr
{incursionStrength > 0 && !hasSpecial(upgradeEffects, SPECIAL_EFFECTS.STEADY_STREAM) && ( @@ -237,13 +246,13 @@ export function ManaStatsSection({ Regen immune to ALL penalties
)} - {hasSpecial(upgradeEffects, SPECIAL_EFFECTS.MANA_TORRENT) && store.rawMana > maxMana * 0.75 && ( + {hasSpecial(upgradeEffects, SPECIAL_EFFECTS.MANA_TORRENT) && rawMana > maxMana * 0.75 && (
Mana Torrent: +50% regen (high mana)
)} - {hasSpecial(upgradeEffects, SPECIAL_EFFECTS.DESPERATE_WELLS) && store.rawMana < maxMana * 0.25 && ( + {hasSpecial(upgradeEffects, SPECIAL_EFFECTS.DESPERATE_WELLS) && rawMana < maxMana * 0.25 && (
Desperate Wells: +50% regen (low mana) diff --git a/src/components/game/stats/ManaTypeBreakdown.tsx b/src/components/game/stats/ManaTypeBreakdown.tsx index 5e6b716..1a9aec2 100644 --- a/src/components/game/stats/ManaTypeBreakdown.tsx +++ b/src/components/game/stats/ManaTypeBreakdown.tsx @@ -1,37 +1,68 @@ 'use client'; import { ELEMENTS } from '@/lib/game/constants'; -import { fmt, fmtDec } from '@/lib/game/store'; -import type { GameStore } from '@/lib/game/types'; -import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; +import { fmt, fmtDec } from '@/lib/game/stores'; import { ATTUNEMENTS_DEF, getAttunementConversionRate } from '@/lib/game/data/attunements'; -import { computeMaxMana, computeElementMax } from '@/lib/game/store'; +import { computeMaxMana, computeElementMax } from '@/lib/game/stores'; import { computeEffectiveRegenForDisplay } from '@/lib/game/store-modules/computed-stats'; import { getUnifiedEffects } from '@/lib/game/effects'; +import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Droplet } from 'lucide-react'; import { Separator } from '@/components/ui/separator'; -export interface ManaTypeBreakdownProps { - store: GameStore; -} +// Modular stores +import { useCombatStore, useManaStore, useSkillStore, usePrestigeStore } from '@/lib/game/stores'; -export function ManaTypeBreakdown({ store }: ManaTypeBreakdownProps) { +export function ManaTypeBreakdown() { + // Get state from modular stores + const skills = useSkillStore((s) => s.skills); + const skillTiers = useSkillStore((s) => s.skillTiers); + const skillUpgrades = useSkillStore((s) => s.skillUpgrades); + + const prestigeUpgrades = usePrestigeStore((s) => s.prestigeUpgrades); + const elements = useManaStore((s) => s.elements); + const rawMana = useManaStore((s) => s.rawMana); + const attunements = useCombatStore((s) => s.attunements); + // Compute unified effects for regen calculations - const effects = getUnifiedEffects(store); + const effects = getUnifiedEffects({ + skillUpgrades, + skillTiers, + equippedInstances: {}, + equipmentInstances: {} + }); // Get effective regen info for raw mana - const regenInfo = computeEffectiveRegenForDisplay(store, effects); + const regenInfo = computeEffectiveRegenForDisplay({ + skills, + prestigeUpgrades, + skillUpgrades, + skillTiers, + elements, + rawMana, + attunements + } as any, effects); // Compute max mana - const maxMana = computeMaxMana(store, effects); + const maxMana = computeMaxMana({ + skills, + prestigeUpgrades, + skillUpgrades, + skillTiers + }, effects); // Get unlocked elements sorted by category then name - const unlockedElements = Object.entries(store.elements) + const unlockedElements = Object.entries(elements) .filter(([, state]) => state.unlocked) .map(([id, state]) => { const def = ELEMENTS[id]; if (!def) return null; - const elemMax = computeElementMax(store, effects, id); + const elemMax = computeElementMax({ + skills, + prestigeUpgrades, + skillUpgrades, + skillTiers + } as any, effects, id); return { id, name: def.name, @@ -69,7 +100,7 @@ export function ManaTypeBreakdown({ store }: ManaTypeBreakdownProps) { (base)
- {fmt(store.rawMana)} + {fmt(rawMana)} / {fmt(maxMana)}
@@ -79,7 +110,7 @@ export function ManaTypeBreakdown({ store }: ManaTypeBreakdownProps) {
@@ -102,13 +133,15 @@ export function ManaTypeBreakdown({ store }: ManaTypeBreakdownProps) {
{/* Show conversion drains by attunement */} - {store.conversionDrains && Object.keys(store.conversionDrains).length > 0 && ( + {attunements && Object.keys(attunements).length > 0 && ( <>
Conversion Drains:
- {Object.entries(store.conversionDrains).map(([attId, rate]) => { + {Object.entries(attunements).map(([attId, attState]) => { const attDef = ATTUNEMENTS_DEF[attId]; - if (!attDef || rate <= 0) return null; + if (!attDef || attState.level === 0) return null; + const rate = getAttunementConversionRate(attId, attState.level); + if (rate <= 0) return null; return (
{attDef.name}: @@ -128,7 +161,7 @@ export function ManaTypeBreakdown({ store }: ManaTypeBreakdownProps) { if (!elem) return null; // Find attunements that convert TO this element - const convertingAttunements = Object.entries(store.attunements || {}) + const convertingAttunements = Object.entries(attunements || {}) .filter(([attId, attState]) => { if (!attState.active) return false; const attDef = ATTUNEMENTS_DEF[attId]; @@ -177,7 +210,7 @@ export function ManaTypeBreakdown({ store }: ManaTypeBreakdownProps) {
Source: {convertingAttunements.map(([attId]) => { const attDef = ATTUNEMENTS_DEF[attId]; - const level = store.attunements[attId]?.level || 1; + const level = attunements[attId]?.level || 1; return `${attDef?.name} (Lv.${level})`; }).join(', ')}
diff --git a/src/components/game/stats/StudyStatsSection.tsx b/src/components/game/stats/StudyStatsSection.tsx index 6631b9d..c7908dd 100644 --- a/src/components/game/stats/StudyStatsSection.tsx +++ b/src/components/game/stats/StudyStatsSection.tsx @@ -1,17 +1,22 @@ 'use client'; -import { fmtDec } from '@/lib/game/store'; -import type { GameStore } from '@/lib/game/types'; +import { fmtDec } from '@/lib/game/stores'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { BookOpen } from 'lucide-react'; +// Modular stores +import { useSkillStore, usePrestigeStore } from '@/lib/game/stores'; + export interface StudyStatsSectionProps { - store: GameStore; studySpeedMult: number; studyCostMult: number; } -export function StudyStatsSection({ store, studySpeedMult, studyCostMult }: StudyStatsSectionProps) { +export function StudyStatsSection({ studySpeedMult, studyCostMult }: StudyStatsSectionProps) { + // Get state from modular stores + const skills = useSkillStore((s) => s.skills); + const prestigeUpgrades = usePrestigeStore((s) => s.prestigeUpgrades); + return ( @@ -29,7 +34,7 @@ export function StudyStatsSection({ store, studySpeedMult, studyCostMult }: Stud
Quick Learner Bonus: - +{((store.skills.quickLearner || 0) * 10)}% + +{((skills.quickLearner || 0) * 10)}%
@@ -39,13 +44,13 @@ export function StudyStatsSection({ store, studySpeedMult, studyCostMult }: Stud
Focused Mind Bonus: - -{((store.skills.focusedMind || 0) * 5)}% + -{((skills.focusedMind || 0) * 5)}%
Progress Retention: - {Math.round((1 + (store.skills.knowledgeRetention || 0) * 0.2) * 100)}% + {Math.round((1 + (skills.knowledgeRetention || 0) * 0.2) * 100)}%
diff --git a/src/components/game/stats/UpgradeEffectsSection.tsx b/src/components/game/stats/UpgradeEffectsSection.tsx index 629e9a8..84d561c 100644 --- a/src/components/game/stats/UpgradeEffectsSection.tsx +++ b/src/components/game/stats/UpgradeEffectsSection.tsx @@ -1,44 +1,46 @@ 'use client'; -import { SKILL_EVOLUTION_PATHS, getTierMultiplier } from '@/lib/game/skill-evolution'; +import { SKILL_EVOLUTION_PATHS } from '@/lib/game/skill-evolution'; import { SKILLS_DEF } from '@/lib/game/constants'; -import type { GameStore, SkillUpgradeChoice } from '@/lib/game/types'; +import type { SkillUpgradeChoice } from '@/lib/game/types'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Badge } from '@/components/ui/badge'; import { Star } from 'lucide-react'; -export interface UpgradeEffectsSectionProps { - store: GameStore; -} +// Modular stores +import { useSkillStore } from '@/lib/game/stores'; -// Helper function to get all selected skill upgrades -function getAllSelectedUpgrades(store: GameStore) { - 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 }); +export function UpgradeEffectsSection() { + // Get state from modular stores + const skillUpgrades = useSkillStore((s) => s.skillUpgrades); + + // Helper function to get all selected skill upgrades + function getAllSelectedUpgrades() { + const upgrades = []; + for (const [skillId, selectedIds] of Object.entries(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; } - return upgrades; -} -export function UpgradeEffectsSection({ store }: UpgradeEffectsSectionProps) { - const selectedUpgrades = getAllSelectedUpgrades(store); + const selectedUpgrades = getAllSelectedUpgrades(); return ( - + Active Skill Upgrades ({selectedUpgrades.length}) @@ -57,17 +59,17 @@ export function UpgradeEffectsSection({ store }: UpgradeEffectsSectionProps) {
{upgrade.desc}
- {upgrade.effect.type === 'multiplier' && ( + {upgrade.effect && upgrade.effect.type === 'multiplier' && (
- +{Math.round((upgrade.effect.value! - 1) * 100)}% {upgrade.effect.stat} + +{Math.round((upgrade.effect.value - 1) * 100)}% {upgrade.effect.stat}
)} - {upgrade.effect.type === 'bonus' && ( + {upgrade.effect && upgrade.effect.type === 'bonus' && (
+{upgrade.effect.value} {upgrade.effect.stat}
)} - {upgrade.effect.type === 'special' && ( + {upgrade.effect && upgrade.effect.type === 'special' && (
⚡ {upgrade.effect.specialDesc || 'Special effect active'}
diff --git a/src/components/game/tabs/DebugTab.tsx b/src/components/game/tabs/DebugTab.tsx index 197f55d..34b3dfb 100755 --- a/src/components/game/tabs/DebugTab.tsx +++ b/src/components/game/tabs/DebugTab.tsx @@ -1,31 +1,26 @@ 'use client'; -import type { GameStore } from '@/lib/game/store'; +import { GameStateDebug } from '@/components/game/debug/GameStateDebug'; import { - GameStateDebug, SkillDebug, - ElementDebug, AttunementDebug, + ElementDebug, GolemDebug, PactDebug } from '@/components/game/debug'; -interface DebugTabProps { - store: GameStore; -} - -export function DebugTab({ store }: DebugTabProps) { +export function DebugTab() { return (
- +
- - + +
- - + +
); diff --git a/src/components/game/tabs/StatsTab.tsx b/src/components/game/tabs/StatsTab.tsx old mode 100755 new mode 100644 index 6c87166..17903c6 --- a/src/components/game/tabs/StatsTab.tsx +++ b/src/components/game/tabs/StatsTab.tsx @@ -3,8 +3,9 @@ import { ELEMENTS, GUARDIANS } from '@/lib/game/constants'; import { getTierMultiplier } from '@/lib/game/skill-evolution'; import { hasSpecial, SPECIAL_EFFECTS } from '@/lib/game/effects'; -import { fmt, fmtDec } from '@/lib/game/store'; -import type { GameStore, UnifiedEffects } from '@/lib/game/types'; +import { getUnifiedEffects } from '@/lib/game/effects'; +import { fmt, fmtDec, computeMaxMana, computeRegen, computeClickMana, getMeditationBonus, getIncursionStrength, getStudySpeedMultiplier, getStudyCostMultiplier } from '@/lib/game/stores'; +import type { UnifiedEffects } from '@/lib/game/types'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Badge } from '@/components/ui/badge'; import { Separator } from '@/components/ui/separator'; @@ -15,57 +16,107 @@ import { CombatStatsSection } from '../stats/CombatStatsSection'; import { StudyStatsSection } from '../stats/StudyStatsSection'; import { UpgradeEffectsSection } from '../stats/UpgradeEffectsSection'; -export interface StatsTabProps { - store: GameStore; - upgradeEffects: UnifiedEffects; - maxMana: number; - baseRegen: number; - clickMana: number; - meditationMultiplier: number; - effectiveRegen: number; - incursionStrength: number; - manaCascadeBonus: number; - manaWaterfallBonus: number; - hasManaWaterfall: boolean; - hasFlowSurge: boolean; - hasManaOverflow: boolean; - hasEternalFlow: boolean; - studySpeedMult: number; - studyCostMult: number; -} +// Modular stores +import { useCombatStore, useManaStore, useSkillStore, usePrestigeStore, useGameStore } from '@/lib/game/stores'; + +export function StatsTab() { + // Get state from modular stores + const skills = useSkillStore((s) => s.skills); + const skillTiers = useSkillStore((s) => s.skillTiers); + const skillUpgrades = useSkillStore((s) => s.skillUpgrades); + + const prestigeUpgrades = usePrestigeStore((s) => s.prestigeUpgrades); + const loopCount = usePrestigeStore((s) => s.loopCount); + const insight = usePrestigeStore((s) => s.insight); + const totalInsight = usePrestigeStore((s) => s.totalInsight); + const memorySlots = usePrestigeStore((s) => s.memorySlots); + + const elements = useManaStore((s) => s.elements); + const totalManaGathered = useManaStore((s) => s.totalManaGathered); + const rawMana = useManaStore((s) => s.rawMana); + const meditateTicks = useManaStore((s) => s.meditateTicks); + + const signedPacts = useCombatStore((s) => s.signedPacts); + const maxFloorReached = useCombatStore((s) => s.maxFloorReached); + const spells = useCombatStore((s) => s.spells); + + // Compute unified effects + const upgradeEffects = getUnifiedEffects({ + skillUpgrades, + skillTiers, + equippedInstances: {}, + equipmentInstances: {} + }) as UnifiedEffects; + + // Compute derived stats + const maxMana = computeMaxMana({ + skills, + prestigeUpgrades, + skillUpgrades, + skillTiers + }, upgradeEffects); + + const baseRegen = computeRegen({ + skills, + prestigeUpgrades, + skillUpgrades, + skillTiers + }, upgradeEffects); + + const clickMana = computeClickMana({ + skills, + prestigeUpgrades, + skillUpgrades, + skillTiers + }); + + // Get meditation multiplier + const meditationMultiplier = getMeditationBonus(meditateTicks, skills, upgradeEffects.meditationEfficiency); + + // Get incursion strength + const day = useGameStore((s) => s.day); + const hour = useGameStore((s) => s.hour); + const incursionStrength = getIncursionStrength(day, hour); + + // Effective regen with incursion penalty + const effectiveRegenWithSpecials = baseRegen * (1 - incursionStrength); + + // Mana Cascade bonus + const manaCascadeBonus = hasSpecial(upgradeEffects, SPECIAL_EFFECTS.MANA_CASCADE) + ? Math.floor(maxMana / 100) * 0.1 + : 0; + + // Mana Waterfall bonus + const manaWaterfallBonus = hasSpecial(upgradeEffects, SPECIAL_EFFECTS.MANA_WATERFALL) + ? Math.floor(maxMana / 100) * 0.25 + : 0; + + // Effective regen + const effectiveRegen = (effectiveRegenWithSpecials + manaCascadeBonus + manaWaterfallBonus) * meditationMultiplier; + + // Get study speed/cost multipliers + const studySpeedMult = getStudySpeedMultiplier(skills, skillUpgrades, skillTiers); + const studyCostMult = getStudyCostMultiplier(skills, skillUpgrades, skillTiers); + + // Check special effects + const hasManaWaterfall = hasSpecial(upgradeEffects, SPECIAL_EFFECTS.MANA_WATERFALL); + const hasFlowSurge = hasSpecial(upgradeEffects, SPECIAL_EFFECTS.FLOW_SURGE); + const hasManaOverflow = hasSpecial(upgradeEffects, SPECIAL_EFFECTS.MANA_OVERFLOW); + const hasEternalFlow = hasSpecial(upgradeEffects, SPECIAL_EFFECTS.ETERNAL_FLOW); -export function StatsTab({ - store, - upgradeEffects, - maxMana, - baseRegen, - clickMana, - meditationMultiplier, - effectiveRegen, - incursionStrength, - manaCascadeBonus, - manaWaterfallBonus, - hasManaWaterfall, - hasFlowSurge, - hasManaOverflow, - hasEternalFlow, - studySpeedMult, - studyCostMult, -}: StatsTabProps) { // Compute element max const elemMax = (() => { - const ea = store.skillTiers?.elemAttune || 1; + const ea = skillTiers?.elemAttune || 1; const tieredSkillId = ea > 1 ? `elemAttune_t${ea}` : 'elemAttune'; - const level = store.skills[tieredSkillId] || store.skills.elemAttune || 0; + const level = skills[tieredSkillId] || skills.elemAttune || 0; const tierMult = getTierMultiplier(tieredSkillId); - return 10 + level * 50 * tierMult + (store.prestigeUpgrades.elementalAttune || 0) * 25; + return 10 + level * 50 * tierMult + (prestigeUpgrades.elementalAttune || 0) * 25; })(); return (
{/* Mana Stats */} {/* Mana Type Breakdown */} - + {/* Combat Stats */} - + {/* Study Stats */} @@ -113,9 +163,9 @@ export function StatsTab({ Elem. Attunement Bonus: {(() => { - const ea = store.skillTiers?.elemAttune || 1; + const ea = skillTiers?.elemAttune || 1; const tieredSkillId = ea > 1 ? `elemAttune_t${ea}` : 'elemAttune'; - const level = store.skills[tieredSkillId] || store.skills.elemAttune || 0; + const level = skills[tieredSkillId] || skills.elemAttune || 0; const tierMult = getTierMultiplier(tieredSkillId); return `+${level * 50 * tierMult}`; })()} @@ -123,24 +173,24 @@ export function StatsTab({
Prestige Attunement: - +{(store.prestigeUpgrades.elementalAttune || 0) * 25} + +{(prestigeUpgrades.elementalAttune || 0) * 25}
Unlocked Elements: - {Object.values(store.elements).filter(e => e.unlocked).length} / {Object.keys(ELEMENTS).length} + {Object.values(elements).filter(e => e.unlocked).length} / {Object.keys(ELEMENTS).length}
Elem. Crafting Bonus: - ×{fmtDec(1 + (store.skills.elemCrafting || 0) * 0.25, 2)} + ×{fmtDec(1 + (skills.elemCrafting || 0) * 0.25, 2)}
Elemental Mana Pools:
- {Object.entries(store.elements) + {Object.entries(elements) .filter(([, state]) => state.unlocked) .map(([id, state]) => { const def = ELEMENTS[id]; @@ -156,9 +206,9 @@ export function StatsTab({ {/* Active Upgrades */} - + - {/* Enchantment Power (placeholder for Task 5) */} + {/* Enchantment Power */} @@ -183,15 +233,15 @@ export function StatsTab({ - Signed Pacts ({store.signedPacts.length}/10) + Signed Pacts ({signedPacts.length}/10) - {store.signedPacts.length === 0 ? ( + {signedPacts.length === 0 ? (
No pacts signed yet. Defeat guardians to earn pacts.
) : (
- {store.signedPacts.map((floor) => { + {signedPacts.map((floor) => { const guardian = GUARDIANS[floor]; if (!guardian) return null; return ( @@ -214,7 +264,7 @@ export function StatsTab({ })}
Combined Pact Multiplier: - ×{fmtDec(store.signedPacts.reduce((m, f) => m * (GUARDIANS[f]?.pact || 1), 1), 2)} + ×{fmtDec(signedPacts.reduce((m, f) => m * (GUARDIANS[f]?.pact || 1), 1), 2)}
)} @@ -232,38 +282,38 @@ export function StatsTab({
-
{store.loopCount}
+
{loopCount}
Loops Completed
-
{fmt(store.insight)}
+
{fmt(insight)}
Current Insight
-
{fmt(store.totalInsight)}
+
{fmt(totalInsight)}
Total Insight
-
{store.maxFloorReached}
+
{maxFloorReached}
Max Floor
-
{Object.values(store.spells).filter(s => s.learned).length}
+
{Object.values(spells).filter(s => s.learned).length}
Spells Learned
-
{Object.values(store.skills).reduce((a, b) => a + b, 0)}
+
{Object.values(skills).reduce((a, b) => a + b, 0)}
Total Skill Levels
-
{fmt(store.totalManaGathered)}
+
{fmt(totalManaGathered)}
Total Mana Gathered
-
{store.memorySlots}
+
{memorySlots}
Memory Slots
diff --git a/src/lib/game/stores/index.ts b/src/lib/game/stores/index.ts index c382471..f2686a5 100755 --- a/src/lib/game/stores/index.ts +++ b/src/lib/game/stores/index.ts @@ -21,14 +21,13 @@ export { useGameStore } from './gameStore'; export { useGameLoop } from './gameHooks'; export type { GameCoordinatorState, GameCoordinatorStore } from './gameStore'; -// Re-export utilities from utils.ts +// Re-export utilities from utils.ts and computed-stats export { fmt, fmtDec, getFloorMaxHP, getFloorElement, computeMaxMana, - computeElementMax, computeRegen, computeEffectiveRegen, computeClickMana, @@ -41,3 +40,7 @@ export { canAffordSpellCost, deductSpellCost, } from '../utils'; + +export { computeElementMax } from '../store-modules/computed-stats'; + +export { getStudySpeedMultiplier, getStudyCostMultiplier } from '../constants';