import type { EntityPosition } from "../scene/entityStore.js"; import { type EntityColliderSet } from "../scene/colliders.js"; import type { Aim } from "../scene/spatial.js"; /** * How a shot's world-space origin (and optional direction) is resolved before prediction/settlement. * - `converge` — the shot leaves the gun `muzzle` yet still passes through whatever the shooter's * sightline (crosshair) covers: origin is the muzzle offset, direction is bent from the muzzle to * the eye ray's aim point. The projectile system's default for a free `{ yaw, pitch }` aim, so a * bullet visibly comes from the barrel without missing the reticle. Needs a scene raycast to find * the aim point (`convergeShot`); a bare `resolveShot` degrades to a straight muzzle ray. Passes an * explicit `{ origin, direction }` aim through untouched. * - `eye` — `aim.origin` when present, else the shooter's entity position raised to eye height; the * shot traces the shooter's sightline, so what the crosshair covers is what gets hit. * - `legacy` — `aim.origin` when present, else the shooter's raw entity position (feet). * - `entity` — always the shooter's entity position. * - `entityOffset` / `muzzle` — entity-local offset rotated by the shooter's yaw (muzzle on a weapon model). * - `camera` — explicit camera/reticle world origin (and optional direction override). * - `world` — absolute world origin. */ export type ShotOriginPolicy = { kind: "converge"; muzzle?: EntityPosition; height?: number; } | { kind: "eye"; height?: number; } | { kind: "legacy"; } | { kind: "entity"; } | { kind: "entityOffset"; offset: EntityPosition; } | { kind: "muzzle"; offset?: EntityPosition; } | { kind: "camera"; origin: EntityPosition; direction?: EntityPosition; } | { kind: "world"; origin: EntityPosition; direction?: EntityPosition; }; /** * A shot's resolved firing geometry in world space: `origin` is the point the projectile/ray starts * from and `direction` is its normalized aim vector, both computed by {@link resolveShot} from the * shooter's position, facing, and the chosen origin policy. */ export interface ResolvedShot { origin: EntityPosition; direction: EntityPosition; } export interface ShotOriginDeps { positionOf(instanceId: string): EntityPosition | undefined; rotationYOf?(instanceId: string): number | undefined; /** When provided, the `eye` policy sizes its height from the shooter's own hitbox instead of the humanoid default. */ collidersOf?(instanceId: string): EntityColliderSet | null | undefined; } /** Shot-origin and first-person camera eye height above an entity's position: 90% of the default 1.8m hitbox top. */ export declare const DEFAULT_EYE_HEIGHT: number; /** Eye height derived from a collider set: 90% of the tallest hitbox top, or the humanoid default when unknown. */ export declare function eyeHeightFromColliders(set: EntityColliderSet | null | undefined): number; export declare function aimDirection(aim: Aim): EntityPosition | null; export declare function aimSpreadDeg(aim: Aim): number; /** * Resolves a shot's world origin and direction from the shooter's eye or muzzle and an {@link Aim}, ready for * `ctx.scene.raycast` — the aim half of a hitscan weapon. * * @capability hitscan-shot aim a hitscan shot (shoot a gun): resolve origin and direction from the eye or muzzle for a raycast */ export declare function resolveShot(deps: ShotOriginDeps, from: string, aim: Aim, policy?: ShotOriginPolicy): ResolvedShot | null; /** * Resolves a `converge` shot with scene knowledge: fires from the gun muzzle but bends the direction * so the shot passes through the aim point the shooter's eye ray covers. `sightHit` casts the eye ray * and returns where it lands (first impact), or `null` to fall back to a point `range` metres down the * sightline. A `{ origin, direction }` aim is passed through unchanged (nothing to converge). */ export declare function convergeShot(deps: ShotOriginDeps, from: string, aim: Aim, range: number, sightHit: (origin: EntityPosition, direction: EntityPosition) => EntityPosition | null, muzzleOffset?: EntityPosition): ResolvedShot | null;