import { beforeEach, describe, expect, it } from "vitest"; import { abilityAtLevel, abilityById } from "./abilityCatalog"; import { resolveStatValue, type ActiveAura } from "./combatAuras"; import { PLAYER_AURA_ENTITY_ID, useCombatStore } from "./combatStore"; import { deriveCharacterStats } from "./wotlkStats"; import { advanceDungeonPartyCombat, resetPartyRuntimeClock } from "./partyRuntime"; import { createConfiguredPartyMember, usePartyStore } from "./partyStore"; import { clearPartyRuntimeRegistry, registerPartyRuntimePosition } from "./partyRuntimeRegistry"; import { EMPTY_ITEM_STATS } from "./itemStats"; import { WOW335_MAGE_FROST_WARDING_ARMOR_ABILITIES, WOW335_MAGE_FROST_WARDING_ARMOR_TAG, WOW335_MAGE_FROST_WARDING_TALENT_ID, } from "./wow335MageFrostWardingRuntime"; const TEST_NOW = 1_000; function isArmorOrResistanceAura(aura: ActiveAura): boolean { return Boolean(aura.definition.modifiers?.some((modifier) => modifier.kind === "stat" && (modifier.stat === "armor" || modifier.stat.startsWith("resistance:")))); } function armorAuras(targetId: string) { return useCombatStore.getState().auras.filter((aura) => ( aura.targetId === targetId && aura.definition.utilityTags?.includes(WOW335_MAGE_FROST_WARDING_ARMOR_TAG) )); } function baseArmor(classId: "mage", level: number, gearStats = EMPTY_ITEM_STATS): number { return deriveCharacterStats(classId, level, gearStats).armor; } function runPlayerArmorCast(armor: "frost" | "ice", rank: number) { useCombatStore.getState().initializeCharacter({ classId: "mage", level: 80, xp: 0 }); const baseAbility = abilityById(WOW335_MAGE_FROST_WARDING_ARMOR_ABILITIES[armor].abilityId); if (!baseAbility) throw new Error(`Missing local Mage ${armor} Armor.`); const ability = abilityAtLevel(baseAbility, 80); useCombatStore.setState((state) => ({ talentRanks: { ...state.talentRanks, [WOW335_MAGE_FROST_WARDING_TALENT_ID]: rank }, })); expect(useCombatStore.getState().castAbility(ability.id, undefined, TEST_NOW)).toMatchObject({ ok: true }); const auras = armorAuras(PLAYER_AURA_ENTITY_ID); const activeAuras = useCombatStore.getState().auras.filter((aura) => aura.targetId === PLAYER_AURA_ENTITY_ID); const sourceAuraPrefix = `wow335:${ability.dbcSpellId}:effect:`; const sourceAuras = activeAuras.filter((aura) => aura.definition.id.startsWith(sourceAuraPrefix) && isArmorOrResistanceAura(aura)); const ambientAuras = activeAuras.filter((aura) => !sourceAuras.includes(aura)); const base = baseArmor("mage", 80, useCombatStore.getState().gearStats); return { auras, armorValue: resolveStatValue(base, activeAuras, "armor") - resolveStatValue(base, ambientAuras, "armor"), frostResistance: resolveStatValue(0, activeAuras, "resistance:frost") - resolveStatValue(0, ambientAuras, "resistance:frost"), sourceAuraCount: sourceAuras.length, }; } function runCompanionArmorCast(armor: "frost" | "ice", rank: number) { useCombatStore.getState().initializeCharacter({ classId: "mage", level: 80, xp: 0 }); usePartyStore.getState().initializeParty(`frost-warding-companion-${armor}-${rank}`, 80, useCombatStore.getState().health, "damage", 1); const talentRanks: Readonly> = rank > 0 ? { [WOW335_MAGE_FROST_WARDING_TALENT_ID]: rank } : {}; const member = createConfiguredPartyMember({ name: "Frost Warding Mage", classId: "mage", specialization: "Frost", specializationId: "mage:frost", talentTreeId: "mage-frost", talentRanks, role: "damage", }, 80, 0, `frost-warding-companion-${armor}-${rank}`); const baseAbility = abilityById(WOW335_MAGE_FROST_WARDING_ARMOR_ABILITIES[armor].abilityId); if (!baseAbility) throw new Error(`Missing local Mage ${armor} Armor.`); const ability = abilityAtLevel(baseAbility, member.level); usePartyStore.setState({ members: [{ ...member, gearStats: EMPTY_ITEM_STATS, talentRanks, activeCast: { abilityId: ability.id, school: "frost", mode: "cast", startedAt: TEST_NOW, completesAt: TEST_NOW, originalDurationMs: ability.castTimeMs, pushbackHits: 0, origin: [0, 0, 0], targetId: member.id, }, activeCastTargetId: member.id, status: "healing", }] }); registerPartyRuntimePosition(member.id, [0, 0, 0]); useCombatStore.getState().synchronizeActors(); advanceDungeonPartyCombat(TEST_NOW); const auras = armorAuras(member.id); const activeAuras = useCombatStore.getState().auras.filter((aura) => aura.targetId === member.id); const sourceAuraPrefix = `wow335:${ability.dbcSpellId}:effect:`; const sourceAuras = activeAuras.filter((aura) => aura.definition.id.startsWith(sourceAuraPrefix) && isArmorOrResistanceAura(aura)); const ambientAuras = activeAuras.filter((aura) => !sourceAuras.includes(aura)); const base = baseArmor("mage", member.level, member.gearStats); return { auras, armorValue: resolveStatValue(base, activeAuras, "armor") - resolveStatValue(base, ambientAuras, "armor"), frostResistance: resolveStatValue(0, activeAuras, "resistance:frost") - resolveStatValue(0, ambientAuras, "resistance:frost"), sourceAuraCount: sourceAuras.length, }; } describe("WoW Mage Frost Warding Frost/Ice Armor integration", () => { beforeEach(() => { clearPartyRuntimeRegistry(); resetPartyRuntimeClock(); useCombatStore.getState().initializeCharacter({ classId: "mage", level: 80, xp: 0 }); usePartyStore.getState().initializeParty("frost-warding-armor-reset", 80, useCombatStore.getState().health, "damage", 1); }); it.each([ { armor: "frost" as const, rank: 0, expectedArmor: 200, expectedResistance: 0 }, { armor: "frost" as const, rank: 1, expectedArmor: 250, expectedResistance: 0 }, { armor: "frost" as const, rank: 2, expectedArmor: 300, expectedResistance: 0 }, { armor: "ice" as const, rank: 0, expectedArmor: 930, expectedResistance: 40 }, { armor: "ice" as const, rank: 1, expectedArmor: 1_162.5, expectedResistance: 50 }, { armor: "ice" as const, rank: 2, expectedArmor: 1_395, expectedResistance: 60 }, ])("casts player $armor Armor with rank $rank", ({ armor, rank, expectedArmor, expectedResistance }) => { const result = runPlayerArmorCast(armor, rank); expect(result.armorValue).toBe(expectedArmor); expect(result.frostResistance).toBe(expectedResistance); expect(result.auras.length).toBe(rank > 0 ? (armor === "ice" ? 2 : 1) : 0); expect(result.sourceAuraCount).toBe(armor === "ice" ? 2 : 1); }); it.each([ { armor: "frost" as const, rank: 0, expectedArmor: 200, expectedResistance: 0 }, { armor: "frost" as const, rank: 1, expectedArmor: 250, expectedResistance: 0 }, { armor: "frost" as const, rank: 2, expectedArmor: 300, expectedResistance: 0 }, { armor: "ice" as const, rank: 0, expectedArmor: 930, expectedResistance: 40 }, { armor: "ice" as const, rank: 1, expectedArmor: 1_162.5, expectedResistance: 50 }, { armor: "ice" as const, rank: 2, expectedArmor: 1_395, expectedResistance: 60 }, ])("casts companion $armor Armor with rank $rank", ({ armor, rank, expectedArmor, expectedResistance }) => { const result = runCompanionArmorCast(armor, rank); expect(result.armorValue).toBe(expectedArmor); expect(result.frostResistance).toBe(expectedResistance); expect(result.auras.length).toBe(rank > 0 ? (armor === "ice" ? 2 : 1) : 0); expect(result.sourceAuraCount).toBe(armor === "ice" ? 2 : 1); }); it("does not apply the conditional armor bonus before a Mage Frost/Ice Armor aura exists", () => { useCombatStore.getState().initializeCharacter({ classId: "mage", level: 80, xp: 0 }); useCombatStore.setState((state) => ({ talentRanks: { ...state.talentRanks, [WOW335_MAGE_FROST_WARDING_TALENT_ID]: 2 }, })); expect(armorAuras(PLAYER_AURA_ENTITY_ID)).toEqual([]); }); });