import type { AbilityDefinition } from "./abilityCatalog"; /** CoA tree node 5744 / source spell 804414: Decapitate is usable below 35% health. */ export const COA_BARBARIAN_DECAPITATE_TALENT_ENTRY_ID = 5744; export const COA_BARBARIAN_DECAPITATE_HEALTH_THRESHOLD = 0.35; /** Source node 6744 / spell 705222 refunds maximum Energy on a Decapitate kill. */ export const COA_BARBARIAN_BEHEADER_TALENT_ENTRY_ID = 6744; type CoaBarbarianDecapitateIdentity = Pick; export interface CoaBarbarianExecuteTargetHealth { readonly health?: number; readonly maxHealth?: number; readonly dead?: boolean; } export function isCoaBarbarianDecapitate( ability: CoaBarbarianDecapitateIdentity | null | undefined, ): boolean { return ability?.classId === "barbarian" && ability.talentEntryId === COA_BARBARIAN_DECAPITATE_TALENT_ENTRY_ID; } /** Other actions pass through; Decapitate requires a living, valid target strictly below 35%. */ export function coaBarbarianDecapitateTargetAllowed( ability: CoaBarbarianDecapitateIdentity | null | undefined, target: CoaBarbarianExecuteTargetHealth | null | undefined, ): boolean { if (!isCoaBarbarianDecapitate(ability)) return true; if (!target || target.dead === true || !Number.isFinite(target.health) || !Number.isFinite(target.maxHealth) || target.health! <= 0 || target.maxHealth! <= 0) return false; return target.health! / target.maxHealth! < COA_BARBARIAN_DECAPITATE_HEALTH_THRESHOLD; } export function coaBarbarianBeheaderEnergyRefund( ability: CoaBarbarianDecapitateIdentity, talentRanks: Readonly>, maximumEnergy: number, result: { readonly amount: number; readonly killed: boolean }, ): number { if (!isCoaBarbarianDecapitate(ability) || !(talentRanks[`coa-entry-${COA_BARBARIAN_BEHEADER_TALENT_ENTRY_ID}`] > 0) || !result.killed || !(result.amount > 0) || !Number.isFinite(maximumEnergy) || maximumEnergy <= 0) return 0; return maximumEnergy; }