Files
Mana-Loop/src/lib/game/effects/dynamic-compute.ts
T
n8n-gitea 48a5ad1855
Build and Publish Mana Loop Docker Image / build-and-publish (push) Successful in 1m24s
fix: 6 priority-3 bug fixes with regression tests
- Issue 83: Mana Tide pulse factor now ranges 0.5x-1.5x (was 0.5x-1.0x)
- Issue 82: SteadyStream no longer returns early like EternalFlow; only skips incursion penalty
- Issue 81: Prestige store partialize now includes defeatedGuardians, signedPacts, signedPactDetails, pactRitualFloor, pactRitualProgress, loopInsight, pactSlots
- Issue 80: Combat store partialize now includes floorHP, floorMaxHP, castProgress, spireMode, clearedFloors, golemancy, equipmentSpellStates, activityLog, achievements
- Issue 78: cancelDesign now always cancels designProgress first, then designProgress2
- Issue 79: startDesigningEnchantment now uses designProgress2 when designProgress is occupied

Added 13 regression tests in src/lib/game/__tests__/regression-fixes.test.ts
Refactored craftingStore types to craftingStore.types.ts to stay under 400-line limit
2026-05-19 11:19:10 +02:00

125 lines
4.0 KiB
TypeScript

// ─── Dynamic Computations ──────────────────────────────────────────────────
// Dynamic computation functions that depend on special effects
import type { ComputedEffects } from './upgrade-effects.types';
import { SPECIAL_EFFECTS, hasSpecial } from './special-effects';
/**
* Compute regen with special effects that depend on dynamic values
*/
export function computeDynamicRegen(
effects: ComputedEffects,
baseRegen: number,
maxMana: number,
currentMana: number,
incursionStrength: number
): number {
let regen = baseRegen;
// Mana Cascade: +0.1 regen per 100 max mana
if (hasSpecial(effects, SPECIAL_EFFECTS.MANA_CASCADE)) {
regen += Math.floor(maxMana / 100) * 0.1;
}
// Mana Waterfall: +0.25 regen per 100 max mana (upgraded cascade)
if (hasSpecial(effects, SPECIAL_EFFECTS.MANA_WATERFALL)) {
regen += Math.floor(maxMana / 100) * 0.25;
}
// Mana Torrent: +50% regen when above 75% mana
if (hasSpecial(effects, SPECIAL_EFFECTS.MANA_TORRENT) && currentMana > maxMana * 0.75) {
regen *= 1.5;
}
// Desperate Wells / Despair Wells: +50% regen when below 25% mana
if ((hasSpecial(effects, SPECIAL_EFFECTS.DESPERATE_WELLS) || hasSpecial(effects, SPECIAL_EFFECTS.DESPAIR_WELLS)) && currentMana < maxMana * 0.25) {
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;
}
// 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)) {
regen *= (1.0 + 0.5 * Math.sin(Date.now() / 10000));
}
// Eternal Flow: Regen immune to ALL penalties
if (hasSpecial(effects, SPECIAL_EFFECTS.ETERNAL_FLOW)) {
return regen * effects.regenMultiplier;
}
// Steady Stream: Regen immune to incursion (skip incursion penalty only)
if (hasSpecial(effects, SPECIAL_EFFECTS.STEADY_STREAM)) {
// incursion penalty is skipped, but regenMultiplier still applies below
} else {
// Apply incursion penalty
regen *= (1 - incursionStrength);
}
return regen * effects.regenMultiplier;
}
/**
* Compute click mana with special effects
*/
export function computeDynamicClickMana(
effects: ComputedEffects,
baseClickMana: number
): number {
let clickMana = baseClickMana;
// Mana Echo: 10% chance to gain double mana from clicks
// 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);
}
/**
* Compute damage with special effects
*/
export function computeDynamicDamage(
effects: ComputedEffects,
baseDamage: number,
floorHPPct: number,
currentMana: number,
maxMana: number
): number {
let damage = baseDamage * effects.baseDamageMultiplier;
// Overpower: +50% damage when mana above 80%
if (hasSpecial(effects, SPECIAL_EFFECTS.OVERPOWER) && currentMana >= maxMana * 0.8) {
damage *= 1.5;
}
// Berserker: +50% damage when below 50% mana
if (hasSpecial(effects, SPECIAL_EFFECTS.BERSERKER) && currentMana < maxMana * 0.5) {
damage *= 1.5;
}
// Combo Master: Every 5th attack deals 3x damage
// Note: The hit counter is tracked in game state, this just returns the multiplier
// The combat handler should check hasSpecial and the hit count
return damage + effects.baseDamageBonus;
}