Phase 4: Mana Well effects (remaining 7)

This commit is contained in:
Refactoring Agent
2026-04-24 16:37:55 +02:00
parent 132a4e6a72
commit 75a43c7209
4 changed files with 55 additions and 6 deletions
+25 -4
View File
@@ -563,6 +563,7 @@ function makeInitial(overrides: Partial<GameState> = {}): 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<string, { current: number; max: number; unlocked: boolean }> = {};
Object.keys(ELEMENTS).forEach((k) => {
@@ -732,6 +733,9 @@ function makeInitial(overrides: Partial<GameState> = {}): 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<GameStore>()(
}
}
// 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,12 +1719,19 @@ export const useGameStore = create<GameStore>()(
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,
insight: total,
@@ -1719,6 +1739,7 @@ export const useGameStore = create<GameStore>()(
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
+5 -2
View File
@@ -19,12 +19,13 @@ export function getEffectiveSkillLevel(
}
export function computeMaxMana(
state: Pick<GameState, 'skills' | 'prestigeUpgrades' | 'skillUpgrades' | 'skillTiers'>,
state: Pick<GameState, 'skills' | 'prestigeUpgrades' | 'skillUpgrades' | 'skillTiers' | 'manaHeartBonus'>,
effects?: ReturnType<typeof computeEffects>
): 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(
+3
View File
@@ -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;
+22
View File
@@ -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);
}