fix: apply mana drain when practicing disciplines
Build and Publish Mana Loop Docker Image / build-and-publish (push) Successful in 1m25s
Build and Publish Mana Loop Docker Image / build-and-publish (push) Successful in 1m25s
- processTick() now calls calculateManaDrain() for non-conversion disciplines - Insufficient mana triggers auto-paused state (skips XP accrual) - Conversion disciplines (sourceManaTypes) correctly skip pool drain - Auto-paused disciplines can be re-activated when mana is restored - Updated 7 tests across 3 files to reflect drain model
This commit is contained in:
@@ -6,6 +6,7 @@ import type { DisciplineState } from '../types/disciplines';
|
||||
import type { ElementState } from '../types';
|
||||
import {
|
||||
calculateStatBonus,
|
||||
calculateManaDrain,
|
||||
canProceedDiscipline,
|
||||
checkDisciplinePrerequisites,
|
||||
getUnlockedPerks
|
||||
@@ -85,12 +86,18 @@ export const useDisciplineStore = create<DisciplineStore>()(
|
||||
// Allow re-activation if discipline exists but is paused
|
||||
const existing = s.disciplines[id];
|
||||
if (activeIds.includes(id)) {
|
||||
// If already active and paused (manually or auto), un-pause it
|
||||
// If already active and paused (manually or auto-paused due to insufficient mana), un-pause it
|
||||
if (existing?.paused) {
|
||||
return {
|
||||
disciplines: { ...s.disciplines, [id]: { ...existing, paused: false, autoPaused: false } },
|
||||
};
|
||||
}
|
||||
// If auto-paused due to insufficient mana, allow re-activation (un-pause when mana is restored)
|
||||
if (existing?.autoPaused) {
|
||||
return {
|
||||
disciplines: { ...s.disciplines, [id]: { ...existing, autoPaused: false } },
|
||||
};
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
@@ -170,13 +177,14 @@ export const useDisciplineStore = create<DisciplineStore>()(
|
||||
|
||||
processTick(mana) {
|
||||
const s = get();
|
||||
const rawMana = mana.rawMana;
|
||||
let rawMana = mana.rawMana;
|
||||
const elements = { ...mana.elements };
|
||||
let newXP = s.totalXP;
|
||||
const newDisciplines = { ...s.disciplines };
|
||||
const newUnlockedEffects: string[] = [];
|
||||
const newUnlockedRecipes: string[] = [];
|
||||
const newProcessedPerks = [...(s.processedPerks ?? [])];
|
||||
const autoPausedNames: string[] = [];
|
||||
|
||||
for (const id of s.activeIds ?? []) {
|
||||
const disc = newDisciplines[id];
|
||||
@@ -187,6 +195,40 @@ export const useDisciplineStore = create<DisciplineStore>()(
|
||||
const def = DISCIPLINE_MAP[id];
|
||||
if (!def) continue;
|
||||
|
||||
// ── Mana drain (skip for conversion disciplines) ──────────────
|
||||
// Conversion disciplines (with sourceManaTypes) are handled by
|
||||
// the unified conversion system — they contribute to conversion
|
||||
// rates, not direct pool drain.
|
||||
const isConversionDiscipline = !!(def.sourceManaTypes && def.sourceManaTypes.length > 0);
|
||||
|
||||
if (!isConversionDiscipline) {
|
||||
const drain = calculateManaDrain(def.drainBase, disc.xp, def.difficultyFactor);
|
||||
|
||||
// Determine which mana pool to drain from
|
||||
if (def.manaType === 'raw') {
|
||||
if (rawMana < drain) {
|
||||
// Insufficient raw mana — auto-pause
|
||||
newDisciplines[id] = { ...disc, autoPaused: true };
|
||||
autoPausedNames.push(def.name);
|
||||
continue; // skip XP accrual
|
||||
}
|
||||
rawMana = Math.max(0, rawMana - drain);
|
||||
} else {
|
||||
// Element-specific drain
|
||||
const elemState = elements[def.manaType];
|
||||
if (!elemState || elemState.current < drain) {
|
||||
// Insufficient element mana — auto-pause
|
||||
newDisciplines[id] = { ...disc, autoPaused: true };
|
||||
autoPausedNames.push(def.name);
|
||||
continue; // skip XP accrual
|
||||
}
|
||||
elements[def.manaType] = {
|
||||
...elemState,
|
||||
current: Math.max(0, elemState.current - drain),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const oldXP = disc.xp;
|
||||
// Compute discipline XP bonus directly to avoid circular import
|
||||
let xpBonus = 0;
|
||||
@@ -255,7 +297,7 @@ export const useDisciplineStore = create<DisciplineStore>()(
|
||||
processedPerks: newProcessedPerks,
|
||||
});
|
||||
|
||||
return { rawMana, elements, unlockedEffects: newUnlockedEffects, unlockedRecipes: newUnlockedRecipes, autoPausedNames: [] };
|
||||
return { rawMana, elements, unlockedEffects: newUnlockedEffects, unlockedRecipes: newUnlockedRecipes, autoPausedNames };
|
||||
},
|
||||
}),
|
||||
{ storage: createSafeStorage(), name: 'mana-loop-discipline-store', version: 1, partialize: (state) => ({ disciplines: state.disciplines, activeIds: state.activeIds, concurrentLimit: state.concurrentLimit, totalXP: state.totalXP, processedPerks: state.processedPerks }) }
|
||||
|
||||
Reference in New Issue
Block a user