Files
healer-man/src/app/dungeonShellRuntime.ts
T
2026-09-09 11:21:33 -04:00

80 lines
3.1 KiB
TypeScript

import { dungeonById } from "../game/dungeonCatalog";
import { activateDungeonSession } from "../game/dungeonSession";
import { useGameStore } from "../game/store";
import {
classCanFillPartyRole,
defaultPartyRoleForClass,
PARTY_ROLE_LABELS,
type PartyRole,
} from "../game/partyRoles";
import { useShellStore } from "./shellStore";
import { registerDungeonShellRuntime } from "./dungeonShellRuntimeBridge";
import { touchCharacter } from "./accountRepository";
import { specializationById } from "../game/specializationCatalog";
import { dungeonContentIsUsable } from "../content/contentManager";
export function installDungeonShellRuntime(): void {
registerDungeonShellRuntime({ enterDungeon });
}
function enterDungeon(dungeonId: string, requestedRole?: PartyRole): boolean {
const dungeon = dungeonById(dungeonId);
if (!dungeon || !dungeon.available) {
useShellStore.setState({ notice: "That dungeon is not available yet." });
return false;
}
if (!dungeonContentIsUsable(dungeonId)) {
useShellStore.setState({ notice: "Install this expedition from Downloads before entering." });
return false;
}
const { session, selectedCharacterId, characters } = useShellStore.getState();
if (!session || !selectedCharacterId) {
useShellStore.setState({ notice: "Select or create a character first." });
return false;
}
const activeCharacter = touchCharacter(session.ownerId, selectedCharacterId)
?? characters.find((character) => character.id === selectedCharacterId)
?? null;
if (!activeCharacter) {
useShellStore.setState({ notice: "That character is no longer available." });
return false;
}
const savedSpecialization = specializationById(activeCharacter.specializationId);
if (activeCharacter.categoryId !== "rom" && !savedSpecialization) {
useShellStore.setState({ phase: "class-hall", notice: "Choose a specialization before entering activities." });
return false;
}
const playerRole = savedSpecialization?.role ?? requestedRole ?? defaultPartyRoleForClass(activeCharacter.classId);
if (savedSpecialization && requestedRole && requestedRole !== savedSpecialization.role) {
useShellStore.setState({ notice: `${savedSpecialization.displayName} is locked to ${PARTY_ROLE_LABELS[savedSpecialization.role]}.` });
return false;
}
if (!classCanFillPartyRole(activeCharacter.classId, playerRole)) {
useShellStore.setState({
notice: `${activeCharacter.name}'s class cannot enter as ${PARTY_ROLE_LABELS[playerRole]}.`,
});
return false;
}
const resume = activeCharacter.dungeonRunCheckpoint?.dungeonId === dungeonId
? activeCharacter.dungeonRunCheckpoint
: null;
if (!activateDungeonSession(dungeonId, resume?.difficultyId, {
spawn: resume?.spawn,
encounterSnapshots: resume?.encounters,
})) {
useShellStore.setState({
notice: dungeon.availabilityReason ?? "That dungeon failed its latest validation gate.",
});
return false;
}
useGameStore.getState().setCompanionOpen(false);
useShellStore.setState({
phase: "game",
activeCharacter,
activeDungeonId: dungeon.id,
activeDungeonRole: playerRole,
notice: "",
});
return true;
}