Files
healer-man/src/game/romRogueCurrentCoaHands.integration.test.ts
2026-10-02 10:38:12 -04:00

108 lines
5.5 KiB
TypeScript

import { beforeEach, describe, expect, it } from "vitest";
import { PLAYER_AGGRO_ID } from "./aggro";
import { abilityById } from "./abilityCatalog";
import { useCombatStore } from "./combatStore";
import {
advanceDungeonPartyCombat,
resetPartyRuntimeClock,
} from "./partyRuntime";
import { registerPartyRuntimePosition, clearPartyRuntimeRegistry } from "./partyRuntimeRegistry";
import { createConfiguredPartyMember, usePartyStore } from "./partyStore";
import { partyAbilityCosts } from "./partyAbilityAi";
import {
ROM_ROGUE_ENERGIZED_HANDS_AURA_TAG,
ROM_ROGUE_ENERGIZED_HANDS_COOLDOWN_REDUCTION_MS,
ROM_ROGUE_ENERGIZED_HANDS_SKILL_ID,
ROM_ROGUE_POISONOUS_HANDS_EXCLUSIVE_GROUP,
} from "./romRogueEnergizedHandsRuntime";
import { ROM_ROGUE_POISON_AURA_TAG, ROM_ROGUE_POISON_SKILL_ID } from "./romRoguePoisonRuntime";
describe("RoM Rogue current CoA Hands skills", () => {
beforeEach(() => {
clearPartyRuntimeRegistry();
resetPartyRuntimeClock();
useCombatStore.getState().initializeCharacter({ classId: "rom-rogue", raceId: "rom-human", level: 50, xp: 0 });
useCombatStore.setState({ playerPosition: [0, 0, 0] });
});
it("replaces the local 490347 Numbing Dagger row with Energized Hands and applies its player mechanics", () => {
const energized = abilityById("rom-rogue-primary-5")!;
const poisoned = abilityById("rom-rogue-primary-6")!;
expect(energized).toMatchObject({
dbcSpellId: ROM_ROGUE_ENERGIZED_HANDS_SKILL_ID,
name: "Energized Hands",
target: "self",
castTimeMs: 1_000,
cooldownMs: 0,
});
expect(energized.description).toContain("maximum Energy by 50%");
expect(poisoned).toMatchObject({ dbcSpellId: ROM_ROGUE_POISON_SKILL_ID, name: "Poisonous Hands", target: "self" });
const poisonAura = poisoned.effects.find((effect) => effect.kind === "apply-aura");
expect(poisonAura?.kind === "apply-aura" && poisonAura.aura.exclusiveGroup)
.toBe(ROM_ROGUE_POISONOUS_HANDS_EXCLUSIVE_GROUP);
expect(energized.description).toContain("0.1 seconds");
expect(useCombatStore.getState().castAbility(energized.id, undefined, 1_000).ok).toBe(true);
useCombatStore.getState().tick(1.1, 2_100);
expect(useCombatStore.getState().maxResourcePools.energy).toBe(150);
expect(useCombatStore.getState().auras.some((aura) => aura.targetId === PLAYER_AGGRO_ID
&& aura.definition.utilityTags?.includes(ROM_ROGUE_ENERGIZED_HANDS_AURA_TAG))).toBe(true);
expect(useCombatStore.getState().castAbility("rom-rogue-primary-14", undefined, 3_600).ok).toBe(true);
expect(useCombatStore.getState().cooldowns["rom-rogue-primary-14"])
.toBe(3_600 + 120_000 - ROM_ROGUE_ENERGIZED_HANDS_COOLDOWN_REDUCTION_MS);
});
it("replaces Energized Hands with Poisonous Hands and restores the base Energy maximum", () => {
expect(useCombatStore.getState().castAbility("rom-rogue-primary-5", undefined, 1_000).ok).toBe(true);
useCombatStore.getState().tick(1.1, 2_100);
expect(useCombatStore.getState().maxResourcePools.energy).toBe(150);
expect(useCombatStore.getState().castAbility("rom-rogue-primary-6", undefined, 3_600).ok).toBe(true);
useCombatStore.getState().tick(1.1, 4_700);
const auras = useCombatStore.getState().auras.filter((aura) => aura.targetId === PLAYER_AGGRO_ID
&& aura.definition.exclusiveGroup === ROM_ROGUE_POISONOUS_HANDS_EXCLUSIVE_GROUP);
expect(auras).toHaveLength(1);
expect(auras[0]?.definition.utilityTags).toContain(ROM_ROGUE_POISON_AURA_TAG);
expect(useCombatStore.getState().maxResourcePools.energy).toBe(100);
});
it("applies Energized Hands Energy capacity, cost, and regeneration to a generated companion", () => {
const member = createConfiguredPartyMember({
name: "Rogue companion",
classId: "rom-rogue",
specialization: "Primary",
role: "damage",
}, 50, 0, "rogue-energized-hands");
const energized = abilityById("rom-rogue-primary-5")!;
const effect = energized.effects.find((candidate) => candidate.kind === "apply-aura");
if (effect?.kind !== "apply-aura") throw new Error("Missing Energized Hands aura effect.");
usePartyStore.getState().initializeParty("rogue-energized-hands", 50, 1_000, "damage", 1, "rom");
usePartyStore.setState({ command: "stop", members: [{ ...member, nextActionAt: 100_000 }] });
registerPartyRuntimePosition(member.id, [0, 0, 0]);
useCombatStore.getState().synchronizeActors();
expect(useCombatStore.getState().applyActorAura(member.id, member.id, energized, effect, 1_000)).toBe(true);
let current = usePartyStore.getState().members[0]!;
expect(current.maxResource).toBe(150);
expect(useCombatStore.getState().actors[member.id]?.resources.energy?.maximum).toBe(150);
const costProbe = {
...abilityById("rom-rogue-primary-14")!,
cost: { resource: "energy" as const, amount: 25 },
costs: [{ resource: "energy" as const, amount: 25 }],
};
expect(partyAbilityCosts(current, costProbe, 1_000)).toEqual([{ resource: "energy", amount: 30 }]);
const reduced = { ...current, resource: 50, resourcePools: { ...current.resourcePools, energy: 50 } };
usePartyStore.setState({ members: [reduced] });
useCombatStore.getState().commitCompanionActors([reduced]);
resetPartyRuntimeClock();
advanceDungeonPartyCombat(2_000);
advanceDungeonPartyCombat(3_000);
current = usePartyStore.getState().members[0]!;
expect(current.resource).toBe(70);
expect(useCombatStore.getState().actors[member.id]?.resources.energy?.maximum).toBe(150);
});
});