Refactor large files into modular components
Build and Publish Mana Loop Docker Image / build-and-publish (push) Failing after 1m9s
Build and Publish Mana Loop Docker Image / build-and-publish (push) Failing after 1m9s
- Refactored page.tsx (613→252 lines) with GameOverScreen and LeftPanel extracted - Refactored StatsTab.tsx (584→92 lines) with section components - Refactored SkillsTab.tsx (434→54 lines) with sub-components - Created modular structure for GameContext, LootInventory, and other components - All extracted components organized into feature directories
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
// ─── Game Store (Coordinator) ─────────────────────────────────────────────────
|
||||
// Manages: day, hour, incursionStrength, containmentWards
|
||||
// Coordinates tick function across all stores
|
||||
// Coordinate tick function across all stores
|
||||
|
||||
import { create } from 'zustand';
|
||||
import { persist } from 'zustand/middleware';
|
||||
@@ -24,6 +24,8 @@ import { usePrestigeStore } from './prestigeStore';
|
||||
import { useManaStore } from './manaStore';
|
||||
import { useSkillStore } from './skillStore';
|
||||
import { useCombatStore, makeInitialSpells } from './combatStore';
|
||||
import { createResetGame, createGatherMana } from './gameActions';
|
||||
import { createStartNewLoop } from './gameLoopActions';
|
||||
|
||||
export interface GameCoordinatorState {
|
||||
day: number;
|
||||
@@ -39,6 +41,7 @@ export interface GameCoordinatorStore extends GameCoordinatorState {
|
||||
togglePause: () => void;
|
||||
startNewLoop: () => void;
|
||||
initGame: () => void;
|
||||
gatherMana: () => void;
|
||||
}
|
||||
|
||||
const initialState: GameCoordinatorState = {
|
||||
@@ -265,145 +268,12 @@ export const useGameStore = create<GameCoordinatorStore>()(
|
||||
});
|
||||
},
|
||||
|
||||
resetGame: () => {
|
||||
// Clear all persisted state
|
||||
localStorage.removeItem('mana-loop-ui-storage');
|
||||
localStorage.removeItem('mana-loop-prestige-storage');
|
||||
localStorage.removeItem('mana-loop-mana-storage');
|
||||
localStorage.removeItem('mana-loop-skill-storage');
|
||||
localStorage.removeItem('mana-loop-combat-storage');
|
||||
localStorage.removeItem('mana-loop-game-storage');
|
||||
|
||||
const startFloor = 1;
|
||||
|
||||
useUIStore.getState().resetUI();
|
||||
usePrestigeStore.getState().resetPrestige();
|
||||
useManaStore.getState().resetMana({}, {}, {}, {});
|
||||
useSkillStore.getState().resetSkills();
|
||||
useCombatStore.getState().resetCombat(startFloor);
|
||||
|
||||
set({
|
||||
...initialState,
|
||||
initialized: true,
|
||||
});
|
||||
},
|
||||
|
||||
resetGame: createResetGame(set, initialState),
|
||||
togglePause: () => {
|
||||
useUIStore.getState().togglePause();
|
||||
},
|
||||
|
||||
gatherMana: () => {
|
||||
const skillState = useSkillStore.getState();
|
||||
const manaState = useManaStore.getState();
|
||||
const prestigeState = usePrestigeStore.getState();
|
||||
|
||||
// Compute click mana
|
||||
let cm = 1 +
|
||||
(skillState.skills.manaTap || 0) * 1 +
|
||||
(skillState.skills.manaSurge || 0) * 3;
|
||||
|
||||
// Mana overflow bonus
|
||||
const overflowBonus = 1 + (skillState.skills.manaOverflow || 0) * 0.25;
|
||||
cm = Math.floor(cm * overflowBonus);
|
||||
|
||||
const effects = computeEffects(skillState.skillUpgrades || {}, skillState.skillTiers || {});
|
||||
const max = computeMaxMana(
|
||||
{ skills: skillState.skills, prestigeUpgrades: prestigeState.prestigeUpgrades, skillUpgrades: skillState.skillUpgrades, skillTiers: skillState.skillTiers },
|
||||
effects
|
||||
);
|
||||
|
||||
useManaStore.getState().gatherMana(cm, max);
|
||||
},
|
||||
|
||||
startNewLoop: () => {
|
||||
const prestigeState = usePrestigeStore.getState();
|
||||
const combatState = useCombatStore.getState();
|
||||
const manaState = useManaStore.getState();
|
||||
const skillState = useSkillStore.getState();
|
||||
|
||||
const insightGained = prestigeState.loopInsight || calcInsight({
|
||||
maxFloorReached: combatState.maxFloorReached,
|
||||
totalManaGathered: manaState.totalManaGathered,
|
||||
signedPacts: prestigeState.signedPacts,
|
||||
prestigeUpgrades: prestigeState.prestigeUpgrades,
|
||||
skills: skillState.skills,
|
||||
});
|
||||
|
||||
const total = prestigeState.insight + insightGained;
|
||||
|
||||
// Spell preservation is only through prestige upgrade "spellMemory" (purchased with insight)
|
||||
// Not through a skill - that would undermine the insight economy
|
||||
|
||||
const pu = prestigeState.prestigeUpgrades;
|
||||
const startFloor = 1 + (pu.spireKey || 0) * 2;
|
||||
|
||||
// Apply saved memories - restore skill levels, tiers, and upgrades
|
||||
const memories = prestigeState.memories || [];
|
||||
const newSkills: Record<string, number> = {};
|
||||
const newSkillTiers: Record<string, number> = {};
|
||||
const newSkillUpgrades: Record<string, string[]> = {};
|
||||
|
||||
if (memories.length > 0) {
|
||||
for (const memory of memories) {
|
||||
const tieredSkillId = memory.tier > 1 ? `${memory.skillId}_t${memory.tier}` : memory.skillId;
|
||||
newSkills[tieredSkillId] = memory.level;
|
||||
|
||||
if (memory.tier > 1) {
|
||||
newSkillTiers[memory.skillId] = memory.tier;
|
||||
}
|
||||
|
||||
newSkillUpgrades[tieredSkillId] = memory.upgrades || [];
|
||||
}
|
||||
}
|
||||
|
||||
// Reset and update all stores for new loop
|
||||
useUIStore.setState({
|
||||
gameOver: false,
|
||||
victory: false,
|
||||
paused: false,
|
||||
logs: ['✨ The loop begins. You start with Mana Bolt. Gather your strength, mage.'],
|
||||
});
|
||||
|
||||
usePrestigeStore.getState().resetPrestigeForNewLoop(
|
||||
total,
|
||||
pu,
|
||||
prestigeState.memories,
|
||||
3 + (pu.deepMemory || 0)
|
||||
);
|
||||
usePrestigeStore.getState().incrementLoopCount();
|
||||
|
||||
useManaStore.getState().resetMana(pu, newSkills, newSkillUpgrades, newSkillTiers);
|
||||
|
||||
useSkillStore.getState().resetSkills(newSkills, newSkillUpgrades, newSkillTiers);
|
||||
|
||||
// Reset combat with starting floor and any spells from prestige upgrades
|
||||
const startSpells = makeInitialSpells();
|
||||
if (pu.spellMemory) {
|
||||
const availableSpells = Object.keys(SPELLS_DEF).filter(s => s !== 'manaBolt');
|
||||
const shuffled = availableSpells.sort(() => Math.random() - 0.5);
|
||||
for (let i = 0; i < Math.min(pu.spellMemory, shuffled.length); i++) {
|
||||
startSpells[shuffled[i]] = { learned: true, level: 1, studyProgress: 0 };
|
||||
}
|
||||
}
|
||||
|
||||
useCombatStore.setState({
|
||||
currentFloor: startFloor,
|
||||
floorHP: getFloorMaxHP(startFloor),
|
||||
floorMaxHP: getFloorMaxHP(startFloor),
|
||||
maxFloorReached: startFloor,
|
||||
activeSpell: 'manaBolt',
|
||||
currentAction: 'meditate',
|
||||
castProgress: 0,
|
||||
spells: startSpells,
|
||||
});
|
||||
|
||||
set({
|
||||
day: 1,
|
||||
hour: 0,
|
||||
incursionStrength: 0,
|
||||
containmentWards: 0,
|
||||
});
|
||||
},
|
||||
startNewLoop: createStartNewLoop(set),
|
||||
gatherMana: createGatherMana(),
|
||||
}),
|
||||
{
|
||||
name: 'mana-loop-game-storage',
|
||||
@@ -416,15 +286,3 @@ export const useGameStore = create<GameCoordinatorStore>()(
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
// Re-export the game loop hook for convenience
|
||||
export function useGameLoop() {
|
||||
const tick = useGameStore((s) => s.tick);
|
||||
|
||||
return {
|
||||
start: () => {
|
||||
const interval = setInterval(tick, TICK_MS);
|
||||
return () => clearInterval(interval);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user