// ─── Study Slice ───────────────────────────────────────────────────────────── // Actions for studying skills and spells import type { GameState } from './types'; import { SKILLS_DEF, SPELLS_DEF, getStudyCostMultiplier } from './constants'; // ─── Study Actions Interface ────────────────────────────────────────────────── export interface StudyActions { startStudyingSkill: (skillId: string) => void; startStudyingSpell: (spellId: string) => void; cancelStudy: () => void; startParallelStudySkill: (skillId: string) => void; cancelParallelStudy: () => void; } // ─── Study Slice Factory ────────────────────────────────────────────────────── export function createStudySlice( set: (partial: Partial | ((state: GameState) => Partial)) => void, get: () => GameState ): StudyActions { return { // Start studying a skill - mana is deducted per hour, not upfront startStudyingSkill: (skillId: string) => { const state = get(); const sk = SKILLS_DEF[skillId]; if (!sk) return; const currentLevel = state.skills[skillId] || 0; if (currentLevel >= sk.max) return; // Check prerequisites if (sk.req) { for (const [r, rl] of Object.entries(sk.req)) { if ((state.skills[r] || 0) < rl) return; } } // Calculate total mana cost and cost per hour const costMult = getStudyCostMultiplier(state.skills); const totalCost = Math.floor(sk.base * (currentLevel + 1) * costMult); const manaCostPerHour = Math.ceil(totalCost / sk.studyTime); // Must have at least 1 hour worth of mana to start if (state.rawMana < manaCostPerHour) return; // Start studying (no upfront cost - mana is deducted per hour during study) set({ currentAction: 'study', currentStudyTarget: { type: 'skill', id: skillId, progress: state.skillProgress[skillId] || 0, required: sk.studyTime, manaCostPerHour: manaCostPerHour, totalCost: totalCost, }, log: [`📚 Started studying ${sk.name} (${manaCostPerHour} mana/hr)...`, ...state.log.slice(0, 49)], }); }, // Start studying a spell startStudyingSpell: (spellId: string) => { const state = get(); const sp = SPELLS_DEF[spellId]; if (!sp || state.spells[spellId]?.learned) return; // Calculate total mana cost and cost per hour const costMult = getStudyCostMultiplier(state.skills); const totalCost = Math.floor(sp.unlock * costMult); const studyTime = sp.studyTime || (sp.tier * 4); const manaCostPerHour = Math.ceil(totalCost / studyTime); // Must have at least 1 hour worth of mana to start if (state.rawMana < manaCostPerHour) return; // Start studying (no upfront cost - mana is deducted per hour during study) set({ currentAction: 'study', currentStudyTarget: { type: 'spell', id: spellId, progress: state.spells[spellId]?.studyProgress || 0, required: studyTime, manaCostPerHour: manaCostPerHour, totalCost: totalCost, }, spells: { ...state.spells, [spellId]: { ...(state.spells[spellId] || { learned: false, level: 0 }), studyProgress: state.spells[spellId]?.studyProgress || 0 }, }, log: [`📚 Started studying ${sp.name} (${manaCostPerHour} mana/hr)...`, ...state.log.slice(0, 49)], }); }, // Cancel current study (saves progress) cancelStudy: () => { const state = get(); if (!state.currentStudyTarget) return; // Knowledge retention bonus const retentionBonus = 1 + (state.skills.knowledgeRetention || 0) * 0.2; const savedProgress = Math.min( state.currentStudyTarget.progress, state.currentStudyTarget.required * retentionBonus ); // Save progress if (state.currentStudyTarget.type === 'skill') { set({ currentStudyTarget: null, currentAction: 'meditate', skillProgress: { ...state.skillProgress, [state.currentStudyTarget.id]: savedProgress, }, log: [`📖 Study interrupted. Progress saved.`, ...state.log.slice(0, 49)], }); } else if (state.currentStudyTarget.type === 'spell') { set({ currentStudyTarget: null, currentAction: 'meditate', spells: { ...state.spells, [state.currentStudyTarget.id]: { ...(state.spells[state.currentStudyTarget.id] || { learned: false, level: 0 }), studyProgress: savedProgress, }, }, log: [`📖 Study interrupted. Progress saved.`, ...state.log.slice(0, 49)], }); } }, // Start parallel study of a skill (requires Parallel Mind upgrade) startParallelStudySkill: (skillId: string) => { const state = get(); if (state.parallelStudyTarget) return; // Already have parallel study if (!state.currentStudyTarget) return; // Need primary study const sk = SKILLS_DEF[skillId]; if (!sk) return; const currentLevel = state.skills[skillId] || 0; if (currentLevel >= sk.max) return; // Can't study same thing in parallel if (state.currentStudyTarget.id === skillId) return; // Calculate mana cost for parallel study const costMult = getStudyCostMultiplier(state.skills); const totalCost = Math.floor(sk.base * (currentLevel + 1) * costMult); const manaCostPerHour = Math.ceil(totalCost / sk.studyTime); set({ parallelStudyTarget: { type: 'skill', id: skillId, progress: state.skillProgress[skillId] || 0, required: sk.studyTime, manaCostPerHour: Math.ceil(manaCostPerHour / 2), // Half speed = half mana cost per tick totalCost: totalCost, }, log: [`📚 Started parallel study of ${sk.name}... (50% speed)`, ...state.log.slice(0, 49)], }); }, // Cancel parallel study cancelParallelStudy: () => { set((state) => { if (!state.parallelStudyTarget) return state; return { parallelStudyTarget: null, log: ['📖 Parallel study cancelled.', ...state.log.slice(0, 49)], }; }); }, }; }