feat: implement DoT/debuff runtime system (spec §6, AC-12, AC-13)
Build and Publish Mana Loop Docker Image / build-and-publish (push) Successful in 1m18s
Build and Publish Mana Loop Docker Image / build-and-publish (push) Successful in 1m18s
- Add ActiveEffect, EffectType types to game.ts; activeEffects + effectiveArmor on EnemyState - Add SpellOnHitEffect + onHitEffect field to SpellDefinition - Wire onHitEffect to fire (burn), death (curse), lightning (armor_corrode), frost (freeze), soul (bypassArmor burn) - Add applyOnHitEffect() — applies on-hit effect on successful spell hit (spec §6.2) - Add processDoTPhase() — ticks all active effects after weapon/golem attacks (spec §6.3) - Add bypassArmor/bypassBarrier support in applyEnemyDefenses() (AC-13) - Export standalone applyEnemyDefenses from combat-tick.ts for DoT pipeline - Split DoT runtime into separate dot-runtime.ts (135 lines) to keep combat-actions.ts under 400 lines - Update all enemy generation sites with activeEffects/effectiveArmor defaults - Fix test helpers for new required fields All 921 tests pass (45 test files)
This commit is contained in:
@@ -0,0 +1,348 @@
|
||||
# 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
|
||||
|
||||
```typescript
|
||||
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 conversion** — `conversionRate = 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 |
|
||||
|
||||
Progress scales at 1.5–2% per tick base, with attunement bonus of 2.5–3% per
|
||||
relevant attunement level.
|
||||
|
||||
---
|
||||
|
||||
## 9. State Fields
|
||||
|
||||
```typescript
|
||||
interface AttunementState {
|
||||
id: string;
|
||||
active: boolean;
|
||||
level: number; // 1–10
|
||||
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 |
|
||||
@@ -0,0 +1,363 @@
|
||||
# Enchanter Attunement — Design Spec
|
||||
|
||||
> Describes the Enchanter attunement: identity, unlock flow, mana behavior, full
|
||||
> discipline list with stats/perks, systems unlocked, and attunement level interactions.
|
||||
|
||||
---
|
||||
|
||||
## 1. Objective
|
||||
|
||||
The Enchanter is the starting attunement and the gateway to the enchanting system.
|
||||
It provides access to Transference-based disciplines that unlock enchantment
|
||||
effects, boost enchantment power, and provide study/utility bonuses. The Enchanter
|
||||
is always the first attunement a player uses, and it remains relevant throughout
|
||||
all stages of the game through its 10 disciplines and the deep enchanting pipeline.
|
||||
|
||||
---
|
||||
|
||||
## 2. Identity
|
||||
|
||||
| Property | Value |
|
||||
|---|---|
|
||||
| **ID** | `enchanter` |
|
||||
| **Slot** | `rightHand` |
|
||||
| **Icon** | `✨` |
|
||||
| **Color** | `#1ABC9C` (Teal) |
|
||||
| **Primary Mana** | `transference` |
|
||||
| **Raw Mana Regen** | +0.5/hour (base, scales with `1.5^(level-1)`) |
|
||||
| **Conversion Rate** | 0.2 raw→transference/hour (base, scales with `1.5^(level-1)`) |
|
||||
| **Unlock** | Starting attunement (unlocked by default) |
|
||||
| **Capabilities** | `['enchanting']` |
|
||||
| **Skill Categories** | `['enchant', 'effectResearch']` |
|
||||
|
||||
---
|
||||
|
||||
## 3. Unlock Condition and Flow
|
||||
|
||||
The Enchanter is **always unlocked** — it is present in the initial game state:
|
||||
|
||||
```typescript
|
||||
attunements: {
|
||||
enchanter: { id: 'enchanter', active: true, level: 1, experience: 0 }
|
||||
}
|
||||
```
|
||||
|
||||
No unlock flow is required. The player begins the game with Enchanter active.
|
||||
|
||||
---
|
||||
|
||||
## 4. Raw Mana Regen Contribution
|
||||
|
||||
Base regen: **+0.5/hour** (at level 1). Scales exponentially:
|
||||
|
||||
```
|
||||
effectiveRegen = 0.5 × 1.5^(level - 1)
|
||||
```
|
||||
|
||||
| Level | Raw Regen |
|
||||
|---|---|
|
||||
| 1 | 0.500/hr |
|
||||
| 5 | 2.531/hr |
|
||||
| 10 | 19.221/hr |
|
||||
|
||||
---
|
||||
|
||||
## 5. Mana Conversion Behavior
|
||||
|
||||
The Enchanter is the **only attunement that converts raw mana to Transference**:
|
||||
|
||||
```
|
||||
effectiveConversionRate = 0.2 × 1.5^(level - 1)
|
||||
```
|
||||
|
||||
This is an automatic per-hour conversion. Each tick:
|
||||
- `0.2 × 1.5^(level-1) × HOURS_PER_TICK` raw mana is consumed
|
||||
- The same amount is added to the Transference mana pool
|
||||
|
||||
At level 10, the Enchanter converts **7.69 raw→transference/hour**.
|
||||
|
||||
---
|
||||
|
||||
## 6. Disciplines
|
||||
|
||||
The Enchanter's discipline pool contains **10 disciplines** across 4 files.
|
||||
|
||||
### 6.1 Core Disciplines (`enchanter.ts`) — 4 disciplines
|
||||
|
||||
#### Enchantment Crafting (`enchant-crafting`)
|
||||
|
||||
| Field | Value |
|
||||
|---|---|
|
||||
| **Mana Type** | `transference` |
|
||||
| **Base Cost** | 8 |
|
||||
| **Stat Bonus** | `enchantPower` +8 (base) |
|
||||
| **Scaling Factor** | 60 |
|
||||
| **Difficulty Factor** | 120 |
|
||||
| **Drain Base** | 3 |
|
||||
|
||||
| Perk ID | Type | Threshold | Bonus |
|
||||
|---|---|---|---|
|
||||
| `enchant-1` | `infinite` | 150 | +5 enchantPower per tier (repeats every 150 XP) |
|
||||
| `enchant-2` | `capped` | 300 | +10 enchantPower per tier, interval 200 XP, max 3 tiers |
|
||||
|
||||
#### Mana Channeling (`mana-channeling`)
|
||||
|
||||
| Field | Value |
|
||||
|---|---|
|
||||
| **Mana Type** | `transference` |
|
||||
| **Base Cost** | 12 |
|
||||
| **Stat Bonus** | `clickManaMultiplier` +0.3 (base) |
|
||||
| **Scaling Factor** | 90 |
|
||||
| **Difficulty Factor** | 180 |
|
||||
| **Drain Base** | 5 |
|
||||
|
||||
| Perk ID | Type | Threshold | Bonus |
|
||||
|---|---|---|---|
|
||||
| `channel-1` | `once` | 250 | `elementCap_lightning` +15 |
|
||||
|
||||
#### Study Basic Weapon Enchantments (`study-basic-weapon-enchantments`)
|
||||
|
||||
| Field | Value |
|
||||
|---|---|
|
||||
| **Mana Type** | `transference` |
|
||||
| **Base Cost** | 10 |
|
||||
| **Stat Bonus** | `enchantPower` +3 (base) |
|
||||
| **Scaling Factor** | 80 |
|
||||
| **Difficulty Factor** | 100 |
|
||||
| **Drain Base** | 2 |
|
||||
|
||||
| Perk ID | Type | Threshold | Unlocks |
|
||||
|---|---|---|---|
|
||||
| `basic-weapon-fire` | `once` | 50 | `sword_fire` |
|
||||
| `basic-weapon-frost` | `once` | 100 | `sword_frost` |
|
||||
| `basic-weapon-lightning` | `once` | 150 | `sword_lightning` |
|
||||
|
||||
#### Study Advanced Weapon Enchantments (`study-advanced-weapon-enchantments`)
|
||||
|
||||
| Field | Value |
|
||||
|---|---|
|
||||
| **Mana Type** | `transference` |
|
||||
| **Base Cost** | 20 |
|
||||
| **Requires** | `study-basic-weapon-enchantments` |
|
||||
| **Stat Bonus** | `enchantPower` +5 (base) |
|
||||
| **Scaling Factor** | 120 |
|
||||
| **Difficulty Factor** | 200 |
|
||||
| **Drain Base** | 4 |
|
||||
|
||||
| Perk ID | Type | Threshold | Unlocks |
|
||||
|---|---|---|---|
|
||||
| `advanced-weapon-void` | `once` | 100 | `sword_void` |
|
||||
| `advanced-weapon-damage-5` | `once` | 150 | `damage_5` |
|
||||
| `advanced-weapon-crit` | `once` | 200 | `crit_5` |
|
||||
| `advanced-weapon-attack-speed` | `once` | 250 | `attack_speed_10` |
|
||||
|
||||
### 6.2 Utility Disciplines (`enchanter-utility.ts`) — 2 disciplines
|
||||
|
||||
#### Study Utility Enchantments (`study-utility-enchantments`)
|
||||
|
||||
| Field | Value |
|
||||
|---|---|
|
||||
| **Mana Type** | `transference` |
|
||||
| **Base Cost** | 8 |
|
||||
| **Stat Bonus** | `studySpeed` +0.05 (base) |
|
||||
| **Scaling Factor** | 60 |
|
||||
| **Difficulty Factor** | 80 |
|
||||
| **Drain Base** | 2 |
|
||||
|
||||
| Perk ID | Type | Threshold | Unlocks |
|
||||
|---|---|---|---|
|
||||
| `utility-meditate` | `once` | 50 | `meditate_10` |
|
||||
| `utility-study` | `once` | 100 | `study_10` |
|
||||
| `utility-insight` | `once` | 150 | `insight_5` |
|
||||
|
||||
#### Study Mana Enchantments (`study-mana-enchantments`)
|
||||
|
||||
| Field | Value |
|
||||
|---|---|
|
||||
| **Mana Type** | `transference` |
|
||||
| **Base Cost** | 15 |
|
||||
| **Stat Bonus** | `maxManaBonus` +10 (base) |
|
||||
| **Scaling Factor** | 100 |
|
||||
| **Difficulty Factor** | 150 |
|
||||
| **Drain Base** | 3 |
|
||||
|
||||
| Perk ID | Type | Threshold | Unlocks |
|
||||
|---|---|---|---|
|
||||
| `mana-cap-50` | `once` | 75 | `mana_cap_50` |
|
||||
| `mana-cap-100` | `once` | 150 | `mana_cap_100` |
|
||||
| `mana-regen-1` | `once` | 100 | `mana_regen_1` |
|
||||
| `mana-regen-2` | `once` | 200 | `mana_regen_2` |
|
||||
| `click-mana-1` | `once` | 125 | `click_mana_1` |
|
||||
| `click-mana-3` | `once` | 225 | `click_mana_3` |
|
||||
|
||||
### 6.3 Spell Disciplines (`enchanter-spells.ts`) — 3 disciplines
|
||||
|
||||
#### Study Basic Spell Enchantments (`study-basic-spell-enchantments`)
|
||||
|
||||
| Field | Value |
|
||||
|---|---|
|
||||
| **Mana Type** | `transference` |
|
||||
| **Base Cost** | 18 |
|
||||
| **Stat Bonus** | `enchantPower` +4 (base) |
|
||||
| **Scaling Factor** | 100 |
|
||||
| **Difficulty Factor** | 160 |
|
||||
| **Drain Base** | 3 |
|
||||
|
||||
| Perk ID | Type | Threshold | Unlocks |
|
||||
|---|---|---|---|
|
||||
| `spell-mana-bolt` | `once` | 50 | `spell_manaBolt` |
|
||||
| `spell-fireball` | `once` | 100 | `spell_fireball` |
|
||||
| `spell-water-jet` | `once` | 100 | `spell_waterJet` |
|
||||
| `spell-gust` | `once` | 100 | `spell_gust` |
|
||||
| `spell-stone-bullet` | `once` | 100 | `spell_stoneBullet` |
|
||||
| `spell-light-lance` | `once` | 150 | `spell_lightLance` |
|
||||
| `spell-shadow-bolt` | `once` | 150 | `spell_shadowBolt` |
|
||||
| `spell-drain` | `once` | 150 | `spell_drain` |
|
||||
|
||||
#### Study Intermediate Spell Enchantments (`study-intermediate-spell-enchantments`)
|
||||
|
||||
| Field | Value |
|
||||
|---|---|
|
||||
| **Mana Type** | `transference` |
|
||||
| **Base Cost** | 25 |
|
||||
| **Requires** | `study-basic-spell-enchantments` |
|
||||
| **Stat Bonus** | `enchantPower` +6 (base) |
|
||||
| **Scaling Factor** | 150 |
|
||||
| **Difficulty Factor** | 250 |
|
||||
| **Drain Base** | 5 |
|
||||
|
||||
| Perk ID | Type | Threshold | Unlocks |
|
||||
|---|---|---|---|
|
||||
| `spell-inferno` | `once` | 100 | `spell_inferno` |
|
||||
| `spell-tidal-wave` | `once` | 100 | `spell_tidalWave` |
|
||||
| `spell-earthquake` | `once` | 120 | `spell_earthquake` |
|
||||
| `spell-chain-lightning` | `once` | 100 | `spell_chainLightning` |
|
||||
| `spell-metal-shard` | `once` | 80 | `spell_metalShard` |
|
||||
| `spell-sand-blast` | `once` | 80 | `spell_sandBlast` |
|
||||
|
||||
#### Study Advanced Spell Enchantments (`study-advanced-spell-enchantments`)
|
||||
|
||||
| Field | Value |
|
||||
|---|---|
|
||||
| **Mana Type** | `transference` |
|
||||
| **Base Cost** | 35 |
|
||||
| **Requires** | `study-intermediate-spell-enchantments` |
|
||||
| **Stat Bonus** | `enchantPower` +10 (base) |
|
||||
| **Scaling Factor** | 200 |
|
||||
| **Difficulty Factor** | 350 |
|
||||
| **Drain Base** | 7 |
|
||||
|
||||
| Perk ID | Type | Threshold | Unlocks |
|
||||
|---|---|---|---|
|
||||
| `spell-pyroclasm` | `once` | 100 | `spell_pyroclasm` |
|
||||
| `spell-tsunami` | `once` | 100 | `spell_tsunami` |
|
||||
| `spell-meteor-strike` | `once` | 120 | `spell_meteorStrike` |
|
||||
| `spell-heaven-light` | `once` | 100 | `spell_heavenLight` |
|
||||
| `spell-oblivion` | `once` | 100 | `spell_oblivion` |
|
||||
| `spell-furnace-blast` | `once` | 100 | `spell_furnaceBlast` |
|
||||
| `spell-dune-collapse` | `once` | 100 | `spell_duneCollapse` |
|
||||
| `spell-stellar-nova` | `once` | 200 | `spell_stellarNova` |
|
||||
| `spell-void-collapse` | `once` | 180 | `spell_voidCollapse` |
|
||||
| `spell-crystal-shatter` | `once` | 160 | `spell_crystalShatter` |
|
||||
|
||||
### 6.4 Special Discipline (`enchanter-special.ts`) — 1 discipline
|
||||
|
||||
#### Study Special Enchantments (`study-special-enchantments`)
|
||||
|
||||
| Field | Value |
|
||||
|---|---|
|
||||
| **Mana Type** | `transference` |
|
||||
| **Base Cost** | 22 |
|
||||
| **Requires** | `study-advanced-weapon-enchantments` |
|
||||
| **Stat Bonus** | `enchantPower` +5 (base) |
|
||||
| **Scaling Factor** | 130 |
|
||||
| **Difficulty Factor** | 220 |
|
||||
| **Drain Base** | 4 |
|
||||
|
||||
| Perk ID | Type | Threshold | Unlocks |
|
||||
|---|---|---|---|
|
||||
| `special-spell-echo` | `once` | 100 | `spell_echo_10` |
|
||||
| `special-guardian-dmg` | `once` | 80 | `guardian_dmg_10` |
|
||||
| `special-overpower` | `once` | 150 | `overpower_80` |
|
||||
| `special-first-strike` | `once` | 120 | `first_strike` |
|
||||
| `special-combo-master` | `once` | 200 | `combo_master` |
|
||||
| `special-adrenaline-rush` | `once` | 180 | `adrenaline_rush` |
|
||||
|
||||
---
|
||||
|
||||
## 7. Systems Unlocked
|
||||
|
||||
The Enchanter attunement gates the **Enchanting System** (see `enchanting-spec.md`):
|
||||
|
||||
- **Design** stage: Create named enchantment designs
|
||||
- **Prepare** stage: Clear existing enchantments, ready equipment
|
||||
- **Apply** stage: Apply saved designs to prepared equipment
|
||||
|
||||
---
|
||||
|
||||
## 8. Puzzle Room Behavior
|
||||
|
||||
In the spire, every 7th floor has a puzzle room. When the room type is
|
||||
`enchanter_trial`, progress scales at 2.5–3% per tick per Enchanter level.
|
||||
|
||||
---
|
||||
|
||||
## 9. Attunement Level Interactions
|
||||
|
||||
Higher Enchanter level affects:
|
||||
|
||||
1. **Raw mana regen**: `0.5 × 1.5^(level-1)` per hour
|
||||
2. **Transference conversion rate**: `0.2 × 1.5^(level-1)` per hour
|
||||
3. **Enchanting XP → Attunement XP**: Enchanting awards Enchanter XP (1 per 10 capacity used), feeding back into leveling
|
||||
|
||||
Attunement level does **not** directly affect enchantment strength or discipline
|
||||
power — those scale through discipline XP alone.
|
||||
|
||||
---
|
||||
|
||||
## 10. Discipline Dependency Chain
|
||||
|
||||
```
|
||||
enchant-crafting (root)
|
||||
mana-channeling (root)
|
||||
study-basic-weapon-enchantments (root)
|
||||
└── study-advanced-weapon-enchantments
|
||||
└── study-special-enchantments
|
||||
study-utility-enchantments (root)
|
||||
study-mana-enchantments (root)
|
||||
study-basic-spell-enchantments (root)
|
||||
└── study-intermediate-spell-enchantments
|
||||
└── study-advanced-spell-enchantments
|
||||
```
|
||||
|
||||
6 root disciplines. Maximum dependency depth: 3.
|
||||
|
||||
---
|
||||
|
||||
## 11. Acceptance Criteria
|
||||
|
||||
| # | Criterion |
|
||||
|---|---|
|
||||
| AC-1 | Enchanter starts unlocked at level 1 with 0 XP. |
|
||||
| AC-2 | All 10 Enchanter disciplines are available when Enchanter is active. |
|
||||
| AC-3 | Discipline dependency chains are enforced — Advanced Weapon Enchantments requires Basic Weapon Enchantments. |
|
||||
| AC-4 | All perk thresholds unlock the correct enchantment effects at the specified XP values. |
|
||||
| AC-5 | Enchantment Power stat bonus from all active Enchanter disciplines stacks additively. |
|
||||
| AC-6 | The `enchant-1` infinite perk grants +5 enchantPower every 150 XP beyond threshold. |
|
||||
| AC-7 | The `enchant-2` capped perk grants +10 enchantPower per tier, max 3 tiers, interval 200 XP beyond threshold. |
|
||||
| AC-8 | Enchanting system is accessible when Enchanter is active, locked when inactive. |
|
||||
| AC-9 | Enchanter `enchanter_trial` puzzle rooms grant bonus progress per Enchanter level. |
|
||||
| AC-10 | Enchanter level scales raw regen and conversion rate by `1.5^(level-1)`. |
|
||||
|
||||
---
|
||||
|
||||
## 12. Files Reference
|
||||
|
||||
| File | Role |
|
||||
|---|---|
|
||||
| `src/lib/game/data/attunements.ts` | Enchanter definition |
|
||||
| `src/lib/game/data/disciplines/enchanter.ts` | Core Enchanter disciplines (4) |
|
||||
| `src/lib/game/data/disciplines/enchanter-utility.ts` | Utility enchantment disciplines (2) |
|
||||
| `src/lib/game/data/disciplines/enchanter-spells.ts` | Spell enchantment disciplines (3) |
|
||||
| `src/lib/game/data/disciplines/enchanter-special.ts` | Special enchantment discipline (1) |
|
||||
| `docs/specs/attunements/enchanter/systems/enchanting-spec.md` | Enchanting system spec |
|
||||
@@ -0,0 +1,655 @@
|
||||
# Enchanting System — Design Spec
|
||||
|
||||
> Describes the three-stage enchanting pipeline: Design → Prepare → Apply.
|
||||
> Covers stage timings, mana costs, auto-transitions, enchantment capacity system,
|
||||
> full enchantment effect categories, disenchanting, and discipline perk interactions.
|
||||
|
||||
---
|
||||
|
||||
## 1. Objective
|
||||
|
||||
Enchanting is the Enchanter attunement's primary system for enhancing equipment. It
|
||||
transforms raw mana and materials into permanent equipment bonuses through a
|
||||
three-stage pipeline. The player creates reusable designs, prepares equipment by
|
||||
stripping existing enchantments, then applies designs to prepared equipment.
|
||||
|
||||
**Design goals:**
|
||||
- Three distinct stages encourage planning and resource management
|
||||
- Capacity and stacking systems allow deep customization of individual items
|
||||
- Discipline perks progressively unlock more powerful enchantment types
|
||||
- Mana costs scale with design complexity, creating meaningful trade-offs
|
||||
- Auto-transitions keep the pipeline flowing without manual state management
|
||||
|
||||
---
|
||||
|
||||
## 2. Controls / API
|
||||
|
||||
### 2.1 Player Actions
|
||||
|
||||
| Action | Stage | Trigger |
|
||||
|---|---|---|
|
||||
| **Create Design** | Design | Select effects, name design, click "Create Design" |
|
||||
| **Start Prepare** | Prepare | Select equipped item, click "Prepare" |
|
||||
| **Apply Enchantment** | Apply | Select saved design + prepared item, click "Apply" |
|
||||
| **Disenchant** | Prepare | Initiate prepare on already-enchanted equipment (enchantments removed) |
|
||||
| **Cancel** | Any | Click "Cancel" during any active stage |
|
||||
|
||||
### 2.2 Auto-Transitions
|
||||
|
||||
- Design complete → returns to idle (Meditate)
|
||||
- Prepare complete → returns to idle (Meditate), item gains "Ready for Enchantment" tag
|
||||
- Apply complete → returns to idle (Meditate), selection state resets
|
||||
|
||||
---
|
||||
|
||||
## 3. Stage 1: Design
|
||||
|
||||
### 3.1 Flow
|
||||
|
||||
1. Player selects an equipment type from the type selector
|
||||
2. Player adds effects from the unlocked pool via the EffectSelector
|
||||
3. Player sets stack count per effect (up to `maxStacks`)
|
||||
4. Player names the design
|
||||
5. Player clicks "Create Design" → design begins
|
||||
6. `designProgress` accumulates at `HOURS_PER_TICK` per tick
|
||||
7. When `designProgress >= requiredTime` → design saved to `completedDesigns`
|
||||
|
||||
### 3.2 Timing Formula
|
||||
|
||||
```
|
||||
calculateDesignTime(effects):
|
||||
time = 1 // base 1 hour
|
||||
for each effect: time += 0.5 * stacks
|
||||
return time
|
||||
```
|
||||
|
||||
| Design Complexity | Time |
|
||||
|---|---|
|
||||
| 1 effect, 1 stack | 1.5 hours |
|
||||
| 3 effects, 1 stack each | 2.5 hours |
|
||||
| 2 effects, 3 stacks each | 4.0 hours |
|
||||
|
||||
Progress per tick: `HOURS_PER_TICK = 0.04` hours.
|
||||
|
||||
### 3.3 Hasty Enchanter (Special Effect)
|
||||
|
||||
If the player has the `HASTY_ENCHANTER` special effect and the design is a **repeat**
|
||||
(re-creating a previously completed design):
|
||||
|
||||
```
|
||||
time *= 0.75 // 25% faster
|
||||
```
|
||||
|
||||
### 3.4 Instant Designs (Special Effect)
|
||||
|
||||
Per tick, if the player has the `INSTANT_DESIGNS` special effect:
|
||||
|
||||
```typescript
|
||||
const INSTANT_DESIGN_CHANCE = 0.10; // 10%
|
||||
if (Math.random() < INSTANT_DESIGN_CHANCE) {
|
||||
designProgress = requiredTime; // instant completion
|
||||
}
|
||||
```
|
||||
|
||||
### 3.5 Dual Design Slot
|
||||
|
||||
A second concurrent design slot is available when:
|
||||
- The first design slot has an active design (`designProgress` exists)
|
||||
- The second slot is empty (`designProgress2 === null`)
|
||||
- The player has the `ENCHANT_MASTERY` special boolean
|
||||
|
||||
### 3.6 Design Mana Cost
|
||||
|
||||
**None.** The Design stage has no mana cost.
|
||||
|
||||
### 3.7 Design Validation
|
||||
|
||||
- `enchantingLevel >= 1` (enchanter attunement must be active)
|
||||
- Each effect must exist in `ENCHANTMENT_EFFECTS`
|
||||
- Each effect's `allowedEquipmentCategories` must include the equipment's category
|
||||
- Stacks cannot exceed the effect's `maxStacks`
|
||||
|
||||
### 3.8 Enchanting XP Award
|
||||
|
||||
```typescript
|
||||
calculateEnchantingXP(capacityUsed: number): number {
|
||||
return Math.max(1, Math.floor(capacityUsed / 10));
|
||||
}
|
||||
```
|
||||
|
||||
Awarded to Enchanter attunement XP on design completion. This is **Attunement XP**,
|
||||
not discipline XP.
|
||||
|
||||
---
|
||||
|
||||
## 4. Stage 2: Prepare
|
||||
|
||||
### 4.1 Flow
|
||||
|
||||
1. Player selects an equipped item to prepare
|
||||
2. System checks: `'Ready for Enchantment'` tag required if item was previously prepared
|
||||
3. If item has existing enchantments, a confirmation dialog warns they will be removed
|
||||
4. Player confirms → preparation begins
|
||||
5. Mana is deducted over the prep duration
|
||||
6. On completion: all enchantments removed, `usedCapacity` reset to 0, rarity reset to `'common'`, `'Ready for Enchantment'` tag added
|
||||
|
||||
### 4.2 Timing Formula
|
||||
|
||||
```
|
||||
calculatePrepTime(equipmentCapacity):
|
||||
time = 2 + floor(equipmentCapacity / 50)
|
||||
```
|
||||
|
||||
| Capacity | Prep Time |
|
||||
|---|---|
|
||||
| 15 (shoes) | 2 hours |
|
||||
| 30 (body) | 2 hours |
|
||||
| 50 (caster) | 3 hours |
|
||||
| 80 (robe) | 3 hours |
|
||||
|
||||
### 4.3 Mana Cost Formula
|
||||
|
||||
```
|
||||
totalMana = equipmentCapacity × 10
|
||||
manaPerHour = totalMana / prepTime
|
||||
manaPerTick = manaPerHour × HOURS_PER_TICK
|
||||
```
|
||||
|
||||
| Capacity | Total Mana Cost |
|
||||
|---|---|
|
||||
| 15 | 150 |
|
||||
| 30 | 300 |
|
||||
| 50 | 500 |
|
||||
| 80 | 800 |
|
||||
|
||||
### 4.4 Disenchant Recovery
|
||||
|
||||
When preparing equipment that has existing enchantments, mana is partially recovered:
|
||||
|
||||
```
|
||||
recoveryRate = 0.10 + disenchantLevel × 0.20
|
||||
manaRecovered = Σ floor(enchantment.actualCost × recoveryRate)
|
||||
```
|
||||
|
||||
| Disenchant Level | Recovery Rate |
|
||||
|---|---|
|
||||
| 0 | 10% |
|
||||
| 1 | 30% |
|
||||
| 2 | 50% |
|
||||
| 3 | 70% |
|
||||
| 4 | 90% |
|
||||
| 5 | 110% |
|
||||
|
||||
> **Note:** `disenchantLevel` is currently hardcoded to `0` in the codebase, so the
|
||||
> effective recovery rate is always **10%**.
|
||||
|
||||
### 4.5 Cancellation Refund
|
||||
|
||||
```
|
||||
remainingFraction = (required - progress) / required
|
||||
refundRate = remainingFraction + (1 - remainingFraction) × 0.5
|
||||
manaRefund = floor(manaSpent × refundRate)
|
||||
```
|
||||
|
||||
Unspent progress gets 100% refund; spent progress gets 50% refund; blended proportionally.
|
||||
|
||||
---
|
||||
|
||||
## 5. Stage 3: Apply
|
||||
|
||||
### 5.1 Flow
|
||||
|
||||
1. Player selects a saved design and a prepared equipment instance
|
||||
2. System validates: `currentAction === 'meditate'`, item has `'Ready for Enchantment'` tag, capacity fits
|
||||
3. Player clicks "Apply" → application begins
|
||||
4. Mana is deducted per hour over the application duration
|
||||
5. On completion: design's effects applied to equipment, `usedCapacity` updated, design consumed
|
||||
|
||||
### 5.2 Timing Formula
|
||||
|
||||
```
|
||||
calculateApplicationTime(design):
|
||||
time = 2 + Σ(stacks) for all effects in design
|
||||
```
|
||||
|
||||
| Design | Apply Time |
|
||||
|---|---|
|
||||
| 1 effect, 1 stack | 3 hours |
|
||||
| 3 effects, 1 stack each | 5 hours |
|
||||
| 2 effects, 3 stacks each | 8 hours |
|
||||
|
||||
### 5.3 Mana Cost Formula
|
||||
|
||||
```
|
||||
manaPerHour = 20 + Σ(stacks × 5) for all effects
|
||||
manaPerTick = manaPerHour × HOURS_PER_TICK
|
||||
```
|
||||
|
||||
| Design | Mana/Hour |
|
||||
|---|---|
|
||||
| 1 effect, 1 stack | 25 |
|
||||
| 3 effects, 1 stack each | 35 |
|
||||
| 2 effects, 3 stacks each | 50 |
|
||||
|
||||
### 5.4 Free Enchant Chances
|
||||
|
||||
Per tick, the system checks for free enchant chances. These are **additive**:
|
||||
|
||||
| Special Effect | Chance |
|
||||
|---|---|
|
||||
| `ENCHANT_PRESERVATION` | 25% |
|
||||
| `THRIFTY_ENCHANTER` | 10% |
|
||||
| `OPTIMIZED_ENCHANTING` | 25% |
|
||||
| **Maximum combined** | **60%** |
|
||||
|
||||
On trigger: `applicationProgress = requiredTime` (instant completion for that tick),
|
||||
**no mana consumed** for that tick.
|
||||
|
||||
### 5.5 Pure Essence (Special Effect)
|
||||
|
||||
If the player has the `PURE_ESSENCE` special effect:
|
||||
|
||||
```typescript
|
||||
const PURE_ESSENCE_STACK_BONUS = 1.25;
|
||||
const PURE_ESSENCE_COST_CAP = 100;
|
||||
|
||||
if (effect.baseCapacityCost < PURE_ESSENCE_COST_CAP) {
|
||||
actualStacks = Math.ceil(baseStacks × PURE_ESSENCE_STACK_BONUS);
|
||||
}
|
||||
```
|
||||
|
||||
Effects with `baseCapacityCost < 100` get **25% more stacks** (rounded up).
|
||||
|
||||
### 5.6 Cancellation Refund
|
||||
|
||||
Same formula as Prepare stage (§4.5).
|
||||
|
||||
---
|
||||
|
||||
## 6. Enchantment Capacity System
|
||||
|
||||
### 6.1 Base Capacity Per Equipment Type
|
||||
|
||||
| Category | Equipment | Base Capacity |
|
||||
|---|---|---|
|
||||
| **Caster** | basicStaff | 50 |
|
||||
| | apprenticeWand | 35 |
|
||||
| | oakStaff | 65 |
|
||||
| | crystalWand | 45 |
|
||||
| | arcanistStaff | 80 |
|
||||
| | battlestaff | 70 |
|
||||
| **Catalyst** | basicCatalyst | 40 |
|
||||
| | fireCatalyst | 55 |
|
||||
| | voidCatalyst | 75 |
|
||||
| **Sword** | ironBlade | 30 |
|
||||
| | steelBlade | 40 |
|
||||
| | crystalBlade | 55 |
|
||||
| | arcanistBlade | 65 |
|
||||
| | voidBlade | 50 |
|
||||
| **Head** | clothHood | 25 |
|
||||
| | apprenticeCap | 30 |
|
||||
| | wizardHat | 45 |
|
||||
| | arcanistCirclet | 40 |
|
||||
| | battleHelm | 50 |
|
||||
| **Body** | civilianShirt | 30 |
|
||||
| | apprenticeRobe | 45 |
|
||||
| | scholarRobe | 55 |
|
||||
| | battleRobe | 65 |
|
||||
| | arcanistRobe | 80 |
|
||||
| **Hands** | civilianGloves | 20 |
|
||||
| | apprenticeGloves | 30 |
|
||||
| | spellweaveGloves | 40 |
|
||||
| | combatGauntlets | 35 |
|
||||
| **Feet** | civilianShoes | 15 |
|
||||
| | apprenticeBoots | 25 |
|
||||
| | travelerBoots | 30 |
|
||||
| | battleBoots | 35 |
|
||||
| **Accessory** | copperRing | 15 |
|
||||
| | silverRing | 25 |
|
||||
| | goldRing | 35 |
|
||||
| | signetRing | 30 |
|
||||
| | copperAmulet | 20 |
|
||||
| | silverAmulet | 30 |
|
||||
| | crystalPendant | 45 |
|
||||
| | manaBrooch | 40 |
|
||||
| | arcanistPendant | 55 |
|
||||
| | voidTouchedRing | 50 |
|
||||
|
||||
### 6.2 Stacking Cost Formula
|
||||
|
||||
```
|
||||
calculateEffectCapacityCost(effectId, stacks, efficiencyBonus):
|
||||
totalCost = 0
|
||||
for i in 0..stacks-1:
|
||||
stackMultiplier = 1 + (i × 0.2)
|
||||
totalCost += baseCapacityCost × stackMultiplier
|
||||
return floor(totalCost × (1 - efficiencyBonus))
|
||||
```
|
||||
|
||||
| Stack Index | Multiplier |
|
||||
|---|---|
|
||||
| 0 (1st) | 1.0× |
|
||||
| 1 (2nd) | 1.2× |
|
||||
| 2 (3rd) | 1.4× |
|
||||
| 3 (4th) | 1.6× |
|
||||
| 4 (5th) | 1.8× |
|
||||
|
||||
Example: 3 stacks of a cost-20 effect:
|
||||
`20×1.0 + 20×1.2 + 20×1.4 = 20 + 24 + 28 = 72` capacity used.
|
||||
|
||||
### 6.3 Efficiency Bonus
|
||||
|
||||
The `efficiencyBonus` reduces total capacity cost. Sources include discipline perks
|
||||
(e.g., Crafting Efficiency discipline from Fabricator pool). Applied as:
|
||||
`totalCost × (1 - efficiencyBonus)`.
|
||||
|
||||
---
|
||||
|
||||
## 7. Enchantment Effect Categories
|
||||
|
||||
### 7.1 Spell Effects (category: `'spell'`) — Casters only
|
||||
|
||||
**Basic Spells:**
|
||||
|
||||
| Effect ID | Name | Base Cost | Max Stacks |
|
||||
|---|---|---|---|
|
||||
| `spell_manaBolt` | Mana Bolt | 50 | 1 |
|
||||
| `spell_manaStrike` | Mana Strike | 40 | 1 |
|
||||
| `spell_fireball` | Fireball | 80 | 1 |
|
||||
| `spell_emberShot` | Ember Shot | 60 | 1 |
|
||||
| `spell_waterJet` | Water Jet | 70 | 1 |
|
||||
| `spell_iceShard` | Ice Shard | 75 | 1 |
|
||||
| `spell_gust` | Gust | 60 | 1 |
|
||||
| `spell_stoneBullet` | Stone Bullet | 80 | 1 |
|
||||
| `spell_lightLance` | Light Lance | 95 | 1 |
|
||||
| `spell_shadowBolt` | Shadow Bolt | 95 | 1 |
|
||||
| `spell_drain` | Drain | 85 | 1 |
|
||||
| `spell_rotTouch` | Rot Touch | 80 | 1 |
|
||||
| `spell_windSlash` | Wind Slash | 72 | 1 |
|
||||
| `spell_rockSpike` | Rock Spike | 88 | 1 |
|
||||
| `spell_radiance` | Radiance | 80 | 1 |
|
||||
| `spell_darkPulse` | Dark Pulse | 68 | 1 |
|
||||
|
||||
**Tier 2 Spells:**
|
||||
|
||||
| Effect ID | Name | Base Cost | Max Stacks |
|
||||
|---|---|---|---|
|
||||
| `spell_inferno` | Inferno | 180 | 1 |
|
||||
| `spell_tidalWave` | Tidal Wave | 175 | 1 |
|
||||
| `spell_hurricane` | Hurricane | 170 | 1 |
|
||||
| `spell_earthquake` | Earthquake | 200 | 1 |
|
||||
| `spell_solarFlare` | Solar Flare | 190 | 1 |
|
||||
| `spell_voidRift` | Void Rift | 175 | 1 |
|
||||
| `spell_flameWave` | Flame Wave | 165 | 1 |
|
||||
| `spell_iceStorm` | Ice Storm | 170 | 1 |
|
||||
| `spell_windBlade` | Wind Blade | 155 | 1 |
|
||||
| `spell_stoneBarrage` | Stone Barrage | 175 | 1 |
|
||||
| `spell_divineSmite` | Divine Smite | 175 | 1 |
|
||||
| `spell_shadowStorm` | Shadow Storm | 168 | 1 |
|
||||
| `spell_soulRend` | Soul Rend | 170 | 1 |
|
||||
|
||||
**Tier 3 Spells:**
|
||||
|
||||
| Effect ID | Name | Base Cost | Max Stacks |
|
||||
|---|---|---|---|
|
||||
| `spell_pyroclasm` | Pyroclasm | 400 | 1 |
|
||||
| `spell_tsunami` | Tsunami | 380 | 1 |
|
||||
| `spell_meteorStrike` | Meteor Strike | 420 | 1 |
|
||||
| `spell_cosmicStorm` | Cosmic Storm | 370 | 1 |
|
||||
| `spell_heavenLight` | Heaven's Light | 390 | 1 |
|
||||
| `spell_oblivion` | Oblivion | 385 | 1 |
|
||||
| `spell_deathMark` | Death Mark | 370 | 1 |
|
||||
|
||||
**Legendary Spells:**
|
||||
|
||||
| Effect ID | Name | Base Cost | Max Stacks |
|
||||
|---|---|---|---|
|
||||
| `spell_stellarNova` | Stellar Nova | 600 | 1 |
|
||||
| `spell_voidCollapse` | Void Collapse | 550 | 1 |
|
||||
| `spell_crystalShatter` | Crystal Shatter | 500 | 1 |
|
||||
|
||||
**Lightning Spells:**
|
||||
|
||||
| Effect ID | Name | Base Cost | Max Stacks |
|
||||
|---|---|---|---|
|
||||
| `spell_spark` | Spark | 70 | 1 |
|
||||
| `spell_lightningBolt` | Lightning Bolt | 90 | 1 |
|
||||
| `spell_chainLightning` | Chain Lightning | 160 | 1 |
|
||||
| `spell_stormCall` | Storm Call | 190 | 1 |
|
||||
| `spell_thunderStrike` | Thunder Strike | 350 | 1 |
|
||||
|
||||
**Frost Spells:**
|
||||
|
||||
| Effect ID | Name | Base Cost | Max Stacks |
|
||||
|---|---|---|---|
|
||||
| `spell_frostBite` | Frost Bite | 78 | 1 |
|
||||
| `spell_iceShard` | Ice Shard | 95 | 1 |
|
||||
| `spell_frostNova` | Frost Nova | 165 | 1 |
|
||||
| `spell_glacialSpike` | Glacial Spike | 200 | 1 |
|
||||
| `spell_absoluteZero` | Absolute Zero | 380 | 1 |
|
||||
|
||||
**Metal Spells:**
|
||||
|
||||
| Effect ID | Name | Base Cost | Max Stacks |
|
||||
|---|---|---|---|
|
||||
| `spell_metalShard` | Metal Shard | 85 | 1 |
|
||||
| `spell_ironFist` | Iron Fist | 120 | 1 |
|
||||
| `spell_steelTempest` | Steel Tempest | 190 | 1 |
|
||||
| `spell_furnaceBlast` | Furnace Blast | 400 | 1 |
|
||||
|
||||
**Sand Spells:**
|
||||
|
||||
| Effect ID | Name | Base Cost | Max Stacks |
|
||||
|---|---|---|---|
|
||||
| `spell_sandBlast` | Sand Blast | 72 | 1 |
|
||||
| `spell_sandstorm` | Sandstorm | 100 | 1 |
|
||||
| `spell_desertWind` | Desert Wind | 155 | 1 |
|
||||
| `spell_duneCollapse` | Dune Collapse | 300 | 1 |
|
||||
|
||||
**BlackFlame Spells:**
|
||||
|
||||
| Effect ID | Name | Base Cost | Max Stacks |
|
||||
|---|---|---|---|
|
||||
| `spell_blackFire` | Black Fire | 82 | 1 |
|
||||
| `spell_shadowEmber` | Shadow Ember | 105 | 1 |
|
||||
| `spell_darkInferno` | Dark Inferno | 175 | 1 |
|
||||
| `spell_umbralBlaze` | Umbral Blaze | 210 | 1 |
|
||||
| `spell_hellfireCurse` | Hellfire Curse | 410 | 1 |
|
||||
|
||||
**Radiant Flames Spells:**
|
||||
|
||||
| Effect ID | Name | Base Cost | Max Stacks |
|
||||
|---|---|---|---|
|
||||
| `spell_radiantBurst` | Radiant Burst | 85 | 1 |
|
||||
| `spell_holyFlame` | Holy Flame | 108 | 1 |
|
||||
| `spell_blindingSun` | Blinding Sun | 180 | 1 |
|
||||
| `spell_purifyingFire` | Purifying Fire | 215 | 1 |
|
||||
| `spell_supernovaBlast` | Supernova Blast | 420 | 1 |
|
||||
|
||||
**Miasma Spells:**
|
||||
|
||||
| Effect ID | Name | Base Cost | Max Stacks |
|
||||
|---|---|---|---|
|
||||
| `spell_toxicCloud` | Toxic Cloud | 76 | 1 |
|
||||
| `spell_plagueTouch` | Plague Touch | 100 | 1 |
|
||||
| `spell_miasmaBurst` | Miasma Burst | 165 | 1 |
|
||||
| `spell_pestilence` | Pestilence | 195 | 1 |
|
||||
| `spell_deathMiasma` | Death Miasma | 390 | 1 |
|
||||
|
||||
**Shadow Glass Spells:**
|
||||
|
||||
| Effect ID | Name | Base Cost | Max Stacks |
|
||||
|---|---|---|---|
|
||||
| `spell_shadowSpike` | Shadow Spike | 88 | 1 |
|
||||
| `spell_darkShard` | Dark Shard | 115 | 1 |
|
||||
| `spell_obsidianStorm` | Obsidian Storm | 185 | 1 |
|
||||
| `spell_voidBlade` | Void Blade | 225 | 1 |
|
||||
| `spell_shadowGlassCataclysm` | Shadow Glass Cataclysm | 415 | 1 |
|
||||
|
||||
**Exotic Spells:**
|
||||
|
||||
| Effect ID | Name | Base Cost | Max Stacks |
|
||||
|---|---|---|---|
|
||||
| `spell_soulPierce` | Soul Pierce | 500 | 1 |
|
||||
| `spell_spiritBlast` | Spirit Blast | 650 | 1 |
|
||||
| `spell_temporalWarp` | Temporal Warp | 520 | 1 |
|
||||
| `spell_chronoStasis` | Chrono Stasis | 680 | 1 |
|
||||
| `spell_plasmaBolt` | Plasma Bolt | 510 | 1 |
|
||||
| `spell_plasmaStorm` | Plasma Storm | 660 | 1 |
|
||||
|
||||
### 7.2 Mana Effects (category: `'mana'`)
|
||||
|
||||
**General Mana** — Allowed on: `['caster', 'catalyst', 'head', 'body', 'accessory']`
|
||||
|
||||
| Effect ID | Name | Description | Base Cost | Max Stacks |
|
||||
|---|---|---|---|---|
|
||||
| `mana_cap_50` | Mana Reserve | +50 max mana | 20 | 3 |
|
||||
| `mana_cap_100` | Mana Reservoir | +100 max mana | 35 | 3 |
|
||||
| `mana_regen_1` | Trickle | +1 mana/hour regen | 15 | 5 |
|
||||
| `mana_regen_2` | Stream | +2 mana/hour regen | 28 | 4 |
|
||||
| `mana_regen_5` | River | +5 mana/hour regen | 50 | 3 |
|
||||
| `click_mana_1` | Mana Tap | +1 mana per click | 20 | 5 |
|
||||
| `click_mana_3` | Mana Surge | +3 mana per click | 35 | 3 |
|
||||
|
||||
**Weapon Mana** — Allowed on: `['caster', 'catalyst', 'sword']`
|
||||
|
||||
| Effect ID | Name | Base Cost | Max Stacks |
|
||||
|---|---|---|---|
|
||||
| `weapon_mana_cap_20` | Mana Cell | 25 | 5 |
|
||||
| `weapon_mana_cap_50` | Mana Vessel | 50 | 3 |
|
||||
| `weapon_mana_cap_100` | Mana Core | 80 | 2 |
|
||||
| `weapon_mana_regen_1` | Mana Wick | 20 | 5 |
|
||||
| `weapon_mana_regen_2` | Mana Siphon | 35 | 3 |
|
||||
| `weapon_mana_regen_5` | Mana Well | 60 | 2 |
|
||||
|
||||
**Per-Element Capacity** — Allowed on: `['caster', 'catalyst', 'head', 'body', 'accessory']`
|
||||
|
||||
Generated for each non-utility element (21 elements). Three tiers per element:
|
||||
- `{element}_cap_10`: cost 30, max 5 stacks
|
||||
- `{element}_cap_25`: cost 60, max 3 stacks
|
||||
- `{element}_cap_50`: cost 100, max 2 stacks
|
||||
|
||||
### 7.3 Combat Effects (category: `'combat'`) — Casters, Hands
|
||||
|
||||
| Effect ID | Name | Description | Base Cost | Max Stacks |
|
||||
|---|---|---|---|---|
|
||||
| `damage_5` | Minor Power | +5 base damage | 15 | 5 |
|
||||
| `damage_10` | Moderate Power | +10 base damage | 28 | 4 |
|
||||
| `damage_pct_10` | Amplification | +10% damage | 30 | 3 |
|
||||
| `crit_5` | Sharp Edge | +5% crit chance | 20 | 4 |
|
||||
| `attack_speed_10` | Swift Casting | +10% attack speed | 22 | 4 |
|
||||
|
||||
### 7.4 Elemental Effects (category: `'elemental'`) — Casters, Swords
|
||||
|
||||
| Effect ID | Name | Description | Base Cost | Max Stacks |
|
||||
|---|---|---|---|---|
|
||||
| `sword_fire` | Fire Enchant | Burns enemies | 40 | 1 |
|
||||
| `sword_frost` | Frost Enchant | Prevents dodge | 40 | 1 |
|
||||
| `sword_lightning` | Lightning Enchant | 30% armor pierce | 50 | 1 |
|
||||
| `sword_void` | Void Enchant | +20% damage | 60 | 1 |
|
||||
|
||||
### 7.5 Utility Effects (category: `'utility'`)
|
||||
|
||||
| Effect ID | Name | Base Cost | Max Stacks | Allowed On |
|
||||
|---|---|---|---|---|
|
||||
| `meditate_10` | Meditative Focus | 18 | 5 | head, body, accessory |
|
||||
| `study_10` | Quick Study | 22 | 4 | caster, catalyst, head, body, hands, feet, accessory |
|
||||
| `insight_5` | Insightful | 25 | 4 | head, accessory |
|
||||
|
||||
### 7.6 Special Effects (category: `'special'`)
|
||||
|
||||
| Effect ID | Name | Base Cost | Max Stacks | Allowed On |
|
||||
|---|---|---|---|---|
|
||||
| `spell_echo_10` | Echo Chamber | 60 | 2 | caster |
|
||||
| `guardian_dmg_10` | Bane | 35 | 3 | caster, catalyst, accessory |
|
||||
| `overpower_80` | Overpower | 55 | 1 | caster, hands |
|
||||
| `first_strike` | First Strike | 45 | 1 | caster, hands |
|
||||
| `combo_master` | Combo Master | 65 | 1 | caster, hands |
|
||||
| `adrenaline_rush` | Adrenaline Rush | 50 | 1 | caster, hands |
|
||||
|
||||
### 7.7 Defense Effects (category: `'defense'`)
|
||||
|
||||
**Empty** — No defense effects are currently defined.
|
||||
|
||||
---
|
||||
|
||||
## 8. Discipline Perks That Affect Enchanting
|
||||
|
||||
| Discipline | Perk | Threshold | Effect |
|
||||
|---|---|---|---|
|
||||
| Enchantment Crafting | `enchant-1` (infinite) | 150 XP | +5 enchantPower per tier |
|
||||
| Enchantment Crafting | `enchant-2` (capped) | 300 XP | +10 enchantPower/tier, max 3 |
|
||||
| Study Basic Weapon Enchantments | `basic-weapon-fire` | 50 XP | Unlocks `sword_fire` |
|
||||
| Study Basic Weapon Enchantments | `basic-weapon-frost` | 100 XP | Unlocks `sword_frost` |
|
||||
| Study Basic Weapon Enchantments | `basic-weapon-lightning` | 150 XP | Unlocks `sword_lightning` |
|
||||
| Study Advanced Weapon Enchantments | `advanced-weapon-void` | 100 XP | Unlocks `sword_void` |
|
||||
| Study Advanced Weapon Enchantments | `advanced-weapon-damage-5` | 150 XP | Unlocks `damage_5` |
|
||||
| Study Advanced Weapon Enchantments | `advanced-weapon-crit` | 200 XP | Unlocks `crit_5` |
|
||||
| Study Advanced Weapon Enchantments | `advanced-weapon-attack-speed` | 250 XP | Unlocks `attack_speed_10` |
|
||||
| Study Utility Enchantments | `utility-meditate` | 50 XP | Unlocks `meditate_10` |
|
||||
| Study Utility Enchantments | `utility-study` | 100 XP | Unlocks `study_10` |
|
||||
| Study Utility Enchantments | `utility-insight` | 150 XP | Unlocks `insight_5` |
|
||||
| Study Mana Enchantments | `mana-cap-50` | 75 XP | Unlocks `mana_cap_50` |
|
||||
| Study Mana Enchantments | `mana-cap-100` | 150 XP | Unlocks `mana_cap_100` |
|
||||
| Study Mana Enchantments | `mana-regen-1` | 100 XP | Unlocks `mana_regen_1` |
|
||||
| Study Mana Enchantments | `mana-regen-2` | 200 XP | Unlocks `mana_regen_2` |
|
||||
| Study Mana Enchantments | `click-mana-1` | 125 XP | Unlocks `click_mana_1` |
|
||||
| Study Mana Enchantments | `click-mana-3` | 225 XP | Unlocks `click_mana_3` |
|
||||
| Study Basic Spell Enchantments | 8 perks | 50–150 XP | Unlock 8 basic spell enchants |
|
||||
| Study Intermediate Spell Enchantments | 6 perks | 80–120 XP | Unlock 6 intermediate spell enchants |
|
||||
| Study Advanced Spell Enchantments | 10 perks | 100–200 XP | Unlock 10 advanced spell enchants |
|
||||
| Study Special Enchantments | 6 perks | 80–200 XP | Unlock 6 special enchants |
|
||||
|
||||
---
|
||||
|
||||
## 9. Attunement Level Interactions
|
||||
|
||||
Enchanter level does **not** directly affect enchanting mechanics (timings, costs,
|
||||
capacity). It affects:
|
||||
|
||||
1. **Raw mana regen**: `0.5 × 1.5^(level-1)` per hour — more raw mana for enchanting
|
||||
2. **Transference conversion**: `0.2 × 1.5^(level-1)` per hour — more transference mana for Enchanter disciplines
|
||||
3. **Enchanting XP → Attunement XP**: 1 Enchanter XP per 10 capacity used
|
||||
|
||||
---
|
||||
|
||||
## 10. Acceptance Criteria
|
||||
|
||||
| # | Criterion |
|
||||
|---|---|
|
||||
| AC-1 | Design stage takes `1 + 0.5 × totalStacks` hours; progress accumulates at 0.04 hours/tick. |
|
||||
| AC-2 | Hasty Enchanter reduces design time by 25% on repeat designs only. |
|
||||
| AC-3 | Instant Designs has a 10% chance per tick to complete the design immediately. |
|
||||
| AC-4 | Dual design slot is available when Enchant Mastery is active and first slot is occupied. |
|
||||
| AC-5 | Prepare stage takes `2 + floor(capacity/50)` hours and costs `capacity × 10` total mana. |
|
||||
| AC-6 | Prepare removes all enchantments, resets usedCapacity to 0, resets rarity to 'common'. |
|
||||
| AC-7 | Disenchant recovery rate is `0.10 + disenchantLevel × 0.20` of each enchantment's actual cost. |
|
||||
| AC-8 | Apply stage takes `2 + totalStacks` hours and costs `20 + sum(stacks × 5)` mana/hour. |
|
||||
| AC-9 | Free enchant chances are additive (max 60%) and skip mana cost for that tick. |
|
||||
| AC-10 | Pure Essence grants 1.25× stacks (ceil) for effects with base cost < 100. |
|
||||
| AC-11 | Stacking cost formula: `baseCost × (1 + i × 0.2)` for stack index i, reduced by efficiencyBonus. |
|
||||
| AC-12 | Cancellation refunds unspent progress at 100% and spent progress at 50%, blended. |
|
||||
| AC-13 | All enchantment effects are gated behind discipline perk thresholds and cannot be used until unlocked. |
|
||||
| AC-14 | Equipment type capacity limits are enforced — designs exceeding capacity are rejected. |
|
||||
| AC-15 | Spell effects can only be applied to caster equipment. |
|
||||
|
||||
---
|
||||
|
||||
## 11. Files Reference
|
||||
|
||||
| File | Role |
|
||||
|---|---|
|
||||
| `src/lib/game/crafting-design.ts` | Design stage logic, timing, validation |
|
||||
| `src/lib/game/crafting-prep.ts` | Prepare stage logic, disenchant recovery |
|
||||
| `src/lib/game/crafting-apply.ts` | Apply stage logic, free enchant, Pure Essence |
|
||||
| `src/lib/game/crafting-utils.ts` | Shared utilities, capacity cost, cancellation refund |
|
||||
| `src/lib/game/crafting-attunements.ts` | Attunement-crafting integration, enchanting XP |
|
||||
| `src/lib/game/data/enchantments/` | All enchantment effect definitions (7 categories) |
|
||||
| `src/lib/game/crafting-actions/design-actions.ts` | Design stage store actions |
|
||||
| `src/lib/game/crafting-actions/preparation-actions.ts` | Prepare stage store actions |
|
||||
| `src/lib/game/crafting-actions/application-actions.ts` | Apply stage store actions |
|
||||
| `src/lib/game/crafting-actions/disenchant-actions.ts` | Disenchant action |
|
||||
| `src/components/game/tabs/CraftingTab.tsx` | Crafting tab wrapper |
|
||||
| `src/components/game/crafting/EnchantmentDesigner.tsx` | Design UI |
|
||||
| `src/components/game/crafting/EnchantmentPreparer.tsx` | Prepare UI |
|
||||
| `src/components/game/crafting/EnchantmentApplier.tsx` | Apply UI |
|
||||
@@ -0,0 +1,264 @@
|
||||
# Fabricator Attunement — Design Spec
|
||||
|
||||
> Describes the Fabricator attunement: identity, unlock flow, mana behavior, full
|
||||
> discipline list with stats/perks, systems unlocked, and attunement level interactions.
|
||||
|
||||
---
|
||||
|
||||
## 1. Objective
|
||||
|
||||
The Fabricator is the crafting and golemancy attunement. It provides access to
|
||||
Earth-based disciplines that unlock equipment fabrication recipes, golem summoning,
|
||||
and crafting cost reduction. The Fabricator is the primary source of custom
|
||||
equipment and the golem combat system.
|
||||
|
||||
---
|
||||
|
||||
## 2. Identity
|
||||
|
||||
| Property | Value |
|
||||
|---|---|
|
||||
| **ID** | `fabricator` |
|
||||
| **Slot** | `leftHand` |
|
||||
| **Icon** | `⚒️` |
|
||||
| **Color** | `#F4A261` (Earth) |
|
||||
| **Primary Mana** | `earth` |
|
||||
| **Raw Mana Regen** | +0.4/hour (base, scales with `1.5^(level-1)`) |
|
||||
| **Conversion Rate** | 0.25 raw→earth/hour (base, scales with `1.5^(level-1)`) |
|
||||
| **Unlock** | Prove crafting worth |
|
||||
| **Capabilities** | `['golemCrafting', 'gearCrafting', 'earthShaping']` |
|
||||
| **Skill Categories** | `['fabrication', 'golemancy']` |
|
||||
|
||||
---
|
||||
|
||||
## 3. Unlock Condition and Flow
|
||||
|
||||
**Condition:** Prove your worth as a crafter.
|
||||
|
||||
**Unlock flow:**
|
||||
1. Meet the crafting-related unlock condition
|
||||
2. Fabricator becomes available for activation
|
||||
3. Player activates Fabricator → initialized at `{ active: true, level: 1, experience: 0 }`
|
||||
4. Fabricator disciplines become available (5 total)
|
||||
|
||||
The unlock condition is stored as a descriptive string:
|
||||
`"Prove your worth as a crafter"`
|
||||
|
||||
---
|
||||
|
||||
## 4. Raw Mana Regen Contribution
|
||||
|
||||
Base regen: **+0.4/hour** (at level 1). Scales exponentially:
|
||||
|
||||
```
|
||||
effectiveRegen = 0.4 × 1.5^(level - 1)
|
||||
```
|
||||
|
||||
| Level | Raw Regen |
|
||||
|---|---|
|
||||
| 1 | 0.400/hr |
|
||||
| 5 | 2.025/hr |
|
||||
| 10 | 15.377/hr |
|
||||
|
||||
---
|
||||
|
||||
## 5. Mana Conversion Behavior
|
||||
|
||||
The Fabricator converts raw mana to Earth:
|
||||
|
||||
```
|
||||
effectiveConversionRate = 0.25 × 1.5^(level - 1)
|
||||
```
|
||||
|
||||
At level 10, the Fabricator converts **9.61 raw→earth/hour**.
|
||||
|
||||
---
|
||||
|
||||
## 6. Disciplines
|
||||
|
||||
The Fabricator's discipline pool contains **5 disciplines**.
|
||||
|
||||
### 6.1 Golem Crafting (`golem-crafting`)
|
||||
|
||||
| Field | Value |
|
||||
|---|---|
|
||||
| **Mana Type** | `earth` |
|
||||
| **Base Cost** | 10 |
|
||||
| **Stat Bonus** | `golemCapacity` +2 (base) |
|
||||
| **Scaling Factor** | 80 |
|
||||
| **Difficulty Factor** | 150 |
|
||||
| **Drain Base** | 4 |
|
||||
|
||||
**Perks:**
|
||||
|
||||
| Perk ID | Type | Threshold | Bonus |
|
||||
|---|---|---|---|
|
||||
| `golem-1` | `once` | 200 | Unlock golem summoning |
|
||||
| `golem-2` | `capped` | 500 | +1 Golem Capacity per tier, interval 500 XP, max 2 tiers |
|
||||
|
||||
### 6.2 Crafting Efficiency (`crafting-efficiency`)
|
||||
|
||||
| Field | Value |
|
||||
|---|---|
|
||||
| **Mana Type** | `earth` |
|
||||
| **Base Cost** | 12 |
|
||||
| **Stat Bonus** | `craftingCostReduction` +15 (base) |
|
||||
| **Scaling Factor** | 90 |
|
||||
| **Difficulty Factor** | 180 |
|
||||
| **Drain Base** | 6 |
|
||||
|
||||
**Perks:**
|
||||
|
||||
| Perk ID | Type | Threshold | Bonus |
|
||||
|---|---|---|---|
|
||||
| `efficiency-1` | `once` | 300 | +10% Crafting Cost Reduction |
|
||||
|
||||
### 6.3 Study Fabricator Recipes (`study-fabricator-recipes`)
|
||||
|
||||
| Field | Value |
|
||||
|---|---|
|
||||
| **Mana Type** | `earth` |
|
||||
| **Base Cost** | 10 |
|
||||
| **Stat Bonus** | `enchantPower` +3 (base) |
|
||||
| **Scaling Factor** | 80 |
|
||||
| **Difficulty Factor** | 100 |
|
||||
| **Drain Base** | 2 |
|
||||
|
||||
**Perks:**
|
||||
|
||||
| Perk ID | Type | Threshold | Unlocks |
|
||||
|---|---|---|---|
|
||||
| `fabricator-earth` | `once` | 50 | `earthHelm`, `earthChest`, `earthBoots` |
|
||||
| `fabricator-metal` | `once` | 100 | `metalBlade`, `metalShield`, `metalGloves` |
|
||||
| `fabricator-sand` | `once` | 150 | `sandBoots`, `sandGloves`, `sandVest` |
|
||||
| `fabricator-crystal` | `once` | 200 | `crystalWand`, `crystalRing`, `crystalAmulet` |
|
||||
|
||||
### 6.4 Study Wizard Equipment (`study-wizard-branch`)
|
||||
|
||||
| Field | Value |
|
||||
|---|---|
|
||||
| **Mana Type** | `earth` |
|
||||
| **Base Cost** | 15 |
|
||||
| **Requires** | `study-fabricator-recipes` |
|
||||
| **Stat Bonus** | `enchantPower` +5 (base) |
|
||||
| **Scaling Factor** | 100 |
|
||||
| **Difficulty Factor** | 150 |
|
||||
| **Drain Base** | 3 |
|
||||
|
||||
**Perks:**
|
||||
|
||||
| Perk ID | Type | Threshold | Unlocks |
|
||||
|---|---|---|---|
|
||||
| `wizard-oak` | `once` | 50 | `oakStaff` |
|
||||
| `wizard-arcanist-staff` | `once` | 100 | `arcanistStaff` |
|
||||
| `wizard-battlestaff` | `once` | 150 | `battlestaff` |
|
||||
| `wizard-arcanist-gear` | `once` | 200 | `arcanistCirclet`, `arcanistRobe` |
|
||||
| `wizard-void-catalyst` | `once` | 250 | `voidCatalyst` |
|
||||
| `wizard-arcanist-pendant` | `once` | 300 | `arcanistPendant` |
|
||||
|
||||
### 6.5 Study Physical Equipment (`study-physical-branch`)
|
||||
|
||||
| Field | Value |
|
||||
|---|---|
|
||||
| **Mana Type** | `earth` |
|
||||
| **Base Cost** | 15 |
|
||||
| **Requires** | `study-fabricator-recipes` |
|
||||
| **Stat Bonus** | `enchantPower` +5 (base) |
|
||||
| **Scaling Factor** | 100 |
|
||||
| **Difficulty Factor** | 150 |
|
||||
| **Drain Base** | 3 |
|
||||
|
||||
**Perks:**
|
||||
|
||||
| Perk ID | Type | Threshold | Unlocks |
|
||||
|---|---|---|---|
|
||||
| `physical-crystal-blade` | `once` | 50 | `crystalBlade` |
|
||||
| `physical-arcanist-blade` | `once` | 100 | `arcanistBlade` |
|
||||
| `physical-void-blade` | `once` | 150 | `voidBlade` |
|
||||
| `physical-battle-gear` | `once` | 200 | `battleHelm`, `battleRobe` |
|
||||
| `physical-battle-boots` | `once` | 250 | `battleBoots` |
|
||||
| `physical-combat-gauntlets` | `once` | 300 | `combatGauntlets` |
|
||||
|
||||
---
|
||||
|
||||
## 7. Systems Unlocked
|
||||
|
||||
The Fabricator attunement gates two systems:
|
||||
|
||||
1. **Golemancy** (see `golemancy-spec.md`): Summon and maintain golems for spire combat
|
||||
2. **Item Fabrication** (see `item-fabrication-spec.md`): Craft equipment and materials from recipes
|
||||
|
||||
---
|
||||
|
||||
## 8. Puzzle Room Behavior
|
||||
|
||||
In the spire, every 7th floor has a puzzle room. When the room type is
|
||||
`fabricator_trial`, progress scales at 2.5–3% per tick per Fabricator level.
|
||||
|
||||
---
|
||||
|
||||
## 9. Attunement Level Interactions
|
||||
|
||||
Higher Fabricator level affects:
|
||||
|
||||
1. **Raw mana regen**: `0.4 × 1.5^(level-1)` per hour
|
||||
2. **Earth conversion rate**: `0.25 × 1.5^(level-1)` per hour
|
||||
3. **Golem slots**: `floor(fabricatorLevel / 2)` — Fabricator level directly determines golem capacity
|
||||
|
||||
| Fabricator Level | Golem Slots |
|
||||
|---|---|
|
||||
| 1 | 0 |
|
||||
| 2–3 | 1 |
|
||||
| 4–5 | 2 |
|
||||
| 6–7 | 3 |
|
||||
| 8–9 | 4 |
|
||||
| 10 | 5 |
|
||||
|
||||
---
|
||||
|
||||
## 10. Discipline Dependency Chain
|
||||
|
||||
```
|
||||
golem-crafting (root)
|
||||
crafting-efficiency (root)
|
||||
study-fabricator-recipes (root)
|
||||
└── study-wizard-branch
|
||||
└── study-physical-branch
|
||||
```
|
||||
|
||||
3 root disciplines. Maximum dependency depth: 2.
|
||||
|
||||
---
|
||||
|
||||
## 11. Acceptance Criteria
|
||||
|
||||
| # | Criterion |
|
||||
|---|---|
|
||||
| AC-1 | Fabricator is locked until the unlock condition is met. |
|
||||
| AC-2 | All 5 Fabricator disciplines are available when Fabricator is active. |
|
||||
| AC-3 | `study-wizard-branch` and `study-physical-branch` require `study-fabricator-recipes`. |
|
||||
| AC-4 | Golem summoning is unlocked at Golem Crafting discipline threshold 200 XP. |
|
||||
| AC-5 | Golem capacity is 2 (base) + up to 2 (from capped perk) = max 4 from disciplines. |
|
||||
| AC-6 | Golem slots from attunement level: `floor(fabricatorLevel / 2)`, max 5 at level 10. |
|
||||
| AC-7 | All recipe unlock perks fire at the correct discipline XP thresholds. |
|
||||
| AC-8 | Crafting Efficiency discipline reduces material costs by 15% (base) + 10% (perk). |
|
||||
| AC-9 | Fabricator `fabricator_trial` puzzle rooms grant bonus progress per Fabricator level. |
|
||||
| AC-10 | Fabricator level scales raw regen and earth conversion by `1.5^(level-1)`. |
|
||||
|
||||
---
|
||||
|
||||
## 12. Files Reference
|
||||
|
||||
| File | Role |
|
||||
|---|---|
|
||||
| `src/lib/game/data/attunements.ts` | Fabricator definition |
|
||||
| `src/lib/game/data/disciplines/fabricator.ts` | Fabricator disciplines (5) |
|
||||
| `src/lib/game/data/golems/` | Golem definitions (10 golems) |
|
||||
| `src/lib/game/crafting-fabricator.ts` | Fabrication crafting logic |
|
||||
| `src/lib/game/data/fabricator-recipes.ts` | Core equipment recipes |
|
||||
| `src/lib/game/data/fabricator-material-recipes.ts` | Material recipes |
|
||||
| `src/lib/game/data/fabricator-physical-recipes.ts` | Physical branch recipes |
|
||||
| `src/lib/game/data/fabricator-wizard-recipes.ts` | Wizard branch recipes |
|
||||
| `src/components/game/tabs/GolemancyTab.tsx` | Golemancy UI |
|
||||
| `docs/specs/attunements/fabricator/systems/golemancy-spec.md` | Golemancy system spec |
|
||||
| `docs/specs/attunements/fabricator/systems/item-fabrication-spec.md` | Item fabrication spec |
|
||||
@@ -0,0 +1,333 @@
|
||||
# Golemancy System — Design Spec
|
||||
|
||||
> Describes the Fabricator attunement's combat system: golem types, loadout
|
||||
> configuration, summoning lifecycle, maintenance costs, room duration, combat
|
||||
> behavior, and discipline interactions.
|
||||
>
|
||||
> **⚠ Spec-defined, implementation pending.** This spec is based on
|
||||
> `docs/specs/spire-combat-spec.md` §9 and represents the intended design.
|
||||
> The current code has golem data defined but disconnected from the combat pipeline.
|
||||
|
||||
---
|
||||
|
||||
## 1. Objective
|
||||
|
||||
Golemancy is the Fabricator attunement's combat contribution. The player configures
|
||||
a golem loadout outside the spire, then golems are automatically summoned at each
|
||||
room entry, fight alongside the player, and disappear after a fixed number of rooms
|
||||
or if their maintenance cost cannot be met.
|
||||
|
||||
**Design goals:**
|
||||
- Golems provide parallel combat damage independent of the player's spells
|
||||
- Different golem types offer tactical variety (single-target, AoE, fast, tanky)
|
||||
- Maintenance cost and room duration create resource management decisions
|
||||
- Hybrid golems require dual-attunement investment (Enchanter 5 + Fabricator 5)
|
||||
- Golem loadout configuration outside spire allows strategic planning
|
||||
|
||||
---
|
||||
|
||||
## 2. Golem Slot Formula
|
||||
|
||||
Golem slots come from **two sources** that add together:
|
||||
|
||||
### 2.1 From Attunement Level
|
||||
|
||||
```
|
||||
attunementSlots = floor(fabricatorLevel / 2)
|
||||
```
|
||||
|
||||
| Fabricator Level | Slots |
|
||||
|---|---|
|
||||
| 1 | 0 |
|
||||
| 2–3 | 1 |
|
||||
| 4–5 | 2 |
|
||||
| 6–7 | 3 |
|
||||
| 8–9 | 4 |
|
||||
| 10 | 5 |
|
||||
|
||||
### 2.2 From Discipline
|
||||
|
||||
The Golem Crafting discipline provides:
|
||||
- Base `golemCapacity`: +2
|
||||
- Perk `golem-2` (capped, threshold 500, maxTier 2): +1 per tier = up to +2
|
||||
|
||||
**Maximum total golem slots: 5 (attunement) + 2 (discipline) = 7**
|
||||
|
||||
> **Note:** The AGENTS.md states `floor(fabricatorLevel / 2)` with max 5 at level 10.
|
||||
> The discipline-based capacity is additive on top of this.
|
||||
|
||||
---
|
||||
|
||||
## 3. Golem Loadout Configuration
|
||||
|
||||
The player configures a **golem loadout** from the Golemancy tab before entering
|
||||
the spire. The loadout defines which golems to attempt to summon and in what order.
|
||||
This configuration persists across rooms but not across spire runs.
|
||||
|
||||
The loadout is a prioritized list of golem IDs. On each room entry, the system
|
||||
iterates the loadout in order, attempting to summon each golem.
|
||||
|
||||
---
|
||||
|
||||
## 4. All 10 Golem Types
|
||||
|
||||
### 4.1 Base Golems (1)
|
||||
|
||||
| Field | Earth Golem |
|
||||
|---|---|
|
||||
| **ID** | `earthGolem` |
|
||||
| **Tier** | 1 |
|
||||
| **Element** | Earth |
|
||||
| **Damage** | 8 |
|
||||
| **Attack Speed** | 1.5/hr |
|
||||
| **HP** (display) | 50 |
|
||||
| **Armor Pierce** | 15% |
|
||||
| **AoE** | No |
|
||||
| **Max Room Duration** | 3 |
|
||||
| **Summon Cost** | 10 earth |
|
||||
| **Maintenance Cost** | 0.5 earth/hr |
|
||||
| **Unlock** | Fabricator level 2 |
|
||||
|
||||
### 4.2 Elemental Golems (3)
|
||||
|
||||
| Field | Steel Golem | Crystal Golem | Sand Golem |
|
||||
|---|---|---|---|
|
||||
| **ID** | `steelGolem` | `crystalGolem` | `sandGolem` |
|
||||
| **Tier** | 2 | 3 | 2 |
|
||||
| **Element** | Metal | Crystal | Sand |
|
||||
| **Damage** | 12 | 18 | 10 |
|
||||
| **Attack Speed** | 1.2/hr | 1.0/hr | 2.0/hr |
|
||||
| **HP** (display) | 60 | 40 | 45 |
|
||||
| **Armor Pierce** | 35% | 25% | 15% |
|
||||
| **AoE** | No | No | **Yes (2 targets)** |
|
||||
| **Max Room Duration** | 3 | 4 | 3 |
|
||||
| **Summon Cost** | 8 metal + 5 earth | 6 crystal + 3 earth | 10 sand + 4 earth |
|
||||
| **Maintenance Cost** | 0.6 metal + 0.2 earth/hr | 0.4 crystal + 0.2 earth/hr | 0.6 sand + 0.25 earth/hr |
|
||||
| **Unlock** | Metal mana unlocked | Crystal mana unlocked | Sand mana unlocked |
|
||||
|
||||
### 4.3 Hybrid Golems (6) — Require Enchanter 5 + Fabricator 5
|
||||
|
||||
| Field | Lava Golem | Galvanic Golem | Obsidian Golem |
|
||||
|---|---|---|---|
|
||||
| **ID** | `lavaGolem` | `galvanicGolem` | `obsidianGolem` |
|
||||
| **Tier** | 3 | 3 | 4 |
|
||||
| **Elements** | Earth + Fire | Metal + Lightning | Earth + Dark |
|
||||
| **Damage** | 15 | 10 | 25 |
|
||||
| **Attack Speed** | 1.0/hr | 3.5/hr | 0.8/hr |
|
||||
| **HP** (display) | 70 | 45 | 55 |
|
||||
| **Armor Pierce** | 20% | 45% | 50% |
|
||||
| **AoE** | **Yes (2 targets)** | No | No |
|
||||
| **Max Room Duration** | 4 | 4 | 5 |
|
||||
| **Summon Cost** | 15 earth + 12 fire | 12 metal + 8 lightning | 18 earth + 10 dark |
|
||||
| **Maintenance Cost** | 0.6 earth + 0.7 fire/hr | 0.4 metal + 0.7 lightning/hr | 0.5 earth + 0.6 dark/hr |
|
||||
| **Special** | Burn DoT | Lightning Speed | Devastating Strike |
|
||||
| **Unlock** | Enchanter 5 + Fabricator 5 | Enchanter 5 + Fabricator 5 | Enchanter 5 + Fabricator 5 |
|
||||
|
||||
| Field | Prism Golem | Quicksilver Golem | Voidstone Golem |
|
||||
|---|---|---|---|
|
||||
| **ID** | `prismGolem` | `quicksilverGolem` | `voidstoneGolem` |
|
||||
| **Tier** | 4 | 3 | 4 |
|
||||
| **Elements** | Crystal + Light | Metal + Water | Earth + Void |
|
||||
| **Damage** | 28 | 14 | **40** |
|
||||
| **Attack Speed** | 2.0/hr | **4.0/hr** | 0.6/hr |
|
||||
| **HP** (display) | 60 | 55 | **100** |
|
||||
| **Armor Pierce** | 45% | 35% | **60%** |
|
||||
| **AoE** | **Yes (3 targets)** | No | **Yes (3 targets)** |
|
||||
| **Max Room Duration** | 5 | 4 | 5 |
|
||||
| **Summon Cost** | 16 crystal + 10 light | 10 metal + 8 water | 22 earth + 14 void |
|
||||
| **Maintenance Cost** | 0.6 crystal + 0.6 light/hr | 0.4 metal + 0.4 water/hr | 0.5 earth + 0.9 void/hr |
|
||||
| **Special** | Piercing Beams | Flow (evasion) | Void Infusion |
|
||||
| **Unlock** | Enchanter 5 + Fabricator 5 | Enchanter 5 + Fabricator 5 | Enchanter 5 + Fabricator 5 |
|
||||
|
||||
### 4.4 Summary Table
|
||||
|
||||
| Golem | Tier | DMG | SPD | HP | Pierce | AoE | Targets | Rooms | Unlock |
|
||||
|---|---|---|---|---|---|---|---|---|---|
|
||||
| Earth | 1 | 8 | 1.5 | 50 | 15% | No | 1 | 3 | Fabricator Lv2 |
|
||||
| Steel | 2 | 12 | 1.2 | 60 | 35% | No | 1 | 3 | Metal mana |
|
||||
| Crystal | 3 | 18 | 1.0 | 40 | 25% | No | 1 | 4 | Crystal mana |
|
||||
| Sand | 2 | 10 | 2.0 | 45 | 15% | Yes | 2 | 3 | Sand mana |
|
||||
| Lava | 3 | 15 | 1.0 | 70 | 20% | Yes | 2 | 4 | Ench5+Fab5 |
|
||||
| Galvanic | 3 | 10 | 3.5 | 45 | 45% | No | 1 | 4 | Ench5+Fab5 |
|
||||
| Obsidian | 4 | 25 | 0.8 | 55 | 50% | No | 1 | 5 | Ench5+Fab5 |
|
||||
| Prism | 4 | 28 | 2.0 | 60 | 45% | Yes | 3 | 5 | Ench5+Fab5 |
|
||||
| Quicksilver | 3 | 14 | 4.0 | 55 | 35% | No | 1 | 4 | Ench5+Fab5 |
|
||||
| Voidstone | 4 | 40 | 0.6 | 100 | 60% | Yes | 3 | 5 | Ench5+Fab5 |
|
||||
|
||||
---
|
||||
|
||||
## 5. Summoning on Room Entry
|
||||
|
||||
When the player enters a new combat room:
|
||||
|
||||
```
|
||||
onRoomEntry():
|
||||
for each golem in golemLoadout:
|
||||
if player has enough mana of golem.summonCostType >= golem.summonCost:
|
||||
deductMana(golem.summonCost, golem.summonCostType)
|
||||
activeGolems.push({
|
||||
...golemDef,
|
||||
roomsRemaining: golemDef.maxRoomDuration,
|
||||
attackProgress: 0,
|
||||
})
|
||||
activityLog("${golem.name} summoned")
|
||||
else:
|
||||
activityLog("Not enough mana to summon ${golem.name} — skipped")
|
||||
```
|
||||
|
||||
**Key rules:**
|
||||
- Golems that cannot be summoned (insufficient mana) are **not re-attempted** within the same room
|
||||
- Failed golems will be attempted again on the next room entry
|
||||
- Summoning order follows the loadout priority list
|
||||
|
||||
---
|
||||
|
||||
## 6. Golem Combat
|
||||
|
||||
Each active golem attacks on its own `attackProgress` timer, identical to swords:
|
||||
|
||||
```
|
||||
golemProgress += HOURS_PER_TICK × golem.attackSpeed
|
||||
while golemProgress >= 1:
|
||||
dmg = golem.baseDamage
|
||||
if golem.element:
|
||||
dmg ×= getElementalBonus(golem.element, enemy.element)
|
||||
applyGolemEffects(golem, dmg, enemy)
|
||||
applyDamageToRoom(dmg)
|
||||
golemProgress -= 1
|
||||
```
|
||||
|
||||
**Key rules:**
|
||||
- Golems ignore Executioner and Berserker discipline specials
|
||||
- AoE golems distribute damage across multiple targets
|
||||
- Elemental matchup applies if the golem has an element
|
||||
|
||||
---
|
||||
|
||||
## 7. Maintenance Cost
|
||||
|
||||
Each tick, each active golem checks its maintenance cost:
|
||||
|
||||
```
|
||||
tickGolemMaintenance(golem):
|
||||
if player mana[golem.maintenanceCostType] >= golem.maintenanceCost × HOURS_PER_TICK:
|
||||
deductMana(golem.maintenanceCost × HOURS_PER_TICK, golem.maintenanceCostType)
|
||||
else:
|
||||
dismiss(golem)
|
||||
activityLog("${golem.name} dismissed — insufficient ${golem.maintenanceCostType} mana")
|
||||
```
|
||||
|
||||
**Key rules:**
|
||||
- A dismissed golem is **not re-summoned mid-room**
|
||||
- It will be re-attempted on the next room entry if mana has recovered
|
||||
- Maintenance is checked every tick, not just on room transitions
|
||||
|
||||
---
|
||||
|
||||
## 8. Room Duration Limit
|
||||
|
||||
```
|
||||
onRoomCleared():
|
||||
for each activeGolem:
|
||||
activeGolem.roomsRemaining -= 1
|
||||
if activeGolem.roomsRemaining <= 0:
|
||||
dismiss(golem)
|
||||
activityLog("${golem.name} has faded after ${maxRoomDuration} rooms")
|
||||
```
|
||||
|
||||
**Key rules:**
|
||||
- Room duration ticks down on room **clear**, not on room **entry**
|
||||
- Golems persist through the full room they were summoned in
|
||||
- When `roomsRemaining` reaches 0, the golem is dismissed
|
||||
|
||||
---
|
||||
|
||||
## 9. Golem Data Shape
|
||||
|
||||
```typescript
|
||||
interface GolemDefinition {
|
||||
id: string;
|
||||
name: string;
|
||||
tier: number; // 1–4 (determines general power)
|
||||
baseDamage: number;
|
||||
attackSpeed: number; // attacks per in-game hour
|
||||
element?: ElementType; // optional elemental type for matchup
|
||||
maxRoomDuration: number; // rooms before disappearing
|
||||
summonCost: number;
|
||||
summonCostType: ElementType | 'raw';
|
||||
maintenanceCost: number; // per in-game hour
|
||||
maintenanceCostType: ElementType | 'raw';
|
||||
onHitEffect?: GolemHitEffect; // DoT, AoE, etc.
|
||||
armorPierce?: number; // 0-1, bypasses this fraction of enemy armor
|
||||
aoe?: boolean;
|
||||
aoeTargets?: number;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 10. Discipline Interactions
|
||||
|
||||
### 10.1 Golem Crafting Discipline
|
||||
|
||||
| Perk | Effect |
|
||||
|---|---|
|
||||
| `golem-1` (once @ 200 XP) | Unlocks golem summoning ability |
|
||||
| `golem-2` (capped @ 500, maxTier 2) | +1 Golem Capacity per tier (max +2) |
|
||||
|
||||
### 10.2 Fabricator Level
|
||||
|
||||
Directly determines base golem slots: `floor(fabricatorLevel / 2)`.
|
||||
|
||||
### 10.3 Dual Attunement Requirement
|
||||
|
||||
All 6 hybrid golems require **Enchanter 5 + Fabricator 5**. This means the player
|
||||
must have both attunements active and leveled to at least 5 to access the most
|
||||
powerful golem types.
|
||||
|
||||
---
|
||||
|
||||
## 11. Known Gaps / Implementation Status
|
||||
|
||||
| Feature | Status |
|
||||
|---|---|
|
||||
| Golem data definitions | ✅ Complete (10 golems in `data/golems/`) |
|
||||
| Golem loadout UI | ✅ Partial (GolemancyTab exists) |
|
||||
| Summoning on room entry | ❌ Not wired into combat tick |
|
||||
| Maintenance cost per tick | ❌ Not wired into combat tick |
|
||||
| Room duration tracking | ❌ Not wired into room clear |
|
||||
| Golem combat (attack timer) | ❌ Not wired into combat tick |
|
||||
| Golemancy combat pipeline | ❌ `golem-combat-actions.ts` exists but disconnected |
|
||||
|
||||
---
|
||||
|
||||
## 12. Acceptance Criteria
|
||||
|
||||
| # | Criterion |
|
||||
|---|---|
|
||||
| AC-1 | Golem slots = `floor(fabricatorLevel / 2)` + discipline bonus. |
|
||||
| AC-2 | Golems are summoned on room entry if mana allows; failed summons are skipped for that room. |
|
||||
| AC-3 | Each golem attacks on its own timer using its `attackSpeed` stat. |
|
||||
| AC-4 | Elemental matchup applies to golem attacks when the golem has an element. |
|
||||
| AC-5 | AoE golems distribute damage across `aoeTargets` enemies. |
|
||||
| AC-6 | Maintenance cost is deducted each tick; golems dismiss if cost cannot be met. |
|
||||
| AC-7 | Dismissed golems are not re-summoned mid-room. |
|
||||
| AC-8 | Room duration ticks down on room clear, not entry. |
|
||||
| AC-9 | Golems disappear after `maxRoomDuration` rooms. |
|
||||
| AC-10 | Hybrid golems require Enchanter 5 + Fabricator 5. |
|
||||
| AC-11 | Golem loadout is configured outside the spire and persists across rooms. |
|
||||
| AC-12 | Golem HP is display-only; golems don't take damage from enemies. |
|
||||
|
||||
---
|
||||
|
||||
## 13. Files Reference
|
||||
|
||||
| File | Role |
|
||||
|---|---|
|
||||
| `src/lib/game/data/golems/golems-data.ts` | All 10 golem definitions |
|
||||
| `src/lib/game/data/golems/types.ts` | Golem type definitions |
|
||||
| `src/lib/game/data/disciplines/fabricator.ts` | Golem Crafting discipline |
|
||||
| `src/lib/game/stores/golem-combat-actions.ts` | Golem combat actions (disconnected) |
|
||||
| `src/lib/game/stores/pipelines/golem-combat.ts` | Golem combat pipeline (disconnected) |
|
||||
| `src/components/game/tabs/GolemancyTab.tsx` | Golemancy UI |
|
||||
| `docs/specs/spire-combat-spec.md` §9 | Authoritative golemancy spec |
|
||||
@@ -0,0 +1,347 @@
|
||||
# Item Fabrication System — Design Spec
|
||||
|
||||
> Describes the Fabricator attunement's crafting system: recipe categories, unlock
|
||||
> gates, material costs, crafting flow, and how fabricated items differ from base loot.
|
||||
|
||||
---
|
||||
|
||||
## 1. Objective
|
||||
|
||||
Item Fabrication is the Fabricator attunement's non-combat crafting system. It allows
|
||||
the player to craft materials and equipment using mana and component items. Recipes
|
||||
are unlocked through Fabricator discipline perks, and the resulting equipment can
|
||||
carry pre-applied enchantments, making fabrication a parallel path to the Enchanter's
|
||||
enchanting system.
|
||||
|
||||
**Design goals:**
|
||||
- Fabricated equipment provides an alternative to loot drops
|
||||
- Material crafting creates a multi-tier resource pipeline
|
||||
- Discipline-gated recipe unlocks reward Fabricator attunement investment
|
||||
- Pre-applied enchantments on crafted gear offer unique combinations
|
||||
- Crafting Efficiency discipline reduces material costs
|
||||
|
||||
---
|
||||
|
||||
## 2. Recipe Categories
|
||||
|
||||
### 2.1 Overview
|
||||
|
||||
| Category | File | Count | Unlock Gate |
|
||||
|---|---|---|---|
|
||||
| Material Recipes | `fabricator-material-recipes.ts` | 15 | None (base recipes) |
|
||||
| Core Equipment (Elemental) | `fabricator-recipes.ts` | 12 | Study Fabricator Recipes discipline |
|
||||
| Wizard Branch | `fabricator-wizard-recipes.ts` | 14 | Study Wizard Equipment discipline |
|
||||
| Physical Branch | `fabricator-physical-recipes.ts` | 7 | Study Physical Equipment discipline |
|
||||
| **Total** | | **48** | |
|
||||
|
||||
### 2.2 Recipe Type Structure
|
||||
|
||||
```typescript
|
||||
interface FabricatorRecipe {
|
||||
id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
manaType: string; // Mana type required (must be unlocked)
|
||||
equipmentTypeId: string; // Equipment type ID produced
|
||||
slot: EquipmentSlot; // Slot the equipment occupies
|
||||
materials: Record<string, number>; // materialId -> count required
|
||||
manaCost: number; // Mana cost in the recipe's mana type
|
||||
craftTime: number; // Craft time in hours
|
||||
rarity: 'common' | 'uncommon' | 'rare' | 'epic' | 'legendary';
|
||||
gearTrait: string; // Flavor text for gear properties
|
||||
bonusEnchantments?: AppliedEnchantment[]; // Pre-applied enchantments
|
||||
recipeType?: 'equipment' | 'material';
|
||||
resultMaterial?: string; // For material recipes: material ID produced
|
||||
resultAmount?: number; // For material recipes: how many are produced
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. Material Recipes
|
||||
|
||||
### 3.1 Tier 1: Basic Materials
|
||||
|
||||
| ID | Name | Mana Type | Mana Cost | Input | Output | Time |
|
||||
|---|---|---|---|---|---|---|
|
||||
| `manaCrystal` | Mana Crystal | raw | 500 | — | 1× manaCrystal | 1h |
|
||||
| `manaCrystalDustCraft` | Mana Crystal Dust | raw | 10 | 1× manaCrystal | 2× manaCrystalDust | 1h |
|
||||
|
||||
### 3.2 Tier 2: Elemental Crystals
|
||||
|
||||
All cost 100 of the respective element mana, take 1 hour, produce 1 crystal.
|
||||
|
||||
| ID | Mana Type | Element |
|
||||
|---|---|---|
|
||||
| `fireCrystal` | fire | Fire |
|
||||
| `waterCrystal` | water | Water |
|
||||
| `airCrystal` | air | Air |
|
||||
| `earthCrystal` | earth | Earth |
|
||||
| `lightCrystal` | light | Light |
|
||||
| `darkCrystal` | dark | Dark |
|
||||
| `metalCrystal` | metal | Metal |
|
||||
| `crystalCrystal` | crystal | Crystal |
|
||||
|
||||
### 3.3 Tier 3: Shards and Cores
|
||||
|
||||
| ID | Mana Type | Mana Cost | Input | Output | Time |
|
||||
|---|---|---|---|---|---|
|
||||
| `earthShardCraft` | earth | 50 | 1× earthCrystal | 1× earthShard | 1h |
|
||||
| `elementalCore` | raw | 100 | 10× manaCrystal | 1× elementalCore | 10h |
|
||||
|
||||
### 3.4 Tier 4: Advanced Materials
|
||||
|
||||
| ID | Mana Type | Mana Cost | Input | Output | Time |
|
||||
|---|---|---|---|---|---|
|
||||
| `aetherWeave` | air | 500 | 3× airCrystal, 3× lightCrystal, 2× elementalCore | 1× aetherWeave | 12h |
|
||||
| `voidCloth` | dark | 500 | 3× airCrystal, 3× darkCrystal, 2× voidEssence | 1× voidCloth | 12h |
|
||||
| `liquidCrystalLattice` | crystal | 800 | 5× crystalCrystal, 3× elementalCore, 2× voidEssence, 1× celestialFragment | 1× liquidCrystalLattice | 20h |
|
||||
|
||||
### 3.5 Material Dependency Chain
|
||||
|
||||
```
|
||||
Raw Mana (500) → Mana Crystal (1)
|
||||
Mana Crystal (1) + Raw Mana (10) → Mana Crystal Dust (2)
|
||||
Mana Crystal (1) + Element Mana (100) → Element Crystal (1) [per element]
|
||||
Element Crystal (1) + Element Mana (50) → Element Shard (1) [earth only]
|
||||
Mana Crystal (10) + Raw Mana (100) → Elemental Core (1) [10hr]
|
||||
Air Crystal (3) + Light Crystal (3) + Elemental Core (2) → Aether Weave (1) [12hr]
|
||||
Air Crystal (3) + Dark Crystal (3) + Void Essence (2) → Void Cloth (1) [12hr]
|
||||
Crystal Crystal (5) + Elemental Core (3) + Void Essence (2) + Celestial Fragment (1) → Liquid Crystal Lattice (1) [20hr]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. Equipment Recipes
|
||||
|
||||
### 4.1 Earth Gear (Unlock: Study Fabricator Recipes @ 50 XP)
|
||||
|
||||
| ID | Name | Slot | Mana Cost | Materials | Rarity | Time |
|
||||
|---|---|---|---|---|---|---|
|
||||
| `earthHelm` | Earthen Helm | head | 200 earth | 4× manaCrystalDust, 2× earthShard | uncommon | 3h |
|
||||
| `earthChest` | Stoneguard Armor | body | 500 earth | 8× manaCrystalDust, 4× earthShard, 1× elementalCore | rare | 6h |
|
||||
| `earthBoots` | Stonegreaves | feet | 150 earth | 3× manaCrystalDust, 1× earthShard | uncommon | 2h |
|
||||
|
||||
### 4.2 Metal Gear (Unlock: Study Fabricator Recipes @ 100 XP)
|
||||
|
||||
| ID | Name | Slot | Mana Cost | Materials | Rarity | Time |
|
||||
|---|---|---|---|---|---|---|
|
||||
| `metalBlade` | Metal Blade | mainHand | 400 metal | 6× manaCrystalDust, 3× metalShard, 2× elementalCore | rare | 5h |
|
||||
| `metalShield` | Metal Spell Focus | offHand | 450 metal | 7× manaCrystalDust, 4× metalShard, 1× elementalCore | rare | 5h |
|
||||
| `metalGloves` | Metalweave Gauntlets | hands | 250 metal | 4× manaCrystalDust, 2× metalShard | uncommon | 3h |
|
||||
|
||||
### 4.3 Sand Gear (Unlock: Study Fabricator Recipes @ 150 XP)
|
||||
|
||||
| ID | Name | Slot | Mana Cost | Materials | Rarity | Time |
|
||||
|---|---|---|---|---|---|---|
|
||||
| `sandBoots` | Sandstrider Boots | feet | 120 sand | 3× manaCrystalDust, 1× sandShard | uncommon | 2h |
|
||||
| `sandGloves` | Sandweave Gloves | hands | 140 sand | 3× manaCrystalDust, 2× sandShard | uncommon | 2h |
|
||||
| `sandVest` | Sandcloth Vest | body | 300 sand | 5× manaCrystalDust, 2× sandShard, 1× elementalCore | rare | 4h |
|
||||
|
||||
### 4.4 Crystal Gear (Unlock: Study Fabricator Recipes @ 200 XP)
|
||||
|
||||
| ID | Name | Slot | Mana Cost | Materials | Rarity | Time |
|
||||
|---|---|---|---|---|---|---|
|
||||
| `crystalWand` | Crystal Focus Wand | mainHand | 600 crystal | 10× manaCrystalDust, 5× crystalShard, 3× elementalCore | epic | 6h |
|
||||
| `crystalRing` | Crystal Ring | accessory1 | 350 crystal | 5× manaCrystalDust, 3× crystalShard, 1× elementalCore | rare | 3h |
|
||||
| `crystalAmulet` | Crystal Pendant | accessory2 | 400 crystal | 6× manaCrystalDust, 3× crystalShard, 2× elementalCore | rare | 4h |
|
||||
|
||||
### 4.5 Wizard Branch (Unlock: Study Wizard Equipment discipline)
|
||||
|
||||
| ID | Name | Slot | Unlock (XP) | Mana Cost | Materials | Rarity | Time |
|
||||
|---|---|---|---|---|---|---|---|
|
||||
| `oakStaff` | Oak Staff | mainHand | 50 | 200 earth | 5× manaCrystalDust, 2× earthShard | uncommon | 3h |
|
||||
| `arcanistStaff` | Arcanist Staff | mainHand | 100 | 700 crystal | 12× manaCrystalDust, 6× crystalShard, 3× elementalCore | epic | 8h |
|
||||
| `battlestaff` | Battlestaff | mainHand | 150 | 500 metal | 8× manaCrystalDust, 4× metalShard, 2× elementalCore | rare | 6h |
|
||||
| `arcanistCirclet` | Arcanist Circlet | head | 150 | 300 crystal | 6× manaCrystalDust, 2× crystalShard, 1× lightCrystal | rare | 4h |
|
||||
| `arcanistRobe` | Arcanist Robe | body | 150 | 800 crystal | 14× manaCrystalDust, 7× crystalShard, 3× elementalCore | epic | 8h |
|
||||
| `voidCatalyst` | Void Catalyst | mainHand | 200 | 600 crystal | 10× manaCrystalDust, 3× darkCrystal, 2× voidEssence, 2× elementalCore | epic | 7h |
|
||||
| `arcanistPendant` | Arcanist Pendant | accessory1 | 250 | 500 crystal | 8× manaCrystalDust, 4× crystalShard, 2× elementalCore | epic | 5h |
|
||||
|
||||
**Advanced Wizard Gear:**
|
||||
|
||||
| ID | Name | Slot | Mana Cost | Materials | Rarity | Time |
|
||||
|---|---|---|---|---|---|---|
|
||||
| `aetherRobe` | Aetherweave Robe | body | 1200 crystal | 3× aetherWeave, 15× manaCrystalDust, 8× crystalShard, 4× elementalCore | legendary | 15h |
|
||||
| `aetherCirclet` | Aetherweave Circlet | head | 900 crystal | 2× aetherWeave, 10× manaCrystalDust, 3× lightCrystal, 3× elementalCore | epic | 10h |
|
||||
| `voidRobe` | Voidweave Robe | body | 1200 sand | 3× voidCloth, 15× manaCrystalDust, 8× crystalShard, 3× voidEssence | legendary | 15h |
|
||||
| `voidCowl` | Voidweave Cowl | head | 900 sand | 2× voidCloth, 10× manaCrystalDust, 3× darkCrystal, 2× voidEssence | epic | 10h |
|
||||
| `latticeStaff` | Crystal Lattice Staff | mainHand | 2000 crystal | 2× liquidCrystalLattice, 2× aetherWeave, 2× voidCloth, 5× elementalCore | legendary | 25h |
|
||||
| `latticeAmulet` | Crystal Lattice Amulet | accessory1 | 1500 crystal | 1× liquidCrystalLattice, 5× crystalCrystal, 4× elementalCore, 2× voidEssence | legendary | 18h |
|
||||
|
||||
### 4.6 Physical Branch (Unlock: Study Physical Equipment discipline)
|
||||
|
||||
| ID | Name | Slot | Unlock (XP) | Mana Cost | Materials | Rarity | Time |
|
||||
|---|---|---|---|---|---|---|---|
|
||||
| `crystalBlade` | Crystal Blade | mainHand | 50 | 500 crystal | 8× manaCrystalDust, 4× crystalShard, 2× elementalCore | rare | 5h |
|
||||
| `arcanistBlade` | Arcanist Blade | mainHand | 100 | 600 metal | 10× manaCrystalDust, 5× metalShard, 3× elementalCore | epic | 7h |
|
||||
| `voidBlade` | Void-Touched Blade | mainHand | 150 | 550 crystal | 9× manaCrystalDust, 3× darkCrystal, 2× voidEssence, 2× elementalCore | epic | 6h |
|
||||
| `battleHelm` | Battle Helm | head | 200 | 350 metal | 6× manaCrystalDust, 3× metalShard, 1× elementalCore | rare | 4h |
|
||||
| `battleRobe` | Battle Robe | body | 200 | 400 sand | 8× manaCrystalDust, 3× sandShard, 2× elementalCore | rare | 5h |
|
||||
| `battleBoots` | Battle Boots | feet | 250 | 180 sand | 4× manaCrystalDust, 2× sandShard | uncommon | 3h |
|
||||
| `combatGauntlets` | Combat Gauntlets | hands | 300 | 300 metal | 5× manaCrystalDust, 2× metalShard, 1× elementalCore | uncommon | 3h |
|
||||
|
||||
---
|
||||
|
||||
## 5. Recipe Unlock Gates
|
||||
|
||||
### 5.1 Study Fabricator Recipes Discipline
|
||||
|
||||
| XP Threshold | Recipes Unlocked |
|
||||
|---|---|
|
||||
| 50 | Earth gear (helm, chest, boots) |
|
||||
| 100 | Metal gear (blade, shield, gloves) |
|
||||
| 150 | Sand gear (boots, gloves, vest) |
|
||||
| 200 | Crystal gear (wand, ring, amulet) |
|
||||
|
||||
### 5.2 Study Wizard Equipment Discipline
|
||||
|
||||
| XP Threshold | Recipes Unlocked |
|
||||
|---|---|
|
||||
| 50 | Oak Staff |
|
||||
| 100 | Arcanist Staff |
|
||||
| 150 | Battlestaff, Arcanist Circlet, Arcanist Robe |
|
||||
| 200 | Void Catalyst |
|
||||
| 250 | Arcanist Pendant |
|
||||
| 300 | (advanced recipes via material availability) |
|
||||
|
||||
### 5.3 Study Physical Equipment Discipline
|
||||
|
||||
| XP Threshold | Recipes Unlocked |
|
||||
|---|---|
|
||||
| 50 | Crystal Blade |
|
||||
| 100 | Arcanist Blade |
|
||||
| 150 | Void Blade |
|
||||
| 200 | Battle Helm, Battle Robe |
|
||||
| 250 | Battle Boots |
|
||||
| 300 | Combat Gauntlets |
|
||||
|
||||
---
|
||||
|
||||
## 6. Crafting Flow
|
||||
|
||||
### 6.1 Pre-Craft Checks
|
||||
|
||||
```
|
||||
checkFabricatorCosts(recipe, materials, rawMana, elements):
|
||||
- Verify all material counts are sufficient
|
||||
- Verify mana (raw or elemental) is sufficient
|
||||
- Return { canCraft, missingMana, missingMaterials }
|
||||
```
|
||||
|
||||
### 6.2 Crafting Execution
|
||||
|
||||
```
|
||||
executeMaterialCraft(recipe, materials):
|
||||
1. Deduct mana cost from raw or elemental pool
|
||||
2. Deduct input materials from inventory
|
||||
3. Add resultAmount of resultMaterial to inventory
|
||||
|
||||
makeFabricatorProgress(recipeId, equipmentTypeId, craftTime, manaCost):
|
||||
1. Create EquipmentCraftingProgress object
|
||||
2. blueprintId = "fabricator-{recipeId}"
|
||||
3. Progress accumulates at HOURS_PER_TICK per tick
|
||||
4. On completion: create equipment instance with bonusEnchantments
|
||||
```
|
||||
|
||||
### 6.3 Cancellation Refund
|
||||
|
||||
```
|
||||
remainingFraction = (required - progress) / required
|
||||
refundRate = remainingFraction + (1 - remainingFraction) × 0.5
|
||||
manaRefund = floor(manaSpent × refundRate)
|
||||
materialRefund = floor(materialsSpent × 0.5)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. Crafting Efficiency Discipline Interaction
|
||||
|
||||
The **Crafting Efficiency** discipline provides:
|
||||
|
||||
| Source | Effect |
|
||||
|---|---|
|
||||
| Base stat bonus | `craftingCostReduction` +15 |
|
||||
| Perk `efficiency-1` (once @ 300 XP) | +10% Crafting Cost Reduction |
|
||||
|
||||
The `craftingCostReduction` stat reduces material costs for all fabrication recipes.
|
||||
Applied as: `actualCost = baseCost × (1 - craftingCostReduction / 100)`.
|
||||
|
||||
At maximum: 15 (base) + 10 (perk) = **25% cost reduction**.
|
||||
|
||||
---
|
||||
|
||||
## 8. How Fabricated Items Differ from Base Loot
|
||||
|
||||
| Property | Loot Drops | Fabricated Items |
|
||||
|---|---|---|
|
||||
| **Source** | Enemy drops, treasure rooms | Crafting recipes |
|
||||
| **Enchantments** | None (must be enchanted) | Pre-applied `bonusEnchantments` |
|
||||
| **Rarity** | Random (common–legendary) | Fixed per recipe |
|
||||
| **Quality** | Random (0–100) | Fixed per recipe |
|
||||
| **Stats** | Base for type | Base for type + enchantment bonuses |
|
||||
| **Control** | None (random) | Full (player chooses recipe) |
|
||||
|
||||
Fabricated items are created with `bonusEnchantments` — pre-applied enchantment
|
||||
objects with `effectId`, `stacks`, and `actualCost`. These enchantments are
|
||||
permanent and cannot be removed without the Enchanter's disenchant process.
|
||||
|
||||
---
|
||||
|
||||
## 9. Equipment Types Producible via Fabrication
|
||||
|
||||
| Slot | Equipment Types |
|
||||
|---|---|
|
||||
| mainHand | Metal Blade, Crystal Focus Wand, Oak Staff, Arcanist Staff, Battlestaff, Void Catalyst, Crystal Lattice Staff |
|
||||
| offHand | Metal Spell Focus |
|
||||
| head | Earthen Helm, Arcanist Circlet, Aetherweave Circlet, Voidweave Cowl, Battle Helm |
|
||||
| body | Stoneguard Armor, Sandcloth Vest, Arcanist Robe, Aetherweave Robe, Voidweave Robe, Battle Robe |
|
||||
| hands | Metalweave Gauntlets, Sandweave Gloves, Combat Gauntlets |
|
||||
| feet | Stonegreaves, Sandstrider Boots, Battle Boots |
|
||||
| accessory1 | Crystal Ring, Arcanist Pendant, Crystal Lattice Amulet |
|
||||
| accessory2 | Crystal Pendant |
|
||||
|
||||
---
|
||||
|
||||
## 10. Rarity Distribution
|
||||
|
||||
| Rarity | Count | Examples |
|
||||
|---|---|---|
|
||||
| common | 2 | Mana Crystal Dust, Earth Shard |
|
||||
| uncommon | 14 | Earth gear, Sand gear, Oak Staff, Battle Boots, Combat Gauntlets, Mana Crystal |
|
||||
| rare | 14 | Earth Chest, Metal gear, Crystal Ring/Amulet, Sand Vest, Crystal Blade, Battle Helm/Robe |
|
||||
| epic | 10 | Crystal Wand, Arcanist Staff/Robe, Void Blade/Catalyst, Arcanist Pendant, Aether Circlet, Void Cowl |
|
||||
| legendary | 5 | Aether Robe, Void Robe, Lattice Staff, Lattice Amulet, Liquid Crystal Lattice |
|
||||
|
||||
---
|
||||
|
||||
## 11. Acceptance Criteria
|
||||
|
||||
| # | Criterion |
|
||||
|---|---|
|
||||
| AC-1 | All 48 recipes are accessible when the Fabricator attunement is active. |
|
||||
| AC-2 | Recipe unlock gates fire at the correct discipline XP thresholds. |
|
||||
| AC-3 | Material crafting correctly consumes mana and input materials, producing the correct output. |
|
||||
| AC-4 | Equipment crafting produces items with the correct pre-applied enchantments. |
|
||||
| AC-5 | Crafting Efficiency discipline reduces material costs by the correct percentage. |
|
||||
| AC-6 | Cancellation refunds mana at the blended rate (100% unspent, 50% spent) and materials at 50%. |
|
||||
| AC-7 | Fabricated items cannot be crafted without the required mana type unlocked. |
|
||||
| AC-8 | Material dependency chain is correct: Mana Crystal → Element Crystal → Elemental Core → Advanced Materials. |
|
||||
| AC-9 | Craft time ranges from 1h (basic materials) to 25h (Crystal Lattice Staff). |
|
||||
| AC-10 | Mana cost ranges from 10 (Mana Crystal Dust) to 2000 (Crystal Lattice Staff). |
|
||||
|
||||
---
|
||||
|
||||
## 12. Files Reference
|
||||
|
||||
| File | Role |
|
||||
|---|---|
|
||||
| `src/lib/game/data/fabricator-material-recipes.ts` | Material recipes (15) |
|
||||
| `src/lib/game/data/fabricator-recipes.ts` | Core equipment recipes (12) |
|
||||
| `src/lib/game/data/fabricator-wizard-recipes.ts` | Wizard branch recipes (14) |
|
||||
| `src/lib/game/data/fabricator-physical-recipes.ts` | Physical branch recipes (7) |
|
||||
| `src/lib/game/data/fabricator-recipe-types.ts` | Recipe type definitions |
|
||||
| `src/lib/game/crafting-fabricator.ts` | Fabrication crafting logic |
|
||||
| `src/lib/game/data/disciplines/fabricator.ts` | Fabricator disciplines (5) |
|
||||
| `src/components/game/tabs/CraftingTab.tsx` | Crafting tab wrapper |
|
||||
| `src/components/game/tabs/CraftingTab/FabricatorSubTab.tsx` | Fabricator crafting UI |
|
||||
@@ -0,0 +1,229 @@
|
||||
# Invoker Attunement — Design Spec
|
||||
|
||||
> Describes the Invoker attunement: identity, unlock flow, mana behavior, full
|
||||
> discipline list with stats/perks, systems unlocked, pact interactions, and
|
||||
> attunement level interactions.
|
||||
|
||||
---
|
||||
|
||||
## 1. Objective
|
||||
|
||||
The Invoker is the pact-focused attunement that transforms Guardian defeats into
|
||||
permanent power. Unlike the other attunements, the Invoker has no primary mana type
|
||||
and no automatic mana conversion — it gains elemental mana exclusively by signing
|
||||
pacts with Guardians. Its disciplines amplify pact power, boon effectiveness, and
|
||||
guardian-related multipliers.
|
||||
|
||||
---
|
||||
|
||||
## 2. Identity
|
||||
|
||||
| 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, scales with `1.5^(level-1)`) |
|
||||
| **Conversion Rate** | None (0 at all levels) |
|
||||
| **Unlock** | Defeat first Guardian |
|
||||
| **Capabilities** | `['pacts', 'guardianPowers', 'elementalMastery']` |
|
||||
| **Skill Categories** | `['invocation', 'pact']` |
|
||||
|
||||
---
|
||||
|
||||
## 3. Unlock Condition and Flow
|
||||
|
||||
**Condition:** Defeat the first Guardian (floor 10).
|
||||
|
||||
**Unlock flow:**
|
||||
1. Defeat the floor 10 Guardian (Ignis Prime)
|
||||
2. Invoker becomes available for activation
|
||||
3. Player activates Invoker → initialized at `{ active: true, level: 1, experience: 0 }`
|
||||
4. Invoker disciplines become available: `pact-attunement`, `guardians-boon`
|
||||
|
||||
The unlock condition is stored as a descriptive string:
|
||||
`"Defeat your first guardian and choose the path of the Invoker"`
|
||||
|
||||
---
|
||||
|
||||
## 4. Raw Mana Regen Contribution
|
||||
|
||||
Base regen: **+0.3/hour** (at level 1). Scales exponentially:
|
||||
|
||||
```
|
||||
effectiveRegen = 0.3 × 1.5^(level - 1)
|
||||
```
|
||||
|
||||
| Level | Raw Regen |
|
||||
|---|---|
|
||||
| 1 | 0.300/hr |
|
||||
| 5 | 1.519/hr |
|
||||
| 10 | 11.533/hr |
|
||||
|
||||
---
|
||||
|
||||
## 5. Mana Gain from Pacts (No Conversion)
|
||||
|
||||
The Invoker has **no automatic mana conversion**. Instead, it gains elemental mana
|
||||
types exclusively through Guardian pacts:
|
||||
|
||||
When a pact is signed (`completePactRitual`):
|
||||
```typescript
|
||||
for (const manaType of guardian.unlocksMana || []) {
|
||||
manaStore.unlockElement(manaType, 0);
|
||||
}
|
||||
```
|
||||
|
||||
Each guardian's `unlocksMana` is resolved via `resolveMultiUnlockChain(element)`,
|
||||
which walks the element recipe tree to unlock the guardian's element and all base
|
||||
components:
|
||||
|
||||
| Guardian | Element | Unlocks Mana Types |
|
||||
|---|---|---|
|
||||
| Floor 10 (Ignis Prime) | fire | `fire` |
|
||||
| Floor 20 (Aqua Regia) | water | `water` |
|
||||
| Floor 40 (Terra Firma) | earth | `earth` |
|
||||
| Floor 90 (Metal) | metal | `fire`, `earth`, `metal` |
|
||||
| Floor 130 (BlackFlame) | blackflame | `fire`, `earth`, `metal` |
|
||||
| Floor 150 (Lightning) | lightning | `fire`, `air`, `lightning` |
|
||||
|
||||
Signing pacts is the **only** way for the Invoker to access elemental mana for
|
||||
casting elemental spells and running elemental disciplines.
|
||||
|
||||
---
|
||||
|
||||
## 6. Disciplines
|
||||
|
||||
The Invoker's discipline pool contains **2 disciplines**.
|
||||
|
||||
### 6.1 Pact Attunement (`pact-attunement`)
|
||||
|
||||
| Field | Value |
|
||||
|---|---|
|
||||
| **Mana Type** | `raw` |
|
||||
| **Base Cost** | 12 |
|
||||
| **Requires** | `['signed_pact']` |
|
||||
| **Stat Bonus** | `pactAffinityBonus` +0.05 (base) |
|
||||
| **Scaling Factor** | 80 |
|
||||
| **Difficulty Factor** | 150 |
|
||||
| **Drain Base** | 4 |
|
||||
|
||||
**Perks:**
|
||||
|
||||
| Perk ID | Type | Threshold | Bonus |
|
||||
|---|---|---|---|
|
||||
| `pact-affinity-scaling` | `once` | 100 | Unlock pact affinity scaling |
|
||||
| `pact-affinity-infinite` | `infinite` | 200 | Every 100 XP: `pactAffinityBonus` +0.05 |
|
||||
| `pact-power-boost` | `capped` | 500 | Every 200 XP: `guardianBoonMultiplier` +0.03, max 5 tiers |
|
||||
|
||||
### 6.2 Guardian's Boon (`guardians-boon`)
|
||||
|
||||
| Field | Value |
|
||||
|---|---|
|
||||
| **Mana Type** | `raw` |
|
||||
| **Base Cost** | 18 |
|
||||
| **Requires** | `['signed_pact']` |
|
||||
| **Stat Bonus** | `guardianBoonMultiplier` +0.10 (base) |
|
||||
| **Scaling Factor** | 100 |
|
||||
| **Difficulty Factor** | 200 |
|
||||
| **Drain Base** | 6 |
|
||||
|
||||
**Perks:**
|
||||
|
||||
| Perk ID | Type | Threshold | Bonus |
|
||||
|---|---|---|---|
|
||||
| `boon-1` | `once` | 100 | `guardianBoonMultiplier` +0.10 |
|
||||
| `boon-2` | `capped` | 200 | Every 350 XP: `guardianBoonMultiplier` +0.05, max 5 tiers |
|
||||
|
||||
### 6.3 Guardian Boon Multiplier Scaling
|
||||
|
||||
Maximum theoretical `guardianBoonMultiplier` from disciplines:
|
||||
|
||||
| Source | Value |
|
||||
|---|---|
|
||||
| Base (Guardian's Boon discipline) | +0.10 |
|
||||
| `boon-1` perk (once @ 100 XP) | +0.10 |
|
||||
| `boon-2` perk (capped, 5 tiers × 0.05) | +0.25 |
|
||||
| `pact-power-boost` perk (capped, 5 tiers × 0.03) | +0.15 |
|
||||
| **Maximum total** | **+0.60** |
|
||||
|
||||
With the base multiplier of 1.0, the maximum guardian boon multiplier is **1.60**.
|
||||
|
||||
---
|
||||
|
||||
## 7. Systems Unlocked
|
||||
|
||||
The Invoker attunement gates the **Pact System** (see `pact-system-spec.md`):
|
||||
|
||||
- Sign pacts with defeated Guardians
|
||||
- Gain permanent boons and elemental mana unlocks
|
||||
- Pact slots limit simultaneous signed pacts
|
||||
- Pact affinity reduces ritual time
|
||||
|
||||
---
|
||||
|
||||
## 8. Puzzle Room Behavior
|
||||
|
||||
In the spire, every 7th floor has a puzzle room. When the room type is
|
||||
`invoker_trial`, progress scales at 2.5–3% per tick per Invoker level.
|
||||
|
||||
---
|
||||
|
||||
## 9. Attunement Level Interactions
|
||||
|
||||
Higher Invoker level affects:
|
||||
|
||||
1. **Raw mana regen**: `0.3 × 1.5^(level-1)` per hour
|
||||
2. **No conversion**: Invoker never has automatic mana conversion
|
||||
3. **Pact affinity**: Higher raw regen supports the raw mana cost of pact rituals
|
||||
|
||||
Attunement level does **not** directly affect pact multipliers or boon power —
|
||||
those scale through discipline XP.
|
||||
|
||||
---
|
||||
|
||||
## 10. Known Code Issues
|
||||
|
||||
The following inconsistencies exist in the codebase:
|
||||
|
||||
| Issue | Description |
|
||||
|---|---|
|
||||
| `pactBinding` upgrade | Referenced in `prestigeStore.doPrestige` but **not defined** in `PRESTIGE_DEF` constants |
|
||||
| UI vs store mismatch | UI displays `prestigeUpgrades.pactCapacity` but store logic checks `pactBinding` |
|
||||
| Pact persistence | `signedPacts` is persisted but also reset to `[]` on `startNewLoop` — pacts don't survive loops in current implementation |
|
||||
| `pactInterferenceMitigation` | Used in `pact-utils.ts` but no prestige upgrade defines it |
|
||||
|
||||
---
|
||||
|
||||
## 11. Acceptance Criteria
|
||||
|
||||
| # | Criterion |
|
||||
|---|---|
|
||||
| AC-1 | Invoker is locked until the first Guardian is defeated. |
|
||||
| AC-2 | Invoker has no primary mana type and no automatic conversion at any level. |
|
||||
| AC-3 | Signing a pact unlocks the guardian's element and all component elements. |
|
||||
| AC-4 | Both Invoker disciplines require at least one signed pact to activate. |
|
||||
| AC-5 | `pact-affinity-infinite` perk grants +0.05 pactAffinityBonus every 100 XP beyond threshold 200. |
|
||||
| AC-6 | `boon-2` capped perk grants +0.05 guardianBoonMultiplier per tier, max 5 tiers, interval 350 XP. |
|
||||
| AC-7 | `pact-power-boost` capped perk grants +0.03 guardianBoonMultiplier per tier, max 5 tiers, interval 200 XP. |
|
||||
| AC-8 | Maximum theoretical guardianBoonMultiplier from disciplines is 1.60 (base 1.0 + 0.60). |
|
||||
| AC-9 | Invoker `invoker_trial` puzzle rooms grant bonus progress per Invoker level. |
|
||||
| AC-10 | Invoker level scales raw regen by `1.5^(level-1)`. |
|
||||
|
||||
---
|
||||
|
||||
## 12. Files Reference
|
||||
|
||||
| File | Role |
|
||||
|---|---|
|
||||
| `src/lib/game/data/attunements.ts` | Invoker definition |
|
||||
| `src/lib/game/data/disciplines/invoker.ts` | Invoker disciplines (2) |
|
||||
| `src/lib/game/stores/prestigeStore.ts` | Pact ritual state, slot management |
|
||||
| `src/lib/game/stores/pipelines/pact-ritual.ts` | Pact ritual tick processing |
|
||||
| `src/lib/game/utils/pact-utils.ts` | Pact multiplier calculations |
|
||||
| `src/lib/game/data/guardian-data.ts` | Static guardian definitions |
|
||||
| `src/lib/game/data/guardian-encounters.ts` | Procedural guardian lookup |
|
||||
| `src/components/game/tabs/GuardianPactsTab.tsx` | Pact signing UI |
|
||||
| `docs/specs/attunements/invoker/systems/pact-system-spec.md` | Pact system spec |
|
||||
@@ -0,0 +1,356 @@
|
||||
# Pact System — Design Spec
|
||||
|
||||
> Describes the Guardian pact system: ritual flow, boon types, pact slot system,
|
||||
> pact persistence, discipline scaling, and how the Invoker gains elemental mana.
|
||||
|
||||
---
|
||||
|
||||
## 1. Objective
|
||||
|
||||
The Pact system is the Invoker attunement's core progression mechanic. After defeating
|
||||
a Guardian boss on every 10th floor, the player can sign a pact through a ritual
|
||||
process. Each signed pact grants permanent boons (stat multipliers) and unlocks
|
||||
elemental mana types. Pact slots limit how many pacts can be active simultaneously,
|
||||
and the Invoker's disciplines amplify pact power.
|
||||
|
||||
**Design goals:**
|
||||
- Pacts are earned through combat achievement (defeating Guardians)
|
||||
- Ritual time creates a meaningful time investment
|
||||
- Multiple pacts provide multiplicative power but with interference penalties
|
||||
- Boon variety ensures each pact feels distinct
|
||||
- Pact affinity (from disciplines) reduces ritual time
|
||||
|
||||
---
|
||||
|
||||
## 2. Pact Ritual Flow
|
||||
|
||||
### 2.1 Step 1: Defeat the Guardian
|
||||
|
||||
- Every 10th floor (10, 20, 30, ...) has a Guardian boss room
|
||||
- Defeating the Guardian adds the floor number to `defeatedGuardians[]`
|
||||
- Only defeated Guardians are eligible for pact signing
|
||||
|
||||
### 2.2 Step 2: Start Ritual
|
||||
|
||||
```
|
||||
startPactRitual(floor):
|
||||
1. Validate guardian exists at floor
|
||||
2. Check floor is in defeatedGuardians
|
||||
3. Check floor is NOT already in signedPacts
|
||||
4. Check signedPacts.length < pactSlots (slot available)
|
||||
5. Check rawMana >= guardian.pactCost (enough raw mana)
|
||||
6. Check pactRitualFloor === null (no other ritual in progress)
|
||||
7. Deduct guardian.pactCost raw mana
|
||||
8. Set pactRitualFloor = floor, pactRitualProgress = 0
|
||||
```
|
||||
|
||||
### 2.3 Step 3: Progress Ritual
|
||||
|
||||
Each game tick:
|
||||
|
||||
```
|
||||
processPactRitual():
|
||||
pactAffinity = min(0.9, pactAffinityUpgrade × 0.1 + pactAffinityBonus)
|
||||
requiredTime = guardian.pactTime × (1 - pactAffinity)
|
||||
pactRitualProgress += HOURS_PER_TICK
|
||||
if pactRitualProgress >= requiredTime → completePactRitual()
|
||||
```
|
||||
|
||||
**Pact affinity sources:**
|
||||
- `pactAffinityUpgrade`: prestige upgrade level (each level = +0.1, capped at 0.9)
|
||||
- `pactAffinityBonus`: discipline bonus from Pact Attunement discipline
|
||||
|
||||
### 2.4 Step 4: Pact Signed
|
||||
|
||||
```
|
||||
completePactRitual():
|
||||
1. Add floor to signedPacts[]
|
||||
2. Remove floor from defeatedGuardians[]
|
||||
3. Reset pactRitualFloor = null, pactRitualProgress = 0
|
||||
4. For each manaType in guardian.unlocksMana:
|
||||
manaStore.unlockElement(manaType, 0)
|
||||
5. Log: "📜 Pact signed with {name}! You have gained their boons."
|
||||
6. Log: "✨ {ManaType} mana unlocked!" for each new element
|
||||
```
|
||||
|
||||
### 2.5 Cancellation
|
||||
|
||||
`cancelPactRitual()` resets `pactRitualFloor = null`, `pactRitualProgress = 0`.
|
||||
The raw mana cost is **not** refunded on cancellation.
|
||||
|
||||
---
|
||||
|
||||
## 3. Guardian Boon Types
|
||||
|
||||
Each Guardian grants **2 boons** from the following pool of 12 types:
|
||||
|
||||
| Boon Type | Effect |
|
||||
|---|---|
|
||||
| `maxMana` | Flat max raw mana bonus |
|
||||
| `manaRegen` | Flat mana regen per hour bonus |
|
||||
| `castingSpeed` | Spell cast speed multiplier |
|
||||
| `elementalDamage` | Elemental damage multiplier |
|
||||
| `rawDamage` | Raw damage multiplier |
|
||||
| `critChance` | Critical hit chance bonus |
|
||||
| `critDamage` | Critical hit damage multiplier |
|
||||
| `spellEfficiency` | Spell efficiency bonus |
|
||||
| `manaGain` | Mana gain multiplier |
|
||||
| `insightGain` | Insight gain multiplier |
|
||||
| `studySpeed` | Study speed multiplier |
|
||||
| `prestigeInsight` | Prestige insight bonus |
|
||||
|
||||
### 3.1 Boon Application
|
||||
|
||||
```typescript
|
||||
for (const floor of signedPacts) {
|
||||
const guardian = getGuardianForFloor(floor);
|
||||
for (const boon of guardian.boons) {
|
||||
let value = boon.value × guardianBoonMultiplier;
|
||||
// Apply to corresponding bonus stat
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The `guardianBoonMultiplier` starts at 1.0 and is increased by the Guardian's Boon
|
||||
discipline and its perks (see §6).
|
||||
|
||||
---
|
||||
|
||||
## 4. Pact Slot System
|
||||
|
||||
### 4.1 Starting Value
|
||||
|
||||
```typescript
|
||||
pactSlots: 1 // in prestigeStore initial state
|
||||
```
|
||||
|
||||
### 4.2 Upgrading
|
||||
|
||||
The `pactBinding` prestige upgrade adds +1 slot per level:
|
||||
```typescript
|
||||
pactSlots: id === 'pactBinding' ? state.pactSlots + 1 : state.pactSlots
|
||||
```
|
||||
|
||||
> **Note:** The `pactBinding` upgrade is referenced in the store logic but is **not
|
||||
> defined** in `PRESTIGE_DEF` constants. This is a known gap — the upgrade exists
|
||||
> in code but has no definition, cost, or max level.
|
||||
|
||||
### 4.3 Slot Enforcement
|
||||
|
||||
A new pact ritual cannot be started if `signedPacts.length >= pactSlots`. The player
|
||||
must choose which pacts to maintain.
|
||||
|
||||
---
|
||||
|
||||
## 5. Pact Persistence Through Prestige
|
||||
|
||||
### 5.1 What Persists
|
||||
|
||||
| Field | Persisted | Reset on New Loop |
|
||||
|---|---|---|
|
||||
| `signedPacts` | Yes (via Zustand persist) | **Yes** (reset to `[]`) |
|
||||
| `signedPactDetails` | Yes | No |
|
||||
| `pactSlots` | Yes | No |
|
||||
| `pactRitualFloor` | Yes | Yes (reset to `null`) |
|
||||
| `pactRitualProgress` | Yes | Yes (reset to `0`) |
|
||||
| `defeatedGuardians` | No | Yes (reset to `[]`) |
|
||||
|
||||
### 5.2 Current Behavior
|
||||
|
||||
In the current implementation, `signedPacts` is reset to `[]` on `startNewLoop`,
|
||||
meaning **pacts do NOT persist through prestige loops**. The player must re-defeat
|
||||
Guardians and re-sign pacts each loop. The `signedPactDetails` record persists
|
||||
for historical tracking but does not confer active boons.
|
||||
|
||||
> **Design intent vs. implementation:** The AGENTS.md states "Signed pacts persist
|
||||
> through prestige (bounded by `pactSlots`)." The current code resets them. This
|
||||
> is a known discrepancy.
|
||||
|
||||
---
|
||||
|
||||
## 6. Invoker Discipline Scaling of Pact Power
|
||||
|
||||
### 6.1 Pact Affinity (Ritual Time Reduction)
|
||||
|
||||
From the **Pact Attunement** discipline:
|
||||
|
||||
```
|
||||
pactAffinity = min(0.9, pactAffinityUpgrade × 0.1 + pactAffinityBonus)
|
||||
requiredTime = guardian.pactTime × (1 - pactAffinity)
|
||||
```
|
||||
|
||||
| pactAffinity | Time Reduction |
|
||||
|---|---|
|
||||
| 0.0 | 0% (full time) |
|
||||
| 0.3 | 30% faster |
|
||||
| 0.5 | 50% faster |
|
||||
| 0.9 | 90% faster (cap) |
|
||||
|
||||
The `pactAffinityBonus` starts at +0.05 (base from discipline) and gains +0.05
|
||||
every 100 XP from the `pact-affinity-infinite` perk (threshold 200).
|
||||
|
||||
### 6.2 Guardian Boon Multiplier (Boon Power)
|
||||
|
||||
From the **Guardian's Boon** discipline and cross-perks:
|
||||
|
||||
| Source | guardianBoonMultiplier Bonus |
|
||||
|---|---|
|
||||
| Guardian's Boon discipline (base) | +0.10 |
|
||||
| `boon-1` perk (once @ 100 XP) | +0.10 |
|
||||
| `boon-2` perk (capped, 5 tiers) | up to +0.25 |
|
||||
| `pact-power-boost` perk (capped, 5 tiers) | up to +0.15 |
|
||||
| **Maximum total** | **+0.60** (multiplier = 1.60) |
|
||||
|
||||
### 6.3 Pact Multiplier (Damage and Insight)
|
||||
|
||||
From `pact-utils.ts`:
|
||||
|
||||
```typescript
|
||||
computePactMultiplier(signedPacts, pactInterferenceMitigation):
|
||||
baseMult = Π guardian.damageMultiplier for each signed pact
|
||||
|
||||
if only 1 pact: return baseMult
|
||||
|
||||
numAdditional = signedPacts.length - 1
|
||||
basePenalty = 0.5 × numAdditional
|
||||
mitigationReduction = min(pactInterferenceMitigation, 5) × 0.1
|
||||
effectivePenalty = max(0, basePenalty - mitigationReduction)
|
||||
|
||||
if pactInterferenceMitigation >= 5:
|
||||
synergyBonus = (pactInterferenceMitigation - 5) × 0.1
|
||||
return baseMult × (1 + synergyBonus)
|
||||
|
||||
return baseMult × (1 - effectivePenalty)
|
||||
```
|
||||
|
||||
**Example (2 pacts, floors 10+20):**
|
||||
- Floor 10 damage multiplier: `1.0 + 10 × 0.01 = 1.10`
|
||||
- Floor 20 damage multiplier: `1.0 + 20 × 0.01 = 1.20`
|
||||
- `baseMult = 1.10 × 1.20 = 1.32`
|
||||
- With 0 mitigation: `1.32 × (1 - 0.5) = 0.66`
|
||||
- With 3 mitigation: `1.32 × (1 - 0.2) = 1.056`
|
||||
- With 5 mitigation: `1.32 × 1 = 1.32`
|
||||
- With 7 mitigation: `1.32 × 1.2 = 1.584`
|
||||
|
||||
The same formula applies to `computePactInsightMultiplier` using
|
||||
`guardian.insightMultiplier` (`1.0 + floor × 0.005`).
|
||||
|
||||
---
|
||||
|
||||
## 7. Invoker's Mana Gain from Pacts
|
||||
|
||||
### 7.1 Elemental Unlocks
|
||||
|
||||
The Invoker gains elemental mana types exclusively through pact signing. Each
|
||||
guardian's `unlocksMana` is derived from `resolveMultiUnlockChain(element)`:
|
||||
|
||||
| Guardian Floor | Element | Mana Types Unlocked |
|
||||
|---|---|---|
|
||||
| 10 | fire | `fire` |
|
||||
| 20 | water | `water` |
|
||||
| 30 | air | `air` |
|
||||
| 40 | earth | `earth` |
|
||||
| 50 | light | `light` |
|
||||
| 60 | dark | `dark` |
|
||||
| 70 | death | `death` |
|
||||
| 80 | transference | `transference` |
|
||||
| 90 | metal | `fire`, `earth`, `metal` |
|
||||
| 100 | sand | `earth`, `water`, `sand` |
|
||||
| 110 | lightning | `fire`, `air`, `lightning` |
|
||||
| 120 | frost | `air`, `water`, `frost` |
|
||||
| 130 | blackflame | `fire`, `earth`, `metal` |
|
||||
| 140 | radiantflames | `light`, `fire` |
|
||||
| 150 | miasma | `air`, `death` |
|
||||
| 160 | shadowglass | `earth`, `dark` |
|
||||
| 170+ | exotic | varies (see guardian-data.ts) |
|
||||
|
||||
### 7.2 No Automatic Conversion
|
||||
|
||||
The Invoker has `conversionRate = 0`. It does **not** automatically convert raw
|
||||
mana to any elemental type. All elemental mana must come from:
|
||||
1. Pact unlocks (elemental types become available)
|
||||
2. Elemental regen disciplines (once the element type is unlocked)
|
||||
3. Equipment with mana regen enchantments
|
||||
|
||||
---
|
||||
|
||||
## 8. Guardian Data Summary
|
||||
|
||||
### 8.1 Tier 1 — Base Elements (Floors 10–80)
|
||||
|
||||
| Floor | Name | Element | Armor | Pact Cost | Pact Time | Boons |
|
||||
|---|---|---|---|---|---|---|
|
||||
| 10 | Ignis Prime | fire | 10% | hp×0.3+power×5+... | 3h | +5% Fire dmg, +50 max mana |
|
||||
| 20 | Aqua Regia | water | 15% | same formula | 4h | +5% Water dmg, +0.5 mana regen |
|
||||
| 30 | Ventus Rex | air | 18% | same formula | 5h | +5% Air dmg, +5% casting speed |
|
||||
| 40 | Terra Firma | earth | 25% | same formula | 6h | +5% Earth dmg, +100 max mana |
|
||||
| 50 | Lux Aeterna | light | 20% | same formula | 7h | +10% Light dmg, +10% insight gain |
|
||||
| 60 | Umbra Mortis | dark | 22% | same formula | 8h | +10% Dark dmg, +15% crit damage |
|
||||
| 70 | Mors Ultima | death | 25% | same formula | 9h | +10% Death dmg, +10% raw damage |
|
||||
| 80 | Vinculum Arcana | transference | 20% | same formula | 10h | +150 max mana, +1.0 mana regen |
|
||||
|
||||
### 8.2 Tier 2 — Composite Elements (Floors 90–160)
|
||||
|
||||
| Floor | Element | Armor | Pact Time |
|
||||
|---|---|---|---|
|
||||
| 90 | metal | 30% | 11h |
|
||||
| 100 | sand | 25% | 12h |
|
||||
| 110 | lightning | 22% | 13h |
|
||||
| 120 | frost | 28% | 14h |
|
||||
| 130 | blackflame | 32% | 15h |
|
||||
| 140 | radiantflames | 25% | 16h |
|
||||
| 150 | miasma | 28% | 17h |
|
||||
| 160 | shadowglass | 33% | 18h |
|
||||
|
||||
### 8.3 Tier 3 — Exotic Elements (Floors 170–240)
|
||||
|
||||
| Floor | Element | Armor | Pact Time |
|
||||
|---|---|---|---|
|
||||
| 170 | crystal | 35% | 19h |
|
||||
| 180 | stellar | 30% | 20h |
|
||||
| 190 | void | 35% | 21h |
|
||||
| 200 | soul+stellar+void | 35% | 22h |
|
||||
| 210 | soul+time+plasma | 32% | 23h |
|
||||
| 220 | plasma | 28% | 24h |
|
||||
| 230 | crystal+stellar+void | 40% | 25h |
|
||||
| 240 | soul+time+plasma | 42% | 26h |
|
||||
|
||||
### 8.4 Tier 4+ — Procedural (Floors 250+)
|
||||
|
||||
Every 10 floors, with scaling armor, pact multiplier, damage multiplier, and
|
||||
insight multiplier. Dual-element combinations cycle through 9 pairings, then
|
||||
scale through 8 tiers of increasing complexity.
|
||||
|
||||
---
|
||||
|
||||
## 9. Acceptance Criteria
|
||||
|
||||
| # | Criterion |
|
||||
|---|---|
|
||||
| AC-1 | Pact ritual can only be started for defeated Guardians with an available pact slot and sufficient raw mana. |
|
||||
| AC-2 | Ritual progress accumulates at `HOURS_PER_TICK` per tick; pact affinity reduces required time. |
|
||||
| AC-3 | On completion, the floor is added to `signedPacts`, removed from `defeatedGuardians`, and mana types are unlocked. |
|
||||
| AC-4 | Pact affinity is capped at 0.9 (90% time reduction). |
|
||||
| AC-5 | Guardian boon multiplier from disciplines correctly increases boon values. |
|
||||
| AC-6 | Pact multiplier formula applies interference penalties for multiple pacts, with mitigation reducing the penalty. |
|
||||
| AC-7 | At 5+ mitigation, synergy bonus applies instead of penalty. |
|
||||
| AC-8 | Starting pact slots = 1; each `pactBinding` upgrade adds +1 slot. |
|
||||
| AC-9 | Invoker gains elemental mana types exclusively through pact signing. |
|
||||
| AC-10 | Cancelling a ritual resets progress but does not refund the raw mana cost. |
|
||||
| AC-11 | Both Invoker disciplines require at least one signed pact (`requires: ['signed_pact']`). |
|
||||
|
||||
---
|
||||
|
||||
## 10. Files Reference
|
||||
|
||||
| File | Role |
|
||||
|---|---|
|
||||
| `src/lib/game/stores/prestigeStore.ts` | Pact ritual state, slot management, start/complete/cancel |
|
||||
| `src/lib/game/stores/pipelines/pact-ritual.ts` | Per-tick ritual processing |
|
||||
| `src/lib/game/utils/pact-utils.ts` | Pact multiplier, insight multiplier, interference formulas |
|
||||
| `src/lib/game/data/guardian-data.ts` | Static guardian definitions (floors 10–240) |
|
||||
| `src/lib/game/data/guardian-encounters.ts` | Procedural guardian lookup (250+) |
|
||||
| `src/lib/game/data/disciplines/invoker.ts` | Invoker disciplines (2) |
|
||||
| `src/lib/game/utils/guardian-utils.ts` | Element unlock chain resolution |
|
||||
| `src/components/game/tabs/GuardianPactsTab.tsx` | Pact signing UI |
|
||||
| `src/components/game/tabs/guardian-pacts-components.tsx` | Pact UI sub-components |
|
||||
Reference in New Issue
Block a user