Files
healer-man/src/game/enemyWeaponDebuffs.test.ts
T
2026-10-06 22:25:34 -04:00

114 lines
5.9 KiB
TypeScript

import { describe, expect, it } from "vitest";
import { applyAura, dispelAuras, resolveDamageValue } from "./combatAuras";
import {
enemyDisarmBlocksCombatChannel,
enemyDisarmCanApplyToTarget,
enemyDisarmInvalidatesAbilityRequirement,
enemyDisarmWeaponChannels,
enemyWeaponDebuffAuraDefinition,
enemyWeaponDebuffContract,
} from "./enemyWeaponDebuffs";
describe("pinned enemy weapon debuffs", () => {
it("pins Disarm's main-hand/ranged rows and per-profile hit and duration contract", () => {
const ascension = enemyWeaponDebuffContract(6713, "ascension")!;
const epoch = enemyWeaponDebuffContract(6713, "epoch")!;
expect(ascension).toMatchObject({
spellMechanic: 3,
signature: {
schoolMask: 1,
damageClass: 2,
durationMs: 5_000,
effects: [
{ effectType: 6, auraType: 67, basePoints: 0, implicitTargetA: 6, miscValue: 0 },
{ effectType: 6, auraType: 278, basePoints: 1, implicitTargetA: 6, miscValue: 0 },
],
},
durationMs: 5_000,
dispelType: 0,
stackAmount: 0,
casterWeaponRequirement: { itemClass: -1, subclassMask: 0, inventoryMask: 0 },
applicationGate: "landed-melee-hit",
weaponChannels: ["main-hand", "ranged"],
});
expect(epoch.signature.effects).toEqual([
{ effectType: 6, auraType: 67, basePoints: 0, mechanic: 0, implicitTargetA: 6, implicitTargetB: 0, radius: 0, miscValue: 0, periodMs: 0 },
]);
expect(enemyDisarmWeaponChannels("ascension")).toEqual(["main-hand", "ranged"]);
expect(enemyDisarmWeaponChannels("epoch")).toEqual(["main-hand"]);
expect(enemyWeaponDebuffContract(999_999, "ascension")).toBeUndefined();
});
it("requires an affected target weapon and leaves off-hand and casting channels alone", () => {
const offHandOnly = { mainHand: false, offHand: true, ranged: false };
expect(enemyDisarmCanApplyToTarget("ascension", offHandOnly)).toBe(false);
expect(enemyDisarmCanApplyToTarget("epoch", offHandOnly)).toBe(false);
expect(enemyDisarmCanApplyToTarget("ascension", { ...offHandOnly, ranged: true })).toBe(true);
expect(enemyDisarmCanApplyToTarget("epoch", { ...offHandOnly, ranged: true })).toBe(false);
expect(enemyDisarmCanApplyToTarget("ascension", { mainHand: true, offHand: false, ranged: false, feralForm: true })).toBe(false);
expect(enemyDisarmBlocksCombatChannel("ascension", "main-hand")).toBe(true);
expect(enemyDisarmBlocksCombatChannel("ascension", "ranged")).toBe(true);
expect(enemyDisarmBlocksCombatChannel("ascension", "off-hand")).toBe(false);
expect(enemyDisarmBlocksCombatChannel("ascension", "spell-cast")).toBe(false);
expect(enemyDisarmBlocksCombatChannel("epoch", "ranged")).toBe(false);
});
it("blocks an explicit weapon requirement only when Disarm disables every matching equipped slot", () => {
const daggerRequirement = { equippedItemClass: 2, equippedItemSubclassMask: 1 << 15 };
const mainHandDagger = [{ channel: "main-hand" as const, itemClass: 2, subclass: 15 }];
const mainHandAndOffHandDaggers = [
...mainHandDagger,
{ channel: "off-hand" as const, itemClass: 2, subclass: 15 },
];
expect(enemyDisarmInvalidatesAbilityRequirement("ascension", daggerRequirement, mainHandDagger)).toBe(true);
expect(enemyDisarmInvalidatesAbilityRequirement("epoch", daggerRequirement, mainHandDagger)).toBe(true);
expect(enemyDisarmInvalidatesAbilityRequirement("ascension", daggerRequirement, mainHandAndOffHandDaggers)).toBe(false);
expect(enemyDisarmInvalidatesAbilityRequirement("ascension", { ...daggerRequirement, equippedItemSubclassMask: 1 << 4 }, mainHandDagger)).toBe(false);
expect(enemyDisarmInvalidatesAbilityRequirement("ascension", { equippedItemClass: -1, equippedItemSubclassMask: 0 }, mainHandDagger)).toBe(false);
});
it("pins Infected Wound as flat physical damage taken, pre-mitigation, disease dispel, and refresh", () => {
for (const profile of ["ascension", "epoch"] as const) {
const contract = enemyWeaponDebuffContract(17230, profile)!;
expect(contract).toMatchObject({
signature: {
schoolMask: 8,
damageClass: 0,
durationMs: 300_000,
effects: [{ effectType: 6, auraType: 14, basePoints: 6, implicitTargetA: 6, miscValue: 1 }],
},
durationMs: 300_000,
dispelType: 3,
dispelCategory: "disease",
stackAmount: 0,
casterWeaponRequirement: { itemClass: -1, subclassMask: 0, inventoryMask: 0 },
applicationGate: "aura-only-no-miss-roll",
modifiers: [{ kind: "damage", direction: "taken", school: "physical", operation: "flat", value: 6, phase: "pre-mitigation" }],
});
}
const definition = enemyWeaponDebuffAuraDefinition(enemyWeaponDebuffContract(17230, "ascension")!);
let auras = applyAura([], { definition, sourceId: "infected-caster-a", targetId: "player", now: 100 }).auras;
auras = applyAura(auras, { definition, sourceId: "infected-caster-b", targetId: "player", now: 1_000 }).auras;
expect(auras).toHaveLength(1);
expect(auras[0]).toMatchObject({ sourceId: "infected-caster-b", appliedAt: 1_000, expiresAt: 301_000 });
expect(resolveDamageValue(100, auras, {
direction: "taken", school: "physical", attackKind: "melee", phase: "pre-mitigation",
})).toBe(106);
expect(resolveDamageValue(100, auras, {
direction: "taken", school: "fire", attackKind: "spell", phase: "pre-mitigation",
})).toBe(100);
expect(resolveDamageValue(100, auras, {
direction: "taken", school: "physical", attackKind: "melee",
})).toBe(100);
expect(dispelAuras(auras, { relationship: "friendly", categories: ["poison"] }).removed).toHaveLength(0);
const diseaseDispel = dispelAuras(auras, { relationship: "friendly", categories: ["disease"] });
expect(diseaseDispel.removed).toHaveLength(1);
expect(diseaseDispel.auras).toHaveLength(0);
});
});