Release Healer Man 0.1.22

This commit is contained in:
phenom committed 2026-09-09 11:21:33 -04:00
1 parent f6f2375145
commit 7f6001723a
144 files changed
+54107 -690

No files matched your search

+32 -10
View File
@@ -4,6 +4,10 @@ import { fileURLToPath } from "node:url";
import { describe, expect, it } from "vitest";
import campaign from "../../dungeon-pipeline/dungeon-campaign.json";
import { DUNGEON_DEFINITIONS } from "./dungeonRegistry";
import {
WOW_DUNGEON_BASIC_ONLY_BOSS_EXCEPTIONS,
WOW_DUNGEON_NO_TRASH_EXCEPTIONS,
} from "./wowDungeonContentExceptions";
import {
createMobAnimationTransform,
getMobAnimationPhase,
@@ -15,14 +19,8 @@ import {
const publicRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../../public");
const campaignIds = new Set(campaign.dungeons.map((dungeon) => dungeon.slug));
const basicOnlyBossExceptions = new Set([
"wailing-caverns:kresh",
"wailing-caverns:deviate-faerie-dragon",
"blackrock-spire:entry-9218",
"blackrock-spire:entry-9219",
"blackrock-spire:entry-10376",
]);
const noTrashExceptions = new Set(["trial-of-the-champion"]);
const basicOnlyBossExceptions = new Set(WOW_DUNGEON_BASIC_ONLY_BOSS_EXCEPTIONS.map(({ key }) => key));
const noTrashExceptions = new Set(WOW_DUNGEON_NO_TRASH_EXCEPTIONS.map(({ key }) => key));
const animationCache = new Map<string, Promise<readonly { readonly name: string }[]>>();
async function readAnimations(url: string): Promise<readonly { readonly name: string }[]> {
@@ -54,9 +52,23 @@ async function readAnimations(url: string): Promise<readonly { readonly name: st
}
describe("WoW dungeon combat and animation coverage", () => {
it("gives all 54 campaign dungeons complete executable populations", async () => {
it("gives all 54 campaign dungeons runtime-spawnable combat populations", async () => {
const dungeons = DUNGEON_DEFINITIONS.filter((definition) => campaignIds.has(definition.id));
expect(dungeons).toHaveLength(54);
expect(basicOnlyBossExceptions.size).toBe(WOW_DUNGEON_BASIC_ONLY_BOSS_EXCEPTIONS.length);
expect(noTrashExceptions.size).toBe(WOW_DUNGEON_NO_TRASH_EXCEPTIONS.length);
const actualBasicOnlyBosses = dungeons.flatMap((dungeon) => Object.entries(dungeon.entities)
.filter(([, entity]) => (
entity.kind === "boss"
&& !(entity.combat?.attacks ?? []).some((attack) => attack.id !== "basic-attack")
))
.map(([entityId]) => `${dungeon.id}:${entityId}`))
.sort();
expect(actualBasicOnlyBosses).toEqual([...basicOnlyBossExceptions].sort());
expect(dungeons
.filter((dungeon) => !Object.values(dungeon.entities).some((entity) => entity.kind === "mob"))
.map((dungeon) => dungeon.id)
.sort()).toEqual([...noTrashExceptions].sort());
for (const dungeon of dungeons) {
const entities = Object.values(dungeon.entities);
@@ -68,7 +80,9 @@ describe("WoW dungeon combat and animation coverage", () => {
expect(mobs.length, dungeon.id + ": mobs").toBeGreaterThan(0);
}
expect(
dungeon.staticSpawns.length + dungeon.roamingPacks.length,
dungeon.staticSpawns.length
+ dungeon.roamingPacks.length
+ (dungeon.encounterSpawnGroups?.reduce((count, group) => count + group.spawns.length, 0) ?? 0),
dungeon.id + ": population",
).toBeGreaterThan(0);
@@ -86,6 +100,14 @@ describe("WoW dungeon combat and animation coverage", () => {
).toBeDefined();
}
}
for (const group of dungeon.encounterSpawnGroups ?? []) {
for (const spawn of group.spawns) {
expect(
dungeon.entities[spawn.entityId],
dungeon.id + ":" + group.id + ":" + spawn.id,
).toBeDefined();
}
}
for (const entity of entities) {
const key = dungeon.id + ":" + entity.id;