Files
healer-man/src/game/wow335MageFrostWardingArmor.integration.test.ts
T
2026-10-02 10:38:12 -04:00

162 lines
7.7 KiB
TypeScript

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<Record<string, number>> = 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([]);
});
});