Files
healer-man/src/game/romKnightScoutBloodPunishment.ts
2026-10-04 13:13:35 -04:00

59 lines
2.5 KiB
TypeScript

import type { AbilityDefinition, AbilityEffect } from "./abilityCatalog";
export const ROM_KNIGHT_SCOUT_BLOOD_PUNISHMENT_TAG = "rom-blood-punishment";
export const ROM_SCOUT_BLOOD_ARROW_AURA_TAG = "rom-self-health-drain";
const BLOOD_PUNISHMENT_MODIFIERS = [
{ kind: "healing", direction: "taken", operation: "percent", value: 0.15 },
{ kind: "damage", direction: "dealt", school: "holy", operation: "percent", value: 0.05 },
] as const satisfies NonNullable<Extract<AbilityEffect, { kind: "apply-aura" }>["aura"]["modifiers"]>;
function hasPassive(tags: readonly string[] | ReadonlySet<string>): boolean {
return Array.isArray(tags)
? tags.includes(ROM_KNIGHT_SCOUT_BLOOD_PUNISHMENT_TAG)
: (tags as ReadonlySet<string>).has(ROM_KNIGHT_SCOUT_BLOOD_PUNISHMENT_TAG);
}
/**
* Current CoA Blood Punishment modifies the active Blood Arrow aura itself.
* Keeping both modifiers on the source aura makes them actor-local and gives
* them the same removal/expiry lifecycle as Blood Arrow, without inventing a
* second timer for the passive.
*/
export function romKnightScoutBloodPunishmentActivationEffects(
ability: AbilityDefinition,
effects: readonly AbilityEffect[],
passiveTags: readonly string[] | ReadonlySet<string>,
): readonly AbilityEffect[] {
if (ability.source !== "runewaker"
|| ability.classId !== "rom-scout"
|| ability.secondaryClassId !== undefined
|| ability.dbcSpellId !== 490434
|| !hasPassive(passiveTags)) return effects;
let attachedToActiveArrow = false;
const updated = effects.map((effect) => {
if (effect.kind !== "apply-aura"
|| effect.recipient !== "caster"
|| !effect.aura.utilityTags?.includes(ROM_SCOUT_BLOOD_ARROW_AURA_TAG)) return effect;
attachedToActiveArrow = true;
const current = effect.aura.modifiers ?? [];
const modifiers = BLOOD_PUNISHMENT_MODIFIERS.filter((addition) => !current.some((modifier) => {
if (addition.kind === "healing") return modifier.kind === "healing"
&& modifier.direction === addition.direction
&& modifier.operation === addition.operation
&& modifier.value === addition.value;
return modifier.kind === "damage"
&& modifier.direction === addition.direction
&& modifier.school === addition.school
&& modifier.operation === addition.operation
&& modifier.value === addition.value;
}));
return modifiers.length === 0 ? effect : {
...effect,
aura: { ...effect.aura, modifiers: [...current, ...modifiers] },
};
});
return attachedToActiveArrow ? updated : effects;
}