65 lines
2.9 KiB
TypeScript
65 lines
2.9 KiB
TypeScript
import { beforeEach, describe, expect, it } from "vitest";
|
|
import { PLAYER_AGGRO_ID } from "./aggro";
|
|
import { preloadAbilityCatalogsForClasses } from "./abilityCatalog";
|
|
import { clearMobRuntimeRegistry, setMobPosition } from "./mobRuntimeRegistry";
|
|
import { clearPartyRuntimeRegistry } from "./partyRuntimeRegistry";
|
|
import { useCombatStore } from "./combatStore";
|
|
import { usePartyStore } from "./partyStore";
|
|
|
|
function soulshatterId(): string {
|
|
const ability = useCombatStore.getState().abilities.find((candidate) => candidate.name === "Soulshatter");
|
|
expect(ability, "Soulshatter").toBeDefined();
|
|
return ability!.id;
|
|
}
|
|
|
|
function setPlayerThreat(id: string, amount: number): void {
|
|
useCombatStore.setState((state) => ({
|
|
mobs: {
|
|
...state.mobs,
|
|
[id]: {
|
|
...state.mobs[id],
|
|
threatByActor: { ...state.mobs[id].threatByActor, [PLAYER_AGGRO_ID]: amount },
|
|
},
|
|
},
|
|
}));
|
|
}
|
|
|
|
describe("WoW 3.3.5 Warlock Soulshatter runtime", () => {
|
|
beforeEach(async () => {
|
|
clearMobRuntimeRegistry();
|
|
clearPartyRuntimeRegistry();
|
|
await preloadAbilityCatalogsForClasses(["warlock"]);
|
|
useCombatStore.getState().initializeCharacter({ classId: "warlock", level: 80 });
|
|
useCombatStore.getState().resetSettings();
|
|
useCombatStore.getState().setPlayerPosition([0, 0, 0]);
|
|
usePartyStore.getState().initializeParty("wow335-warlock-soulshatter-tests", 1,
|
|
useCombatStore.getState().health);
|
|
});
|
|
|
|
it("cuts threat in half inside the caster's 50-yard radius and leaves outside enemies alone", () => {
|
|
useCombatStore.getState().registerMob("soulshatter-inside", { name: "Inside", maxHealth: 10_000 });
|
|
useCombatStore.getState().registerMob("soulshatter-outside", { name: "Outside", maxHealth: 10_000 });
|
|
setMobPosition("soulshatter-inside", [20, 0, 0]);
|
|
setMobPosition("soulshatter-outside", [60, 0, 0]);
|
|
setPlayerThreat("soulshatter-inside", 100);
|
|
setPlayerThreat("soulshatter-outside", 100);
|
|
|
|
const cast = useCombatStore.getState().castAbility(soulshatterId(), undefined, 1_000);
|
|
|
|
expect(cast).toMatchObject({ ok: true, affectedMobIds: ["soulshatter-inside"] });
|
|
expect(useCombatStore.getState().mobs["soulshatter-inside"].threatByActor[PLAYER_AGGRO_ID]).toBe(50);
|
|
expect(useCombatStore.getState().mobs["soulshatter-outside"].threatByActor[PLAYER_AGGRO_ID]).toBe(100);
|
|
});
|
|
|
|
it("does not reduce distant enemies when nobody is within the caster-centered radius", () => {
|
|
useCombatStore.getState().registerMob("soulshatter-far", { name: "Far", maxHealth: 10_000 });
|
|
setMobPosition("soulshatter-far", [60, 0, 0]);
|
|
setPlayerThreat("soulshatter-far", 100);
|
|
|
|
const cast = useCombatStore.getState().castAbility(soulshatterId(), undefined, 1_000);
|
|
|
|
expect(cast).toMatchObject({ ok: true, affectedMobIds: [] });
|
|
expect(useCombatStore.getState().mobs["soulshatter-far"].threatByActor[PLAYER_AGGRO_ID]).toBe(100);
|
|
});
|
|
});
|