import { triggeredAbilityBySpellId, type AbilityDefinition, type AbilityEffect } from "./abilityCatalog"; type ChannelAmountEffect = Extract; /** Direct channel amounts span the cast; periodic trigger payloads fire each pulse. */ export function channelAmountEffects(ability: AbilityDefinition, totalTicks: number): readonly { effect: ChannelAmountEffect; multiplier: number; }[] { const ticks = Math.max(1, totalTicks); const amounts: { effect: ChannelAmountEffect; multiplier: number }[] = []; for (const effect of ability.effects) { if (effect.kind === "damage" || effect.kind === "heal" || effect.kind === "dot" || effect.kind === "hot") { amounts.push({ effect, multiplier: (effect.kind === "dot" || effect.kind === "hot" ? effect.ticks : 1) / ticks }); } else if (effect.kind === "apply-aura") { for (const proc of effect.aura.procs ?? []) { const triggers = Array.isArray(proc.triggers) ? proc.triggers : [proc.triggers]; const action = proc.action; if (!triggers.includes("periodic") || proc.chance !== 1 || proc.internalCooldownMs || proc.charges !== undefined || action.kind !== "custom" || !["wow335-trigger-spell", "rom-trigger-skill"].includes(action.id) || typeof action.data?.spellId !== "number") continue; const payload = triggeredAbilityBySpellId(action.data.spellId); for (const payloadEffect of payload?.effects ?? []) { if (payloadEffect.kind === "damage" || payloadEffect.kind === "heal") { amounts.push({ effect: payloadEffect, multiplier: 1 }); } } } } } return amounts; }