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

@@ -0,0 +1,482 @@
import { createHash } from "node:crypto";
import { readFileSync } from "node:fs";
import { resolve } from "node:path";
import { gunzipSync, strFromU8 } from "fflate";
import { describe, expect, it } from "vitest";
import {
createDungeonEncounterSnapshot,
reduceDungeonEncounter,
resetDungeonEncounterSnapshot,
validateDungeonEncounterDefinition,
} from "./dungeonEncounterRuntime";
import type { DungeonDefinition, DungeonEncounterSpawnGroupDefinition } from "./dungeonTypes";
import type { DungeonEncounterDefinition, DungeonEncounterSnapshot } from "./dungeonEncounterTypes";
import { validateDungeonWorldObject } from "./dungeonWorldObjects";
import compressedCampaign from "./generated/dungeonCampaignCatalog.compressed";
import {
WOW_CLASSIC_ENCOUNTER_BATCH_TWO_REVIEWS,
withWowClassicEncounterBatchTwo,
} from "./wowClassicEncounterBatchTwoCatalog";
function decodeBase64(value: string): Uint8Array {
const decoded = atob(value);
const bytes = new Uint8Array(decoded.length);
for (let index = 0; index < decoded.length; index += 1) bytes[index] = decoded.charCodeAt(index);
return bytes;
}
const campaign = JSON.parse(strFromU8(gunzipSync(decodeBase64(compressedCampaign)))) as {
readonly definitions: readonly DungeonDefinition[];
};
function original(id: string): DungeonDefinition {
const definition = campaign.definitions.find((candidate) => candidate.id === id);
if (!definition) throw new Error(`Missing generated dungeon ${id}`);
return definition;
}
function adapted(id: string): DungeonDefinition {
return withWowClassicEncounterBatchTwo(original(id));
}
function encounter(definition: DungeonDefinition): DungeonEncounterDefinition {
const value = definition.encounters?.find((candidate) => candidate.id === `${definition.id}:classic-batch-two`);
if (!value) throw new Error(`Missing Classic batch-two encounter for ${definition.id}`);
return value;
}
function group(definition: DungeonDefinition, id: string): DungeonEncounterSpawnGroupDefinition {
const value = definition.encounterSpawnGroups?.find((candidate) => candidate.id === id);
if (!value) throw new Error(`Missing encounter group ${id}`);
return value;
}
function objectBySpawn(definition: DungeonDefinition, spawnId: number) {
const matches = definition.serverGameObjects.filter((object) => object.source?.spawnId === spawnId);
if (matches.length !== 1) throw new Error(`${definition.id} expected one source object ${spawnId}, found ${matches.length}`);
return matches[0];
}
function killGroup(
definition: DungeonEncounterDefinition,
snapshot: DungeonEncounterSnapshot,
spawnGroup: DungeonEncounterSpawnGroupDefinition,
now: number,
) {
const entityIds = spawnGroup.spawns.map((spawn) => spawn.id);
return reduceDungeonEncounter(definition, snapshot, {
kind: "tick",
now,
facts: { registeredEntityIds: entityIds, deadEntityIds: entityIds },
}).snapshot;
}
function staticEntries(definition: DungeonDefinition): readonly number[] {
return definition.staticSpawns.flatMap((spawn) => {
const entry = definition.entities[spawn.entityId]?.combat?.serverEntry;
return entry === undefined ? [] : [entry];
});
}
describe("Classic source-backed encounter batch two", () => {
it("pins exact source hashes, validates every reference, suppresses event actors, and stays idempotent", () => {
const cases = [
["sunken-temple", [8_580, 8_443, 5_709]],
["blackrock-depths", [9_035, 9_038, 9_040, 9_037, 9_036, 9_034, 9_039]],
["scholomance", [1_853]],
["stratholme", [10_440]],
] as const;
expect(WOW_CLASSIC_ENCOUNTER_BATCH_TWO_REVIEWS.map((review) => review.dungeonId))
.toEqual(cases.map(([id]) => id));
const verifiedPaths = new Set<string>();
for (const review of WOW_CLASSIC_ENCOUNTER_BATCH_TWO_REVIEWS) {
expect(review.fidelity).toBe("source-backed-adapted");
expect(review.adaptations.length).toBeGreaterThan(0);
expect(review.remainingGaps.length).toBeGreaterThan(0);
for (const sourceFile of review.sourceFiles) {
expect(sourceFile.sha256).toMatch(/^[a-f0-9]{64}$/);
expect(sourceFile.anchors.length).toBeGreaterThan(0);
expect(sourceFile.anchors.every((anchor) => /lines? \d+/.test(anchor))).toBe(true);
if (!verifiedPaths.has(sourceFile.path)) {
const actualHash = createHash("sha256").update(readFileSync(resolve(sourceFile.path))).digest("hex");
expect(actualHash, sourceFile.path).toBe(sourceFile.sha256);
verifiedPaths.add(sourceFile.path);
}
}
}
for (const [id, suppressedEntries] of cases) {
const definition = adapted(id);
const scripted = encounter(definition);
validateDungeonEncounterDefinition(scripted);
expect(withWowClassicEncounterBatchTwo(definition)).toBe(definition);
expect(staticEntries(definition)).not.toEqual(expect.arrayContaining([...suppressedEntries]));
const spawnIds = new Set([
...definition.staticSpawns.map((spawn) => spawn.id),
...(definition.encounterSpawnGroups ?? []).flatMap((spawnGroup) => spawnGroup.spawns.map((spawn) => spawn.id)),
]);
const spawnGroupIds = new Set(definition.encounterSpawnGroups?.map((spawnGroup) => spawnGroup.id));
const objectIds = new Set(definition.serverGameObjects.map((object) => object.id));
const objectiveIds = new Set(definition.bosses.map((objective) => objective.id));
for (const spawnGroup of definition.encounterSpawnGroups ?? []) {
for (const spawn of spawnGroup.spawns) {
expect(definition.entities[spawn.entityId], `${id}:${spawnGroup.id}:${spawn.id}`).toBeDefined();
}
}
for (const rule of scripted.rules) {
if (rule.trigger.kind === "interact") expect(objectIds.has(rule.trigger.objectId), `${id}:${rule.id}`).toBe(true);
if (rule.trigger.kind === "entity-death" || rule.trigger.kind === "entity-engaged" || rule.trigger.kind === "entity-health") {
expect(spawnIds.has(rule.trigger.entityId), `${id}:${rule.id}:${rule.trigger.entityId}`).toBe(true);
}
if (rule.trigger.kind === "entities-dead") {
expect(rule.trigger.entityIds.every((entityId) => spawnIds.has(entityId)), `${id}:${rule.id}`).toBe(true);
}
for (const action of rule.actions) {
if (action.kind === "activate-spawn-group" || action.kind === "deactivate-spawn-group") {
expect(spawnGroupIds.has(action.spawnGroupId), `${id}:${rule.id}:${action.id}`).toBe(true);
}
if (action.kind === "set-world-object-state") {
const object = definition.serverGameObjects.find((candidate) => candidate.id === action.objectId);
expect(object, `${id}:${rule.id}:${action.id}`).toBeDefined();
expect(object?.states.some((state) => state.id === action.state), `${id}:${rule.id}:${action.id}`).toBe(true);
}
if (action.kind === "complete-objective") {
expect(objectiveIds.has(action.objectiveId), `${id}:${rule.id}:${action.id}`).toBe(true);
}
}
}
const sourceSpawnIds = definition.serverGameObjects
.flatMap((object) => object.source?.spawnId === undefined ? [] : [object.source.spawnId]);
expect(new Set(sourceSpawnIds).size).toBe(sourceSpawnIds.length);
for (const object of definition.serverGameObjects.filter((candidate) => (
scripted.initialState?.worldObjectStates?.[candidate.id] !== undefined
))) {
validateDungeonWorldObject(object);
expect(object.visual?.hidden).not.toBe(true);
}
expect(definition.validation.warnings.some((warning) => warning.includes("remain"))).toBe(true);
}
});
it("runs Sunken Temple's ordered statues, ritual, defender gate, and Eranikus recovery", () => {
const definition = adapted("sunken-temple");
const scripted = encounter(definition);
const statues = [27_898, 27_899, 28_111, 28_112, 28_113, 28_114]
.map((spawnId) => objectBySpawn(definition, spawnId));
const forcefield = objectBySpawn(definition, 268_932);
const altar = objectBySpawn(definition, 11_922);
const flames = [47_561, 47_562, 47_563, 47_564].map((spawnId) => objectBySpawn(definition, spawnId));
let snapshot = createDungeonEncounterSnapshot(scripted);
snapshot = reduceDungeonEncounter(scripted, snapshot, { kind: "interact", objectId: statues[1].id, now: 1 }).snapshot;
expect(snapshot.counters["statue-progress"]).toBe(0);
for (let index = 0; index < statues.length; index += 1) {
snapshot = reduceDungeonEncounter(scripted, snapshot, {
kind: "interact",
objectId: statues[index].id,
now: index + 2,
}).snapshot;
}
expect(snapshot).toMatchObject({ phase: "atal-alarion-active", counters: { "statue-progress": 6 } });
expect(snapshot.activeSpawnGroupIds).toContain("sunken-temple:atal-alarion");
snapshot = resetDungeonEncounterSnapshot(scripted, snapshot, "boss-wipe", 20);
expect(snapshot).toMatchObject({ phase: "recovery", counters: { "statue-progress": 6 }, activeSpawnGroupIds: [] });
snapshot = reduceDungeonEncounter(scripted, snapshot, { kind: "tick", now: 20 }).snapshot;
expect(snapshot.activeSpawnGroupIds).toContain("sunken-temple:atal-alarion");
snapshot = killGroup(scripted, snapshot, group(definition, "sunken-temple:atal-alarion"), 21);
const atalAlarion = definition.bosses.find((objective) => objective.name === "Atal'alarion")!;
expect(snapshot.completedObjectiveIds).toContain(atalAlarion.id);
const defenderIds = ["creature-39843", "creature-39844", "creature-39845", "creature-39846", "creature-34522", "creature-39847"];
snapshot = reduceDungeonEncounter(scripted, snapshot, {
kind: "tick",
now: 22,
facts: { registeredEntityIds: defenderIds, deadEntityIds: defenderIds },
}).snapshot;
expect(snapshot.worldObjectStates[forcefield.id]).toBe("open");
snapshot = reduceDungeonEncounter(scripted, snapshot, { kind: "interact", objectId: altar.id, now: 30 }).snapshot;
expect(snapshot.activeSpawnGroupIds).toContain("sunken-temple:hakkar-pack-1");
snapshot = resetDungeonEncounterSnapshot(scripted, snapshot, "boss-wipe", 31);
snapshot = reduceDungeonEncounter(scripted, snapshot, { kind: "tick", now: 31 }).snapshot;
expect(snapshot).toMatchObject({ phase: "idle", activeSpawnGroupIds: [] });
expect(snapshot.worldObjectStates[altar.id]).toBe("ready");
snapshot = reduceDungeonEncounter(scripted, snapshot, { kind: "interact", objectId: altar.id, now: 40 }).snapshot;
for (let index = 0; index < 4; index += 1) {
const ritualGroup = group(definition, `sunken-temple:hakkar-pack-${index + 1}`);
snapshot = killGroup(scripted, snapshot, ritualGroup, 41 + index * 2);
expect(snapshot.worldObjectStates[flames[index].id]).toBe("ready");
snapshot = reduceDungeonEncounter(scripted, snapshot, {
kind: "interact",
objectId: flames[index].id,
now: 42 + index * 2,
}).snapshot;
}
expect(snapshot.activeSpawnGroupIds).toContain("sunken-temple:avatar-of-hakkar");
snapshot = killGroup(scripted, snapshot, group(definition, "sunken-temple:avatar-of-hakkar"), 60);
const avatar = definition.bosses.find((objective) => objective.name === "Avatar of Hakkar")!;
expect(snapshot.completedObjectiveIds).toContain(avatar.id);
expect(flames.every((flame) => snapshot.worldObjectStates[flame.id] === "doused")).toBe(true);
snapshot = reduceDungeonEncounter(scripted, snapshot, { kind: "entity-death", entityId: "creature-39737", now: 70 }).snapshot;
expect(snapshot.activeSpawnGroupIds).toContain("sunken-temple:shade-of-eranikus");
snapshot = resetDungeonEncounterSnapshot(scripted, snapshot, "boss-wipe", 71);
snapshot = reduceDungeonEncounter(scripted, snapshot, { kind: "tick", now: 71 }).snapshot;
expect(snapshot.activeSpawnGroupIds).toContain("sunken-temple:shade-of-eranikus");
snapshot = killGroup(scripted, snapshot, group(definition, "sunken-temple:shade-of-eranikus"), 72);
const eranikus = definition.bosses.find((objective) => objective.name === "Shade of Eranikus")!;
expect(snapshot.completedObjectiveIds).toContain(eranikus.id);
expect(snapshot.checkpointId).toBe("sunken-temple-eranikus");
});
it("runs BRD's deterministic arena, twelve-coffer vault, and exact seven-stage tomb with retry", () => {
const definition = adapted("blackrock-depths");
const scripted = encounter(definition);
const arenaGate4 = objectBySpawn(definition, 15_309);
const arenaGate3 = objectBySpawn(definition, 15_295);
const arenaGroups = [
group(definition, "blackrock-depths:ring-wave-1"),
group(definition, "blackrock-depths:ring-wave-2"),
group(definition, "blackrock-depths:ring-boss"),
];
expect(arenaGroups.map((spawnGroup) => spawnGroup.spawns.length)).toEqual([3, 3, 1]);
let snapshot = reduceDungeonEncounter(scripted, createDungeonEncounterSnapshot(scripted), {
kind: "interact",
objectId: arenaGate4.id,
now: 0,
}).snapshot;
snapshot = reduceDungeonEncounter(scripted, snapshot, { kind: "tick", now: 5_000 }).snapshot;
snapshot = resetDungeonEncounterSnapshot(scripted, snapshot, "boss-wipe", 5_001);
expect(snapshot.worldObjectStates[arenaGate4.id]).toBe("ready");
expect(snapshot.activeSpawnGroupIds).toEqual([]);
snapshot = reduceDungeonEncounter(scripted, snapshot, { kind: "interact", objectId: arenaGate4.id, now: 6_000 }).snapshot;
snapshot = reduceDungeonEncounter(scripted, snapshot, { kind: "tick", now: 11_000 }).snapshot;
snapshot = killGroup(scripted, snapshot, arenaGroups[0], 11_001);
snapshot = reduceDungeonEncounter(scripted, snapshot, { kind: "tick", now: 16_001 }).snapshot;
snapshot = killGroup(scripted, snapshot, arenaGroups[1], 16_002);
snapshot = reduceDungeonEncounter(scripted, snapshot, { kind: "tick", now: 21_002 }).snapshot;
snapshot = killGroup(scripted, snapshot, arenaGroups[2], 21_003);
expect(snapshot.completedObjectiveIds).toContain("blackrock-depths:ring-of-law-gorosh");
expect(snapshot.worldObjectStates[arenaGate3.id]).toBe("open");
expect(snapshot.worldObjectStates[arenaGate4.id]).toBe("open");
const coffers = [15_306, 15_329, 15_330, 15_331, 15_363, 15_364, 15_365, 15_536, 17_904, 35_801, 35_864, 39_924]
.map((spawnId) => objectBySpawn(definition, spawnId));
for (let index = 0; index < 6; index += 1) {
snapshot = reduceDungeonEncounter(scripted, snapshot, { kind: "interact", objectId: coffers[index].id, now: 30 + index }).snapshot;
}
snapshot = resetDungeonEncounterSnapshot(scripted, snapshot, "boss-wipe", 40);
expect(snapshot.counters["opened-coffers"]).toBe(6);
expect(coffers.slice(0, 6).every((coffer) => snapshot.worldObjectStates[coffer.id] === "open")).toBe(true);
for (let index = 6; index < coffers.length; index += 1) {
snapshot = reduceDungeonEncounter(scripted, snapshot, { kind: "interact", objectId: coffers[index].id, now: 41 + index }).snapshot;
}
snapshot = reduceDungeonEncounter(scripted, snapshot, { kind: "tick", now: 60 }).snapshot;
const watchman = group(definition, "blackrock-depths:vault-watchman");
expect(snapshot.activeSpawnGroupIds).toContain(watchman.id);
snapshot = killGroup(scripted, snapshot, watchman, 61);
expect(snapshot.completedObjectiveIds).toContain("blackrock-depths:watchman-doomgrip");
expect(snapshot.worldObjectStates[objectBySpawn(definition, 43_094).id]).toBe("open");
const marker = definition.serverGameObjects.find((object) => object.id === "blackrock-depths:doomrel-marker")!;
const tombGroups = Array.from({ length: 7 }, (_, index) => group(definition, `blackrock-depths:tomb-spectral-${index + 1}`));
expect(tombGroups.map((spawnGroup) => spawnGroup.spawns.length)).toEqual([1, 1, 1, 1, 1, 1, 1]);
snapshot = reduceDungeonEncounter(scripted, snapshot, { kind: "interact", objectId: marker.id, now: 100 }).snapshot;
snapshot = reduceDungeonEncounter(scripted, snapshot, { kind: "tick", now: 1_100 }).snapshot;
expect(snapshot.activeSpawnGroupIds).toContain(tombGroups[0].id);
snapshot = resetDungeonEncounterSnapshot(scripted, snapshot, "boss-wipe", 1_101);
expect(snapshot).toMatchObject({ phase: "idle", counters: { "tomb-kills": 0 }, activeSpawnGroupIds: [] });
expect(snapshot.worldObjectStates[marker.id]).toBe("ready");
snapshot = reduceDungeonEncounter(scripted, snapshot, { kind: "interact", objectId: marker.id, now: 2_000 }).snapshot;
snapshot = reduceDungeonEncounter(scripted, snapshot, { kind: "tick", now: 3_000 }).snapshot;
snapshot = reduceDungeonEncounter(scripted, snapshot, {
kind: "entity-death",
entityId: tombGroups[0].spawns[0].id,
now: 3_001,
}).snapshot;
for (let index = 1; index < tombGroups.length; index += 1) {
snapshot = reduceDungeonEncounter(scripted, snapshot, {
kind: "tick",
now: snapshot.phaseStartedAt + 30_000,
}).snapshot;
snapshot = reduceDungeonEncounter(scripted, snapshot, {
kind: "entity-death",
entityId: tombGroups[index].spawns[0].id,
now: snapshot.phaseStartedAt + 1,
}).snapshot;
}
snapshot = reduceDungeonEncounter(scripted, snapshot, { kind: "tick", now: snapshot.phaseStartedAt + 2 }).snapshot;
expect(snapshot.completedObjectiveIds).toContain("blackrock-depths:tomb-of-seven");
expect(snapshot.worldObjectStates[objectBySpawn(definition, 67_872).id]).toBe("available");
expect(snapshot.worldObjectStates[objectBySpawn(definition, 15_334).id]).toBe("open");
});
it("gates Scholomance completion on six minibosses and a wipe-safe Gandling reveal", () => {
const definition = adapted("scholomance");
const scripted = encounter(definition);
const brazier = objectBySpawn(definition, 43_208);
const kirtonosGate = objectBySpawn(definition, 18_892);
const gandlingEntrance = objectBySpawn(definition, 43_201);
const progression = definition.encounters?.find((candidate) => candidate.id === "scholomance:boss-progression")!;
expect(progression.rules.some((rule) => rule.id === "all-required-bosses-defeated")).toBe(false);
let snapshot = reduceDungeonEncounter(scripted, createDungeonEncounterSnapshot(scripted), {
kind: "interact",
objectId: brazier.id,
now: 0,
}).snapshot;
expect(snapshot.worldObjectStates[kirtonosGate.id]).toBe("closed");
snapshot = resetDungeonEncounterSnapshot(scripted, snapshot, "boss-wipe", 1);
snapshot = reduceDungeonEncounter(scripted, snapshot, { kind: "tick", now: 1 }).snapshot;
expect(snapshot.worldObjectStates[brazier.id]).toBe("ready");
snapshot = reduceDungeonEncounter(scripted, snapshot, { kind: "interact", objectId: brazier.id, now: 2 }).snapshot;
snapshot = reduceDungeonEncounter(scripted, snapshot, { kind: "tick", now: 5_002 }).snapshot;
expect(snapshot.activeSpawnGroupIds).toContain("scholomance:kirtonos");
snapshot = reduceDungeonEncounter(scripted, snapshot, {
kind: "entity-death",
entityId: "scholomance:kirtonos-the-herald",
now: 5_003,
}).snapshot;
expect(snapshot.completedObjectiveIds).toContain("scholomance:kirtonos-the-herald");
expect(snapshot.worldObjectStates[kirtonosGate.id]).toBe("open");
const miniBossIds = ["creature-48867", "creature-48925", "creature-48946", "creature-48863", "creature-48857", "creature-48854"];
snapshot = reduceDungeonEncounter(scripted, snapshot, {
kind: "tick",
now: 6_000,
facts: { registeredEntityIds: miniBossIds, deadEntityIds: miniBossIds },
}).snapshot;
expect(snapshot.phase).toBe("gandling-reveal");
snapshot = resetDungeonEncounterSnapshot(scripted, snapshot, "boss-wipe", 6_001);
snapshot = reduceDungeonEncounter(scripted, snapshot, { kind: "tick", now: 6_001 }).snapshot;
expect(snapshot).toMatchObject({ phase: "gandling-ready", flags: { "gandling-unlocked": true } });
expect(snapshot.activeSpawnGroupIds).toContain("scholomance:gandling");
snapshot = reduceDungeonEncounter(scripted, snapshot, {
kind: "entity-engaged",
entityId: "creature-247104",
now: 6_002,
}).snapshot;
expect(snapshot.worldObjectStates[gandlingEntrance.id]).toBe("closed");
snapshot = resetDungeonEncounterSnapshot(scripted, snapshot, "boss-wipe", 6_003);
snapshot = reduceDungeonEncounter(scripted, snapshot, { kind: "tick", now: 6_003 }).snapshot;
expect(snapshot.worldObjectStates[gandlingEntrance.id]).toBe("open");
snapshot = reduceDungeonEncounter(scripted, snapshot, {
kind: "entity-death",
entityId: "creature-247104",
now: 6_004,
}).snapshot;
expect(snapshot.completedObjectiveIds).toContain("creature-247104");
const fleetRequired = definition.bosses.filter((objective) => !objective.optional && !objective.eventOnly);
for (const objective of fleetRequired) {
snapshot = reduceDungeonEncounter(scripted, snapshot, {
kind: "entity-death",
entityId: objective.id,
now: snapshot.revision + 10_000,
}).snapshot;
}
snapshot = reduceDungeonEncounter(scripted, snapshot, { kind: "tick", now: 20_000 }).snapshot;
expect(snapshot).toMatchObject({ phase: "complete", flags: { "dungeon-complete": true } });
});
it("persists and resumes Stratholme's exact 3-to-13-to-1-to-33-to-5 slaughter chain", () => {
const definition = adapted("stratholme");
const scripted = encounter(definition);
const acolytes = Array.from({ length: 3 }, (_, index) => group(definition, `stratholme:ziggurat-${index + 1}-acolyte`));
const zigguratBosses = ["creature-54238", "creature-54239", "creature-54240"];
const zigguratDoors = [11_415, 11_414, 11_416].map((spawnId) => objectBySpawn(definition, spawnId));
const mindless = group(definition, "stratholme:mindless-undead");
const guards = group(definition, "stratholme:black-guards");
expect(acolytes.map((spawnGroup) => spawnGroup.spawns.length)).toEqual([1, 1, 1]);
expect(mindless.spawns).toHaveLength(33);
expect(guards.spawns).toHaveLength(5);
let snapshot = createDungeonEncounterSnapshot(scripted);
snapshot = reduceDungeonEncounter(scripted, snapshot, { kind: "entity-death", entityId: zigguratBosses[0], now: 1 }).snapshot;
expect(snapshot.activeSpawnGroupIds).toContain(acolytes[0].id);
snapshot = resetDungeonEncounterSnapshot(scripted, snapshot, "boss-wipe", 2);
expect(snapshot.worldObjectStates[zigguratDoors[0].id]).toBe("open");
snapshot = reduceDungeonEncounter(scripted, snapshot, { kind: "tick", now: 2 }).snapshot;
expect(snapshot.activeSpawnGroupIds).toContain(acolytes[0].id);
snapshot = reduceDungeonEncounter(scripted, snapshot, {
kind: "entity-death",
entityId: acolytes[0].spawns[0].id,
now: 3,
}).snapshot;
for (let index = 1; index < 3; index += 1) {
snapshot = reduceDungeonEncounter(scripted, snapshot, {
kind: "entity-death",
entityId: zigguratBosses[index],
now: 4 + index * 2,
}).snapshot;
snapshot = reduceDungeonEncounter(scripted, snapshot, {
kind: "entity-death",
entityId: acolytes[index].spawns[0].id,
now: 5 + index * 2,
}).snapshot;
}
snapshot = reduceDungeonEncounter(scripted, snapshot, { kind: "tick", now: 20 }).snapshot;
expect(snapshot.flags["ziggurats-complete"]).toBe(true);
expect(snapshot.worldObjectStates[objectBySpawn(definition, 6_911).id]).toBe("open");
expect(snapshot.worldObjectStates[objectBySpawn(definition, 6_908).id]).toBe("open");
const slaughterIds = [
"creature-53969", "creature-54002", "creature-54018", "creature-54019",
"creature-54020", "creature-54021", "creature-54022", "creature-54026", "creature-54027",
"creature-54039", "creature-54040", "creature-54041", "creature-54050",
];
snapshot = reduceDungeonEncounter(scripted, snapshot, {
kind: "tick",
now: 21,
facts: { registeredEntityIds: slaughterIds, deadEntityIds: slaughterIds },
}).snapshot;
expect(snapshot.activeSpawnGroupIds).toContain("stratholme:ramstein");
snapshot = resetDungeonEncounterSnapshot(scripted, snapshot, "boss-wipe", 22);
snapshot = reduceDungeonEncounter(scripted, snapshot, { kind: "tick", now: 22 }).snapshot;
expect(snapshot.activeSpawnGroupIds).toContain("stratholme:ramstein");
snapshot = reduceDungeonEncounter(scripted, snapshot, {
kind: "entity-death",
entityId: "stratholme:ramstein-the-gorger",
now: 23,
}).snapshot;
expect(snapshot.phase).toBe("mindless-delay");
snapshot = resetDungeonEncounterSnapshot(scripted, snapshot, "checkpoint", 24);
snapshot = reduceDungeonEncounter(scripted, snapshot, { kind: "tick", now: 24 }).snapshot;
expect(snapshot.phase).toBe("mindless-delay");
snapshot = reduceDungeonEncounter(scripted, snapshot, { kind: "tick", now: 5_024 }).snapshot;
expect(snapshot.activeSpawnGroupIds).toContain(mindless.id);
snapshot = killGroup(scripted, snapshot, mindless, 5_025);
expect(snapshot.phase).toBe("black-guard-delay");
snapshot = resetDungeonEncounterSnapshot(scripted, snapshot, "boss-wipe", 5_026);
snapshot = reduceDungeonEncounter(scripted, snapshot, { kind: "tick", now: 5_026 }).snapshot;
expect(snapshot.phase).toBe("black-guard-delay");
snapshot = reduceDungeonEncounter(scripted, snapshot, { kind: "tick", now: 25_026 }).snapshot;
expect(snapshot.activeSpawnGroupIds).toContain(guards.id);
expect(snapshot.worldObjectStates[objectBySpawn(definition, 11_808).id]).toBe("open");
snapshot = killGroup(scripted, snapshot, guards, 25_027);
expect(snapshot.activeSpawnGroupIds).toContain("stratholme:baron-rivendare");
expect(snapshot.worldObjectStates[objectBySpawn(definition, 35_848).id]).toBe("open");
snapshot = reduceDungeonEncounter(scripted, snapshot, {
kind: "entity-engaged",
entityId: "creature-54241",
now: 25_028,
}).snapshot;
expect(snapshot.worldObjectStates[objectBySpawn(definition, 35_848).id]).toBe("closed");
snapshot = resetDungeonEncounterSnapshot(scripted, snapshot, "boss-wipe", 25_029);
snapshot = reduceDungeonEncounter(scripted, snapshot, { kind: "tick", now: 25_029 }).snapshot;
expect(snapshot).toMatchObject({ phase: "baron-ready", flags: { "guards-defeated": true } });
expect(snapshot.worldObjectStates[objectBySpawn(definition, 35_848).id]).toBe("open");
snapshot = reduceDungeonEncounter(scripted, snapshot, {
kind: "entity-death",
entityId: "creature-54241",
now: 25_030,
}).snapshot;
expect(snapshot.completedObjectiveIds).toContain("creature-54241");
expect(snapshot.checkpointId).toBe("creature-54241");
});
});