import type { CollisionEvent } from "./physicsWorld.js"; export interface DamageZoneDef { id: string; thresholds: readonly number[]; detachStage?: number; } export interface DamageZoneState { id: string; accumulated: number; stage: number; detached: boolean; } export interface DamageTransition { zone: string; stage: number; previousStage: number; detached: boolean; disabled: boolean; accumulated: number; total: number; } export interface DamageModelConfig { zones: readonly DamageZoneDef[]; disableAt?: number; onStage?: (transition: DamageTransition) => void; onDetach?: (zoneId: string, accumulated: number) => void; } /** * Coarse crash-damage model (issue #86 — stages, not soft-body). Each zone accumulates contact impulse * fed from G3's `onCollision` `CollisionEvent`; crossing a threshold bumps the zone to the next discrete * stage (the caller swaps the visual/collider), an optional `detachStage` ejects a part as debris once, * and a total-impulse `disableAt` flips the whole body to a disabled state. `absorb` returns a transition * only when something actually changed, so it doubles as the event source for HUD/feed. */ export declare class DamageModel { private readonly zones; private readonly order; private readonly disableAt; private readonly onStage?; private readonly onDetach?; private totalImpulse; private disabledFlag; constructor(config: DamageModelConfig); get total(): number; get disabled(): boolean; stageOf(zoneId: string): number; states(): readonly DamageZoneState[]; absorb(zoneId: string, impulse: number): DamageTransition | null; /** * Route a raw {@link CollisionEvent} into a zone by a caller-supplied selector (front/rear/side from * `nx`/`nz`, or which body index took the hit). The event's `impulse` feeds `absorb`. */ routeCollision(event: CollisionEvent, resolveZone: (event: CollisionEvent) => string | null): DamageTransition | null; reset(): void; } export declare function createDamageModel(config: DamageModelConfig): DamageModel;