Update Healer Man server
This commit is contained in:
1 parent
daa417ec17
commit
8b9c95b24f
3 files changed
+49
-6
No files matched your search
@@ -34,8 +34,9 @@ describe("bite-sized Stormwind Stockades", () => {
|
||||
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"]);
|
||||
expect(biteSized.navigationLinks).toEqual(source.navigationLinks);
|
||||
expect(biteSized.traversalRamps).toEqual(source.traversalRamps);
|
||||
expect(biteSized.roamingPacks).toEqual([]);
|
||||
});
|
||||
|
||||
it("seals both side wings with visible movement and sight blockers", () => {
|
||||
|
||||
@@ -133,8 +133,10 @@ export function createBiteSizedStockadesDefinition(
|
||||
roamingPacks: [],
|
||||
bosses: [boss],
|
||||
objectiveOrder: [boss],
|
||||
navigationLinks: source.navigationLinks.filter((link) => link.id === "entrance-to-central-stairs"),
|
||||
traversalRamps: source.traversalRamps?.filter((ramp) => ramp.id === "entrance-stair-ramp"),
|
||||
// Keep the complete reviewed Stockades navigation graph connected. The
|
||||
// physical branch walls, not navmesh pruning, close the unused wings.
|
||||
navigationLinks: source.navigationLinks,
|
||||
traversalRamps: source.traversalRamps,
|
||||
encounters: [{
|
||||
id: `${BITE_SIZED_STOCKADES_DUNGEON_ID}:boss-progression`,
|
||||
dungeonId: BITE_SIZED_STOCKADES_DUNGEON_ID,
|
||||
@@ -147,8 +149,8 @@ export function createBiteSizedStockadesDefinition(
|
||||
files: ["src/game/dungeons/biteSizedStockades.ts"],
|
||||
reviewedBehavior: "A single seeded Stockades boss completes the bite-sized run in the first boss room.",
|
||||
adaptations: [
|
||||
"Each seeded run retains the selected source boss objective ID so saves, loot, guides, and leaderboards report the correct variant.",
|
||||
"The two side-wing stairs are permanently sealed and omitted from party navigation.",
|
||||
"Each seeded run retains the selected source boss objective ID so saves, loot, guides, and leaderboards report the correct variant.",
|
||||
"The side-wing stairs retain their navigation bridges so the central route stays on the retained navmesh component; physical walls seal both unused wings.",
|
||||
],
|
||||
remainingGaps: [],
|
||||
},
|
||||
|
||||
@@ -29,7 +29,9 @@ const STOCKADES_NAVIGATION = "public/assets/game/manastorm/34-stormwindjail/navi
|
||||
const TANK_RANGE = Object.freeze({ minimum: 0, preferred: 2.9, maximum: 3.15 });
|
||||
|
||||
const stockades = requireDungeonDefinition("stormwind-stockade");
|
||||
const biteSizedStockades = requireDungeonDefinition("bite-sized-stormwind-stockade");
|
||||
let graph: PartyNavigationGraph;
|
||||
let biteSizedGraph: PartyNavigationGraph;
|
||||
let sourceCollision: Group;
|
||||
|
||||
beforeAll(async () => {
|
||||
@@ -64,6 +66,10 @@ beforeAll(async () => {
|
||||
graph = preparePartyNavigationGraph(
|
||||
"/test/stockades-navigation.glb", scene, stockades.navigationLinks, stockades.traversalRamps,
|
||||
);
|
||||
biteSizedGraph = preparePartyNavigationGraph(
|
||||
"/test/bite-sized-stockades-navigation.glb", scene,
|
||||
biteSizedStockades.navigationLinks, biteSizedStockades.traversalRamps,
|
||||
);
|
||||
geometry.dispose();
|
||||
|
||||
const collisionDocument = await new NodeIO()
|
||||
@@ -256,6 +262,40 @@ describe("Stormwind Stockade party navigation", () => {
|
||||
expect(graph.triangleNodes?.length).toBe(graph.triangles?.length);
|
||||
});
|
||||
|
||||
it("keeps the bite-sized entrance and boss room on the retained navigation surface", () => {
|
||||
const world = collisionWorld();
|
||||
try {
|
||||
for (const wall of biteSizedStockades.serverGameObjects.filter((object) => object.id.startsWith("bite-sized-"))) {
|
||||
world.createCollider(RAPIER.ColliderDesc.cuboid(...wall.halfExtents)
|
||||
.setTranslation(...wall.position)
|
||||
.setCollisionGroups(DUNGEON_PHYSICAL_COLLISION_GROUPS));
|
||||
}
|
||||
world.step();
|
||||
const entrance = findNearestPartyNavigationSurface(
|
||||
biteSizedGraph,
|
||||
biteSizedStockades.entrance.footPosition,
|
||||
6,
|
||||
);
|
||||
const boss = findNearestPartyNavigationSurface(
|
||||
biteSizedGraph,
|
||||
biteSizedStockades.bosses[0].position,
|
||||
15,
|
||||
);
|
||||
expect(entrance).not.toBeNull();
|
||||
expect(boss).not.toBeNull();
|
||||
expect(findPartyNavigationPath(
|
||||
biteSizedGraph,
|
||||
entrance!.position,
|
||||
boss!.position,
|
||||
{
|
||||
maxStartSnapDistance: 0.1,
|
||||
maxEndSnapDistance: 0.1,
|
||||
routeSegmentAllowed: createPartyRouteSegmentValidator(RAPIER, world),
|
||||
},
|
||||
)).not.toBeNull();
|
||||
} finally { world.free(); }
|
||||
});
|
||||
|
||||
it("projects every entrance formation slot onto the retained walkable surface", () => {
|
||||
const slots = derivePartySpawnSlots({
|
||||
footPosition: stockades.entrance.footPosition,
|
||||
|
||||
Reference in new issue
Block a user