74 lines
3.2 KiB
TypeScript
74 lines
3.2 KiB
TypeScript
import type { AuraDefinition } from "./combatAuras";
|
|
import { WOW335_TALENT_NODES } from "./wow335Talents.generated";
|
|
|
|
export const WOW335_DEATH_KNIGHT_BLOODY_VENGEANCE_TALENT_ID = "talent-1944";
|
|
export const WOW335_DEATH_KNIGHT_BLOODY_VENGEANCE_AURA_ID = "wow335:death-knight:bloody-vengeance";
|
|
|
|
const BLOODY_VENGEANCE_NODE = WOW335_TALENT_NODES.find(
|
|
(node) => node.id === WOW335_DEATH_KNIGHT_BLOODY_VENGEANCE_TALENT_ID,
|
|
);
|
|
|
|
export interface Wow335DeathKnightBloodyVengeanceProfile {
|
|
readonly rank: number;
|
|
readonly physicalDamageBonusPerStack: number;
|
|
readonly durationMs: number;
|
|
readonly maxStacks: number;
|
|
readonly triggerSpellId: number;
|
|
}
|
|
|
|
/** Read the exact per-rank values and linked aura child from the generated local talent row. */
|
|
export function wow335DeathKnightBloodyVengeanceProfile(
|
|
rank: number,
|
|
): Wow335DeathKnightBloodyVengeanceProfile | null {
|
|
const normalizedRank = Math.trunc(rank);
|
|
const talentRank = BLOODY_VENGEANCE_NODE?.rankEffects[normalizedRank - 1];
|
|
const description = BLOODY_VENGEANCE_NODE?.rankDescriptions[normalizedRank - 1];
|
|
if (normalizedRank < 1 || !talentRank || !description || talentRank.procChance !== 100) return null;
|
|
|
|
const values = description.match(
|
|
/^Gives you a (\d+(?:\.\d+)?)% bonus to physical damage you deal for (\d+(?:\.\d+)?) seconds after dealing a critical strike from a weapon swing, spell, or ability\. This effect stacks up to (\d+) times\.$/,
|
|
);
|
|
const triggerSpellId = talentRank.effects.find((effect) => effect.triggerSpellId > 0)?.triggerSpellId ?? 0;
|
|
if (!values || triggerSpellId <= 0) return null;
|
|
|
|
const physicalDamageBonusPerStack = Number(values[1]) / 100;
|
|
const durationMs = Number(values[2]) * 1_000;
|
|
const maxStacks = Number(values[3]);
|
|
if (!Number.isFinite(physicalDamageBonusPerStack) || physicalDamageBonusPerStack <= 0
|
|
|| !Number.isFinite(durationMs) || durationMs <= 0
|
|
|| !Number.isInteger(maxStacks) || maxStacks <= 0) return null;
|
|
return { rank: normalizedRank, physicalDamageBonusPerStack, durationMs, maxStacks, triggerSpellId };
|
|
}
|
|
|
|
/** Every eligible critical-damage event can add one stack; noncrit damage cannot trigger the talent. */
|
|
export function wow335DeathKnightBloodyVengeanceShouldTrigger(
|
|
rank: number,
|
|
criticalDamageEvent: boolean,
|
|
): boolean {
|
|
return criticalDamageEvent && wow335DeathKnightBloodyVengeanceProfile(rank) !== null;
|
|
}
|
|
|
|
/** The generated tooltip scopes the stack to physical damage, regardless of attack kind. */
|
|
export function wow335DeathKnightBloodyVengeanceAuraDefinition(
|
|
rank: number,
|
|
): AuraDefinition | null {
|
|
const profile = wow335DeathKnightBloodyVengeanceProfile(rank);
|
|
if (!profile) return null;
|
|
return {
|
|
id: WOW335_DEATH_KNIGHT_BLOODY_VENGEANCE_AURA_ID,
|
|
name: "Bloody Vengeance",
|
|
description: `Critical strikes increase physical damage dealt by ${Math.round(profile.physicalDamageBonusPerStack * 100)}% per stack for ${profile.durationMs / 1_000} seconds, stacking up to ${profile.maxStacks} times.`,
|
|
disposition: "buff",
|
|
durationMs: profile.durationMs,
|
|
maxStacks: profile.maxStacks,
|
|
stackBehavior: "add",
|
|
modifiers: [{
|
|
kind: "damage",
|
|
direction: "dealt",
|
|
operation: "percent",
|
|
school: "physical",
|
|
value: profile.physicalDamageBonusPerStack,
|
|
}],
|
|
};
|
|
}
|