Phase 4: Mana Well effects (1st 7)

This commit is contained in:
Refactoring Agent
2026-04-24 16:17:50 +02:00
parent 6e3b867e7d
commit 132a4e6a72
3 changed files with 46 additions and 7 deletions
+25 -3
View File
@@ -298,7 +298,7 @@ function getEffectiveSkillLevel(
} }
export function computeMaxMana( export function computeMaxMana(
state: Pick<GameState, 'skills' | 'prestigeUpgrades' | 'skillUpgrades' | 'skillTiers' | 'equipmentInstances' | 'equippedInstances'>, state: Pick<GameState, 'skills' | 'prestigeUpgrades' | 'skillUpgrades' | 'skillTiers' | 'equipmentInstances' | 'equippedInstances' | 'totalManaGathered'>,
effects?: ComputedEffects | UnifiedEffects effects?: ComputedEffects | UnifiedEffects
): number { ): number {
const pu = state.prestigeUpgrades; const pu = state.prestigeUpgrades;
@@ -313,10 +313,21 @@ export function computeMaxMana(
} }
// Apply effects if available (now includes equipment bonuses) // Apply effects if available (now includes equipment bonuses)
let maxMana: number;
if (effects) { if (effects) {
return Math.floor((base + effects.maxManaBonus) * effects.maxManaMultiplier); maxMana = Math.floor((base + effects.maxManaBonus) * effects.maxManaMultiplier);
} else {
maxMana = base;
} }
return base;
// MANA_CONDENSE: +1% max mana per 1000 total mana gathered
if (effects && hasSpecial(effects, SPECIAL_EFFECTS.MANA_CONDENSE)) {
const totalGathered = state.totalManaGathered || 0;
const condensesBonus = Math.floor(totalGathered / 1000);
maxMana = Math.floor(maxMana * (1 + condensesBonus * 0.01));
}
return maxMana;
} }
export function computeElementMax( export function computeElementMax(
@@ -1695,6 +1706,12 @@ export const useGameStore = create<GameStore>()(
spellsToKeep = learnedSpells.slice(0, state.skills.temporalMemory); spellsToKeep = learnedSpells.slice(0, state.skills.temporalMemory);
} }
// EMERGENCY_RESERVE: Keep 10% mana on new loop
const effects = computeEffects(state.skillUpgrades || {}, state.skillTiers || {});
const hasEmergencyReserve = hasSpecial(effects, SPECIAL_EFFECTS.EMERGENCY_RESERVE);
const maxMana = computeMaxMana(state, effects);
const keepMana = hasEmergencyReserve ? Math.floor(maxMana * 0.10) : 0;
const newState = makeInitial({ const newState = makeInitial({
loopCount: state.loopCount + 1, loopCount: state.loopCount + 1,
insight: total, insight: total,
@@ -1704,6 +1721,11 @@ export const useGameStore = create<GameStore>()(
skills: state.skills, // Keep skills through temporal memory for now skills: state.skills, // Keep skills through temporal memory for now
}); });
// Set the kept mana from EMERGENCY_RESERVE
if (keepMana > 0) {
newState.rawMana = keepMana;
}
// Add kept spells // Add kept spells
if (spellsToKeep.length > 0) { if (spellsToKeep.length > 0) {
spellsToKeep.forEach(spellId => { spellsToKeep.forEach(spellId => {
+6 -1
View File
@@ -5,7 +5,7 @@ import type { StateCreator } from 'zustand';
import type { GameState, ElementState, SpellCost } from '../types'; import type { GameState, ElementState, SpellCost } from '../types';
import { ELEMENTS, MANA_PER_ELEMENT, BASE_UNLOCKED_ELEMENTS } from '../constants'; import { ELEMENTS, MANA_PER_ELEMENT, BASE_UNLOCKED_ELEMENTS } from '../constants';
import { computeMaxMana, computeElementMax, computeClickMana, canAffordSpellCost, getMeditationBonus } from './computed'; import { computeMaxMana, computeElementMax, computeClickMana, canAffordSpellCost, getMeditationBonus } from './computed';
import { computeEffects } from '../upgrade-effects'; import { computeEffects, hasSpecial, SPECIAL_EFFECTS } from '../upgrade-effects';
export interface ManaSlice { export interface ManaSlice {
// State // State
@@ -67,6 +67,11 @@ export const createManaSlice = (
const effects = computeEffects(state.skillUpgrades || {}, state.skillTiers || {}); const effects = computeEffects(state.skillUpgrades || {}, state.skillTiers || {});
const max = computeMaxMana(state, effects); const max = computeMaxMana(state, effects);
// Mana Conversion: Convert 5% of max mana to click bonus
if (hasSpecial(effects, SPECIAL_EFFECTS.MANA_CONVERSION)) {
cm += Math.floor(max * 0.05);
}
// Mana Echo: 10% chance to gain double mana from clicks // Mana Echo: 10% chance to gain double mana from clicks
const hasManaEcho = effects.specials?.has('MANA_ECHO') ?? false; const hasManaEcho = effects.specials?.has('MANA_ECHO') ?? false;
if (hasManaEcho && Math.random() < 0.1) { if (hasManaEcho && Math.random() < 0.1) {
+15 -3
View File
@@ -72,7 +72,8 @@ export const SPECIAL_EFFECTS = {
ETERNAL_FLOW: 'eternalFlow', // Regen immune to all penalties ETERNAL_FLOW: 'eternalFlow', // Regen immune to all penalties
// Mana Well special effects // Mana Well special effects
DESPERATE_WELLS: 'desperateWells', // +50% regen when below 25% mana DESPAIR_WELLS: 'despairWells', // +50% regen when below 25% mana (task name)
DESPERATE_WELLS: 'desperateWells', // +50% regen when below 25% mana (legacy name)
MANA_ECHO: 'manaEcho', // 10% chance double mana from clicks MANA_ECHO: 'manaEcho', // 10% chance double mana from clicks
EMERGENCY_RESERVE: 'emergencyReserve', // Keep 10% mana on new loop EMERGENCY_RESERVE: 'emergencyReserve', // Keep 10% mana on new loop
MANA_THRESHOLD: 'manaThreshold', // +30% max mana, -10% regen trade-off MANA_THRESHOLD: 'manaThreshold', // +30% max mana, -10% regen trade-off
@@ -309,6 +310,12 @@ export function computeEffects(
} }
} }
// MANA_THRESHOLD: +30% max mana, -10% regen trade-off
if (hasSpecial(effects, SPECIAL_EFFECTS.MANA_THRESHOLD)) {
effects.maxManaMultiplier *= 1.30;
effects.regenMultiplier *= 0.90;
}
return effects; return effects;
} }
@@ -346,11 +353,16 @@ export function computeDynamicRegen(
regen *= 1.5; regen *= 1.5;
} }
// Desperate Wells: +50% regen when below 25% mana // Desperate Wells / Despair Wells: +50% regen when below 25% mana
if (hasSpecial(effects, SPECIAL_EFFECTS.DESPERATE_WELLS) && currentMana < maxMana * 0.25) { if ((hasSpecial(effects, SPECIAL_EFFECTS.DESPERATE_WELLS) || hasSpecial(effects, SPECIAL_EFFECTS.DESPAIR_WELLS)) && currentMana < maxMana * 0.25) {
regen *= 1.5; regen *= 1.5;
} }
// Panic Reserve: +100% regen when below 10% mana
if (hasSpecial(effects, SPECIAL_EFFECTS.PANIC_RESERVE) && currentMana < maxMana * 0.1) {
regen *= 2.0;
}
// Eternal Flow: Regen immune to ALL penalties (stronger than Steady Stream) // Eternal Flow: Regen immune to ALL penalties (stronger than Steady Stream)
if (hasSpecial(effects, SPECIAL_EFFECTS.ETERNAL_FLOW)) { if (hasSpecial(effects, SPECIAL_EFFECTS.ETERNAL_FLOW)) {
return regen * effects.regenMultiplier; return regen * effects.regenMultiplier;