Files
healer-man/src/game/runewakerCompletion.ts
2026-09-13 11:07:56 -04:00

39 lines
2.0 KiB
TypeScript

import type { DungeonDefinition } from "./dungeonTypes";
import type { DungeonEncounterDefinition } from "./dungeonEncounterTypes";
/** Authored completion bookkeeping, independent of reviewed RoM encounter scripts. */
export function withRunewakerCompletion(definition: DungeonDefinition): DungeonDefinition {
if (definition.expansion !== "runewaker" || definition.bosses.length === 0) return definition;
const objectives = [...new Map([...definition.objectiveOrder, ...definition.bosses]
.map((objective) => [objective.id, objective] as const)).values()];
const encounter: DungeonEncounterDefinition = {
id: `${definition.id}:completion-baseline`,
dungeonId: definition.id,
initialPhase: "running",
initialState: { flags: { "dungeon-complete": false } },
source: {
fidelity: "healer-man-authored", scope: "instance-orchestration",
files: ["src/game/runewakerCompletion.ts"],
reviewedBehavior: "Records defeated dungeon bosses and completes the required objectives.",
adaptations: ["Completion bookkeeping uses runtime spawn ids and persists across checkpoints."],
remainingGaps: [],
},
rules: [
...objectives.filter((objective) => !objective.eventOnly).map((objective) => ({
id: `defeated:${objective.id}`,
trigger: { kind: "entities-dead" as const, entityIds: [objective.id] },
actions: [{ id: `record:${objective.id}`, kind: "complete-objective" as const,
objectiveId: objective.id, persistence: "run" as const }],
})),
{
id: "complete", trigger: { kind: "tick" },
guards: objectives.filter((objective) => !objective.optional).map((objective) => ({
kind: "objective-complete", objectiveId: objective.id, equals: true,
})),
actions: [{ id: "complete", kind: "set-flag", flagId: "dungeon-complete", value: true, persistence: "run" }],
},
],
};
return { ...definition, encounters: [...definition.encounters ?? [], encounter] };
}