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 |
|
||||
Reference in New Issue
Block a user