147 lines
5.3 KiB
TypeScript
147 lines
5.3 KiB
TypeScript
import { WOW335_TALENT_NODES } from "./wow335Talents.generated";
|
|
import type { AuraDefinition } from "./combatAuras";
|
|
|
|
export const WOW335_WARRIOR_IMPROVED_VICTORY_RUSH_TALENT_ID = "talent-161";
|
|
export const WOW335_WARRIOR_IMPROVED_VICTORY_RUSH_READY_TAG = "wow335-warrior-improved-victory-rush-ready";
|
|
export const WOW335_WARRIOR_IMPROVED_VICTORY_RUSH_COOLDOWN_TAG = "wow335-warrior-improved-victory-rush-cooldown";
|
|
export const WOW335_WARRIOR_IMPROVED_VICTORY_RUSH_ABILITY_ID = "wow335-warrior-improved-victory-rush";
|
|
export const WOW335_WARRIOR_VICTORY_RUSH_KILL_READY_TAG = "wow335-warrior-victory-rush-kill-ready";
|
|
export const WOW335_WARRIOR_VICTORY_RUSH_KILL_WINDOW_MS = 20_000;
|
|
|
|
export interface Wow335WarriorImprovedVictoryRushProfile {
|
|
readonly rank: number;
|
|
readonly parryProcChancePercent: number;
|
|
readonly criticalChanceBonusPercent: number;
|
|
readonly additionalThreatPercent: number;
|
|
readonly readyDurationMs: number;
|
|
readonly internalCooldownMs: number;
|
|
}
|
|
|
|
const talent = WOW335_TALENT_NODES.find((node) => (
|
|
node.id === WOW335_WARRIOR_IMPROVED_VICTORY_RUSH_TALENT_ID
|
|
));
|
|
|
|
function boundedRank(rank: number): number {
|
|
return Math.min(3, Math.max(0, Math.trunc(Number.isFinite(rank) ? rank : 0)));
|
|
}
|
|
|
|
function parsePositiveMatch(text: string | undefined, pattern: RegExp): number {
|
|
const value = Number(text?.match(pattern)?.[1]);
|
|
return Number.isFinite(value) && value > 0 ? value : 0;
|
|
}
|
|
|
|
export function wow335WarriorImprovedVictoryRushProfile(
|
|
rank: number,
|
|
): Wow335WarriorImprovedVictoryRushProfile {
|
|
const safeRank = boundedRank(rank);
|
|
const rankIndex = safeRank - 1;
|
|
const rankDescription = safeRank > 0 ? talent?.rankDescriptions[rankIndex] : undefined;
|
|
return {
|
|
rank: safeRank,
|
|
parryProcChancePercent: safeRank > 0
|
|
? talent?.rankEffects[rankIndex]?.procChance ?? 0
|
|
: 0,
|
|
criticalChanceBonusPercent: parsePositiveMatch(
|
|
rankDescription,
|
|
/critical strike chance of your Victory Rush by (\d+)%/i,
|
|
),
|
|
additionalThreatPercent: parsePositiveMatch(
|
|
rankDescription,
|
|
/additional (\d+)% threat/i,
|
|
),
|
|
readyDurationMs: parsePositiveMatch(
|
|
talent?.description,
|
|
/allow the use of Victory Rush for (\d+) seconds/i,
|
|
) * 1_000,
|
|
internalCooldownMs: parsePositiveMatch(
|
|
talent?.description,
|
|
/once every (\d+) seconds/i,
|
|
) * 1_000,
|
|
};
|
|
}
|
|
|
|
/** A successful parry can arm the generated Victory Rush window unless its ICD is active. */
|
|
export function wow335WarriorImprovedVictoryRushShouldProc(
|
|
rank: number,
|
|
parried: boolean,
|
|
internalCooldownActive: boolean,
|
|
rollPercent: number,
|
|
): boolean {
|
|
const profile = wow335WarriorImprovedVictoryRushProfile(rank);
|
|
return profile.rank > 0
|
|
&& parried
|
|
&& !internalCooldownActive
|
|
&& Number.isFinite(rollPercent)
|
|
&& rollPercent >= 0
|
|
&& rollPercent < profile.parryProcChancePercent;
|
|
}
|
|
|
|
/** The tooltip's permanent rank bonus applies to every Victory Rush hit. */
|
|
export function wow335WarriorImprovedVictoryRushCriticalChanceBonusPercent(
|
|
rank: number,
|
|
abilityName: string,
|
|
): number {
|
|
if (abilityName.trim().toLowerCase() !== "victory rush") return 0;
|
|
return wow335WarriorImprovedVictoryRushProfile(rank).criticalChanceBonusPercent;
|
|
}
|
|
|
|
/** The extra-threat rider applies only to Victory Rush casts made from the parry window. */
|
|
export function wow335WarriorImprovedVictoryRushThreatScale(
|
|
rank: number,
|
|
abilityName: string,
|
|
parryWindowReady: boolean,
|
|
): number {
|
|
if (!parryWindowReady || abilityName.trim().toLowerCase() !== "victory rush") return 1;
|
|
return 1 + wow335WarriorImprovedVictoryRushProfile(rank).additionalThreatPercent / 100;
|
|
}
|
|
|
|
export function wow335WarriorImprovedVictoryRushReadyAuraDefinition(
|
|
rank: number,
|
|
): AuraDefinition | null {
|
|
const profile = wow335WarriorImprovedVictoryRushProfile(rank);
|
|
if (profile.rank <= 0 || profile.readyDurationMs <= 0) return null;
|
|
return {
|
|
id: WOW335_WARRIOR_IMPROVED_VICTORY_RUSH_READY_TAG,
|
|
name: "Victory Rush ready",
|
|
description: `A parry enables Victory Rush with ${profile.additionalThreatPercent}% additional threat.`,
|
|
disposition: "buff",
|
|
durationMs: profile.readyDurationMs,
|
|
maxStacks: 1,
|
|
stackBehavior: "refresh",
|
|
uniqueBySource: true,
|
|
utilityTags: [WOW335_WARRIOR_IMPROVED_VICTORY_RUSH_READY_TAG],
|
|
};
|
|
}
|
|
|
|
export function wow335WarriorImprovedVictoryRushCooldownAuraDefinition(
|
|
rank: number,
|
|
): AuraDefinition | null {
|
|
const profile = wow335WarriorImprovedVictoryRushProfile(rank);
|
|
if (profile.rank <= 0 || profile.internalCooldownMs <= 0) return null;
|
|
return {
|
|
id: WOW335_WARRIOR_IMPROVED_VICTORY_RUSH_COOLDOWN_TAG,
|
|
name: "Improved Victory Rush cooldown",
|
|
disposition: "buff",
|
|
durationMs: profile.internalCooldownMs,
|
|
maxStacks: 1,
|
|
stackBehavior: "refresh",
|
|
hideFromAuraStrip: true,
|
|
uniqueBySource: true,
|
|
utilityTags: [WOW335_WARRIOR_IMPROVED_VICTORY_RUSH_COOLDOWN_TAG],
|
|
};
|
|
}
|
|
|
|
export function wow335WarriorVictoryRushKillAuraDefinition(): AuraDefinition {
|
|
return {
|
|
id: WOW335_WARRIOR_VICTORY_RUSH_KILL_READY_TAG,
|
|
name: "Victory Rush ready",
|
|
description: "A qualifying kill enables Victory Rush for 20 seconds.",
|
|
disposition: "buff",
|
|
durationMs: WOW335_WARRIOR_VICTORY_RUSH_KILL_WINDOW_MS,
|
|
maxStacks: 1,
|
|
stackBehavior: "refresh",
|
|
uniqueBySource: true,
|
|
utilityTags: [WOW335_WARRIOR_VICTORY_RUSH_KILL_READY_TAG],
|
|
};
|
|
}
|