Files
healer-man/src/game/wow335HunterPetInheritedDefenseRuntime.ts
2026-10-02 10:38:12 -04:00

112 lines
4.7 KiB
TypeScript

import type { DamageSchool } from "./itemStats";
import { wow335HunterPetBaseDefenseForLevel } from "./wow335HunterPetDefenseData";
export { wow335HunterPetBaseDefenseForLevel } from "./wow335HunterPetDefenseData";
export type { Wow335HunterPetBaseDefense } from "./wow335HunterPetDefenseData";
export type Wow335HunterPetMagicSchool = Exclude<DamageSchool, "physical">;
export type Wow335HunterPetOwnerResistances = Readonly<Record<Wow335HunterPetMagicSchool, number>>;
export interface Wow335HunterPetInheritedDefenses {
/** Owner-derived contribution only; pet base armor and pet modifiers are separate. */
readonly armor: number;
/** Owner-derived contribution for the six non-physical schools. */
readonly resistances: Wow335HunterPetOwnerResistances;
}
export const WOW335_HUNTER_PET_OWNER_ARMOR_INHERITANCE_PERCENT = 35;
export const WOW335_HUNTER_PET_OWNER_MAGIC_RESISTANCE_INHERITANCE_PERCENT = 40;
function finite(value: number): number {
return Number.isFinite(value) ? value : 0;
}
function float32(value: number): number {
const rounded = Math.fround(finite(value));
return Number.isFinite(rounded) ? rounded : 0;
}
/** Match TrinityCore CalculatePct<T>: float arithmetic, then conversion to T. */
function calculatePctAsInteger(base: number, percent: number): number {
const product = float32(float32(base) * float32(percent));
const result = float32(product / float32(100));
return Math.trunc(result);
}
/**
* Compute only the owner-derived defense contribution for a Hunter pet.
* Callers still need to combine the pet's own armor/aura values and use these
* values as the pet's owner-dependent defenses change.
*/
export function wow335HunterPetInheritedDefenses(
ownerArmor: number,
ownerResistances: Wow335HunterPetOwnerResistances,
): Wow335HunterPetInheritedDefenses {
const inherit = (value: number, percent: number): number => calculatePctAsInteger(value, percent);
return {
armor: inherit(ownerArmor, WOW335_HUNTER_PET_OWNER_ARMOR_INHERITANCE_PERCENT),
resistances: {
holy: inherit(ownerResistances.holy, WOW335_HUNTER_PET_OWNER_MAGIC_RESISTANCE_INHERITANCE_PERCENT),
fire: inherit(ownerResistances.fire, WOW335_HUNTER_PET_OWNER_MAGIC_RESISTANCE_INHERITANCE_PERCENT),
nature: inherit(ownerResistances.nature, WOW335_HUNTER_PET_OWNER_MAGIC_RESISTANCE_INHERITANCE_PERCENT),
frost: inherit(ownerResistances.frost, WOW335_HUNTER_PET_OWNER_MAGIC_RESISTANCE_INHERITANCE_PERCENT),
shadow: inherit(ownerResistances.shadow, WOW335_HUNTER_PET_OWNER_MAGIC_RESISTANCE_INHERITANCE_PERCENT),
arcane: inherit(ownerResistances.arcane, WOW335_HUNTER_PET_OWNER_MAGIC_RESISTANCE_INHERITANCE_PERCENT),
},
};
}
export interface Wow335HunterPetArmorInputs {
/** `pet_levelstats.armor`, or the pet's current BASE_VALUE if modified. */
readonly petBaseArmor: number;
/** Effective pet Agility after pet-owned stat modifiers. */
readonly petAgility: number;
/** Current effective owner armor. */
readonly ownerArmor: number;
/** TrinityCore BASE_PCT multiplier; defaults to 1. */
readonly baseArmorMultiplier?: number;
/** Flat pet armor from TOTAL_VALUE; defaults to 0. */
readonly petFlatArmor?: number;
/** TrinityCore TOTAL_PCT multiplier; defaults to 1. */
readonly totalArmorMultiplier?: number;
}
/**
* Compose pet armor using the pinned TrinityCore 3.3.5 Guardian::UpdateArmor
* order, including integer CalculatePct<T> owner inheritance and final
* int32(value) truncation. This does not calculate incoming-damage mitigation.
*/
export function wow335HunterPetArmorForProfile(inputs: Wow335HunterPetArmorInputs): number {
const baseArmorMultiplier = float32(inputs.baseArmorMultiplier ?? 1);
const petFlatArmor = float32(inputs.petFlatArmor ?? 0);
const totalArmorMultiplier = float32(inputs.totalArmorMultiplier ?? 1);
const inheritedArmor = calculatePctAsInteger(
inputs.ownerArmor,
WOW335_HUNTER_PET_OWNER_ARMOR_INHERITANCE_PERCENT,
);
let value = float32(float32(inputs.petBaseArmor) * baseArmorMultiplier);
value = float32(value + float32(float32(inputs.petAgility) * float32(2)));
value = float32(value + float32(petFlatArmor + float32(inheritedArmor)));
value = float32(value * totalArmorMultiplier);
return Math.trunc(value);
}
/** Compose the pinned entry-1 baseline with current owner armor. */
export function wow335HunterPetArmorForLevel(
level: number,
ownerArmor: number,
modifiers: Omit<Wow335HunterPetArmorInputs, "petBaseArmor" | "petAgility" | "ownerArmor"> = {},
): number {
const baseline = wow335HunterPetBaseDefenseForLevel(level);
return wow335HunterPetArmorForProfile({
...modifiers,
petBaseArmor: baseline.armor,
petAgility: baseline.agility,
ownerArmor,
});
}