Files
healer-man/src/game/dungeonWorldInteraction.ts
T
2026-09-08 10:40:26 -04:00

66 lines
2.4 KiB
TypeScript

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<Record<string, string>> {
const game = useGameStore.getState();
const states: Record<string, string> = {};
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;
}