Files
healer-man/src/game/combatAuraRuntime.test.ts
T

194 lines
7.2 KiB
TypeScript

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([]);
});
});