forked from phenom/healer-man
Update Healer Man server
This commit is contained in:
1 parent
4c768fbec6
commit
b16821e92e
330 files changed
+35406
-1760
No files matched your search
@@ -0,0 +1,153 @@
|
||||
import type { AuraDefinition } from "./combatAuras";
|
||||
import { WOW335_TALENT_NODES } from "./wow335Talents.generated";
|
||||
|
||||
export const WOW335_MAGE_WINTERS_CHILL_TALENT_ID = "talent-68";
|
||||
export const WOW335_MAGE_WINTERS_CHILL_TAG = "wow335-mage-winters-chill";
|
||||
|
||||
const WINTERS_CHILL_TALENT = WOW335_TALENT_NODES.find((talent) => (
|
||||
talent.id === WOW335_MAGE_WINTERS_CHILL_TALENT_ID
|
||||
));
|
||||
|
||||
function tooltipNumber(description: string, pattern: RegExp): number {
|
||||
const parsed = Number(description.match(pattern)?.[1]);
|
||||
return Number.isFinite(parsed) ? parsed : 0;
|
||||
}
|
||||
|
||||
const WINTERS_CHILL_EFFECT_DESCRIPTION = WINTERS_CHILL_TALENT?.rankDescriptions[0] ?? "";
|
||||
const WINTERS_CHILL_TARGET_CRITICAL_CHANCE_PER_STACK_PERCENT = tooltipNumber(
|
||||
WINTERS_CHILL_EFFECT_DESCRIPTION,
|
||||
/increasing the chance spells will critically strike the target by\s+(\d+(?:\.\d+)?)%/i,
|
||||
);
|
||||
const WINTERS_CHILL_TARGET_HEALING_REDUCTION_PER_STACK_PERCENT = tooltipNumber(
|
||||
WINTERS_CHILL_EFFECT_DESCRIPTION,
|
||||
/reducing healing received by\s+(\d+(?:\.\d+)?)%/i,
|
||||
);
|
||||
const WINTERS_CHILL_DURATION_MS = tooltipNumber(
|
||||
WINTERS_CHILL_EFFECT_DESCRIPTION,
|
||||
/for\s+(\d+(?:\.\d+)?)\s+seconds/i,
|
||||
) * 1_000;
|
||||
const WINTERS_CHILL_MAXIMUM_STACKS = tooltipNumber(
|
||||
WINTERS_CHILL_EFFECT_DESCRIPTION,
|
||||
/stacks up to\s+(\d+)\s+times/i,
|
||||
);
|
||||
|
||||
function normalizedRank(rank: number): number {
|
||||
return Number.isFinite(rank)
|
||||
? Math.max(0, Math.min(WINTERS_CHILL_TALENT?.rankEffects.length ?? 0, Math.trunc(rank)))
|
||||
: 0;
|
||||
}
|
||||
|
||||
function generatedRankValue(rank: number, pattern: RegExp): number {
|
||||
const description = WINTERS_CHILL_TALENT?.rankDescriptions[normalizedRank(rank) - 1] ?? "";
|
||||
return tooltipNumber(description, pattern);
|
||||
}
|
||||
|
||||
export const WOW335_MAGE_WINTERS_CHILL_AURA: AuraDefinition = {
|
||||
id: "wow335:mage:winters-chill",
|
||||
name: "Winter's Chill",
|
||||
description: `Each stack increases incoming spell critical chance by ${WINTERS_CHILL_TARGET_CRITICAL_CHANCE_PER_STACK_PERCENT}% and reduces healing received by ${WINTERS_CHILL_TARGET_HEALING_REDUCTION_PER_STACK_PERCENT}% for ${WINTERS_CHILL_DURATION_MS / 1_000} seconds.`,
|
||||
disposition: "debuff",
|
||||
durationMs: WINTERS_CHILL_DURATION_MS,
|
||||
maxStacks: WINTERS_CHILL_MAXIMUM_STACKS,
|
||||
stackBehavior: "add",
|
||||
uniqueBySource: false,
|
||||
// Local child data is absent; WotLKDB 3.3.5a spell 12579 identifies it as Magic-dispellable.
|
||||
dispelCategory: "magic",
|
||||
modifiers: [{
|
||||
kind: "healing",
|
||||
direction: "taken",
|
||||
operation: "percent",
|
||||
value: -WINTERS_CHILL_TARGET_HEALING_REDUCTION_PER_STACK_PERCENT / 100,
|
||||
}],
|
||||
utilityTags: [WOW335_MAGE_WINTERS_CHILL_TAG],
|
||||
};
|
||||
|
||||
export interface Wow335MageWintersChillEvent {
|
||||
readonly abilityName: string;
|
||||
readonly attackKind: string;
|
||||
readonly school: string;
|
||||
readonly periodic: boolean;
|
||||
readonly landedDamage: number;
|
||||
}
|
||||
|
||||
export interface Wow335MageWintersChillProfile {
|
||||
readonly casterCriticalChanceBonusPercent: number;
|
||||
readonly procChancePercent: number;
|
||||
readonly targetCriticalChanceBonusPercentPerStack: number;
|
||||
readonly targetHealingReceivedReductionPercentPerStack: number;
|
||||
readonly durationMs: number;
|
||||
readonly maximumStacks: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Local generated Mage talent node 68, ranks 11180/28592/28593. Its rank
|
||||
* descriptions give the passive crit bonus, proc chance, and custom 8-second
|
||||
* child effect values; the stock 3.3.5a child row is not this custom payload.
|
||||
*/
|
||||
export function wow335MageWintersChillProfileForRank(rank: number): Wow335MageWintersChillProfile {
|
||||
const normalized = normalizedRank(rank);
|
||||
const rankEffect = WINTERS_CHILL_TALENT?.rankEffects[normalized - 1];
|
||||
return {
|
||||
casterCriticalChanceBonusPercent: generatedRankValue(
|
||||
normalized,
|
||||
/critical strike chance with all spells and abilities by\s+(\d+(?:\.\d+)?)%/i,
|
||||
),
|
||||
procChancePercent: Math.max(0, Math.min(100, rankEffect?.procChance ?? 0)),
|
||||
targetCriticalChanceBonusPercentPerStack: WINTERS_CHILL_TARGET_CRITICAL_CHANCE_PER_STACK_PERCENT,
|
||||
targetHealingReceivedReductionPercentPerStack: WINTERS_CHILL_TARGET_HEALING_REDUCTION_PER_STACK_PERCENT,
|
||||
durationMs: WINTERS_CHILL_DURATION_MS,
|
||||
maximumStacks: WINTERS_CHILL_MAXIMUM_STACKS,
|
||||
};
|
||||
}
|
||||
|
||||
export function wow335MageWintersChillProcChancePercent(
|
||||
rank: number,
|
||||
event: Wow335MageWintersChillEvent,
|
||||
): number {
|
||||
const profile = wow335MageWintersChillProfileForRank(rank);
|
||||
const eligible = profile.procChancePercent > 0
|
||||
&& event.attackKind === "spell"
|
||||
&& event.school === "frost"
|
||||
&& !event.periodic
|
||||
&& Number.isFinite(event.landedDamage)
|
||||
&& event.landedDamage > 0
|
||||
&& event.abilityName.toLowerCase() !== "frozen orb";
|
||||
return eligible ? profile.procChancePercent : 0;
|
||||
}
|
||||
|
||||
export function wow335MageWintersChillShouldProc(
|
||||
rank: number,
|
||||
event: Wow335MageWintersChillEvent,
|
||||
roll: number,
|
||||
): boolean {
|
||||
if (!Number.isFinite(roll) || roll < 0 || roll >= 1) return false;
|
||||
return roll < wow335MageWintersChillProcChancePercent(rank, event) / 100;
|
||||
}
|
||||
|
||||
export function wow335MageWintersChillStacksAfterEvent(
|
||||
currentStacks: number,
|
||||
rank: number,
|
||||
event: Wow335MageWintersChillEvent,
|
||||
roll: number,
|
||||
): number {
|
||||
const profile = wow335MageWintersChillProfileForRank(rank);
|
||||
const stacks = Number.isFinite(currentStacks)
|
||||
? Math.max(0, Math.min(profile.maximumStacks, Math.trunc(currentStacks)))
|
||||
: 0;
|
||||
return wow335MageWintersChillShouldProc(rank, event, roll)
|
||||
? Math.min(profile.maximumStacks, stacks + 1)
|
||||
: stacks;
|
||||
}
|
||||
|
||||
export function wow335MageWintersChillTargetModifiers(stacks: number): {
|
||||
readonly criticalChanceBonusPercent: number;
|
||||
readonly healingReceivedReductionPercent: number;
|
||||
} {
|
||||
const normalized = Number.isFinite(stacks)
|
||||
? Math.max(0, Math.min(WINTERS_CHILL_MAXIMUM_STACKS, Math.trunc(stacks)))
|
||||
: 0;
|
||||
return {
|
||||
criticalChanceBonusPercent: normalized * WINTERS_CHILL_TARGET_CRITICAL_CHANCE_PER_STACK_PERCENT,
|
||||
healingReceivedReductionPercent: normalized * WINTERS_CHILL_TARGET_HEALING_REDUCTION_PER_STACK_PERCENT,
|
||||
};
|
||||
}
|
||||
Reference in new issue
Block a user