Files
Mana-Loop/docs/specs/attunements/attunement-system-spec.md
T
n8n-gitea 573130cdb1
Build and Publish Mana Loop Docker Image / build-and-publish (push) Successful in 1m24s
fix: attunement system spec-vs-code discrepancies (issue #331)
- Fix conversion rate level scaling from linear (1+level*0.5) to exponential (1.5^(level-1)) in conversion-rates.ts
- Fix getAttunementLevelMultiplier formula to match spec §4.3
- Add level-up logging in attunementStore.ts via combat store addActivityLog
- Clarify getAttunementConversionRate returns flat base rate (level scaling applied separately)
- Update spec §8 to describe time-based puzzle room system matching code implementation
- Add 17 regression tests verifying exponential scaling, base rate behavior, and spec table values
2026-06-08 22:08:17 +02:00

12 KiB
Raw Blame History

Attunement System — Design Spec

Describes the three-attunement class system: Enchanter, Invoker, and Fabricator. Covers slot assignments, unlock conditions, leveling, regen/conversion scaling, discipline pool gating, and interaction with mana conversion and the incursion system.


1. Objective

Attunements are class-like specializations that gate access to discipline pools and unique capabilities. A player can have multiple attunements active simultaneously, each contributing raw mana regen and (for Enchanter and Fabricator) automatic mana conversion. Attunements level up independently through attunement-specific XP sources, scaling their regen and conversion rates exponentially.

Design goals:

  • Three distinct attunements with unique identities and roles
  • Attunements unlock over time, expanding the player's options
  • Leveling provides meaningful exponential scaling without being mandatory
  • Discipline pool access is gated behind attunement unlock status
  • Invoker's lack of primary mana creates a distinct pact-dependent playstyle

2. The Three Attunements

2.1 Enchanter (Right Hand) — Starting Attunement

Property Value
ID enchanter
Slot rightHand
Icon
Color #1ABC9C (Teal)
Primary Mana transference
Raw Mana Regen +0.5/hour (base)
Conversion Rate 0.2 raw→transference/hour (base)
Unlock Starting (unlocked by default)
Capabilities ['enchanting']
Skill Categories ['enchant', 'effectResearch']

Disciplines: 10 disciplines across 4 files (core: 4, utility: 2, spells: 3, special: 1)

2.2 Invoker (Chest) — Locked

Property Value
ID invoker
Slot chest
Icon 💜
Color #9B59B6 (Purple)
Primary Mana None (gains elemental mana from pacts)
Raw Mana Regen +0.3/hour (base)
Conversion Rate None (0 at all levels)
Unlock Defeat first Guardian
Capabilities ['pacts', 'guardianPowers', 'elementalMastery']
Skill Categories ['invocation', 'pact']

Disciplines: 2 disciplines

2.3 Fabricator (Left Hand) — Locked

Property Value
ID fabricator
Slot leftHand
Icon ⚒️
Color #F4A261 (Earth)
Primary Mana earth
Raw Mana Regen +0.4/hour (base)
Conversion Rate 0.25 raw→earth/hour (base)
Unlock Prove crafting worth
Capabilities ['golemCrafting', 'gearCrafting', 'earthShaping']
Skill Categories ['fabrication', 'golemancy']

Disciplines: 5 disciplines


3. Unlock Conditions

Attunement Condition Implementation
Enchanter Starting Present in initial state: { active: true, level: 1, experience: 0 }
Invoker Defeat first Guardian Descriptive: "Defeat your first guardian and choose the path of the Invoker"
Fabricator Prove crafting worth Descriptive: "Prove your worth as a crafter"

Unlocking is performed via debugUnlockAttunement(attunementId) in the store, which initializes the attunement at { active: true, level: 1, experience: 0 }. The conditions are currently descriptive strings rather than hard-coded mechanical checks.


4. Attunement Leveling

4.1 XP Thresholds

Level 1: 0 XP (starting)
Level 2: 1,000 XP
Level ≥ 3: Math.floor(1000 * Math.pow(2, level - 2) * 1.25)
Level XP Threshold Cumulative XP
1 0 0
2 1,000 1,000
3 2,500 3,500
4 5,000 8,500
5 10,000 18,500
6 20,000 38,500
7 40,000 78,500
8 80,000 158,500
9 160,000 318,500
10 320,000 638,500

Max Level: MAX_ATTUNEMENT_LEVEL = 10

4.2 Level-Up Mechanism

addAttunementXP(attunementId, amount):
  state.experience += amount
  while state.experience >= xpForNextLevel && level < MAX:
    state.experience -= xpForNextLevel
    level += 1
    log("Attunement leveled up!")

XP does not roll over beyond the threshold check — the threshold amount is subtracted and any remainder carries into the next level.

4.3 Regen and Conversion Rate Scaling

Both raw mana regen and conversion rate use the same exponential formula:

scaledValue = baseValue × 1.5^(level - 1)

Effective raw mana regen by level (per attunement):

Level Enchanter (0.5) Invoker (0.3) Fabricator (0.4)
1 0.500/hr 0.300/hr 0.400/hr
2 0.750/hr 0.450/hr 0.600/hr
3 1.125/hr 0.675/hr 0.900/hr
4 1.688/hr 1.013/hr 1.350/hr
5 2.531/hr 1.519/hr 2.025/hr
6 3.797/hr 2.278/hr 3.038/hr
7 5.695/hr 3.417/hr 4.556/hr
8 8.543/hr 5.126/hr 6.834/hr
9 12.814/hr 7.689/hr 10.252/hr
10 19.221/hr 11.533/hr 15.377/hr

Effective conversion rate by level:

Level Enchanter (0.2) Fabricator (0.25)
1 0.200/hr 0.250/hr
2 0.300/hr 0.375/hr
3 0.450/hr 0.563/hr
4 0.675/hr 0.844/hr
5 1.013/hr 1.266/hr
6 1.519/hr 1.898/hr
7 2.278/hr 2.848/hr
8 3.417/hr 4.271/hr
9 5.126/hr 6.407/hr
10 7.689/hr 9.610/hr

Invoker has conversionRate = 0 at all levels — no auto-conversion.

Total regen = sum of baseRegen × 1.5^(level-1) across all active attunements. Total conversion drain = sum of baseConversionRate × 1.5^(level-1) across active attunements that have a non-zero conversion rate. This drain is applied to the raw mana pool.


5. Attunement XP Gain Sources

5.1 Enchanting → Enchanter XP

calculateEnchantingXP(capacityUsed: number): number {
  return Math.max(1, Math.floor(capacityUsed / 10));
}
  • 1 Enchanter XP per 10 capacity used (floored), minimum 1 XP per enchant.

5.2 Other Sources

The addAttunementXP(attunementId, amount) store action is the generic mechanism. Any system can call it to award XP to any attunement. In the codebase as-is, only enchanting has an explicit calculation function. Invoker and Fabricator XP gain is expected to be called from their respective systems (pact signing and item fabrication) but explicit calculation functions are not yet defined.


6. Discipline Pool Gating

6.1 Skill Categories

Attunements gate discipline access through skill categories:

Category Disciplines
Always available mana, study, research
Enchanter enchant, effectResearch
Invoker invocation, pact
Fabricator fabrication, golemancy

The function getAvailableSkillCategories() iterates all active attunements, collects their skillCategories into a Set, and returns the deduplicated array.

6.2 Discipline Pool Counts per Attunement

Attunement File Count
Enchanter Core enchanter.ts 4
Enchanter Utility enchanter-utility.ts 2
Enchanter Spells enchanter-spells.ts 3
Enchanter Special enchanter-special.ts 1
Invoker invoker.ts 2
Fabricator fabricator.ts 5
Attunement-gated total 17

The remaining 47 disciplines are available regardless of attunement status (base, elemental, elemental-regen, elemental-regen-advanced pools).

6.3 Capability Gating

Each attunement grants capabilities that unlock specific game systems:

Capability System
enchanting Enchantment Design/Prepare/Apply pipeline
pacts Guardian pact signing and boon system
guardianPowers Guardian power access
elementalMastery Element mastery bonuses
golemCrafting Golem summoning (Golemancy)
gearCrafting Gear fabrication recipes
earthShaping Earth mana shaping

7. Mana Conversion Interaction

7.1 Conversion Flow

Each tick, the mana system:

  1. Computes total raw regen (base + attunement regen + discipline bonus + equipment) × temporalEcho × meditationMultiplier
  2. Subtracts incursion reduction: × (1 - incursionStrength)
  3. Computes total conversion drain: sum of all active attunement conversion rates
  4. Applies: rawMana += totalRegen - totalConversionDrain (per tick)
  5. For each attunement with conversion: adds conversionRate × HOURS_PER_TICK to the target element

7.2 Invoker's Unique Position

The Invoker has no automatic conversionconversionRate = 0. Instead, it gains elemental mana types exclusively by signing Guardian pacts. Each guardian's unlocksMana array is resolved through resolveMultiUnlockChain(element), which unlocks the guardian's element and all base components.

Example: Signing a Metal guardian (floor 90) unlocks fire, earth, and metal.

7.3 Conversion and Incursion

Incursion reduces net raw mana regeneration:

effectiveRegen = max(0, baseRegen × (1 - incursionStrength) × meditationMult - totalConversionPerTick)

As incursion strength approaches 95% (day 30), conversion drains can exceed regen, causing raw mana to decrease. Since conversion is contingent on available raw mana, attunement conversion effectively stalls during peak incursion if the raw pool is insufficient.


8. Puzzle Room Interaction

From spire-climbing-spec.md §4.3, puzzle rooms appear on every 7th floor and have per-attunement variants:

Room Type Description
enchanter_trial Enchanter-themed puzzle challenge
fabricator_trial Fabricator-themed puzzle challenge
invoker_trial Invoker-themed puzzle challenge
hybrid_enchanter_fabricator Dual attunement challenge
hybrid_enchanter_invoker Dual attunement challenge
hybrid_fabricator_invoker Dual attunement challenge

Time-based progression system: Each puzzle room has a base time requirement that varies by floor range (4h for floors 120, 8h for 2150, 16h for 51100, 24h for 101+). Each relevant attunement reduces the total time needed, up to a maximum 90% reduction shared across all relevant attunements. Progress accumulates at HOURS_PER_TICK (0.04h) per tick. The room completes when puzzleProgress >= puzzleRequired.


9. State Fields

interface AttunementState {
  id: string;
  active: boolean;
  level: number;        // 110
  experience: number;   // current XP toward next level
}

// Initial state (prestige):
attunements: {
  enchanter: { id: 'enchanter', active: true, level: 1, experience: 0 }
}

10. Acceptance Criteria

# Criterion
AC-1 Enchanter is the only active attunement at game start (level 1, 0 XP).
AC-2 Invoker and Fabricator are locked until unlocked; their unlock conditions are displayed in the Attunements tab.
AC-3 Attunement XP accumulates and triggers level-ups at the correct thresholds; each level requires the exact XP specified in the formula.
AC-4 Regen and conversion rates scale by 1.5^(level-1) — a level 10 Enchanter converts at 7.69 raw→transference/hour.
AC-5 Both raw regen and conversion from all active attunements are summed and applied each tick.
AC-6 Invoker has no automatic mana conversion at any level.
AC-7 Enchanting awards Enchanter XP at 1 per 10 capacity used (minimum 1).
AC-8 Attunement skill categories correctly gate discipline pool access — Enchanter disciplines require Enchanter to be active.
AC-9 Attunement tab shows unlocked/locked visual distinction, XP progress bar, level badge, and all attunement capabilities.
AC-10 Puzzle rooms on every 7th floor use per-attunement room types with the correct progress scaling.
AC-11 Incursion correctly reduces net raw mana regeneration, potentially stalling conversion at peak incursion.

11. Files Reference

File Role
src/lib/game/data/attunements.ts Attunement definitions (the 3 attunements)
src/lib/game/stores/attunementStore.ts Attunement state, leveling, XP, unlock
src/lib/game/types/attunements.ts Attunement type definitions
src/components/game/tabs/AttunementsTab.tsx Attunement UI display
src/lib/game/stores/manaStore.ts Mana regen, conversion, incursion effects
docs/specs/spire-climbing-spec.md Puzzle room types per attunement