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,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