/** One hit zone: what a hit there multiplies, and how much likelier it is to crit. */ export interface HitZoneDef { id: string; /** Multiplier for a hit in this zone that does not crit. Default `1`. */ multiplier?: number; /** Added to the table's base crit chance for hits in this zone. Default `0`. */ critChance?: number; /** Crit multiplier in this zone; defaults to the table's `critMultiplier`. */ critMultiplier?: number; } /** * A serializable hit-zone table: where a hit landed, what that multiplies, and the table's base crit * chance and multiplier. A generated gun or a weapon runtime passes its own zones in; the engine has * no built-in headshot. */ export interface HitZoneTable { zones: readonly HitZoneDef[]; /** Zone used when a caller names one the table does not list. Must appear in `zones`. */ defaultZone: string; /** Base crit chance in `[0,1]`. Default `0`. */ critChance?: number; /** Base crit multiplier. Default `2`. */ critMultiplier?: number; } /** One resolved zone: where the hit landed, whether it crit, and the single multiplier to apply. */ export interface HitZoneResolution { zone: string; crit: boolean; /** * The one multiplier this hit earns. A crit *replaces* the zone's normal multiplier instead of * compounding with it, so a headshot crit can never silently become zone × crit. */ multiplier: number; /** The crit draw, or `null` when the chance was zero and no draw was taken. */ roll: number | null; /** True when the named zone was absent from the table and `defaultZone` was used. */ fallback: boolean; } /** Raised when neither the named zone nor the table's `defaultZone` exists — a data error, not a 1× hit. * @capability hit-zone-unknown reject a hit zone table whose named default does not exist */ export declare class UnknownHitZoneError extends Error { readonly zone: string; constructor(zone: string); } /** Default crit multiplier for a zone that does not name one. */ export declare const DEFAULT_CRIT_MULTIPLIER = 2; /** Validate a zone table once at construction: duplicate ids and a missing default fail loudly. * @capability hit-zone-validate reject a hit-zone table with duplicate zones or a missing default */ export declare function assertHitZoneTable(table: HitZoneTable): void; /** * The multiplier a zone earns for a known crit outcome, without rolling. `resolveHitZone` and a * time-to-kill quote both read through this, so a quoted crit uses the same number combat does. * * @capability hit-zone-multiplier quote a zone's multiplier for a known crit outcome without rolling */ export declare function hitZoneMultiplier(table: HitZoneTable, zone: string | undefined, crit: boolean): { zone: string; multiplier: number; fallback: boolean; }; /** * Resolve where a hit landed into one multiplier: roll the crit chance for that zone, and apply the * crit multiplier when it lands, otherwise the zone's own multiplier. The injected `rng` keeps the * roll reproducible; a zero chance draws nothing, so a deterministic test can force either outcome. * * @capability hit-zone resolve a hit zone into one damage multiplier, crit by zone with an injected RNG */ export declare function resolveHitZone(table: HitZoneTable, zone: string | undefined, rng?: () => number): HitZoneResolution;