forked from phenom/healer-man
Update Healer Man server
This commit is contained in:
1 parent
8a98797fcf
commit
11934a3979
44 files changed
+3183
-329
No files matched your search
@@ -1,13 +1,20 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import {
|
||||
RANDOMIZED_BITE_SIZED_STOCKADES_DUNGEON_ID,
|
||||
RANDOMIZED_BITE_SIZED_AVAILABLE_DUNGEON_ID,
|
||||
STORMWIND_STOCKADE_DUNGEON_ID,
|
||||
} from "./dungeonContentSource";
|
||||
import {
|
||||
DUNGEON_REGISTRY,
|
||||
RANDOMIZED_BITE_SIZED_CREATURE_CATALOG,
|
||||
AVAILABLE_RANDOMIZED_CREATURE_CATALOG,
|
||||
BITE_SIZED_RANDOMIZED_CREATURE_CATALOG,
|
||||
dungeonDefinitionById,
|
||||
randomizedBiteSizedDefinitionForSeed,
|
||||
dungeonCanEnter,
|
||||
} from "./dungeonRegistry";
|
||||
import { dungeonLeaderboardCatalog } from "./dungeonLeaderboardCatalog";
|
||||
import { seededBossIndex } from "./dungeons/seededBossSelection";
|
||||
import { activateDungeonSession } from "./dungeonSession";
|
||||
import { createBiteSizedStockadesDefinition } from "./dungeons/biteSizedStockades";
|
||||
import { createRandomizedBiteSizedStockadesDefinition } from "./dungeons/randomizedBiteSizedStockades";
|
||||
@@ -82,13 +89,12 @@ describe("Randomized Bite-Sized Stockades", () => {
|
||||
}
|
||||
});
|
||||
|
||||
it("uses independent deterministic trash and boss rolls across run ids", () => {
|
||||
it("uses deterministic cross-dungeon trash and bosses across run ids", () => {
|
||||
const first = create("shared-run");
|
||||
const second = create("shared-run");
|
||||
expect(second.staticSpawns).toEqual(first.staticSpawns);
|
||||
expect(second.bosses).toEqual(first.bosses);
|
||||
|
||||
const bossEntityIds = new Set(catalog.filter((candidate) => candidate.kind === "boss").map((candidate) => candidate.entityId));
|
||||
const observedBossEntityIds = new Set<string>();
|
||||
const observedTrashLineups = new Set<string>();
|
||||
for (let index = 0; index < 2_000; index += 1) {
|
||||
@@ -101,28 +107,48 @@ describe("Randomized Bite-Sized Stockades", () => {
|
||||
.map((spawn) => spawn.entityId)
|
||||
.join("|"));
|
||||
}
|
||||
expect([...observedBossEntityIds].every((entityId) => bossEntityIds.has(entityId))).toBe(true);
|
||||
expect(observedBossEntityIds.size).toBeGreaterThan(100);
|
||||
expect([...observedBossEntityIds].every((entityId) => catalog.some((candidate) => candidate.kind === "boss" && candidate.entityId === entityId))).toBe(true);
|
||||
expect(observedBossEntityIds.size).toBeGreaterThan(50);
|
||||
expect(observedTrashLineups.size).toBeGreaterThan(1_900);
|
||||
|
||||
expect(activateDungeonSession(RANDOMIZED_BITE_SIZED_STOCKADES_DUNGEON_ID, undefined, { runId: "shared-run" })).toBe(true);
|
||||
expect(dungeonDefinitionById(RANDOMIZED_BITE_SIZED_STOCKADES_DUNGEON_ID)?.staticSpawns).toEqual(first.staticSpawns);
|
||||
});
|
||||
|
||||
it("keeps the randomized boss on the location's stable completion objective", () => {
|
||||
it("uses the selected cross-dungeon boss for combat and completion", () => {
|
||||
const randomized = create("random-boss-objective");
|
||||
const boss = randomized.bosses[0];
|
||||
const spawn = randomized.staticSpawns.find((candidate) => candidate.id === boss.id)!;
|
||||
const entity = randomized.entities[spawn.entityId];
|
||||
const base = createBiteSizedStockadesDefinition(source, "random-boss-objective:objective-slot");
|
||||
const originalSpawn = base.staticSpawns.find((candidate) => candidate.id === boss.id)!;
|
||||
const originalBoss = base.entities[originalSpawn.entityId];
|
||||
const candidate = catalog.find((entry) => `randomized:${entry.key}` === boss.id)!;
|
||||
|
||||
expect(entity.kind).toBe("boss");
|
||||
expect(boss.name).toBe(entity.name);
|
||||
expect(catalog.some((candidate) => candidate.kind === "boss" && candidate.entityId === spawn.entityId)).toBe(true);
|
||||
expect(entity.combat?.serverEntry).not.toBe(originalBoss.combat?.serverEntry);
|
||||
expect(candidate.kind).toBe("boss");
|
||||
expect(entity.combat?.serverEntry).toBe(candidate.definition.combat?.serverEntry);
|
||||
expect(randomized.encounters?.[0].rules[0].trigger).toEqual({ kind: "entities-dead", entityIds: [boss.id] });
|
||||
expect(entity.combat).toMatchObject({ healthMultiplier: 1, damageMultiplier: 1 });
|
||||
expect(entity.combat?.healthMultiplier).toBe(1);
|
||||
});
|
||||
|
||||
it("keeps both selectable pools available and excludes unavailable source dungeons", () => {
|
||||
expect(BITE_SIZED_RANDOMIZED_CREATURE_CATALOG.length).toBeGreaterThan(12);
|
||||
expect(AVAILABLE_RANDOMIZED_CREATURE_CATALOG.length).toBeGreaterThan(BITE_SIZED_RANDOMIZED_CREATURE_CATALOG.length);
|
||||
const allKeys = new Set(AVAILABLE_RANDOMIZED_CREATURE_CATALOG.map((entry) => entry.key));
|
||||
expect(BITE_SIZED_RANDOMIZED_CREATURE_CATALOG.every((entry) => allKeys.has(entry.key))).toBe(true);
|
||||
expect(AVAILABLE_RANDOMIZED_CREATURE_CATALOG.every((entry) => dungeonCanEnter(entry.sourceDungeonId))).toBe(true);
|
||||
for (const [dungeonId, pool] of [
|
||||
[RANDOMIZED_BITE_SIZED_STOCKADES_DUNGEON_ID, AVAILABLE_RANDOMIZED_CREATURE_CATALOG],
|
||||
[RANDOMIZED_BITE_SIZED_AVAILABLE_DUNGEON_ID, BITE_SIZED_RANDOMIZED_CREATURE_CATALOG],
|
||||
] as const) {
|
||||
const definition = randomizedBiteSizedDefinitionForSeed("shared-pool-seed", dungeonId);
|
||||
expect(definition.id).toBe(dungeonId);
|
||||
expect(definition.staticSpawns.every((spawn) => pool.some((entry) => (
|
||||
entry.kind === "boss" ? entry.entityId === spawn.entityId : `randomized:${entry.key}` === spawn.entityId
|
||||
)))).toBe(true);
|
||||
expect(definition.bosses[0].id).toMatch(/^randomized:(wow|rom):boss:/);
|
||||
const board = dungeonLeaderboardCatalog.dungeons.find((entry) => entry.id === dungeonId)!;
|
||||
const finalBossIds = board.difficulties[0].finalBossIds!;
|
||||
expect(definition.bosses[0].id).toBe(finalBossIds[seededBossIndex("shared-pool-seed:boss", finalBossIds.length)]);
|
||||
}
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user