import type { AbilityEffect } from "./abilityCatalog"; import { resolveDamageValue, resolveStatValue, type ActiveAura, type DamageSchool } from "./combatAuras"; import type { RomGeneratedAbilityLike } from "./romAbilitySemantics"; export const ROM_PRIEST_HOLY_BLESSING = Object.freeze({ spellId: 490_274, wisdomFlat: 115, wisdomPercent: 10.5, lightDamagePercent: 100.9, }); export const ROM_PRIEST_HOLY_BLESSING_TAG = "rom-priest:490274:holy-blessing"; /** Resolve CoA's `(current Wisdom + 115) × 10.5% + 115` stat stage. */ export function romPriestHolyBlessingWisdom(currentWisdom: number): number { const wisdom = Number.isFinite(currentWisdom) ? Math.max(0, currentWisdom) : 0; return (wisdom + ROM_PRIEST_HOLY_BLESSING.wisdomFlat) * (1 + ROM_PRIEST_HOLY_BLESSING.wisdomPercent / 100); } export interface RomPriestHolyBlessingStats { readonly intellect: number; readonly currentWisdom: number; readonly wisdom: number; readonly spellPowerBonus: number; readonly active: boolean; } /** * Resolve existing primary-stat modifiers first, then apply Holy Blessing to * that current Wisdom. Its spell-power bonus is only the incremental Spirit * conversion; generic spell-power aura modifiers remain on their normal path. */ export function romPriestHolyBlessingStats( base: { readonly intellect: number; readonly spirit: number }, auras: readonly ActiveAura[], ): RomPriestHolyBlessingStats { const active = auras.some((aura) => aura.definition.utilityTags?.includes(ROM_PRIEST_HOLY_BLESSING_TAG)); const existingAuras = active ? auras.filter((aura) => !aura.definition.utilityTags?.includes(ROM_PRIEST_HOLY_BLESSING_TAG)) : auras; const primary = (value: number, ...names: string[]) => names.reduce( (current, stat) => resolveStatValue(current, existingAuras, stat), value, ); const intellect = primary(base.intellect, "intellect", "all-primary", "all-primary-attributes"); const currentWisdom = primary(base.spirit, "spirit", "wisdom", "all-primary", "all-primary-attributes"); const wisdom = active ? romPriestHolyBlessingWisdom(currentWisdom) : currentWisdom; const spellPowerBonus = active ? Math.round(intellect * 0.35 + wisdom * 0.15) - Math.round(intellect * 0.35 + currentWisdom * 0.15) : 0; return { intellect, currentWisdom, wisdom, spellPowerBonus, active }; } /** Apply Holy Blessing's source-only Light/Holy damage modifier without widening its school scope. */ export function romPriestHolyBlessingDamage( amount: number, auras: readonly ActiveAura[], school: DamageSchool, ): number { const blessingAuras = auras.filter((aura) => aura.definition.utilityTags?.includes(ROM_PRIEST_HOLY_BLESSING_TAG)); return resolveDamageValue(amount, blessingAuras, { direction: "dealt", school, attackKind: "spell" }); } export const ROM_PRIEST_HOLY_BLESSING_PASSIVE_EFFECT: Extract = { kind: "apply-aura", recipient: "caster", aura: { id: ROM_PRIEST_HOLY_BLESSING_TAG, name: "Holy Blessing", description: "Increases Wisdom by (current Wisdom + 115) × 10.5% + 115 and Light Damage by 100.9%.", disposition: "buff", durationMs: null, maxStacks: 1, stackBehavior: "refresh", utilityTags: [ROM_PRIEST_HOLY_BLESSING_TAG], modifiers: [ { kind: "stat", stat: "wisdom", operation: "flat", value: ROM_PRIEST_HOLY_BLESSING.wisdomFlat, }, { kind: "stat", stat: "wisdom", operation: "percent", value: ROM_PRIEST_HOLY_BLESSING.wisdomPercent / 100, }, { kind: "damage", direction: "dealt", school: "holy", operation: "percent", value: ROM_PRIEST_HOLY_BLESSING.lightDamagePercent / 100, }, ], }, sourceEffectType: -1, sourceAuraType: -1, miscValue: ROM_PRIEST_HOLY_BLESSING.wisdomPercent, triggerSpellId: ROM_PRIEST_HOLY_BLESSING.spellId, }; /** Holy Blessing belongs only to the Priest primary skill set. */ export function romPriestHolyBlessingEffects( row: RomGeneratedAbilityLike, ): readonly AbilityEffect[] | null { if (row.classId !== "rom-priest" || row.secondaryClassId !== undefined || row.sourceSkillId !== ROM_PRIEST_HOLY_BLESSING.spellId) return null; return [ROM_PRIEST_HOLY_BLESSING_PASSIVE_EFFECT]; }