forked from phenom/healer-man
84 lines
3.6 KiB
TypeScript
84 lines
3.6 KiB
TypeScript
import { beforeEach, describe, expect, it } from "vitest";
|
|
import { abilitiesForCharacter } from "./abilityCatalog";
|
|
import { useCombatStore, stableCombatUnit } from "./combatStore";
|
|
import { ROM_PRIEST_CHAMPION_REGENERATE_PROC_AURA_ID } from "./romPriestChampionOverrides";
|
|
import { createConfiguredPartyMember, usePartyStore } from "./partyStore";
|
|
import { advanceDungeonPartyCombat, resetPartyRuntimeClock } from "./partyRuntime";
|
|
import { clearPartyRuntimeRegistry, registerPartyRuntimePosition } from "./partyRuntimeRegistry";
|
|
|
|
describe("RoM Priest/Champion Protection Rune Seal companion reset", () => {
|
|
beforeEach(() => {
|
|
clearPartyRuntimeRegistry();
|
|
resetPartyRuntimeClock();
|
|
useCombatStore.getState().initializeCharacter({
|
|
classId: "rom-warrior", raceId: "rom-human", level: 80,
|
|
});
|
|
usePartyStore.getState().initializeParty("priest-protection-rune-seal", 80,
|
|
useCombatStore.getState().health, "damage", 1, "rom");
|
|
});
|
|
|
|
it("resets only its Priest/Champion owner's Heart Rune Energy on a successful Regenerate heal tick", () => {
|
|
const member = createConfiguredPartyMember({
|
|
name: "Priest Champion",
|
|
classId: "rom-priest",
|
|
secondaryClassId: "rom-champion",
|
|
specialization: "Healer",
|
|
role: "healer",
|
|
talentRanks: {},
|
|
}, 80, 0, "protection-rune-seal");
|
|
const abilities = abilitiesForCharacter(member.classId, member.secondaryClassId);
|
|
const regenerate = abilities.find((ability) => ability.dbcSpellId === 490_269)!;
|
|
const heartRuneEnergy = abilities.find((ability) => ability.dbcSpellId === 498_612)!;
|
|
const unrelatedCooldowns = { ...member.cooldowns, [heartRuneEnergy.id]: 33_333 };
|
|
const readyAtFirstTick = {
|
|
...member,
|
|
cooldowns: unrelatedCooldowns,
|
|
activeCast: {
|
|
abilityId: regenerate.id,
|
|
school: "nature" as const,
|
|
mode: "cast" as const,
|
|
startedAt: 1_000,
|
|
completesAt: 1_000,
|
|
originalDurationMs: 0,
|
|
pushbackHits: 0,
|
|
origin: [0, 0, 0] as const,
|
|
targetId: member.id,
|
|
},
|
|
activeCastTargetId: member.id,
|
|
status: "healing" as const,
|
|
};
|
|
usePartyStore.setState({ members: [readyAtFirstTick] });
|
|
useCombatStore.setState((state) => ({
|
|
cooldowns: { ...state.cooldowns, [heartRuneEnergy.id]: 22_222 },
|
|
}));
|
|
registerPartyRuntimePosition(member.id, [0, 0, 0]);
|
|
useCombatStore.getState().synchronizeActors();
|
|
|
|
advanceDungeonPartyCombat(1_000);
|
|
|
|
const protectionAura = useCombatStore.getState().auras.find((aura) => (
|
|
aura.definition.id === ROM_PRIEST_CHAMPION_REGENERATE_PROC_AURA_ID
|
|
));
|
|
expect(protectionAura).toMatchObject({ sourceId: member.id, targetId: member.id });
|
|
const hot = useCombatStore.getState().effects.find((effect) => (
|
|
effect.kind === "hot" && effect.sourceActorId === member.id && effect.sourceAbilityId === regenerate.id
|
|
));
|
|
expect(hot).toBeDefined();
|
|
|
|
const partyCooldown = () => usePartyStore.getState().members
|
|
.find((candidate) => candidate.id === member.id)!.cooldowns[heartRuneEnergy.id];
|
|
expect(partyCooldown()).toBe(33_333);
|
|
useCombatStore.getState().tick(0, 2_999);
|
|
expect(partyCooldown()).toBe(33_333);
|
|
|
|
// The actor-owned proc rolls below the established local 8% boundary at this first tick.
|
|
expect(stableCombatUnit(
|
|
`${protectionAura!.instanceId}:rom-priest-protection-rune-seal-reset:periodic:${regenerate.id}:${member.id}:3000`,
|
|
)).toBeLessThan(0.08);
|
|
useCombatStore.getState().tick(0, 3_000);
|
|
|
|
expect(partyCooldown()).toBe(0);
|
|
expect(useCombatStore.getState().cooldowns[heartRuneEnergy.id]).toBe(22_222);
|
|
});
|
|
});
|