66 lines
2.4 KiB
TypeScript
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;
|
|
}
|