Release Healer Man 0.1.59

This commit is contained in:
phenom committed 2026-09-27 10:16:42 -04:00
1 parent 11934a3979
commit ab1434a3b8
44 files changed
+1242 -103

No files matched your search

@@ -12,6 +12,11 @@ const sliceIds = [
"bite-sized-forsaken-abbey-ancalon",
"bite-sized-paspers-shrine-hafiz",
"bite-sized-mystic-altar-golem",
"bite-sized-grafu-castle-barkud",
"bite-sized-barren-caves-anglo",
"bite-sized-hoto-teeth",
"bite-sized-kawaks-tomb-linobia",
"bite-sized-hall-of-survivors-pursuer",
] as const;
describe("RoM bite-sized finales", () => {
@@ -43,7 +48,8 @@ describe("RoM bite-sized finales", () => {
expect(source).toBeDefined();
expect(dungeonContentPackId(id)).toBe(`dungeon:${source.id}`);
expect(slice.assets).toBe(source.assets);
expect(slice.staticSpawns).toHaveLength(6);
expect(slice.staticSpawns).toHaveLength(id === "bite-sized-barren-caves-anglo" ? 4
: id === "bite-sized-kawaks-tomb-linobia" || id === "bite-sized-hall-of-survivors-pursuer" ? 5 : 6);
expect(slice.staticSpawns.every((spawn) => source.staticSpawns.includes(spawn))).toBe(true);
expect(slice.bosses).toHaveLength(1);
expect(slice.bosses[0].eventOnly).toBe(true);
@@ -65,7 +71,7 @@ describe("RoM bite-sized finales", () => {
expect(completed.flags["dungeon-complete"]).toBe(true);
expect(completed.phase).toBe("complete");
// The complete source remains available with its original population and objectives.
expect(source.bosses.length).toBeGreaterThan(1);
expect(source.bosses.length).toBeGreaterThanOrEqual(1);
expect(slice.presentation.ambientLight.intensity).toBeGreaterThan(source.presentation.ambientLight.intensity);
expect(slice.presentation.hemisphereLight.intensity).toBeGreaterThan(source.presentation.hemisphereLight.intensity);
});
+116 -3
View File
@@ -9,6 +9,11 @@ import {
BITE_SIZED_FORSAKEN_ABBEY_DUNGEON_ID,
BITE_SIZED_MYSTIC_ALTAR_DUNGEON_ID,
BITE_SIZED_PASPERS_SHRINE_DUNGEON_ID,
BITE_SIZED_GRAFU_CASTLE_DUNGEON_ID,
BITE_SIZED_BARREN_CAVES_DUNGEON_ID,
BITE_SIZED_HOTO_DUNGEON_ID,
BITE_SIZED_KAWAKS_TOMB_DUNGEON_ID,
BITE_SIZED_HALL_OF_SURVIVORS_DUNGEON_ID,
} from "../dungeonContentSource";
import { seededBossIndex } from "./seededBossSelection";
@@ -24,6 +29,7 @@ interface RoMSlice {
readonly mobSpawnIds: readonly string[];
readonly summary: string;
readonly adaptation: string;
readonly lighting?: { readonly ambient: number; readonly hemisphere: number; readonly directional: number };
}
const ROM_SLICES: readonly RoMSlice[] = [
@@ -80,6 +86,91 @@ const ROM_SLICES: readonly RoMSlice[] = [
summary: "Clear the guards, beetles, and Morcus beasts before one surprise Altar boss.",
adaptation: "Dorlos, the earlier altar route, and the remaining beetle swarm are outside this short run.",
},
{
sourceId: "grafu-castle",
id: BITE_SIZED_GRAFU_CASTLE_DUNGEON_ID,
title: "Grafu Castle: Late Gallery",
location: "Grafu Castle · Barkud's Gallery",
entranceName: "Barkud's Gallery",
start: [-78.5, -40.2, -133.98],
forward: [1, 0, 0],
finaleBossName: "Larvanger Barkud",
mobSpawnIds: [
"rw-grafu-castle-spawn-41927461", "rw-grafu-castle-spawn-41927502",
"rw-grafu-castle-spawn-41927501", "rw-grafu-castle-spawn-41927460",
"rw-grafu-castle-spawn-41927499", "rw-grafu-castle-spawn-41927498",
],
summary: "Clear the clowns and steel soldiers in the late gallery, then defeat one surprise Castle boss.",
adaptation: "Chapeaunoir, earlier bosses, side branches, and patrol scripts are outside this late-gallery run.",
},
{
sourceId: "barren-caves",
id: BITE_SIZED_BARREN_CAVES_DUNGEON_ID,
title: "Barren Caves: Last Bend",
location: "Barren Caves · Anglo's Bend",
entranceName: "Anglo's Bend",
start: [-20, -0.1, 75],
forward: [0, 0, -1],
finaleBossName: "Anglo",
mobSpawnIds: [
"rw-barren-caves-spawn-5951185", "rw-barren-caves-spawn-5951182",
"rw-barren-caves-spawn-5951181", "rw-barren-caves-spawn-5951183",
],
summary: "Clear the last kobold bend, then defeat Anglo.",
adaptation: "The earlier cave loop is outside this short run; Anglo is the source dungeon's only boss.",
lighting: { ambient: 0.48, hemisphere: 0.65, directional: 0.85 },
},
{
sourceId: "hoto",
id: BITE_SIZED_HOTO_DUNGEON_ID,
title: "Hoto: Reef Approach",
location: "Hoto · Teeth of the Reef Approach",
entranceName: "Reef Approach",
start: [114.160107, -33.598026, 64.647491],
forward: [0.70710678, 0, -0.70710678],
finaleBossName: "Teeth of the Reef",
mobSpawnIds: [
"rw-hoto-spawn-5978485", "rw-hoto-spawn-5978483",
"rw-hoto-spawn-5978486", "rw-hoto-spawn-5978484",
"rw-hoto-spawn-5978631", "rw-hoto-spawn-5979808",
],
summary: "Clear the Ayam guards, casters, and defenders, then defeat one surprise Hoto boss.",
adaptation: "Jiasha, earlier boss rooms, and unrelated Hoto population are outside this short run.",
},
{
sourceId: "kawaks-tomb",
id: BITE_SIZED_KAWAKS_TOMB_DUNGEON_ID,
title: "Kawak's Tomb: Scorpion Passage",
location: "Kawak's Tomb · Linobia's Passage",
entranceName: "Linobia's Passage",
start: [-85, -9.4, -243],
forward: [-1, 0, 0],
finaleBossName: "Linobia",
mobSpawnIds: [
"rw-kawaks-tomb-spawn-41889142", "rw-kawaks-tomb-spawn-41889139",
"rw-kawaks-tomb-spawn-41892423", "rw-kawaks-tomb-spawn-41890637",
"rw-kawaks-tomb-spawn-41889112",
],
summary: "Clear the scorpions, beetles, and scarab, then defeat Linobia.",
adaptation: "The earlier tomb route is outside this short run; Linobia is the source dungeon's only boss.",
},
{
sourceId: "hall-of-survivors",
id: BITE_SIZED_HALL_OF_SURVIVORS_DUNGEON_ID,
title: "Hall of Survivors: Pursuer Ward",
location: "Hall of Survivors · Pursuer Ward",
entranceName: "Pursuer Ward",
start: [-155, -17.55, 35],
forward: [-1, 0, 0],
finaleBossName: "Divine Punishment Pursuer",
mobSpawnIds: [
"rw-hall-of-survivors-spawn-11962803", "rw-hall-of-survivors-spawn-11962817",
"rw-hall-of-survivors-spawn-5991940", "rw-hall-of-survivors-spawn-5991941",
"rw-hall-of-survivors-spawn-5991939",
],
summary: "Clear the hunters and Rune Guardians, then defeat one surprise Hall boss.",
adaptation: "The other Pursuer and Seeker bosses, earlier rooms, and their combined source scripts are outside this short run.",
},
];
function createRoMSlice(source: DungeonDefinition, slice: RoMSlice, seed: string): DungeonDefinition {
@@ -161,9 +252,11 @@ function createRoMSlice(source: DungeonDefinition, slice: RoMSlice, seed: string
presentation: { ...source.presentation, location: slice.location, theme: "Bite-Sized Dungeon",
summary: slice.summary, loadingMessage: `Entering ${slice.entranceName}...`,
unchartedAreaName: slice.entranceName,
ambientLight: { color: "#e2dccc", intensity: 0.9 },
hemisphereLight: { skyColor: "#ded9d0", groundColor: "#5a5350", intensity: 1.2 },
directionalLight: { ...source.presentation.directionalLight, color: "#fff0d9", intensity: 1.35 } },
ambientLight: { color: "#e2dccc", intensity: slice.lighting?.ambient ?? 0.9 },
hemisphereLight: { skyColor: "#ded9d0", groundColor: "#5a5350", intensity: slice.lighting?.hemisphere ?? 1.2 },
directionalLight: { ...source.presentation.directionalLight,
color: slice.lighting ? source.presentation.directionalLight.color : "#fff0d9",
intensity: slice.lighting?.directional ?? 1.35 } },
areas,
entities,
staticSpawns: mobSpawns,
@@ -190,3 +283,23 @@ export function createBiteSizedPaspersShrineDefinition(source: DungeonDefinition
export function createBiteSizedMysticAltarDefinition(source: DungeonDefinition, seed: string): DungeonDefinition {
return createRoMSlice(source, ROM_SLICES[2], seed);
}
export function createBiteSizedGrafuCastleDefinition(source: DungeonDefinition, seed: string): DungeonDefinition {
return createRoMSlice(source, ROM_SLICES[3], seed);
}
export function createBiteSizedBarrenCavesDefinition(source: DungeonDefinition, seed: string): DungeonDefinition {
return createRoMSlice(source, ROM_SLICES[4], seed);
}
export function createBiteSizedHotoDefinition(source: DungeonDefinition, seed: string): DungeonDefinition {
return createRoMSlice(source, ROM_SLICES[5], seed);
}
export function createBiteSizedKawaksTombDefinition(source: DungeonDefinition, seed: string): DungeonDefinition {
return createRoMSlice(source, ROM_SLICES[6], seed);
}
export function createBiteSizedHallOfSurvivorsDefinition(source: DungeonDefinition, seed: string): DungeonDefinition {
return createRoMSlice(source, ROM_SLICES[7], seed);
}