77 lines
2.5 KiB
TypeScript
77 lines
2.5 KiB
TypeScript
import type { ActiveAura } from "./combatAuras";
|
|
import type { EnemyAuraSourceProfile, EnemySourceAuraContract } from "./enemySourceAuras";
|
|
|
|
const BLOODLUST_EFFECT = Object.freeze({
|
|
effectType: 6,
|
|
auraType: 138,
|
|
basePoints: 30,
|
|
mechanic: 0,
|
|
implicitTargetA: 21,
|
|
implicitTargetB: 0,
|
|
radius: 0,
|
|
miscValue: 0,
|
|
periodMs: 0,
|
|
});
|
|
|
|
const bloodlustContract = (profile: EnemyAuraSourceProfile): EnemySourceAuraContract => Object.freeze({
|
|
spellId: 6742,
|
|
name: "Bloodlust",
|
|
profile,
|
|
signature: Object.freeze({
|
|
rangeIndex: 4,
|
|
schoolMask: 8,
|
|
damageClass: 1,
|
|
durationMs: 30_000,
|
|
effects: Object.freeze([BLOODLUST_EFFECT]),
|
|
}),
|
|
durationMs: 30_000,
|
|
targetGeometry: Object.freeze({ kind: "explicit-friendly", rangeYards: 30 }),
|
|
disposition: "buff",
|
|
dispelCategory: "magic",
|
|
stackAmount: 0,
|
|
childTriggerSpellIds: Object.freeze([]),
|
|
modifiers: Object.freeze([
|
|
Object.freeze({ kind: "stat", stat: "melee-haste", operation: "flat", value: 30, multiplicative: true }),
|
|
]),
|
|
unsupportedEffects: Object.freeze([]),
|
|
});
|
|
|
|
const CONTRACTS: Readonly<Record<EnemyAuraSourceProfile, EnemySourceAuraContract>> = Object.freeze({
|
|
ascension: bloodlustContract("ascension"),
|
|
epoch: bloodlustContract("epoch"),
|
|
});
|
|
|
|
/** Return the profile-specific audited Spell.dbc contract for NPC Bloodlust 6742. */
|
|
export function enemyBloodlustContract(profile: EnemyAuraSourceProfile): EnemySourceAuraContract {
|
|
return CONTRACTS[profile];
|
|
}
|
|
|
|
/**
|
|
* Return the remaining main-hand/off-hand swing interval multiplier for one
|
|
* enemy's already-filtered active auras. Marked source Aura 138 modifiers use
|
|
* AzerothCore's separate percent speed factors; unmarked modifiers retain the
|
|
* runtime's existing additive haste calculation as a compatibility fallback.
|
|
*/
|
|
export function enemyMeleeHasteIntervalMultiplier(auras: readonly ActiveAura[]): number {
|
|
let sourceIntervalMultiplier = 1;
|
|
let additiveHastePercent = 0;
|
|
|
|
for (const aura of auras) {
|
|
for (const modifier of aura.definition.modifiers ?? []) {
|
|
if (modifier.kind !== "stat" || modifier.stat !== "melee-haste" || modifier.operation !== "flat") continue;
|
|
|
|
const hastePercent = modifier.value * (modifier.perStack === false ? 1 : aura.stacks);
|
|
if (!modifier.multiplicative) {
|
|
additiveHastePercent += hastePercent;
|
|
continue;
|
|
}
|
|
|
|
sourceIntervalMultiplier *= hastePercent >= 0
|
|
? 1 / Math.max(0.01, 1 + hastePercent / 100)
|
|
: 1 + Math.abs(hastePercent) / 100;
|
|
}
|
|
}
|
|
|
|
return sourceIntervalMultiplier / Math.max(0.01, 1 + additiveHastePercent / 100);
|
|
}
|