import { beforeEach, describe, expect, it } from "vitest"; import { PLAYER_AGGRO_ID } from "./aggro"; import { ROM_ALL_ABILITIES } from "./romAbilityCatalog"; import { useCombatStore } from "./combatStore"; import { clearMobRuntimeRegistry } from "./mobRuntimeRegistry"; import { createConfiguredPartyMember, usePartyStore } from "./partyStore"; import { clearPartyRuntimeRegistry, registerPartyRuntimePosition, updatePartyRuntimePosition } from "./partyRuntimeRegistry"; import { isRomMageDruidPair, ROM_MAGE_DRUID_GREEN_GUARDIAN_AURA_TAG, ROM_MAGE_DRUID_GREEN_GUARDIAN_SKILL_ID, romMageDruidGreenGuardianMovementSpeedMultiplier, } from "./romMageDruidGreenGuardianRuntime"; const skill = ROM_ALL_ABILITIES.find((ability) => ability.dbcSpellId === ROM_MAGE_DRUID_GREEN_GUARDIAN_SKILL_ID && ability.classId === "rom-mage" && ability.secondaryClassId === "rom-druid"); function guardianAura(targetId: string) { return useCombatStore.getState().auras.find((aura) => aura.targetId === targetId && aura.definition.utilityTags?.includes(ROM_MAGE_DRUID_GREEN_GUARDIAN_AURA_TAG)); } describe("CoA Mage/Druid Green Guardian runtime", () => { beforeEach(() => { clearMobRuntimeRegistry(); clearPartyRuntimeRegistry(); useCombatStore.getState().initializeCharacter({ classId: "rom-mage", secondaryClassId: "rom-druid", raceId: "rom-elf", level: 45, role: "damage", }); usePartyStore.getState().initializeParty( "green-guardian-test", 45, useCombatStore.getState().health, "damage", 2, "rom", ); }); it("casts as a self skill, accrues only after standing, pauses after movement, and speeds player movement", () => { if (!skill) throw new Error("Missing generated Mage/Druid Green Guardian row"); expect(isRomMageDruidPair(useCombatStore.getState())).toBe(true); expect(useCombatStore.getState().castAbility(skill.id, undefined, 1_000)).toMatchObject({ ok: true }); expect(guardianAura(PLAYER_AGGRO_ID)?.stacks).toBe(0); useCombatStore.getState().tick(0.5, 1_500); useCombatStore.getState().tick(0.5, 2_000); useCombatStore.getState().tick(0.5, 2_500); expect(guardianAura(PLAYER_AGGRO_ID)?.stacks).toBe(1); expect(romMageDruidGreenGuardianMovementSpeedMultiplier( useCombatStore.getState().auras, PLAYER_AGGRO_ID, 2_500, )).toBe(1.01); useCombatStore.getState().setPlayerPosition([1, 0, 0]); useCombatStore.getState().tick(0.25, 2_750); expect(guardianAura(PLAYER_AGGRO_ID)?.stacks).toBe(1); useCombatStore.getState().tick(0.5, 3_250); expect(guardianAura(PLAYER_AGGRO_ID)?.stacks).toBe(1); useCombatStore.getState().tick(0.5, 3_750); expect(guardianAura(PLAYER_AGGRO_ID)?.stacks).toBe(2); }); it("starts a generated Mage/Druid companion at zero and accrues against its runtime position", () => { if (!skill) throw new Error("Missing generated Mage/Druid Green Guardian row"); const seed = "green-guardian-companion-test"; const companion = createConfiguredPartyMember({ name: "Green Guardian Mage", classId: "rom-mage", secondaryClassId: "rom-druid", specialization: "Primary", role: "damage", }, 45, 0, seed); usePartyStore.getState().initializeParty(seed, 45, useCombatStore.getState().health, "damage", 2, "rom"); usePartyStore.setState({ members: [companion] }); registerPartyRuntimePosition(companion.id, [0, 0, 0]); useCombatStore.getState().synchronizeActors(); const effect = skill.effects.find((candidate) => candidate.kind === "apply-aura"); if (!effect || effect.kind !== "apply-aura") throw new Error("Green Guardian has no self aura effect"); expect(useCombatStore.getState().applyActorAura(companion.id, companion.id, skill, effect, 1_000)).toBe(true); expect(guardianAura(companion.id)?.stacks).toBe(0); useCombatStore.getState().tick(0.5, 1_500); useCombatStore.getState().tick(0.5, 2_000); useCombatStore.getState().tick(0.5, 2_500); expect(guardianAura(companion.id)?.stacks).toBe(1); expect(romMageDruidGreenGuardianMovementSpeedMultiplier( useCombatStore.getState().auras, companion.id, 2_500, )).toBe(1.01); updatePartyRuntimePosition(companion.id, 1, 0, 0); useCombatStore.getState().tick(0.25, 2_750); expect(guardianAura(companion.id)?.stacks).toBe(1); useCombatStore.getState().tick(1, 3_750); expect(guardianAura(companion.id)?.stacks).toBe(2); }); it("does not grant movement speed to the reverse Druid/Mage pair", () => { useCombatStore.getState().initializeCharacter({ classId: "rom-druid", secondaryClassId: "rom-mage", raceId: "rom-elf", level: 45, role: "damage", }); expect(isRomMageDruidPair(useCombatStore.getState())).toBe(false); expect(romMageDruidGreenGuardianMovementSpeedMultiplier([], PLAYER_AGGRO_ID, 2_500)).toBe(1); }); });