import type { CameraRigKind, ChaseCameraConfig, ChaseView, CinematicCameraConfig, GameCameraConfig } from "../game/playableGame.js"; import type { GameContext } from "./gameContext.js"; /** Data overlay for an existing rig; callbacks and Canvas projection/preferences remain configured by the game. */ export type CameraRigConfig = Omit; /** Runtime rig selection and detached data overlay over the configured camera. */ export interface CameraRigOverride { kind: CameraRigKind; config: CameraRigConfig; } /** Camera policy state before the JSON-safe snapshot number encoding. */ export interface CameraDirectorState { followEntityId?: string | null; rig: CameraRigOverride | null; cinematic: CinematicCameraConfig | null; chase: ChaseCameraTuning | null; } type CameraSerialized = T extends number ? number | { $cameraNumber: "Infinity"; } : T extends object ? { [Key in keyof T]: CameraSerialized; } : T; /** JSON-safe camera policy; documented instant chase responses use an explicit Infinity marker. */ export type CameraDirectorSnapshot = CameraSerialized; /** @internal */ export declare function validateCameraRig(kind: CameraRigKind, config?: CameraRigConfig): void; /** @internal */ export declare function validateChaseCameraTuning(tuning: ChaseCameraTuning | null): void; /** Runtime patch over the static `camera.chase` config — distance/height/fov retuning from gameplay events (#286.11), a whole driving-feel overlay applied only while a vehicle is piloted (#1299), or a `view` switch between chase and seat cameras. */ export type ChaseCameraTuning = Partial>; /** Default order {@link nextChaseView} cycles through. */ export declare const CHASE_VIEWS: readonly ChaseView[]; /** * The view after `current` in `views`, wrapping at the end; a view missing from the list starts the cycle over. * Pair with `setChaseTuning` to bind a "change camera" key: * `ctx.camera.setChaseTuning({ ...ctx.camera.chaseTuning(), view: nextChaseView(view) })`. * * @capability chase-view-cycle cycle a vehicle camera between chase, hood and cockpit views at runtime */ export declare function nextChaseView(current: ChaseView, views?: readonly ChaseView[]): ChaseView; export interface CameraDirector { follow(entityId: string | null): void; /** `undefined` means no runtime override — the shell falls back to the static `playable.camera.followEntityId`. `null` means explicitly follow nothing. */ followedEntityId(): string | null | undefined; /** Replace the runtime rig overlay; `null` restores the game's configured rig/config. Existing chase tuning remains independent. */ setRig(kind: CameraRigKind | null, config?: CameraRigConfig): void; rig(): CameraRigOverride | null; setCinematic(config: CinematicCameraConfig | null): void; cinematic(): CinematicCameraConfig | null; /** Overlay a runtime patch on the chase rig's config — a boss-intro pull-back, drift zoom-out; `null` restores the static config. */ setChaseTuning(tuning: ChaseCameraTuning | null): void; chaseTuning(): ChaseCameraTuning | null; /** Add a transient FOV impulse in degrees (a landing, a hit, a boost) that the chase rig layers on and decays per `camera.chase.fovKick`. Kicks from one frame sum. */ kickFov(degrees: number): void; /** Drain the FOV impulses queued since the last call; the shell's chase rig calls this once per frame. */ takeFovKick(): number; snapshot(): CameraDirectorSnapshot; /** Invalid state throws before changing any camera field. */ restore(state: CameraDirectorSnapshot): void; /** Clear runtime policy and transient FOV kicks; configured camera data remains untouched. */ reset(): void; subscribe(listener: () => void): () => void; } /** @internal */ export declare function createCameraDirector(): CameraDirector; /** Local camera policy is saved, never broadcast to another player's presentation. @internal */ export declare function installCameraPersistence(ctx: GameContext): void; export {};