import type { ClassId } from "../app/characterCatalog"; import type { AbilityDefinition, AbilityEffect } from "./abilityCatalog"; import type { ActiveAura, AuraDefinition } from "./combatAuras"; export const ROM_MAGE_WARRIOR_MEDITATION_PATH_PASSIVE_SPELL_ID = 499588; export const ROM_MAGE_WARRIOR_MEDITATION_PATH_TRIGGER_SPELL_IDS = new Set([490204, 490212, 490242, 490239]); export const ROM_MAGE_WARRIOR_MEDITATION_PATH_ACTIVE_TAG = "rom-mage-warrior-meditation-path-active"; export const ROM_MAGE_WARRIOR_MEDITATION_PATH_LOCKOUT_TAG = "rom-mage-warrior-meditation-path-lockout"; const MEDITATION_PATH_ACTIVE_AURA: AuraDefinition = { id: "rom:499588:mobile-casting", name: "Meditation Path", disposition: "buff", durationMs: 7_000, maxStacks: 1, stackBehavior: "refresh", utilityTags: [ROM_MAGE_WARRIOR_MEDITATION_PATH_ACTIVE_TAG], }; const MEDITATION_PATH_LOCKOUT_AURA: AuraDefinition = { id: "rom:499588:retrigger-lockout", name: "Meditation Path lockout", disposition: "buff", durationMs: 15_000, maxStacks: 1, stackBehavior: "refresh", utilityTags: [ROM_MAGE_WARRIOR_MEDITATION_PATH_LOCKOUT_TAG], }; function auraEffect(aura: AuraDefinition): Extract { return { kind: "apply-aura", recipient: "caster", aura, sourceEffectType: -1, sourceAuraType: -1, miscValue: 0, triggerSpellId: ROM_MAGE_WARRIOR_MEDITATION_PATH_PASSIVE_SPELL_ID, }; } export const ROM_MAGE_WARRIOR_MEDITATION_PATH_ACTIVE_EFFECT = auraEffect(MEDITATION_PATH_ACTIVE_AURA); export const ROM_MAGE_WARRIOR_MEDITATION_PATH_LOCKOUT_EFFECT = auraEffect(MEDITATION_PATH_LOCKOUT_AURA); export function romMageWarriorMeditationPathCanProc( classId: ClassId, secondaryClassId: ClassId | null | undefined, hasPassive: boolean, ability: AbilityDefinition, ): boolean { return classId === "rom-mage" && secondaryClassId === "rom-warrior" && hasPassive && ability.source === "runewaker" && ROM_MAGE_WARRIOR_MEDITATION_PATH_TRIGGER_SPELL_IDS.has(ability.dbcSpellId); } export function romMageWarriorMeditationPathHasState( auras: readonly ActiveAura[], actorId: string, tag: string, now: number, ): boolean { return auras.some((aura) => aura.targetId === actorId && (aura.expiresAt === null || aura.expiresAt > now) && aura.definition.utilityTags?.includes(tag)); } export function romMageWarriorMeditationPathAllowsMovement( classId: ClassId, secondaryClassId: ClassId | null | undefined, hasPassive: boolean, auras: readonly ActiveAura[], actorId: string, now: number, ): boolean { return classId === "rom-mage" && secondaryClassId === "rom-warrior" && hasPassive && romMageWarriorMeditationPathHasState( auras, actorId, ROM_MAGE_WARRIOR_MEDITATION_PATH_ACTIVE_TAG, now, ); }