import { beforeEach, describe, expect, it } from "vitest"; import { EMPTY_ITEM_STATS } from "./itemStats"; import { clearMobRuntimeRegistry, setMobPosition } from "./mobRuntimeRegistry"; import { clearPartyRuntimeRegistry, registerPartyRuntimePosition, updatePartyRuntimeTargetVisibility, } from "./partyRuntimeRegistry"; import { advanceDungeonPartyCombat, resetPartyRuntimeClock } from "./partyRuntime"; import { createConfiguredPartyMember, usePartyStore } from "./partyStore"; import { PLAYER_AURA_ENTITY_ID, useCombatStore } from "./combatStore"; import { abilitiesForCharacter } from "./abilityCatalog"; const FEARLESS_ABILITY_ID = "rom-knight-rom-warrior-elite-35"; describe("RoM Knight/Warrior Fearless", () => { beforeEach(() => { clearMobRuntimeRegistry(); clearPartyRuntimeRegistry(); resetPartyRuntimeClock(); useCombatStore.getState().initializeCharacter({ classId: "warrior", level: 40 }); usePartyStore.getState().initializeParty("rom-knight-fearless", 40, useCombatStore.getState().health, "damage", 2, "rom"); }); it("gives the player source-defined stats and 20 seconds of Fear immunity", () => { useCombatStore.getState().initializeCharacter({ classId: "rom-knight", secondaryClassId: "rom-warrior", raceId: "rom-human", level: 40, role: "tank", }); useCombatStore.setState((state) => ({ resourcePools: { ...state.resourcePools, rage: 100 }, })); const cast = useCombatStore.getState().castAbility(FEARLESS_ABILITY_ID, undefined, 1_000); expect(cast).toMatchObject({ ok: true }); const auras = useCombatStore.getState().auras.filter((active) => ( active.targetId === PLAYER_AURA_ENTITY_ID && active.definition.name.startsWith("Fearless:") )); expect(auras).toHaveLength(2); expect(auras.every((aura) => aura.definition.controlImmunities?.includes("fear"))).toBe(true); expect(auras.flatMap((aura) => aura.definition.modifiers ?? [])).toEqual(expect.arrayContaining([ { kind: "stat", stat: "strength", operation: "percent", value: 0.03 }, { kind: "stat", stat: "stamina", operation: "percent", value: 0.03 }, ])); expect(auras.every((aura) => aura.expiresAt === 21_000)).toBe(true); }); it("gives a generated Knight/Warrior companion the same Fear immunity", () => { const seed = "rom-knight-fearless-companion"; const knight = createConfiguredPartyMember({ name: "Fearless Knight", classId: "rom-knight", secondaryClassId: "rom-warrior", raceId: "rom-human", specialization: "Knight/Warrior", role: "tank", }, 40, 0, seed); const targetId = "rom-knight-fearless-target"; const activeCooldowns = Object.fromEntries( abilitiesForCharacter("rom-knight", "rom-warrior") .filter((ability) => !ability.passive && ability.id !== FEARLESS_ABILITY_ID) .map((ability) => [ability.id, 60_000]), ); usePartyStore.getState().initializeParty( seed, 40, useCombatStore.getState().health, "tank", 2, "rom", ); usePartyStore.setState({ members: [{ ...knight, gearStats: EMPTY_ITEM_STATS, resourcePools: { ...knight.resourcePools, rage: 50 }, cooldowns: activeCooldowns, globalCooldownEndsAt: 0, nextActionAt: 0, status: "ready", }], command: "attack", activeMobId: targetId, }); registerPartyRuntimePosition(knight.id, [0, 0, 0]); useCombatStore.getState().synchronizeActors(); useCombatStore.getState().registerMob(targetId, { name: "Fearless target", maxHealth: 100_000, xpReward: 0 }); setMobPosition(targetId, [2, 0, 0]); useCombatStore.getState().damageMob(targetId, 1, 100); updatePartyRuntimeTargetVisibility(knight.id, targetId, true); advanceDungeonPartyCombat(1_000); const auras = useCombatStore.getState().auras.filter((active) => ( active.sourceId === knight.id && active.targetId === knight.id && active.definition.name.startsWith("Fearless:") )); expect(auras).toHaveLength(2); expect(auras.every((aura) => aura.definition.controlImmunities?.includes("fear"))).toBe(true); expect(auras.every((aura) => aura.expiresAt === 21_000)).toBe(true); }); });