Release Healer Man 0.1.21

This commit is contained in:
phenom committed 2026-09-08 10:40:26 -04:00
1 parent 699fc858c9
commit f6f2375145
210 files changed
+976039 -6247

No files matched your search

+189
View File
@@ -0,0 +1,189 @@
import { describe, expect, it } from "vitest";
import { buildBossGuideCatalog, buildDungeonBossGuide, bossGuideOverrideKey } from "./bossGuide";
import { DUNGEON_DEFINITION_SCHEMA_VERSION, type DungeonDefinition } from "./dungeonTypes";
import { DUNGEON_DEFINITIONS } from "./dungeonRegistry";
import { BOSS_GUIDE_OVERRIDES } from "./bossGuideOverrides";
const fixture = {
schemaVersion: DUNGEON_DEFINITION_SCHEMA_VERSION,
id: "guide-fixture",
title: "Guide Fixture",
mapId: 1,
lfgDungeonIds: [],
expansion: "runewaker",
environmentMode: "runewaker-ros",
difficultyVariants: [{ id: "normal", difficulty: "normal", spawnMask: 1, levelRange: [1, 2] }],
defaultDifficultyId: "normal",
availability: "available",
presentation: {
location: "Test",
theme: "Test",
summary: "Test",
loadingMessage: "Test",
unchartedAreaName: "Test",
background: "#000",
fog: { color: "#000", near: 1, far: 2 },
ambientLight: { color: "#fff", intensity: 1 },
hemisphereLight: { skyColor: "#fff", groundColor: "#000", intensity: 1 },
directionalLight: { color: "#fff", intensity: 1, offset: [0, 1, 0] },
materials: { cutoutPatterns: [], cutoutNames: [], blendPatterns: [], blendNames: [], additivePatterns: [], additiveNames: [] },
map: { width: 100, height: 100, padding: 1, contours: [] },
},
assets: { visual: [], collision: [] },
transform: { position: [0, 0, 0], rotation: [0, 0, 0], scale: 1 },
bounds: { min: [0, 0, 0], max: [1, 1, 1] },
entrance: { name: "Entrance", footPosition: [0, 0, 0], forward: [0, 0, 1], yaw: 0 },
areas: [],
entities: {
herald: {
id: "herald",
name: "The Herald",
kind: "boss",
title: "Keeper of Tests",
combat: {
attacks: [
{
id: "basic-attack",
name: "Basic Attack",
delivery: "melee",
target: "primary",
school: "physical",
animation: "attack",
range: 4,
cooldownMs: 2_000,
damageMultiplier: 1,
},
{
id: "falling-test",
name: "Falling Test",
spellId: 42,
delivery: "area",
target: "random-party",
school: "arcane",
animation: "cast",
castTimeMs: 2_000,
range: 30,
cooldownMs: 12_000,
initialCooldownMs: [8_000, 10_000],
repeatCooldownMs: [12_000, 14_000],
maximumCasts: 1,
damageMultiplier: 1.2,
telegraph: { shape: "circle", anchor: "target", radius: 6, warningMs: 2_000 },
condition: { kind: "self-health-percent", minimum: 0, maximum: 50 },
},
{
id: "source-gap-sweep",
name: "Fallback Sweep",
delivery: "area",
target: "nearby-party",
school: "physical",
animation: "attack",
castTimeMs: 1_800,
range: 8,
cooldownMs: 10_000,
damageMultiplier: 1,
telegraph: { shape: "cone", anchor: "source", length: 8, angleDegrees: 90, warningMs: 1_800 },
},
],
},
visual: { primaryColor: "#000", accentColor: "#fff", scale: 1, archetype: "humanoid" },
},
sentinel: {
id: "sentinel",
name: "Silent Sentinel",
kind: "boss",
title: "The Unscripted",
combat: { attacks: [] },
visual: { primaryColor: "#000", accentColor: "#fff", scale: 1, archetype: "humanoid" },
},
},
staticSpawns: [
{ id: "herald-spawn", entityId: "herald", position: [0, 0, 0] },
{ id: "sentinel-spawn", entityId: "sentinel", position: [1, 0, 0] },
],
roamingPacks: [],
bosses: [
{ id: "herald-spawn", name: "The Herald", position: [0, 0, 0] },
{ id: "sentinel-spawn", name: "Silent Sentinel", position: [1, 0, 0] },
],
objectiveOrder: [],
navigationLinks: [],
serverGameObjects: [],
provenance: { clientBuild: "test", clientArchiveHashes: {}, databaseAdapter: "test", coordinateTransform: "test" },
validation: { status: "green", blockers: [], warnings: [] },
} as const satisfies DungeonDefinition;
describe("boss guide model", () => {
it("derives health triggers, timing, telegraph geometry, instructions, and fidelity from runtime attacks", () => {
const guide = buildDungeonBossGuide(fixture, {
[bossGuideOverrideKey("guide-fixture", "herald", "falling-test")]: {
counterplay: "Use the authored safe spot.",
},
});
const mechanic = guide.bosses[0].mechanics[0];
expect(mechanic).toMatchObject({
id: "falling-test",
trigger: "When the boss reaches 50% health",
timing: "First: 8s–10s · Repeats: 12s–14s · Cast: 2s · Maximum uses: 1",
targetAndEffect: "Arcane damage to a random party member (1.2× boss power)",
telegraph: "6m radius circle centered on the target · 2s warning",
counterplay: "Use the authored safe spot.",
fidelity: "source",
fidelityLabel: "Source backed",
});
expect(mechanic.testInstruction).toContain("cross the threshold");
expect(guide.bosses[0].mechanics[1]).toMatchObject({
fidelity: "fallback",
fidelityLabel: "HealerMan fallback",
});
});
it("omits basic attacks and preserves an honest empty entry for a boss with no specials", () => {
const guide = buildDungeonBossGuide(fixture);
expect(guide.bosses[0].mechanics.map((mechanic) => mechanic.id)).toEqual([
"falling-test",
"source-gap-sweep",
]);
expect(guide.bosses[1].mechanics).toEqual([]);
});
it("covers every registered boss objective and every non-basic runtime mechanic", () => {
const catalog = buildBossGuideCatalog(DUNGEON_DEFINITIONS, BOSS_GUIDE_OVERRIDES);
const guideByDungeon = new Map(catalog.map((guide) => [guide.id, guide]));
for (const dungeon of DUNGEON_DEFINITIONS) {
const guide = guideByDungeon.get(dungeon.id);
expect(guide, dungeon.id).toBeDefined();
expect(guide!.bosses.length, dungeon.id).toBeGreaterThanOrEqual(dungeon.bosses.length);
for (const objective of dungeon.bosses) {
const boss = guide!.bosses.find((entry) => entry.id === objective.id);
expect(boss, `${dungeon.id}:${objective.name}`).toBeDefined();
expect(boss!.entityId, `${dungeon.id}:${objective.name}`).toBeDefined();
}
for (const boss of guide!.bosses) {
if (!boss.entityId) continue;
const expectedIds = dungeon.entities[boss.entityId]?.combat?.attacks
.filter((attack) => attack.id !== "basic-attack")
.map((attack) => attack.id) ?? [];
expect(boss.mechanics.map((mechanic) => mechanic.id), `${dungeon.id}:${boss.name}`).toEqual(expectedIds);
for (const mechanic of boss.mechanics) {
expect(mechanic.trigger, `${dungeon.id}:${boss.name}:${mechanic.name}:trigger`).not.toBe("");
expect(mechanic.timing, `${dungeon.id}:${boss.name}:${mechanic.name}:timing`).not.toBe("");
expect(mechanic.telegraph, `${dungeon.id}:${boss.name}:${mechanic.name}:telegraph`).not.toBe("");
expect(mechanic.counterplay, `${dungeon.id}:${boss.name}:${mechanic.name}:counterplay`).not.toBe("");
expect(mechanic.testInstruction, `${dungeon.id}:${boss.name}:${mechanic.name}:test`).not.toBe("");
}
}
}
const archaedas = guideByDungeon.get("uldaman")!.bosses.find((boss) => boss.name === "Archaedas")!;
expect(archaedas.mechanics.find((mechanic) => mechanic.id === "archaedas-awaken-earthen-guardians"))
.toMatchObject({
fidelityLabel: "Source backed",
counterplay: "At 70% health, the tank gathers the six awakened guardians while the party clears them together.",
});
const flowingChaos = guideByDungeon.get("forsaken-abbey")!.bosses.find((boss) => boss.name === "Flowing Chaos")!;
expect(flowingChaos.mechanics[0].fidelityLabel).toBe("HealerMan fallback");
});
});