Files
Mana-Loop/docs/specs/attunements/enchanter/systems/transference-channel-spec.md
T
n8n-gitea 718aed38b1
Build and Publish Mana Loop Docker Image / build-and-publish (push) Successful in 1m21s
feat: implement Transference Channel system for Enchanter attunement
- Add isChanneling, channelSpeedMultiplier, channelDrainRate to CombatState
- Add startChanneling/stopChanneling actions to combat store
- Add transference-channeling discipline with 3 perks (channel-efficiency, channel-power, channel-mastery)
- Add channelIntensity and channelEfficiency to KNOWN_BONUS_STATS
- Create combat-channel.ts with drain + speed multiplier computation
- Apply channel speed multiplier to equipment spells and melee attacks
- Add Channel Transference hold-button UI to SpireCombatPage
- Add compact channel status indicator to SpireCombatControls
- Channel state resets on spire exit, persists across room transitions
- All 1235 existing tests pass
2026-06-14 21:56:20 +02:00

17 KiB
Raw Blame History

Transference Channel — Design Spec

Describes the Transference Channel system: an active combat mechanic for the Enchanter attunement that lets the player hold a button to drain Transference mana and boost the cast speed of all equipment spells and melee attacks.


1. Objective

The Enchanter attunement currently lacks an active combat mechanic. The Invocation system (Invoker attunement) provides automatic combat acceleration through guardian channeling. The Transference Channel gives the Enchanter a manual, hold-to-channel button that spends Transference mana to temporarily accelerate all equipment-based combat actions.

Design goals:

  • Give the Enchanter an active, holdable combat button
  • Spend Transference mana — the only utility mana type — as the fuel
  • Boost equipment spells and melee attacks only — not the player's active spell
  • Create a resource management decision: channel now for burst speed, or conserve Transference for enchanting and disciplines
  • Scale through a new Enchanter discipline that trades mana cost for potency
  • Complement (not compete with) Invocation — different resource, different trigger, different target

2. The Channel Button

2.1 UI Placement

A "Channel Transference" button on the SpireCombatPage, visible only when:

  • The Enchanter attunement is active (attunements.enchanter.active === true)
  • The player is in climb action (combat)
  • The player has at least 1 Transference mana

2.2 Interaction Model

Property Value
Interaction Press and hold (mousedown / touchstart) to channel, release to stop
Keyboard Optional hotkey (e.g., C) for accessibility
Visual Button glows while active; shows Transference drain rate
Cooldown None — player controls start/stop

The hold-to-channel interaction is intentional: it creates a "power moment" where the player chooses to actively engage. The game is fully playable without it — this is an optional acceleration for players who want active involvement.

2.3 Hold Behavior

While the button is held:

  1. Transference mana drains at drainRate per tick (see §3)
  2. All equipment spells and melee attacks gain speedMultiplier cast speed
  3. If Transference reaches 0: channel stops automatically (no penalty)
  4. If player leaves climb action: channel stops automatically
  5. If player releases button: channel stops immediately

3. Drain Rate and Speed Multiplier

3.1 Mana Economy Context

Transference mana is generated slowly through the Enchanter's automatic conversion (0.2/hour at level 1, scaling with 1.5^(level-1)). At level 10, this is ~7.69/hour. Transference is also the fuel for all Enchanter disciplines and the enchanting pipeline.

The Channel system is designed as a burst expenditure — the player accumulates Transference over time and then spends it in combat for temporary acceleration. The drain rate must be high enough to create meaningful decisions ("can I afford to channel right now?") but not so high that it's trivially exhausted.

3.2 Base Values

Parameter Base Value Description
baseDrainRate 0.08 Transference/tick 0.4 Transference/second at 200ms/tick
baseSpeedMultiplier 1.5× Equipment spells and melee attack 50% faster

3.3 Duration Estimate

At base values with various Transference pool sizes:

Transference Pool Drain Rate Approximate Duration
20 0.08/tick 250 ticks = 50 seconds
50 0.08/tick 625 ticks = 125 seconds
100 0.08/tick 1250 ticks = 250 seconds

With discipline scaling (e.g., 1.8× speed at ~1.8× drain):

Transference Pool Drain Rate Approximate Duration
50 0.144/tick 347 ticks = 69 seconds
100 0.144/tick 694 ticks = 139 seconds

The discipline makes each "pool of Transference" worth less raw seconds but more effective combat time because actions complete faster.

3.4 Scaling with Discipline

A new discipline (transference-channeling) controls the tradeoff between mana cost and speed:

effectiveDrainRate = baseDrainRate × (1 + intensityBonus) × (1 - channelEfficiency)
effectiveSpeedMultiplier = baseSpeedMultiplier + speedBonus

Where intensityBonus and speedBonus come from the discipline's stat bonus and perks (see §5).

Design philosophy: The discipline lets the player invest XP to get more speed, but at proportionally higher mana cost. Perks can shift the ratio in the player's favor (more speed per mana).


4. What Gets Boosted

4.1 Affected

Action Boosted? Notes
Equipment spell casts Yes All equipmentSpellStates cast progress
Melee sword attacks Yes All meleeSwordProgress accumulators

4.2 Not Affected

Action Boosted? Notes
Player's active spell No The manually-selected spell is not equipment
Invocation spells No Invocation is pact-based, not equipment-based
Golem attacks No Golems are independent entities
DoT ticks No DoTs are time-based, not cast-based

4.3 Implementation — Speed Multiplier Application

The channel state is tracked in the combat store. When active, the multiplier is applied to progressPerTick calculations for equipment spells and melee:

// Equipment spells (in combat-actions.ts equipment spell block)
const channelMult = state.isChanneling ? state.channelSpeedMultiplier : 1.0;
const eProgressPerTick = HOURS_PER_TICK * eSpellCastSpeed * totalAttackSpeed * channelMult;

// Melee (in combat-melee.ts)
const channelMult = state.isChanneling ? state.channelSpeedMultiplier : 1.0;
const meleeProgressPerTick = HOURS_PER_TICK * swordAttackSpeed * attackSpeedMult * channelMult;

Important: The speed multiplier only affects cast progress accumulation. It does NOT affect mana costs per cast. Equipment spells still cost the same mana per cast — they just complete faster. This prevents the feedback loop where faster casting drains mana exponentially faster.


5. New Discipline: Transference Channeling

5.1 Definition

Field Value
ID transference-channeling
Name Transference Channeling
Attunement enchanter
Mana Type transference
Base Cost 15
Stat Bonus channelIntensity +0.10 (base)
Scaling Factor 100
Difficulty Factor 180
Drain Base 4

Main stat: channelIntensity

This stat controls both the speed boost and the drain rate:

speedBonus = channelIntensity × 0.5        // added to baseSpeedMultiplier
intensityBonus = channelIntensity × 1.0    // multiplier on drain rate

At 0 XP: channelIntensity = 0.10 → speed = 1.5 + 0.05 = 1.55×, drain = 0.08 × 1.10 = 0.088/tick.

The stat scales with XP via the standard discipline math:

StatBonus = baseValue × (XP / scalingFactor)^0.65
          = 0.10 × (XP / 100)^0.65

5.2 Perks

Perk ID Type Threshold Bonus Description
channel-efficiency once 100 channelEfficiency +0.15 15% less drain for same speed — shifts the ratio in the player's favor
channel-power infinite 200 Every 150 XP: channelIntensity +0.05 Core scaling — more speed (and proportionally more drain)
channel-mastery capped 400 Every 200 XP: channelEfficiency +0.10, max 3 tiers Late-game efficiency — up to 45% less drain

5.3 Effective Formulas with Perks

channelEfficiency = 0 + sum of efficiency perks (0.15 from once, up to 0.30 from capped)
                   hard-capped at 0.60 — prevents drain rate from reaching 0
effectiveSpeedMultiplier = 1.5 + (channelIntensity × 0.5)
effectiveDrainRate = 0.08 × (1 + channelIntensity × 1.0) × (1 - channelEfficiency)

The channelEfficiency cap of 0.60 is enforced in the formula itself. Even if perk bonuses would exceed 0.60, the effective drain rate can never go below 0.08 × (1 + intensity) × 0.40. This ensures channeling always costs meaningful Transference mana.

Example at 500 XP with all perks:

  • channelIntensity = 0.10 × (500/100)^0.65 + 0.05 × 2 (two infinite intervals) ≈ 0.24 + 0.10 = 0.34
  • channelEfficiency = 0.15 + 0.20 (two capped tiers) = 0.35
  • Speed = 1.5 + 0.34 × 0.5 = 1.67×
  • Drain = 0.08 × (1 + 0.34) × (1 - 0.35) = 0.08 × 1.34 × 0.65 = 0.070/tick

5.4 Discipline Identity

"I channel transference mana through my equipment, making my enchanted gear strike and cast faster. The more I master this, the faster I go — but it costs more mana to sustain."


6. Store Changes

6.1 Combat Store (combatStore.ts)

New state fields:

// Transference Channel state
isChanneling: boolean;           // true while button is held
channelSpeedMultiplier: number;  // current speed multiplier (1.5+)
channelDrainRate: number;        // current drain rate per tick

New actions:

startChanneling: () => void;
stopChanneling: () => void;

6.2 Combat State Types (combat-state.types.ts)

Add to CombatState:

isChanneling: boolean;
channelSpeedMultiplier: number;
channelDrainRate: number;

Add to CombatActions:

startChanneling: () => void;
stopChanneling: () => void;

6.3 No Changes To

  • manaStore.ts — Transference mana is drained via existing element deduction
  • craftingStore.ts — enchanting is unaffected
  • prestigeStore.ts — no prestige interaction
  • invocation-utils.ts — Invocation is completely separate

7. Combat Tick Integration

7.1 Modified Flow in combat-actions.ts

The channel state is read from the combat store at the start of each tick. The speed multiplier is applied to equipment spell and melee progress:

1. Read isChanneling from combat store
2. If isChanneling:
   a. Drain Transference: transferencePool -= channelDrainRate
   b. If transference <= 0: stop channeling (set isChanneling = false)
3. Compute channelMult = isChanneling ? channelSpeedMultiplier : 1.0
4. Equipment spell progress: eProgressPerTick *= channelMult
5. Melee progress: meleeProgressPerTick *= channelMult

File size note: combat-actions.ts is currently 377 lines. Adding channel drain logic and speed multiplier application may push it toward the 400-line limit. If so, extract the channel logic into a new file (e.g., combat-channel.ts) and call it from processCombatTick.

7.2 Transference Drain

Transference is drained from the mana store. The drain uses the existing element deduction pattern:

// Per tick while channeling:
const transferencePool = useManaStore.getState().elements.transference;
if (transferencePool.current >= channelDrainRate) {
  useManaStore.getState().deductElement('transference', channelDrainRate);
} else {
  // Insufficient mana — stop channeling
  useCombatStore.getState().stopChanneling();
}

7.3 Auto-Stop Conditions

Channeling stops when any of the following is true:

  1. Player releases the button
  2. Transference mana reaches 0
  3. Player leaves climb action
  4. Enchanter attunement is deactivated mid-combat

Room transitions: Channeling persists across room transitions within the same climb. If the player is channeling and kills an enemy (triggering advanceRoomOrFloor), channeling continues into the next room. The isChanneling state is stored on the combat store and is not reset by room transitions — only by the auto-stop conditions above or by spire exit.


8. UI Changes

8.1 SpireCombatPage

Add a "Channel Transference" button between the SpireHeader and RoomDisplay:

  • Visible when: Enchanter active + in climb action
  • Button style: Teal-colored (#1ABC9C, matching Enchanter), with Transference icon (🔗)
  • While channeling: Button glows, shows drain rate per second
  • Transference bar: Small bar below button showing remaining Transference mana
  • Tooltip: "Hold to channel transference mana through your equipment, boosting attack speed"

8.2 SpireCombatControls

Add a compact channel status indicator:

  • Shows " Channeling" with speed multiplier when active
  • Hidden when not channeling

8.3 No New Tabs

All channel information is visible in the existing SpireCombatPage layout.


9. Data Flow Summary

Player holds button
  → startChanneling() [combatStore]
  → isChanneling = true, channelSpeedMultiplier = 1.5+, channelDrainRate = 0.08+

gameStore.tick()
  → buildTickContext() [snapshots all stores]
  → processCombatTick() [combat-actions.ts]
    → If isChanneling:
        - Deduct transference mana from manaStore
        - If transference <= 0: stopChanneling()
    → channelMult = isChanneling ? channelSpeedMultiplier : 1.0
    → Equipment spell progress: eProgressPerTick *= channelMult
    → Melee progress: meleeProgressPerTick *= channelMult
  → applyTickWrites() [writes combat store changes back]

Player releases button
  → stopChanneling() [combatStore]
  → isChanneling = false

10. Acceptance Criteria

# Criterion
AC-1 "Channel Transference" button is visible on SpireCombatPage when Enchanter is active and player is in climb action.
AC-2 Button is hidden when Enchanter is inactive, player is not in climb, or Transference pool is 0.
AC-3 Holding the button (mousedown) activates channeling; releasing deactivates it.
AC-4 While channeling, Transference mana drains at channelDrainRate per tick.
AC-5 When Transference reaches 0, channeling stops automatically with no penalty.
AC-6 While channeling, all equipment spell cast progress is multiplied by channelSpeedMultiplier.
AC-7 While channeling, all melee sword attack progress is multiplied by channelSpeedMultiplier.
AC-8 The player's active spell is NOT affected by channeling.
AC-9 Invocation spells are NOT affected by channeling.
AC-10 Golem attacks are NOT affected by channeling.
AC-11 DoT ticks are NOT affected by channeling.
AC-12 Base drain rate is 0.08 Transference/tick; base speed multiplier is 1.5×.
AC-13 transference-channeling discipline scales channelIntensity stat with XP.
AC-14 channel-efficiency once perk (100 XP) grants 15% drain reduction.
AC-15 channel-power infinite perk (200 XP, every 150 XP) grants +0.05 channelIntensity.
AC-16 channel-mastery capped perk (400 XP, every 200 XP, max 3 tiers) grants +0.10 channelEfficiency per tier.
AC-17 channelEfficiency is capped at 0.60 (prevents drain from reaching 0).
AC-18 Channel state resets on spire exit (isChanneling = false).
AC-19 Existing saves without channel fields get default values (isChanneling = false, channelSpeedMultiplier = 1.5, channelDrainRate = 0.08).
AC-20 Channel stops automatically when player leaves climb action.
AC-21 Speed multiplier affects cast progress accumulation only — mana costs per cast are unchanged.

11. Files Reference

File Role
src/lib/game/stores/combatStore.ts New channel state fields + startChanneling/stopChanneling actions
src/lib/game/stores/combat-state.types.ts Type definitions for new state
src/lib/game/stores/combat-actions.ts Channel drain + speed multiplier application for equipment spells (or extracted to combat-channel.ts if file size exceeds 400 lines)
src/lib/game/stores/combat-melee.ts Speed multiplier application for melee attacks
src/lib/game/data/disciplines/enchanter.ts Add transference-channeling discipline definition

Implementation note: enchanter.ts currently has 4 disciplines (146 lines). If adding transference-channeling would push it toward the 400-line limit (e.g. when combined with the room-enchanting discipline from the room enchantments spec), create a new file enchanter-combat.ts (following the existing pattern of enchanter-utility.ts, enchanter-spells.ts, etc.) and re-export from data/disciplines/index.ts. | src/lib/game/effects/discipline-effects.ts | Add channelIntensity and channelEfficiency to known bonus stats | | src/components/game/tabs/SpireCombatPage/SpireCombatPage.tsx | Channel button UI | | src/components/game/tabs/SpireCombatPage/SpireCombatControls.tsx | Compact channel status indicator | | docs/specs/attunements/enchanter/systems/transference-channel-spec.md | THIS FILE |


12. Out of Scope

  • Channel affecting the player's active spell
  • Channel affecting Invocation spells
  • Channel affecting golem attacks
  • Channel affecting DoT ticks
  • Auto-channel toggle (manual hold only in v1)
  • Channel working outside of combat (climb action only)
  • Prestige upgrades that affect channeling
  • Channel interacting with the enchanting pipeline (Design/Prepare/Apply)