# Task 11: Fix Spell Info Display - Context Summary ## Task Status **Partially done** - dmg/cast is shown correctly, total DPS is shown, but per-spell DPS display is incorrect. ## Files Analyzed ### 1. `/home/user/repos/Mana-Loop/src/components/game/tabs/SpireTab.tsx` - **Lines 356-360**: Spell info display for active equipment spells - Shows: `⚔️ {fmt(calcDamage(store, spellId))} dmg/cast` - Shows: `⚡ {fmt(Math.floor(calcDamage(store, spellId) * (spellDef.castSpeed || 1)))} dmg/hr` - **ISSUE**: The "dmg/hr" calculation is incorrect. It multiplies damage by `castSpeed` (which is casts/hour), but doesn't account for: 1. `quickCast` skill bonus (`1 + (skills.quickCast || 0) * 0.05`) 2. Equipment `attackSpeedMultiplier` from upgrade effects 3. The actual conversion from casts/hour to DPS ### 2. `/home/user/repos/Mana-Loop/src/lib/game/constants/spells.ts` - **Spell Definition Structure** (`SpellDef` interface in `/src/lib/game/types/spells.ts`): - `castSpeed?: number` - **Casts per hour** (default 1, higher = faster) - `dmg: number` - Base damage per cast - Examples: `manaBolt` has `castSpeed: 3` (3 casts per hour), `fireball` has `castSpeed: 2` ### 3. `/home/user/repos/Mana-Loop/src/lib/game/utils/combat-utils.ts` - **`calcDamage(state, spellId, floorElem)`** (lines 84-131): - Calculates damage per cast - Factors: `baseDmg = sp.dmg + (skills.combatTrain || 0) * 5` - Multipliers: `arcaneFury`, `elementalMastery`, `guardianBane`, `rawDamage`, `elemDamage` - Elemental bonus: `getElementalBonus(sp.elem, floorElem)` - Crit: `precision` skill + boon critChance - **`getTotalDPS(state, upgradeEffects, floorElem)`** (lines 265-300): - Calculates TRUE total DPS from all active equipment spells - Uses `baseCastTime` (not `castSpeed`) - **BUG**: `baseCastTime` is not defined in `SpellDef`! - Actual formula used: ```typescript const baseCastTime = spellDef.baseCastTime || 1.0; const castingSpeedBonus = 1 + (state.skills.castingSpeed || 0) * 0.1; const equipmentAttackSpeed = upgradeEffects.attackSpeedMultiplier || 1; const castTime = baseCastTime / (castingSpeedBonus * equipmentAttackSpeed); const spellDPS = damage / castTime; ``` - **ISSUE**: `baseCastTime` is always 1.0 (fallback), so the formula doesn't use `castSpeed` at all! ### 4. `/home/user/repos/Mana-Loop/src/lib/game/hooks/useGameDerived.ts` - **DPS calculation for active spell** (lines 145-152): ```typescript const spellCastSpeed = activeSpellDef.castSpeed || 1; // casts per hour const quickCastBonus = 1 + (store.skills.quickCast || 0) * 0.05; const attackSpeedMult = upgradeEffects.attackSpeedMultiplier; const totalCastSpeed = spellCastSpeed * quickCastBonus * attackSpeedMult; const damagePerCast = calcDamage(store, store.activeSpell, floorElem); const castsPerSecond = totalCastSpeed * HOURS_PER_TICK / (TICK_MS / 1000); return damagePerCast * castsPerSecond; ``` - **This is the CORRECT formula for DPS**: - `castsPerSecond = castSpeed * quickCastBonus * attackSpeedMult * (HOURS_PER_TICK / (TICK_MS / 1000))` - With `HOURS_PER_TICK = 0.04` and `TICK_MS = 200`: - `castsPerSecond = castSpeed * quickCastBonus * attackSpeedMult * 0.04 / 0.2 = castSpeed * quickCastBonus * attackSpeedMult * 0.2` ### 5. `/home/user/repos/Mana-Loop/src/lib/game/store/combatSlice.ts` - **`processCombat`** (lines 60-75): Actual combat uses `castSpeed` correctly: ```typescript const baseAttackSpeed = 1 + (state.skills.quickCast || 0) * 0.05; const totalAttackSpeed = baseAttackSpeed * effects.attackSpeedMultiplier; const spellCastSpeed = spellDef.castSpeed || 1; const progressPerTick = deltaHours * spellCastSpeed * totalAttackSpeed; ``` - Note: Uses `quickCast` skill (not `castingSpeed` which is from boons) ## Summary of Issues ### Issue 1: Per-spell "dmg/hr" display is wrong in SpireTab.tsx - **Current**: `calcDamage(store, spellId) * (spellDef.castSpeed || 1)` - **Problem**: This just multiplies damage by casts/hour, but doesn't convert to actual DPS correctly - **Correct formula** (from `useGameDerived.ts`): - `dps = damagePerCast * castSpeed * quickCastBonus * attackSpeedMult * HOURS_PER_TICK / (TICK_MS / 1000)` - Or simpler: `dps = damagePerCast * castSpeed * 0.2` (when no bonuses) ### Issue 2: `getTotalDPS` uses wrong field - **Current**: Uses `baseCastTime` which doesn't exist in `SpellDef` - **Fix needed**: Should use `castSpeed` (casts per hour) and convert to DPS properly - **Correct formula**: ```typescript const castsPerHour = spellDef.castSpeed || 1; const quickCastBonus = 1 + (state.skills.quickCast || 0) * 0.05; const attackSpeedMult = upgradeEffects.attackSpeedMultiplier || 1; const totalCastsPerHour = castsPerHour * quickCastBonus * attackSpeedMult; const spellDPS = damage * totalCastsPerHour / 3600; // Convert casts/hour to casts/second ``` ### Issue 3: Inconsistent skill usage - `combatSlice.ts` and `useGameDerived.ts` use `quickCast` skill for cast speed bonus - `getTotalDPS` uses `castingSpeed` (which is from boons, not player skills) - Need to verify which is correct or use both ## Correct Formulas ### True DPS for a spell: ``` DPS = damage_per_cast × (castSpeed × quickCast_bonus × attackSpeed_multiplier) / 3600 ``` Where: - `damage_per_cast` = `calcDamage(store, spellId, floorElem)` - `castSpeed` = `spellDef.castSpeed || 1` (casts per hour) - `quickCast_bonus` = `1 + (skills.quickCast || 0) * 0.05` - `attackSpeed_multiplier` = from equipment effects - Divide by 3600 to convert from casts/hour to casts/second ### For display in SpireTab.tsx per-spell: - **dmg/cast**: Already correct - uses `calcDamage(store, spellId)` - **DPS**: Should show `damage_per_cast × (castSpeed × quickCast × attackSpeed) / 3600` - Current "dmg/hr" is misleading - it's not actually damage per hour with bonuses ## Files to Modify 1. `/home/user/repos/Mana-Loop/src/components/game/tabs/SpireTab.tsx` (lines 356-360) - Fix per-spell DPS display 2. `/home/user/repos/Mana-Loop/src/lib/game/utils/combat-utils.ts` (lines 280-295) - Fix `getTotalDPS` to use `castSpeed` instead of `baseCastTime`