From 75a43c72093df3d64b57bae7dde3325c92113b98 Mon Sep 17 00:00:00 2001 From: Refactoring Agent <[email protected]> Date: Fri, 24 Apr 2026 16:37:55 +0200 Subject: [PATCH] Phase 4: Mana Well effects (remaining 7) --- src/lib/game/store.ts | 29 +++++++++++++++++++++++++---- src/lib/game/store/computed.ts | 7 +++++-- src/lib/game/types/game.ts | 3 +++ src/lib/game/upgrade-effects.ts | 22 ++++++++++++++++++++++ 4 files changed, 55 insertions(+), 6 deletions(-) diff --git a/src/lib/game/store.ts b/src/lib/game/store.ts index 6205335..253caa9 100755 --- a/src/lib/game/store.ts +++ b/src/lib/game/store.ts @@ -563,6 +563,7 @@ function makeInitial(overrides: Partial = {}): GameState { const pu = overrides.prestigeUpgrades || {}; const startFloor = 1 + (pu.spireKey || 0) * 2; const elemMax = computeElementMax({ skills: overrides.skills || {}, prestigeUpgrades: pu }); + const manaHeartBonus = overrides.manaHeartBonus || 0; const elements: Record = {}; Object.keys(ELEMENTS).forEach((k) => { @@ -732,6 +733,9 @@ function makeInitial(overrides: Partial = {}): GameState { log: ['✨ The loop begins. You start with a Basic Staff (Mana Bolt) and civilian clothes. Gather your strength, mage.'], loopInsight: 0, flowSurgeEndTime: 0, // Hour timestamp for FLOW_SURGE effect (0 = inactive) + + // Mana Well Effects (Phase 4) + manaHeartBonus: manaHeartBonus, // Cumulative +10% max mana per loop from MANA_HEART }; } @@ -883,10 +887,19 @@ export const useGameStore = create()( } } - // Mana regeneration with MANA_OVERFLOW support + // Mana regeneration with MANA_OVERFLOW and VOID_STORAGE support const overflowMultiplier = hasSpecial(effects, SPECIAL_EFFECTS.MANA_OVERFLOW) ? 1.2 : 1.0; - const maxManaWithOverflow = maxMana * overflowMultiplier; - let rawMana = Math.min(state.rawMana + effectiveRegen * HOURS_PER_TICK, maxManaWithOverflow); + const hasVoidStorage = hasSpecial(effects, SPECIAL_EFFECTS.VOID_STORAGE); + const voidStorageMultiplier = hasVoidStorage ? 1.5 : 1.0; // VOID_STORAGE: Store 150% max + const maxManaStorage = maxMana * overflowMultiplier * voidStorageMultiplier; + + // MANA_GENESIS: Generate 1% of max mana per hour passively + let manaGenesisBonus = 0; + if (hasSpecial(effects, SPECIAL_EFFECTS.MANA_GENESIS)) { + manaGenesisBonus = maxMana * 0.01 * HOURS_PER_TICK; + } + + let rawMana = Math.min(state.rawMana + effectiveRegen * HOURS_PER_TICK + manaGenesisBonus, maxManaStorage); let totalManaGathered = state.totalManaGathered; // Attunement mana conversion - convert raw mana to attunement's primary mana type @@ -1706,11 +1719,18 @@ export const useGameStore = create()( spellsToKeep = learnedSpells.slice(0, state.skills.temporalMemory); } - // EMERGENCY_RESERVE: Keep 10% mana on new loop + // Compute effects for special checks const effects = computeEffects(state.skillUpgrades || {}, state.skillTiers || {}); + + // EMERGENCY_RESERVE: Keep 10% mana on new loop const hasEmergencyReserve = hasSpecial(effects, SPECIAL_EFFECTS.EMERGENCY_RESERVE); const maxMana = computeMaxMana(state, effects); const keepMana = hasEmergencyReserve ? Math.floor(maxMana * 0.10) : 0; + + // MANA_HEART: +10% max mana per loop (permanent bonus, compounds) + const hasManaHeart = hasSpecial(effects, SPECIAL_EFFECTS.MANA_HEART); + const currentHeartBonus = state.manaHeartBonus || 0; + const newHeartBonus = hasManaHeart ? currentHeartBonus + 0.10 : currentHeartBonus; const newState = makeInitial({ loopCount: state.loopCount + 1, @@ -1719,6 +1739,7 @@ export const useGameStore = create()( prestigeUpgrades: state.prestigeUpgrades, memories: state.memories, skills: state.skills, // Keep skills through temporal memory for now + manaHeartBonus: newHeartBonus, }); // Set the kept mana from EMERGENCY_RESERVE diff --git a/src/lib/game/store/computed.ts b/src/lib/game/store/computed.ts index 4b33fbd..e836f0c 100755 --- a/src/lib/game/store/computed.ts +++ b/src/lib/game/store/computed.ts @@ -19,12 +19,13 @@ export function getEffectiveSkillLevel( } export function computeMaxMana( - state: Pick, + state: Pick, effects?: ReturnType ): number { const pu = state.prestigeUpgrades; const skillTiers = state.skillTiers || {}; const skillUpgrades = state.skillUpgrades || {}; + const manaHeartBonus = state.manaHeartBonus || 0; const manaWellLevel = getEffectiveSkillLevel(state.skills, 'manaWell', skillTiers); @@ -34,7 +35,9 @@ export function computeMaxMana( (pu.manaWell || 0) * 500; const computedEffects = effects ?? computeEffects(skillUpgrades, skillTiers); - return Math.floor((base + computedEffects.maxManaBonus) * computedEffects.maxManaMultiplier); + // Apply MANA_HEART bonus (+10% per loop, compounds) + const heartMultiplier = 1 + manaHeartBonus; + return Math.floor((base + computedEffects.maxManaBonus) * computedEffects.maxManaMultiplier * heartMultiplier); } export function computeElementMax( diff --git a/src/lib/game/types/game.ts b/src/lib/game/types/game.ts index 974379d..be3b505 100644 --- a/src/lib/game/types/game.ts +++ b/src/lib/game/types/game.ts @@ -192,6 +192,9 @@ export interface GameState { memorySlots: number; memories: string[]; + // Mana Well Effects (Phase 4) + manaHeartBonus: number; // Cumulative +10% max mana per loop from MANA_HEART + // Incursion incursionStrength: number; containmentWards: number; diff --git a/src/lib/game/upgrade-effects.ts b/src/lib/game/upgrade-effects.ts index f7b12d1..db57bc4 100755 --- a/src/lib/game/upgrade-effects.ts +++ b/src/lib/game/upgrade-effects.ts @@ -363,6 +363,22 @@ export function computeDynamicRegen( regen *= 2.0; } + // Deep Reserve: +0.5 regen per 100 max mana + if (hasSpecial(effects, SPECIAL_EFFECTS.DEEP_RESERVE)) { + regen += Math.floor(maxMana / 100) * 0.5; + } + + // Mana Core: 0.5% of max mana added as regen + if (hasSpecial(effects, SPECIAL_EFFECTS.MANA_CORE)) { + regen += maxMana * 0.005; + } + + // Mana Tide: Regen pulses ±50% (sinusoidal based on time) + if (hasSpecial(effects, SPECIAL_EFFECTS.MANA_TIDE)) { + const pulseFactor = 0.5 + 0.5 * Math.sin(Date.now() / 10000); // 10 second cycles + regen *= (0.5 + pulseFactor * 0.5); // Range: 0.5x to 1.0x + } + // Eternal Flow: Regen immune to ALL penalties (stronger than Steady Stream) if (hasSpecial(effects, SPECIAL_EFFECTS.ETERNAL_FLOW)) { return regen * effects.regenMultiplier; @@ -392,6 +408,12 @@ export function computeDynamicClickMana( // Note: The chance is handled in the click handler, this just returns the base // The click handler should check hasSpecial and apply the 10% chance + // Mana Genesis: Generate 1% of max mana per hour passively + // This is handled in the game loop (store.ts), not here + + // Mana Heart: +10% max mana per loop (permanent) + // This is applied during loop reset in store.ts + return Math.floor((clickMana + effects.clickManaBonus) * effects.clickManaMultiplier); }