16 KiB
Mana Conversion System — Specification
Overview
This spec defines a unified mana conversion system that replaces the current fragmented approach (attunement conversions, discipline conversions, manual conversion, and guardian pact conversions). All conversion types use the same core mechanics: consuming source mana types to produce a destination mana type, with costs deducted from regen (not from the mana pool directly).
1. Element Distance from Raw Mana
Every mana type has a distance from raw mana. This value is used in two places:
- Calculating conversion cost ratios
- Calculating meditation multiplier strength for that element's conversion
Distance Table
| Element | Category | Distance |
|---|---|---|
| Raw | — | 0 |
| Fire, Water, Air, Earth, Light, Dark, Death | Base | 1 |
| Transference | Utility | 1 |
| Metal, Sand, Lightning, Frost, BlackFlame, RadiantFlames, Miasma, ShadowGlass | Composite | 2 |
| Crystal, Stellar, Void, Soul, Plasma | Exotic (tier 1) | 3 |
| Time | Exotic (tier 2) | 4 |
Reusable Function
// src/lib/game/utils/element-distance.ts
export function getElementDistance(elementId: string): number
Returns the distance for any element. If a composite element's recipe contains components at different distances, the element's distance = max(component distances) + 1.
2. Conversion Cost Ratios
All conversions produce 1 unit of destination mana. The cost depends on the destination's distance from raw.
Cost Formula
For a destination element at distance d:
-
Raw mana cost =
10^(d+1)- Distance 1 (base):
10^2 = 100raw per 1 element - Distance 2 (composite):
10^3 = 1,000raw per 1 element - Distance 3 (exotic):
10^4 = 10,000raw per 1 element - Distance 4 (time):
10^5 = 100,000raw per 1 element
- Distance 1 (base):
-
Each component mana cost =
10 * (d + 1)per 1 destination element- Distance 1:
10 * 2 = 20of that element per 1 destination - Distance 2:
10 * 3 = 30of that element per 1 destination - Distance 3:
10 * 4 = 40of that element per 1 destination - Distance 4:
10 * 5 = 50of that element per 1 destination
- Distance 1:
Cost Table (per 1 unit of destination mana)
| Destination | Distance | Raw Cost | Each Component Cost | Components |
|---|---|---|---|---|
| Fire (base) | 1 | 100 | — | — |
| Transference | 1 | 100 | — | — |
| Metal | 2 | 1,000 | 30 fire + 30 earth | fire, earth |
| Sand | 2 | 1,000 | 30 earth + 30 water | earth, water |
| Lightning | 2 | 1,000 | 30 fire + 30 air | fire, air |
| Frost | 2 | 1,000 | 30 air + 30 water | air, water |
| BlackFlame | 2 | 1,000 | 30 dark + 30 fire | dark, fire |
| Radiant Flames | 2 | 1,000 | 30 light + 30 fire | light, fire |
| Miasma | 2 | 1,000 | 30 air + 30 death | air, death |
| Shadow Glass | 2 | 1,000 | 30 earth + 30 dark | earth, dark |
| Crystal | 3 | 10,000 | 40 sand + 40 light | sand, light |
| Stellar | 3 | 10,000 | 40 plasma + 40 light | plasma, light |
| Void | 3 | 10,000 | 40 dark + 40 death | dark, death |
| Soul | 3 | 10,000 | 40 light + 40 dark + 40 transference | light, dark, transference |
| Plasma | 3 | 10,000 | 40 lightning + 40 fire + 40 transference | lightning, fire, transference |
| Time | 4 | 100,000 | 50 soul + 50 sand + 50 transference | soul, sand, transference |
Key Constraint
Raw mana cost is always greater than any individual component cost. This is inherent in the formula: 10^(d+1) for raw vs 10*(d+1) for each component.
3. Conversion Rate — Unified Formula
All three sources (disciplines, attunements, guardian pacts) contribute to a single base conversion rate for each element. This rate is then exponentially boosted by attunement levels and pact bonuses.
Formula
finalRate = (disciplineRate + attunementBaseRate + pactBaseRate) ^ (1 + attunementLevelBonus + pactLevelBonus)
Where:
disciplineRate= sum of conversion rates from active disciplines for this element (see §4)attunementBaseRate= sum of base conversion rates from attunements for this element (see §5)pactBaseRate= sum of base conversion rates from guardian pacts for this element (see §6)attunementLevelBonus= sum of relevant attunement levels (e.g., Enchanter level for transference, Fabricator level for earth)pactLevelBonus= count of pacts with guardians that have this element as primary × Invoker attunement level
Example
A player with:
- Fire Conversion discipline active (rate = 0.5)
- Enchanter attunement level 3 (no fire base rate, but level contributes to exponent if fire is the attunement's primary)
- Fabricator attunement level 2 (earth primary, so contributes to earth conversions)
- 2 fire-type guardian pacts, Invoker level 3
For fire mana conversion:
baseRate = 0.5 (discipline) + 0 (no attunement base for fire) + 0 (no pact base for fire)
exponent = 1 + 0 (no attunement has fire as primary) + 0 (no fire-type pact bonus)
finalRate = 0.5^1 = 0.5/hr
For metal mana conversion (fire + earth):
baseRate = 0.35 (metal discipline) + 0 (no attunement base) + 0 (no pact base)
exponent = 1 + 2 (Fabricator level 2, earth is a component of metal) + 0
finalRate = 0.35^3 = 0.0429/hr
Wait — this produces lower rates at higher levels, which is wrong. The exponent should be a multiplier, not an exponent on the rate. Let me restate:
Corrected Formula
finalRate = (disciplineRate + attunementBaseRate + pactBaseRate) × (1 + attunementLevelBonus + pactLevelBonus)
Where the multiplier is additive:
attunementLevelBonus= sum of relevant attunement levels × 0.5 (each level adds +50% to rate)pactLevelBonus= count of pacts with this element × Invoker level × 0.25
So:
finalRate = baseRate × (1 + Σ(attunementLevel_i × 0.5) + Σ(pactCount_element × invokerLevel × 0.25))
Revised Example
For metal mana with Metal Conversion discipline (0.35/hr), Fabricator level 2:
baseRate = 0.35
multiplier = 1 + (2 × 0.5) = 2.0
finalRate = 0.35 × 2.0 = 0.70/hr
For transference mana with Transference Conversion discipline (0.4/hr), Enchanter level 3:
baseRate = 0.4
multiplier = 1 + (3 × 0.5) = 2.5
finalRate = 0.4 × 2.5 = 1.0/hr
4. Discipline Contributions
Each conversion discipline provides a base rate that scales with XP.
Base Rates (per hour)
| Element | Base Rate | Difficulty Factor | Scaling Factor |
|---|---|---|---|
| Fire, Water, Air, Earth, Light, Dark, Death | 0.5 | 120 | 60 |
| Transference | 0.4 | 100 | 50 |
| Metal, Sand, Lightning, Frost | 0.35 | 160 | 80 |
| BlackFlame, RadiantFlames, Miasma, ShadowGlass | 0.30 | 170 | 85 |
| Crystal, Void | 0.25 | 220 | 110 |
| Stellar, Soul, Plasma | 0.20 | 240 | 120 |
| Time | 0.15 | 260 | 130 |
XP Scaling
The discipline's effective rate bonus follows the standard stat bonus formula:
statBonus = baseValue × (XP / scalingFactor)^0.65
The discipline's total contribution to the base rate is:
disciplineRate = baseRate + statBonus
Perks
Each discipline has perks that add flat bonuses to the rate:
onceperk: grants+baseRateto the conversion rate at threshold XPinfiniteperk: every N XP grants+baseRate × 0.5to the conversion rate
5. Attunement Contributions
Attunements provide a base conversion rate for their primary mana type, plus a level-based multiplier to all conversions involving their element.
Attunement Base Rates
| Attunement | Primary Mana | Base Rate (per hour) |
|---|---|---|
| Enchanter | Transference | 0.2 |
| Fabricator | Earth | 0.25 |
| Invoker | None | 0 |
Attunement Level Multiplier
Each attunement level adds +0.5 to the multiplier for conversions where the attunement's primary element is either:
- The destination element, OR
- A component element of the destination
Example: Fabricator (earth) level 3 boosts:
- Earth conversions (earth is destination)
- Metal conversions (earth is component)
- Sand conversions (earth is component)
- Shadow Glass conversions (earth is component)
But NOT fire conversions (earth is not involved).
6. Guardian Pact Contributions
Guardian pacts provide:
- A base conversion rate for the guardian's element
- A level bonus to the multiplier, scaled by Invoker attunement level
Pact Base Rate
Each signed pact grants +0.15/hr base rate for the guardian's primary element.
Pact Level Bonus
For each signed pact whose guardian has element E as primary:
pactLevelBonus_E += invokerLevel × 0.25
So an Invoker at level 4 with 2 fire-type pacts grants:
pactLevelBonus_fire = 2 × 4 × 0.25 = 2.0
This adds to the multiplier for fire conversions and any composite that uses fire.
7. Meditation Multiplier
Meditation boosts conversion rates, but the boost is reduced for elements further from raw.
Formula
meditationBoost = 1 + (meditationMultiplier - 1) / distance
Where distance is the destination element's distance from raw mana.
| Element Distance | Meditation Strength |
|---|---|
| 1 (base) | Full: meditationMultiplier |
| 2 (composite) | Half: 1 + (med - 1) / 2 |
| 3 (exotic) | Third: 1 + (med - 1) / 3 |
| 4 (time) | Quarter: 1 + (med - 1) / 4 |
For elements with components at different distances, use the highest distance value (i.e., the weakest meditation boost).
8. Regen Deduction Model
All conversion costs are deducted from mana regen, not from the mana pool directly. This means:
- Each element has a gross regen (from attunements, upgrades, etc.)
- Conversions that consume this element as a source reduce the effective regen
- The remaining regen is the net regen that actually adds to the pool
Raw Mana
rawNetRegen = rawGrossRegen
- Σ (conversionRate_destination × rawCost_destination) for all active conversions
Element Mana (e.g., fire)
fireNetRegen = fireGrossRegen
+ fireProducedRate (from raw→fire conversion)
- Σ (conversionRate_destination × fireCost_destination) for all conversions using fire as component
Display Format
Each element's regen display shows:
Fire Mana Regen:
+0.50/hr converted from raw mana (Fire Conversion discipline, rate × attunement multiplier × meditation)
-0.15/hr being converted into Metal mana (30 per unit × 0.005 units/hr)
-0.10/hr being converted into Lightning mana (30 per unit × 0.0033 units/hr)
─────────────────
+0.25/hr net fire mana regen
9. Insufficient Regen — Auto-Pause
If a conversion's source cost exceeds the gross regen of that source type, the conversion is completely disabled (not partially throttled).
Conditions
A conversion for element E is paused if:
conversionRate_E × sourceCost_source > sourceGrossRegen
for any source type (raw or component element) in the conversion.
UI Warning
When a conversion is paused due to insufficient regen:
- The conversion's entry in the stats tab shows a red warning: "⚠️ PAUSED: Insufficient [source] regen (need X/hr, have Y/hr)"
- The mana display for the source element shows a warning icon next to the draining conversion
Auto-Resume
When regen increases (e.g., attunement levels up, new discipline XP gained, meditation active), paused conversions automatically resume if the regen now covers the cost.
10. No Manual Conversion
The existing convertMana action and processConvertAction are removed. All mana conversion happens passively through the unified system. The "convert" player action is removed from the action buttons.
11. Stats Tab Display
The Stats tab includes a new Conversion Stats section showing:
Per-Element Conversion Table
For each element with active conversions:
┌─────────────────────────────────────────────────────────────┐
│ 🔥 FIRE MANA CONVERSION │
│ │
│ Base Rate: 0.50/hr (Fire Conversion discipline) │
│ Attunement Bonus: ×1.00 (no attunement for fire) │
│ Pact Bonus: ×1.00 (0 fire-type pacts) │
│ Meditation: ×1.00 (not meditating) │
│ ───────────────────────────────────────── │
│ Effective Rate: 0.50/hr → produces 0.50 fire/hr │
│ │
│ Costs (deducted from raw regen): │
│ Raw: 100 × 0.50 = 50.0 raw/hr │
│ │
│ Drained by downstream conversions: │
│ → Metal: 30 × 0.005 = 0.15 fire/hr │
│ → Lightning: 30 × 0.003 = 0.10 fire/hr │
│ │
│ Net Fire Regen: +0.50 - 0.15 - 0.10 = +0.25 fire/hr │
└─────────────────────────────────────────────────────────────┘
Formula Summary
A collapsible formula reference is shown at the top:
Conversion Rate Formula:
finalRate = (disciplineRate + attunementBase + pactBase) × attunementMult × pactMult × meditationMult
Where:
attunementMult = 1 + Σ(relevantAttunementLevel × 0.5)
pactMult = 1 + Σ(pactCount_element × invokerLevel × 0.25)
meditationMult = 1 + (meditationMultiplier - 1) / elementDistance
Cost per 1 unit of destination:
rawCost = 10^(distance+1)
componentCost = 10 × (distance+1) per component
All costs deducted from source regen (not from mana pool).
Conversions pause if source regen < conversion cost.
12. Implementation Notes
New Files
src/lib/game/utils/element-distance.ts—getElementDistance()functionsrc/lib/game/utils/conversion-rates.ts— Unified conversion rate calculatorsrc/lib/game/data/conversion-costs.ts— Cost ratio table per element
Modified Files
src/lib/game/data/disciplines/elemental-regen.ts— Update base rates, remove drain modelsrc/lib/game/data/disciplines/elemental-regen-advanced.ts— Update base rates, remove drain modelsrc/lib/game/data/attunements.ts— Update conversion rates to match new systemsrc/lib/game/effects/discipline-effects.ts— Update conversion computationsrc/lib/game/stores/gameStore.ts— Replace tick conversion logic with unified systemsrc/lib/game/stores/manaStore.ts— RemoveconvertMana,processConvertAction,craftCompositesrc/lib/game/stores/prestigeStore.ts— Add pact conversion rate datasrc/components/game/tabs/StatsTab/ElementStatsSection.tsx— Add conversion displaysrc/components/game/ManaDisplay.tsx— Add per-element regen breakdown
Removed
- Manual conversion (
convertMana,processConvertAction) - Composite crafting via
craftComposite(replaced by passive conversion) - The "convert" action from player actions
- Per-tick mana pool deduction for conversions (replaced by regen deduction)
13. Migration Notes
Existing save data will need migration:
- Active discipline conversion rates are preserved (the XP and discipline IDs stay the same)
- Attunement conversion rates are recalculated from the new base rates
- Any manually-converted element mana in pools is preserved
- The
convertManaandcraftCompositestore actions are kept as no-ops for save compatibility but have no UI