71 lines
2.5 KiB
TypeScript
71 lines
2.5 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import {
|
|
addActorThreat,
|
|
pruneThreatTable,
|
|
resolveAggroTarget,
|
|
seedActorThreat,
|
|
tauntThreat,
|
|
threatFromDamage,
|
|
threatFromHealing,
|
|
} from "./aggro";
|
|
|
|
describe("pure aggro rules", () => {
|
|
it("uses five-times tank damage threat and applies the final talent scalar", () => {
|
|
expect(threatFromDamage(10, "tank")).toBe(50);
|
|
expect(threatFromDamage(10, "damage")).toBe(10);
|
|
expect(threatFromDamage(10, "healer")).toBe(10);
|
|
expect(threatFromDamage(10, "tank", 0.8)).toBe(40);
|
|
});
|
|
|
|
it("uses effective healing at one quarter strength split across engaged mobs", () => {
|
|
expect(threatFromHealing(80, 1)).toBe(20);
|
|
expect(threatFromHealing(80, 4)).toBe(5);
|
|
expect(threatFromHealing(80, 0)).toBe(0);
|
|
});
|
|
|
|
it("seeds only a missing actor and adds subsequent threat", () => {
|
|
const seeded = seedActorThreat({}, "puller");
|
|
expect(seeded).toEqual({ puller: 1 });
|
|
expect(seedActorThreat(seeded, "puller")).toBe(seeded);
|
|
expect(addActorThreat(seeded, "puller", 4)).toEqual({ puller: 5 });
|
|
});
|
|
|
|
it("preserves the incumbent on exact ties and otherwise uses actor-id ordering", () => {
|
|
const table = { bravo: 10, alpha: 10 };
|
|
const eligible = new Set(["alpha", "bravo"]);
|
|
expect(resolveAggroTarget(table, eligible, "bravo", null, 1_000).targetActorId).toBe("bravo");
|
|
expect(resolveAggroTarget(table, eligible, null, null, 1_000).targetActorId).toBe("alpha");
|
|
});
|
|
|
|
it("puts a taunter at max plus one for the forced duration", () => {
|
|
const table = tauntThreat({ healer: 27, tank: 2 }, "tank");
|
|
expect(table).toEqual({ healer: 27, tank: 28 });
|
|
const forced = { actorId: "tank", endsAt: 4_000 };
|
|
const eligible = new Set(["healer", "tank"]);
|
|
expect(resolveAggroTarget(table, eligible, "healer", forced, 3_999)).toEqual({
|
|
targetActorId: "tank",
|
|
forcedTarget: forced,
|
|
});
|
|
expect(resolveAggroTarget({ ...table, healer: 40 }, eligible, "tank", forced, 4_000)).toEqual({
|
|
targetActorId: "healer",
|
|
forcedTarget: null,
|
|
});
|
|
});
|
|
|
|
it("drops an unavailable forced target and removes stale threat", () => {
|
|
const table = { downed: 50, living: 10 };
|
|
const eligible = new Set(["living"]);
|
|
expect(resolveAggroTarget(
|
|
table,
|
|
eligible,
|
|
"downed",
|
|
{ actorId: "downed", endsAt: 9_000 },
|
|
1_000,
|
|
)).toEqual({
|
|
targetActorId: "living",
|
|
forcedTarget: null,
|
|
});
|
|
expect(pruneThreatTable(table, eligible)).toEqual({ living: 10 });
|
|
});
|
|
});
|