import type { DamageSchool } from "./itemStats"; import { wow335HunterPetBaseDefenseForLevel } from "./wow335HunterPetDefenseData"; export { wow335HunterPetBaseDefenseForLevel } from "./wow335HunterPetDefenseData"; export type { Wow335HunterPetBaseDefense } from "./wow335HunterPetDefenseData"; export type Wow335HunterPetMagicSchool = Exclude; export type Wow335HunterPetOwnerResistances = Readonly>; 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: 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 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 = {}, ): number { const baseline = wow335HunterPetBaseDefenseForLevel(level); return wow335HunterPetArmorForProfile({ ...modifiers, petBaseArmor: baseline.armor, petAgility: baseline.agility, ownerArmor, }); }