feat: overhaul mana conversion system to unified regen-deduction model
Build and Publish Mana Loop Docker Image / build-and-publish (push) Failing after 1m2s
Build and Publish Mana Loop Docker Image / build-and-publish (push) Failing after 1m2s
- New files: element-distance.ts, conversion-costs.ts, conversion-rates.ts - All conversion types (discipline, attunement, pact) use unified formula - Conversion costs scale exponentially by element tier (10^(d+1) raw, 10*(d+1) per component) - Costs deducted from regen, not from mana pool - Auto-pause on insufficient regen with UI warning - Meditation boosts conversion rates (reduced by distance) - Attunement levels provide +50% multiplicative bonus per level - Guardian pacts provide +0.15/hr base rate + invoker level bonus - Removed convertMana, processConvertAction, craftComposite from manaStore - Stats tab shows per-element conversion breakdown with formulas - ManaDisplay shows per-element net regen rates - All 916 tests pass, all files under 400 lines
This commit is contained in:
@@ -1,5 +1,9 @@
|
||||
// ─── Discipline Effects ───────────────────────────────────────────────────────
|
||||
// Computes bonuses from active disciplines and integrates with the unified effect system
|
||||
//
|
||||
// NEW MODEL: Conversion disciplines contribute to conversion_{element} stat bonuses.
|
||||
// The unified conversion-rates.ts calculator handles rate computation and regen deduction.
|
||||
// This file no longer builds a direct conversions map for the tick pipeline.
|
||||
|
||||
import type { DisciplineStoreState } from '../stores/discipline-slice';
|
||||
import type { DisciplineState } from '../types/disciplines';
|
||||
@@ -32,21 +36,40 @@ const KNOWN_BONUS_STATS = new Set([
|
||||
'disciplineXpBonus',
|
||||
'clickManaMultiplier',
|
||||
'studySpeed',
|
||||
// Conversion stat bonuses (one per element)
|
||||
'conversion_fire',
|
||||
'conversion_water',
|
||||
'conversion_air',
|
||||
'conversion_earth',
|
||||
'conversion_light',
|
||||
'conversion_dark',
|
||||
'conversion_death',
|
||||
'conversion_transference',
|
||||
'conversion_metal',
|
||||
'conversion_sand',
|
||||
'conversion_lightning',
|
||||
'conversion_frost',
|
||||
'conversion_blackflame',
|
||||
'conversion_radiantflames',
|
||||
'conversion_miasma',
|
||||
'conversion_shadowglass',
|
||||
'conversion_crystal',
|
||||
'conversion_stellar',
|
||||
'conversion_void',
|
||||
'conversion_soul',
|
||||
'conversion_plasma',
|
||||
'conversion_time',
|
||||
]);
|
||||
|
||||
export interface DisciplineEffectsResult {
|
||||
bonuses: Record<string, number>;
|
||||
multipliers: Record<string, number>;
|
||||
specials: Set<string>;
|
||||
/**
|
||||
* Bonus to the meditation multiplier cap from disciplines.
|
||||
* Each point of meditationCapBonus adds +0.5 to the max meditation multiplier.
|
||||
*/
|
||||
meditationCapBonus: number;
|
||||
/**
|
||||
* Conversion entries: for each active discipline with a conversionRate,
|
||||
* maps target mana type → { rate, sourceManaTypes }.
|
||||
* The tick pipeline drains source mana types and adds to the target.
|
||||
* Used by the unified conversion calculator for rate computation.
|
||||
*/
|
||||
conversions: Record<string, { rate: number; sourceManaTypes: string[] }>;
|
||||
}
|
||||
@@ -77,15 +100,15 @@ export function computeDisciplineEffects(_state?: DisciplineStoreState): Discipl
|
||||
}
|
||||
|
||||
for (const { disc, def } of activeDiscs) {
|
||||
// Continuous stat bonus
|
||||
// Continuous stat bonus (includes conversion_{element} for regen disciplines)
|
||||
const statBonus = calculateStatBonus(def.statBonus.baseValue, disc.xp, def.scalingFactor);
|
||||
if (def.statBonus.stat) {
|
||||
addBonus(def.statBonus.stat, statBonus);
|
||||
}
|
||||
|
||||
// Conversion entry — if this discipline defines conversionRate
|
||||
// This is used by the unified conversion calculator
|
||||
if (def.conversionRate && def.sourceManaTypes && def.sourceManaTypes.length > 0) {
|
||||
// Scale the conversion rate by the stat bonus multiplier
|
||||
const scaledRate = def.conversionRate + statBonus;
|
||||
conversions[def.manaType] = {
|
||||
rate: scaledRate,
|
||||
@@ -102,7 +125,6 @@ export function computeDisciplineEffects(_state?: DisciplineStoreState): Discipl
|
||||
} else if (!perk.unlocksEffects) {
|
||||
specials.add(perk.id);
|
||||
}
|
||||
// Perks with unlocksEffects are handled by discipline-slice.ts processTick()
|
||||
} else if (perk.type === 'infinite') {
|
||||
if (perk.bonus) {
|
||||
const interval = perk.value;
|
||||
|
||||
Reference in New Issue
Block a user