import { requireDungeonDefinition } from "./dungeonRegistry"; import { dispatchActiveDungeonInteraction, dispatchDungeonEncounterSignal, exportDungeonEncounterSnapshots, } from "./dungeonEncounterRuntime"; import { combatHasLineOfSight } from "./combatSpatial"; import { nearestDungeonWorldInteraction, type DungeonWorldObjectDefinition, type DungeonWorldInteractionCandidate, } from "./dungeonWorldObjects"; import type { MobVector3 } from "./mobPopulation"; import { onlinePlayerActorId, onlineSessionLocalAccountId, requestOnlineInteraction, } from "./onlineSessionRuntime"; import { useGameStore } from "./store"; export function activeDungeonWorldObjectStates(): Readonly> { const game = useGameStore.getState(); const states: Record = {}; for (const snapshot of exportDungeonEncounterSnapshots(game.activeDungeonId)) { Object.assign(states, snapshot.worldObjectStates); } return states; } export function activeDungeonInteractionCandidate(): DungeonWorldInteractionCandidate | null { const game = useGameStore.getState(); return dungeonInteractionCandidateAt(game.playerPosition); } export function dungeonInteractionCandidateAt(origin: MobVector3): DungeonWorldInteractionCandidate | null { const game = useGameStore.getState(); if (game.gameMode !== "dungeon") return null; const definition = requireDungeonDefinition(game.activeDungeonId); return nearestDungeonWorldInteraction( definition.serverGameObjects, activeDungeonWorldObjectStates(), origin, combatHasLineOfSight, ); } export function dispatchDungeonWorldObjectInteraction( object: DungeonWorldObjectDefinition, actorId: string | undefined, now: number, ): void { dispatchActiveDungeonInteraction(object.id, actorId, now); dispatchDungeonEncounterSignal(object.interaction!.signalId, now); } /** Followers request; the party leader validates and mutates the shared encounter. */ export function interactWithActiveDungeonObject(now = Date.now()): boolean { const candidate = activeDungeonInteractionCandidate(); if (!candidate) return false; if (requestOnlineInteraction("interact", candidate.object.id)) return true; const localAccountId = onlineSessionLocalAccountId(); const actorId = localAccountId ? onlinePlayerActorId(localAccountId) : undefined; dispatchDungeonWorldObjectInteraction(candidate.object, actorId, now); return true; }