import { beforeEach, describe, expect, it } from "vitest"; import { abilityById } from "./abilityCatalog"; import { PLAYER_AGGRO_ID } from "./aggro"; import { useCombatStore } from "./combatStore"; import { clearMobRuntimeRegistry } from "./mobRuntimeRegistry"; import { advanceDungeonPartyCombat, resetPartyRuntimeClock } from "./partyRuntime"; import { clearPartyRuntimeRegistry, registerPartyRuntimePosition, } from "./partyRuntimeRegistry"; import { createConfiguredPartyMember, usePartyStore } from "./partyStore"; import { ROM_PRIEST_CHAMPION_BEACON_OF_REGENERATION_ID } from "./romPriestChampionBeaconRuntime"; const beacon = abilityById(ROM_PRIEST_CHAMPION_BEACON_OF_REGENERATION_ID)!; const heal = abilityById("rom-priest-primary-2")!; const beaconTag = "rom-priest-champion-beacon-of-regeneration"; function setPlayerMana(amount: number): void { useCombatStore.setState((state) => ({ resource: amount, maxResource: amount, maxResourcePools: { ...state.maxResourcePools, mana: amount }, resourcePools: { ...state.resourcePools, mana: amount }, })); } function activeCast(abilityId: string, targetId: string, startedAt: number, completesAt: number) { return { abilityId, school: "holy" as const, mode: "cast" as const, startedAt, completesAt, originalDurationMs: Math.max(0, completesAt - startedAt), pushbackHits: 0, origin: [0, 0, 0] as const, targetId, }; } describe("RoM Priest/Champion Beacon of Regeneration integration", () => { beforeEach(() => { clearMobRuntimeRegistry(); clearPartyRuntimeRegistry(); resetPartyRuntimeClock(); useCombatStore.getState().initializeCharacter({ classId: "rom-priest", secondaryClassId: "rom-champion", raceId: "rom-dwarf", level: 80, role: "healer", }); usePartyStore.getState().initializeParty( "rom-priest-champion-beacon", 80, useCombatStore.getState().health, "healer", 2, "rom", ); usePartyStore.getState().setCommand("stop"); setPlayerMana(10_000); }); it("applies a player's Beacon with the caster's healing-done modifiers", () => { const seed = "rom-priest-champion-beacon-player-target"; const marked = createConfiguredPartyMember({ name: "Marked ally", classId: "rom-warrior", raceId: "rom-human", specialization: "Primary", role: "tank", }, 80, 0, seed); const healTarget = createConfiguredPartyMember({ name: "Heal target", classId: "rom-warrior", raceId: "rom-human", specialization: "Primary", role: "tank", }, 80, 1, seed); usePartyStore.setState({ members: [{ ...marked, health: 1 }, { ...healTarget, health: 1 }] }); registerPartyRuntimePosition(marked.id, [1, 0, 0]); registerPartyRuntimePosition(healTarget.id, [2, 0, 0]); useCombatStore.getState().synchronizeActors(); expect(useCombatStore.getState().castAbility(beacon.id, { targetActorId: marked.id, now: 1_000, })).toMatchObject({ ok: true }); expect(useCombatStore.getState().auras).toEqual(expect.arrayContaining([ expect.objectContaining({ sourceId: PLAYER_AGGRO_ID, targetId: marked.id, expiresAt: 31_000, definition: expect.objectContaining({ utilityTags: [beaconTag] }), }), ])); expect(useCombatStore.getState().castAbility(heal.id, { targetActorId: healTarget.id, now: 3_000, })).toMatchObject({ ok: true }); useCombatStore.getState().tick(3, 5_000); const event = useCombatStore.getState().combatEvents.find((candidate) => ( candidate.kind === "healing" && candidate.abilityId === beacon.id )); const faith = useCombatStore.getState().auras.find((aura) => ( aura.sourceId === PLAYER_AGGRO_ID && aura.definition.name === "Faith: healing-power-percent" )); expect(faith?.definition.modifiers).toContainEqual({ kind: "healing", direction: "done", operation: "percent", value: 0.05, }); expect(event).toMatchObject({ sourceActorId: PLAYER_AGGRO_ID, targetActorId: marked.id, rawAmount: 809, effectiveAmount: 809, overheal: 0, critical: false, }); expect(usePartyStore.getState().members.find((member) => member.id === marked.id)?.health).toBe(810); }); it("applies a generated companion's Beacon and resolves its direct-heal trigger", () => { const seed = "rom-priest-champion-beacon-companion"; const caster = createConfiguredPartyMember({ name: "Priest/Champion", classId: "rom-priest", secondaryClassId: "rom-champion", raceId: "rom-dwarf", specialization: "Priest/Champion", role: "healer", }, 80, 0, seed); const marked = createConfiguredPartyMember({ name: "Marked companion ally", classId: "rom-warrior", raceId: "rom-human", specialization: "Primary", role: "tank", }, 80, 1, seed); const healTarget = createConfiguredPartyMember({ name: "Heal target companion", classId: "rom-warrior", raceId: "rom-human", specialization: "Primary", role: "tank", }, 80, 2, seed); usePartyStore.setState({ members: [ { ...caster, resource: 10_000, maxResource: 10_000, resourcePools: { ...caster.resourcePools, mana: 10_000 }, activeCast: activeCast(beacon.id, marked.id, 1_000, 1_000), activeCastTargetId: marked.id, status: "attacking" }, { ...marked, health: 1 }, { ...healTarget, health: 1 }, ] }); registerPartyRuntimePosition(caster.id, [0, 0, 0]); registerPartyRuntimePosition(marked.id, [1, 0, 0]); registerPartyRuntimePosition(healTarget.id, [2, 0, 0]); useCombatStore.getState().synchronizeActors(); advanceDungeonPartyCombat(1_000); expect(useCombatStore.getState().auras).toEqual(expect.arrayContaining([ expect.objectContaining({ sourceId: caster.id, targetId: marked.id, definition: expect.objectContaining({ utilityTags: [beaconTag] }) }), ])); usePartyStore.setState((state) => ({ members: state.members.map((member) => member.id === caster.id ? { ...member, activeCast: activeCast(heal.id, healTarget.id, 1_000, 3_000), activeCastTargetId: healTarget.id, status: "attacking", } : member), })); useCombatStore.getState().synchronizeActors(); advanceDungeonPartyCombat(3_000); const faith = useCombatStore.getState().auras.find((aura) => ( aura.sourceId === caster.id && aura.definition.name === "Faith: healing-power-percent" )); expect(faith?.definition.modifiers).toContainEqual({ kind: "healing", direction: "done", operation: "percent", value: 0.05, }); const event = useCombatStore.getState().combatEvents.find((candidate) => ( candidate.kind === "healing" && candidate.sourceActorId === caster.id && candidate.abilityId === beacon.id )); expect(event).toMatchObject({ targetActorId: marked.id, // Beacon contributes 770; the companion's ordinary Faith aura applies its +5% healing bonus. rawAmount: 809, effectiveAmount: 809, overheal: 0, critical: false, }); expect(usePartyStore.getState().members.find((member) => member.id === marked.id)?.health).toBe(810); }); });