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; }