Update Healer Man server

This commit is contained in:
phenom committed 2026-09-20 13:40:23 -04:00
1 parent cc3b2fa4d5
commit daa417ec17
46 files changed
+1334 -172

No files matched your search

+105
View File
@@ -0,0 +1,105 @@
import { describe, expect, it } from "vitest";
import {
createDungeonEncounterSnapshot,
reduceDungeonEncounter,
validateDungeonEncounterDefinition,
} from "./dungeonEncounterRuntime";
import { BITE_SIZED_STOCKADES_DUNGEON_ID, STORMWIND_STOCKADE_DUNGEON_ID } from "./dungeonContentSource";
import { DUNGEON_REGISTRY, dungeonDefinitionById } from "./dungeonRegistry";
import { activateDungeonSession, restartActiveDungeonSession } from "./dungeonSession";
import { useDungeonRunStore } from "./dungeonRunStore";
import {
BITE_SIZED_STOCKADES_BOSS_CANDIDATES,
createBiteSizedStockadesDefinition,
} from "./dungeons/biteSizedStockades";
import { validateDungeonWorldObject } from "./dungeonWorldObjects";
const source = DUNGEON_REGISTRY[STORMWIND_STOCKADE_DUNGEON_ID];
describe("bite-sized Stormwind Stockades", () => {
it("creates a separate central-corridor dungeon without changing Stockades", () => {
const originalBossIds = source.bosses.map((boss) => boss.id);
const originalSpawnCount = source.staticSpawns.length;
const biteSized = createBiteSizedStockadesDefinition(source, "run-a");
expect(biteSized.id).toBe(BITE_SIZED_STOCKADES_DUNGEON_ID);
expect(biteSized).not.toBe(source);
expect(source.bosses.map((boss) => boss.id)).toEqual(originalBossIds);
expect(source.staticSpawns).toHaveLength(originalSpawnCount);
expect(source.bosses).toHaveLength(5);
expect(source.serverGameObjects.some((object) => object.id.startsWith("bite-sized-"))).toBe(false);
const bossId = biteSized.bosses[0].id;
expect(BITE_SIZED_STOCKADES_BOSS_CANDIDATES.map((boss) => boss.sourceSpawnId)).toContain(bossId);
expect(biteSized.objectiveOrder).toEqual(biteSized.bosses);
expect(biteSized.staticSpawns.filter((spawn) => spawn.id === bossId)).toHaveLength(1);
expect(biteSized.staticSpawns.every((spawn) => Math.abs(spawn.position[2]) <= 15)).toBe(true);
expect(biteSized.navigationLinks.map((link) => link.id)).toEqual(["entrance-to-central-stairs"]);
expect(biteSized.traversalRamps?.map((ramp) => ramp.id)).toEqual(["entrance-stair-ramp"]);
});
it("seals both side wings with visible movement and sight blockers", () => {
const biteSized = createBiteSizedStockadesDefinition(source, "run-b");
const walls = biteSized.serverGameObjects.filter((object) => object.id.startsWith("bite-sized-stockades-"));
expect(walls.map((wall) => wall.id).sort()).toEqual([
"bite-sized-stockades-north-wall",
"bite-sized-stockades-south-wall",
]);
for (const wall of walls) {
expect(() => validateDungeonWorldObject(wall)).not.toThrow();
expect(wall.states).toEqual([expect.objectContaining({
id: "sealed",
visible: true,
blocksMovement: true,
blocksSight: true,
})]);
}
});
it("chooses all five source bosses deterministically across fresh run ids", () => {
const selected = new Set<string>();
for (let index = 0; index < 1_000; index += 1) {
selected.add(createBiteSizedStockadesDefinition(source, `fresh-run-${index}`).bosses[0].name);
}
expect([...selected].sort()).toEqual(BITE_SIZED_STOCKADES_BOSS_CANDIDATES.map((boss) => boss.name).sort());
const first = createBiteSizedStockadesDefinition(source, "same-run");
const second = createBiteSizedStockadesDefinition(source, "same-run");
expect(second.bosses[0]).toEqual(first.bosses[0]);
expect(second.staticSpawns.find((spawn) => spawn.id === second.bosses[0].id)?.entityId)
.toBe(first.staticSpawns.find((spawn) => spawn.id === first.bosses[0].id)?.entityId);
});
it("uses the run identity for fresh, restarted, and shared sessions", () => {
expect(activateDungeonSession(BITE_SIZED_STOCKADES_DUNGEON_ID, undefined, { runId: "run-a" })).toBe(true);
const firstBoss = dungeonDefinitionById(BITE_SIZED_STOCKADES_DUNGEON_ID)!.bosses[0].name;
expect(useDungeonRunStore.getState().progress?.id).toBe("run-a");
expect(restartActiveDungeonSession()).toBe(true);
expect(dungeonDefinitionById(BITE_SIZED_STOCKADES_DUNGEON_ID)!.bosses[0].name).toBe(firstBoss);
expect(activateDungeonSession(BITE_SIZED_STOCKADES_DUNGEON_ID, undefined, { runId: "run-b" })).toBe(true);
expect(useDungeonRunStore.getState().progress?.id).toBe("run-b");
expect(dungeonDefinitionById(BITE_SIZED_STOCKADES_DUNGEON_ID)!.bosses[0].name).not.toBe(firstBoss);
});
it("completes the one-boss run only through its stable objective", () => {
const biteSized = createBiteSizedStockadesDefinition(source, "completion-run");
const bossId = biteSized.bosses[0].id;
const encounter = biteSized.encounters![0];
expect(() => validateDungeonEncounterDefinition(encounter)).not.toThrow();
const snapshot = createDungeonEncounterSnapshot(encounter, 1_000);
const reduced = reduceDungeonEncounter(encounter, snapshot, {
kind: "tick",
now: 2_000,
facts: {
registeredEntityIds: [bossId],
deadEntityIds: [bossId],
},
}).snapshot;
expect(reduced.completedObjectiveIds).toEqual([bossId]);
expect(reduced.flags["dungeon-complete"]).toBe(true);
expect(reduced.phase).toBe("complete");
});
});