80 lines
3.1 KiB
TypeScript
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;
|
|
}
|