diff --git a/src/lib/game/effects.ts b/src/lib/game/effects.ts index 32c8e2e..52683c8 100755 --- a/src/lib/game/effects.ts +++ b/src/lib/game/effects.ts @@ -157,9 +157,10 @@ export function computeTotalMaxMana( effects?: UnifiedEffects ): number { const pu = state.prestigeUpgrades; + const skillMult = effects?.skillLevelMultiplier || 1; const base = 100 + - (state.skills.manaWell || 0) * 100 + + (state.skills.manaWell || 0) * 100 * skillMult + (pu.manaWell || 0) * 500; if (!effects) { @@ -178,10 +179,11 @@ export function computeTotalRegen( ): number { const pu = state.prestigeUpgrades; const temporalBonus = 1 + (pu.temporalEcho || 0) * 0.1; + const skillMult = effects?.skillLevelMultiplier || 1; const base = 2 + - (state.skills.manaFlow || 0) * 1 + - (state.skills.manaSpring || 0) * 2 + + (state.skills.manaFlow || 0) * 1 * skillMult + + (state.skills.manaSpring || 0) * 2 * skillMult + (pu.manaFlow || 0) * 0.5; let regen = base * temporalBonus; @@ -202,10 +204,11 @@ export function computeTotalClickMana( state: Pick, effects?: UnifiedEffects ): number { + const skillMult = effects?.skillLevelMultiplier || 1; const base = 1 + - (state.skills.manaTap || 0) * 1 + - (state.skills.manaSurge || 0) * 3; + (state.skills.manaTap || 0) * 1 * skillMult + + (state.skills.manaSurge || 0) * 3 * skillMult; if (!effects) { effects = getUnifiedEffects(state as any); diff --git a/src/lib/game/store.ts b/src/lib/game/store.ts index 3e717b4..35428a1 100755 --- a/src/lib/game/store.ts +++ b/src/lib/game/store.ts @@ -302,9 +302,10 @@ export function computeMaxMana( effects?: ComputedEffects | UnifiedEffects ): number { const pu = state.prestigeUpgrades; + const skillMult = (effects as any)?.skillLevelMultiplier || 1; const base = 100 + - (state.skills.manaWell || 0) * 100 + + (state.skills.manaWell || 0) * 100 * skillMult + (pu.manaWell || 0) * 500; // If effects not provided, compute unified effects (includes equipment) @@ -350,10 +351,11 @@ export function computeRegen( ): number { const pu = state.prestigeUpgrades; const temporalBonus = 1 + (pu.temporalEcho || 0) * 0.1; + const skillMult = (effects as any)?.skillLevelMultiplier || 1; const base = 2 + - (state.skills.manaFlow || 0) * 1 + - (state.skills.manaSpring || 0) * 2 + + (state.skills.manaFlow || 0) * 1 * skillMult + + (state.skills.manaSpring || 0) * 2 * skillMult + (pu.manaFlow || 0) * 0.5; let regen = base * temporalBonus; @@ -399,10 +401,11 @@ export function computeClickMana( state: Pick, effects?: ComputedEffects | UnifiedEffects ): number { + const skillMult = (effects as any)?.skillLevelMultiplier || 1; const base = 1 + - (state.skills.manaTap || 0) * 1 + - (state.skills.manaSurge || 0) * 3; + (state.skills.manaTap || 0) * 1 * skillMult + + (state.skills.manaSurge || 0) * 3 * skillMult; // If effects not provided, compute unified effects (includes equipment) if (!effects && state.equipmentInstances && state.equippedInstances) { @@ -437,16 +440,18 @@ function getElementalBonus(spellElem: string, floorElem: string): number { export function calcDamage( state: Pick, spellId: string, - floorElem?: string + floorElem?: string, + effects?: ComputedEffects | UnifiedEffects ): number { const sp = SPELLS_DEF[spellId]; if (!sp) return 5; const skills = state.skills; - const baseDmg = sp.dmg + (skills.combatTrain || 0) * 5; - const pct = 1 + (skills.arcaneFury || 0) * 0.1; + const skillMult = (effects as any)?.skillLevelMultiplier || 1; + const baseDmg = sp.dmg + (skills.combatTrain || 0) * 5 * skillMult; + const pct = 1 + (skills.arcaneFury || 0) * 0.1 * skillMult; // Elemental mastery bonus - const elemMasteryBonus = 1 + (skills.elementalMastery || 0) * 0.15; + const elemMasteryBonus = 1 + (skills.elementalMastery || 0) * 0.15 * skillMult; // Guardian bane bonus const guardianBonus = floorElem && GUARDIANS[Object.values(GUARDIANS).find(g => g.element === floorElem)?.hp ? 0 : 0] @@ -954,6 +959,17 @@ export const useGameStore = create()( // Calculate base study speed let studySpeedMult = getStudySpeedMultiplier(skills); + // STUDY_RUSH: First hour of study is 2x speed + if (hasSpecial(effects, SPECIAL_EFFECTS.STUDY_RUSH) && consecutiveStudyHours === 0) { + studySpeedMult *= 2; + log = [`⚡ Study Rush activated! Double speed for the first hour!`, ...log.slice(0, 49)]; + } + + // MENTAL_CLARITY: +10% study speed when mana > 75% + if (hasSpecial(effects, SPECIAL_EFFECTS.MENTAL_CLARITY) && state.rawMana > maxMana * 0.75) { + studySpeedMult *= 1.10; + } + // DEEP_CONCENTRATION: +20% study speed when mana > 90% if (hasSpecial(effects, SPECIAL_EFFECTS.DEEP_CONCENTRATION) && state.rawMana > maxMana * 0.9) { studySpeedMult *= 1.20; @@ -1009,6 +1025,13 @@ export const useGameStore = create()( skillProgress = { ...skillProgress, [skillId]: 0 }; log = [`✅ ${SKILLS_DEF[skillId]?.name} Lv.${newLevel} mastered!`, ...log.slice(0, 49)]; + // STUDY_REFUND: 25% mana back on study complete + if (hasSpecial(effects, SPECIAL_EFFECTS.STUDY_REFUND)) { + const refundAmount = Math.floor(currentStudyTarget.totalCost * 0.25); + rawMana += refundAmount; + log = [`💰 Study Refund: ${refundAmount} mana returned!`, ...log.slice(0, 49)]; + } + // Check if this skill unlocks effects (research skills) const effectsToUnlock = EFFECT_RESEARCH_MAPPING[skillId]; if (effectsToUnlock && newLevel >= (SKILLS_DEF[skillId]?.max || 1)) { diff --git a/src/lib/game/study-slice.ts b/src/lib/game/study-slice.ts index cd9ef96..5efdd5e 100755 --- a/src/lib/game/study-slice.ts +++ b/src/lib/game/study-slice.ts @@ -3,6 +3,7 @@ import type { GameState } from './types'; import { SKILLS_DEF, SPELLS_DEF, getStudyCostMultiplier } from './constants'; +import { computeEffects, hasSpecial, SPECIAL_EFFECTS } from './upgrade-effects'; // ─── Study Actions Interface ────────────────────────────────────────────────── @@ -39,19 +40,37 @@ export function createStudySlice( // Calculate total mana cost and cost per hour const costMult = getStudyCostMultiplier(state.skills); - const totalCost = Math.floor(sk.base * (currentLevel + 1) * costMult); + let totalCost = Math.floor(sk.base * (currentLevel + 1) * costMult); + + // CHAIN_STUDY: -5% cost per maxed skill + const effects = computeEffects(state.skillUpgrades || {}, state.skillTiers || {}); + if (hasSpecial(effects, SPECIAL_EFFECTS.CHAIN_STUDY)) { + const maxedSkills = Object.entries(SKILLS_DEF).filter(([id, sk]) => + (state.skills[id] || 0) >= sk.max + ).length; + const discount = Math.pow(0.95, maxedSkills); // -5% per maxed skill + totalCost = Math.floor(totalCost * discount); + } + const manaCostPerHour = Math.ceil(totalCost / sk.studyTime); // Must have at least 1 hour worth of mana to start if (state.rawMana < manaCostPerHour) return; + // KNOWLEDGE_TRANSFER: New skills start at 10% progress + let initialProgress = state.skillProgress[skillId] || 0; + if (hasSpecial(effects, SPECIAL_EFFECTS.KNOWLEDGE_TRANSFER) && initialProgress === 0) { + initialProgress = sk.studyTime * 0.10; // 10% of required time + log = [`📖 Knowledge Transfer: Starting with 10% progress!`, ...state.log.slice(0, 49)]; + } + // 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, + progress: initialProgress, required: sk.studyTime, manaCostPerHour: manaCostPerHour, totalCost: totalCost, @@ -68,7 +87,18 @@ export function createStudySlice( // Calculate total mana cost and cost per hour const costMult = getStudyCostMultiplier(state.skills); - const totalCost = Math.floor(sp.unlock * costMult); + let totalCost = Math.floor(sp.unlock * costMult); + + // CHAIN_STUDY: -5% cost per maxed skill + const effects = computeEffects(state.skillUpgrades || {}, state.skillTiers || {}); + if (hasSpecial(effects, SPECIAL_EFFECTS.CHAIN_STUDY)) { + const maxedSkills = Object.entries(SKILLS_DEF).filter(([id, sk]) => + (state.skills[id] || 0) >= sk.max + ).length; + const discount = Math.pow(0.95, maxedSkills); // -5% per maxed skill + totalCost = Math.floor(totalCost * discount); + } + const studyTime = sp.studyTime || (sp.tier * 4); const manaCostPerHour = Math.ceil(totalCost / studyTime); diff --git a/src/lib/game/upgrade-effects.ts b/src/lib/game/upgrade-effects.ts index db57bc4..4d1778f 100755 --- a/src/lib/game/upgrade-effects.ts +++ b/src/lib/game/upgrade-effects.ts @@ -56,6 +56,9 @@ export interface ComputedEffects { // All active upgrades for display activeUpgrades: ActiveUpgradeEffect[]; + + // DEEP_UNDERSTANDING: +10% bonus from all skill levels + skillLevelMultiplier: number; } // ─── Special Effect IDs ──────────────────────────────────────────────────────── @@ -231,8 +234,14 @@ export function computeEffects( permanentRegenBonus: 0, specials: new Set(), activeUpgrades, + skillLevelMultiplier: 1, }; + // Apply DEEP_UNDERSTANDING: +10% bonus from all skill levels + if (hasSpecial(effects, SPECIAL_EFFECTS.DEEP_UNDERSTANDING)) { + effects.skillLevelMultiplier = 1.10; + } + // Apply each upgrade effect for (const upgrade of activeUpgrades) { const { effect } = upgrade;