91 lines
3.2 KiB
TypeScript
91 lines
3.2 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { WAILING_CAVERNS_ENTITIES } from "./mobPopulation";
|
|
import {
|
|
LOOT_CATALOG,
|
|
bossHasLoot,
|
|
bossLootTable,
|
|
rollBossLoot,
|
|
scaledLootItemLevel,
|
|
} from "./lootCatalog";
|
|
|
|
describe("SQL-generated boss loot catalog", () => {
|
|
it("covers every authored Wailing Caverns boss with queryable item templates", () => {
|
|
const bossKeys = Object.values(WAILING_CAVERNS_ENTITIES)
|
|
.filter((entity) => entity.kind === "boss")
|
|
.map((entity) => entity.id)
|
|
.sort();
|
|
const catalogKeys = LOOT_CATALOG.bosses
|
|
.filter((boss) => boss.dungeonId === "wailing-caverns")
|
|
.map((boss) => boss.bossKey)
|
|
.sort();
|
|
|
|
expect(catalogKeys).toEqual(bossKeys);
|
|
expect(LOOT_CATALOG.bosses).toHaveLength(9);
|
|
expect(LOOT_CATALOG.bosses.flatMap((boss) => boss.items)).toHaveLength(23);
|
|
for (const boss of LOOT_CATALOG.bosses) {
|
|
expect(boss.items.length).toBeGreaterThan(0);
|
|
expect(boss.items.every((item) => item.weight > 0)).toBe(true);
|
|
expect(bossHasLoot(boss.bossKey)).toBe(true);
|
|
}
|
|
});
|
|
|
|
it("rolls recognizable boss items while setting item level from the player", () => {
|
|
const first = rollBossLoot("lady-anacondra", 80, { random: () => 0, now: 12_345 });
|
|
const last = rollBossLoot("lady-anacondra", 80, { random: () => 0.999, now: 12_346 });
|
|
|
|
expect(first).toHaveLength(1);
|
|
expect(first[0]).toMatchObject({
|
|
itemId: 5404,
|
|
name: "Serpent's Shoulders",
|
|
itemLevel: 85,
|
|
sourceItemLevel: 23,
|
|
sourceBossKey: "lady-anacondra",
|
|
acquiredAt: 12_345,
|
|
});
|
|
expect(last[0]).toMatchObject({
|
|
itemId: 10412,
|
|
name: "Belt of the Fang",
|
|
itemLevel: 85,
|
|
sourceItemLevel: 21,
|
|
});
|
|
expect(first[0].stats.agility).toBeGreaterThan(0);
|
|
expect(first[0].stats.strength).toBe(0);
|
|
expect(first[0].stats.armor).toBeGreaterThan(0);
|
|
expect(bossLootTable("lady-anacondra")?.lootTableId).toBe("wc-lady-anacondra");
|
|
});
|
|
|
|
it("clamps generated item levels to the supported character range", () => {
|
|
expect(scaledLootItemLevel(-10)).toBe(1);
|
|
expect(scaledLootItemLevel(42.9)).toBe(42);
|
|
expect(scaledLootItemLevel(900)).toBe(85);
|
|
expect(rollBossLoot("not-a-boss", 20)).toEqual([]);
|
|
});
|
|
|
|
it("adds at most one bonus weighted item without changing normal rolls", () => {
|
|
const normal = rollBossLoot("lady-anacondra", 80, {
|
|
random: () => 0,
|
|
now: 20_000,
|
|
});
|
|
const guaranteedBonus = rollBossLoot("lady-anacondra", 80, {
|
|
random: () => 0,
|
|
now: 20_001,
|
|
bonusItemChance: 1,
|
|
});
|
|
const failedBonus = rollBossLoot("lady-anacondra", 80, {
|
|
random: () => 0.999,
|
|
now: 20_002,
|
|
bonusItemChance: 0.5,
|
|
});
|
|
|
|
expect(normal).toHaveLength(1);
|
|
expect(guaranteedBonus).toHaveLength(2);
|
|
expect(failedBonus).toHaveLength(1);
|
|
expect(new Set(guaranteedBonus.map((item) => item.instanceId)).size).toBe(2);
|
|
expect(guaranteedBonus.every((item) => item.sourceBossKey === "lady-anacondra")).toBe(true);
|
|
});
|
|
|
|
it.each([1, 37, 79])("suppresses equipment and bonus equipment at level %i", (level) => {
|
|
expect(rollBossLoot("lady-anacondra", level, { random: () => 0, bonusItemChance: 1 })).toEqual([]);
|
|
});
|
|
});
|