import { beforeEach, describe, expect, it } from "vitest"; import { PLAYER_AGGRO_ID } from "./aggro"; import { applyAura, type AuraDefinition } from "./combatAuras"; import { useCombatStore } from "./combatStore"; import { clearMobRuntimeRegistry, setMobPosition } from "./mobRuntimeRegistry"; import { clearPartyRuntimeRegistry } from "./partyRuntimeRegistry"; import { usePartyStore } from "./partyStore"; function registerTarget(id = "target", distance = 2): void { useCombatStore.getState().registerMob(id, { name: id, maxHealth: 1_000, xpReward: 0 }); setMobPosition(id, [distance, 0, 0]); expect(useCombatStore.getState().selectMob(id)).toBe(true); } describe("named aura combat runtime", () => { beforeEach(() => { clearMobRuntimeRegistry(); clearPartyRuntimeRegistry(); usePartyStore.getState().initializeParty("aura-runtime", 80, 2_000); usePartyStore.getState().selectMember(null); useCombatStore.getState().initializeCharacter({ classId: "priest", level: 80 }); useCombatStore.getState().setPlayerPosition([0, 0, 0]); }); it("applies and expires an imported named player buff", () => { const now = 10_000; const result = useCombatStore.getState().castAbility( "wow335-priest-power-word-fortitude", undefined, now, ); expect(result.ok).toBe(true); const fortitude = useCombatStore.getState().auras.find((aura) => ( aura.definition.name.startsWith("Power Word: Fortitude (DBC") )); expect(fortitude).toMatchObject({ sourceId: PLAYER_AGGRO_ID, targetId: PLAYER_AGGRO_ID, expiresAt: now + 1_800_000, definition: { disposition: "buff", dispelCategory: "magic", icon: useCombatStore.getState().abilities.find((ability) => ( ability.id === "wow335-priest-power-word-fortitude" ))?.icon, }, }); useCombatStore.getState().tick(0, now + 1_800_000); expect(useCombatStore.getState().auras.some((aura) => aura.definition.id === fortitude?.definition.id)).toBe(false); }); it("consumes a named absorb before player health", () => { const now = Date.now(); expect(useCombatStore.getState().castAbility( "wow335-priest-power-word-shield", undefined, now, ).ok).toBe(true); const beforeHealth = useCombatStore.getState().health; const beforeAbsorb = useCombatStore.getState().auras .flatMap((aura) => aura.absorbs) .reduce((total, absorb) => total + absorb.remaining, 0); expect(beforeAbsorb).toBeGreaterThan(0); expect(useCombatStore.getState().auras.find((aura) => aura.absorbs.length)?.definition.icon).toBe( useCombatStore.getState().abilities.find((ability) => ( ability.id === "wow335-priest-power-word-shield" ))?.icon, ); const healthDamage = useCombatStore.getState().damagePlayer(20, "shadow", 80); const afterAbsorb = useCombatStore.getState().auras .flatMap((aura) => aura.absorbs) .reduce((total, absorb) => total + absorb.remaining, 0); expect(healthDamage).toBe(0); expect(useCombatStore.getState().health).toBe(beforeHealth); expect(afterAbsorb).toBeLessThan(beforeAbsorb); }); it("cleanses a matching debuff without removing an unrelated category", () => { useCombatStore.getState().initializeCharacter({ classId: "paladin", level: 80 }); const magic: AuraDefinition = { id: "test-magic-debuff", name: "Magic Debuff", disposition: "debuff", durationMs: 30_000, dispelCategory: "magic", }; const curse: AuraDefinition = { id: "test-curse-debuff", name: "Curse Debuff", disposition: "debuff", durationMs: 30_000, dispelCategory: "curse", }; let auras = applyAura([], { definition: magic, sourceId: "enemy", targetId: PLAYER_AGGRO_ID, now: 1_000 }).auras; auras = applyAura(auras, { definition: curse, sourceId: "enemy", targetId: PLAYER_AGGRO_ID, now: 1_001 }).auras; useCombatStore.setState({ auras }); expect(useCombatStore.getState().castAbility("wow335-paladin-cleanse", undefined, 2_000).ok).toBe(true); expect(useCombatStore.getState().auras.map((aura) => aura.definition.id)).toEqual(["test-curse-debuff"]); }); it("interrupts an active enemy cast and applies its school lockout", () => { useCombatStore.getState().initializeCharacter({ classId: "rogue", level: 80 }); registerTarget("caster"); useCombatStore.setState((state) => ({ mobs: { ...state.mobs, caster: { ...state.mobs.caster, activeCast: { attackId: "fireball", name: "Fireball", school: "fire", interruptible: true, targetActorId: PLAYER_AGGRO_ID, startedAt: 1_000, completesAt: 6_000, }, }, }, })); expect(useCombatStore.getState().castAbility("rogue-kick", undefined, 2_000).ok).toBe(true); expect(useCombatStore.getState().mobs.caster.activeCast).toBeNull(); expect(useCombatStore.getState().mobs.caster.schoolLockedUntil.fire).toBeGreaterThanOrEqual(7_000); }); it("executes a guaranteed aura proc as the real triggered spell", () => { useCombatStore.getState().initializeCharacter({ classId: "warlock", level: 80 }); registerTarget("proc-target"); const procAura: AuraDefinition = { id: "test-triggered-fear", name: "Triggered Fear", disposition: "buff", durationMs: null, procs: [{ id: "test-triggered-fear-proc", triggers: "cast", chance: 1, action: { kind: "custom", id: "wow335-trigger-spell", data: { spellId: 5782 } }, }], }; useCombatStore.setState({ auras: applyAura([], { definition: procAura, sourceId: PLAYER_AGGRO_ID, targetId: PLAYER_AGGRO_ID, now: 1_000, }).auras, }); expect(useCombatStore.getState().castAbility("warlock-corruption", undefined, 2_000).ok).toBe(true); expect(useCombatStore.getState().mobs["proc-target"].statuses).toContainEqual({ kind: "fear", sourceAbilityId: "warlock-fear", endsAt: 8_000, }); }); it("purges the named and legacy views of a real enemy magic buff", () => { useCombatStore.getState().initializeCharacter({ classId: "shaman", level: 80 }); registerTarget("buffed-enemy"); const enemyBuff: AuraDefinition = { id: "enemy:buffed-enemy:arcane-empowerment", name: "Arcane Empowerment", disposition: "buff", durationMs: 30_000, dispelCategory: "magic", }; useCombatStore.setState((state) => ({ auras: applyAura(state.auras, { definition: enemyBuff, sourceId: "buffed-enemy", targetId: "buffed-enemy", now: 1_000, }).auras, mobs: { ...state.mobs, "buffed-enemy": { ...state.mobs["buffed-enemy"], auras: [{ id: "arcane-empowerment", sourceAbilityId: "enemy-buff", endsAt: 31_000 }], }, }, })); expect(useCombatStore.getState().castAbility("wow335-shaman-purge", undefined, 2_000).ok).toBe(true); expect(useCombatStore.getState().auras.some((aura) => aura.definition.id === enemyBuff.id)).toBe(false); expect(useCombatStore.getState().mobs["buffed-enemy"].auras).toEqual([]); }); });