import type { ActiveAura, AuraDefinition, AuraModifier } from "./combatAuras"; import type { AbilityEffect } from "./abilityCatalog"; export const ROM_ROGUE_ENERGIZED_HANDS_SKILL_ID = 490347; export const ROM_ROGUE_ENERGIZED_HANDS_AURA_TAG = "rom-energized-hands"; export const ROM_ROGUE_POISONOUS_HANDS_EXCLUSIVE_GROUP = "rom-rogue-hands"; export const ROM_ROGUE_ENERGIZED_HANDS_DURATION_MS = 900_000; export const ROM_ROGUE_ENERGIZED_HANDS_COOLDOWN_REDUCTION_MS = 100; export const ROM_ROGUE_ENERGIZED_HANDS_MAX_ENERGY_PERCENT = 50; export const ROM_ROGUE_ENERGIZED_HANDS_REGENERATION_PERCENT = 100; export const ROM_ROGUE_ENERGIZED_HANDS_COST_PERCENT = 20; export const ROM_ROGUE_ENERGIZED_HANDS_DESCRIPTION = "Increases Energy recovery by 100%, reduces skill cooldowns by 0.1 seconds, and increases maximum Energy by 50%, but increases Energy costs by 20% for 900 seconds. Mutually exclusive with Poisonous Hands."; export const ROM_ROGUE_POISONOUS_HANDS_DESCRIPTION = "Uses 1 Poison Bottle. For 900 seconds, regular attacks have a 50% chance to apply Poisonous Hands to the target, reducing damage dealt by the target by 8%. Each successful application stacks up to 10 times and grants you 1% Physical Attack Speed per stack applied to your current target. Attacking a new target resets this attack-speed sequence. Mutually exclusive with Energized Hands."; export function romRogueEnergizedHandsAuraDefinition(): AuraDefinition { const modifiers: readonly AuraModifier[] = [ { kind: "resource", resource: "energy", property: "maximum", operation: "percent", value: ROM_ROGUE_ENERGIZED_HANDS_MAX_ENERGY_PERCENT / 100, }, { kind: "resource", resource: "energy", property: "regeneration", operation: "percent", value: ROM_ROGUE_ENERGIZED_HANDS_REGENERATION_PERCENT / 100, }, { kind: "resource", resource: "energy", property: "cost", operation: "percent", value: ROM_ROGUE_ENERGIZED_HANDS_COST_PERCENT / 100, }, ]; return { id: "rom-rogue-energized-hands", name: "Energized Hands", description: ROM_ROGUE_ENERGIZED_HANDS_DESCRIPTION, disposition: "buff", durationMs: ROM_ROGUE_ENERGIZED_HANDS_DURATION_MS, exclusiveGroup: ROM_ROGUE_POISONOUS_HANDS_EXCLUSIVE_GROUP, utilityTags: [ROM_ROGUE_ENERGIZED_HANDS_AURA_TAG], modifiers, }; } export function romRogueEnergizedHandsApplyEffect(): AbilityEffect { return { kind: "apply-aura", recipient: "caster", sourceEffectType: 6, sourceAuraType: 0, miscValue: 0, triggerSpellId: 0, aura: romRogueEnergizedHandsAuraDefinition(), }; } export function romRogueEnergizedHandsActive( auras: readonly ActiveAura[], actorId: string, now?: number, ): boolean { return auras.some((aura) => aura.targetId === actorId && aura.definition.utilityTags?.includes(ROM_ROGUE_ENERGIZED_HANDS_AURA_TAG) && (now === undefined || aura.expiresAt === null || aura.expiresAt > now)); } /** * Translate the current max-Energy aura between snapshots without changing * current Energy. The stored pool maximum is the runtime authority, so apply * only the ratio of the old and new aura modifiers (refreshes remain neutral). */ export function romRogueEnergyMaximumAfterAuraTransition( currentMaximum: number, previousAuras: readonly ActiveAura[], nextAuras: readonly ActiveAura[], targetId: string, ): number { const maximumModifier = (auras: readonly ActiveAura[]) => auras .filter((aura) => aura.targetId === targetId) .reduce((total, aura) => { const hasEnergizedHands = aura.definition.utilityTags?.includes(ROM_ROGUE_ENERGIZED_HANDS_AURA_TAG); if (!hasEnergizedHands) return total; const percent = (aura.definition.modifiers ?? []).reduce((value, modifier) => ( modifier.kind === "resource" && modifier.resource === "energy" && modifier.property === "maximum" ? value + (modifier.operation === "percent" ? modifier.value : 0) : value ), 0); return total * (1 + percent); }, 1); const previous = maximumModifier(previousAuras); const next = maximumModifier(nextAuras); return Math.max(0, Math.round(currentMaximum * next / Math.max(0.0001, previous))); }