78 lines
3.7 KiB
TypeScript
78 lines
3.7 KiB
TypeScript
import { beforeEach, describe, expect, it } from "vitest";
|
|
import { abilityTalentNodeId } from "./abilityCatalog";
|
|
import { clearMobRuntimeRegistry, setMobPosition } from "./mobRuntimeRegistry";
|
|
import { clearPartyRuntimeRegistry } from "./partyRuntimeRegistry";
|
|
import { PLAYER_AURA_ENTITY_ID, useCombatStore } from "./combatStore";
|
|
import { usePartyStore } from "./partyStore";
|
|
|
|
function unlockShamanTalent(abilityName: string): string {
|
|
const ability = useCombatStore.getState().abilities.find((candidate) => candidate.name === abilityName);
|
|
expect(ability, abilityName).toBeDefined();
|
|
const nodeId = abilityTalentNodeId(ability!);
|
|
expect(nodeId, abilityName).toBeTruthy();
|
|
useCombatStore.setState((state) => ({ talentRanks: { ...state.talentRanks, [nodeId!]: 1 } }));
|
|
return ability!.id;
|
|
}
|
|
|
|
describe("WoW Shaman Shamanistic Rage source proc", () => {
|
|
beforeEach(() => {
|
|
clearMobRuntimeRegistry();
|
|
clearPartyRuntimeRegistry();
|
|
useCombatStore.getState().initializeCharacter({ classId: "shaman", level: 80, xp: 0 });
|
|
useCombatStore.getState().resetSettings();
|
|
useCombatStore.getState().setPlayerPosition([0, 0, 0]);
|
|
usePartyStore.getState().initializeParty("wow-shamanistic-rage-runtime-tests", 1, useCombatStore.getState().health);
|
|
useCombatStore.getState().registerMob("shamanistic-rage-target", { name: "Shamanistic Rage target", maxHealth: 100_000, xpReward: 0 });
|
|
setMobPosition("shamanistic-rage-target", [2, 0, 0]);
|
|
useCombatStore.getState().selectMob("shamanistic-rage-target");
|
|
});
|
|
|
|
it("restores 15% attack power as mana on landed melee hits for the 15-second aura window", () => {
|
|
const rageId = unlockShamanTalent("Shamanistic Rage");
|
|
const rageAbility = useCombatStore.getState().abilities.find((candidate) => candidate.id === rageId);
|
|
expect(rageAbility?.dbcSpellId).toBe(30823);
|
|
useCombatStore.setState((state) => ({
|
|
resource: 300,
|
|
resourcePools: { ...state.resourcePools, mana: 300 },
|
|
}));
|
|
|
|
const rageCast = useCombatStore.getState().castAbility(rageId, undefined, 1_000);
|
|
expect(rageCast.ok).toBe(true);
|
|
const aura = useCombatStore.getState().auras.find((candidate) => (
|
|
candidate.targetId === PLAYER_AURA_ENTITY_ID
|
|
&& candidate.definition.procs?.some((proc) => proc.action.kind === "custom"
|
|
&& proc.action.id === "wow335-shamanistic-rage-mana")
|
|
));
|
|
expect(aura).toBeDefined();
|
|
expect(aura?.expiresAt).toBe(16_000);
|
|
|
|
for (let now = 3_000; now < 16_000; now += 2_500) {
|
|
useCombatStore.setState({ autoAttackTargetId: "shamanistic-rage-target", nextAutoAttackAt: now });
|
|
useCombatStore.getState().tick(0.1, now);
|
|
if (useCombatStore.getState().combatEvents.some((event) => (
|
|
event.kind === "resource" && event.abilityId === rageId && event.effectiveAmount > 0
|
|
))) break;
|
|
}
|
|
const afterMelee = useCombatStore.getState();
|
|
expect(afterMelee.resourcePools.mana).toBeGreaterThan(0);
|
|
expect(afterMelee.combatEvents.some((event) => (
|
|
event.kind === "resource"
|
|
&& event.abilityId === rageId
|
|
&& event.effectiveAmount > 0
|
|
))).toBe(true);
|
|
|
|
const rageRestoresBeforeExpiry = afterMelee.combatEvents.filter((event) => (
|
|
event.kind === "resource" && event.abilityId === rageId
|
|
)).length;
|
|
useCombatStore.setState({
|
|
autoAttackTargetId: "shamanistic-rage-target",
|
|
nextAutoAttackAt: 20_000,
|
|
});
|
|
useCombatStore.getState().tick(0.1, 20_000);
|
|
expect(useCombatStore.getState().auras.some((entry) => entry.instanceId === aura?.instanceId)).toBe(false);
|
|
expect(useCombatStore.getState().combatEvents.filter((event) => (
|
|
event.kind === "resource" && event.abilityId === rageId
|
|
))).toHaveLength(rageRestoresBeforeExpiry);
|
|
});
|
|
});
|