forked from phenom/healer-man
77 lines
3.3 KiB
TypeScript
77 lines
3.3 KiB
TypeScript
import { WOW335_TALENT_NODES } from "./wow335Talents.generated";
|
|
|
|
export const WOW335_WARRIOR_UNBRIDLED_WRATH_TALENT_ID = "talent-159";
|
|
export const WOW335_WARRIOR_UNBRIDLED_WRATH_ABILITY_ID = "wow335-warrior-unbridled-wrath";
|
|
export const WOW335_WARRIOR_UNBRIDLED_WRATH_PPM_PER_RANK = 3;
|
|
|
|
const UNBRIDLED_WRATH_SOURCE = WOW335_TALENT_NODES.find((node) => (
|
|
node.id === WOW335_WARRIOR_UNBRIDLED_WRATH_TALENT_ID
|
|
));
|
|
|
|
export interface Wow335WarriorUnbridledWrathProfile {
|
|
readonly rank: 1 | 2;
|
|
readonly ragePerProc: number;
|
|
/** PPM for each weapon hand, matching the simulator's PPM manager. */
|
|
readonly procsPerMinutePerWeapon: number;
|
|
}
|
|
|
|
/**
|
|
* Reads Rage per proc from this project's generated tooltip and supplies the
|
|
* otherwise missing rate from the upstream WotLK Simulator's 3 PPM per rank
|
|
* model. The simulator applies that rate to melee white-hit proc masks and
|
|
* awards 1 Rage; local tooltip values remain authoritative for our 2/4 Rage.
|
|
*
|
|
* The generated rank-1 tooltip says 2 Rage but links child 12964, whose local
|
|
* payload says 1. Rank 2 says 4 Rage and links custom child 812964, which is
|
|
* absent from stock 3.3.5a. This helper intentionally trusts tooltip amounts
|
|
* and does not use child payloads or the generated procChance field (zero).
|
|
* Sources: https://github.com/wowsims/wotlk/blob/master/sim/warrior/talents.go
|
|
* and https://wotlkdb.com/?spell=12964
|
|
*/
|
|
export function wow335WarriorUnbridledWrathProfile(
|
|
talentRank: number,
|
|
): Wow335WarriorUnbridledWrathProfile | null {
|
|
const maximumRank = Math.min(2, UNBRIDLED_WRATH_SOURCE?.rankDescriptions.length ?? 0);
|
|
const rank = Math.min(maximumRank, Math.max(0, Math.trunc(
|
|
Number.isFinite(talentRank) ? talentRank : 0,
|
|
)));
|
|
if (rank === 0) return null;
|
|
|
|
const description = UNBRIDLED_WRATH_SOURCE?.rankDescriptions[rank - 1];
|
|
const rankEffect = UNBRIDLED_WRATH_SOURCE?.rankEffects[rank - 1];
|
|
const ragePerProc = Number(description?.match(/generate (\d+) additional rage points/i)?.[1]);
|
|
if (!description || !rankEffect || rankEffect.spellId !== UNBRIDLED_WRATH_SOURCE?.rankSpellIds[rank - 1]
|
|
|| !Number.isFinite(ragePerProc) || ragePerProc <= 0) return null;
|
|
|
|
return {
|
|
rank: rank as 1 | 2,
|
|
ragePerProc,
|
|
procsPerMinutePerWeapon: WOW335_WARRIOR_UNBRIDLED_WRATH_PPM_PER_RANK * rank,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* The upstream simulator's PPM manager converts per-weapon PPM to a proc
|
|
* chance using the weapon's un-hasted swing speed: PPM * speed / 60 seconds.
|
|
* Call only for a landed damaging hit matching its melee-white-hit mask.
|
|
*/
|
|
export function wow335WarriorUnbridledWrathChancePerMeleeWhiteHit(
|
|
talentRank: number,
|
|
weaponSwingSpeedMs: number,
|
|
): number {
|
|
const profile = wow335WarriorUnbridledWrathProfile(talentRank);
|
|
if (!profile || !Number.isFinite(weaponSwingSpeedMs) || weaponSwingSpeedMs <= 0) return 0;
|
|
return Math.min(1, profile.procsPerMinutePerWeapon * weaponSwingSpeedMs / 60_000);
|
|
}
|
|
|
|
/** Resolve a deterministic 0..1 proc roll for an eligible melee white hit. */
|
|
export function wow335WarriorUnbridledWrathShouldProc(
|
|
talentRank: number,
|
|
weaponSwingSpeedMs: number,
|
|
roll: number,
|
|
): boolean {
|
|
const chance = wow335WarriorUnbridledWrathChancePerMeleeWhiteHit(talentRank, weaponSwingSpeedMs);
|
|
if (chance <= 0 || !Number.isFinite(roll) || roll < 0 || roll >= 1) return false;
|
|
return roll < chance;
|
|
}
|