Files
healer-man/src/game/combatChannelAmounts.ts
T
2026-09-12 23:55:24 -04:00

34 lines
1.7 KiB
TypeScript

import { triggeredAbilityBySpellId, type AbilityDefinition, type AbilityEffect } from "./abilityCatalog";
type ChannelAmountEffect = Extract<AbilityEffect, { kind: "damage" | "dot" | "heal" | "hot" }>;
/** 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;
}