112 lines
4.7 KiB
TypeScript
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,
|
|
});
|
|
}
|