forked from phenom/healer-man
Update Healer Man server
This commit is contained in:
1 parent
35dfdaed61
commit
4fb7a0b9c8
161 files changed
+24618
-529
No files matched your search
@@ -0,0 +1,121 @@
|
||||
import { WOW335_TALENT_NODES } from "./wow335Talents.generated";
|
||||
import generatedData from "./wow335AbilityData.generated.json";
|
||||
|
||||
export const WOW335_WARRIOR_ANGER_MANAGEMENT_TALENT_ID = "talent-137";
|
||||
export const WOW335_WARRIOR_ANGER_MANAGEMENT_CHARGE_AURA_TAG = "wow335-warrior-anger-management-charge";
|
||||
|
||||
const SOURCE = WOW335_TALENT_NODES.find((node) => (
|
||||
node.id === WOW335_WARRIOR_ANGER_MANAGEMENT_TALENT_ID
|
||||
));
|
||||
const CHARGE_SOURCE = generatedData.classes.warrior.find((ability) => ability.name === "Charge");
|
||||
|
||||
export function wow335WarriorChargeRank(spellId: number): number {
|
||||
return CHARGE_SOURCE?.ranks.find((rank) => rank.spellId === spellId)?.rank ?? 0;
|
||||
}
|
||||
|
||||
export interface Wow335WarriorAngerManagementProfile {
|
||||
readonly rank: number;
|
||||
readonly ragePerTick: number;
|
||||
readonly tickIntervalMs: number;
|
||||
readonly chargeBonusRage: number;
|
||||
readonly chargeDamageReductionPercent: number;
|
||||
readonly chargeDamageReductionDurationMs: number;
|
||||
readonly chargeDamageReductionSpellId: number | null;
|
||||
}
|
||||
|
||||
export interface Wow335WarriorChargeRageProfile {
|
||||
readonly chargeRank: number;
|
||||
readonly chargeSpellId: number;
|
||||
readonly angerManagementRank: number;
|
||||
readonly baseRage: number;
|
||||
readonly angerManagementBonusRage: number;
|
||||
readonly totalRage: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the base Charge Rage and the selected Anger Management rank.
|
||||
* Generated Charge tooltips hide the amount as "listed amount" while the
|
||||
* local dummy effect contains 90/120/150. WotLKDB's Charge rank-1 tooltip
|
||||
* confirms that dummy value 90 means 9 Rage; the same local field conversion
|
||||
* is applied to ranks 2 and 3 (120/150 => 12/15 Rage). The database supplies
|
||||
* only the missing unit scale; local rank rows remain the data source.
|
||||
*/
|
||||
export function wow335WarriorChargeRageProfile(
|
||||
chargeRank: number,
|
||||
angerManagementRank: number,
|
||||
): Wow335WarriorChargeRageProfile | null {
|
||||
const maxChargeRank = CHARGE_SOURCE?.ranks.length ?? 0;
|
||||
const safeChargeRank = Math.min(maxChargeRank, Math.max(0, Math.trunc(
|
||||
Number.isFinite(chargeRank) ? chargeRank : 0,
|
||||
)));
|
||||
const charge = CHARGE_SOURCE?.ranks.find((rank) => rank.rank === safeChargeRank);
|
||||
const rageEffect = charge?.effects.find((effect) => effect.effectType === 3 && effect.implicitTargetA === 1);
|
||||
if (safeChargeRank === 0 || !charge || !rageEffect || rageEffect.basePoints <= 0 || rageEffect.basePoints % 10 !== 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const maxTalentRank = SOURCE?.rankSpellIds.length ?? 0;
|
||||
const safeTalentRank = Math.min(maxTalentRank, Math.max(0, Math.trunc(
|
||||
Number.isFinite(angerManagementRank) ? angerManagementRank : 0,
|
||||
)));
|
||||
const talentProfile = wow335WarriorAngerManagementProfile(safeTalentRank);
|
||||
const baseRage = rageEffect.basePoints / 10;
|
||||
const angerManagementBonusRage = talentProfile?.chargeBonusRage ?? 0;
|
||||
return {
|
||||
chargeRank: safeChargeRank,
|
||||
chargeSpellId: charge.spellId,
|
||||
angerManagementRank: safeTalentRank,
|
||||
baseRage,
|
||||
angerManagementBonusRage,
|
||||
totalRage: baseRage + angerManagementBonusRage,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the local generated rank tooltip and rank effects. The three rank
|
||||
* tooltips specify passive Rage and Charge bonuses; the maximum-rank tooltip
|
||||
* additionally describes Charge's four-second damage reduction. Rank 1 and
|
||||
* 2 mention that capstone in their text only as a rank-3 unlock, so it is not
|
||||
* exposed until the final rank is allocated.
|
||||
*/
|
||||
export function wow335WarriorAngerManagementProfile(
|
||||
rank: number,
|
||||
): Wow335WarriorAngerManagementProfile | null {
|
||||
const rankCount = SOURCE?.rankSpellIds.length ?? 0;
|
||||
const safeRank = Math.min(rankCount, Math.max(0, Math.trunc(Number.isFinite(rank) ? rank : 0)));
|
||||
const description = SOURCE?.rankDescriptions[safeRank - 1];
|
||||
const rankEffect = SOURCE?.rankEffects[safeRank - 1];
|
||||
if (safeRank === 0 || !description || !rankEffect) return null;
|
||||
|
||||
const rage = description.match(/generates (\d+) rage per (\d+) seconds/i);
|
||||
const chargeBonus = description.match(/Charge ability by (\d+)/i);
|
||||
if (!rage || !chargeBonus) return null;
|
||||
|
||||
const ragePerTick = Number(rage[1]);
|
||||
const tickIntervalMs = Number(rage[2]) * 1_000;
|
||||
const chargeBonusRage = Number(chargeBonus[1]);
|
||||
if (![ragePerTick, tickIntervalMs, chargeBonusRage].every(Number.isFinite)
|
||||
|| ragePerTick < 0 || tickIntervalMs <= 0 || chargeBonusRage < 0) return null;
|
||||
|
||||
let chargeDamageReductionPercent = 0;
|
||||
let chargeDamageReductionDurationMs = 0;
|
||||
let chargeDamageReductionSpellId: number | null = null;
|
||||
if (safeRank === rankCount) {
|
||||
const reduction = description.match(/Charge also reduces your damage taken by (\d+)% for (\d+) seconds/i);
|
||||
if (reduction) {
|
||||
chargeDamageReductionPercent = Number(reduction[1]);
|
||||
chargeDamageReductionDurationMs = Number(reduction[2]) * 1_000;
|
||||
chargeDamageReductionSpellId = rankEffect.effects.find((effect) => effect.triggerSpellId > 0)?.triggerSpellId ?? null;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
rank: safeRank,
|
||||
ragePerTick,
|
||||
tickIntervalMs,
|
||||
chargeBonusRage,
|
||||
chargeDamageReductionPercent,
|
||||
chargeDamageReductionDurationMs,
|
||||
chargeDamageReductionSpellId,
|
||||
};
|
||||
}
|
||||
Reference in new issue
Block a user