forked from phenom/healer-man
123 lines
5.6 KiB
TypeScript
123 lines
5.6 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { applyAura, resolveDamageValue, resolveStatValue } from "./combatAuras";
|
|
import {
|
|
WOW335_WARLOCK_METAMORPHOSIS_AURA_TAG,
|
|
WOW335_WARLOCK_METAMORPHOSIS_FORM_ID,
|
|
WOW335_WARLOCK_METAMORPHOSIS_FORM_ABILITY_IDS,
|
|
warlockMetamorphosisCanCastAbilityWhileActive,
|
|
warlockMetamorphosisAbilityEligible,
|
|
warlockMetamorphosisFormActionReady,
|
|
wow335WarlockImmolationAttackPowerAura,
|
|
wow335WarlockImmolationAttackPowerReduction,
|
|
wow335WarlockMetamorphosisAuraForRank,
|
|
wow335WarlockMetamorphosisControlDuration,
|
|
wow335WarlockMetamorphosisEffectsForRank,
|
|
} from "./wow335WarlockMetamorphosisRuntime";
|
|
|
|
describe("WoW Warlock Metamorphosis profile", () => {
|
|
it("uses the generated 3.3.5a rank values and leaves unlearned ranks inactive", () => {
|
|
expect(wow335WarlockMetamorphosisEffectsForRank(0)).toBeNull();
|
|
expect(wow335WarlockMetamorphosisEffectsForRank(1)).toEqual({
|
|
rank: 1,
|
|
durationMs: 30_000,
|
|
cooldownMs: 180_000,
|
|
armorContributionPercent: 130,
|
|
damagePercent: 15,
|
|
meleeCritChanceTakenReductionPercent: 6,
|
|
stunSnareDurationReductionPercent: 25,
|
|
allowedSchools: ["fire", "shadow"],
|
|
pvpDamageBonusPercent: null,
|
|
});
|
|
expect(wow335WarlockMetamorphosisEffectsForRank(Number.NaN)).toBeNull();
|
|
});
|
|
|
|
it("allows only Fire/Shadow or explicitly shapeshift-usable abilities while active", () => {
|
|
expect(warlockMetamorphosisAbilityEligible(false, {})).toBe(true);
|
|
expect(warlockMetamorphosisAbilityEligible(true, { school: "fire" })).toBe(true);
|
|
expect(warlockMetamorphosisAbilityEligible(true, { school: "shadow" })).toBe(true);
|
|
expect(warlockMetamorphosisAbilityEligible(true, { schools: ["holy", "shadow"] })).toBe(true);
|
|
expect(warlockMetamorphosisAbilityEligible(true, {
|
|
school: "arcane",
|
|
usableWhileShapeshifted: true,
|
|
})).toBe(true);
|
|
expect(warlockMetamorphosisAbilityEligible(true, { school: "arcane" })).toBe(false);
|
|
expect(warlockMetamorphosisAbilityEligible(true, { school: "physical" })).toBe(false);
|
|
expect(warlockMetamorphosisAbilityEligible(true, {})).toBe(false);
|
|
expect(warlockMetamorphosisCanCastAbilityWhileActive({
|
|
id: "physical-strike", description: "Strikes for physical damage.", effects: [{ kind: "damage", coefficient: 1, school: "physical" }],
|
|
} as Parameters<typeof warlockMetamorphosisCanCastAbilityWhileActive>[0])).toBe(false);
|
|
expect(warlockMetamorphosisCanCastAbilityWhileActive({
|
|
id: "explicit-shadow", description: "Deals Shadow damage.", effects: [{ kind: "damage", coefficient: 1 }],
|
|
} as Parameters<typeof warlockMetamorphosisCanCastAbilityWhileActive>[0])).toBe(true);
|
|
expect(warlockMetamorphosisCanCastAbilityWhileActive({
|
|
id: "physical-melee", description: "Usable while shapeshifted.", effects: [{ kind: "damage", coefficient: 1, school: "physical" }],
|
|
} as Parameters<typeof warlockMetamorphosisCanCastAbilityWhileActive>[0])).toBe(true);
|
|
expect(warlockMetamorphosisFormActionReady(WOW335_WARLOCK_METAMORPHOSIS_FORM_ABILITY_IDS[0], false)).toBe(false);
|
|
expect(warlockMetamorphosisFormActionReady(WOW335_WARLOCK_METAMORPHOSIS_FORM_ABILITY_IDS[0], true)).toBe(true);
|
|
});
|
|
|
|
it("creates a timed source-scoped aura with only supported armor and damage modifiers", () => {
|
|
const definition = wow335WarlockMetamorphosisAuraForRank(1);
|
|
expect(definition).toMatchObject({
|
|
id: "wow335:warlock:metamorphosis",
|
|
durationMs: 30_000,
|
|
uniqueBySource: true,
|
|
utilityTags: ["shapeshift", WOW335_WARLOCK_METAMORPHOSIS_AURA_TAG],
|
|
});
|
|
expect(wow335WarlockMetamorphosisAuraForRank(0)).toBeNull();
|
|
expect(WOW335_WARLOCK_METAMORPHOSIS_FORM_ID).toBe(22);
|
|
|
|
const active = applyAura([], {
|
|
definition: definition!,
|
|
sourceId: "warlock-a",
|
|
targetId: "warlock-a",
|
|
now: 10_000,
|
|
}).aura;
|
|
expect(active.expiresAt).toBe(40_000);
|
|
expect(resolveStatValue(100, [active], "armor")).toBeCloseTo(230);
|
|
expect(resolveDamageValue(100, [active], {
|
|
direction: "dealt",
|
|
school: "shadow",
|
|
attackKind: "spell",
|
|
})).toBeCloseTo(115);
|
|
expect(resolveDamageValue(100, [active], {
|
|
direction: "dealt",
|
|
school: "physical",
|
|
attackKind: "melee",
|
|
})).toBeCloseTo(115);
|
|
expect(definition?.modifiers).toHaveLength(3);
|
|
expect(resolveStatValue(100, [active], "incoming-melee-critical-strike")).toBe(94);
|
|
});
|
|
|
|
it("keeps two Warlocks' form auras source-scoped", () => {
|
|
const definition = wow335WarlockMetamorphosisAuraForRank(1)!;
|
|
const first = applyAura([], {
|
|
definition,
|
|
sourceId: "warlock-a",
|
|
targetId: "warlock-a",
|
|
now: 1_000,
|
|
});
|
|
const second = applyAura(first.auras, {
|
|
definition,
|
|
sourceId: "warlock-b",
|
|
targetId: "warlock-b",
|
|
now: 1_500,
|
|
});
|
|
expect(second.auras).toHaveLength(2);
|
|
expect(second.auras.map((aura) => aura.sourceId)).toEqual(["warlock-a", "warlock-b"]);
|
|
});
|
|
|
|
it("uses the Immolation AP formula and reduces only sourced stun, root, and slow durations", () => {
|
|
expect(wow335WarlockImmolationAttackPowerReduction(1)).toBe(2);
|
|
expect(wow335WarlockImmolationAttackPowerReduction(80)).toBe(357);
|
|
expect(wow335WarlockImmolationAttackPowerAura(80).modifiers).toEqual([
|
|
{ kind: "stat", stat: "attack-power", operation: "flat", value: -357 },
|
|
]);
|
|
for (const mechanic of ["stun", "root", "slow"]) {
|
|
expect(wow335WarlockMetamorphosisControlDuration(10_000, mechanic, true)).toBe(7_500);
|
|
}
|
|
expect(wow335WarlockMetamorphosisControlDuration(10_000, "fear", true)).toBe(10_000);
|
|
expect(wow335WarlockMetamorphosisControlDuration(10_000, "stun", false)).toBe(10_000);
|
|
});
|
|
});
|