Files
i-want-to-heal/src/modes/iwt2/content/healerAbilities.ts
T
2026-07-05 22:48:56 -04:00

127 lines
4.2 KiB
TypeScript

import type { Spell } from '../../../game'
import type { Iwt2InfusionAbilityId } from './infusionAbilities'
import { iwt2HealerInfusionAbility } from './healerInfusionAbilities'
export type Iwt2AbilityTarget = 'party-member' | 'self' | 'ground'
export type Iwt2HealerId = 'dawnweaver' | 'lifebinder' | 'runesage'
export type Iwt2HealerMetadata = {
id: Iwt2HealerId
name: string
icon: string
description: string
}
export type Iwt2HealerAbility = {
id: string
healerId: Iwt2HealerId
slot: number
name: string
icon: string
kind: Spell['kind']
power: number
effectType?: string
manaCost: number
cooldownSeconds: number
target: Iwt2AbilityTarget
extraTargets?: number
triggeredEffects?: Iwt2TriggeredAbilityEffect[]
}
export type Iwt2TriggeredAbilityEffect = {
id: string
name: string
kind: Spell['kind']
power: number
effectType?: string
}
export const IWT2_HEALER_METADATA: Record<Iwt2HealerId, Iwt2HealerMetadata> = {
dawnweaver: {
id: 'dawnweaver',
name: 'Dawnweaver',
icon: '+',
description: 'Direct heals, radiant group recovery, shields, and cleanse.',
},
lifebinder: {
id: 'lifebinder',
name: 'Lifebinder',
icon: '~',
description: 'Verdant healing over time, barkskin shielding, and steady group recovery.',
},
runesage: {
id: 'runesage',
name: 'Runesage',
icon: 'R',
description: 'Rune-scripted mends, concordance healing, aegis shielding, and unraveling cleanse.',
},
}
export const IWT2_HEALER_ORDER: Iwt2HealerId[] = ['dawnweaver', 'lifebinder', 'runesage']
export const IWT2_HEALER_ABILITIES: Record<Iwt2HealerId, Iwt2HealerAbility[]> = {
dawnweaver: [
createAbility('dawnweaver', 1, 'mend', 'Mend', '+', 'direct', 30, 5, 0.5),
createAbility('dawnweaver', 2, 'renew', 'Renew', '~', 'hot', 12, 7, 0.5, 'heal_over_time'),
createAbility('dawnweaver', 3, 'radiance', 'Radiance', '*', 'group', 18, 12, 8),
createAbility('dawnweaver', 4, 'sun-ward', 'Sun Ward', 'O', 'shield', 36, 8, 7, 'shield'),
createAbility('dawnweaver', 5, 'purify', 'Purify', 'x', 'cleanse', 10, 5, 5, 'cleanse'),
],
lifebinder: [
createAbility('lifebinder', 1, 'verdant-touch', 'Verdant Touch', '+', 'direct', 24, 4, 0.55),
createAbility('lifebinder', 2, 'seed-of-life', 'Seed of Life', '~', 'hot', 16, 9, 1, 'heal_over_time'),
createAbility('lifebinder', 3, 'wild-growth', 'Wild Growth', '*', 'group', 15, 11, 7.5),
createAbility('lifebinder', 4, 'barkskin', 'Barkskin', 'O', 'shield', 46, 10, 5.5, 'shield'),
createAbility('lifebinder', 5, 'purging-sap', 'Purging Sap', 'x', 'cleanse', 12, 6, 4.5, 'cleanse'),
],
runesage: [
createAbility('runesage', 1, 'etched-mend', 'Etched Mend', '+', 'direct', 22, 3, 0.35),
createAbility('runesage', 2, 'mending-rune', 'Mending Rune', '~', 'hot', 10, 5, 0.45, 'heal_over_time'),
createAbility('runesage', 3, 'concordance', 'Concordance', '*', 'group', 16, 9, 5.5),
createAbility('runesage', 4, 'aegis-script', 'Aegis Script', 'O', 'shield', 28, 6, 4.5, 'shield'),
createAbility('runesage', 5, 'unravel', 'Unravel', 'x', 'cleanse', 8, 4, 3.5, 'cleanse'),
],
}
export function abilitiesForHealer(healerId: Iwt2HealerId | string, infusionAbilityId?: Iwt2InfusionAbilityId | null) {
const base = IWT2_HEALER_ABILITIES[asIwt2HealerId(healerId)]
const infusion = infusionAbilityId ? iwt2HealerInfusionAbility(infusionAbilityId, asIwt2HealerId(healerId)) : null
return infusion ? [...base, infusion] : base
}
export function asIwt2HealerId(value: unknown): Iwt2HealerId {
if (value === 'field_medic') return 'dawnweaver'
if (value === 'ward_sage') return 'lifebinder'
if (value === 'storm_chanter') return 'runesage'
return IWT2_HEALER_ORDER.includes(value as Iwt2HealerId)
? value as Iwt2HealerId
: 'dawnweaver'
}
function createAbility(
healerId: Iwt2HealerId,
slot: number,
slug: string,
name: string,
icon: string,
kind: Spell['kind'],
power: number,
manaCost: number,
cooldownSeconds: number,
effectType?: string,
): Iwt2HealerAbility {
return {
id: `${healerId}-${slug}`,
healerId,
slot,
name,
icon,
kind,
power,
effectType,
manaCost,
cooldownSeconds,
target: 'party-member',
}
}