@adatechnology/game-vehicles-three 0.8.2 → 0.8.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/test-area/module.ts","../src/build.ts","../src/lite.ts","../src/vehicle-lod.ts","../src/cabin-smoke.ts","../src/test-area/lane-damage.ts","../src/test-area/scenarios.ts","../src/test-area/text.ts","../src/audio/profiles.ts","../src/test-area/types.ts","../src/audio/engine-mix.ts","../src/audio/vehicle-sound.ts","../src/audio/bank.ts","../src/test-area/proving/module.ts","../src/test-area/proving/cockpit.ts","../src/body.ts","../src/dashboard.ts","../src/lamps.ts","../src/windshield-mist.ts","../src/audio/engine-budget.ts","../src/wheel-roll.ts","../src/test-area/proving/crash.ts","../src/test-area/proving/systems-text.ts","../src/test-area/proving/text.ts"],"sourcesContent":["import type * as THREE_NS from 'three'\nimport { DEFERRED_PRIORITY, DEFERRED_QUEUE_ID, footprintBlocker } from '@adatechnology/game-contracts'\nimport { discardObject3D } from '@adatechnology/game-shapes-three'\nimport type { AnimationClipSpec, Footprint, BenchChange, ModuleArea, ModuleControl, ModuleHost, ModuleLayer, ModuleMetric, ModuleScenario, TestableItem, TestableModule, Vec3 } from '@adatechnology/game-contracts'\nimport { buildVehicleItem, crackedGlassMaterial, createCreaseQueue, createVehicleDestructible, createVehicleKit } from '@adatechnology/game-vehicles'\nimport type { ParticleMaterials, VehicleContext, VehicleItem, VehicleKit } from '@adatechnology/game-vehicles'\nimport { isRenderPools } from '@adatechnology/game-render-three'\nimport { createArcadeDriver, createSemiSimDriver, createSurfaces, vehicleCorners } from '@adatechnology/game-vehicles-driving'\n\nimport { colorFromSeed, fleetDims, installFleet, paintPalettes, paletteOf } from '@adatechnology/game-vehicles-fleet'\n\nimport { createVehiclesThree, primaryPaint } from '../build'\nimport { createVehicleLod } from '../vehicle-lod'\nimport type { VehicleLod } from '../vehicle-lod'\nimport { createCabinSmoke } from '../cabin-smoke'\nimport { createLaneDamage, LANE_DAMAGE } from './lane-damage'\nimport type { LaneDamage } from './lane-damage'\nimport { createScenarios } from './scenarios'\nimport { fill, TEXT } from './text'\nimport { LIBRARY_BANK } from '@adatechnology/game-audio'\nimport { DEFAULT_TEST_WRECKS, defaultEffectIds, defaultSoundIds } from './types'\nimport type { EffectsLike, VehiclesContext, VehiclesTestFleet, VehiclesTestOptions } from './types'\nimport { createVehicleSound } from '../audio/vehicle-sound'\nimport type { VehicleSound } from '../audio/vehicle-sound'\nimport { VEHICLE_PRELOAD_SOUNDS, VEHICLE_SOUND_BANK } from '../audio/bank'\n\nexport const VEHICLES_AREA_ID = 'vehicles_area'\n\n/** The eight vehicles of the Frota test page, in its order, and the item id each one has in the area. */\nexport const DEFAULT_TEST_VEHICLES: readonly string[] = ['compact_hatch', 'midsize_sedan', 'midsize_pickup', 'sport_bike', 'box_truck', 'city_bus', 'battle_tank', 'attack_helicopter']\nconst ITEM_OF: Readonly<Record<string, string>> = { compact_hatch: 'hatch', midsize_sedan: 'sedan', midsize_pickup: 'pickup', sport_bike: 'sport_bike', box_truck: 'box_truck', city_bus: 'city_bus', battle_tank: 'battle_tank', attack_helicopter: 'attack_helicopter' }\nconst itemId = (key: string): string => ITEM_OF[key] ?? key\n\n/** One item of the area: the fleet vehicle it is built from, its item id and, for a wreck, the scenario built into it. */\ntype Entry = { readonly key: string; readonly id: string; readonly scenario?: string }\n\nconst LANE = { z: 11, from: -12, wall: 13 }\n/** A rim on the road throws a burst of sparks this often. */\nconst SPARK_EVERY_S = 0.08\n/** The lane damages of a tyre. */\nconst TYRE_DAMAGE: ReadonlySet<LaneDamage> = new Set<LaneDamage>(['flat_tyre', 'torn_tyre', 'run_flat'])\n/** Radians a door, hood or lid may be off its rest and still count as shut. */\nconst LEAF_REST_RADIANS = 0.02\nconst MATERIAL_COLOURS: Record<string, number> = { metal: 0xcccccc, glass: 0x44aaff, rubber: 0xff9900, fuel: 0xff3300 }\n/** Seconds the lane car idles after the key is turned (the starter and the engine catching) before it pulls away. */\nconst LANE_START_S = 1.2\nconst ZONE_COLOURS: Record<string, number> = { door: 0x55dd55, hood: 0xdddd33, lid: 0xdd9933, bumper: 0xdd55dd, glass: 0x44aaff, light: 0xffffff, wheel: 0xff7733 }\n\ntype Three = typeof THREE_NS\n/** Parts whose bottom is above this (m, from the ground) are overhead: the player walks under them (the helicopter's rotor, the tank's gun). */\nconst BODY_HEIGHT = 1.7\ntype Placed = {\n readonly root: THREE_NS.Group\n readonly key: string\n /** The damage scenario built into a wreck (its size is not the design size, so it is left out of the size error). */\n readonly scenario?: string\n readonly item: VehicleItem\n readonly index: number\n paint?: THREE_NS.MeshStandardMaterial\n /** Near in full, far fused (`createVehicleLod`); none in the light quality, which is fused already. */\n lod?: VehicleLod\n /** Hit: its damage only exists on the full model. */\n touched?: boolean\n /** Leaves away from their rest (an open door): drawn in full while any is. */\n posedParts?: Set<string>\n size?: { length: number; width: number; height: number }\n /** What the walking player bumps into, in the root's own space: the box of the parts low enough to hit a body (a rotor overhead is walked under). */\n footprint?: Footprint\n helpers: THREE_NS.Object3D[]\n}\n\n/**\n * The vehicles test area as a `TestableModule`: the vehicles of the Frota test (hatch, sedan, pickup, sport bike, box truck, city bus, battle tank, attack helicopter), each with its own\n * `DestructibleImpl` and its door, hood and trunk clips, the eleven scenarios of that page (literal) and two for the drivers. The bench sets the quality (full or light mode), the paint\n * by seed and palette, the driving mode and the surface, and shows the damageable boxes by material, the zones by type and the axes of the output frame. Effects (fire, glass, sparks,\n * exhaust) are requested by id through `host.effects` when the host has it; this module draws none.\n */\nexport function createVehiclesTestModule(options: VehiclesTestOptions = {}): TestableModule<VehiclesContext> & { readonly placed: ReadonlyMap<string, unknown> } {\n const fleet: VehiclesTestFleet = options.fleet ?? { colorFromSeed, fleetDims, installFleet, paintPalettes, paletteOf }\n const locale = options.locale ?? 'pt-BR'\n const text = TEXT[locale] ?? (TEXT['pt-BR'] as (typeof TEXT)[string])\n const keys = options.vehicles ?? DEFAULT_TEST_VEHICLES\n const wrecks = options.wrecks ?? DEFAULT_TEST_WRECKS\n const entries: Entry[] = [...keys.map((key): Entry => ({ key, id: itemId(key) })), ...wrecks.map((w): Entry => ({ key: w.vehicle, id: w.key, scenario: w.scenario }))]\n const effectIds = { ...defaultEffectIds, ...options.effects }\n const soundIds = { ...defaultSoundIds, ...options.sounds }\n const settings = { quality: 'high', paint: false, seed: 1, palette: 'auto', driving: 'arcade', surface: 'dry_asphalt', damage: 'none' as LaneDamage }\n const kits = new WeakMap<object, VehicleKit>()\n const placed = new Map<string, Placed>()\n // the cabins hold the room's smoke out: through a shut car it does not pass, it gets in only by an open door, a broken window or a bullet hole\n const cabins = createCabinSmoke()\n let host: ModuleHost | null = null\n let three: Three | null = null\n let counter = 0\n let helpersShown = ''\n let axes: THREE_NS.Object3D[] = []\n let lane: Lane | null = null\n\n type Lane = { car: ReturnType<ReturnType<typeof createVehiclesThree>['build']>; group: THREE_NS.Object3D; wall: THREE_NS.Mesh<THREE_NS.BoxGeometry, THREE_NS.MeshStandardMaterial>; mode: 'arcade' | 'semi'; step(dt: number): void; speed(): number; distance(): number; done: boolean; stopped: number }\n\n const effects = (): EffectsLike | undefined => host?.effects\n // the sounds are asked of the host's shared engine by id (the sink may be absent, and then the module is silent)\n const audio = () => host?.audio\n // the lane car's engine, tyres and crashes (the vehicle bank of this package)\n let carSound: VehicleSound | undefined\n const stopEngine = (): void => {\n carSound?.dispose()\n carSound = undefined\n }\n\n /** The puffs' materials come from the host's pool when it lends one (read at each puff: the host attaches after the first build). */\n const particleMaterials: ParticleMaterials = {\n own: <TMaterial>(build: () => TMaterial): TMaterial => (isRenderPools(host?.pools) ? (host.pools.materials.own(build as never) as unknown as TMaterial) : build()),\n release: (material) => (isRenderPools(host?.pools) ? host.pools.materials.release(material as never) : (material as { dispose?(): void }).dispose?.()),\n }\n\n const kitFor = (THREE: Three): VehicleKit => {\n three = THREE\n let kit = kits.get(THREE)\n if (!kit) {\n if (options.createKit) kit = options.createKit(THREE)\n else {\n kit = createVehicleKit({ THREE, locale, particleMaterials, effects: () => host?.effects, ...(options.document ? { document: options.document as never } : {}) })\n fleet.installFleet(kit)\n }\n kits.set(THREE, kit)\n }\n return kit\n }\n\n const paletteFor = (key: string) => (settings.palette === 'civil' ? fleet.paintPalettes.civil : settings.palette === 'military' ? fleet.paintPalettes.military : fleet.paletteOf(key))\n const paintOf = (entry: Placed): void => {\n if (!settings.paint) return\n entry.lod?.dispose()\n delete entry.lod\n const color = fleet.colorFromSeed(settings.seed + entry.index, paletteFor(entry.key))\n if (!entry.paint) {\n const vehicle = entry.item.vehicle as unknown as { vehicle: THREE_NS.Object3D }\n const primary = primaryPaint(entry.item.vehicle)\n if (!primary) return\n entry.paint = primary.clone()\n vehicle.vehicle.traverse((obj) => {\n const mesh = obj as THREE_NS.Mesh\n if (!mesh.isMesh) return\n if (Array.isArray(mesh.material)) mesh.material = mesh.material.map((m) => (m === primary ? entry.paint! : m))\n else if (mesh.material === primary) mesh.material = entry.paint!\n })\n }\n entry.paint.color.set(color)\n }\n\n const item = ({ key, id: itemKey, scenario }: Entry): TestableItem => ({\n id: itemKey,\n name: text.items[itemKey] ?? key,\n movable: false,\n // the first build of a vehicle takes most of a second\n slow: true,\n build: (THREE: unknown) => {\n const kit = kitFor(THREE as Three)\n const built = buildVehicleItem(kit, key, { lod: settings.quality === 'lite', ...(scenario ? { scenario } : {}) })\n built.root.userData.kit = kit\n const entry: Placed = { root: built.root, key, ...(scenario ? { scenario } : {}), item: built, index: counter++, helpers: [] }\n placed.set(built.root.uuid, entry)\n // measured now, before the destructible adds its own plates and mirrors: this is the size the fleet records\n measure(entry)\n paintOf(entry)\n return built.root\n },\n impl: (root: unknown, id: string) => {\n const r = root as { userData: Record<string, unknown> }\n const kit = r.userData.kit as VehicleKit\n const d = createVehicleDestructible(kit, r.userData.vehicle as VehicleContext, { id, frame: root, name: text.items[itemKey] ?? key, creaseQueue })\n tapEffects(d)\n // a leaf the room swings (door, hood, lid) is posed through here: away from its rest the vehicle draws in full, or the fused one shows it shut\n const setPartPose = d.setPartPose?.bind(d)\n {\n const rests = new Map((d.describe().parts as Array<{ id: string; rotation?: Vec3 }>).map((part) => [part.id, part.rotation ?? [0, 0, 0]]))\n d.setPartPose = (partId: string, position: Vec3, rotation?: Vec3) => {\n const entry = [...placed.values()].find((candidate) => candidate.root === root)\n const rest = rests.get(partId) ?? [0, 0, 0]\n const isOpen = (rotation ?? [0, 0, 0]).some((angle, axis) => Math.abs(angle - (rest[axis] ?? 0)) > LEAF_REST_RADIANS)\n if (entry) {\n entry.posedParts ??= new Set()\n if (isOpen) entry.posedParts.add(partId)\n else entry.posedParts.delete(partId)\n }\n return setPartPose?.(partId, position, rotation)\n }\n }\n const hitBody = d.hit.bind(d)\n d.hit = (h: never) => {\n const entry = [...placed.values()].find((candidate) => candidate.root === root)\n if (entry) entry.touched = true\n return hitBody(h)\n }\n cabins.track(id, d, root as { parent: unknown | null })\n r.userData.destructible = d\n return d\n },\n ...(clipsOf(key) ? { animations: clipsOf(key) as AnimationClipSpec[] } : {}),\n })\n\n // the clips are numbers (rotations of the door, hood and lid parts), so any three.js namespace computes them: the one in the options, else the global one\n const clipCache = new Map<string, AnimationClipSpec[]>()\n const clipsOf = (key: string): AnimationClipSpec[] | undefined => {\n const THREE = options.three ?? (globalThis as { THREE?: unknown }).THREE\n if (!THREE) return undefined\n if (!clipCache.has(key)) {\n const kit = kitFor(THREE as Three)\n const built = buildVehicleItem(kit, key)\n const d = createVehicleDestructible(kit, built.vehicle, { id: `${itemId(key)}_clips`, frame: built.root, headless: true })\n clipCache.set(key, d.animations())\n kit.dispose(built.vehicle)\n }\n return clipCache.get(key)\n }\n\n // events of the vehicle become effect requests: the module owns no particle code\n const tapEffects = (d: { hit(h: never): unknown[]; update?(dt: number): unknown[] }): void => {\n const request = (events: unknown[]): void => {\n const fx = effects()\n if (!fx) return\n for (const e of events as { type: string; part?: string; point?: Vec3; worldPoint?: Vec3 }[]) {\n const position = e.point ?? e.worldPoint\n if (!position) continue\n // a pierced tank only leaks; when the leak catches fire the whole sequence plays (the fire runs to the tank, then the blast)\n if (e.type === 'ignite') fx.play({ effect: /fuel_tank|tank/.test(e.part ?? '') ? effectIds.leakIgnited : effectIds.ignite, point: position })\n else if (e.type === 'explode') fx.play({ effect: effectIds.explode, point: position })\n else if (e.type === 'leak') fx.play({ effect: effectIds.leak, point: position })\n else if (e.type === 'fracture' && /glass|window|windshield/.test(e.part ?? '')) fx.play({ effect: effectIds.glass, point: position })\n else if (e.type === 'hole') fx.play({ effect: /glass|window|windshield/.test(e.part ?? '') ? effectIds.glass : effectIds.sparks, point: position })\n }\n }\n const hit = d.hit.bind(d)\n d.hit = (h) => {\n const events = hit(h)\n request(events)\n return events\n }\n if (d.update) {\n const update = d.update.bind(d)\n d.update = (dt) => {\n const events = update(dt)\n request(events)\n return events\n }\n }\n }\n\n // ---- measuring and the layers ----------------------------------------------------------------------------------------------------------\n const rootMatrix = (entry: Placed): THREE_NS.Matrix4 => {\n const m = new three!.Matrix4().copy(entry.root.matrixWorld).invert()\n return m.multiply((entry.item.vehicle as unknown as { vehicle: THREE_NS.Object3D }).vehicle.matrixWorld)\n }\n const measure = (entry: Placed): { length: number; width: number; height: number } => {\n if (entry.size) return entry.size\n entry.root.updateMatrixWorld(true)\n const inverse = new three!.Matrix4().copy(entry.root.matrixWorld).invert()\n const bounds = new three!.Box3()\n const low = new three!.Box3()\n const piece = new three!.Box3()\n const matrix = new three!.Matrix4()\n entry.root.traverse((obj) => {\n const mesh = obj as THREE_NS.Mesh\n if (!mesh.isMesh || !mesh.geometry || mesh.userData.ghost) return\n for (let p: THREE_NS.Object3D | null = mesh; p; p = p.parent) if (p.visible === false) return\n if (mesh.userData.helper) return\n mesh.geometry.computeBoundingBox()\n piece.copy(mesh.geometry.boundingBox!).applyMatrix4(matrix.multiplyMatrices(inverse, mesh.matrixWorld))\n bounds.union(piece)\n if (piece.min.y < BODY_HEIGHT) low.union(piece)\n })\n const size = bounds.getSize(new three!.Vector3())\n entry.size = { length: size.z, width: size.x, height: size.y }\n if (!low.isEmpty()) entry.footprint = { minX: low.min.x, maxX: low.max.x, minZ: low.min.z, maxZ: low.max.z }\n return entry.size\n }\n const clearHelpers = (): void => {\n for (const entry of placed.values()) {\n discardObject3D(entry.helpers)\n entry.helpers = []\n }\n discardObject3D(axes)\n axes = []\n helpersShown = ''\n }\n const boxKey = (): string => `${host?.bench?.layer('damageables')}|${host?.bench?.layer('zones')}|${host?.bench?.layer('axes')}|${placed.size}`\n const refreshLayers = (): void => {\n if (!host?.bench || !three) return\n clearHelpers()\n const kit = [...placed.values()][0] && ((([...placed.values()][0] as Placed).root.userData.kit as VehicleKit | undefined) ?? undefined)\n const mark = (entry: Placed, box: THREE_NS.Box3, color: number): void => {\n const helper = new three!.Box3Helper(box, color)\n helper.userData.helper = true\n entry.root.add(helper)\n entry.helpers.push(helper)\n }\n if (kit) {\n for (const entry of placed.values()) {\n if (!entry.root.parent) continue\n entry.root.updateMatrixWorld(true)\n const matrix = rootMatrix(entry)\n if (host.bench.layer('damageables')) for (const d of kit.damageables(entry.item.vehicle, matrix) as { material: string; box: THREE_NS.Box3 }[]) mark(entry, d.box, MATERIAL_COLOURS[d.material] ?? 0xffffff)\n if (host.bench.layer('zones')) {\n for (const zone of (entry.item.vehicle as unknown as { zones: { type: string; box?: { x0: number; y0: number; z0: number; x1: number; y1: number; z1: number } }[] }).zones ?? []) {\n if (!zone.box || zone.type === 'internal') continue\n const box = new three.Box3(new three.Vector3(zone.box.x0, zone.box.y0, zone.box.z0), new three.Vector3(zone.box.x1, zone.box.y1, zone.box.z1)).applyMatrix4(matrix)\n mark(entry, box, ZONE_COLOURS[zone.type] ?? 0xffffff)\n }\n }\n }\n }\n if (host.bench.layer('axes')) {\n const front = new three.ArrowHelper(new three.Vector3(0, 0, 1), new three.Vector3(0, 0.05, 0), 3, 0x3366ff)\n const right = new three.ArrowHelper(new three.Vector3(-1, 0, 0), new three.Vector3(0, 0.05, 0), 3, 0xff3333)\n const up = new three.ArrowHelper(new three.Vector3(0, 1, 0), new three.Vector3(0, 0.05, 0), 3, 0x33cc33)\n for (const arrow of [front, right, up]) {\n ;(host.scene as THREE_NS.Object3D).add(arrow)\n axes.push(arrow)\n }\n }\n helpersShown = boxKey()\n }\n\n // ---- the walking player ------------------------------------------------------------------------------------------------------------------\n // every vehicle on the floor (and the car on the lane) is solid: the point is taken into the vehicle's own space, so a turned vehicle blocks by its turned footprint\n const laneBlocked = footprintBlocker(\n () => lane?.group,\n () => (lane ? { minX: -lane.car.width / 2, maxX: lane.car.width / 2, minZ: -lane.car.length / 2, maxZ: lane.car.length / 2 } : null),\n )\n const blocked = (x: number, z: number, radius: number): boolean => {\n for (const entry of placed.values()) if (entry.footprint && footprintBlocker(entry.root, entry.footprint)(x, z, radius)) return true\n return laneBlocked(x, z, radius)\n }\n\n // ---- the lane ---------------------------------------------------------------------------------------------------------------------------\n const clearLane = (): void => {\n stopEngine()\n if (!lane) return\n lane.group.parent?.remove(lane.group)\n lane.wall.parent?.remove(lane.wall)\n lane = null\n }\n const startLane = (): void => {\n if (!host || !three) return\n clearLane()\n const kit = kitFor(three)\n const vehicles = createVehiclesThree(three, { kit, fleet })\n // damage needs the parts drawn: the car is built in full only then\n const built = vehicles.build('compact_hatch', { quality: settings.damage === 'none' ? 'lite' : 'high', seed: settings.seed })\n const wall = new three.Mesh(new three.BoxGeometry(0.6, 2, 6), new three.MeshStandardMaterial({ color: 0x777777 }))\n wall.position.set(LANE.wall + 0.3, 1, LANE.z)\n const scene = host.scene as THREE_NS.Object3D\n scene.add(built.group, wall)\n // damage acts through the semi driver's condition\n const mode = settings.driving === 'semi' || settings.damage !== 'none' ? 'semi' : 'arcade'\n const damage = settings.damage === 'none' || !built.context ? null : createLaneDamage({ kit, context: built.context as VehicleContext, frame: built.group, damage: settings.damage })\n const surfaces = createSurfaces()\n const idle = { throttle: 0, brake: 0, steer: 0, handbrake: false }\n const state = { time: 0, exhaust: 0, sparks: 0, ended: false, wasBlocked: false }\n const arcade = createArcadeDriver({ length: built.length, width: built.width })\n const semi = createSemiSimDriver({}, { surfaces })\n const driver = mode === 'semi' ? semi : arcade\n driver.place(LANE.from, LANE.z, 0)\n const gap = (): number => LANE.wall - (driver.state.x + built.length / 2)\n // brakes when the stopping distance (at the rule's deceleration, the surface's grip in the semi mode) plus a margin reaches the wall\n const decel = (): number => (mode === 'semi' ? 9 * surfaces.get(settings.surface).grip : arcade.spec.brakeAgainstMotion)\n const brakeAt = (): number => (lane ? (lane.speed() * lane.speed()) / (2 * decel()) + 3 : 3)\n const pose = (): void => {\n built.group.position.set(driver.state.x, 0, driver.state.z)\n built.group.rotation.y = driver.state.yaw + Math.PI / 2\n }\n pose()\n carSound = createVehicleSound(audio(), { sounds: soundIds })\n // the key is turned before the car moves: the starter, then the engine catches\n carSound.start([driver.state.x, 0.5, driver.state.z])\n const log = (key: 'crash' | 'end', value: number): void => host?.log(fill(text, locale, text.lane[key], value.toFixed(1)))\n lane = {\n car: built,\n group: built.group,\n wall,\n mode,\n done: false,\n stopped: 0,\n speed: () => ('u' in driver.state ? (driver.state as { u: number }).u : (driver.state as { v: number }).v),\n distance: () => driver.state.x - LANE.from,\n step(dt) {\n // the run is over, the damage is not: torn panels, crumples and leaks finish over the next frames\n if (state.ended) {\n damage?.settle(dt)\n // stopped at the wall or against it: ignition off, the loops run down to silence\n const at: Vec3 = [driver.state.x, 0.5, driver.state.z]\n if (carSound?.reading.running) carSound.stop(at)\n carSound?.update({ dt, position: at, speed: 0, throttle: 0 })\n return\n }\n state.time += dt\n // the crash run does not brake: it shows what the wall does to the car\n const braking = settings.damage !== 'into_wall' && gap() < brakeAt() && state.time > 0.5\n const moving = state.time > LANE_START_S\n // a run on a damaged tyre holds the wheel straight: the pull to the side of the tyre is the car's, not the driver's weave\n const straight = settings.damage === 'into_wall' || TYRE_DAMAGE.has(settings.damage) || !moving\n const input = { ...idle, throttle: braking || !moving ? 0 : 1, brake: braking ? 1 : 0, steer: straight ? 0 : Math.sin(state.time * 1.4) * 0.15 }\n if (mode === 'arcade') {\n const { events } = arcade.step(input, dt, { blocked: (x, z, yaw) => vehicleCorners(arcade.spec, x, z, yaw).some(([px]) => px >= LANE.wall) })\n for (const e of events) {\n if (e.type !== 'crash') continue\n log('crash', e.speed)\n carSound?.crash(e.speed, [driver.state.x + built.length / 2, 0.5, driver.state.z])\n }\n } else {\n semi.step(input, dt, { ground: () => ({ surface: settings.surface }) })\n const grinding = damage?.step({ dt, speed: Math.abs(lane?.speed() ?? 0), throttle: input.throttle, driver: semi }) ?? []\n state.sparks -= dt\n const fx = effects()\n if (fx && state.sparks <= 0 && Math.abs(lane?.speed() ?? 0) > 0.5) {\n state.sparks = grinding.length ? SPARK_EVERY_S : 0\n for (const point of grinding) fx.play({ effect: effectIds.sparks, point })\n }\n if (gap() <= 0) {\n state.ended = true\n const crashed = damage?.crash({ speed: Math.abs((semi.state as { u: number }).u), direction: [Math.cos(driver.state.yaw), 0, -Math.sin(driver.state.yaw)] })\n if (crashed) {\n const parts = (type: string): string => [...new Set(crashed.flatMap((e) => (e.type === type && 'part' in e ? [e.part] : [])))].join(', ') || '-'\n host?.log(fill(text, locale, text.lane.damage, parts('dent'), parts('fracture')))\n }\n log('crash', Math.abs((semi.state as { u: number }).u))\n carSound?.crash((semi.state as { u: number }).u, [driver.state.x + built.length / 2, 0.5, driver.state.z])\n }\n }\n pose()\n {\n const speed = Math.abs(lane?.speed() ?? 0)\n // the engine by RPM and load (the semi driver has its own RPM; the arcade one is guessed from the speed), the tyres by slip and speed\n const semiState = mode === 'semi' ? (semi.state as { rpm: number; slip: number[] }) : null\n carSound?.update({\n dt,\n position: [driver.state.x, 0.5, driver.state.z],\n speed,\n throttle: input.throttle,\n ...(semiState ? { rpm: semiState.rpm, slip: Math.max(0, ...semiState.slip.map(Math.abs)) } : { slip: braking && speed > 3 ? 0.6 : 0 }),\n surface: /dirt|gravel|sand|grass|mud/.test(settings.surface) ? 'dirt' : 'asphalt',\n brake: input.brake,\n })\n }\n state.exhaust -= dt\n const fx = effects()\n if (fx && state.exhaust <= 0 && Math.abs(lane?.speed() ?? 0) > 0.5) {\n state.exhaust = 0.4\n fx.play({ effect: effectIds.exhaust, point: [driver.state.x - Math.cos(driver.state.yaw) * (built.length / 2), 0.3, driver.state.z + Math.sin(driver.state.yaw) * (built.length / 2)], scale: Math.min(1, Math.abs(lane?.speed() ?? 0) / 17) })\n }\n if (!state.ended && state.time > LANE_START_S + 1 && Math.abs(lane?.speed() ?? 0) < 0.05) {\n state.ended = true\n log('end', Math.max(0, gap()))\n }\n },\n }\n }\n\n // ---- the bench ----------------------------------------------------------------------------------------------------------------------------\n const onChange = (change: BenchChange): void => {\n if (change.kind === 'layer') return refreshLayers()\n if (change.kind === 'action') {\n if (change.id === 'repaint') for (const entry of placed.values()) paintOf(entry)\n else if (change.id === 'drive_lane') startLane()\n else if (change.id === 'clear_lane') clearLane()\n else if (change.id === 'honk') audio()?.play({ sound: soundIds.horn, position: lane ? [lane.group.position.x, 1, lane.group.position.z] : undefined })\n return\n }\n switch (change.id) {\n case 'quality': settings.quality = String(change.value); break\n case 'paint_by_seed': settings.paint = Boolean(change.value); for (const entry of placed.values()) paintOf(entry); break\n case 'color_seed': settings.seed = Number(change.value); for (const entry of placed.values()) paintOf(entry); break\n case 'palette': settings.palette = String(change.value); for (const entry of placed.values()) paintOf(entry); break\n case 'driving': settings.driving = String(change.value); break\n case 'surface': settings.surface = String(change.value); break\n case 'lane_damage': settings.damage = String(change.value) as LaneDamage; break\n default: break\n }\n }\n\n // one crease queue for every vehicle of the area; a host with a frame budget runs it, any other leaves each vehicle smoothing in its own update\n const creaseQueue = createCreaseQueue()\n\n const updateLod = (entry: Placed): void => {\n if (!host || settings.quality === 'lite') return\n entry.lod ??= createVehicleLod(entry.root.userData.kit, entry.item.vehicle, entry.root, entry.root.children[0])\n const at = host.player().position\n const distance = Math.hypot(at[0] - entry.root.position.x, at[2] - entry.root.position.z)\n // rolling over and blowing up move the body without a part pose: the fused copy would stay upright where the car was\n const c = entry.item.vehicle as { rollState?: unknown; flipped?: boolean; blast?: unknown; exploded?: boolean } | undefined\n if (c && (c.rollState || c.flipped || c.blast || c.exploded)) entry.touched = true\n // a wreck is built damaged: it never draws fused, only in batches (as a posed one)\n entry.lod.update(distance, entry.touched === true, entry.scenario !== undefined || (entry.posedParts?.size ?? 0) > 0)\n }\n\n const frame = (dt: number): void => {\n for (const [id, entry] of placed) {\n if (!entry.root.parent) {\n placed.delete(id)\n continue\n }\n measure(entry)\n updateLod(entry)\n }\n if (host?.bench && boxKey() !== helpersShown && (host.bench.layer('damageables') || host.bench.layer('zones') || helpersShown !== '')) refreshLayers()\n lane?.step(dt)\n cabins.sync(effects())\n }\n\n const count = (): { drawCalls: number; triangles: number } => {\n let drawCalls = 0\n let triangles = 0\n for (const entry of placed.values()) {\n entry.root.traverse((obj) => {\n const mesh = obj as THREE_NS.Mesh\n if (!mesh.isMesh || mesh.userData.helper) return\n for (let p: THREE_NS.Object3D | null = mesh; p; p = p.parent) if (p.visible === false) return\n drawCalls += 1\n const g = mesh.geometry\n triangles += (g.index ? g.index.count : g.attributes.position.count) / 3\n })\n }\n return { drawCalls, triangles: Math.round(triangles) }\n }\n const boxesOf = (material: string): number => {\n let total = 0\n for (const entry of placed.values()) {\n const kit = entry.root.userData.kit as VehicleKit | undefined\n if (kit) total += (kit.damageables(entry.item.vehicle) as { material: string }[]).filter((d) => d.material === material).length\n }\n return total\n }\n const sizeError = (): number => {\n let worst = 0\n for (const entry of placed.values()) {\n const want = fleet.fleetDims(entry.key)\n const got = entry.size\n if (!want || !got || entry.scenario) continue\n worst = Math.max(worst, Math.abs(got.length - want.length), Math.abs(got.width - want.width), Math.abs(got.height - want.height))\n }\n return Math.round(worst * 1000)\n }\n\n return {\n id: VEHICLES_AREA_ID,\n name: text.name,\n ground: { surface: 'road' },\n group: text.group,\n get placed() {\n return placed\n },\n items: () => entries.map(item),\n area: (): ModuleArea => {\n // the front row, each vehicle given room by its width, the front to +z; what is wider than a street (a helicopter with its rotor) stands alone in a row behind\n const gap = 1.6\n const WIDE = 6\n const rowOf = (list: readonly Entry[], z: number) => {\n let cursor = 0\n const spots = list.map((entry) => {\n const width = fleet.fleetDims(entry.key)?.width ?? 2\n const x = cursor + width / 2\n cursor += width + gap\n return { id: entry.id, x }\n })\n return { spots, z, width: Math.max(0, cursor - gap) }\n }\n const front = rowOf(entries.filter((e) => (fleet.fleetDims(e.key)?.width ?? 2) <= WIDE), 0)\n const back = rowOf(entries.filter((e) => (fleet.fleetDims(e.key)?.width ?? 2) > WIDE), -16)\n const placements = [front, back].flatMap((row) => row.spots.map(({ id, x }) => ({ item: id, position: [x - row.width / 2, 0, row.z] as Vec3, rotationY: 0 })))\n return { placements, view: { eye: [0, 5, Math.max(14, front.width * 0.6)], target: [0, 1, -2] } }\n },\n controls: (): ModuleControl[] => {\n const surfaceIds = createSurfaces().surfaces.map((s) => s.id)\n return [\n { kind: 'choice', id: 'quality', name: text.controls.quality, hint: text.hints.quality, options: (['high', 'lite'] as const).map((id) => ({ id, name: text.options.quality[id] as string })), default: 'high' },\n { kind: 'boolean', id: 'paint_by_seed', name: text.controls.paint_by_seed, hint: text.hints.paint_by_seed, default: false },\n { kind: 'number', id: 'color_seed', name: text.controls.color_seed, min: 0, max: 999, step: 1, default: 1 },\n { kind: 'choice', id: 'palette', name: text.controls.palette, hint: text.hints.palette, options: (['auto', 'civil', 'military'] as const).map((id) => ({ id, name: text.options.palette[id] as string })), default: 'auto' },\n { kind: 'choice', id: 'driving', name: text.controls.driving, hint: text.hints.driving, options: (['arcade', 'semi'] as const).map((id) => ({ id, name: text.options.driving[id] as string })), default: 'arcade' },\n { kind: 'choice', id: 'surface', name: text.controls.surface, hint: text.hints.surface, options: surfaceIds.map((id) => ({ id, name: text.options.surface[id] ?? id })), default: 'dry_asphalt' },\n { kind: 'choice', id: 'lane_damage', name: text.controls.lane_damage, hint: text.hints.lane_damage, options: LANE_DAMAGE.map((id) => ({ id, name: text.options.lane_damage[id] ?? id })), default: 'none' },\n { kind: 'action', id: 'repaint', name: text.actions.repaint },\n { kind: 'action', id: 'drive_lane', name: text.actions.drive_lane },\n { kind: 'action', id: 'clear_lane', name: text.actions.clear_lane },\n { kind: 'action', id: 'honk', name: text.actions.honk },\n ]\n },\n layers: (): ModuleLayer[] => (['damageables', 'zones', 'axes'] as const).map((id) => ({ id, name: text.layers[id], default: false })),\n metrics: (): ModuleMetric[] => [\n { id: 'vehicles', name: text.metrics.vehicles, read: () => placed.size },\n { id: 'triangles', name: text.metrics.triangles, read: () => count().triangles },\n { id: 'draw_calls', name: text.metrics.draw_calls, read: () => count().drawCalls },\n { id: 'size_error_mm', name: text.metrics.size_error_mm, unit: 'mm', read: sizeError },\n { id: 'metal', name: text.metrics.metal, read: () => boxesOf('metal') },\n { id: 'glass', name: text.metrics.glass, read: () => boxesOf('glass') },\n { id: 'rubber', name: text.metrics.rubber, read: () => boxesOf('rubber') },\n { id: 'fuel', name: text.metrics.fuel, read: () => boxesOf('fuel') },\n { id: 'speed', name: text.metrics.speed, unit: 'km/h', digits: 0, read: () => Math.round(Math.abs(lane?.speed() ?? 0) * 3.6) },\n { id: 'lane', name: text.metrics.lane, unit: 'm', digits: 1, read: () => lane?.distance() ?? 0 },\n ],\n scenarios: (): ModuleScenario<VehiclesContext>[] => createScenarios({ text, locale }),\n attach(lent) {\n host = lent\n three = lent.THREE as Three\n const stopChange = lent.bench?.onChange(onChange)\n const stopFrame = lent.onFrame(frame)\n const stopBlocker = lent.addBlocker?.(blocked)\n const stopCrease = lent.defer?.(creaseQueue.deferredQueue(), DEFERRED_PRIORITY[DEFERRED_QUEUE_ID.VEHICLE_CREASE])\n if (isRenderPools(lent.pools)) lent.pools.materials.register('vehicles.cracked-glass', () => crackedGlassMaterial(three!, new three!.DataTexture(new Uint8Array(4), 1, 1)))\n // the engine loop and the horn live in the library bank of game-audio, which the room's engine does not carry on its own\n lent.audio?.register?.(LIBRARY_BANK)\n lent.audio?.register?.(VEHICLE_SOUND_BANK)\n // the recordings of the car (when the game has them) decode now, so the first door opened or engine started is already the file\n lent.audio?.preload?.(VEHICLE_PRELOAD_SOUNDS)\n return () => {\n stopChange?.()\n stopFrame()\n stopBlocker?.()\n stopCrease?.()\n cabins.clear(effects())\n clearHelpers()\n clearLane()\n host = null\n }\n },\n }\n}\n\n/** What `loadVehiclesTestModule` needs of a room: `TestRoom.loadModule` has it. */\nexport type ModuleRoomLike = { loadModule(module: never): unknown }\n\n/**\n * Loads the vehicles module into a room. The door, hood and trunk clips of the items are computed when the room reads the items, before the module is lent the room's three.js\n * (`attach`), so this first lends an empty module to learn the namespace and then loads the real one with it. Pass `three` to skip that.\n */\nexport function loadVehiclesTestModule<Room extends ModuleRoomLike>(room: Room, options: VehiclesTestOptions = {}): ReturnType<Room['loadModule']> {\n let three = options.three\n if (!three) {\n room.loadModule({ id: 'vehicles_probe', name: 'Vehicles probe', group: 'Vehicles', items: () => [], attach: (lent: ModuleHost) => { three = lent.THREE; return () => undefined } } as never)\n }\n return room.loadModule(createVehiclesTestModule({ ...options, three }) as never) as ReturnType<Room['loadModule']>\n}\n","import { markKitOrigin } from '@adatechnology/game-contracts'\nimport type { Damageable, VehicleContext, VehicleKit } from '@adatechnology/game-vehicles'\nimport type * as THREE_NS from 'three'\nimport type { Group, Material, Mesh, MeshStandardMaterial, Object3D } from 'three'\n\nimport { colorFromSeed as defaultColorFromSeed, fleetDims as defaultFleetDims, paintPalettes as defaultPaintPalettes, paletteOf as defaultPaletteOf } from '@adatechnology/game-vehicles-fleet'\n\nimport { fuse, liteMaterials, liteMeshes } from './lite'\n\nexport type VehicleQuality = 'high' | 'lite'\n\n/** The measured size of a fleet vehicle in metres (the shape of `FleetDims` of `game-vehicles-fleet`). */\nexport interface FleetDims {\n length: number\n width: number\n height: number\n}\n\n/**\n * The fleet content the builder reads: the paint palettes, the size the team measured and the colour a seed picks. It is the shape of what\n * `game-vehicles-fleet` exports (`defaultVehicleFleet()` of `game-kit-defaults` hands it over), so this adapter imports no content.\n */\nexport interface VehicleFleetContent {\n readonly paintPalettes: { readonly civil: unknown; readonly military: unknown }\n paletteOf(group: string): unknown\n colorFromSeed(seed: number | string, palette: unknown): string\n fleetDims(id: string): FleetDims | undefined\n}\n\nexport interface BuildVehicleOptions {\n /** `high`: the kit's vehicle at full detail. `lite`: fused into six meshes. Default `high`. */\n quality?: VehicleQuality\n /** Body colour as a CSS colour. Wins over `seed`. */\n color?: string\n /** Picks the body colour from the palette of the vehicle's group. */\n seed?: number | string\n /** State of the vehicle. Default `intact`. */\n state?: 'intact' | 'damaged' | 'modified'\n}\n\nexport interface BuiltVehicle {\n key: string\n quality: VehicleQuality\n /** The colour the body ended up with, or null when the vehicle keeps its own paint. */\n color: string | null\n seed: number | string | null\n /** Group in the game frame: front on +z, right on -x, centred on x and z, wheels on y = 0. */\n group: Group\n /** Damageable boxes in the game frame. */\n damageables: Damageable[]\n triangles: number\n drawCalls: number\n /** Measured size of the group in metres: length along z, width along x, height along y. */\n length: number\n width: number\n height: number\n /** Pieces dropped for being smaller than 3 cm (lite only). */\n pruned: number\n /** The measured size the team recorded for this vehicle, when the fleet knows it. */\n expected: FleetDims | undefined\n /** The kit's context, for damage and animation (full detail only). */\n context: VehicleContext | null\n /**\n * The driver's eyes in the group frame: over the front seat on the driver's side (+x, left-hand drive), a seated person's eye height above the cushion.\n * Null when the vehicle has no seats drawn (lite detail, a boat deck).\n */\n driverEye: [number, number, number] | null\n dispose(): void\n}\n\nexport interface VehiclesThree {\n readonly THREE: typeof THREE_NS\n readonly kit: VehicleKit\n build(key: string, options?: BuildVehicleOptions): BuiltVehicle\n}\n\nexport interface VehiclesThreeOptions {\n kit: VehicleKit\n /**\n * The fleet's palettes and measured sizes (`defaultVehicleFleet()` of `game-kit-defaults`, or the game's own). Default the ones of `game-vehicles-fleet`.\n * @deprecated pass `fleet`; the default is removed in the next major.\n */\n fleet?: VehicleFleetContent\n /** Vehicle id to the group id whose palette paints it. Defaults to the fleet group of the vehicle (`military` for the military ones). */\n groupOf?: (key: string) => string\n}\n\n/** Triangles and draw calls of the visible meshes of an object (a multi-material mesh costs one call per group). */\nfunction count(root: Object3D): { triangles: number; drawCalls: number } {\n let triangles = 0\n let drawCalls = 0\n root.traverse((node) => {\n const o = node as Mesh\n if (!o.isMesh || !o.geometry) return\n for (let p: Object3D | null = o; p; p = p.parent) if (p.visible === false) return\n const g = o.geometry\n const n = g.index ? g.index.count : g.attributes.position ? g.attributes.position.count : 0\n if (Array.isArray(o.material) && g.groups.length) drawCalls += g.groups.length\n else drawCalls++\n triangles += n / 3\n })\n return { triangles: Math.round(triangles), drawCalls }\n}\n\n/** The material most triangles are painted with: the body colour. */\nexport function primaryPaint(c: { vehicle: Object3D; paints: ReadonlySet<Material> }): MeshStandardMaterial | null {\n let best: MeshStandardMaterial | null = null\n let bestCount = -1\n const counts = new Map<Material, number>()\n c.vehicle.traverse((node) => {\n const o = node as Mesh\n if (!o.isMesh || !o.geometry) return\n const mats = Array.isArray(o.material) ? o.material : [o.material]\n const g = o.geometry\n const n = (g.index ? g.index.count : g.attributes.position.count) / 3\n for (const m of mats) if (c.paints.has(m)) counts.set(m, (counts.get(m) || 0) + n)\n })\n counts.forEach((n, m) => {\n if (n > bestCount) {\n bestCount = n\n best = m as MeshStandardMaterial\n }\n })\n return best\n}\n\n/**\n * Builds vehicles in a game frame. Port of `FrotaLeve.criar(...).construir` (frota-leve.js 14311-14442): the kit builds with +x to the front\n * and +z to the right; the game wants +z to the front and -x to the right, the vehicle centred on x and z and standing on y = 0.\n */\n/** Eyes of a seated driver over the top of the seat cushion and behind its centre, metres: the cushion gives under the body and the hips sit at its back. */\nconst SEATED_EYE = { up: 0.55, back: 0.28 }\n\n/** The driver's eyes in the group frame (the group sits at the origin while it is built): the frontmost seat, on the driver's side. */\ntype Point = { x: number; y: number; z: number }\nfunction eyeOf(THREE: { Vector3: new (x: number, y: number, z: number) => Point }, c: { seatTops?: Point[]; vehicle: { localToWorld(v: Point): Point } }): [number, number, number] | null {\n const tops = c.seatTops ?? []\n if (!tops.length) return null\n const points = tops.map((t) => c.vehicle.localToWorld(new THREE.Vector3(t.x, t.y, t.z)))\n const front = Math.max(...points.map((p) => p.z))\n const row = points.filter((p) => p.z > front - 0.25)\n const seat = row.reduce((a, b) => (b.x > a.x ? b : a))\n return [+seat.x.toFixed(3), +(seat.y + SEATED_EYE.up).toFixed(3), +(seat.z - SEATED_EYE.back).toFixed(3)]\n}\n\nexport function createVehiclesThree(THREE: typeof THREE_NS, options: VehiclesThreeOptions): VehiclesThree {\n const kit = options.kit\n const fleet: VehicleFleetContent = options.fleet ?? { colorFromSeed: defaultColorFromSeed, fleetDims: defaultFleetDims, paintPalettes: defaultPaintPalettes, paletteOf: defaultPaletteOf }\n const { colorFromSeed, fleetDims, paintPalettes, paletteOf } = fleet\n const groupOf = options.groupOf || ((key: string) => (kit.find(key)?.group === kit.config.defaultGroup ? 'cars' : String(kit.find(key)?.group)))\n const militaryKeys = new Set<string>()\n const isMilitary = (key: string): boolean => militaryKeys.has(key) || paletteOf(groupOf(key)) === paintPalettes.military\n\n const build = (key: string, o: BuildVehicleOptions = {}): BuiltVehicle => {\n const quality: VehicleQuality = o.quality === 'lite' ? 'lite' : 'high'\n const spec = kit.find(key)\n if (!spec) throw new Error(`createVehiclesThree: unknown vehicle \"${key}\"`)\n const seed = o.seed == null ? null : o.seed\n const color = o.color || (seed != null ? colorFromSeed(seed, isMilitary(key) ? paintPalettes.military : paintPalettes.civil) : null)\n const c = kit.build(key, o.state || 'intact', undefined, { lod: quality === 'lite' })\n c.root.updateMatrixWorld(true)\n const primary = primaryPaint(c)\n const rotation = new THREE.Matrix4().makeRotationY(-Math.PI / 2)\n const bounds = new THREE.Box3()\n const piece = new THREE.Box3()\n const turned = new THREE.Matrix4()\n c.vehicle.traverse((node: Object3D) => {\n const m = node as Mesh\n if (!m.isMesh || !m.geometry || m.userData.ghost) return\n for (let p: Object3D | null = m; p; p = p.parent) if (p.visible === false) return\n m.geometry.computeBoundingBox()\n piece.copy(m.geometry.boundingBox!).applyMatrix4(turned.multiplyMatrices(rotation, m.matrixWorld))\n bounds.union(piece)\n })\n const cx = (bounds.min.x + bounds.max.x) / 2\n const cz = (bounds.min.z + bounds.max.z) / 2\n const pivotMatrix = new THREE.Matrix4().makeTranslation(-cx, -bounds.min.y, -cz).multiply(rotation)\n const group = new THREE.Group()\n group.name = `vehicle:${key}`\n markKitOrigin(group, { owner: 'game-vehicles-three', kind: 'vehicle', id: key })\n const damageables = kit.damageables(c, pivotMatrix)\n let pruned = 0\n let driverEye: [number, number, number] | null = null\n if (quality === 'high') {\n const pivot = new THREE.Group()\n pivot.name = 'vehicle'\n pivot.matrixAutoUpdate = false\n pivot.matrix.copy(pivotMatrix)\n pivot.matrixWorldNeedsUpdate = true\n c.vehicle.matrixAutoUpdate = true\n pivot.add(c.vehicle)\n group.add(pivot)\n // the kit refreshes the matrices of what it deforms from c.root: it has to be the group that now carries the vehicle\n c.root = group\n if (color && primary) {\n const repainted = primary.clone()\n repainted.color.set(color)\n c.vehicle.traverse((node: Object3D) => {\n const m = node as Mesh\n if (!m.isMesh) return\n if (Array.isArray(m.material)) m.material = m.material.map((x) => (x === primary ? repainted : x))\n else if (m.material === primary) m.material = repainted\n })\n }\n markDamageables(c, damageables)\n group.updateMatrixWorld(true)\n driverEye = eyeOf(THREE, c)\n } else {\n const fusion = fuse(THREE, c, pivotMatrix, color ? new THREE.Color(color) : null, primary, kit.lodHiddenMaterials())\n for (const mesh of liteMeshes(THREE, fusion, liteMaterials(THREE, kit.studioEnvironment()))) group.add(mesh)\n pruned = fusion.pruned\n }\n const size = new THREE.Box3().setFromObject(group).getSize(new THREE.Vector3())\n const counted = count(group)\n group.userData.damageables = damageables\n group.userData.key = key\n group.userData.quality = quality\n return {\n key,\n quality,\n color,\n seed,\n group,\n damageables,\n triangles: counted.triangles,\n drawCalls: counted.drawCalls,\n length: +size.z.toFixed(3),\n width: +size.x.toFixed(3),\n height: +size.y.toFixed(3),\n pruned,\n expected: fleetDims(key),\n context: quality === 'high' ? c : null,\n driverEye,\n dispose() {\n group.traverse((node) => {\n const m = node as Mesh\n if (m.geometry) m.geometry.dispose()\n })\n },\n }\n }\n\n return { THREE, kit, build }\n}\n\n/** Tags the meshes of each damageable zone (and the tyres) so a hit test can tell what it hit. */\nfunction markDamageables(c: VehicleContext, damageables: Damageable[]): void {\n const byZone: Record<string, Damageable> = {}\n for (const d of damageables) byZone[d.zone] = d\n for (const z of c.zones || []) {\n const d = byZone[z.id]\n if (!d) continue\n for (const o of z.objs || z.meshes || []) if (o && o.userData) o.userData.damageable = { material: d.material, zone: d.zone }\n }\n for (const w of c.wheels || []) {\n const z = (c.zones || []).find((zz) => zz.type === 'wheel' && zz.objs && zz.objs.indexOf(w) >= 0)\n w.userData.damageable = { material: 'rubber', zone: z ? z.id : 'wheel' }\n }\n}\n","/**\n * The light mode of the team's Frota Leve (frota-leve.js 14202-14310): a built vehicle fused into six meshes, one per class of material,\n * with the meshes nobody sees from outside left out. A literal port: the classes, the thresholds (3 cm prune, 0.99 opacity, 0.5 metalness,\n * 0.25 and 0.45 emissive) and the colours are the team's.\n */\nimport type * as THREE_NS from 'three'\nimport type { BufferGeometry, Color, Material, Matrix4, Mesh, MeshBasicMaterial, MeshStandardMaterial, Object3D, Texture } from 'three'\n\ntype Three = typeof THREE_NS\n\n/** The six classes of a fused vehicle, in the order they are added to the group. */\nexport const LITE_CLASSES = ['paint', 'trim', 'metal', 'glass', 'light', 'plate'] as const\nexport type LiteClass = (typeof LITE_CLASSES)[number]\n\n/** Smallest extent in metres a piece needs to survive the fusion (the plate is always kept). */\nexport const PRUNE_BELOW = 0.03\n\n/** A material of the built vehicle as the fusion reads it (standard, basic or line materials alike). */\nexport type LiteSourceMaterial = Material & {\n map?: Texture | null\n color: Color\n metalness?: number\n roughness?: number\n emissive?: Color\n emissiveIntensity?: number\n isMeshBasicMaterial?: boolean\n}\n\n/** What the fusion reads of the built vehicle: its root and the paints (`c.paints`). */\nexport interface LiteSource {\n vehicle: Object3D\n paints?: ReadonlySet<Material> | null\n}\n\n/** A material of the fused vehicle (`liteMaterials`). */\nexport type LiteMaterial = MeshStandardMaterial | MeshBasicMaterial\n\ninterface Accumulator {\n P: number[]\n N: number[]\n C: number[]\n U: number[]\n I: number[]\n nv: number\n alpha: boolean\n uv: boolean\n map: Texture | null | undefined\n}\n\nexport interface LiteFusion {\n acc: Record<LiteClass, Accumulator>\n pruned: number\n}\n\nconst createAccumulators = (): Record<LiteClass, Accumulator> => {\n const acc = {} as Record<LiteClass, Accumulator>\n for (const name of LITE_CLASSES) acc[name] = { P: [], N: [], C: [], U: [], I: [], nv: 0, alpha: name === 'glass', uv: name === 'plate', map: null }\n return acc\n}\n\n/** Which class a material belongs to, or `null` when it is left out. */\nexport function classify(mat: LiteSourceMaterial, mesh: Object3D, c: LiteSource): LiteClass | null {\n if (mat.map) {\n if (mesh.userData.plate) return 'plate'\n if ((mat.userData && mat.userData.grille) || mat.name === 'grille' || (mat.metalness != null && mat.roughness != null && !mat.transparent)) return 'trim'\n return null\n }\n if (mat.transparent && mat.opacity < 0.99) {\n const col = mat.color\n if (col.r > col.g + col.b * 0.9 && col.r > 0.35) return 'light'\n if (col.r > 0.8 && col.g > 0.8 && mat.opacity < 0.3) return null\n return 'glass'\n }\n if (mat.isMeshBasicMaterial) return null\n const e = mat.emissive\n const ei = mat.emissiveIntensity == null ? 1 : mat.emissiveIntensity\n if (e && ((e.r + e.g + e.b) / 3) * ei > 0.25 && !mat.metalness) return 'light'\n if (e && ((e.r + e.g + e.b) / 3) * ei > 0.45) return 'light'\n if ((mat.metalness as number) >= 0.5) return 'metal'\n if (c.paints && c.paints.has(mat)) return 'paint'\n if (mat.opacity < 1 && mat.transparent) return null\n return 'trim'\n}\n\n/** The vertex colour of a piece of a class. `paintColor` replaces the primary paint. */\nexport function classColor(mat: LiteSourceMaterial, cls: LiteClass, primary: Material | null | undefined, paintColor: Color | null | undefined, out: Color): Color {\n if (cls === 'paint' && paintColor && mat === primary) return out.copy(paintColor)\n if (cls === 'light') {\n const e = mat.emissive\n const ei = mat.emissiveIntensity == null ? 1 : mat.emissiveIntensity\n if (e && e.r + e.g + e.b > 0.05) {\n out.copy(e).multiplyScalar(Math.max(1, ei) * 1.0)\n out.r = Math.min(out.r, 1)\n out.g = Math.min(out.g, 1)\n out.b = Math.min(out.b, 1)\n return out\n }\n return out.copy(mat.color)\n }\n if (mat.map) return out.setRGB(0.12, 0.13, 0.14)\n return out.copy(mat.color)\n}\n\n/** The material of each class (vertex colours; glass blends; light is unlit; the plate keeps its canvas texture). */\nexport function liteMaterials(THREE: Three, environment: Texture | null): Record<LiteClass, LiteMaterial> {\n return {\n paint: new THREE.MeshStandardMaterial({ vertexColors: true, roughness: 0.42, metalness: 0.3, side: THREE.DoubleSide, envMap: environment, envMapIntensity: 0.35 }),\n trim: new THREE.MeshStandardMaterial({ vertexColors: true, roughness: 0.78, metalness: 0.08, side: THREE.DoubleSide }),\n metal: new THREE.MeshStandardMaterial({ vertexColors: true, roughness: 0.32, metalness: 0.85, envMap: environment, envMapIntensity: 1.1, side: THREE.DoubleSide }),\n glass: new THREE.MeshStandardMaterial({ vertexColors: true, transparent: true, depthWrite: false, roughness: 0.06, metalness: 0.3, side: THREE.DoubleSide, envMap: environment, envMapIntensity: 0.9 }),\n light: new THREE.MeshBasicMaterial({ vertexColors: true, side: THREE.DoubleSide }),\n plate: new THREE.MeshStandardMaterial({ roughness: 0.5, metalness: 0.1, side: THREE.DoubleSide }),\n }\n}\n\n/**\n * Walks the built vehicle and collects every visible mesh, in the frame of `pivot`, into one set of arrays per class.\n * `hidden` is the set of materials nobody sees from outside (`kit.lodHiddenMaterials()`).\n */\nexport function fuse(THREE: Three, c: LiteSource, pivot: Matrix4, paintColor: Color | null, primary: Material | null | undefined, hidden: ReadonlySet<Material>): LiteFusion {\n const acc = createAccumulators()\n const mw = new THREE.Matrix4()\n const nm = new THREE.Matrix3()\n const v = new THREE.Vector3()\n const col = new THREE.Color()\n const tmp = new THREE.Box3()\n let pruned = 0\n c.vehicle.updateMatrixWorld(true)\n c.vehicle.traverse((node) => {\n const o = node as Mesh<BufferGeometry, LiteSourceMaterial | LiteSourceMaterial[]> & { isInstancedMesh?: boolean; isSkinnedMesh?: boolean }\n if (!o.isMesh || o.isInstancedMesh || o.isSkinnedMesh || !o.geometry || !o.geometry.attributes.position) return\n for (let p: Object3D | null = o; p; p = p.parent) if (p.visible === false) return\n if (o.userData && (o.userData.ghost || o.userData.skipLite)) return\n const mats = Array.isArray(o.material) ? o.material : [o.material]\n const geo = o.geometry\n mw.multiplyMatrices(pivot, o.matrixWorld)\n nm.getNormalMatrix(mw)\n const flip = mw.determinant() < 0\n geo.computeBoundingBox()\n tmp.copy(geo.boundingBox!).applyMatrix4(mw)\n const ext = Math.max(tmp.max.x - tmp.min.x, tmp.max.y - tmp.min.y, tmp.max.z - tmp.min.z)\n const pa = geo.attributes.position\n const na = geo.attributes.normal\n const ua = geo.attributes.uv\n const ca = geo.attributes.color\n const ix = geo.index\n const tot = ix ? ix.count : pa.count\n const groups = Array.isArray(o.material) && geo.groups.length ? geo.groups : [{ start: 0, count: tot, materialIndex: 0 }]\n groups.forEach((gr) => {\n const mat = mats[gr.materialIndex as number] || mats[0]\n if (!mat || hidden.has(mat)) return\n const cls = classify(mat, o, c)\n if (!cls) return\n if (ext < PRUNE_BELOW && cls !== 'plate') {\n pruned++\n return\n }\n const A = acc[cls]\n const a0 = Math.min(gr.start, tot)\n let n0 = Math.min(gr.count, tot - a0)\n n0 -= n0 % 3\n if (n0 < 3) return\n const cc = classColor(mat, cls, primary, paintColor, col)\n const alpha = cls === 'glass' ? (mat.transparent ? mat.opacity : 1) : 1\n if (cls === 'plate' && A.map && mat.map !== A.map) return\n if (cls === 'plate') A.map = mat.map\n const remap = new Map<number, number>()\n for (let i = 0; i < n0; i++) {\n const vi = ix ? ix.getX(a0 + i) : a0 + i\n if (remap.has(vi)) continue\n remap.set(vi, A.nv++)\n v.fromBufferAttribute(pa, vi).applyMatrix4(mw)\n A.P.push(v.x, v.y, v.z)\n if (na) {\n v.fromBufferAttribute(na, vi).applyMatrix3(nm).normalize()\n A.N.push(v.x, v.y, v.z)\n } else A.N.push(0, 1, 0)\n let cr = cc.r\n let cg = cc.g\n let cb = cc.b\n if (ca && cls !== 'plate') {\n cr *= ca.getX(vi)\n cg *= ca.getY(vi)\n cb *= ca.getZ(vi)\n }\n if (A.alpha) A.C.push(cr, cg, cb, alpha)\n else A.C.push(cr, cg, cb)\n if (A.uv) A.U.push(ua ? ua.getX(vi) : 0, ua ? ua.getY(vi) : 0)\n }\n for (let t = 0; t < n0; t += 3) {\n const i0 = remap.get(ix ? ix.getX(a0 + t) : a0 + t) as number\n const i1 = remap.get(ix ? ix.getX(a0 + t + 1) : a0 + t + 1) as number\n const i2 = remap.get(ix ? ix.getX(a0 + t + 2) : a0 + t + 2) as number\n if (flip) A.I.push(i0, i2, i1)\n else A.I.push(i0, i1, i2)\n }\n })\n })\n return { acc, pruned }\n}\n\n/** One mesh per class that has triangles. */\nexport function liteMeshes(THREE: Three, fusion: LiteFusion, materials: Record<LiteClass, LiteMaterial>): Mesh[] {\n const meshes: Mesh[] = []\n for (const name of LITE_CLASSES) {\n const A = fusion.acc[name]\n if (!A.I.length) continue\n const g = new THREE.BufferGeometry()\n g.setAttribute('position', new THREE.Float32BufferAttribute(A.P, 3))\n g.setAttribute('normal', new THREE.Float32BufferAttribute(A.N, 3))\n g.setAttribute('color', new THREE.Float32BufferAttribute(A.C, A.alpha ? 4 : 3))\n if (A.uv) g.setAttribute('uv', new THREE.Float32BufferAttribute(A.U, 2))\n g.setIndex(A.nv > 65535 ? new THREE.Uint32BufferAttribute(A.I, 1) : new THREE.Uint16BufferAttribute(A.I, 1))\n g.computeBoundingBox()\n g.computeBoundingSphere()\n let mt = materials[name]\n if (name === 'plate') {\n mt = mt.clone()\n mt.map = A.map as Texture | null\n if (mt.map) mt.map.needsUpdate = true\n }\n const mesh = new THREE.Mesh(g, mt)\n mesh.name = name\n mesh.castShadow = name !== 'glass' && name !== 'light'\n mesh.receiveShadow = name !== 'light'\n meshes.push(mesh)\n }\n return meshes\n}\n","import { markKitOrigin } from '@adatechnology/game-contracts'\nimport { createStaticBatcher } from '@adatechnology/game-render-three'\nimport type { StaticBatcher } from '@adatechnology/game-render-three'\nimport type { VehicleContext } from '@adatechnology/game-vehicles'\nimport type * as THREE_NS from 'three'\nimport type { Group, Material, Mesh, Object3D, Texture } from 'three'\n\nimport { fuse, liteMaterials, liteMeshes } from './lite'\nimport { primaryPaint } from './build'\n\n/** Past this distance (m) an untouched vehicle draws fused: nobody sees a door seam from here, and the full model costs hundreds of draw calls. */\nexport const VEHICLE_LOD_DISTANCE = 14\nconst BATCH_BUDGET_MS = 2\n/**\n * A vehicle hit in play changes part by part (dents, holes, a door torn off): it is batched again once nothing has changed on it for this long.\n * Before 2026-11-03 a hit vehicle never batched again and drew one call per part for good (~950 draws per frame for the sedan, colour and shadow,\n * after the first blast of the horde chain), the larger share of the frame time of `chain_horde` in perf.mjs.\n */\nexport const VEHICLE_REBATCH_AFTER_MS = 1500\n\nexport type VehicleLodOptions = {\n /** The clock (ms) the quiet time is read from (default `performance.now`). */\n readonly now?: () => number\n}\n\nexport type VehicleLod = {\n /** `touched`: hit or driven, from now on it always draws in full (its damage only exists there); `posed`: a door, hood or lid is open now (fused only while all are shut). */\n update(distance: number, touched: boolean, posed?: boolean): void\n readonly fused: boolean\n dispose(): void\n}\n\n/** What the level of detail reads of the vehicle kit: its three.js, the materials nobody sees from outside and the studio environment. */\nexport type VehicleLodKit = {\n readonly THREE: typeof THREE_NS\n lodHiddenMaterials(): ReadonlySet<Material>\n studioEnvironment(): Texture | null\n}\n\nconst isShown = (object: Object3D, top: Object3D): boolean => {\n for (let node: Object3D | null = object; node && node !== top; node = node.parent) if (node.visible === false) return false\n return true\n}\n\n/** Shows `full` near and the kit's fused light mode (one mesh per class of material) far, in `root`'s own space. Hit tests read the full model, visible or not. */\nexport function createVehicleLod(kit: VehicleLodKit, context: VehicleContext, root: Object3D, full: Object3D, options: VehicleLodOptions = {}): VehicleLod {\n const THREE = kit.THREE\n const now = options.now ?? (() => performance.now())\n // when the vehicle last changed (hit, rebuilt, a batched part given back): a hit one is batched again only after a quiet time\n let changedAt = Number.NEGATIVE_INFINITY\n // the full model is drawn whole once, off-camera parts included, before it may hide: its buffers reach the GPU then, not in the frame of a\n // blast. A model rebuilt in place (the destructible's reset) is new geometry, so it is drawn whole again.\n let isUploaded = false\n let modelKey = ''\n const culled = new Map<Mesh, boolean>()\n const keyOf = (): string => full.children.filter((child) => child.name !== 'static-batches').map((child) => child.uuid).join()\n const armUpload = (): void => {\n // a model rebuilt again before its first draw (frames skipped on a slow machine) lets go of the old one's meshes\n for (const [mesh, wasCulled] of culled) mesh.frustumCulled = wasCulled\n culled.clear()\n modelKey = keyOf()\n isUploaded = false\n full.traverse((node) => {\n const object = node as Mesh\n if (!object.isMesh || culled.has(object)) return\n culled.set(object, object.frustumCulled)\n object.frustumCulled = false\n })\n const probe = [...culled.keys()][0]\n if (!probe) {\n isUploaded = true\n return\n }\n const before = probe.onAfterRender\n probe.onAfterRender = function (this: Mesh, ...args: Parameters<Mesh['onAfterRender']>) {\n isUploaded = true\n probe.onAfterRender = before\n before?.apply(this, args)\n }\n }\n armUpload()\n let lite: Group | null = null\n let isFused = false\n let isLocked = false\n // near, the full model draws its still parts in batches by material; a part that moves, dents or falls draws on its own again\n let batcher: StaticBatcher | null = null\n let shadow: Mesh | null = null\n const castsShadow = new Set<Mesh>()\n /** One mesh with the shape of the fused body, drawn only into the shadow map. */\n const shadowProxyOf = (fused: Group): Mesh => {\n const positions: number[] = []\n const indices: number[] = []\n for (const child of fused.children) {\n const mesh = child as Mesh\n if (!mesh.isMesh || !mesh.castShadow) continue\n const geometry = mesh.geometry.clone().applyMatrix4(mesh.matrix)\n const offset = positions.length / 3\n const position = geometry.attributes.position\n for (let at = 0; at < position.count; at++) positions.push(position.getX(at), position.getY(at), position.getZ(at))\n const index = geometry.index ? Array.from(geometry.index.array as ArrayLike<number>) : Array.from({ length: position.count }, (_, at) => at)\n for (const vertex of index) indices.push(vertex + offset)\n geometry.dispose()\n }\n const geometry = new THREE.BufferGeometry()\n geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3))\n geometry.setIndex(indices)\n geometry.computeBoundingSphere()\n const proxy = new THREE.Mesh(geometry, new THREE.MeshBasicMaterial({ colorWrite: false, depthWrite: false }))\n proxy.name = 'vehicle-shadow'\n markKitOrigin(proxy, { owner: 'game-vehicles-three', kind: 'vehicle', id: root.name })\n proxy.castShadow = true\n proxy.userData.skipLite = true\n proxy.raycast = () => undefined\n root.add(proxy)\n return proxy\n }\n const batchLocked = (): void => {\n // the parts keep their own shadows (the proxy has the shape of the vehicle before the hit); the batches cast for the still ones\n batcher = createStaticBatcher(THREE, full, { budgetMs: BATCH_BUDGET_MS })\n batcher.group.traverse((object) => (object.userData.skipLite = true))\n // the batches copy the parts' triangles: a hit test reads the parts (`surfaceRay`), never the copy\n batcher.group.userData.noSurfaceRay = true\n markKitOrigin(batcher.group, { owner: 'game-vehicles-three', kind: 'vehicle', id: root.name })\n }\n const drawFull = (): void => {\n // a vehicle hit in play is changing part by part: batched now, its batches would be given back as fast as they are made\n if (!batcher && isLocked) {\n if (now() - changedAt >= VEHICLE_REBATCH_AFTER_MS) batchLocked()\n return\n }\n if (!batcher) {\n lite ??= build()\n lite.visible = isFused\n shadow ??= shadowProxyOf(lite)\n shadow.visible = !isFused\n // the shadow comes from the one proxy, not from each part: a part's own shadow would be one more pass per draw\n full.traverse((node) => {\n const object = node as Mesh\n if (!object.isMesh || !object.castShadow) return\n castsShadow.add(object)\n object.castShadow = false\n })\n // merged a material at a time over the next frames (BATCH_BUDGET_MS each), never in one frame\n batcher = createStaticBatcher(THREE, full, { budgetMs: BATCH_BUDGET_MS })\n batcher.group.traverse((object) => (object.userData.skipLite = true))\n batcher.group.userData.noSurfaceRay = true\n markKitOrigin(batcher.group, { owner: 'game-vehicles-three', kind: 'vehicle', id: root.name })\n return\n }\n if (!batcher) return\n if (batcher.update() > 0) changedAt = now()\n // every part changed (the model was rebuilt, or all of it dented): batch what stands now (a hit vehicle, once it is quiet again)\n if (batcher.stats().batched === 0 && batcher.stats().released > 0) {\n batcher.dispose()\n batcher = null\n }\n }\n const build = (): Group => {\n root.updateMatrixWorld(true)\n const inverse = new THREE.Matrix4().copy(root.matrixWorld).invert()\n // a painted texture (a livery, a lettering) does not survive the fusion into vertex colours: those meshes stay as they are, drawn from the same geometry\n const textured: Mesh[] = []\n full.traverse((node) => {\n const object = node as Mesh\n if (!object.isMesh || object.userData.skipLite || !isShown(object, full)) return\n const materials = Array.isArray(object.material) ? object.material : [object.material]\n if (materials.some((material) => (material as Material & { map?: Texture | null })?.map && !/plate/i.test(material.name ?? '')) && !/plate/i.test(object.name ?? '')) textured.push(object)\n })\n for (const mesh of textured) mesh.userData.skipLite = true\n const fusion = fuse(THREE, { ...context, vehicle: full }, inverse, null, primaryPaint(context), kit.lodHiddenMaterials())\n for (const mesh of textured) delete mesh.userData.skipLite\n const group = new THREE.Group()\n group.name = 'vehicle-lite'\n markKitOrigin(group, { owner: 'game-vehicles-three', kind: 'vehicle', id: root.name })\n for (const mesh of liteMeshes(THREE, fusion, liteMaterials(THREE, kit.studioEnvironment()))) group.add(mesh)\n for (const mesh of textured) {\n const copy = new THREE.Mesh(mesh.geometry, mesh.material)\n copy.matrixAutoUpdate = false\n copy.matrix.multiplyMatrices(inverse, mesh.matrixWorld)\n copy.castShadow = mesh.castShadow\n copy.receiveShadow = mesh.receiveShadow\n group.add(copy)\n }\n root.add(group)\n return group\n }\n const show = (shouldFuse: boolean): void => {\n if (shouldFuse === isFused) return\n isFused = shouldFuse\n full.visible = !shouldFuse\n if (lite) lite.visible = shouldFuse\n if (shadow) shadow.visible = !shouldFuse\n }\n const api: VehicleLod = {\n update(distance, touched, posed = false) {\n if (touched && !isLocked) changedAt = now()\n isLocked ||= touched\n if (keyOf() !== modelKey) {\n changedAt = now()\n // the fused copy and the batches were made from the old model\n api.dispose()\n armUpload()\n }\n if (!isUploaded) return show(false)\n if (culled.size > 0) {\n for (const [mesh, wasCulled] of culled) mesh.frustumCulled = wasCulled\n culled.clear()\n }\n const shouldFuse = !isLocked && !posed && distance > (isFused ? VEHICLE_LOD_DISTANCE * 0.9 : VEHICLE_LOD_DISTANCE)\n if (shouldFuse && !lite) lite = build()\n show(shouldFuse)\n if (!shouldFuse) drawFull()\n },\n get fused() {\n return isFused\n },\n dispose() {\n show(false)\n batcher?.dispose()\n batcher = null\n for (const mesh of castsShadow) mesh.castShadow = true\n castsShadow.clear()\n shadow?.removeFromParent()\n shadow?.geometry.dispose()\n shadow = null\n if (!lite) return\n lite.removeFromParent()\n lite.traverse((object) => (object as Mesh).geometry?.dispose())\n lite = null\n },\n }\n return api\n}\n","import type { EffectSink, Enclosure } from '@adatechnology/game-contracts'\nimport { cabinEnclosure } from '@adatechnology/game-vehicles'\nimport type { CabinSource } from '@adatechnology/game-vehicles'\n\n/** One vehicle whose cabin holds out the host's smoke: its destructible and the object the host placed it in. */\ninterface Tracked {\n readonly source: CabinSource\n readonly frame: { readonly parent: unknown | null }\n declared: boolean\n /** It has been in the scene: leaving it now means it was taken away. */\n placed: boolean\n}\n\n/**\n * Keeps the host's effects told where the cabins of the vehicles are and how open they are (`EffectSink.enclose`), so the smoke, dust and steam\n * do not pass through a shut car: they go round it and get in only through an open door, a broken window or a bullet hole. `sync` every frame;\n * a vehicle whose object left the scene is forgotten and its cabin ended.\n */\nexport interface CabinSmoke {\n /** Follows the cabin of a vehicle by its object id; `frame` is the object the host placed it in (the destructible's `frame`). */\n track(id: string, source: CabinSource, frame: { readonly parent: unknown | null }): void\n /** Ends the cabin of one vehicle now. */\n untrack(id: string, effects: EffectSink | undefined): void\n /** Tells `effects` where every cabin is now. A host without `enclose` lets the smoke through, as before. */\n sync(effects: EffectSink | undefined): void\n /** Ends every cabin (the module leaves). */\n clear(effects: EffectSink | undefined): void\n /** The ids followed now. */\n ids(): string[]\n}\n\nexport function createCabinSmoke(): CabinSmoke {\n const tracked = new Map<string, Tracked>()\n const end = (id: string, entry: Tracked, effects: EffectSink | undefined): void => {\n if (entry.declared) effects?.enclose?.(id, null)\n tracked.delete(id)\n }\n return {\n track(id, source, frame) {\n tracked.set(id, { source, frame, declared: false, placed: false })\n },\n untrack(id, effects) {\n const entry = tracked.get(id)\n if (entry) end(id, entry, effects)\n },\n sync(effects) {\n if (!effects?.enclose) return\n for (const [id, entry] of tracked) {\n if (!entry.frame.parent) {\n // not placed yet (built, not added): wait; taken out of the scene: forget it\n if (entry.placed) end(id, entry, effects)\n continue\n }\n entry.placed = true\n const enclosure: Enclosure | null = cabinEnclosure(entry.source, { frame: entry.frame })\n if (enclosure || entry.declared) effects.enclose(id, enclosure)\n entry.declared = enclosure !== null\n }\n },\n clear(effects) {\n for (const [id, entry] of [...tracked]) end(id, entry, effects)\n },\n ids: () => [...tracked.keys()],\n }\n}\n","import { crashVehicle, createVehicleDestructible } from '@adatechnology/game-vehicles'\nimport type { VehicleContext, VehicleKit } from '@adatechnology/game-vehicles'\nimport { conditionFromDamage } from '@adatechnology/game-vehicles-driving'\nimport type { SemiDriver } from '@adatechnology/game-vehicles-driving'\nimport type { DestructionEvent, Vec3 } from '@adatechnology/game-contracts'\n\n/** What the drive lane's car starts with: whole, driven into the wall without braking (its front crumples), a tyre burst by a rifle round, that tyre already torn off, the same burst on an armoured car (run-flat), the brake fluid drained. */\nexport const LANE_DAMAGE = ['none', 'into_wall', 'flat_tyre', 'torn_tyre', 'run_flat', 'no_brake_fluid'] as const\nexport type LaneDamage = (typeof LANE_DAMAGE)[number]\n\nconst RIFLE = { energy: 3500, caliber: 7.8, penetration: { steel: 18 } }\n/** Far enough on a flat tyre to tear it off. */\nconst TEAR_OFF_M = 5000\n/** The lane car's mass, kg; how wide its front meets the wall, metres; how far ahead of the bumper's centre the wall is touched. */\nconst LANE_CAR_KG = 1150\nconst LANE_WALL_CONTACT = 1.6\nconst WALL_REACH = 0.15\n/** Seconds the drained brake lines are left to empty. */\nconst DRAIN_S = 600\n\nexport type LaneDamageModel = {\n /** Drives the damage `dt` seconds at `speed` m/s and `throttle`, and gives the driver the condition it leaves. Answers where rims grind on the road. */\n step(params: { readonly dt: number; readonly speed: number; readonly throttle: number; readonly driver: SemiDriver }): Vec3[]\n /** The car ran into the lane's wall at `speed` m/s, moving along `direction`: its front takes the crash. */\n crash(params: { readonly speed: number; readonly direction: Vec3 }): DestructionEvent[]\n /** Lets the damage play out `dt` seconds with the car standing (after the run). */\n settle(dt: number): void\n}\n\nexport type CreateLaneDamageParams = {\n readonly kit: VehicleKit\n /** The lane car drawn in full (the lite build has no parts to show the damage on), and the group that carries it. */\n readonly context: VehicleContext\n readonly frame: unknown\n readonly damage: Exclude<LaneDamage, 'none'>\n}\n\n/** The lane car's damage model, drawn on the car (the tyre sags or is gone), only while the lane has a damage set. */\nexport function createLaneDamage(params: CreateLaneDamageParams): LaneDamageModel {\n const d = createVehicleDestructible(params.kit, params.context, { id: 'lane', frame: params.frame, armour: params.damage === 'run_flat' ? 'IIIA' : null })\n const part = (prefix: string): string | undefined => (d.describe().parts as Array<{ id: string }>).find((p) => p.id.startsWith(prefix))?.id\n const shoot = (id: string | undefined): void => {\n if (id) d.hit({ type: 'ballistic', point: d.partWorldCenter(id), part: id, direction: [0, 0, 1], ...RIFLE })\n }\n if (params.damage === 'into_wall') {\n // nothing broken before the run\n } else if (params.damage === 'no_brake_fluid') {\n shoot(part('brakes'))\n for (let t = 0; t < DRAIN_S; t++) d.update?.(1)\n } else {\n shoot(part('tyre_front_left'))\n if (params.damage === 'torn_tyre') d.rollFlat(TEAR_OFF_M, 8)\n }\n return {\n step({ dt, speed, throttle, driver }) {\n d.rollFlat(speed * dt, speed)\n d.runEngine(dt, throttle)\n const events = d.update?.(dt) ?? []\n driver.condition = conditionFromDamage(driver.spec, d.driveReport())\n return events.flatMap((e) => (e.type === 'debris' && e.kind === 'sparks' ? [e.point] : []))\n },\n settle(dt) {\n d.update?.(dt)\n },\n crash({ speed, direction }) {\n const front = part('bumper_front')\n if (!front) return []\n const at = d.partWorldCenter(front)\n return crashVehicle(d, { point: [at[0] + direction[0] * WALL_REACH, at[1], at[2] + direction[2] * WALL_REACH], direction, speed, massKg: LANE_CAR_KG, otherMassKg: Infinity, contactWidth: LANE_WALL_CONTACT }).events\n },\n }\n}\n","import type { ModuleScenario, Vec3 } from '@adatechnology/game-contracts'\nimport { createArcadeDriver, createSemiSimDriver, createSurfaces, vehicleCorners } from '@adatechnology/game-vehicles-driving'\nimport type { SemiInput, SemiWorld } from '@adatechnology/game-vehicles-driving'\nimport type { VehicleContext } from '@adatechnology/game-vehicles'\n\nimport { fill } from './text'\nimport type { VehiclesText } from './text'\nimport type { PartView, VehiclesContext, VehiclesRoom } from './types'\n\ntype Destructible = {\n partWorldCenter(part: string): Vec3\n detachedParts(): string[]\n describe(): { parts: { id: string; hp: number; shape: { size: Vec3 } }[] }\n status(): { leaking: unknown[]; exploded: boolean; lightsOn: boolean; canStart: boolean; canDrive: boolean }\n state(): { groups: unknown[] }\n rollover(): void\n vehicle: { flipped?: boolean }\n}\n\ntype Spawned = { id: string; d: Destructible }\n\nexport type ScenarioDeps = {\n readonly text: VehiclesText\n readonly locale: string\n}\n\nconst add = (p: Vec3, dx: number, dy: number, dz: number): Vec3 => [p[0] + dx, p[1] + dy, p[2] + dz]\n\n/**\n * The scenarios of the vehicles area. The first eleven are the Frota test page's, literal (same shots, same hits, same checks and the same sentences); the vehicle faces +z,\n * its left is +x and its right -x. Then the burnt sedan built by the kit's `burnt` scenario, the arcade driver down a lane that ends in a wall, and the semi-simulation braking on three surfaces (new in the kit).\n */\nexport const createScenarios = (deps: ScenarioDeps): ModuleScenario<VehiclesContext>[] => {\n const { text, locale } = deps\n const say = (id: string, ...values: unknown[]): string => fill(text, locale, text.checks[id] as string, ...values)\n const scenario = (id: string, run: ModuleScenario<VehiclesContext>['run']): ModuleScenario<VehiclesContext> => ({ id, name: text.scenarios[id] ?? id, run })\n const put = (room: VehiclesRoom, item: string, z = -7): Spawned => {\n const spawned = room.spawn(item, [0, 0, z], 0)\n return { id: spawned.objectId, d: spawned.root.userData.destructible as Destructible }\n }\n const part = (room: VehiclesRoom, v: Spawned, id: string): PartView => room.world.part(v.id, id)\n const events = (room: VehiclesRoom, type: string, v: Spawned): number => room.log.entries({ type, objectId: v.id }).length\n\n return [\n scenario('vehicles_9mm_windshield', ({ room, step, expect }) => {\n const v = put(room, 'hatch')\n const c = v.d.partWorldCenter('windshield')\n room.setTool('pistol_9mm')\n room.waitUntilReady()\n room.look(add(c, 0, 0.5, 3), c)\n step(0.1)\n room.use()\n step(0.4)\n const w = part(room, v, 'windshield')\n expect(w.holes.length >= 1 && !!w.holes[0]?.through, say('windshield_holes', w.holes.length, w.holes[0]?.through))\n expect(w.cracks.length >= 1 && w.status === 'damaged', say('windshield_cracks', w.cracks.length, w.status))\n }),\n scenario('vehicles_shotgun_door', ({ room, step, expect }) => {\n const v = put(room, 'sedan')\n const c = v.d.partWorldCenter('door_front_left')\n room.setTool('shotgun_pump_12')\n room.waitUntilReady()\n room.look(add(c, 2.5, 0, 0), c)\n step(0.1)\n room.use()\n step(0.4)\n const p = part(room, v, 'door_front_left')\n const marks = p.holes.length + p.dents.length\n expect(marks >= 2 && p.hp < p.maxHp, say('door_marks', p.holes.length, p.dents.length, Math.round(p.hp), p.maxHp))\n }),\n scenario('vehicles_ram_front', ({ room, step, expect }) => {\n const v = put(room, 'hatch')\n const c = v.d.partWorldCenter('bumper_front')\n room.world.hit(v.id, { type: 'blunt', point: c, direction: [0, 0, -1], energy: 45000, radius: 0.6, source: 'teste' })\n step(2.5)\n const b = part(room, v, 'bumper_front')\n const h = part(room, v, 'hood')\n expect(b.dents.length >= 1 && h.dents.length >= 1, say('front_crush', b.dents.length, h.dents.length))\n const det = v.d.detachedParts()\n expect(det.indexOf('bumper_front') >= 0, say('bumper_off', det.join(', ')))\n }),\n scenario('vehicles_engine_fire', ({ room, step, expect }) => {\n const v = put(room, 'pickup')\n const c = v.d.partWorldCenter('engine')\n for (let i = 0; i < 80; i++) {\n room.world.hit(v.id, { type: 'fire', point: c, temperature: 900, radius: 0.5, duration: 0.1, source: 'teste' })\n step(0.1)\n }\n const e = part(room, v, 'engine')\n expect(e.burning && e.temperature > 250, say('engine_burning', e.burning, Math.round(e.temperature)))\n expect(events(room, 'ignite', v) >= 1, say('ignite_lines', events(room, 'ignite', v)))\n }),\n scenario('vehicles_fuel_tank', ({ room, step, expect }) => {\n const v = put(room, 'hatch')\n const spec = v.d.describe().parts.filter((p) => p.id === 'fuel_tank')[0] as { shape: { size: Vec3 } }\n const c = v.d.partWorldCenter('fuel_tank')\n // the shot comes in from below, under the fuel level\n const low: Vec3 = [c[0], c[1] - spec.shape.size[1] / 2 + 0.06, c[2]]\n room.setTool('pistol_9mm')\n room.waitUntilReady()\n room.look(add(low, 0, 0, -2.5), low)\n step(0.1)\n room.use()\n step(1)\n const t = part(room, v, 'fuel_tank')\n const nl = v.d.status().leaking.length\n expect(nl >= 1 && t.liters < 55, say('tank_leaking', nl, t.liters.toFixed(1)))\n for (let i = 0; i < 160 && !events(room, 'explode', v); i++) {\n room.world.hit(v.id, { type: 'fire', point: c, temperature: 900, radius: 0.6, duration: 0.1, source: 'teste' })\n step(0.1)\n }\n expect(events(room, 'ignite', v) >= 1, say('ignited', events(room, 'ignite', v)))\n step(2)\n expect(events(room, 'explode', v) === 1 && v.d.status().exploded, say('exploded', events(room, 'explode', v)))\n const vc = v.d.partWorldCenter('engine')\n room.look(add(vc, 4, 0, -3), vc)\n }),\n scenario('vehicles_unbolt_wheel', ({ room, step, expect }) => {\n const v = put(room, 'sedan')\n const joint = 'wheel_front_left~underbody'\n const c = v.d.partWorldCenter('wheel_front_left')\n room.setTool('wrench')\n // the wrench turns the hub bolts (the wheel~chassis joint), the same path as the first-person use\n for (let k = 0; k < 120 && room.world.disassemble(v.id, joint, 'wrench', 0.1) < 1; k++) step(0.1)\n step(1)\n const st = room.world.state(v.id)\n const open = !!st.joints.filter((j) => j.id === joint)[0]?.open\n expect(open && st.groups.length >= 2 && events(room, 'detach', v) >= 1, say('wheel_wrench', open, st.groups.length, events(room, 'detach', v)))\n step(2)\n room.look(add(c, 2.2, 0, 0.2), add(c, 0, -0.1, 0))\n }),\n scenario('vehicles_tear_bumper', ({ room, step, expect }) => {\n const v = put(room, 'hatch')\n const c = v.d.partWorldCenter('bumper_front')\n room.world.hit(v.id, { type: 'blunt', point: c, direction: [0, 0, -1], energy: 30000, radius: 0.6, source: 'teste' })\n step(2.5)\n const det = v.d.detachedParts()\n expect(det.indexOf('bumper_front') >= 0, say('loose_parts', det.join(', ')))\n room.look(add(c, 2, 0, 3.5), add(c, 0, 0, -0.5))\n }),\n scenario('vehicles_break_mirror', ({ room, step, expect }) => {\n const v = put(room, 'sedan')\n const c = v.d.partWorldCenter('mirror_left')\n room.world.hit(v.id, { type: 'blunt', point: c, direction: [-1, 0, 0], energy: 2500, radius: 0.1, source: 'teste' })\n step(2)\n const m = part(room, v, 'mirror_left')\n expect(m.status === 'broken' && v.d.state().groups.length >= 1, say('mirror_broken', m.status))\n }),\n scenario('vehicles_kill_battery', ({ room, step, expect }) => {\n const v = put(room, 'pickup')\n expect(v.d.status().lightsOn && v.d.status().canStart, say('battery_before'))\n room.playAnimation('open_hood', v.id)\n step(1.5)\n for (let i = 0; i < 80 && room.world.disassemble(v.id, 'battery~underbody', 'wrench', 0.1) < 1; i++) step(0.1)\n step(0.5)\n const s = v.d.status()\n expect(!s.lightsOn && !s.canStart && !s.canDrive, say('battery_after', s.lightsOn, s.canStart))\n }),\n scenario('vehicles_rollover', ({ room, step, expect }) => {\n const v = put(room, 'sedan')\n const maxRoof = (v.d.describe().parts.filter((p) => p.id === 'roof')[0] as { hp: number }).hp\n v.d.rollover()\n step(8)\n const roof = part(room, v, 'roof')\n expect(!!v.d.vehicle.flipped, say('rolled_over', !!v.d.vehicle.flipped))\n expect(roof.hp < maxRoof && roof.dents.length >= 1, say('roof', Math.round(roof.hp), maxRoof, roof.dents.length))\n }),\n scenario('vehicles_melt', ({ room, step, expect }) => {\n const v = put(room, 'hatch')\n const c = v.d.partWorldCenter('tyre_front_left')\n for (let i = 0; i < 60; i++) {\n room.world.hit(v.id, { type: 'fire', point: c, temperature: 900, radius: 0.7, duration: 0.1, source: 'teste' })\n step(0.1)\n }\n step(30)\n const t = part(room, v, 'tyre_front_left')\n expect(events(room, 'melt', v) >= 1 && (t.status === 'melted' || t.melt > 0.5), say('tyre_melt', t.status, Math.round(t.melt * 100), events(room, 'melt', v)))\n }),\n // new in the kit: the burnt wreck comes ready from the kit (the fleet's `burnt` scenario built into the vehicle), no damage applied by the area\n scenario('vehicles_burnt_wreck', ({ room, expect }) => {\n const c = room.spawn('sedan_burnt', [0, 0, -7], 0).root.userData.vehicle as VehicleContext\n expect(c.zoneState.flags.burnt === true, say('wreck_burnt', c.zoneState.flags.burnt === true))\n const glass = c.zones.filter((z) => z.type === 'glass')\n const up = glass.filter((z) => (c.zoneState.health[z.id] ?? 100) > 0)\n expect(glass.length >= 1 && up.length === 0, say('wreck_glass', glass.length, up.length))\n }),\n // new in the kit: the drivers, headless (no vehicle is spawned)\n scenario('vehicles_drive_arcade', ({ expect }) => {\n const driver = createArcadeDriver()\n const wallX = 60\n driver.place(0, 0, 0)\n const world = { blocked: (x: number, z: number, yaw: number) => vehicleCorners(driver.spec, x, z, yaw).some(([px]) => px >= wallX) }\n let crashSpeed = 0\n let engine = 0\n let crashNoise = 0\n let after = 0\n for (let t = 0; t < 12; t += 1 / 60) {\n const { events: out } = driver.step({ throttle: 1, brake: 0, steer: 0, handbrake: false }, 1 / 60, world)\n for (const e of out) {\n if (e.type === 'crash' && !crashSpeed) {\n crashSpeed = e.speed\n after = driver.state.v\n }\n if (e.type === 'noise' && e.source === 'engine') engine++\n if (e.type === 'noise' && e.source === 'crash') crashNoise++\n }\n }\n expect(crashSpeed > driver.spec.crash.damageSpeed && crashSpeed <= driver.spec.maxForward + 1e-6, say('arcade_crash', crashSpeed.toFixed(1), driver.spec.maxForward))\n expect(after < 0, say('arcade_bounce', after.toFixed(1)))\n expect(engine >= 1 && crashNoise >= 1, say('arcade_noise', engine, crashNoise))\n }),\n scenario('vehicles_drive_semi', ({ expect }) => {\n const surfaces = createSurfaces()\n const coast: SemiInput = { throttle: 0, brake: 0, steer: 0, handbrake: false }\n const dt = 1 / 60\n const world = (surface: string): SemiWorld => ({ ground: () => ({ surface }) })\n const braking = (surface: string): number => {\n const driver = createSemiSimDriver({}, { surfaces })\n driver.state.u = 80 / 3.6\n for (let t = 0; t < 1; t += dt) driver.step({ ...coast, throttle: 0.3 }, dt, world(surface))\n driver.state.u = 80 / 3.6\n const start = driver.state.x\n for (let t = 0; t < 30 && driver.state.u > 0.1; t += dt) driver.step({ ...coast, brake: 1 }, dt, world(surface))\n return driver.state.x - start\n }\n const dry = braking('dry_asphalt')\n const wet = braking('wet_asphalt')\n const mud = braking('mud')\n expect(dry < wet && wet < mud, say('semi_order', dry.toFixed(1), wet.toFixed(1), mud.toFixed(1)))\n const bog = createSemiSimDriver({}, { surfaces })\n let bogged = 0\n for (let t = 0; t < 8; t += dt) bogged += bog.step({ ...coast, throttle: 1 }, dt, world('mud')).events.filter((e) => e.type === 'bogged').length\n expect(bog.state.bogged && bogged >= 1, say('semi_mud', bog.state.bogged))\n }),\n ]\n}\n","/** Words and sentences of the vehicles area. The check lines keep the sentences of the Frota test page; `{0}`, `{1}`... are filled in order, `{0:b}` is yes / no (true / false in English), `{0:open}` open / tight, `{0:on}` on / off. */\nexport type VehiclesText = {\n group: string\n name: string\n items: Record<string, string>\n controls: Record<'quality' | 'paint_by_seed' | 'color_seed' | 'palette' | 'driving' | 'surface' | 'lane_damage', string>\n hints: Record<'quality' | 'paint_by_seed' | 'palette' | 'driving' | 'surface' | 'lane_damage', string>\n options: { quality: Record<string, string>; palette: Record<string, string>; driving: Record<string, string>; surface: Record<string, string>; lane_damage: Record<string, string> }\n actions: Record<'repaint' | 'drive_lane' | 'clear_lane' | 'honk', string>\n layers: Record<'damageables' | 'zones' | 'axes', string>\n metrics: Record<'vehicles' | 'triangles' | 'draw_calls' | 'size_error_mm' | 'metal' | 'glass' | 'rubber' | 'fuel' | 'speed' | 'lane', string>\n words: { yes: string; no: string; open: string; tight: string; on: string; off: string }\n lane: Record<'crash' | 'end' | 'damage', string>\n scenarios: Record<string, string>\n checks: Record<string, string>\n}\n\nconst scenarioIds = [\n 'vehicles_9mm_windshield',\n 'vehicles_shotgun_door',\n 'vehicles_ram_front',\n 'vehicles_engine_fire',\n 'vehicles_fuel_tank',\n 'vehicles_unbolt_wheel',\n 'vehicles_tear_bumper',\n 'vehicles_break_mirror',\n 'vehicles_kill_battery',\n 'vehicles_rollover',\n 'vehicles_melt',\n 'vehicles_burnt_wreck',\n 'vehicles_drive_arcade',\n 'vehicles_drive_semi',\n] as const\n\nexport const VEHICLE_SCENARIO_IDS: readonly string[] = scenarioIds\n\n/** The ids of the Frota test page, for whoever keeps a report or a link made against it. */\nexport const PAGE_SCENARIO_ALIASES: Readonly<Record<string, string>> = {\n veiculos_9mm_parabrisa: 'vehicles_9mm_windshield',\n veiculos_espingarda_porta: 'vehicles_shotgun_door',\n veiculos_bater_frente: 'vehicles_ram_front',\n veiculos_fogo_motor: 'vehicles_engine_fire',\n veiculos_tanque: 'vehicles_fuel_tank',\n veiculos_soltar_roda: 'vehicles_unbolt_wheel',\n veiculos_arrancar_parachoque: 'vehicles_tear_bumper',\n veiculos_quebrar_retrovisor: 'vehicles_break_mirror',\n veiculos_matar_bateria: 'vehicles_kill_battery',\n veiculos_capotar: 'vehicles_rollover',\n veiculos_derreter: 'vehicles_melt',\n}\n\nexport const PAGE_ITEM_ALIASES: Readonly<Record<string, string>> = {\n hatch: 'hatch',\n sedan: 'sedan',\n picape: 'pickup',\n moto: 'sport_bike',\n caminhao: 'box_truck',\n onibus: 'city_bus',\n tanque: 'battle_tank',\n helicoptero: 'attack_helicopter',\n}\n\nexport const TEXT: Record<string, VehiclesText> = {\n en: {\n group: 'Vehicles',\n name: 'Vehicles area',\n items: { hatch: 'Compact hatch', sedan: 'Midsize sedan', pickup: 'Midsize pickup', sport_bike: 'Sport bike', box_truck: 'Box truck', city_bus: 'City bus', battle_tank: 'Battle tank', attack_helicopter: 'Attack helicopter', sedan_burnt: 'Burnt sedan', hatch_burnt: 'Burnt hatch' },\n controls: { quality: 'Quality', paint_by_seed: 'Paint by seed', color_seed: 'Colour seed', palette: 'Palette', driving: 'Driving', surface: 'Surface', lane_damage: 'Lane damage' },\n hints: {\n quality: 'High: the kit at full detail. Light: fewer segments and no interior (the light mode of the fleet); applies to the vehicles placed from now on',\n paint_by_seed: 'Off: every vehicle keeps its own paint. On: the body colour comes from the seed and the palette',\n palette: 'Auto: the palette of the vehicle group (civil, or military for the army vehicles)',\n driving: 'Arcade: the game car, simple and forgiving. Semi: a rigid body with springs, tyre friction, gears and surfaces',\n surface: 'The ground under the wheels in the semi mode (grip and aquaplaning)',\n lane_damage: 'What the lane car starts with; it drives in the semi mode and the damage model sets its tyres, brakes and engine',\n },\n options: {\n quality: { high: 'High', lite: 'Light' },\n palette: { auto: 'Auto', civil: 'Civil', military: 'Military' },\n driving: { arcade: 'Arcade', semi: 'Semi-simulation' },\n surface: { dry_asphalt: 'Dry asphalt', wet_asphalt: 'Wet asphalt', dirt: 'Dirt', grass: 'Grass', mud: 'Mud', blood: 'Blood' },\n lane_damage: { none: 'None', into_wall: 'Into the wall, no braking', flat_tyre: 'Flat tyre (rifle round)', torn_tyre: 'Tyre torn off: rim on the road', run_flat: 'Armoured, flat tyre (run-flat)', no_brake_fluid: 'No brake fluid' },\n },\n actions: { repaint: 'Repaint with the seed', drive_lane: 'Drive the lane', clear_lane: 'Remove the lane car', honk: 'Honk the horn' },\n layers: { damageables: 'Damageable boxes by material', zones: 'Zone boxes by type', axes: 'Output frame axes' },\n metrics: { vehicles: 'Vehicles', triangles: 'Triangles', draw_calls: 'Draw calls', size_error_mm: 'Size against DIMS', metal: 'Metal boxes', glass: 'Glass boxes', rubber: 'Rubber boxes', fuel: 'Fuel boxes', speed: 'Lane speed', lane: 'Lane distance' },\n words: { yes: 'true', no: 'false', open: 'open', tight: 'tight', on: 'on', off: 'off' },\n lane: { crash: 'Lane: the car hit the wall at {0} m/s', end: 'Lane: the car stopped {0} m from the wall', damage: 'Lane: the crash dented {0} and broke {1}' },\n scenarios: {\n vehicles_9mm_windshield: 'Vehicles: 9 mm through the windshield',\n vehicles_shotgun_door: 'Vehicles: shotgun on the door',\n vehicles_ram_front: 'Vehicles: ram the front',\n vehicles_engine_fire: 'Vehicles: fire on the engine',\n vehicles_fuel_tank: 'Vehicles: shoot the fuel tank (leaks, ignites, explodes)',\n vehicles_unbolt_wheel: 'Vehicles: unbolt the wheel with the wrench',\n vehicles_tear_bumper: 'Vehicles: tear off the bumper',\n vehicles_break_mirror: 'Vehicles: break the mirror',\n vehicles_kill_battery: 'Vehicles: kill the battery (lights go out)',\n vehicles_rollover: 'Vehicles: roll over',\n vehicles_melt: 'Vehicles: melt (long fire burns the tyres)',\n vehicles_drive_arcade: 'Vehicles: arcade driving down a lane that ends in a wall',\n vehicles_drive_semi: 'Vehicles: semi-simulation braking on dry, wet and mud',\n vehicles_burnt_wreck: 'Vehicles: the burnt sedan comes out of the kit burnt, with the glass gone',\n },\n checks: {\n windshield_holes: 'Windshield: {0} hole(s), went through {1:b} (expected: 1, true)',\n windshield_cracks: 'Windshield cracked: {0} crack(s), state {1} (expected: damaged)',\n door_marks: 'Front left door: {0} hole(s), {1} dent(s), hp {2}/{3} (expected: 2 marks or more)',\n front_crush: 'Front crushed: bumper {0} dent(s), hood {1} (expected: 1 or more each)',\n bumper_off: 'The bumper came off: {0} (expected: bumper_front)',\n engine_burning: 'Engine: burning {0:b}, {1} °C (expected: true, above 250)',\n ignite_lines: 'Ignite lines in the log: {0} (expected: 1 or more)',\n tank_leaking: 'Tank leaking: {0} leak(s), {1} L left (expected: 1 or more, below 55)',\n ignited: 'Ignited: {0} ignite line(s) (expected: 1 or more)',\n exploded: 'Exploded: {0} explosion(s) (expected: 1)',\n wheel_wrench: 'Wrench on the wheel: bolts {0:open}, {1} group(s), {2} detach line(s) (expected: open, 2 or more, 1)',\n loose_parts: 'Loose parts: {0} (expected: bumper_front)',\n mirror_broken: 'Left mirror: {0} (expected: broken)',\n battery_before: 'Before: lights on and it starts (expected: yes)',\n battery_after: 'No battery: lights {0:on}, start {1:b} (expected: off, false)',\n rolled_over: 'Rolled over: {0:b} (expected: true)',\n roof: 'Roof: hp {0}/{1}, {2} dent(s) (expected: below max, 1 or more)',\n tyre_melt: 'Tyre: {0}, melted {1}%, {2} melt line(s) (expected: melted or above 50%)',\n arcade_crash: 'Arcade: the wall is hit at {0} m/s (expected: the crash above 4 m/s, at most {1})',\n arcade_bounce: 'Arcade: the car bounces back at {0} m/s (expected: below 0)',\n arcade_noise: 'Arcade: {0} engine noise(s) and {1} crash noise(s) (expected: 1 or more each)',\n semi_order: 'Semi: braking from 80 km/h takes dry {0} m, wet {1} m, mud {2} m (expected: dry shorter than wet shorter than mud)',\n semi_mud: 'Semi: a 2WD car on mud {0:on} (expected: bogged on, a bog event)',\n wreck_burnt: 'Burnt sedan: burnt flag {0:b} (expected: yes)',\n wreck_glass: 'Burnt sedan: {0} glass zone(s), {1} still above 0 (expected: 1 or more, none above 0)',\n },\n },\n 'pt-BR': {\n group: 'Veículos',\n name: 'Área de veículos',\n items: { hatch: 'Hatch compacto', sedan: 'Sedã médio', pickup: 'Picape média', sport_bike: 'Moto esportiva', box_truck: 'Caminhão baú', city_bus: 'Ônibus urbano', battle_tank: 'Tanque de guerra', attack_helicopter: 'Helicóptero de ataque', sedan_burnt: 'Sedã queimado', hatch_burnt: 'Hatch queimado' },\n controls: { quality: 'Qualidade', paint_by_seed: 'Pintar pela semente', color_seed: 'Semente da cor', palette: 'Paleta', driving: 'Direção', surface: 'Piso', lane_damage: 'Dano na pista' },\n hints: {\n quality: 'Alta: o kit com todo o detalhe. Leve: menos segmentos e sem interior (o modo leve da frota); vale para os veículos postos daqui em diante',\n paint_by_seed: 'Desligado: cada veículo mantém a própria pintura. Ligado: a cor da carroceria vem da semente e da paleta',\n palette: 'Auto: a paleta do grupo do veículo (civil, ou militar para os do exército)',\n driving: 'Arcade: o carro do jogo, simples e tolerante. Semi: corpo rígido com molas, atrito do pneu, marchas e pisos',\n surface: 'O chão sob as rodas no modo semi (aderência e aquaplanagem)',\n lane_damage: 'Com o que o carro da pista sai; ele anda no modo semi e o modelo de dano define pneus, freio e motor',\n },\n options: {\n quality: { high: 'Alta', lite: 'Leve' },\n palette: { auto: 'Auto', civil: 'Civil', military: 'Militar' },\n driving: { arcade: 'Arcade', semi: 'Semissimulação' },\n surface: { dry_asphalt: 'Asfalto seco', wet_asphalt: 'Asfalto molhado', dirt: 'Terra', grass: 'Grama', mud: 'Lama', blood: 'Sangue' },\n lane_damage: { none: 'Nenhum', into_wall: 'Contra o muro, sem frear', flat_tyre: 'Pneu furado (tiro de fuzil)', torn_tyre: 'Pneu desfeito: aro no chão', run_flat: 'Blindado, pneu furado (run-flat)', no_brake_fluid: 'Sem fluido de freio' },\n },\n actions: { repaint: 'Repintar com a semente', drive_lane: 'Percorrer a pista', clear_lane: 'Tirar o carro da pista', honk: 'Buzinar' },\n layers: { damageables: 'Caixas danificáveis por material', zones: 'Caixas das zonas por tipo', axes: 'Eixos do quadro de saída' },\n metrics: { vehicles: 'Veículos', triangles: 'Triângulos', draw_calls: 'Chamadas de desenho', size_error_mm: 'Medida contra DIMS', metal: 'Caixas de metal', glass: 'Caixas de vidro', rubber: 'Caixas de borracha', fuel: 'Caixas de combustível', speed: 'Velocidade na pista', lane: 'Distância na pista' },\n words: { yes: 'sim', no: 'não', open: 'soltos', tight: 'presos', on: 'acesos', off: 'apagados' },\n lane: { crash: 'Pista: o carro bateu no muro a {0} m/s', end: 'Pista: o carro parou a {0} m do muro', damage: 'Pista: a batida amassou {0} e quebrou {1}' },\n scenarios: {\n vehicles_9mm_windshield: 'Veículos: 9 mm atravessa o para-brisa',\n vehicles_shotgun_door: 'Veículos: espingarda na porta',\n vehicles_ram_front: 'Veículos: bater de frente',\n vehicles_engine_fire: 'Veículos: fogo no motor',\n vehicles_fuel_tank: 'Veículos: atirar no tanque (vaza, pega fogo, explode)',\n vehicles_unbolt_wheel: 'Veículos: soltar a roda com a chave inglesa',\n vehicles_tear_bumper: 'Veículos: arrancar o para-choque',\n vehicles_break_mirror: 'Veículos: quebrar o retrovisor',\n vehicles_kill_battery: 'Veículos: matar a bateria (faróis apagam)',\n vehicles_rollover: 'Veículos: capotar',\n vehicles_melt: 'Veículos: derreter (fogo longo queima os pneus)',\n vehicles_drive_arcade: 'Veículos: direção arcade numa pista que acaba num muro',\n vehicles_drive_semi: 'Veículos: frenagem da semissimulação no seco, no molhado e na lama',\n vehicles_burnt_wreck: 'Veículos: o sedã queimado sai do kit queimado, sem os vidros',\n },\n checks: {\n windshield_holes: 'Para-brisa: {0} furo(s), atravessou {1:b} (esperado: 1, sim)',\n windshield_cracks: 'Para-brisa trincou: {0} trinca(s), estado {1} (esperado: damaged)',\n door_marks: 'Porta dianteira esquerda: {0} furo(s), {1} amassado(s), vida {2}/{3} (esperado: 2 marcas ou mais)',\n front_crush: 'Frente amassada: para-choque {0} amassado(s), capô {1} (esperado: 1 ou mais cada)',\n bumper_off: 'O para-choque soltou: {0} (esperado: bumper_front)',\n engine_burning: 'Motor: pegando fogo {0:b}, {1} °C (esperado: sim, acima de 250)',\n ignite_lines: 'Linhas de ignição no log: {0} (esperado: 1 ou mais)',\n tank_leaking: 'Tanque vazando: {0} vazamento(s), {1} L restantes (esperado: 1 ou mais, menos de 55)',\n ignited: 'Pegou fogo: {0} linha(s) de ignição (esperado: 1 ou mais)',\n exploded: 'Explodiu: {0} explosão (esperado: 1)',\n wheel_wrench: 'Chave na roda: parafusos {0:open}, {1} grupo(s), {2} linha(s) de soltura (esperado: soltos, 2 ou mais, 1)',\n loose_parts: 'Peças soltas: {0} (esperado: bumper_front)',\n mirror_broken: 'Retrovisor esquerdo: {0} (esperado: broken)',\n battery_before: 'Antes: faróis acesos e dá partida (esperado: sim)',\n battery_after: 'Sem bateria: faróis {0:on}, partida {1:b} (esperado: apagados, não)',\n rolled_over: 'Capotou: {0:b} (esperado: sim)',\n roof: 'Teto: vida {0}/{1}, {2} amassado(s) (esperado: menos que o máximo, 1 ou mais)',\n tyre_melt: 'Pneu: {0}, derretido {1}%, {2} linha(s) de derretimento (esperado: melted ou mais de 50%)',\n arcade_crash: 'Arcade: bate no muro a {0} m/s (esperado: a batida acima de 4 m/s, no máximo {1})',\n arcade_bounce: 'Arcade: o carro volta a {0} m/s (esperado: abaixo de 0)',\n arcade_noise: 'Arcade: {0} ruído(s) de motor e {1} de batida (esperado: 1 ou mais de cada)',\n semi_order: 'Semi: frear de 80 km/h leva no seco {0} m, no molhado {1} m, na lama {2} m (esperado: seco menor que molhado menor que lama)',\n semi_mud: 'Semi: um carro 2WD na lama {0:on} (esperado: atolado, com evento de atolamento)',\n wreck_burnt: 'Sedã queimado: marca de queimado {0:b} (esperado: sim)',\n wreck_glass: 'Sedã queimado: {0} zona(s) de vidro, {1} ainda acima de 0 (esperado: 1 ou mais, nenhuma acima de 0)',\n },\n },\n}\n\n/** Fills a check sentence: `{i}` plain, `{i:b}` yes / no, `{i:open}` open / tight, `{i:on}` on / off. In English the `:b` form prints the value itself (true, false, undefined), as the page does. */\nexport function fill(text: VehiclesText, locale: string, template: string, ...values: readonly unknown[]): string {\n return template.replace(/\\{(\\d+)(?::(b|open|on))?\\}/g, (_match, index: string, kind?: string) => {\n const value = values[Number(index)]\n if (kind === 'b') return locale === 'en' ? String(value) : value ? text.words.yes : text.words.no\n if (kind === 'open') return value ? text.words.open : text.words.tight\n if (kind === 'on') return value ? text.words.on : text.words.off\n return String(value)\n })\n}\n","/**\n * How a vehicle sounds, as data. An engine is a few loops crossfaded by RPM (idle, low/mid, high) plus a load layer (intake and exhaust roar) that\n * follows the throttle, the way a sampled engine is mixed: when recorded loops arrive they take the same ids and the same crossfade. The pitch of\n * each tone layer is the firing frequency of the engine (`rpm / 60 × cylinders / 2` for a four-stroke) times its harmonic.\n */\n\n/** One tone layer of the engine: the loop id, where in the RPM range it is loudest (0 idle … 1 redline), and its level and cutoff. */\nexport type EngineLayer = {\n readonly sound: string\n /** Normalised RPM (0 at idle, 1 at the redline) where the layer is loudest. */\n readonly centre: number\n /** How far from `centre` the layer fades out (equal-power crossfade). */\n readonly width: number\n /** Multiple of the firing frequency the oscillator plays at. */\n readonly harmonic: number\n /** Level at full load. */\n readonly gain: number\n /** Low-pass cutoff, Hz, from no load at idle to full load at the redline. */\n readonly cutoff: readonly [min: number, max: number]\n}\n\n/** The roar of the intake and exhaust: a noise loop that opens with the throttle and the RPM. */\nexport type EngineLoadLayer = { readonly sound: string; readonly gain: number; readonly cutoff: readonly [min: number, max: number] }\n\nexport type EngineProfile = {\n readonly id: string\n readonly cylinders: number\n readonly idleRpm: number\n readonly redlineRpm: number\n /** Gear ratios times final drive per m/s, to guess the RPM from the speed when the driver has no engine model (the arcade driver). */\n readonly rpmPerMps: readonly number[]\n readonly layers: readonly EngineLayer[]\n readonly load: EngineLoadLayer\n /** Level with the throttle closed, as a share of full load (engine braking is quieter and darker). */\n readonly closedThrottle: number\n}\n\n/** The sound ids a vehicle plays besides its engine. Every one is a key of `VEHICLE_SOUND_BANK`, and a game can point any of them elsewhere. */\nexport type VehicleSoundKeys = {\n readonly start: string\n readonly stop: string\n readonly fail: string\n readonly crashLight: string\n readonly crashMedium: string\n readonly crashHeavy: string\n readonly skidAsphalt: string\n readonly skidDirt: string\n readonly roll: string\n /** Pads squealing on the discs as a car brakes to a stop (not a skid: the tyres still grip). */\n readonly brakeSqueal: string\n /** A body hit by the vehicle; a game points it at its own (a zombie, an animal) through `sounds` or the `hit` call. */\n readonly hitBody: string\n /** An emergency siren, its pitch swept by the vehicle (`frame.siren`). */\n readonly siren: string\n /** A helicopter's blades (`frame.rotor`). */\n readonly rotor: string\n}\n\nexport const DEFAULT_VEHICLE_SOUND_KEYS: VehicleSoundKeys = {\n start: 'engine_start',\n stop: 'engine_stop',\n fail: 'engine_fail',\n crashLight: 'crash_light',\n crashMedium: 'crash_medium',\n crashHeavy: 'crash_heavy',\n skidAsphalt: 'tire_skid_asphalt',\n skidDirt: 'tire_skid_dirt',\n roll: 'tire_roll',\n brakeSqueal: 'brake_squeal',\n hitBody: 'vehicle_hit_pedestrian',\n siren: 'siren',\n rotor: 'helicopter_rotor_loop',\n}\n\n/** The speed of the hit, m/s, where a crash stops being light (≈ 22 km/h: dents and plastic) and where it turns heavy (≈ 50 km/h: metal folds, glass goes). */\nexport const CRASH_SPEEDS = { medium: 6, heavy: 14 } as const\n\nconst layers = (id: string, cutoffs: readonly (readonly [number, number])[], gains: readonly number[]): EngineLayer[] => [\n { sound: `engine_${id}_low`, centre: 0, width: 0.5, harmonic: 1, gain: gains[0] as number, cutoff: cutoffs[0] as readonly [number, number] },\n { sound: `engine_${id}_mid`, centre: 0.45, width: 0.5, harmonic: 1, gain: gains[1] as number, cutoff: cutoffs[1] as readonly [number, number] },\n { sound: `engine_${id}_high`, centre: 1, width: 0.6, harmonic: 2, gain: gains[2] as number, cutoff: cutoffs[2] as readonly [number, number] },\n]\n\n/** A four-cylinder petrol car: 800 to 6 500 rpm. */\nexport const CAR_ENGINE: EngineProfile = {\n id: 'car',\n cylinders: 4,\n idleRpm: 800,\n redlineRpm: 6500,\n // a 5-speed hatch: 1st tops at ~13 m/s, 5th at ~50 m/s\n rpmPerMps: [500, 300, 205, 155, 125],\n layers: layers('car', [[220, 520], [420, 1300], [900, 2600]], [0.11, 0.075, 0.04]),\n load: { sound: 'engine_car_load', gain: 0.05, cutoff: [350, 1600] },\n closedThrottle: 0.55,\n}\n\n/** A six-cylinder diesel truck or bus: 650 to 2 600 rpm, low and clattering. */\nexport const TRUCK_ENGINE: EngineProfile = {\n id: 'truck',\n cylinders: 6,\n idleRpm: 650,\n redlineRpm: 2600,\n rpmPerMps: [420, 260, 170, 120, 90, 72],\n layers: layers('truck', [[160, 380], [300, 800], [600, 1500]], [0.13, 0.08, 0.035]),\n load: { sound: 'engine_truck_load', gain: 0.06, cutoff: [250, 900] },\n closedThrottle: 0.6,\n}\n\n/** A four-cylinder sport bike: 1 300 to 12 000 rpm, bright and fast to rev. */\nexport const BIKE_ENGINE: EngineProfile = {\n id: 'bike',\n cylinders: 4,\n idleRpm: 1300,\n redlineRpm: 12000,\n rpmPerMps: [900, 640, 500, 410, 350, 310],\n layers: layers('bike', [[350, 900], [700, 2200], [1500, 4200]], [0.08, 0.07, 0.05]),\n load: { sound: 'engine_bike_load', gain: 0.045, cutoff: [600, 2600] },\n closedThrottle: 0.5,\n}\n\nexport const ENGINE_PROFILES: Readonly<Record<string, EngineProfile>> = { car: CAR_ENGINE, truck: TRUCK_ENGINE, bike: BIKE_ENGINE }\n","import { DEFAULT_VEHICLE_SOUND_KEYS } from '../audio/profiles'\nimport type { VehicleSoundKeys } from '../audio/profiles'\nimport type { EffectSink, Vec3 } from '@adatechnology/game-contracts'\nimport type { VehicleKit } from '@adatechnology/game-vehicles'\n\nimport type { VehicleFleetContent } from '../build'\n\n/** The fleet the area runs on: its palettes and sizes, and how it is installed in a kit (`defaultVehicleFleet()` of `game-kit-defaults`). */\nexport type VehiclesTestFleet = VehicleFleetContent & { installFleet(kit: VehicleKit): void }\n\n/** What the module needs of a document (canvas textures of the kit): a real `document`, or a stub in Node. */\nexport type DocumentLike = { createElement(tag: string): unknown }\n\n/** The host's effects (`host.effects`, an `EffectSink` of the contracts: `game-vfx-three` is one): the module asks by id and writes no particle code. */\nexport type EffectsLike = EffectSink\n\n/** The events the module turns into effect requests, and the effect id each one asks for. A game maps its own ids over these. */\nexport type VehicleEffectIds = {\n readonly ignite: string\n readonly explode: string\n readonly glass: string\n readonly sparks: string\n readonly leak: string\n /** The leak of a pierced tank caught fire: the whole sequence (fire along the pool, then the blast). `leak` is only the pool and the drips. */\n readonly leakIgnited: string\n readonly exhaust: string\n}\n\nexport const defaultEffectIds: VehicleEffectIds = {\n ignite: 'vehicle_fire',\n explode: 'car_fuel_tank',\n glass: 'glass_burst',\n sparks: 'impact_metal',\n leak: 'vehicle_leak',\n leakIgnited: 'vehicle_leak_ignited',\n exhaust: 'vehicle_exhaust',\n}\n\n/**\n * The sounds the module asks of `host.audio`, by id of the host's banks: the horn (placed at the car), and the vehicle's own sounds (`createVehicleSound`: the starter, the\n * crashes by speed, the tyres). The engine loops come from the engine profile.\n */\nexport type VehicleSoundIds = { readonly horn: string } & VehicleSoundKeys\n\nexport const defaultSoundIds: VehicleSoundIds = { horn: 'horn_car', ...DEFAULT_VEHICLE_SOUND_KEYS }\n\n/** A damaged vehicle of the area: the item id, the fleet vehicle it is built from and the scenario of the kit applied while building. */\nexport type VehicleWreck = { readonly key: string; readonly vehicle: string; readonly scenario: string }\n\nexport const DEFAULT_TEST_WRECKS: readonly VehicleWreck[] = [\n { key: 'sedan_burnt', vehicle: 'midsize_sedan', scenario: 'burnt' },\n { key: 'hatch_burnt', vehicle: 'compact_hatch', scenario: 'burnt' },\n]\n\nexport type VehiclesTestOptions = {\n /**\n * The fleet content: paint palettes, measured sizes and the install into the default kit (`defaultVehicleFleet()` of `game-kit-defaults`). Default the ones of `game-vehicles-fleet`.\n * @deprecated pass `fleet`; the default is removed in the next major.\n */\n readonly fleet?: VehiclesTestFleet\n /** `en` or `pt-BR` (default). */\n readonly locale?: string\n /** The kit the vehicles are built with, per three.js namespace. Default: `createVehicleKit` with the fleet installed (`fleet.installFleet`). */\n readonly createKit?: (THREE: unknown) => VehicleKit\n readonly document?: DocumentLike\n /** The three.js namespace the door, hood and trunk clips are computed with (they are plain numbers, so any copy works). Default: the global `THREE`; without either the items bring no clips. */\n readonly three?: unknown\n /** The vehicles to lay out, as fleet ids (default the 8 of the Frota test: hatch, sedan, pickup, sport bike, box truck, city bus, battle tank, attack helicopter). */\n readonly vehicles?: readonly string[]\n /** Wrecks laid out after the vehicles: item `key` is the fleet vehicle `vehicle` built with the registered damage `scenario` (default `sedan_burnt` and `hatch_burnt`, the fleet's `burnt`; an empty list lays none). */\n readonly wrecks?: readonly VehicleWreck[]\n /** Effect ids requested through `host.effects` (the defaults are ids of `game-vfx`: the Garagem's `car_fuel_tank` blast, the `vehicle_fire`, `vehicle_leak` (pool and drips only), `vehicle_leak_ignited` (the whole sequence) and `vehicle_exhaust` recipes written around a car from `engine_smoke` and `fuel_leak`, and the point-based `glass_burst` and `impact_metal`). */\n readonly effects?: Partial<VehicleEffectIds>\n /** Sound ids requested through `host.audio` (the defaults: the vehicle bank of this package). */\n readonly sounds?: Partial<VehicleSoundIds>\n}\n\n/** The part of the test room the scenarios use (the room's `ScenarioContext.room` has all of it). */\nexport type PartView = {\n holes: { through?: boolean }[]\n cracks: unknown[]\n dents: unknown[]\n status: string\n hp: number\n maxHp: number\n temperature: number\n burning: boolean\n liters: number\n melt: number\n}\n\nexport type SpawnedVehicle = { objectId: string; root: { userData: Record<string, unknown> } }\n\nexport type VehiclesRoom = {\n spawn(item: string, position?: Vec3, rotationY?: number): SpawnedVehicle\n setTool(weaponId: string): void\n /** Lets the tool in hand finish its draw time (the room's rule: a weapon cannot fire the moment it is taken). */\n waitUntilReady(): void\n look(position: Vec3, target: Vec3): void\n use(hold?: number): void\n playAnimation(clipId: string, objectId?: string): boolean\n world: {\n part(object: string, part: string): PartView\n hit(object: string, hit: Record<string, unknown>): unknown\n disassemble(object: string, joint: string, tool: string, dt: number): number\n state(object: string): { joints: { id: string; open: boolean }[]; groups: unknown[][] }\n }\n log: { entries(filter: { type?: string; objectId?: string }): readonly unknown[] }\n}\n\n/** What a scenario needs of the room: the pass/fail line, time, and the room for the ones that shoot and hit. */\nexport type VehiclesContext = {\n room: VehiclesRoom\n expect(condition: boolean, label: string, data?: Record<string, unknown>): void\n step(seconds: number): void\n}\n","import type { EngineProfile } from './profiles'\n\n/** What one engine loop is set to this frame. `frequency` is absent for the load layer (noise has no pitch). */\nexport type EngineLayerSetting = { readonly sound: string; readonly volume: number; readonly frequency?: number; readonly cutoff: number }\n\nexport type EngineMixInput = {\n readonly rpm: number\n /** 0..1, how open the throttle is (the engine's load). */\n readonly throttle: number\n}\n\nconst clamp01 = (v: number): number => (v < 0 ? 0 : v > 1 ? 1 : v)\n\n/** The firing frequency of a four-stroke engine, Hz: every cylinder fires once every two turns. */\nexport const firingHz = (profile: EngineProfile, rpm: number): number => (rpm / 60) * (profile.cylinders / 2)\n\n/** RPM as a share of the range: 0 at idle, 1 at the redline. */\nexport const rpmShare = (profile: EngineProfile, rpm: number): number => clamp01((rpm - profile.idleRpm) / (profile.redlineRpm - profile.idleRpm))\n\n/** Equal-power weight of a layer centred at `centre` with `width` at the normalised RPM `n`. */\nexport const layerWeight = (centre: number, width: number, n: number): number => {\n const d = Math.abs(n - centre) / width\n return d >= 1 ? 0 : Math.cos((d * Math.PI) / 2)\n}\n\n/**\n * The engine's loops for an RPM and a throttle: every tone layer at the firing frequency times its harmonic, faded in and out across the RPM range so\n * the sum stays even, louder and brighter under load; the load layer opens with the throttle. A stopped engine (`rpm` 0) is silent.\n */\nexport function engineMix(profile: EngineProfile, input: EngineMixInput): EngineLayerSetting[] {\n const throttle = clamp01(input.throttle)\n const on = input.rpm > 0\n const n = rpmShare(profile, input.rpm)\n const level = on ? profile.closedThrottle + (1 - profile.closedThrottle) * throttle : 0\n const open = 0.5 * n + 0.5 * throttle\n const hz = firingHz(profile, input.rpm)\n const tones = profile.layers.map((layer) => ({\n sound: layer.sound,\n volume: layer.gain * level * layerWeight(layer.centre, layer.width, n),\n frequency: hz * layer.harmonic,\n cutoff: layer.cutoff[0] + (layer.cutoff[1] - layer.cutoff[0]) * open,\n }))\n const load = profile.load\n return [\n ...tones,\n { sound: load.sound, volume: on ? load.gain * (0.15 + 0.85 * throttle) * (0.35 + 0.65 * n) : 0, cutoff: load.cutoff[0] + (load.cutoff[1] - load.cutoff[0]) * open },\n ]\n}\n\n/**\n * A guess of the RPM from the speed for a driver without an engine model: the gear is kept between calls (up above 85% of the redline, down below\n * 40%), so the RPM climbs and drops at each shift as it does in a real car.\n */\nexport function createGearGuess(profile: EngineProfile): { rpm(speed: number, throttle: number): number; readonly gear: number } {\n let gear = 0\n return {\n rpm(speed, throttle) {\n const v = Math.abs(speed)\n const ratios = profile.rpmPerMps\n if (v < 0.3) {\n gear = 0\n return profile.idleRpm + (profile.redlineRpm - profile.idleRpm) * 0.12 * clamp01(throttle)\n }\n const at = (g: number): number => v * (ratios[g] as number)\n while (gear < ratios.length - 1 && at(gear) > profile.redlineRpm * 0.85) gear++\n while (gear > 0 && at(gear) < profile.redlineRpm * 0.4) gear--\n return Math.max(profile.idleRpm, Math.min(profile.redlineRpm, at(gear)))\n },\n get gear() {\n return gear\n },\n }\n}\n","import type { AudioSink, LoopHandle, Vec3 } from '@adatechnology/game-contracts'\n\nimport type { EngineBudget } from './engine-budget'\nimport { createGearGuess, engineMix } from './engine-mix'\nimport { CAR_ENGINE, CRASH_SPEEDS, DEFAULT_VEHICLE_SOUND_KEYS } from './profiles'\nimport type { EngineProfile, VehicleSoundKeys } from './profiles'\n\n/** What the vehicle is doing this frame. Without `rpm` (a driver with no engine model) the RPM is guessed from the speed through the profile's gears. */\nexport type VehicleSoundFrame = {\n readonly dt: number\n readonly position: Vec3\n /** m/s, signed or not. */\n readonly speed: number\n /** 0..1. */\n readonly throttle: number\n readonly rpm?: number\n /** 0..1: how much the tyres slide (the largest wheel slip; 1 = locked or spinning). */\n readonly slip?: number\n /** What the tyres are on: `dirt` for earth, gravel, sand or grass; anything else squeals as asphalt. */\n readonly surface?: 'asphalt' | 'dirt'\n /** 0..1, how hard the brakes are pressed: the pads squeal as the car comes to a stop without skidding. */\n readonly brake?: number\n /** An emergency vehicle's siren: `wail` sweeps 650–1500 Hz in ~4 s, `yelp` in a quarter second; absent or `off`, silent. */\n readonly siren?: 'off' | 'wail' | 'yelp'\n /** 0..1, how fast a helicopter's rotor turns (the blades spool up and down with it). */\n readonly rotor?: number\n}\n\nexport type VehicleSoundOptions = {\n readonly profile?: EngineProfile\n /** Any of the one-shot and tyre ids, pointed at other sounds. */\n readonly sounds?: Partial<VehicleSoundKeys>\n /** Seconds the starter turns before the engine catches (the `engine_start` recipe catches at 0.75 s). */\n readonly crankSeconds?: number\n /** Shared by the vehicles of a scene: only the nearest few keep their loops (`createEngineBudget`). */\n readonly budget?: EngineBudget\n}\n\n/** What was asked of the sink, for the checks and the bench: the RPM in use and the level of each loop. */\nexport type VehicleSoundReading = {\n readonly running: boolean\n readonly rpm: number\n readonly levels: Readonly<Record<string, number>>\n}\n\nexport type VehicleSound = {\n /** Turns the key: the starter, then the engine catches with a flare of RPM. `fail` cranks without catching (no fuel, a dead engine). */\n start(position: Vec3, options?: { readonly fail?: boolean }): void\n /** Ignition off: the engine runs down. */\n stop(position: Vec3): void\n /** A hit at `speed` m/s: light, medium or heavy by speed, louder with it. */\n crash(speed: number, position: Vec3): 'light' | 'medium' | 'heavy'\n /** A body hit at `speed` m/s (a person, an animal; `sound` names another id, a zombie in a game), louder with the speed. */\n hit(speed: number, position: Vec3, sound?: string): void\n update(frame: VehicleSoundFrame): void\n readonly reading: VehicleSoundReading\n dispose(): void\n}\n\nconst clamp01 = (v: number): number => (v < 0 ? 0 : v > 1 ? 1 : v)\n\n/**\n * The sounds of one vehicle on a host's sink (`ModuleHost.audio`): the engine loops by RPM and load, the starter, the tyres skidding and rolling,\n * and crashes by speed. The loops are placed at the vehicle every frame (distance and side come from the sink). Works without a sink (silent).\n */\nexport function createVehicleSound(audio: AudioSink | undefined, options: VehicleSoundOptions = {}): VehicleSound {\n const profile = options.profile ?? CAR_ENGINE\n const keys = { ...DEFAULT_VEHICLE_SOUND_KEYS, ...options.sounds }\n const crankSeconds = options.crankSeconds ?? 0.75\n const gears = createGearGuess(profile)\n const loops = new Map<string, LoopHandle>()\n const budget = options.budget\n // the key the budget knows this vehicle by\n const self = {}\n const levels: Record<string, number> = {}\n // running: the engine turns; cranking counts down the starter; flare is the RPM the engine overshoots to as it catches\n const state = { running: false, cranking: 0, catches: false, flare: 0, rpm: 0, sirenPhase: 0 }\n\n const loopOf = (sound: string): LoopHandle | undefined => {\n let handle = loops.get(sound)\n if (!handle && audio?.loop) {\n handle = audio.loop(sound)\n loops.set(sound, handle)\n }\n return handle\n }\n const setLoop = (sound: string, volume: number, position: Vec3, extra: { frequency?: number; cutoff?: number } = {}): void => {\n levels[sound] = volume\n // a silent loop that was never made stays unmade\n if (volume <= 0 && !loops.has(sound)) return\n loopOf(sound)?.set({ volume, position, ...(extra.frequency === undefined ? {} : { frequency: extra.frequency }), ...(extra.cutoff === undefined ? {} : { params: { cutoff: extra.cutoff } }) })\n }\n const play = (sound: string, position: Vec3, volume = 1): void => void audio?.play({ sound, position, volume })\n\n return {\n start(position, startOptions = {}) {\n if (state.running || state.cranking > 0) return\n state.catches = !startOptions.fail\n state.cranking = state.catches ? crankSeconds : 1.7\n play(state.catches ? keys.start : keys.fail, position)\n },\n stop(position) {\n if (!state.running && state.cranking <= 0) return\n state.running = false\n state.cranking = 0\n play(keys.stop, position)\n },\n crash(speed, position) {\n const v = Math.abs(speed)\n const kind = v >= CRASH_SPEEDS.heavy ? 'heavy' : v >= CRASH_SPEEDS.medium ? 'medium' : 'light'\n play(kind === 'heavy' ? keys.crashHeavy : kind === 'medium' ? keys.crashMedium : keys.crashLight, position, Math.min(1, 0.35 + v / 20))\n return kind\n },\n hit(speed, position, sound) {\n const v = Math.abs(speed)\n if (v < 0.5) return\n play(sound ?? keys.hitBody, position, Math.min(1, 0.3 + v / 15))\n },\n update(frame) {\n if (state.cranking > 0) {\n state.cranking -= frame.dt\n if (state.cranking <= 0 && state.catches) {\n state.running = true\n state.flare = 1\n }\n }\n state.flare = Math.max(0, state.flare - frame.dt / 0.9)\n const throttle = clamp01(frame.throttle)\n const driven = frame.rpm ?? gears.rpm(frame.speed, throttle)\n // as it catches the engine overshoots to ~2.2× idle and settles back\n const rpm = state.running ? Math.max(driven, profile.idleRpm * (1 + 1.2 * state.flare * state.flare)) : 0\n state.rpm = rpm\n // out of the budget (too many vehicles nearer the listener) every loop goes quiet; the state above keeps running so it comes back in step\n const heard = budget ? (budget.admit(self, frame.position) ? 1 : 0) : 1\n for (const layer of engineMix(profile, { rpm, throttle: Math.max(throttle, state.flare * 0.6) })) {\n setLoop(layer.sound, heard * layer.volume, frame.position, { ...(layer.frequency === undefined ? {} : { frequency: layer.frequency }), cutoff: layer.cutoff })\n }\n const speed = Math.abs(frame.speed)\n // a slide squeals once the slip passes ~15% and the car moves; on dirt it is a hiss, not a squeal\n const slide = clamp01(((frame.slip ?? 0) - 0.15) / 0.5) * clamp01(speed / 4)\n const dirt = frame.surface === 'dirt'\n setLoop(keys.skidAsphalt, heard * (dirt ? 0 : 0.16 * slide), frame.position, { cutoff: 1700 + 600 * slide })\n setLoop(keys.skidDirt, heard * (dirt ? 0.2 * slide : 0), frame.position, { cutoff: 500 + 500 * slide })\n // road noise grows with the speed and gets brighter\n setLoop(keys.roll, heard * 0.06 * clamp01(speed / 25), frame.position, { cutoff: 250 + 45 * Math.min(speed, 40) })\n // the pads squeal in the last metres of a stop on the brakes, while the tyres still grip (a skid is the tyres' sound, not the pads')\n const squeal = clamp01(((frame.brake ?? 0) - 0.3) / 0.4) * clamp01(speed / 0.8) * clamp01((5 - speed) / 2) * (slide > 0 ? 0 : 1)\n setLoop(keys.brakeSqueal, heard * 0.05 * squeal, frame.position, { cutoff: 3200 + 400 * squeal })\n // the siren's sweep is a triangle in time: up and down between 650 and 1500 Hz\n const siren = frame.siren ?? 'off'\n if (siren !== 'off' || loops.has(keys.siren)) {\n const period = siren === 'yelp' ? 0.25 : 4\n state.sirenPhase = (state.sirenPhase + frame.dt / period) % 1\n const tri = state.sirenPhase < 0.5 ? state.sirenPhase * 2 : 2 - state.sirenPhase * 2\n setLoop(keys.siren, heard * (siren === 'off' ? 0 : 0.07), frame.position, { frequency: 650 + 850 * tri, cutoff: 2600 })\n }\n const rotor = clamp01(frame.rotor ?? 0)\n setLoop(keys.rotor, heard * 0.12 * rotor, frame.position, { cutoff: 180 + 220 * rotor })\n },\n get reading() {\n return { running: state.running, rpm: state.rpm, levels: { ...levels } }\n },\n dispose() {\n budget?.release(self)\n for (const handle of loops.values()) handle.stop()\n loops.clear()\n },\n }\n}\n","// The vehicle sounds as recipes of @adatechnology/game-audio, made by the kit (no team delivered vehicle sounds beyond the game's saw, horn and crash):\n// engines as loops crossfaded by RPM, the starter, tyres, crashes by speed and the doors, hood and trunk of a car. The ids follow the sound list\n// (`sons/checklist-sons.md`, 5.6), so a recorded loop or one-shot replaces a recipe by registering the same id.\nimport { sceneMany as many, sceneNoise as noise, sceneRecipe, sceneTone as tone } from '@adatechnology/game-audio'\nimport type { Falloff, Layer, LoopRecipe, SampleAlias, SoundBank, SoundRecipe } from '@adatechnology/game-audio'\n\nimport { firingHz } from './engine-mix'\nimport { CAR_ENGINE } from './profiles'\n\n/** How a vehicle loop falls off: `1 / (1 + d² × 0.004)`, the game's one-shot curve, with the cutoff muffled by `1 + d × 0.01` (a car far away is dull). */\nexport const VEHICLE_LOOP_FALLOFF: Falloff = { model: 'inverse_square', k: 0.004, cutoffK: 0.01 }\n\nconst SDK = 'sdk: vehicle sounds (sons/checklist-sons.md 5.6)'\n\n// the loops are set every frame by the vehicle: short time constants, so the pitch follows the RPM through a shift\nconst SMOOTHING = { volume: 0.06, frequency: 0.04 } as const\n\nconst toneLoop = (id: string, wave: OscillatorType, filter: BiquadFilterType, cutoff: number, q: number, line: string): LoopRecipe => ({\n id,\n bus: 'world',\n order: 'game_loop',\n source: { kind: 'osc', wave, loop: true },\n filters: { mode: 'serial', bank: [{ type: filter, frequency: { set: cutoff }, q }] },\n smoothing: SMOOTHING,\n falloff: VEHICLE_LOOP_FALLOFF,\n pan: true,\n sources: [SDK, line],\n})\n\nconst noiseLoop = (id: string, filter: BiquadFilterType, cutoff: number, q: number, line: string): LoopRecipe => ({\n id,\n bus: 'world',\n order: 'game_loop',\n source: { kind: 'noise', offset: 'random', loop: true },\n filters: { mode: 'serial', bank: [{ type: filter, frequency: { set: cutoff }, q }] },\n smoothing: SMOOTHING,\n falloff: VEHICLE_LOOP_FALLOFF,\n pan: true,\n sources: [SDK, line],\n})\n\nconst engineLoops = (id: string, low: number, mid: number, high: number, load: number): LoopRecipe[] => [\n toneLoop(`engine_${id}_low`, 'sawtooth', 'lowpass', low, 1.4, 'idle and low RPM: the firing frequency, a saw through a low-pass'),\n toneLoop(`engine_${id}_mid`, 'square', 'lowpass', mid, 0.9, 'mid RPM: odd harmonics, the bark'),\n toneLoop(`engine_${id}_high`, 'sawtooth', 'bandpass', high, 1.2, 'high RPM: the second harmonic through a band-pass, the scream near the redline'),\n noiseLoop(`engine_${id}_load`, 'bandpass', load, 0.8, 'intake and exhaust roar, opened by the throttle'),\n]\n\n/** The engines (car, truck, bike) and the tyres, as loops. */\nexport const VEHICLE_LOOPS: readonly LoopRecipe[] = [\n ...engineLoops('car', 400, 900, 1600, 700),\n ...engineLoops('truck', 280, 600, 1000, 500),\n ...engineLoops('bike', 600, 1400, 2800, 1200),\n noiseLoop('tire_skid_asphalt', 'bandpass', 1900, 5, 'rubber squealing on asphalt: a narrow band of noise near 2 kHz'),\n noiseLoop('tire_skid_dirt', 'lowpass', 700, 0.8, 'tyres sliding on dirt and gravel: a dull, wide hiss'),\n noiseLoop('tire_roll', 'lowpass', 400, 0.7, 'road noise of the tyres rolling, brighter with the speed'),\n // a pad on a disc: a thin, nearly pure whistle near 3.4 kHz (a narrow band of noise, so it wavers as a real squeal does)\n // a siren: a square through a low-pass, its pitch swept by the vehicle every frame (wail: a slow rise and fall; yelp: a fast one)\n toneLoop('siren', 'square', 'lowpass', 2600, 0.8, 'emergency siren, the sweep driven by the vehicle'),\n // the blades: a low rumble chopped at the blade-pass rate (≈ 18 Hz for a light helicopter's main rotor)\n {\n ...noiseLoop('helicopter_rotor_loop', 'lowpass', 320, 0.9, 'helicopter rotor: low rumble chopped by the blades'),\n modulators: [{ target: 'gain', wave: 'sine', rate: 18, depth: 0.45, base: 0.55 }],\n },\n noiseLoop('brake_squeal', 'bandpass', 3400, 28, 'brake pads squealing on the discs as the car comes to a stop'),\n]\n\nconst recipe = (id: string, layers: readonly Layer[], line: string): SoundRecipe => ({ ...sceneRecipe(id, layers, line), sources: [SDK, line] })\n\n// the starter turning the engine over: a compression pulse every ~0.1 s and the motor's whine\nconst crank = (count: number, spacing: number): Layer[] => [\n { ...noise({ type: 'bandpass', f: [300, 380], q: 1.5, d: 0.07, vol: 0.45 }), repeat: { count, spacing } },\n tone({ wave: 'sawtooth', f: 95, f2: count > 8 ? 70 : 110, d: count * spacing, vol: 0.035 }),\n]\n\n// a latch: a short click and a tiny ring\nconst latch = (delay: number, vol: number): Layer[] => [\n noise({ type: 'bandpass', f: [2600, 3200], q: 3, d: 0.018, vol, delay }),\n tone({ f: 1300, f2: 1180, d: 0.025, vol: vol * 0.15, delay: delay + 0.004 }),\n]\n\n/** The one-shots: the starter, the engine stopping, crashes by speed, and the doors, trunk and hood of a car. */\nexport const VEHICLE_SOUNDS: readonly SoundRecipe[] = [\n // the engine catches at 0.75 s: the loops take over from there (the vehicle flares the RPM)\n recipe('engine_start', [...crank(7, 0.105), tone({ wave: 'sawtooth', f: 45, f2: 27, d: 0.35, vol: 0.3, delay: 0.72 }), noise({ f: 260, d: 0.3, vol: 0.35, delay: 0.72 })], 'starter cranking, then the engine catches'),\n recipe('engine_fail', [...crank(13, 0.125), ...latch(1.65, 0.2)], 'starter cranking slower and slower, the engine never catches, the key released'),\n recipe('engine_stop', [tone({ wave: 'sawtooth', f: 27, f2: 8, d: 0.45, vol: 0.3 }), noise({ f: 200, f2: 60, d: 0.4, vol: 0.32 }), noise({ type: 'bandpass', f: 120, q: 2, d: 0.12, vol: 0.3, delay: 0.32 })], 'ignition off: the engine runs down and shudders to a stop'),\n // light: a dent and plastic giving; medium: the body folding and a pane cracking; heavy: metal folding, glass going, debris falling\n recipe(\n 'crash_light',\n [tone({ f: 110, f2: 55, d: 0.16, vol: 0.7 }), noise({ type: 'bandpass', f: 1100, q: 1, d: 0.18, vol: 0.85, wet: 0.2 }), noise({ type: 'highpass', f: 2500, d: 0.05, vol: 0.45 }), ...many(3, () => noise({ type: 'bandpass', f: [1800, 3200], q: 3, d: 0.03, vol: 0.2, delay: [0.03, 0.2] }))],\n 'crash below 22 km/h: bumper and plastic, a dull dent',\n ),\n recipe(\n 'crash_medium',\n [\n tone({ f: 85, f2: 38, d: 0.3, vol: 1.1 }),\n noise({ type: 'bandpass', f: 700, q: 0.9, d: 0.5, vol: 0.8, wet: 0.3 }),\n ...many(5, () => noise({ type: 'bandpass', f: [500, 1300], q: 2, d: [0.08, 0.18], vol: 0.55, delay: [0, 0.35] })),\n ...many(6, () => tone({ f: [3500, 7000], d: 0.06, vol: 0.08, delay: [0.05, 0.5] })),\n ],\n 'crash at 22–50 km/h: the body folding, a pane cracking',\n ),\n recipe(\n 'crash_heavy',\n [\n tone({ f: 65, f2: 28, d: 0.6, vol: 1.5 }),\n noise({ f: 900, f2: 150, d: 0.9, vol: 1.3, wet: 0.5 }),\n ...many(9, () => noise({ type: 'bandpass', f: [300, 1200], q: 2, d: [0.1, 0.25], vol: 0.6, delay: [0, 0.7] })),\n noise({ type: 'highpass', f: 3200, d: 0.5, vol: 0.7, delay: 0.03, wet: 0.4 }),\n ...many(14, () => tone({ f: [3000, 7500], d: [0.05, 0.12], vol: 0.12, delay: [0.05, 1.2] })),\n ...many(6, () => noise({ type: 'bandpass', f: [1500, 3000], q: 2, d: 0.04, vol: 0.25, delay: [0.5, 1.5] })),\n ],\n 'crash above 50 km/h: metal folding, the glass going, debris falling',\n ),\n // a body hit by a car: the dull slap of the bumper on a person, the body folding over the bonnet, at speed a crack of the windscreen\n recipe(\n 'vehicle_hit_pedestrian',\n [\n tone({ f: 95, f2: 50, d: 0.14, vol: 0.9 }),\n noise({ type: 'lowpass', f: 600, d: 0.12, vol: 0.8 }),\n noise({ type: 'bandpass', f: 280, q: 1.2, d: 0.18, vol: 0.55, delay: 0.09 }),\n noise({ type: 'highpass', f: 2600, d: 0.05, vol: 0.18, delay: 0.1 }),\n ],\n 'a person hit by a car: the bumper slap, the body on the bonnet',\n ),\n // the game's horn (two squares at 415 and 523 Hz, jogo L70272) heard from where the car is; a truck's air horn lower and longer\n recipe('horn_car', [tone({ wave: 'square', f: 415, d: 0.6, vol: 0.09 }), tone({ wave: 'square', f: 523, d: 0.6, vol: 0.09 })], 'car horn: the game chord, placed and panned'),\n recipe('horn_truck', [tone({ wave: 'sawtooth', f: 220, d: 1.1, vol: 0.1 }), tone({ wave: 'sawtooth', f: 277, d: 1.1, vol: 0.08 }), noise({ type: 'bandpass', f: 900, q: 2, d: 1.1, vol: 0.05 })], 'truck air horn: low reedy chord'),\n // a car door is a padded \"tum\" with a latch, not a hollow metal box (the fridge's shut_metal)\n recipe('car_door_open', [...latch(0, 0.32), noise({ f: 400, d: 0.06, vol: 0.14, delay: 0.035 })], 'car door: the handle pulled, the latch released, the seal letting go'),\n recipe('car_door_close', [tone({ f: 75, f2: 48, d: 0.16, vol: 0.75 }), noise({ f: 320, d: 0.1, vol: 0.6 }), ...latch(0.012, 0.3)], 'car door shut: a dull padded thump and the latch catching'),\n recipe('car_trunk_close', [tone({ f: 90, f2: 55, d: 0.15, vol: 0.65 }), noise({ type: 'bandpass', f: 500, q: 1, d: 0.12, vol: 0.5 }), ...latch(0.01, 0.28), noise({ type: 'bandpass', f: 1800, q: 3, d: 0.04, vol: 0.1, delay: 0.06 })], 'trunk or hatch shut: a lighter thump, the latch and a small rattle'),\n recipe('car_hood_close', [tone({ f: 70, f2: 40, d: 0.22, vol: 0.8 }), noise({ type: 'bandpass', f: 850, q: 1.4, d: 0.2, vol: 0.6, wet: 0.3 }), tone({ f: 900, f2: 860, d: 0.18, vol: 0.05 }), ...latch(0.015, 0.3)], 'hood slammed: a big sheet of metal ringing a little, the latch'),\n]\n\n/**\n * The RPM each car recording runs at, measured on the files (the crank turning at 16.7 and 42 Hz, the firing at four times that: a V8). A layer\n * plays its file at `rpm / recorded rpm`.\n */\nexport const CAR_RECORDED_RPM = { idle: 1000, high: 2520 } as const\n\n/** Where the start and the stop sit in the recording of a car starting, running and stopping (`engine_start_run_stop`), in seconds. */\nexport const CAR_START_RUN_STOP = {\n /** The take the times below were measured on. */\n take: '_01.',\n /** The starter and the engine catching (at 0.58 s) and flaring; the loops take over at the crank time of the vehicle. */\n start: { offset: 0, duration: 1.3 },\n /** The ignition off: the engine running down to the end of the file. */\n stop: { offset: 9.96, duration: 0.64 },\n} as const\n\nconst carLayer = (id: string, file: string, rpm: number, harmonic: number, offset?: number): SampleAlias => ({\n id,\n file,\n loop: true,\n // the layer's oscillator plays the firing frequency times its harmonic: the file sounds at that frequency for the RPM it was recorded at\n baseFrequency: firingHz(CAR_ENGINE, rpm) * harmonic,\n falloff: VEHICLE_LOOP_FALLOFF,\n ...(offset === undefined ? {} : { offset }),\n})\n\n/**\n * The vehicle ids answered by the recordings of the kit's manifest (files kept by the game, never in the SDK): the car engine layers by RPM, the\n * start and the stop cut out of one recording, the door and the trunk. Each recipe above stays as the fallback while the files load or where the\n * game has none. `car_door_open` is a file id of its own and needs no alias; the hood, the truck, the bike, the tyres, crashes and horns have no\n * recording yet.\n */\nexport const VEHICLE_SAMPLE_ALIASES: readonly SampleAlias[] = [\n carLayer('engine_car_low', 'engine_loop_car_idle', CAR_RECORDED_RPM.idle, 1),\n carLayer('engine_car_mid', 'engine_loop_car_high', CAR_RECORDED_RPM.high, 1),\n // the same file as the mid layer, read from two seconds in, so the two do not sum in phase where they cross\n carLayer('engine_car_high', 'engine_loop_car_high', CAR_RECORDED_RPM.high, 2, 2),\n // the cut points are of take _01 (10.6 s); _02 (21.9 s) starts already running and idles at 9.96 s, so it is left out of both\n { id: 'engine_start', file: 'engine_start_run_stop', only: CAR_START_RUN_STOP.take, ...CAR_START_RUN_STOP.start, falloff: VEHICLE_LOOP_FALLOFF },\n { id: 'engine_stop', file: 'engine_start_run_stop', only: CAR_START_RUN_STOP.take, ...CAR_START_RUN_STOP.stop, falloff: VEHICLE_LOOP_FALLOFF },\n { id: 'car_door_close', file: 'car_door_shut' },\n { id: 'car_trunk_close', file: 'car_trunk_shut' },\n]\n\n/** The ids a host should decode as the vehicles load (`AudioSink.preload`): every aliased recording and the door's own file id. */\nexport const VEHICLE_PRELOAD_SOUNDS: readonly string[] = [...VEHICLE_SAMPLE_ALIASES.map((alias) => alias.id), 'car_door_open']\n\nexport const VEHICLE_SOUND_BANK: SoundBank = { id: 'vehicles_three', sounds: VEHICLE_SOUNDS, loops: VEHICLE_LOOPS, sampleAliases: VEHICLE_SAMPLE_ALIASES }\n","import { createVehicleCamera, defaultEye, mirrorPoses } from '@adatechnology/game-camera'\nimport type { MirrorPose, VehicleCameraMode, VehicleFrame, VehicleThreeLib } from '@adatechnology/game-camera'\nimport { markKitOrigin } from '@adatechnology/game-contracts'\nimport type * as THREE_NS from 'three'\nimport type { CanvasTexture, Group, Mesh, MeshStandardMaterial, Object3D, PerspectiveCamera, PlaneGeometry } from 'three'\nimport type { BenchChange, ModuleArea, ModuleControl, ModuleHost, ModuleLayer, ModuleMetric, ModuleScenario, TestableModule } from '@adatechnology/game-contracts'\nimport { CABIN_BANK, LIBRARY_BANK, RADIO_BANK } from '@adatechnology/game-audio'\nimport type { VehicleKit } from '@adatechnology/game-vehicles'\nimport { createSemiSimDriver } from '@adatechnology/game-vehicles-driving'\nimport type { SemiDriver, StorageStack } from '@adatechnology/game-vehicles-driving'\nimport { certify, createProvingTests, startRun, statusOf, subjectSpec, withResult } from '@adatechnology/game-vehicles-proving'\nimport type { ProvingCertificate, ProvingResult, ProvingRun, ProvingSubject, ProvingTestRegistry } from '@adatechnology/game-vehicles-proving'\nimport { discardObject3D } from '@adatechnology/game-shapes-three'\n\nimport { createVehiclesThree } from '../../build'\nimport type { BuiltVehicle } from '../../build'\nimport { defaultSoundIds } from '../types'\nimport { createVehicleSound } from '../../audio/vehicle-sound'\nimport type { VehicleSound } from '../../audio/vehicle-sound'\nimport type { VehicleSoundIds } from '../types'\nimport { createCockpit } from './cockpit'\nimport type { Cockpit } from './cockpit'\nimport { VEHICLE_SOUND_BANK } from '../../audio'\nimport { createWheelRoll } from '../../wheel-roll'\nimport type { WheelRoll } from '../../wheel-roll'\nimport { createProvingCrash } from './crash'\nimport type { ProvingCrash } from './crash'\nimport { SYSTEMS_TEXT } from './systems-text'\nimport type { SystemsText } from './systems-text'\nimport { fillText, PROVING_TEXT } from './text'\nimport type { ProvingText } from './text'\n\nexport const PROVING_AREA_ID = 'vehicles_proving'\n\ntype Three = typeof THREE_NS\n\n/** Content comes in by option (the adapter does not import a content pack): the example wires the kit's fleet, a game its own catalogue. */\nexport interface ProvingModuleOptions {\n locale?: string\n /** Vehicles offered on the bench, by catalogue id. */\n vehicles: readonly string[]\n /** Catalogue id of the person thrown out of a crash without a belt (a person item of the characters module); without it the crash only logs. */\n occupant?: string\n /** Catalogue id of the car parked behind for the parking sensors (a vehicle item of the vehicles module). Default `sedan` (the vehicles module's midsize sedan). */\n parkedCar?: string\n /** The proving subject of a vehicle (`fleetProvingSubject` of game-vehicles-fleet); `mass` is the kit's own when it has one. Null hides the vehicle. */\n subject(id: string, mass: number | undefined): ProvingSubject | null\n /** The vehicle's name on the bench and the board (default: the id). */\n nameOf?(id: string): string | undefined\n /** The tests (default: the kit's, see `createProvingTests`). */\n tests?: ProvingTestRegistry\n /** Builds the vehicle kit, with the catalogue installed, for a three.js namespace. */\n createKit(THREE: Three): VehicleKit\n sounds?: Partial<VehicleSoundIds>\n /** Called whenever a certificate changes (a result in, a sign-off), so a page can keep or show them. */\n onCertificate?(certificate: ProvingCertificate): void\n /** What the glovebox and the trunk of `vehicle` hold when someone gets in (items of the host's catalogue, as `game-items` finds them for a car). Default empty. */\n stock?(compartment: string, vehicle: string): readonly StorageStack[]\n /** The name of an item of the host's catalogue, for the log (default: its id). */\n itemName?(id: string): string | undefined\n}\n\n/** Track: a straight strip along +x (the semi driver's forward at yaw 0), drawn as a 260 m tile the vehicle wraps on so a top-speed run of kilometres stays on the same tarmac. */\nconst TRACK = { x0: -30, z: 22, tile: 260, width: 14, start: 4 }\nconst SURFACE_LOOK: Record<string, { color: number; roughness: number }> = { dry_asphalt: { color: 0x2b2d31, roughness: 0.95 }, wet_asphalt: { color: 0x1c1f24, roughness: 0.18 }, mud: { color: 0x4a3524, roughness: 1 } }\nconst VISUAL_CHECKS = ['cabin', 'cameras', 'mirrors'] as const\nconst MIRROR_RECTS: Record<string, { x: number; y: number; width: number; height: number; rounded: number }> = {\n rear_view: { x: 0.38, y: 0.02, width: 0.24, height: 0.09, rounded: 0.35 },\n left: { x: 0.02, y: 0.72, width: 0.19, height: 0.13, rounded: 0.3 },\n right: { x: 0.79, y: 0.72, width: 0.19, height: 0.13, rounded: 0.3 },\n reverse: { x: 0.36, y: 0.13, width: 0.28, height: 0.18, rounded: 0.06 },\n}\n\n/**\n * The proving ground as a `TestableModule`: a track where a fleet vehicle runs the measured tests of `game-vehicles-proving` live (0-100, top speed, braking, turning circle, wet braking, mud)\n * on the same semi-simulation driver the headless runner uses, with the vehicle cameras of `game-camera` (chase, cockpit, hood) taking over the room's view, the rear-view and side mirrors\n * and the reversing camera with its guide lines as extra views of the host, a board by the track with the vehicle's certificate, and the sign-off of the visual checks.\n */\nconst ADJUST_KEYS = { seat_forward: 'seatForward', seat_height: 'seatHeight', mirror_left: 'mirrorLeft', mirror_right: 'mirrorRight' } as const\n\nexport function createProvingModule(options: ProvingModuleOptions): TestableModule & { certificates(): ProvingCertificate[]; certificate(id: string): ProvingCertificate | undefined } {\n const locale = options.locale ?? 'pt-BR'\n const text: ProvingText = PROVING_TEXT[locale] ?? (PROVING_TEXT['pt-BR'] as ProvingText)\n const sysText: SystemsText = SYSTEMS_TEXT[locale] ?? (SYSTEMS_TEXT['pt-BR'] as SystemsText)\n const tests = options.tests ?? createProvingTests()\n const vehicles = options.vehicles\n const sounds = { ...defaultSoundIds, ...options.sounds }\n const measured = tests.tests.filter((t) => t.kind === 'measured').map((t) => t.id)\n const settings = { vehicle: vehicles.includes('compact_hatch') ? 'compact_hatch' : (vehicles[0] ?? 'compact_hatch'), test: measured[0] ?? 'accel_0_100', camera: 'chase', timeScale: 4, visual: 'cameras' as string }\n const certificates = new Map<string, ProvingCertificate>()\n const kits = new WeakMap<object, VehicleKit>()\n\n let host: ModuleHost | null = null\n // set in attach (nothing runs before it)\n let three = null as unknown as Three\n let track: Group | null = null\n let strip: Mesh<PlaneGeometry, MeshStandardMaterial> | null = null\n let board: { mesh: Mesh; canvas: HTMLCanvasElement; texture: CanvasTexture } | null = null\n let car: { built: BuiltVehicle; guides: Group; subject: ProvingSubject } | null = null\n let run: ProvingRun | null = null\n let parking: { driver: SemiDriver; time: number } | null = null\n /** The player at the wheel: the room's walking keys are held and the vehicle takes them. */\n let driving: Cockpit | null = null\n let crashes: ProvingCrash | null = null\n /** The wheels rolling with the distance the car covers, and where it was last frame (x, z of the driver). */\n let wheels: WheelRoll | null = null\n let lastAt: { x: number; z: number } | null = null\n let parked: { root: { position: { x: number; z: number } }; remove(): void } | null = null\n /** The driver's seat (metres) and the side mirrors (turn of their aim, out positive). */\n const adjust = { seatForward: 0, seatHeight: 0, mirrorLeft: 0, mirrorRight: 0 }\n const aimed = (pose: MirrorPose): MirrorPose => {\n const turn = pose.id === 'left' ? adjust.mirrorLeft : pose.id === 'right' ? -adjust.mirrorRight : 0\n return turn ? { ...pose, look: [pose.look[0] + turn, pose.look[1], pose.look[2]] } : pose\n }\n let gearbox: 'automatic' | 'manual' = 'automatic'\n /** The key is in the ignition (the bench takes it out to hotwire the car), and the weather the glass mists by. */\n let hasKey = true\n let weather = { outsideC: 25, rain: 0 }\n let misted = false\n let lastGear: number | null = null\n let driveClock = 0\n let queue: string[] = []\n /** True while the room has this area open: nothing is built or simulated otherwise, so loading the module costs nothing elsewhere in the room. */\n let open = false\n let lastWrap = 0\n // the car's own sounds (engine by RPM and load, starter, tyres), as on the lane of the vehicles area\n let engine: VehicleSound | undefined\n const rig = { camera: null as PerspectiveCamera | null, vehicle: null as ReturnType<typeof createVehicleCamera> | null, mirrors: [] as Array<{ pose: MirrorPose; camera: PerspectiveCamera; remove: () => void }> }\n\n const name = (id: string): string => options.nameOf?.(id) ?? id.replace(/_/g, ' ')\n const kitFor = (THREE: Three): VehicleKit => {\n let kit = kits.get(THREE)\n if (!kit) {\n kit = options.createKit(THREE)\n kits.set(THREE, kit)\n }\n return kit\n }\n const subjectOf = (id: string): ProvingSubject | null => {\n const mass = three ? (kitFor(three).find(id) as { mass?: number } | null)?.mass : undefined\n return options.subject(id, mass)\n }\n const blank = (subject: ProvingSubject): ProvingCertificate => {\n const results: ProvingResult[] = tests.forDomain(subject.domain).map((t) => ({ test: t.id, kind: t.kind, unit: t.unit, range: t.range?.(subject) ?? {}, value: null, verdict: 'pending', note: t.kind === 'measured' ? 'not run' : t.kind === 'visual' ? 'awaiting sign-off' : 'room not built yet' }))\n return { vehicle: subject.id, domain: subject.domain, category: subject.category, status: statusOf(results), results }\n }\n const certificateOf = (id: string): ProvingCertificate | undefined => {\n if (!certificates.has(id)) {\n const subject = subjectOf(id)\n if (subject) certificates.set(id, blank(subject))\n }\n return certificates.get(id)\n }\n const store = (certificate: ProvingCertificate): void => {\n certificates.set(certificate.vehicle, certificate)\n options.onCertificate?.(certificate)\n drawBoard()\n }\n\n // ---- the track ----------------------------------------------------------------------------------------------------------------------\n const buildTrack = (): void => {\n if (!host || track) return\n const THREE = three\n track = markKitOrigin(new THREE.Group(), { owner: '@adatechnology/game-vehicles-three', kind: 'room', id: 'proving_track' })\n track.name = 'proving_track'\n const look = SURFACE_LOOK.dry_asphalt!\n strip = new THREE.Mesh(new THREE.PlaneGeometry(TRACK.tile + 80, TRACK.width), new THREE.MeshStandardMaterial({ color: look.color, roughness: look.roughness, metalness: 0.05 }))\n strip.rotation.x = -Math.PI / 2\n strip.position.set(TRACK.x0 + TRACK.tile / 2, 0.012, TRACK.z)\n strip.receiveShadow = true\n track.add(strip)\n const paint = new THREE.MeshBasicMaterial({ color: 0xe8e8e2 })\n const yellow = new THREE.MeshBasicMaterial({ color: 0xf2c230 })\n const dash = new THREE.PlaneGeometry(3, 0.14)\n const edge = new THREE.PlaneGeometry(TRACK.tile + 80, 0.16)\n for (const side of [-1, 1]) {\n const line = new THREE.Mesh(edge, paint)\n line.rotation.x = -Math.PI / 2\n line.position.set(TRACK.x0 + TRACK.tile / 2, 0.016, TRACK.z + side * (TRACK.width / 2 - 0.4))\n track.add(line)\n }\n for (let x = TRACK.x0 - 40; x < TRACK.x0 + TRACK.tile + 40; x += 9) {\n const d = new THREE.Mesh(dash, paint)\n d.rotation.x = -Math.PI / 2\n d.position.set(x, 0.016, TRACK.z - 1.5)\n track.add(d)\n }\n // a distance board every 50 m of the tile and the start line\n const post = new THREE.BoxGeometry(0.12, 1.4, 0.12)\n const plate = new THREE.BoxGeometry(0.06, 0.5, 0.9)\n for (let m = 0; m <= TRACK.tile; m += 50) {\n const p = new THREE.Mesh(post, yellow)\n p.position.set(TRACK.x0 + m, 0.7, TRACK.z - TRACK.width / 2 - 0.6)\n const q = new THREE.Mesh(plate, m === 0 ? yellow : paint)\n q.position.set(TRACK.x0 + m, 1.45, TRACK.z - TRACK.width / 2 - 0.6)\n track.add(p, q)\n }\n const startLine = new THREE.Mesh(new THREE.PlaneGeometry(0.5, TRACK.width - 1), yellow)\n startLine.rotation.x = -Math.PI / 2\n startLine.position.set(TRACK.x0, 0.017, TRACK.z)\n track.add(startLine)\n ;(host.scene as Object3D).add(track)\n buildBoard()\n }\n const setSurface = (surface: string): void => {\n if (!strip) return\n const look = SURFACE_LOOK[surface] ?? SURFACE_LOOK.dry_asphalt!\n strip.material.color.setHex(look.color)\n strip.material.roughness = look.roughness\n }\n\n // ---- the certificate board ------------------------------------------------------------------------------------------------------------\n const buildBoard = (): void => {\n if (!host || board || typeof document === 'undefined') return\n const THREE = three\n const canvas = document.createElement('canvas')\n canvas.width = 1024\n canvas.height = 640\n const texture = new THREE.CanvasTexture(canvas)\n texture.colorSpace = THREE.SRGBColorSpace\n const mesh = markKitOrigin(new THREE.Mesh(new THREE.PlaneGeometry(9.6, 6), new THREE.MeshBasicMaterial({ map: texture, toneMapped: false })), { owner: '@adatechnology/game-vehicles-three', kind: 'room', id: 'proving_board' })\n mesh.position.set(TRACK.x0 + 6, 3.6, TRACK.z - TRACK.width / 2 - 3)\n const legs = new THREE.Mesh(new THREE.BoxGeometry(9.8, 0.2, 0.2), new THREE.MeshStandardMaterial({ color: 0x1c1f25 }))\n legs.position.set(0, -3.1, -0.05)\n const stand = new THREE.Mesh(new THREE.BoxGeometry(0.25, 3.4, 0.25), legs.material)\n stand.position.set(0, -4.6, -0.1)\n mesh.add(legs, stand)\n track!.add(mesh)\n board = { mesh, canvas, texture }\n drawBoard()\n }\n const fmtRange = (r: ProvingResult['range']): string => (r.min == null && r.max == null ? '—' : `${r.min ?? '…'}–${r.max ?? '…'}`)\n const drawBoard = (): void => {\n if (!board) return\n const cert = certificateOf(settings.vehicle)\n const g = board.canvas.getContext('2d')\n if (!g || !cert) return\n const W = board.canvas.width\n g.fillStyle = '#16181c'\n g.fillRect(0, 0, W, board.canvas.height)\n g.fillStyle = '#f2c230'\n g.fillRect(0, 0, W, 10)\n g.font = '600 26px monospace'\n g.fillStyle = '#8d95a3'\n g.fillText(text.board.title.toUpperCase(), 32, 50)\n g.font = '700 46px sans-serif'\n g.fillStyle = '#e7e9ec'\n g.fillText(name(cert.vehicle), 32, 102)\n const colour = { approved: '#5cc98a', rejected: '#ef6a5b', pending: '#a7a0f0' }[cert.status]\n g.font = '700 34px sans-serif'\n const status = text.status[cert.status]\n const sw = g.measureText(status).width + 32\n g.strokeStyle = colour\n g.lineWidth = 3\n g.strokeRect(W - sw - 32, 66, sw, 48)\n g.fillStyle = colour\n g.fillText(status, W - sw - 16, 102)\n g.font = '22px monospace'\n g.fillStyle = '#8d95a3'\n const cols = [32, 430, 640, 860]\n ;[text.board.test, text.board.value, text.board.range, text.board.verdict].forEach((h, i) => g.fillText(h.toUpperCase(), cols[i]!, 150))\n let y = 190\n for (const r of cert.results) {\n const live = run && run.test.id === r.test && !run.done\n g.fillStyle = '#e7e9ec'\n g.font = '26px sans-serif'\n g.fillText(text.tests[r.test] ?? r.test, cols[0]!, y)\n g.font = '26px monospace'\n g.fillStyle = '#5fd4e0'\n const value = live ? text.board.running : r.value == null ? (r.kind === 'measured' && r.note === 'not run' ? text.board.notRun : '—') : `${r.value} ${r.unit}`\n g.fillText(value, cols[1]!, y)\n g.fillStyle = '#8d95a3'\n g.fillText(r.kind === 'measured' ? fmtRange(r.range) : r.kind === 'visual' ? 'visual' : 'sala', cols[2]!, y)\n g.fillStyle = { pass: '#5cc98a', fail: '#ef6a5b', pending: '#a7a0f0' }[r.verdict]\n g.fillText(r.verdict === 'pass' ? '✓ ' + text.verdict.pass : r.verdict === 'fail' ? '✗ ' + text.verdict.fail : '…', cols[3]!, y)\n y += 30\n }\n // the gearbox live: the gear and the engine speed of the run or of the driver\n const live = run?.driver.state ?? driving?.driver.state\n if (live) {\n g.font = '24px monospace'\n g.fillStyle = '#f2c230'\n g.fillText(fillText(text.board.gear, gearName(live.gear), Math.round(live.rpm), Math.round(Math.abs(live.u) * 3.6)), cols[0]!, y + 16)\n }\n board.texture.needsUpdate = true\n }\n\n // ---- the vehicle ----------------------------------------------------------------------------------------------------------------------\n const removeCar = (): void => {\n if (!car) return\n wheels = null\n lastAt = null\n discardObject3D(car.built.group)\n car = null\n }\n const placeCar = (): void => {\n if (!host || !three) return\n const subject = subjectOf(settings.vehicle)\n if (!subject) return\n removeCar()\n const built = createVehiclesThree(three, { kit: kitFor(three) }).build(settings.vehicle, { quality: 'high' })\n const guides = reverseGuides(built)\n built.group.add(guides)\n ;(host.scene as Object3D).add(built.group)\n car = { built, guides, subject }\n wheels = createWheelRoll(three, built)\n pose({ x: 0, z: TRACK.start, yaw: 0, pitch: 0, roll: 0, height: 0 }, 0)\n rig.vehicle?.reset()\n drawBoard()\n }\n /** Guide lines of the reversing camera (on layer 1, which only that camera sees): green, yellow and red at 3, 2 and 1 m behind the bumper, bending with the steering. */\n const reverseGuides = (built: BuiltVehicle): Group => {\n const THREE = three\n const group = new THREE.Group()\n group.name = 'reverse_guides'\n const half = built.width / 2 - 0.05\n const tail = -built.length / 2\n const bands: Array<[number, number, number]> = [\n [0.2, 1, 0xef4a3b],\n [1, 2, 0xf2c230],\n [2, 3.2, 0x5cc98a],\n ]\n for (const [a, b, colour] of bands) {\n const material = new THREE.MeshBasicMaterial({ color: colour, transparent: true, opacity: 0.85, depthTest: false })\n for (const side of [-1, 1]) {\n const bar = new THREE.Mesh(new THREE.PlaneGeometry(0.06, b - a), material)\n bar.rotation.x = -Math.PI / 2\n bar.position.set(side * half, 0.03, tail - (a + b) / 2)\n bar.userData.side = side\n bar.userData.mid = (a + b) / 2\n group.add(bar)\n }\n const cross = new THREE.Mesh(new THREE.PlaneGeometry(half * 2, 0.05), material)\n cross.rotation.x = -Math.PI / 2\n cross.position.set(0, 0.03, tail - a)\n cross.userData.mid = a\n group.add(cross)\n }\n group.traverse((o) => o.layers.set(1))\n return group\n }\n const bendGuides = (steer: number): void => {\n if (!car) return\n // the lines follow the arc the rear will take: sideways offset grows with the square of the distance\n for (const bar of car.guides.children) {\n const d = bar.userData.mid as number\n const offset = -steer * 0.18 * d * d\n bar.position.x = (bar.userData.side ?? 0) * (car.built.width / 2 - 0.05) + offset\n }\n }\n const pose = (s: { x: number; z: number; yaw: number; pitch: number; roll: number; height: number }, steer: number): void => {\n if (!car) return\n const wrapped = ((s.x % TRACK.tile) + TRACK.tile) % TRACK.tile\n if (Math.abs(wrapped - lastWrap) > TRACK.tile / 2) rig.vehicle?.reset()\n lastWrap = wrapped\n car.built.group.position.set(TRACK.x0 + wrapped, 0, TRACK.z + s.z)\n car.built.group.rotation.set(-s.pitch, s.yaw + Math.PI / 2, s.roll, 'YXZ')\n bendGuides(steer)\n // the distance along the car's heading since the last frame turns the wheels (a jump to a new run starts them afresh)\n if (lastAt) {\n const along = (s.x - lastAt.x) * Math.cos(s.yaw) - (s.z - lastAt.z) * Math.sin(s.yaw)\n if (Math.abs(along) < 5) wheels?.roll(along, steer)\n }\n lastAt = { x: s.x, z: s.z }\n }\n const frameOf = (speed: number): VehicleFrame | null => {\n if (!car) return null\n const g = car.built.group\n const size = { length: car.built.length, width: car.built.width, height: car.built.height }\n // the seat moves the eyes: forward along the car and up\n const [ex, ey, ez] = car.built.driverEye ?? defaultEye(size)\n return { x: g.position.x, y: g.position.y, z: g.position.z, yaw: g.rotation.y, pitch: -g.rotation.x, roll: g.rotation.z, speed, ...size, eye: [ex, ey + adjust.seatHeight, ez + adjust.seatForward] }\n }\n\n // ---- cameras and mirrors --------------------------------------------------------------------------------------------------------------\n const applyCamera = (): void => {\n if (!host?.setViewCamera) return\n host.setViewCamera(settings.camera === 'room' ? null : rig.camera)\n if (settings.camera !== 'room') rig.vehicle?.setMode(settings.camera as VehicleCameraMode)\n }\n const refreshMirrors = (): void => {\n for (const m of rig.mirrors) m.remove()\n rig.mirrors = []\n if (!host?.addView || !car) return\n const poses = mirrorPoses(car.built)\n const want = (id: string): boolean => (id === 'reverse' ? !!host?.bench?.layer('reverse_camera') : !!host?.bench?.layer('mirrors'))\n for (const pose of poses) {\n if (!want(pose.id)) continue\n const camera = new three.PerspectiveCamera(pose.fov, 2, 0.05, 400)\n if (pose.id === 'reverse') camera.layers.enable(1)\n const rect = MIRROR_RECTS[pose.id]!\n const remove = host.addView({ camera, rect, mirror: pose.mirror, rounded: rect.rounded, label: pose.id, resolution: pose.id === 'reverse' ? 0.6 : 0.45 })\n rig.mirrors.push({ pose, camera, remove })\n }\n }\n let mirrorKey = ''\n\n // ---- runs -----------------------------------------------------------------------------------------------------------------------------\n const stopEngine = (): void => {\n engine?.dispose()\n engine = undefined\n }\n const startTest = (id: string): void => {\n const test = tests.get(id)\n if (!host || !test || test.kind !== 'measured') return\n if (!car || car.subject.id !== settings.vehicle) placeCar()\n if (!car) return\n parking = null\n run = startRun(test, car.subject)\n setSurface(run.surface)\n // the turning circle needs room on the left: start it at the right edge\n if (id === 'turn_circle') run.driver.place(0, TRACK.start, 0)\n rig.vehicle?.reset()\n stopEngine()\n engine = createVehicleSound(host.audio, { sounds })\n engine.start([car.built.group.position.x, 0.5, car.built.group.position.z])\n host.log(fillText(text.log.start, name(settings.vehicle), text.tests[id] ?? id))\n drawBoard()\n }\n const finishTest = (): void => {\n if (!run || !car) return\n const result = run.result()\n const cert = certificateOf(car.subject.id)\n if (cert) store(withResult(cert, result))\n host?.log(fillText(text.log.result, name(car.subject.id), text.tests[result.test] ?? result.test, result.value ?? '—', result.unit, fmtRange(result.range), result.verdict), { vehicle: car.subject.id, ...result, trace: undefined }, 'proving_result')\n run = null\n stopEngine()\n const next = queue.shift()\n if (next) startTest(next)\n else setSurface('dry_asphalt')\n }\n const startParking = (): void => {\n if (!host) return\n if (!car || car.subject.id !== settings.vehicle) placeCar()\n if (!car) return\n run = null\n queue = []\n setSurface('dry_asphalt')\n const driver = createSemiSimDriver(subjectSpec(car.subject))\n driver.place(40, 0, 0)\n parking = { driver, time: 0 }\n }\n\n const stopDriving = (): void => {\n if (!driving) return\n driving.stop()\n driving = null\n host?.holdPlayer?.(false)\n host?.bench?.sheet?.(null)\n stopEngine()\n host?.log(text.log.leave)\n }\n const startDriving = (): void => {\n if (!host || !three) return\n if (!car || car.subject.id !== settings.vehicle) placeCar()\n if (!car) return\n run = null\n queue = []\n parking = null\n setSurface(weather.rain > 0 ? 'wet_asphalt' : 'dry_asphalt')\n misted = false\n driving = createCockpit({\n THREE: three,\n host,\n built: car.built,\n subject: car.subject,\n place: [0, 0, 0],\n kit: kitFor(three),\n obstacles: () => (parked ? [[parked.root.position.x, parked.root.position.z] as const] : []),\n gauge: (kitFor(three) as { materials?: Record<string, unknown> }).materials?.gauge,\n needle: (kitFor(three) as { materials?: Record<string, unknown> }).materials?.amber,\n // the engine's own sound turns the key (starter, catch, idle by RPM)\n sounds: { starter: '' },\n hasKey,\n weather,\n stock: (compartment) => options.stock?.(compartment, settings.vehicle) ?? [],\n onExit: () => stopDriving(),\n onEvent: (event) => {\n if (event.type === 'hotwire') {\n host?.log(sysText.events[event.stage === 'joined' ? 'hotwire_joined' : 'hotwire_started'], { vehicle: settings.vehicle, stage: event.stage }, 'proving_system')\n if (event.stage === 'joined' && car && driving?.systems.canCrank() !== false) engine?.start([car.built.group.position.x, 0.5, car.built.group.position.z])\n return\n }\n if (event.type === 'refused') return host?.log(text.cabin.refused[event.reason] ?? sysText.refused[event.reason as keyof SystemsText['refused']] ?? event.reason)\n if (event.type === 'sound') return\n if (event.type !== 'command') {\n if (event.type === 'out_of_fuel' || event.type === 'stall' || event.type === 'seized') engine?.stop([car?.built.group.position.x ?? 0, 0.5, car?.built.group.position.z ?? 0])\n return host?.log(sysText.events[event.type as keyof SystemsText['events']] ?? event.type, { vehicle: settings.vehicle, ...event }, 'proving_system')\n }\n const st = event.state\n const line = cabinLine(event.command, st)\n if (line) host?.log(line)\n if (event.command === 'ignition' && car) {\n const at: [number, number, number] = [car.built.group.position.x, 0.5, car.built.group.position.z]\n if (st.ignition && driving?.systems.canCrank() !== false) engine?.start(at)\n else engine?.stop(at)\n }\n if (event.command === 'gearbox') {\n gearbox = st.gearbox\n host?.bench?.patch('gearbox', { value: st.gearbox })\n }\n },\n })\n if (gearbox !== driving.controls.state.gearbox) driving.controls.command('gearbox')\n host.holdPlayer?.(true)\n if (settings.camera === 'room') {\n settings.camera = 'cockpit'\n host.bench?.patch('camera', { value: 'cockpit' })\n applyCamera()\n }\n rig.vehicle?.reset()\n stopEngine()\n // the engine is off until the key turns (I): the sound cranks, catches and idles by the RPM\n engine = createVehicleSound(host.audio, { sounds })\n host.bench?.sheet?.({ kicker: text.name, title: fillText(text.log.drive, name(settings.vehicle)), body: `${text.cabin.keys} · ${sysText.keys} · ${sysText.bodyKeys}` })\n host.log(fillText(text.log.drive, name(settings.vehicle)))\n }\n const onOff = (on: boolean): string => (on ? text.cabin.on : text.cabin.off)\n const cabinLine = (command: string, st: Cockpit['controls']['state']): string | null => {\n const c = text.cabin\n switch (command) {\n case 'ignition': return `${c.ignition}: ${onOff(st.ignition)}`\n case 'gearbox': return `${c.gearbox}: ${text.gearbox[st.gearbox]}`\n case 'gear_up':\n case 'gear_down': return `${c.gear}: ${gearName(st.gear)}`\n case 'parking_brake': return `${c.parkingBrake}: ${onOff(st.parkingBrake)}`\n case 'drive_mode': return `${c.driveMode}: ${c.modes[st.driveMode]}`\n case 'lights':\n case 'high_beam': return `${c.lights}: ${c.lampModes[st.lamps.mode]}`\n case 'fog_lights': return `${c.fog}: ${onOff(st.lamps.fog)}`\n case 'interior_light': return `${c.interior}: ${onOff(st.lamps.interior)}`\n case 'alarm': return `${c.alarm}: ${c.alarmStates[st.alarm]}`\n case 'radio':\n case 'radio_source':\n case 'radio_track': return `${c.radio}: ${st.radio.on ? `${c.sources[st.radio.source]} · ${fillText(sysText.track, st.radio.track + 1)}` : c.off}`\n case 'indicator_left':\n case 'indicator_right':\n case 'hazard': return `${c.indicator}: ${c.indicators[st.indicator]}`\n case 'wipers': return `${c.wipers}: ${sysText.wiperModes[st.wipers]}`\n case 'drive_profile': return `${sysText.profile}: ${sysText.profiles[st.profile]}`\n case 'traction_control': return `${sysText.traction}: ${onOff(st.tractionControl)}`\n case 'abs': return `${sysText.abs}: ${onOff(st.abs)}`\n case 'cruise': return st.cruise.on ? fillText(sysText.cruiseSet, Math.round(st.cruise.speed * 3.6)) : `${sysText.cruise}: ${c.off}`\n case 'climate': return `${sysText.climate}: ${onOff(st.climate.on)}`\n case 'demist': return `${sysText.demist}: ${onOff(st.climate.demist)}`\n case 'seatbelt': return `${c.seatbelt}: ${onOff(st.seatbelt)}`\n case 'siren': return `${sysText.siren}: ${sysText.sirenModes[st.siren]}`\n case 'beacon': return `${sysText.beacon}: ${onOff(st.beacon)}`\n case 'glovebox': return `${sysText.glovebox}: ${sysText.lid[st.glovebox ? 'open' : 'shut']}`\n default: return null\n }\n }\n const itemName = (id: string): string => options.itemName?.(id) ?? id\n /** What a compartment holds, for the log: refused while shut, empty, or its stacks with the weight. */\n const listCompartment = (cockpit: Cockpit, id: 'glovebox' | 'trunk'): void => {\n const label = sysText.storage.names[id]\n const data = { vehicle: settings.vehicle, compartment: id }\n if (!cockpit.storage.compartments.some((c) => c.id === id)) return host?.log(fillText(sysText.storage.none, label.toLowerCase()), data, 'proving_storage')\n if (!cockpit.storage.reachable(id, cockpit.access())) return host?.log(fillText(sysText.storage.shut, label), data, 'proving_storage')\n const stacks = cockpit.storage.contents(id).filter((x): x is StorageStack => x !== null)\n if (!stacks.length) return host?.log(fillText(sysText.storage.empty, label), data, 'proving_storage')\n host?.log(fillText(sysText.storage.list, label, cockpit.storage.loadKg(id).toFixed(1), stacks.map((x) => (x.count > 1 ? `${x.count}× ${itemName(x.itemId)}` : itemName(x.itemId))).join(', ')), { ...data, stacks: stacks.map((x) => ({ item: x.itemId, count: x.count })) }, 'proving_storage')\n }\n /** The bench's tests of the car's systems, on the car being driven (the driving seat opens if nobody is in it). */\n const systemsAction = (id: keyof SystemsText['actions']): void => {\n if (id === 'take_key') {\n // the key out (or back): the driver gets in again with or without it\n hasKey = !hasKey\n if (driving) stopDriving()\n startDriving()\n host?.log(hasKey ? sysText.keyBack : sysText.keyTaken, { vehicle: settings.vehicle, hasKey }, 'proving_system')\n return\n }\n if (id === 'cold_rain') {\n weather = weather.rain > 0 ? { outsideC: 25, rain: 0 } : { outsideC: 8, rain: 1 }\n if (driving) driving.weather = { ...weather }\n setSurface(weather.rain > 0 ? 'wet_asphalt' : 'dry_asphalt')\n host?.log(weather.rain > 0 ? sysText.fog.weather : sysText.fog.fair, { vehicle: settings.vehicle, ...weather }, 'proving_system')\n return\n }\n if (!driving) startDriving()\n const cockpit = driving\n if (!cockpit) return\n const d = cockpit.driver\n const done = (key: keyof SystemsText['done']): void => host?.log(sysText.done[key], { vehicle: settings.vehicle, action: key }, 'proving_system')\n switch (id) {\n case 'puncture': {\n const tyres = d.spec.wheels.map((_, i) => d.condition.tyres?.[i] ?? 1)\n tyres[0] = 0\n d.condition = { ...d.condition, tyres }\n return done('puncture')\n }\n case 'fit_spare': {\n const flat = d.spec.wheels.findIndex((_, i) => (d.condition.tyres?.[i] ?? 1) < 0.2)\n const event = cockpit.systems.fitSpare(d, Math.max(0, flat))\n host?.log(sysText.events[event.type], { vehicle: settings.vehicle, ...event }, 'proving_system')\n return\n }\n case 'refuel':\n d.refuel(d.spec.tank.capacity)\n return done('refuel')\n case 'empty_tank':\n d.state.fuel = Math.min(d.state.fuel, d.spec.tank.capacity * 0.04)\n return done('empty_tank')\n case 'drain_battery':\n // below what the starter needs (a quarter): the key clicks and nothing turns\n cockpit.systems.charge(-(cockpit.systems.state.charge - 0.15))\n return done('drain_battery')\n case 'jump_start':\n cockpit.systems.charge(1)\n return done('jump_start')\n case 'break_radiator':\n cockpit.radiator = 0.05\n return done('break_radiator')\n case 'remote_lock':\n case 'remote_unlock': {\n const lock = id === 'remote_lock'\n cockpit.body?.lock(lock)\n // the remote arms the alarm with a chirp and blinks the hazards once; unlocking disarms it\n cockpit.controls.state.alarm = lock ? 'armed' : 'off'\n host?.audio?.play?.({ sound: 'alarm_chirp', position: [car?.built.group.position.x ?? 0, 1, car?.built.group.position.z ?? 0] })\n host?.log(sysText.remote[lock ? 'locked' : 'unlocked'], { vehicle: settings.vehicle, locked: lock }, 'proving_system')\n return\n }\n case 'crash_wall': {\n const g = car?.built.group as { position: { x: number; y: number; z: number }; rotation: { y: number } } | undefined\n if (!g || !host) return\n crashes ??= createProvingCrash(host, options.occupant)\n const speed = d.state.u\n const ejection = crashes.crash({ car: { position: g.position, rotationY: g.rotation.y }, u: d.state.u, w: d.state.w, belted: cockpit.controls.state.seatbelt, destructible: cockpit.destructible })\n d.state.u = d.state.w = d.state.yawRate = 0\n const kmh = Math.round(Math.abs(speed) * 3.6)\n const belted = cockpit.controls.state.seatbelt\n host.log(ejection ? fillText(sysText.crash.ejected, kmh, sysText.crash.exits[ejection.exit]) : fillText(belted ? sysText.crash.stayed : sysText.crash.mild, kmh), { vehicle: settings.vehicle, kmh, belted: cockpit.controls.state.seatbelt, ejection }, 'proving_crash')\n return\n }\n case 'park_behind': {\n // a car parked three metres behind the bumper: backing up, the sensors beep faster as it comes close\n const g = car?.built.group as { position: { x: number; z: number }; rotation: { y: number } } | undefined\n if (!g || !host) return\n parked?.remove()\n const back = (car?.built.length ?? 4.5) / 2 + 3 + 2.3\n const at: [number, number, number] = [g.position.x - Math.sin(g.rotation.y) * back, 0, g.position.z - Math.cos(g.rotation.y) * back]\n const placed = host.addObject?.(options.parkedCar ?? 'sedan', { position: at, rotationY: g.rotation.y })\n parked = placed ? { root: placed.root as { position: { x: number; z: number } }, remove: placed.remove } : null\n host.log(placed ? sysText.parking.placed : sysText.parking.none, { vehicle: settings.vehicle }, 'proving_system')\n return\n }\n case 'glovebox_contents':\n return listCompartment(cockpit, 'glovebox')\n case 'trunk_contents':\n return listCompartment(cockpit, 'trunk')\n case 'take_from_trunk': {\n const storage = cockpit.storage\n if (!storage.compartments.some((c) => c.id === 'trunk')) return listCompartment(cockpit, 'trunk')\n const slot = storage.contents('trunk').findIndex((x) => x !== null)\n if (slot < 0 || !storage.reachable('trunk', cockpit.access())) return listCompartment(cockpit, 'trunk')\n const stack = storage.take('trunk', slot, cockpit.access())\n if (!stack) return\n // it lands on the ground behind the car, an item of the host's like any other\n const g = car?.built.group as { position: { x: number; z: number }; rotation: { y: number } } | undefined\n const back = (car?.built.length ?? 4.5) / 2 + 0.8\n const placed = g ? host?.addObject?.(stack.itemId, { position: [g.position.x - Math.sin(g.rotation.y) * back, 0, g.position.z - Math.cos(g.rotation.y) * back] }) : null\n host?.log(fillText(placed ? sysText.storage.taken : sysText.storage.ground, itemName(stack.itemId)), { vehicle: settings.vehicle, item: stack.itemId, count: stack.count, placed: !!placed }, 'proving_storage')\n return\n }\n case 'force_door': {\n // a locked door forced open: with the alarm armed, it goes off\n const body = cockpit.body\n if (!body) return\n if (body.locked) body.lock(false)\n body.toggle('door_front_left')\n if (cockpit.controls.state.alarm === 'armed') cockpit.controls.state.alarm = 'ringing'\n host?.log(sysText.remote.forced, { vehicle: settings.vehicle, alarm: cockpit.controls.state.alarm }, 'proving_system')\n return\n }\n }\n }\n const gearName = (gear: number): string => (gear < 0 ? 'R' : gear === 0 ? 'N' : String(gear))\n\n const onChange = (change: BenchChange): void => {\n if (change.kind === 'layer') {\n if (change.id === 'scoreboard' && board) board.mesh.visible = !!host?.bench?.layer('scoreboard')\n return refreshMirrors()\n }\n if (change.kind === 'action') {\n if (change.id === 'drive') return driving ? stopDriving() : startDriving()\n if (change.id in sysText.actions) return systemsAction(change.id as keyof SystemsText['actions'])\n if (change.id === 'run_test' || change.id === 'run_all' || change.id === 'reverse_park') stopDriving()\n if (change.id === 'run_test') {\n queue = []\n startTest(settings.test)\n } else if (change.id === 'run_all') {\n queue = measured.slice(1)\n startTest(measured[0]!)\n } else if (change.id === 'certify_now') {\n const subject = subjectOf(settings.vehicle)\n if (!subject) return\n const prior = certificateOf(subject.id)\n const signOffs = (prior?.results ?? []).filter((r) => r.kind !== 'measured' && r.verdict !== 'pending').map((r) => ({ vehicle: subject.id, test: r.test, ok: r.verdict === 'pass', by: r.signedBy ?? 'test room' }))\n const cert = certify(subject, { tests, signOffs })\n store(cert)\n host?.log(fillText(text.log.certified, name(subject.id), text.status[cert.status]), { vehicle: subject.id, status: cert.status }, 'proving_certificate')\n } else if (change.id === 'reverse_park') startParking()\n else if (change.id === 'sign_ok' || change.id === 'sign_fail') {\n const cert = certificateOf(settings.vehicle)\n if (!cert) return\n const ok = change.id === 'sign_ok'\n store(withResult(cert, { test: settings.visual, kind: 'visual', unit: '', range: {}, value: null, verdict: ok ? 'pass' : 'fail', signedBy: 'test room' }))\n host?.log(fillText(text.log.signed, name(settings.vehicle), text.tests[settings.visual] ?? settings.visual, ok ? text.verdict.pass : text.verdict.fail))\n } else if (change.id === 'reset') {\n const subject = subjectOf(settings.vehicle)\n if (subject) store(blank(subject))\n }\n return\n }\n switch (change.id) {\n case 'vehicle':\n settings.vehicle = String(change.value)\n stopDriving()\n run = null\n queue = []\n parking = null\n stopEngine()\n placeCar()\n refreshMirrors()\n break\n case 'test':\n settings.test = String(change.value)\n break\n case 'camera':\n settings.camera = String(change.value)\n applyCamera()\n break\n case 'seat_forward':\n case 'seat_height':\n case 'mirror_left':\n case 'mirror_right':\n adjust[ADJUST_KEYS[change.id]] = Number(change.value)\n break\n case 'time_scale':\n settings.timeScale = Number(change.value)\n break\n case 'gearbox':\n gearbox = change.value === 'manual' ? 'manual' : 'automatic'\n if (driving && driving.controls.state.gearbox !== gearbox) driving.controls.command('gearbox')\n break\n case 'visual_check':\n settings.visual = String(change.value)\n break\n default:\n break\n }\n }\n\n const frame = (dt: number): void => {\n if (!host || !open) return\n if (!track) buildTrack()\n if (!car) {\n placeCar()\n refreshMirrors()\n }\n let speed = 0\n let steer = 0\n if (run) {\n run.step(dt * settings.timeScale)\n const s = run.driver.state\n pose(s, s.steerAngle)\n speed = s.u\n steer = s.steerAngle\n if (run.done) finishTest()\n } else if (driving) {\n const d = driving\n d.step(dt)\n if (!driving) return\n // the mist on the glass to the log as it comes and goes\n if (!misted && d.fog.state.fog > 0.6) {\n misted = true\n host.log(sysText.fog.misted, { vehicle: settings.vehicle, fog: +d.fog.state.fog.toFixed(2), humidity: +d.fog.state.humidity.toFixed(2) }, 'proving_system')\n } else if (misted && d.fog.state.fog < 0.1) {\n misted = false\n host.log(sysText.fog.clear, { vehicle: settings.vehicle }, 'proving_system')\n }\n pose(d.driver.state, d.driver.state.steerAngle)\n speed = d.driver.state.u\n steer = d.driver.state.steerAngle\n } else if (parking) {\n // backs up 12 m along a gentle curve to the right, the way a driver parks watching the reversing camera\n parking.time += dt\n const p = parking\n p.driver.step({ throttle: 0, brake: p.time < 7 ? 0.35 : 1, steer: p.time > 2 ? -0.6 : 0, handbrake: false }, dt)\n pose(p.driver.state, p.driver.state.steerAngle)\n speed = p.driver.state.u\n steer = p.driver.state.steerAngle\n if (p.time > 9) parking = null\n }\n if (car) engine?.update({ dt, position: [car.built.group.position.x, 0.5, car.built.group.position.z], speed, throttle: run ? 1 : (driving?.throttle ?? 0), rpm: driving ? driving.driver.state.rpm : undefined })\n const f = frameOf(speed)\n if (f && rig.vehicle && settings.camera !== 'room') rig.vehicle.update(rig.camera!, f, dt)\n if (f && rig.vehicle) for (const m of rig.mirrors) rig.vehicle.placeMirror(m.camera, aimed(m.pose), f)\n void steer\n const key = `${host.bench?.layer('mirrors')}|${host.bench?.layer('reverse_camera')}`\n if (key !== mirrorKey) {\n mirrorKey = key\n refreshMirrors()\n }\n // each shift of the gearbox goes to the log (the automatic climbs the gears on a run, the driver shifts by hand)\n const geared = run?.driver.state ?? driving?.driver.state\n if (geared && geared.gear !== lastGear) {\n if (lastGear !== null && geared.gear > 0) host.log(fillText(text.log.shift, gearName(lastGear), gearName(geared.gear), Math.round(Math.abs(geared.u) * 3.6)), { from: lastGear, to: geared.gear, kmh: +(Math.abs(geared.u) * 3.6).toFixed(1), rpm: Math.round(geared.rpm) }, 'proving_shift')\n lastGear = geared.gear\n drawBoard()\n } else if (!geared) lastGear = null\n if ((run && Math.floor(run.time * 2) !== Math.floor((run.time - dt * settings.timeScale) * 2)) || (driving && Math.floor(driveClock * 2) !== Math.floor((driveClock - dt) * 2))) drawBoard()\n if (driving) driveClock += dt\n }\n\n const speedNow = (): number => Math.abs(run?.driver.state.u ?? driving?.driver.state.u ?? parking?.driver.state.u ?? 0) * 3.6\n const counts = (verdict: 'pass' | 'fail' | 'pending'): number => certificateOf(settings.vehicle)?.results.filter((r) => r.verdict === verdict).length ?? 0\n\n const teardown = (): void => {\n crashes?.dispose()\n crashes = null\n parked?.remove()\n parked = null\n stopDriving()\n stopEngine()\n for (const m of rig.mirrors) m.remove()\n rig.mirrors = []\n removeCar()\n mirrorKey = ''\n if (track) discardObject3D(track)\n track = null\n strip = null\n board = null\n run = null\n parking = null\n }\n\n return {\n id: PROVING_AREA_ID,\n name: text.name,\n group: text.name,\n ground: { surface: 'road' },\n certificates: () => [...certificates.values()],\n certificate: (id) => certificateOf(id),\n items: () => [],\n area: (): ModuleArea => {\n // the room asks for the layout right after clearing for this area: from now on the track is built and the runs step\n open = true\n applyCamera()\n // the room's own view opens by the start line, the board in front and the track running away to the right\n return { placements: [], view: { eye: [TRACK.x0 - 4, 3.2, TRACK.z + 9], target: [TRACK.x0 + 6, 2.2, TRACK.z - TRACK.width / 2 - 3] } }\n },\n controls: (): ModuleControl[] => [\n { kind: 'choice', id: 'vehicle', name: text.controls.vehicle, hint: text.hints.vehicle, options: vehicles.map((id) => ({ id, name: name(id) })), default: settings.vehicle },\n { kind: 'choice', id: 'test', name: text.controls.test, hint: text.hints.test, options: measured.map((id) => ({ id, name: text.tests[id] ?? id })), default: settings.test },\n { kind: 'choice', id: 'camera', name: text.controls.camera, hint: text.hints.camera, options: (['room', 'chase', 'cockpit', 'hood'] as const).map((id) => ({ id, name: text.cameras[id] })), default: settings.camera },\n { kind: 'number', id: 'seat_forward', name: sysText.adjust.seat_forward, min: -0.2, max: 0.2, step: 0.02, default: 0 },\n { kind: 'number', id: 'seat_height', name: sysText.adjust.seat_height, min: -0.1, max: 0.1, step: 0.01, default: 0 },\n { kind: 'number', id: 'mirror_left', name: sysText.adjust.mirror_left, min: -0.3, max: 0.3, step: 0.02, default: 0 },\n { kind: 'number', id: 'mirror_right', name: sysText.adjust.mirror_right, min: -0.3, max: 0.3, step: 0.02, default: 0 },\n { kind: 'number', id: 'time_scale', name: text.controls.time_scale, hint: text.hints.time_scale, min: 1, max: 20, step: 1, default: settings.timeScale },\n { kind: 'choice', id: 'visual_check', name: text.controls.visual_check, hint: text.hints.visual_check, options: VISUAL_CHECKS.map((id) => ({ id, name: text.tests[id] ?? id })), default: settings.visual },\n { kind: 'action', id: 'drive', name: text.actions.drive },\n ...(Object.keys(sysText.actions) as Array<keyof SystemsText['actions']>).map((id): ModuleControl => ({ kind: 'action', id, name: sysText.actions[id] })),\n { kind: 'choice', id: 'gearbox', name: text.controls.gearbox, hint: text.hints.gearbox, options: (['automatic', 'manual'] as const).map((id) => ({ id, name: text.gearbox[id] })), default: gearbox },\n { kind: 'action', id: 'run_test', name: text.actions.run_test },\n { kind: 'action', id: 'run_all', name: text.actions.run_all },\n { kind: 'action', id: 'certify_now', name: text.actions.certify_now },\n { kind: 'action', id: 'reverse_park', name: text.actions.reverse_park },\n { kind: 'action', id: 'sign_ok', name: text.actions.sign_ok },\n { kind: 'action', id: 'sign_fail', name: text.actions.sign_fail },\n { kind: 'action', id: 'reset', name: text.actions.reset },\n ],\n layers: (): ModuleLayer[] => [\n { id: 'mirrors', name: text.layers.mirrors, default: false },\n { id: 'reverse_camera', name: text.layers.reverse_camera, default: false },\n { id: 'scoreboard', name: text.layers.scoreboard, default: true },\n ],\n metrics: (): ModuleMetric[] => [\n { id: 'speed', name: text.metrics.speed, unit: 'km/h', digits: 0, read: speedNow },\n { id: 'gear', name: text.metrics.gear, read: () => driving?.driver.state.gear ?? run?.driver.state.gear ?? 0 },\n { id: 'rpm', name: text.metrics.rpm, unit: 'rpm', digits: 0, read: () => driving?.driver.state.rpm ?? run?.driver.state.rpm ?? 0 },\n { id: 'time', name: text.metrics.time, unit: 's', digits: 1, read: () => run?.time ?? 0 },\n { id: 'fog', name: sysText.fog.metric, unit: '%', digits: 0, read: () => (driving?.fog.state.fog ?? 0) * 100 },\n { id: 'value', name: text.metrics.value, digits: 1, read: () => (run ? (run.trace[run.trace.length - 1]?.[1] ?? 0) : 0) },\n { id: 'passed', name: text.metrics.passed, read: () => counts('pass') },\n { id: 'failed', name: text.metrics.failed, read: () => counts('fail') },\n { id: 'pending', name: text.metrics.pending, read: () => counts('pending') },\n { id: 'status', name: text.metrics.status, read: () => ({ approved: 1, rejected: -1, pending: 0 })[certificateOf(settings.vehicle)?.status ?? 'pending'] },\n ],\n scenarios: (): ModuleScenario[] => [],\n attach(lent) {\n host = lent\n three = lent.THREE as Three\n rig.camera = new three.PerspectiveCamera(60, 1.6, 0.05, 900)\n rig.vehicle = createVehicleCamera(three as VehicleThreeLib)\n lent.audio?.register?.(LIBRARY_BANK)\n lent.audio?.register?.(CABIN_BANK)\n lent.audio?.register?.(VEHICLE_SOUND_BANK)\n lent.audio?.register?.(RADIO_BANK)\n const stopChange = lent.bench?.onChange(onChange)\n const stopFrame = lent.onFrame(frame)\n const stopClear = lent.onClear?.(() => {\n // the room cleared its area (another area opens, or this one again): the track and the car go until `area()` is asked again\n open = false\n teardown()\n lent.setViewCamera?.(null)\n })\n return () => {\n stopChange?.()\n stopFrame()\n stopClear?.()\n teardown()\n lent.setViewCamera?.(null)\n host = null\n }\n },\n }\n}\n\n/** What `loadProvingModule` needs of a room: `TestRoom.loadModule` has it. */\nexport type ProvingRoomLike = { loadModule(module: never): unknown; openArea?(id: string): unknown }\n\nexport function loadProvingModule<Room extends ProvingRoomLike>(room: Room, options: ProvingModuleOptions): ReturnType<Room['loadModule']> {\n return room.loadModule(createProvingModule(options) as never) as ReturnType<Room['loadModule']>\n}\n","/**\n * The player at the wheel of the proving ground's vehicle: the keyboard read into the vehicle controls of `game-vehicles-driving` (pedals, wheel, gearbox,\n * handbrake, ignition, drive mode, lamps, indicators, wipers, belt, horn, alarm and radio), the semi driver stepped with them, the car's systems\n * (`createVehicleSystems`: battery, coolant, spare tyre) stepped after it, the lamps of the built vehicle\n * switched (`createVehicleLamps`, the beacon of an emergency vehicle flashing with them), the glovebox and the trunk holding items (`createVehicleStorage`), the\n * glass misting up inside by the weather and the people in it (`createWindshieldFog`, drawn by `createWindshieldMist`) and the cabin sounds asked of the host.\n * Without the key (`hasKey: false`) the ignition key held hotwires the car. The driving keys are taken before the room sees them (capture phase), so W does\n * not also walk and F gets the driver out instead of the room's own use. Everything is removed by `stop`.\n */\nimport { RADIO_TRACKS } from '@adatechnology/game-audio'\nimport type { ModuleHost } from '@adatechnology/game-contracts'\nimport { bumperDistance, createSemiSimDriver, createVehicleControls, createVehicleStorage, createVehicleSystems, createWindshieldFog, GLOVEBOX, parkingBeepInterval, trunkFor } from '@adatechnology/game-vehicles-driving'\nimport type { CompartmentSpec, ControlEvent, SemiDriver, SemiEvent, StorageAccess, StorageStack, SystemsEvent, VehicleControls, VehicleStorage, VehicleSystems, WindshieldFog } from '@adatechnology/game-vehicles-driving'\nimport { subjectSpec } from '@adatechnology/game-vehicles-proving'\nimport type { ProvingSubject } from '@adatechnology/game-vehicles-proving'\n\nimport { createVehicleDestructible } from '@adatechnology/game-vehicles'\nimport type { VehicleContext, VehicleDestructible, VehicleKit } from '@adatechnology/game-vehicles'\n\nimport { createVehicleBody } from '../../body'\nimport type { BodyEvent, BodyThree, VehicleBody, WindowId } from '../../body'\nimport type { BuiltVehicle } from '../../build'\nimport { createVehicleDashboard } from '../../dashboard'\nimport type { VehicleDashboard } from '../../dashboard'\nimport { createVehicleLamps } from '../../lamps'\nimport type { VehicleLamps } from '../../lamps'\nimport { createWindshieldMist } from '../../windshield-mist'\nimport type { MistThree, WindshieldMist } from '../../windshield-mist'\n\n/** The cabin's sounds; an empty name stays silent (the starter, when the host's engine sound turns the key itself). */\nexport type CockpitSounds = { horn: string; blinker: string; starter: string; alarm: string; chirp: string; wiper: string; chime: string; radio: string; beep: string; wail: string; yelp: string; spark: string; glovebox: string }\nexport const DEFAULT_COCKPIT_SOUNDS: CockpitSounds = {\n horn: 'horn',\n blinker: 'blinker_tick',\n starter: 'starter_crank',\n alarm: 'car_alarm',\n chirp: 'alarm_chirp',\n wiper: 'wiper_swish',\n chime: 'seatbelt_chime',\n radio: 'radio_static',\n beep: 'parking_beep',\n wail: 'siren_wail',\n yelp: 'siren_yelp',\n spark: 'hotwire_spark',\n glovebox: 'glovebox_latch',\n}\n\n/** The weather around the car, for the mist on its glass: air temperature (°C) and rain on the glass (0..1). */\nexport interface CockpitWeather {\n outsideC: number\n rain: number\n}\n\n/** What the cockpit reports: a control used or refused, the engine (stall, out of fuel) and the systems (flat battery, overheating, spare). */\nexport type CockpitEvent = ControlEvent | SemiEvent | SystemsEvent | BodyEvent\n\n/** Keys of the body (doors 1-4, hood 5, trunk 6, the windows with Shift, the sunroof Shift+5, the central locking V). */\nexport const BODY_KEYS: Readonly<Record<string, string>> = {\n Digit1: 'door_front_left',\n Digit2: 'door_front_right',\n Digit3: 'door_rear_left',\n Digit4: 'door_rear_right',\n Digit5: 'hood',\n Digit6: 'lid',\n}\nconst WINDOW_KEYS: Readonly<Record<string, WindowId>> = { Digit1: 'front_left', Digit2: 'front_right', Digit3: 'rear_left', Digit4: 'rear_right' }\nconst LOCK_KEY = 'KeyV'\n/** Sweeps a second of the wiper blades in each mode (intermittent sweeps once every four seconds or so). */\nconst WIPE_RATE: Readonly<Record<string, number>> = { off: 0, intermittent: 0.25, slow: 0.7, fast: 1.4 }\n\nexport interface Cockpit {\n readonly driver: SemiDriver\n readonly controls: VehicleControls\n readonly systems: VehicleSystems\n /** The doors, windows, sunroof, wipers and locks (null on a vehicle drawn without its damage model). */\n readonly body: VehicleBody | null\n /** The car's damage model (null without the kit). */\n readonly destructible: VehicleDestructible | null\n /** What is left of the radiator, 0..1 (a punctured one barely cools). */\n radiator: number\n readonly lamps: VehicleLamps\n readonly dashboard: VehicleDashboard | null\n /** The gas this step, 0..1 (what the engine's sound loads by). */\n readonly throttle: number\n /** The glovebox and the trunk (only those the vehicle has: no trunk without a lid). */\n readonly storage: VehicleStorage\n /** What reaches the glovebox and the trunk now (the driver is seated). */\n access(): StorageAccess\n /** The glass misting up inside, and its look on the panes. */\n readonly fog: WindshieldFog\n readonly mist: WindshieldMist\n /** The weather the mist reads; change it at will. */\n weather: CockpitWeather\n /** The vehicle has a siren and a beacon. */\n readonly emergency: boolean\n step(dt: number): void\n stop(): void\n}\n\nexport function createCockpit(o: {\n THREE: Parameters<typeof createVehicleLamps>[0] & Parameters<typeof createVehicleDashboard>[0] & BodyThree & MistThree\n /** World points (x, z) the parking sensors see: obstacles near the bumpers. */\n obstacles?: () => ReadonlyArray<readonly [number, number]>\n /** The vehicle kit: with it the car gets its damage model, whose hinges the doors, hood and lid open on. */\n kit?: VehicleKit\n /** The kit's dial material (`kit.materials.gauge`): with it the cluster reads live. */\n gauge?: unknown\n /** The kit's needle material (`kit.materials.amber`). */\n needle?: unknown\n host: ModuleHost\n built: BuiltVehicle\n subject: ProvingSubject\n sounds?: Partial<CockpitSounds>\n /** The driver has the key. Default true; without it the ignition key held hotwires the car. */\n hasKey?: boolean\n /** What the glovebox and the trunk hold when the driver gets in (the host's items), by compartment id. */\n stock?: (compartment: string) => readonly StorageStack[]\n /** Trunk size, litres. Default 450. */\n trunkLitres?: number\n weather?: CockpitWeather\n place: [number, number, number]\n onEvent?: (event: CockpitEvent) => void\n onExit: () => void\n}): Cockpit {\n const sounds = { ...DEFAULT_COCKPIT_SOUNDS, ...o.sounds }\n const spec = subjectSpec(o.subject)\n const driver = createSemiSimDriver(spec)\n driver.place(o.place[0], o.place[1], o.place[2])\n const lamps = createVehicleLamps(o.THREE, o.built, { lights: o.host.lights, owner: 'proving-ground' })\n const mist = createWindshieldMist(o.THREE, o.built)\n const fog = createWindshieldFog()\n const audio = o.host.audio\n // the cluster: the speedometer to the next 20 km/h over the vehicle's top speed, the rev counter to its red line\n const top = o.subject.stats.maxSpeedKmh\n const dashboard = o.gauge ? createVehicleDashboard(o.THREE, o.built, { gauge: o.gauge, needle: o.needle, redlineRpm: spec.engine.redlineRpm, maxKmh: top ? Math.ceil((top + 10) / 20) * 20 : undefined }) : null\n const at = (): [number, number, number] => [o.built.group.position.x, 1, o.built.group.position.z]\n const play = (sound: string, volume = 1): void => void audio?.play?.({ sound, position: at(), volume })\n let alarmAgain = 0\n let hornAgain = 0\n let wipeAgain = 0\n let chimeAgain = 0\n let radioAgain = 0\n let beepAgain = 0\n let bar = 0\n let exitAsked = false\n let sirenAgain = 0\n let sparkAgain = 0\n let wiresBefore = 0\n let gas = 0\n const systems = createVehicleSystems()\n const context = o.built.context as VehicleContext | null\n const destructible: VehicleDestructible | null = o.kit && context ? createVehicleDestructible(o.kit, context, { id: 'driven', frame: o.built.group }) : null\n const body = destructible ? createVehicleBody(o.built, { THREE: o.THREE, clips: destructible.animations() }) : null\n // the glovebox behind the dashboard of a vehicle with doors, the trunk behind its lid\n const compartments: CompartmentSpec[] = []\n if (!body || body.parts.some((p) => p.startsWith('door'))) compartments.push(GLOVEBOX)\n if (body?.parts.includes('lid')) compartments.push(trunkFor(o.trunkLitres))\n const storage = createVehicleStorage({ compartments })\n for (const c of compartments) storage.stock(c.id, o.stock?.(c.id) ?? [])\n const access = (): StorageAccess => ({\n seated: true,\n frontDoorOpen: (body?.openness('door_front_left') ?? 0) >= 0.5 || (body?.openness('door_front_right') ?? 0) >= 0.5,\n gloveboxOpen: controls.state.glovebox,\n lid: body?.openness('lid') ?? 0,\n })\n const bodyEvents = (events: readonly BodyEvent[]): void => {\n for (const event of events) {\n if (event.type === 'sound') play(event.key, 0.9)\n o.onEvent?.(event)\n }\n }\n\n const controls = createVehicleControls({\n canCrank: systems.canCrank,\n onCrank: systems.crank,\n powerLimit: systems.powerLimit,\n gears: spec.gears?.length ?? 5,\n fourWheelDrive: !!o.subject.body.fourWheelDrive,\n fogLamps: lamps.has.fog,\n clutchPedal: true,\n radioTracks: RADIO_TRACKS.length,\n hasKey: o.hasKey,\n emergency: lamps.has.beacon,\n onEvent: (event) => {\n if (event.type === 'command') {\n if (event.command === 'ignition' && !event.state.ignition) driver.state.engineOn = false\n if (event.command === 'alarm' && event.state.alarm === 'armed') play(sounds.chirp)\n if (event.command === 'alarm') alarmAgain = 0\n if (event.command === 'radio' || event.command === 'radio_source' || event.command === 'radio_track') {\n radioAgain = 0\n bar = 0\n }\n if (event.command === 'exit') exitAsked = true\n if (event.command === 'siren') sirenAgain = 0\n if (event.command === 'glovebox') play(sounds.glovebox, 0.8)\n }\n o.onEvent?.(event)\n },\n })\n // the driver gets in with the engine off: the key (I) or the gas pedal starts it\n driver.state.engineOn = false\n\n const target: Window | null = typeof window !== 'undefined' ? window : null\n const bodyKey = (e: KeyboardEvent): boolean => {\n if (!body) return false\n if (e.code === LOCK_KEY) bodyEvents(body.lock(!body.locked))\n else if (e.shiftKey && e.code === 'Digit5') body.toggleSunroof()\n else if (e.shiftKey && WINDOW_KEYS[e.code]) body.toggleWindow(WINDOW_KEYS[e.code] as WindowId)\n else if (!e.shiftKey && BODY_KEYS[e.code]) bodyEvents(body.toggle(BODY_KEYS[e.code] as string))\n else return false\n return true\n }\n const down = (e: KeyboardEvent): void => {\n if (!e.repeat && bodyKey(e)) {\n e.stopImmediatePropagation()\n return\n }\n if (!controls.key(e.code, true)) return\n // the room listens on the window too: a driving key stops here\n e.stopImmediatePropagation()\n if (e.code.startsWith('Arrow') || e.code === 'Space') e.preventDefault()\n }\n const up = (e: KeyboardEvent): void => {\n if (controls.key(e.code, false)) e.stopImmediatePropagation()\n }\n const blur = (): void => controls.release()\n target?.addEventListener('keydown', down, true)\n target?.addEventListener('keyup', up, true)\n target?.addEventListener('blur', blur)\n\n const cockpit: Cockpit = {\n radiator: 1,\n storage,\n access,\n fog,\n mist,\n weather: { ...(o.weather ?? { outsideC: 25, rain: 0 }) },\n emergency: lamps.has.beacon,\n driver,\n controls,\n systems,\n body,\n destructible,\n lamps,\n dashboard,\n get throttle() {\n return gas\n },\n step(dt) {\n const input = controls.input(dt, driver)\n gas = input.throttle\n if (input.start && sounds.starter) play(sounds.starter)\n const engine = driver.step(input, dt).events\n controls.after(driver, dt)\n const s = controls.state\n const report = [...engine.filter((e) => e.type !== 'shift'), ...systems.step({ driver, controls: s, throttle: input.throttle, dt, radiator: cockpit.radiator })]\n for (const event of report) o.onEvent?.(event)\n // a flat battery with the engine off lights nothing\n const powered = driver.state.engineOn || systems.state.charge > 0\n const high = s.lamps.mode === 'high' || s.lamps.flash\n lamps.set({\n mode: !powered ? 'off' : s.lamps.flash ? 'high' : s.lamps.mode,\n fog: s.lamps.fog,\n interior: s.lamps.interior,\n brake: s.brakeLights,\n reverse: s.reverseLights,\n left: s.blinkOn && (s.indicator === 'left' || s.indicator === 'hazard'),\n right: s.blinkOn && (s.indicator === 'right' || s.indicator === 'hazard'),\n beacon: s.beacon && powered ? s.beaconSide : null,\n })\n // the glass mists by the people inside (the driver), the weather and the rain on it; the windows and the demister clear it\n const w = cockpit.weather\n const windows = body ? body.windows.reduce((sum, id) => sum + body.window(id), 0) / Math.max(1, body.windows.length) : 0\n const warm = systems.state.temperature\n const cabinC = s.climate.on ? 22 : w.outsideC + (driver.state.engineOn ? 3 + 5 * Math.min(1, warm * 2) : 2)\n mist.set(fog.step({ dt, occupants: 1, outsideC: w.outsideC, cabinC, rain: w.rain, speed: Math.abs(driver.state.u), windows, climate: s.climate, engineWarm: driver.state.engineOn ? Math.min(1, warm * 2) : 0 }).fog)\n // the siren: its tone again as it ends; the wires sparking while the hotwire key is held\n if (s.siren !== 'off' && powered && (sirenAgain -= dt) <= 0) {\n play(s.siren === 'wail' ? sounds.wail : sounds.yelp)\n sirenAgain = s.siren === 'wail' ? 2.95 : 1.95\n }\n const working = s.hotwire.progress > wiresBefore\n wiresBefore = s.hotwire.progress\n if (working && (sparkAgain -= dt) <= 0) {\n play(sounds.spark, 0.7)\n sparkAgain = 0.45 + 0.4 * ((s.hotwire.progress * 7) % 1)\n }\n dashboard?.update(\n {\n kmh: Math.abs(driver.state.u) * 3.6,\n rpm: driver.state.engineOn ? driver.state.rpm : 0,\n gear: driver.state.gear,\n ignition: s.ignition,\n engineOn: driver.state.engineOn,\n left: s.blinkOn && (s.indicator === 'left' || s.indicator === 'hazard'),\n right: s.blinkOn && (s.indicator === 'right' || s.indicator === 'hazard'),\n highBeam: high,\n fuel: driver.state.fuel / spec.tank.capacity,\n temperature: systems.state.temperature,\n cruise: s.cruise.on,\n profile: s.profile,\n tractionOff: !s.tractionControl,\n absOff: !s.abs,\n charging: systems.state.netW >= 0,\n lowBeam: s.lamps.mode === 'low' || s.lamps.mode === 'position',\n fog: s.lamps.fog,\n parkingBrake: s.parkingBrake,\n seatbelt: s.seatbelt,\n fourWheel: s.fourWheelEngaged,\n },\n dt,\n )\n if (body) bodyEvents(body.update(dt, s.washer ? 1.2 : (WIPE_RATE[s.wipers] ?? 0)))\n if (s.tick) play(sounds.blinker, 0.8)\n // parking sensors: in reverse the rear bumper, creeping forward the front one\n const near = o.obstacles?.() ?? []\n if (s.ignition && near.length && Math.abs(driver.state.u) < 3) {\n const g = o.built.group as { position: { x: number; z: number }; rotation: { y: number } }\n const reversing = driver.state.gear < 0 || driver.state.u < -0.05\n const distance = bumperDistance({ x: g.position.x, z: g.position.z, heading: [Math.sin(g.rotation.y), Math.cos(g.rotation.y)], length: o.built.length, width: o.built.width, forward: !reversing, obstacles: near })\n const every = parkingBeepInterval(distance)\n if (every != null && (beepAgain -= dt) <= 0) {\n play(sounds.beep, 0.7)\n beepAgain = every === 0 ? 0.09 : every\n }\n }\n // the horn's note is 0.6 s: held, it sounds again before the last one ends\n if (s.horn && (hornAgain -= dt) <= 0) {\n play(sounds.horn)\n hornAgain = 0.5\n } else if (!s.horn) hornAgain = 0\n if (s.alarm === 'ringing' && (alarmAgain -= dt) <= 0) {\n play(sounds.alarm)\n alarmAgain = 2.9\n }\n if ((s.wipers !== 'off' || s.washer) && (wipeAgain -= dt) <= 0) {\n play(sounds.wiper, 0.7)\n wipeAgain = s.washer || s.wipers === 'fast' ? 0.6 : s.wipers === 'slow' ? 1.4 : 4\n }\n // moving without the belt: the chime, every few seconds\n const kmh = Math.abs(driver.state.u) * 3.6\n if (!s.seatbelt && s.ignition && kmh > 10 && (chimeAgain -= dt) <= 0) {\n play(sounds.chime, 0.6)\n chimeAgain = 6\n }\n // the radio: the track picked, from the station (a little hiss under it) or the tape; a loop plays again when it ends\n if (s.radio.on && (radioAgain -= dt) <= 0) {\n const song = RADIO_TRACKS[s.radio.track % RADIO_TRACKS.length]\n if (song) {\n play(song.bars[bar % song.bars.length] as string, s.radio.source === 'tape' ? 0.8 : 0.7)\n bar++\n }\n if (s.radio.source === 'radio') play(sounds.radio, 0.12)\n radioAgain = song?.barSeconds ?? 2\n }\n if (exitAsked) {\n exitAsked = false\n o.onExit()\n }\n },\n stop() {\n target?.removeEventListener('keydown', down, true)\n target?.removeEventListener('keyup', up, true)\n target?.removeEventListener('blur', blur)\n controls.release()\n lamps.dispose()\n mist.dispose()\n storage.clear()\n dashboard?.dispose()\n body?.dispose()\n destructible?.dispose?.()\n },\n }\n return cockpit\n}\n","/**\n * The openings of a built vehicle worked by hand: each door, the hood and the trunk lid swing on the hinges the vehicle destructible draws (their open\n * pose is the one of its `open_*` clips, so the door takes its skin, glass and trim with it), each side window slides down into its door, a sunroof\n * slides back when the model has one, the wiper blades sweep, and the central locking keeps the doors and the lid shut. It moves only what the kit\n * drew and puts every part back on `dispose`.\n */\nimport type { AnimationClipSpec } from '@adatechnology/game-contracts'\n\nimport type { BuiltVehicle } from './build'\n\ntype Vec = { x: number; y: number; z: number; copy(v: Vec): Vec; clone(): Vec; sub(v: Vec): Vec; add(v: Vec): Vec; applyQuaternion(q: Quat): Vec }\ntype Quat = { copy(q: Quat): Quat; clone(): Quat; setFromAxisAngle(axis: Vec, angle: number): Quat; multiply(q: Quat): Quat }\n/** What the body needs of three.js: vectors and quaternions to turn a wiper about its spindle. */\nexport type BodyThree = { Vector3: new (x?: number, y?: number, z?: number) => Vec; Quaternion: new () => Quat }\ntype Obj = { name: string; parent: Obj | null; position: Vec; quaternion: Quat; rotation: { x: number; y: number; z: number; set(x: number, y: number, z: number): void }; userData: Record<string, unknown>; visible: boolean; traverse(fn: (o: Obj) => void): void; getObjectByName(name: string): Obj | undefined }\ntype Pane = Obj & { geometry?: { boundingBox: { min: { y: number }; max: { y: number } } | null; computeBoundingBox(): void } }\n\n/** A side window by where it sits: `front_left`, `rear_right`... */\nexport type WindowId = `${'front' | 'rear'}_${'left' | 'right'}`\n\nexport type BodyEvent = { type: 'sound'; key: string; part: string } | { type: 'refused'; part: string; reason: 'locked' | 'missing' }\n\nexport interface VehicleBodyOptions {\n THREE: BodyThree\n /** The open and close clips of the vehicle destructible (`animations()`): the open pose of each door, the hood and the lid. */\n clips: readonly AnimationClipSpec[]\n /** Seconds a door, the hood or the lid takes to open. Default 1.2 (the clips'). */\n swingSeconds?: number\n /** Seconds a window takes from shut to open. Default 3.5. */\n windowSeconds?: number\n /** Share of the pane's height that goes into the door. Default 0.92 (the top edge stays in the seal). */\n windowTravel?: number\n}\n\nexport interface VehicleBody {\n /** Part ids the body can open: `door_front_left`..., `hood`, `lid`. */\n readonly parts: readonly string[]\n readonly windows: readonly WindowId[]\n readonly hasSunroof: boolean\n readonly wipers: number\n readonly locked: boolean\n /** 0 shut to 1 open. */\n openness(part: string): number\n /** Opens a shut part or shuts an open one. Locked doors and lid refuse. */\n toggle(part: string): BodyEvent[]\n /** Window opening, 0 shut to 1 down. */\n window(id: WindowId): number\n toggleWindow(id: WindowId): void\n setWindow(id: WindowId, open: number): void\n toggleSunroof(): void\n /** Locks or unlocks the doors and the lid (the key or the remote). */\n lock(locked: boolean): BodyEvent[]\n /** Advances the moving parts; `wipe` is the wipers' sweeps per second (0 parked). */\n update(dt: number, wipe?: number): BodyEvent[]\n dispose(): void\n}\n\n/** The kit's own sounds (`VEHICLE_SOUND_BANK`): the latch opening any of them, and each one's slam shut. */\nconst OPEN_SOUND = 'car_door_open'\nconst SHUT_SOUND: Record<string, string> = { door: 'car_door_close', hood: 'car_hood_close', lid: 'car_trunk_close' }\nconst clamp = (x: number, a: number, b: number): number => Math.max(a, Math.min(b, x))\n\nexport function createVehicleBody(built: BuiltVehicle, options: VehicleBodyOptions): VehicleBody {\n const swing = options.swingSeconds ?? 1.2\n const windowSeconds = options.windowSeconds ?? 3.5\n const travel = options.windowTravel ?? 0.92\n const root = (built.context as { vehicle?: Obj } | null)?.vehicle ?? (built.group as Obj)\n // the open pose of each part, from the clips\n const poses = new Map<string, [number, number, number]>()\n for (const clip of options.clips) {\n if (!clip.id.startsWith('open_')) continue\n const last = clip.keys[clip.keys.length - 1]\n for (const [id, pose] of Object.entries(last?.parts ?? {})) if (pose.rotation) poses.set(id, pose.rotation as [number, number, number])\n }\n const hinges = new Map<string, { pivot: Obj; open: [number, number, number]; now: number; target: number }>()\n for (const [id, open] of poses) {\n const pivot = root.getObjectByName(id)\n if (pivot) hinges.set(id, { pivot, open, now: 0, target: 0 })\n }\n const kind = (part: string): string => (part.startsWith('door') ? 'door' : part === 'hood' ? 'hood' : 'lid')\n // side windows: the kit's panes keyed window_front / window_rear, side by the sign of z (left negative)\n const panes = new Map<WindowId, { pane: Pane; drop: number; now: number; target: number; applied: number }>()\n for (const glass of ((built.context as { glass?: Pane[] } | null)?.glass ?? [])) {\n const g = glass.userData.glass as { key?: string; side?: number } | undefined\n if (!g || (g.key !== 'window_front' && g.key !== 'window_rear')) continue\n const id = `${g.key === 'window_front' ? 'front' : 'rear'}_${(g.side ?? 1) < 0 ? 'left' : 'right'}` as WindowId\n if (panes.has(id) || !glass.geometry) continue\n glass.geometry.computeBoundingBox()\n const box = glass.geometry.boundingBox\n if (box) panes.set(id, { pane: glass, drop: (box.max.y - box.min.y) * travel, now: 0, target: 0, applied: 0 })\n }\n const sunroofs: Array<{ obj: Obj; slide: number; base: number }> = []\n // a wiper piece turns about its spindle on the windshield's normal; parked it is back exactly where the builder drew it\n const wipers: Array<{ obj: Obj; arm: number; sweep: number; spindle: Vec; axis: Vec; rest: Vec; restQ: Quat }> = []\n const T = options.THREE\n const turn = new T.Quaternion()\n root.traverse((o) => {\n const sun = o.userData.sunroof as { slide: number } | undefined\n if (sun) sunroofs.push({ obj: o, slide: sun.slide, base: o.position.x })\n })\n for (const { part, tag } of ((built.context as { wipers?: Array<{ part: Obj; tag: { arm: number; sweep: number; spindle: readonly number[]; axis: readonly number[] } }> } | null)?.wipers ?? []))\n wipers.push({ obj: part, arm: tag.arm, sweep: tag.sweep, spindle: new T.Vector3(...tag.spindle), axis: new T.Vector3(...tag.axis), rest: part.position.clone(), restQ: part.quaternion.clone() })\n let sunNow = 0\n let sunTarget = 0\n let wipePhase = 0\n let locked = false\n const placeWiper = (w: (typeof wipers)[number], angle: number): void => {\n if (angle === 0) {\n w.obj.position.copy(w.rest)\n w.obj.quaternion.copy(w.restQ)\n return\n }\n turn.setFromAxisAngle(w.axis, angle)\n w.obj.position.copy(w.rest).sub(w.spindle).applyQuaternion(turn).add(w.spindle)\n w.obj.quaternion.copy(turn).multiply(w.restQ)\n }\n const ease = (now: number, target: number, seconds: number, dt: number): number => now + clamp(target - now, -dt / seconds, dt / seconds)\n\n return {\n parts: [...hinges.keys()],\n windows: [...panes.keys()],\n hasSunroof: sunroofs.length > 0,\n wipers: new Set(wipers.map((w) => w.arm)).size,\n get locked() {\n return locked\n },\n openness: (part) => hinges.get(part)?.now ?? 0,\n toggle(part) {\n const h = hinges.get(part)\n if (!h) return [{ type: 'refused', part, reason: 'missing' }]\n if (locked && kind(part) !== 'hood' && h.target === 0) return [{ type: 'refused', part, reason: 'locked' }]\n h.target = h.target > 0 ? 0 : 1\n return h.target > 0 ? [{ type: 'sound', key: OPEN_SOUND, part }] : []\n },\n window: (id) => panes.get(id)?.now ?? 0,\n toggleWindow(id) {\n const w = panes.get(id)\n if (w) w.target = w.target > 0.5 ? 0 : 1\n },\n setWindow(id, open) {\n const w = panes.get(id)\n if (w) w.target = clamp(open, 0, 1)\n },\n toggleSunroof() {\n sunTarget = sunTarget > 0.5 ? 0 : 1\n },\n lock(on) {\n locked = on\n return [{ type: 'sound', key: 'blinker_tick', part: 'doors' }]\n },\n update(dt, wipe = 0) {\n const events: BodyEvent[] = []\n for (const [id, h] of hinges) {\n if (h.now === h.target) continue\n h.now = ease(h.now, h.target, swing, dt)\n h.pivot.rotation.set(h.open[0] * h.now, h.open[1] * h.now, h.open[2] * h.now)\n if (h.now === 0) events.push({ type: 'sound', key: SHUT_SOUND[kind(id)] ?? 'car_door_close', part: id })\n }\n // a window moves in its parent's frame: it may be the body or, once the door has swung, the door's hinge (both keep y up)\n for (const w of panes.values()) {\n if (w.now === w.target) continue\n w.now = ease(w.now, w.target, windowSeconds, dt)\n const offset = -w.drop * w.now\n w.pane.position.y += offset - w.applied\n w.applied = offset\n }\n if (sunNow !== sunTarget) {\n sunNow = ease(sunNow, sunTarget, 2.5, dt)\n for (const s of sunroofs) s.obj.position.x = s.base - s.slide * sunNow\n }\n // the blades sweep out and back; parked they come down to rest\n wipePhase = wipe > 0 ? (wipePhase + dt * wipe) % 1 : wipePhase > 0 ? Math.min(1, wipePhase + dt * 1.5) % 1 : 0\n const sweep = Math.sin(Math.PI * wipePhase)\n for (const w of wipers) placeWiper(w, w.sweep * sweep)\n return events\n },\n dispose() {\n for (const h of hinges.values()) h.pivot.rotation.set(0, 0, 0)\n for (const w of panes.values()) w.pane.position.y -= w.applied\n for (const s of sunroofs) s.obj.position.x = s.base\n for (const w of wipers) placeWiper(w, 0)\n },\n }\n}\n","/**\n * The instrument cluster of a built vehicle working: the two dials the kit draws in front of the driver (`kit.dashboard`, material `gauge`) get a\n * face that reads live, the speedometer and the rev counter with the gear, and the warning lights a driver looks for (indicators, high beam, fog,\n * handbrake, belt, battery and oil while the key is on and the engine is not, 4x4). The faces are canvases laid over the kit's dials, facing the\n * driver's eyes, and only while someone drives: `dispose` takes them away and frees them, the kit's drawing is never changed.\n */\nimport { discardObject3D } from '@adatechnology/game-shapes-three'\nimport type { CanvasTexture, CircleGeometry, Mesh, MeshBasicMaterial, Object3D, Vector3 } from 'three'\n\nimport type { BuiltVehicle } from './build'\n\n/** What the cluster shows this instant. */\nexport type DashboardReading = {\n kmh: number\n rpm: number\n /** -1 reverse, 0 neutral, 1.. forward. */\n gear: number\n ignition: boolean\n engineOn: boolean\n left: boolean\n right: boolean\n highBeam: boolean\n lowBeam: boolean\n fog: boolean\n parkingBrake: boolean\n seatbelt: boolean\n fourWheel: boolean\n /** Engine temperature, 0 (cold) to 1 (overheating); leave out while the engine has no heat model. */\n temperature?: number\n /** Fuel, 0 (empty) to 1 (full); leave out while the vehicle has no fuel model. */\n fuel?: number\n /** Cruise control holding a speed. */\n cruise?: boolean\n /** Drive profile shown by its letter (E economy, S sport; nothing for normal). */\n profile?: 'eco' | 'normal' | 'sport'\n /** The aids switched off light their amber lamps. */\n tractionOff?: boolean\n absOff?: boolean\n /** The alternator does not keep up (the battery drains with the engine running). */\n charging?: boolean\n}\n\n/** The scale of the dials and how often the faces are redrawn. */\nexport type DashboardOptions = {\n /** The kit's dial material (`kit.materials.gauge`): the dials are found by it. */\n gauge: unknown\n /** The kit's needle material (`kit.materials.amber`): the fixed needles drawn on the dials hide while the live face shows. */\n needle?: unknown\n /** Top of the speedometer, km/h. Default 220. */\n maxKmh?: number\n /** Red line of the rev counter. Default 6500. */\n redlineRpm?: number\n /** Redraws per second at most. Default 15. */\n fps?: number\n /** Where the canvases come from (tests pass a fake one). Default the page's. */\n document?: { createElement(tag: 'canvas'): HTMLCanvasElement }\n}\n\nexport interface VehicleDashboard {\n /** How many dials were found (0: a vehicle without a cluster drawn, nothing to show). */\n readonly dials: number\n update(reading: DashboardReading, dt: number): void\n dispose(): void\n}\n\ntype ThreeLib = {\n CanvasTexture: new (canvas: HTMLCanvasElement) => CanvasTexture\n CircleGeometry: new (radius: number, segments: number) => CircleGeometry\n MeshBasicMaterial: new (p: { map: CanvasTexture; transparent: boolean; toneMapped: boolean; depthWrite: boolean }) => MeshBasicMaterial\n Mesh: new (g: CircleGeometry, m: MeshBasicMaterial) => Mesh\n Vector3: new (x?: number, y?: number, z?: number) => Vector3\n}\n\n/** The colours of the cluster: the warning lights by the usual code (red stop, amber caution, green and blue information). */\nexport const DASHBOARD_LOOK = {\n face: '#0b1110',\n ring: '#2f3a36',\n marks: '#cfe8dc',\n needle: '#ff6a2a',\n red: '#e2402f',\n amber: '#f2a630',\n green: '#46d16f',\n blue: '#3f8cff',\n dim: 'rgba(207,232,220,0.12)',\n /** How far in front of the kit's dial the face sits, metres (the kit's needle sticks out 6 mm). */\n lift: 0.011,\n} as const\n\nconst SIZE = 256\n\nexport function createVehicleDashboard(THREE: ThreeLib, built: BuiltVehicle, options: DashboardOptions): VehicleDashboard {\n const maxKmh = options.maxKmh ?? 220\n const redline = options.redlineRpm ?? 6500\n const doc: { createElement(tag: 'canvas'): HTMLCanvasElement } | null = options.document ?? (typeof document !== 'undefined' ? document : null)\n const dials: Mesh[] = []\n built.group.traverse((o: Object3D) => {\n if ((o as Mesh).isMesh && (o as Mesh).material === options.gauge) dials.push(o as Mesh)\n })\n const eye = built.driverEye\n const hidden: Object3D[] = []\n const faces: Array<{ mesh: Mesh; canvas: HTMLCanvasElement; g: CanvasRenderingContext2D; texture: CanvasTexture; kind: 'speed' | 'rpm' }> = []\n if (doc && eye && dials.length) {\n built.group.updateMatrixWorld(true)\n const eyeWorld = built.group.localToWorld(new THREE.Vector3(eye[0], eye[1], eye[2]))\n // the two dials nearest the driver: speed on the left of the driver's view (+x is the driver's left), revs on the right\n const near = dials\n .map((d) => ({ d, at: d.getWorldPosition(new THREE.Vector3()) }))\n .sort((a, b) => a.at.distanceTo(eyeWorld) - b.at.distanceTo(eyeWorld))\n .slice(0, 2)\n .sort((a, b) => built.group.worldToLocal(b.at.clone()).x - built.group.worldToLocal(a.at.clone()).x)\n near.forEach(({ d, at }, i) => {\n const canvas = doc.createElement('canvas')\n canvas.width = canvas.height = SIZE\n const g = canvas.getContext('2d')\n if (!g) return\n const texture = new THREE.CanvasTexture(canvas)\n const radius = (d.geometry as { parameters?: { radiusTop?: number } }).parameters?.radiusTop ?? 0.055\n const mesh = new THREE.Mesh(new THREE.CircleGeometry(radius * 1.12, 40), new THREE.MeshBasicMaterial({ map: texture, transparent: true, toneMapped: false, depthWrite: false }))\n mesh.name = 'dashboard_face'\n // the face lies on the dial, along the dial's own axis (a cylinder's y), on the driver's side\n const axis = new THREE.Vector3(0, 1, 0).applyQuaternion(d.getWorldQuaternion(d.quaternion.clone())).normalize()\n if (axis.dot(eyeWorld.clone().sub(at)) < 0) axis.negate()\n const front = at.clone().addScaledVector(axis, DASHBOARD_LOOK.lift)\n mesh.position.copy(built.group.worldToLocal(front.clone()))\n built.group.add(mesh)\n mesh.updateMatrixWorld(true)\n mesh.lookAt(front.add(axis))\n // the kit's dial (its glowing side shows round the face at an angle) and its fixed needle step aside while the live face shows\n d.visible = false\n hidden.push(d)\n // the needle: the amber stick drawn on this dial\n if (options.needle)\n built.group.traverse((o: Object3D) => {\n if ((o as Mesh).isMesh && (o as Mesh).material === options.needle && o.visible && o.getWorldPosition(new THREE.Vector3()).distanceTo(at) < radius * 1.2) {\n o.visible = false\n hidden.push(o)\n }\n })\n faces.push({ mesh, canvas, g, texture, kind: near.length === 1 || i === 0 ? 'speed' : 'rpm' })\n })\n }\n\n const lamp = (g: CanvasRenderingContext2D, x: number, y: number, on: boolean, colour: string, draw: (g: CanvasRenderingContext2D) => void): void => {\n g.save()\n g.translate(x, y)\n g.fillStyle = g.strokeStyle = on ? colour : DASHBOARD_LOOK.dim\n g.lineWidth = 4\n draw(g)\n g.restore()\n }\n const arrow = (dir: 1 | -1) => (g: CanvasRenderingContext2D) => {\n g.beginPath()\n g.moveTo(dir * 14, 0)\n g.lineTo(-dir * 2, -12)\n g.lineTo(-dir * 2, -5)\n g.lineTo(-dir * 14, -5)\n g.lineTo(-dir * 14, 5)\n g.lineTo(-dir * 2, 5)\n g.lineTo(-dir * 2, 12)\n g.closePath()\n g.fill()\n }\n const beam = (g: CanvasRenderingContext2D) => {\n g.beginPath()\n g.arc(-4, 0, 10, Math.PI / 2, -Math.PI / 2, true)\n g.closePath()\n g.fill()\n for (let k = -1; k <= 1; k++) g.fillRect(8, k * 6 - 1.5, 10, 3)\n }\n // a seated person with the belt across the chest\n const belt = (g: CanvasRenderingContext2D) => {\n g.beginPath()\n g.arc(0, -10, 5, 0, Math.PI * 2)\n g.fill()\n g.fillRect(-6, -3, 12, 16)\n g.strokeStyle = DASHBOARD_LOOK.face\n g.lineWidth = 3\n g.beginPath()\n g.moveTo(-7, -3)\n g.lineTo(7, 12)\n g.stroke()\n }\n const letter = (text: string) => (g: CanvasRenderingContext2D) => {\n g.font = 'bold 22px sans-serif'\n g.textAlign = 'center'\n g.textBaseline = 'middle'\n g.fillText(text, 0, 1)\n }\n const ring = (text: string) => (g: CanvasRenderingContext2D) => {\n g.beginPath()\n g.arc(0, 0, 13, 0, Math.PI * 2)\n g.stroke()\n letter(text)(g)\n }\n const dial = (g: CanvasRenderingContext2D, value: number, top: number, step: number, redFrom: number | null, label: (v: number) => string): void => {\n const c = SIZE / 2\n g.clearRect(0, 0, SIZE, SIZE)\n g.fillStyle = DASHBOARD_LOOK.face\n g.beginPath()\n g.arc(c, c, c - 2, 0, Math.PI * 2)\n g.fill()\n g.strokeStyle = DASHBOARD_LOOK.ring\n g.lineWidth = 6\n g.stroke()\n // 240 degrees of sweep, from the lower left round to the lower right\n const angle = (v: number): number => Math.PI * 0.75 + (Math.max(0, Math.min(top, v)) / top) * Math.PI * 1.5\n for (let v = 0; v <= top + 1e-6; v += step) {\n const a = angle(v)\n g.strokeStyle = redFrom !== null && v >= redFrom ? DASHBOARD_LOOK.red : DASHBOARD_LOOK.marks\n g.lineWidth = 4\n g.beginPath()\n g.moveTo(c + Math.cos(a) * (c - 12), c + Math.sin(a) * (c - 12))\n g.lineTo(c + Math.cos(a) * (c - 30), c + Math.sin(a) * (c - 30))\n g.stroke()\n g.fillStyle = DASHBOARD_LOOK.marks\n g.font = '18px sans-serif'\n g.textAlign = 'center'\n g.textBaseline = 'middle'\n g.fillText(label(v), c + Math.cos(a) * (c - 48), c + Math.sin(a) * (c - 48))\n }\n const a = angle(value)\n g.strokeStyle = DASHBOARD_LOOK.needle\n g.lineWidth = 6\n g.beginPath()\n g.moveTo(c - Math.cos(a) * 14, c - Math.sin(a) * 14)\n g.lineTo(c + Math.cos(a) * (c - 22), c + Math.sin(a) * (c - 22))\n g.stroke()\n g.fillStyle = DASHBOARD_LOOK.ring\n g.beginPath()\n g.arc(c, c, 10, 0, Math.PI * 2)\n g.fill()\n }\n const bar = (g: CanvasRenderingContext2D, x: number, share: number | undefined, warnAbove: boolean, label: string): void => {\n if (share === undefined) return\n const h = 60\n g.strokeStyle = DASHBOARD_LOOK.marks\n g.lineWidth = 2\n g.strokeRect(x - 5, 150, 10, h)\n const s = Math.max(0, Math.min(1, share))\n g.fillStyle = (warnAbove ? s > 0.85 : s < 0.12) ? DASHBOARD_LOOK.red : DASHBOARD_LOOK.marks\n g.fillRect(x - 4, 150 + h * (1 - s), 8, h * s)\n g.font = '14px sans-serif'\n g.textAlign = 'center'\n g.fillText(label, x, 222)\n }\n\n const draw = (r: DashboardReading): void => {\n const warn = r.ignition && !r.engineOn\n for (const f of faces) {\n const g = f.g\n if (f.kind === 'speed') {\n dial(g, r.kmh, maxKmh, maxKmh > 160 ? 20 : 10, null, (v) => String(Math.round(v)))\n g.fillStyle = DASHBOARD_LOOK.marks\n g.font = 'bold 30px sans-serif'\n g.textAlign = 'center'\n g.fillText(String(Math.round(r.kmh)), SIZE / 2, SIZE / 2 + 52)\n lamp(g, 92, 178, r.left, DASHBOARD_LOOK.green, arrow(-1))\n lamp(g, 164, 178, r.right, DASHBOARD_LOOK.green, arrow(1))\n lamp(g, 104, 214, r.highBeam, DASHBOARD_LOOK.blue, beam)\n lamp(g, 152, 214, r.lowBeam || r.fog, r.fog ? DASHBOARD_LOOK.amber : DASHBOARD_LOOK.green, beam)\n bar(g, 40, r.fuel, false, 'F')\n lamp(g, 104, 244, !!r.cruise, DASHBOARD_LOOK.green, letter('CRZ'))\n if (r.profile && r.profile !== 'normal') lamp(g, 152, 244, true, r.profile === 'eco' ? DASHBOARD_LOOK.green : DASHBOARD_LOOK.amber, letter(r.profile === 'eco' ? 'E' : 'S'))\n } else {\n dial(g, r.rpm / 1000, Math.ceil(redline / 1000) + 1, 1, redline / 1000, (v) => String(Math.round(v)))\n g.fillStyle = DASHBOARD_LOOK.marks\n g.font = 'bold 34px sans-serif'\n g.textAlign = 'center'\n g.fillText(r.gear < 0 ? 'R' : r.gear === 0 ? 'N' : String(r.gear), SIZE / 2, SIZE / 2 + 54)\n lamp(g, 86, 178, r.parkingBrake, DASHBOARD_LOOK.red, ring('P'))\n lamp(g, 128, 214, r.ignition && !r.seatbelt, DASHBOARD_LOOK.red, belt)\n lamp(g, 170, 178, warn || (r.engineOn && r.charging === false), DASHBOARD_LOOK.red, letter('+−'))\n lamp(g, 104, 244, r.ignition && !!r.tractionOff, DASHBOARD_LOOK.amber, letter('TC'))\n lamp(g, 152, 244, r.ignition && !!r.absOff, DASHBOARD_LOOK.amber, letter('ABS'))\n lamp(g, 86, 214, warn, DASHBOARD_LOOK.red, letter('OIL'))\n lamp(g, 170, 214, r.fourWheel, DASHBOARD_LOOK.green, letter('4x4'))\n bar(g, SIZE - 40, r.temperature, true, 'T')\n }\n f.texture.needsUpdate = true\n }\n }\n\n let wait = 0\n let last = ''\n return {\n dials: faces.length,\n update(reading, dt) {\n if (!faces.length) return\n wait -= dt\n const key = JSON.stringify(reading)\n if (wait > 0 || key === last) return\n wait = 1 / (options.fps ?? 15)\n last = key\n draw(reading)\n },\n dispose() {\n for (const f of faces) {\n discardObject3D(f.mesh)\n f.texture.dispose()\n f.canvas.width = f.canvas.height = 0\n }\n faces.length = 0\n for (const o of hidden) o.visible = true\n hidden.length = 0\n },\n }\n}\n","/**\n * The lamps of a built vehicle switched on and off: position, low and high beam, fog lamps, the brake and reversing lamps and the cabin light. The glass of\n * each lamp the kit drew (`context.lights`) glows by the switch, its halo shows only when lit, and the beams that light the world are sources of the host's\n * light budget (`game-render-three`), never lights of their own. The beacon lamps of an emergency vehicle (meshes the fleet tags `userData.lamp = 'beacon'`\n * with their `beaconSide`, 0 or 1) flash one side and then the other. Everything it changes is put back by `dispose`.\n */\nimport { isLightBudget, LIGHT_PRIORITY } from '@adatechnology/game-render-three'\nimport type { LightBudget, SourceHandle } from '@adatechnology/game-render-three'\n\nimport type { Object3D } from 'three'\n\nimport type { BuiltVehicle } from './build'\n\nexport type LampSwitch = {\n mode: 'off' | 'position' | 'low' | 'high'\n fog: boolean\n interior: boolean\n brake: boolean\n reverse: boolean\n /** Indicator lamps lit this instant (the controls blink them). */\n left: boolean\n right: boolean\n /** The beacon: the side lit this instant (0 or 1), null with it off. Default off. */\n beacon?: 0 | 1 | null\n}\n\n/** Glow of the lamp glass by switch, as a share of what the kit drew (the kit draws them lit), and the beams. */\nexport const LAMP_RULES = {\n glow: { head: { off: 0.04, position: 0.3, low: 1, high: 1.35 }, tail: { off: 0.15, on: 0.7, brake: 1.6 }, fog: { off: 0.04, on: 1.1 }, amber: { off: 0.1, on: 2.2 }, beacon: { off: 0.35, dark: 0.12, lit: 2.8 } },\n low: { color: 0xfff1d0, intensity: 2.4, distance: 32, angle: 0.42, penumbra: 0.55, decay: 1.6, drop: 0.09 },\n high: { color: 0xfff6e2, intensity: 3.6, distance: 70, angle: 0.3, penumbra: 0.45, decay: 1.4, drop: 0.015 },\n fog: { color: 0xfff0c8, intensity: 1.6, distance: 16, angle: 0.75, penumbra: 0.7, decay: 1.8, drop: 0.12 },\n reverse: { color: 0xf4f6ff, intensity: 0.9, distance: 7, decay: 2 },\n interior: { color: 0xffe2b0, intensity: 0.5, distance: 2.4, decay: 2 },\n} as const\n\nexport interface VehicleLamps {\n /** What this vehicle has: fog lamps only when the kit drew them. */\n readonly has: { head: boolean; tail: boolean; fog: boolean; indicators: boolean; beacon: boolean }\n set(lamps: LampSwitch): void\n readonly state: LampSwitch\n dispose(): void\n}\n\n/** A lamp's glass material: the kit's are emissive standard materials (`MATERIALS.head`, `tail`, `led`, `amber`). */\ntype Glass = { clone(): Glass; dispose?(): void; emissiveIntensity?: number; color?: { r: number; g: number; b: number } }\ntype Glazed = { material: Glass | Glass[] | null }\ntype Lamp = { kind: string; fog?: boolean; inner: Glazed[]; halo?: Array<{ visible: boolean; scale: { x: number; y: number; set(x: number, y: number, z: number): void } }>; group?: { position?: { x: number } } }\n\nexport function createVehicleLamps(THREE: { Object3D: new () => Object3D }, built: BuiltVehicle, options: { lights?: unknown; owner?: string } = {}): VehicleLamps {\n const budget: LightBudget | null = isLightBudget(options.lights) ? options.lights : null\n const owner = options.owner ?? 'vehicle-lamps'\n // the kit's lamps, a fog lamp drawn as a headlight marked `fog`, and the decorative fog bulbs a body lists in `context.fogBulbs` (or tags `userData.lamp = 'fog'`)\n const context = built.context as { lights?: Array<Lamp & { fog?: boolean }>; fogBulbs?: Glazed[] } | null\n const lamps: Lamp[] = (context?.lights ?? [])\n .filter((l) => l && Array.isArray(l.inner))\n .map((l) => (l.fog ? { ...l, kind: 'fog' } : l))\n const bulbs: Glazed[] = (context?.fogBulbs ?? []).filter((o) => o?.material)\n built.group.traverse((o: Object3D & Partial<Glazed>) => {\n if (o.userData?.lamp === 'fog' && o.material && !bulbs.includes(o as Glazed)) bulbs.push(o as Glazed)\n })\n if (bulbs.length) lamps.push({ kind: 'fog', inner: bulbs })\n const beacons: Array<{ mesh: Glazed; side: 0 | 1 }> = []\n built.group.traverse((o: Object3D & Partial<Glazed>) => {\n if (o.userData?.lamp === 'beacon' && o.material) beacons.push({ mesh: o as Glazed, side: o.userData.beaconSide === 1 ? 1 : 0 })\n })\n const has = { head: lamps.some((l) => l.kind === 'headlight'), tail: lamps.some((l) => l.kind === 'taillight'), fog: lamps.some((l) => l.kind === 'fog'), indicators: false, beacon: beacons.length > 0 }\n // the kit's lamp materials are shared by every vehicle: this one gets its own copies, given back on dispose\n const originals = new Map<Glazed, Glass>()\n const copies = new Map<Glass, Glass>()\n const base = new Map<Glass, number>()\n const own = (mesh: Glazed): Glass | null => {\n const mat = mesh.material\n if (!mat || Array.isArray(mat)) return null\n if (copies.has(mat) || base.has(mat)) return mat\n const copy = mat.clone()\n originals.set(mesh, mat)\n copies.set(copy, mat)\n base.set(copy, mat.emissiveIntensity ?? 1)\n mesh.material = copy\n return copy\n }\n for (const b of beacons) own(b.mesh)\n const haloBase = new Map<object, number>()\n for (const l of lamps) {\n for (const m of l.inner) own(m)\n for (const h of l.halo ?? []) haloBase.set(h, h.scale.x)\n }\n // the amber parts of a lamp (indicators) blink on their own: told by the colour of the kit's amber, and by the side of the lamp (left is +x)\n const amber = new Set<Glazed>()\n const sideOf = new Map<Glazed, 'left' | 'right'>()\n for (const l of lamps) {\n const x = l.group?.position?.x ?? 0\n for (const m of l.inner) {\n const mat = Array.isArray(m.material) ? null : m.material\n const c = (mat && (copies.get(mat) ?? mat))?.color\n if (c && c.r > 0.5 && c.r - c.b > 0.35 && c.g < c.r * 0.8 && c.g > c.b) {\n amber.add(m)\n sideOf.set(m, x >= 0 ? 'left' : 'right')\n }\n }\n }\n has.indicators = amber.size > 0\n const glowMesh = (m: Glazed, share: number): void => {\n const mat = m.material\n if (mat && !Array.isArray(mat) && base.has(mat) && 'emissiveIntensity' in mat) mat.emissiveIntensity = (base.get(mat) as number) * share\n }\n const glow = (l: Lamp, share: number): void => {\n for (const m of l.inner) {\n if (amber.has(m)) continue\n glowMesh(m, share)\n }\n for (const h of l.halo ?? []) {\n h.visible = share > 0.5\n const s = (haloBase.get(h) ?? 1) * Math.min(1.4, share)\n h.scale.set(s, s, 1)\n }\n }\n\n // anchors on the vehicle for the beams: its front is +z, a spot shines down its anchor's -z\n const L = built.length\n const W = built.width\n const H = built.height\n const anchors: Object3D[] = []\n const anchor = (x: number, y: number, z: number, yaw: number, drop: number): Object3D => {\n const a = new THREE.Object3D()\n a.position.set(x, y, z)\n a.rotation.set(-drop, yaw, 0, 'YXZ')\n built.group.add(a)\n anchors.push(a)\n return a\n }\n const front = [-1, 1].map((s) => anchor(s * W * 0.34, Math.min(0.9, H * 0.48), L / 2 - 0.05, Math.PI, 0))\n const fogAnchors = [-1, 1].map((s) => anchor(s * W * 0.38, Math.min(0.45, H * 0.25), L / 2 - 0.03, Math.PI, 0))\n const rear = anchor(0, Math.min(0.9, H * 0.45), -L / 2 - 0.3, 0, 0)\n const cabin = anchor(0, H * 0.85, 0, 0, 0)\n\n const sources = new Map<string, SourceHandle[]>()\n const beam = (id: string, on: boolean, make: () => SourceHandle[]): void => {\n const now = sources.get(id)\n if (on && !now && budget) sources.set(id, make())\n if (!on && now) {\n for (const s of now) s.remove()\n sources.delete(id)\n }\n }\n const spots = (at: Object3D[], rule: { color: number; intensity: number; distance: number; angle: number; penumbra: number; decay: number; drop: number }): SourceHandle[] =>\n at.map((a) => {\n a.rotation.x = -rule.drop\n return (budget as LightBudget).addSource({ owner, kind: 'spot', priority: LIGHT_PRIORITY.headlight, color: rule.color, intensity: rule.intensity, distance: rule.distance, decay: rule.decay, angle: rule.angle, penumbra: rule.penumbra, position: [0, 0, 0], follow: a })\n })\n const point = (a: Object3D, rule: { color: number; intensity: number; distance: number; decay: number }): SourceHandle[] => [\n (budget as LightBudget).addSource({ owner, kind: 'point', priority: LIGHT_PRIORITY.lamp, color: rule.color, intensity: rule.intensity, distance: rule.distance, decay: rule.decay, position: [0, 0, 0], follow: a }),\n ]\n\n const state: LampSwitch = { mode: 'off', fog: false, interior: false, brake: false, reverse: false, left: false, right: false }\n const apply = (): void => {\n const g = LAMP_RULES.glow\n for (const l of lamps) {\n if (l.kind === 'headlight') glow(l, g.head[state.mode])\n else if (l.kind === 'taillight') glow(l, state.brake ? g.tail.brake : state.mode === 'off' ? g.tail.off : g.tail.on)\n else if (l.kind === 'fog') glow(l, state.fog ? g.fog.on : g.fog.off)\n }\n for (const m of amber) glowMesh(m, state[sideOf.get(m) ?? 'left'] ? g.amber.on : g.amber.off)\n const lit = state.beacon ?? null\n for (const b of beacons) glowMesh(b.mesh, lit === null ? g.beacon.off : lit === b.side ? g.beacon.lit : g.beacon.dark)\n // the low and the high beam are the same two spots, re-aimed: switching re-adds them with the other cone\n const beamId = state.mode === 'low' || state.mode === 'high' ? state.mode : null\n for (const id of ['low', 'high'] as const) beam(id, beamId === id, () => spots(front, LAMP_RULES[id]))\n beam('fog', state.fog && has.fog, () => spots(fogAnchors, LAMP_RULES.fog))\n beam('reverse', state.reverse, () => point(rear, LAMP_RULES.reverse))\n beam('interior', state.interior, () => point(cabin, LAMP_RULES.interior))\n }\n apply()\n\n return {\n has,\n get state() {\n return { ...state }\n },\n set(next) {\n if (next.mode === state.mode && next.fog === state.fog && next.interior === state.interior && next.brake === state.brake && next.reverse === state.reverse && next.left === state.left && next.right === state.right && (next.beacon ?? null) === (state.beacon ?? null)) return\n Object.assign(state, next)\n apply()\n },\n dispose() {\n for (const list of sources.values()) for (const s of list) s.remove()\n sources.clear()\n for (const a of anchors) a.removeFromParent()\n anchors.length = 0\n const giveBack = (m: Glazed): void => {\n const copy = m.material\n const original = originals.get(m)\n if (!original) return\n originals.delete(m)\n m.material = original\n if (copy && !Array.isArray(copy)) copy.dispose?.()\n }\n for (const b of beacons) giveBack(b.mesh)\n for (const l of lamps) {\n for (const m of l.inner) giveBack(m)\n for (const h of l.halo ?? []) {\n h.visible = true\n const s = haloBase.get(h) ?? 1\n h.scale.set(s, s, 1)\n }\n }\n originals.clear()\n copies.clear()\n base.clear()\n },\n }\n}\n","/**\n * The mist on the inside of a built vehicle's glass, drawn from the fog share of `createWindshieldFog` (`game-vehicles-driving`). Each pane the kit drew\n * (`context.glass`) gets a thin pale film that follows it (a side window going down, a door swinging), on the pane's own geometry; the windshield shows\n * the whole share and the other panes a little less, since the demister blows on the windshield first. The film is never hit by a shot (it has no\n * raycast) and never writes depth. `dispose` takes the films away and frees their materials; the geometry is the pane's and stays.\n */\nimport type { BufferGeometry, Material, Mesh, Object3D, Side } from 'three'\n\nimport type { BuiltVehicle } from './build'\n\n/** What the mist needs of three.js. */\nexport type MistThree = {\n Mesh: new (geometry: BufferGeometry, material: Material) => Mesh\n MeshBasicMaterial: new (parameters: { color: number; transparent: boolean; opacity: number; depthWrite: boolean; side: Side; polygonOffset: boolean; polygonOffsetFactor: number; polygonOffsetUnits: number }) => Material & { opacity: number }\n}\n\n/** How the mist looks: its colour, how opaque full fog is, and the share of it on the side and rear panes. */\nexport const MIST_RULES = { color: 0xe4e8ec, opacity: 0.72, others: 0.8 } as const\n\nexport interface WindshieldMist {\n /** Panes with a film. */\n readonly panes: number\n /** Shows `fog` (0 clear to 1 misted over). */\n set(fog: number): void\n readonly fog: number\n dispose(): void\n}\n\ntype Pane = Object3D & { geometry?: BufferGeometry; material?: { side?: number } | unknown[]; userData: { glass?: { key?: string } } }\n/** three.js `DoubleSide`: the kit draws its glass from both faces, and the film is seen from inside and out the same way. */\nconst DOUBLE_SIDE: Side = 2\n\nexport function createWindshieldMist(THREE: MistThree, built: BuiltVehicle): WindshieldMist {\n const glass = ((built.context as { glass?: Pane[] } | null)?.glass ?? []).filter((p) => p?.geometry)\n const films: Array<{ mesh: Mesh; material: Material & { opacity: number }; share: number }> = []\n for (const pane of glass) {\n const side = (!Array.isArray(pane.material) && (pane.material as { side?: Side } | undefined)?.side) || DOUBLE_SIDE\n const material = new THREE.MeshBasicMaterial({ color: MIST_RULES.color, transparent: true, opacity: 0, depthWrite: false, side, polygonOffset: true, polygonOffsetFactor: -1, polygonOffsetUnits: -1 })\n const mesh = new THREE.Mesh(pane.geometry as BufferGeometry, material)\n mesh.name = 'windshield_mist'\n // the film is a look of the pane, not a piece: shots, blows and the camera's picking pass to the glass under it\n mesh.raycast = () => {}\n mesh.userData.mist = true\n // drawn right after its pane (the kit sorts its glass with a render order of its own)\n mesh.renderOrder = pane.renderOrder + 1\n mesh.visible = false\n pane.add(mesh)\n films.push({ mesh, material, share: pane.userData.glass?.key === 'windshield' ? 1 : MIST_RULES.others })\n }\n let fog = 0\n return {\n panes: films.length,\n get fog() {\n return fog\n },\n set(next) {\n const share = Math.max(0, Math.min(1, next))\n if (Math.abs(share - fog) < 0.005 && (share > 0) === (fog > 0)) return\n fog = share\n for (const f of films) {\n f.material.opacity = MIST_RULES.opacity * fog * f.share\n f.mesh.visible = fog > 0.01\n }\n },\n dispose() {\n for (const f of films) {\n // the geometry is the pane's: only the film's own material goes\n f.mesh.removeFromParent()\n f.material.dispose()\n }\n films.length = 0\n },\n }\n}\n","import type { Vec3 } from '@adatechnology/game-contracts'\n\n/** How many vehicles are heard at once: the nearest `max` to the listener keep their loops, the others are silent until they come closer. */\nexport type EngineBudget = {\n /** Reports where a vehicle is this frame; true when it is among the nearest `max` (it may sound). */\n admit(vehicle: object, position: Vec3): boolean\n /** Forgets a vehicle (it left the scene). */\n release(vehicle: object): void\n /** Vehicles being tracked. */\n readonly size: number\n}\n\nexport type EngineBudgetOptions = {\n /** Default 6: a street of idling cars is a hum, not a wall of a hundred engines. */\n readonly max?: number\n /** Where the listener is (the camera or the player). */\n readonly listener: () => Vec3\n}\n\nconst distanceSq = (a: Vec3, b: Vec3): number => (a[0] - b[0]) ** 2 + (a[1] - b[1]) ** 2 + (a[2] - b[2]) ** 2\n\n/**\n * A level of detail for vehicle sound, shared by every `createVehicleSound` of a scene (`VehicleSoundOptions.budget`): each vehicle reports its\n * place every frame and only the nearest `max` keep their engine and tyre loops. A vehicle that falls out fades its loops to silence; its one-shots\n * (a crash, the starter) still play, since they are rare and the engine's voice limiter already ranks them.\n */\nexport function createEngineBudget(options: EngineBudgetOptions): EngineBudget {\n const max = Math.max(1, options.max ?? 6)\n const places = new Map<object, number>()\n return {\n admit(vehicle, position) {\n const own = distanceSq(position, options.listener())\n places.set(vehicle, own)\n if (places.size <= max) return true\n // its rank among the vehicles reported: how many are nearer (ties go to the one reported first)\n let nearer = 0\n for (const [other, d] of places) {\n if (other === vehicle) continue\n if (d < own) nearer++\n if (nearer >= max) return false\n }\n return true\n },\n release(vehicle) {\n places.delete(vehicle)\n },\n get size() {\n return places.size\n },\n }\n}\n","/**\n * The wheels of a built vehicle turning as it moves: each wheel the kit drew (`context.wheels`) rolls about its axle by the distance travelled over\n * its radius, and the front ones turn with the steering. The turn is applied over the wheel's own rest pose, so a mirrored or tilted wheel rolls the\n * right way, and `dispose` puts every wheel back exactly as it was drawn.\n */\nimport type { BuiltVehicle } from './build'\n\ntype Vec = { x: number; y: number; z: number }\ntype Quat = { copy(q: Quat): Quat; clone(): Quat; setFromAxisAngle(axis: Vec, angle: number): Quat; multiply(q: Quat): Quat; premultiply(q: Quat): Quat }\ntype Wheel = { position: Vec; quaternion: Quat; userData: Record<string, unknown> }\n\n/** What the wheels need of three.js. */\nexport type WheelRollThree = { Vector3: new (x?: number, y?: number, z?: number) => Vec; Quaternion: new () => Quat }\n\nexport interface WheelRoll {\n /** Wheels found on the vehicle. */\n readonly count: number\n /** The vehicle went `distance` metres forward (negative backwards) with the front wheels steered `steer` radians (positive to the left). */\n roll(distance: number, steer: number): void\n dispose(): void\n}\n\n/** A wheel's radius when the kit did not record one, metres. */\nconst DEFAULT_RADIUS = 0.32\n\nexport function createWheelRoll(THREE: WheelRollThree, built: BuiltVehicle): WheelRoll {\n const wheels = ((built.context as { wheels?: Wheel[] } | null)?.wheels ?? []).map((wheel) => ({\n wheel,\n rest: wheel.quaternion.clone(),\n radius: Number(wheel.userData.r) || DEFAULT_RADIUS,\n // in the kit's frame the front is +x: the wheels ahead of the middle steer\n front: wheel.position.x > 0,\n angle: 0,\n }))\n // the kit's frame: x forward, y up, z to the right; a wheel rolling forward turns about +z the negative way\n const axle = new THREE.Vector3(0, 0, 1)\n const up = new THREE.Vector3(0, 1, 0)\n const spin = new THREE.Quaternion()\n const steering = new THREE.Quaternion()\n return {\n count: wheels.length,\n roll(distance, steer) {\n for (const w of wheels) {\n w.angle = (w.angle - distance / w.radius) % (Math.PI * 2)\n spin.setFromAxisAngle(axle, w.angle)\n steering.setFromAxisAngle(up, w.front ? steer : 0)\n w.wheel.quaternion.copy(w.rest).premultiply(spin).premultiply(steering)\n }\n },\n dispose() {\n for (const w of wheels) w.wheel.quaternion.copy(w.rest)\n },\n }\n}\n","/**\n * The proving ground's crash against an immovable wall: the driven car stops dead, the pulse goes to `ejectionOf` of `game-vehicles-driving`, and an\n * occupant without a belt breaks the glass of the exit and flies out: a person of the host's catalogue thrown with `launchBody`, so the module that\n * animates it flies, lands, slides and lays it down as it does a body a blast knocked over. Everything it adds goes on `dispose`.\n */\nimport { launchBody } from '@adatechnology/game-contracts'\nimport type { ModuleHost, Vec3 } from '@adatechnology/game-contracts'\nimport { ejectionOf } from '@adatechnology/game-vehicles-driving'\nimport type { Ejection } from '@adatechnology/game-vehicles-driving'\nimport type { VehicleDestructible } from '@adatechnology/game-vehicles'\n\n/** Energy of the body against the glass, joules: enough to break a windshield or a side window. */\nconst GLASS_BLOW = 6000\n\ntype Root = { position: { x: number; y: number; z: number }; userData: Record<string, unknown> }\n\nexport interface ProvingCrash {\n /** Stops the car dead against a wall: answers the ejection, or null when the occupant stays in. */\n crash(params: { car: { position: Root['position']; rotationY: number }; u: number; w: number; belted: boolean; destructible: VehicleDestructible | null }): Ejection | null\n dispose(): void\n}\n\nexport function createProvingCrash(host: ModuleHost, occupant: string | undefined): ProvingCrash {\n const thrown: Array<() => void> = []\n const breakGlass = (destructible: VehicleDestructible | null, exit: Ejection['exit'], forward: Vec3): void => {\n if (!destructible) return\n const want = exit === 'windshield' ? 'windshield' : exit === 'rear_window' ? 'rear' : exit.startsWith('left') ? 'left' : 'right'\n const pane = destructible.describe().parts.find((p) => p.id.includes(exit === 'windshield' || exit === 'rear_window' ? want : 'window') && (exit === 'windshield' || exit === 'rear_window' || p.id.includes(want)))\n if (!pane) return\n destructible.hit({ type: 'blunt', partId: pane.id, point: destructible.partWorldCenter(pane.id), direction: forward, energy: GLASS_BLOW, radius: 0.35, source: 'occupant' } as never)\n }\n return {\n crash({ car, u, w, belted, destructible }) {\n const ejection = ejectionOf({ before: { u, w }, after: { u: 0, w: 0 } }, belted)\n if (!ejection) return null\n // the game frame: front +z, right −x, turned by the car's yaw\n const s = Math.sin(car.rotationY)\n const c = Math.cos(car.rotationY)\n const forward: Vec3 = [s, 0, c]\n const right: Vec3 = [-c, 0, s]\n breakGlass(destructible, ejection.exit, forward)\n const [vf, vr, vu] = ejection.velocity\n const start: Vec3 = [car.position.x + forward[0] * 1.2, 1.1, car.position.z + forward[2] * 1.2]\n const placed = occupant ? host.addObject?.(occupant, { position: start, rotationY: car.rotationY }) : null\n if (placed) {\n launchBody(placed.root as Root, [forward[0] * vf + right[0] * vr, vu, forward[2] * vf + right[2] * vr])\n thrown.push(placed.remove)\n }\n return ejection\n },\n dispose() {\n for (const remove of thrown.splice(0)) remove()\n },\n }\n}\n","/** The words of the car's systems and driver aids in the proving ground: the bench actions that test them and the log lines of what they report. */\nexport interface SystemsText {\n keys: string\n profile: string\n profiles: Record<'eco' | 'normal' | 'sport', string>\n traction: string\n abs: string\n cruise: string\n cruiseSet: string\n climate: string\n demist: string\n wiperModes: Record<'off' | 'intermittent' | 'slow' | 'fast', string>\n refused: Record<'battery_flat' | 'too_slow' | 'locked' | 'missing' | 'no_key' | 'no_siren', string>\n events: Record<'stall' | 'out_of_fuel' | 'bogged' | 'aquaplaning' | 'battery_flat' | 'overheating' | 'seized' | 'spare_fitted' | 'no_spare' | 'cruise_cancelled' | 'hotwire_started' | 'hotwire_joined', string>\n actions: Record<\n | 'puncture'\n | 'fit_spare'\n | 'refuel'\n | 'drain_battery'\n | 'jump_start'\n | 'break_radiator'\n | 'empty_tank'\n | 'remote_lock'\n | 'remote_unlock'\n | 'force_door'\n | 'crash_wall'\n | 'park_behind'\n | 'take_key'\n | 'cold_rain'\n | 'glovebox_contents'\n | 'trunk_contents'\n | 'take_from_trunk',\n string\n >\n /** The siren, the beacon and the glovebox switches as the log shows them. */\n siren: string\n sirenModes: Record<'off' | 'wail' | 'yelp', string>\n beacon: string\n glovebox: string\n lid: Record<'open' | 'shut', string>\n storage: { names: Record<'glovebox' | 'trunk', string>; empty: string; shut: string; list: string; none: string; taken: string; ground: string }\n fog: { misted: string; clear: string; weather: string; fair: string; metric: string }\n keyTaken: string\n keyBack: string\n parking: Record<'placed' | 'none', string>\n track: string\n adjust: Record<'seat_forward' | 'seat_height' | 'mirror_left' | 'mirror_right', string>\n crash: { mild: string; stayed: string; ejected: string; exits: Record<'windshield' | 'left_window' | 'right_window' | 'rear_window', string> }\n bodyKeys: string\n remote: Record<'locked' | 'unlocked' | 'forced', string>\n done: Record<'puncture' | 'refuel' | 'drain_battery' | 'jump_start' | 'break_radiator' | 'empty_tank', string>\n}\n\nexport const SYSTEMS_TEXT: Record<string, SystemsText> = {\n 'pt-BR': {\n keys: 'C embreagem (câmbio manual) · X lampejo do farol alto · Z esguicho do limpador · 7 modo econômico/normal/esporte · 8 controle de tração · 9 ABS · 0 piloto automático · - ar-condicionado · = desembaçador · ] troca a faixa do rádio ou da fita · ; sirene · \\' giroflex (veículo de emergência) · / porta-luvas · sem a chave, segure I: ligação direta',\n profile: 'Modo de condução',\n profiles: { eco: 'econômico', normal: 'normal', sport: 'esporte' },\n traction: 'Controle de tração',\n abs: 'ABS',\n cruise: 'Piloto automático',\n cruiseSet: 'Piloto automático: segurando {0} km/h',\n climate: 'Ar-condicionado',\n demist: 'Desembaçador',\n wiperModes: { off: 'desligado', intermittent: 'intermitente', slow: 'lento', fast: 'rápido' },\n refused: { battery_flat: 'Bateria descarregada: o motor de partida não gira', too_slow: 'Piloto automático só acima de 30 km/h', locked: 'Porta travada', missing: 'Este veículo não tem essa peça', no_key: 'Sem a chave: segure I para fazer a ligação direta', no_siren: 'Este veículo não tem sirene nem giroflex' },\n events: {\n stall: 'O motor morreu',\n out_of_fuel: 'Acabou o combustível',\n bogged: 'Atolou',\n aquaplaning: 'Aquaplanagem',\n battery_flat: 'A bateria descarregou',\n overheating: 'Motor superaquecendo: perdendo potência',\n seized: 'O motor fundiu de tanto esquentar',\n spare_fitted: 'Estepe colocado',\n no_spare: 'Não há estepe',\n cruise_cancelled: 'Piloto automático desligado',\n hotwire_started: 'Fios descascados sob a coluna: continue segurando I',\n hotwire_joined: 'Ligação direta feita: a ignição pegou e o motor de partida gira',\n },\n actions: { puncture: 'Furar pneu (dianteiro esquerdo)', fit_spare: 'Trocar pelo estepe', refuel: 'Abastecer', drain_battery: 'Descarregar bateria', jump_start: 'Chupeta (carregar bateria)', break_radiator: 'Furar o radiador', empty_tank: 'Deixar o tanque na reserva', remote_lock: 'Controle: travar (arma o alarme)', remote_unlock: 'Controle: destravar', force_door: 'Forçar a porta do motorista', crash_wall: 'Bater no muro (parada seca)', park_behind: 'Estacionar um carro atrás (sensor de ré)', take_key: 'Tirar a chave (ligação direta) / devolver', cold_rain: 'Tempo: frio e chuva / bom', glovebox_contents: 'Ver o porta-luvas', trunk_contents: 'Ver o porta-malas', take_from_trunk: 'Tirar um item do porta-malas para o chão' },\n siren: 'Sirene',\n sirenModes: { off: 'desligada', wail: 'contínua', yelp: 'rápida (cruzamento)' },\n beacon: 'Giroflex',\n glovebox: 'Porta-luvas',\n lid: { open: 'aberto', shut: 'fechado' },\n storage: { names: { glovebox: 'Porta-luvas', trunk: 'Porta-malas' }, empty: '{0}: vazio', shut: '{0} fechado: abra antes (porta-luvas com / sentado, porta-malas com 6)', list: '{0} ({1} kg): {2}', none: 'Este veículo não tem {0}', taken: '{0} tirado do porta-malas e posto no chão', ground: '{0} tirado do porta-malas (sem catálogo de itens nesta sala para pô-lo no chão)' },\n fog: { misted: 'O para-brisa embaçou por dentro: = desembaçador, ar-condicionado ou um vidro aberto', clear: 'Para-brisa desembaçado', weather: 'Lá fora: 8 °C e chuva', fair: 'Lá fora: 25 °C, sem chuva', metric: 'Vidro embaçado' },\n keyTaken: 'Sem a chave no contato: segure I para a ligação direta',\n keyBack: 'Chave de volta no contato',\n parking: { placed: 'Carro parado 3 m atrás: dê ré e escute o sensor', none: 'Sem catálogo de veículos nesta sala: o sensor não tem o que ver' },\n track: 'faixa {0}',\n adjust: { seat_forward: 'Banco: frente/trás (m)', seat_height: 'Banco: altura (m)', mirror_left: 'Retrovisor esquerdo: ângulo', mirror_right: 'Retrovisor direito: ângulo' },\n crash: { mild: 'Batida a {0} km/h: fraca demais para lançar quem está sem cinto', stayed: 'Batida a {0} km/h: o cinto segurou o motorista', ejected: 'Batida a {0} km/h sem cinto: o motorista saiu pelo {1}', exits: { windshield: 'para-brisa', left_window: 'vidro esquerdo', right_window: 'vidro direito', rear_window: 'vidro traseiro' } },\n bodyKeys: '1 a 4 portas · 5 capô · 6 porta-malas · Shift+1 a 4 vidros · Shift+5 teto solar · V trava as portas',\n remote: { locked: 'Travado pelo controle: alarme armado', unlocked: 'Destravado pelo controle', forced: 'Porta forçada' },\n done: { puncture: 'Pneu dianteiro esquerdo furado', refuel: 'Tanque cheio', drain_battery: 'Bateria quase sem carga', jump_start: 'Bateria carregada', break_radiator: 'Radiador furado: o motor vai esquentar', empty_tank: 'Tanque na reserva' },\n },\n en: {\n keys: \"C clutch (manual gearbox) · X flash the high beam · Z washer · 7 eco/normal/sport · 8 traction control · 9 ABS · 0 cruise control · - air conditioning · = demister · ] next radio or tape track · ; siren · ' beacon (emergency vehicle) · / glovebox · without the key, hold I: hotwire\",\n profile: 'Drive profile',\n profiles: { eco: 'eco', normal: 'normal', sport: 'sport' },\n traction: 'Traction control',\n abs: 'ABS',\n cruise: 'Cruise control',\n cruiseSet: 'Cruise control: holding {0} km/h',\n climate: 'Air conditioning',\n demist: 'Demister',\n wiperModes: { off: 'off', intermittent: 'intermittent', slow: 'slow', fast: 'fast' },\n refused: { battery_flat: 'Flat battery: the starter does not turn', too_slow: 'Cruise control only above 30 km/h', locked: 'The door is locked', missing: 'This vehicle has no such part', no_key: 'No key: hold I to hotwire it', no_siren: 'This vehicle has no siren or beacon' },\n events: {\n stall: 'The engine stalled',\n out_of_fuel: 'Out of fuel',\n bogged: 'Bogged down',\n aquaplaning: 'Aquaplaning',\n battery_flat: 'The battery went flat',\n overheating: 'Engine overheating: losing power',\n seized: 'The engine seized from the heat',\n spare_fitted: 'Spare tyre fitted',\n no_spare: 'No spare tyre left',\n cruise_cancelled: 'Cruise control off',\n hotwire_started: 'Wires stripped under the column: keep holding I',\n hotwire_joined: 'Hotwired: the ignition is live and the starter turns',\n },\n actions: { puncture: 'Puncture a tyre (front left)', fit_spare: 'Fit the spare', refuel: 'Refuel', drain_battery: 'Drain the battery', jump_start: 'Jump start (charge the battery)', break_radiator: 'Puncture the radiator', empty_tank: 'Leave the tank on reserve', remote_lock: 'Remote: lock (arms the alarm)', remote_unlock: 'Remote: unlock', force_door: \"Force the driver's door\", crash_wall: 'Hit a wall (dead stop)', park_behind: 'Park a car behind (rear sensor)', take_key: 'Take the key out (hotwire) / give it back', cold_rain: 'Weather: cold and rain / fair', glovebox_contents: 'Look in the glovebox', trunk_contents: 'Look in the trunk', take_from_trunk: 'Take an item out of the trunk to the ground' },\n siren: 'Siren',\n sirenModes: { off: 'off', wail: 'wail', yelp: 'yelp (junction)' },\n beacon: 'Beacon',\n glovebox: 'Glovebox',\n lid: { open: 'open', shut: 'shut' },\n storage: { names: { glovebox: 'Glovebox', trunk: 'Trunk' }, empty: '{0}: empty', shut: '{0} shut: open it first (glovebox with / while seated, trunk with 6)', list: '{0} ({1} kg): {2}', none: 'This vehicle has no {0}', taken: '{0} taken out of the trunk and put on the ground', ground: '{0} taken out of the trunk (no item catalogue in this room to put it on the ground)' },\n fog: { misted: 'The windshield misted up inside: = demister, air conditioning or a window down', clear: 'Windshield clear', weather: 'Outside: 8 °C and rain', fair: 'Outside: 25 °C, no rain', metric: 'Glass misted' },\n keyTaken: 'No key in the ignition: hold I to hotwire',\n keyBack: 'Key back in the ignition',\n parking: { placed: 'A car parked 3 m behind: reverse and listen to the sensor', none: 'No vehicle catalogue in this room: the sensor has nothing to see' },\n track: 'track {0}',\n adjust: { seat_forward: 'Seat: forward/back (m)', seat_height: 'Seat: height (m)', mirror_left: 'Left mirror: angle', mirror_right: 'Right mirror: angle' },\n crash: { mild: 'Crash at {0} km/h: too mild to throw an unbelted occupant out', stayed: 'Crash at {0} km/h: the belt held the driver', ejected: 'Crash at {0} km/h without a belt: the driver went out through the {1}', exits: { windshield: 'windshield', left_window: 'left window', right_window: 'right window', rear_window: 'rear window' } },\n bodyKeys: '1 to 4 doors · 5 hood · 6 trunk · Shift+1 to 4 windows · Shift+5 sunroof · V locks the doors',\n remote: { locked: 'Locked by the remote: alarm armed', unlocked: 'Unlocked by the remote', forced: 'Door forced' },\n done: { puncture: 'Front left tyre punctured', refuel: 'Tank full', drain_battery: 'Battery almost flat', jump_start: 'Battery charged', break_radiator: 'Radiator punctured: the engine will heat up', empty_tank: 'Tank on reserve' },\n },\n}\n","/** Texts of the proving ground, in Brazilian Portuguese and English. */\nexport type ProvingText = {\n name: string\n controls: Record<'vehicle' | 'test' | 'camera' | 'time_scale' | 'visual_check' | 'gearbox', string>\n hints: Record<'vehicle' | 'test' | 'camera' | 'time_scale' | 'visual_check' | 'gearbox', string>\n gearbox: Record<'automatic' | 'manual', string>\n actions: Record<'drive' | 'run_test' | 'run_all' | 'certify_now' | 'reverse_park' | 'sign_ok' | 'sign_fail' | 'reset', string>\n layers: Record<'mirrors' | 'reverse_camera' | 'scoreboard', string>\n metrics: Record<'gear' | 'rpm' | 'speed' | 'time' | 'value' | 'passed' | 'failed' | 'pending' | 'status', string>\n cameras: Record<'room' | 'chase' | 'cockpit' | 'hood', string>\n tests: Record<string, string>\n status: Record<'approved' | 'rejected' | 'pending', string>\n verdict: Record<'pass' | 'fail' | 'pending', string>\n board: { title: string; test: string; value: string; range: string; verdict: string; notRun: string; running: string; gear: string }\n log: { start: string; result: string; signed: string; certified: string; drive: string; leave: string; shift: string }\n cabin: {\n keys: string\n on: string\n off: string\n ignition: string\n gearbox: string\n gear: string\n parkingBrake: string\n driveMode: string\n modes: Record<'4x2' | '4x4' | 'auto', string>\n lights: string\n lampModes: Record<'off' | 'position' | 'low' | 'high', string>\n fog: string\n interior: string\n alarm: string\n alarmStates: Record<'off' | 'armed' | 'ringing', string>\n radio: string\n sources: Record<'radio' | 'tape', string>\n indicator: string\n indicators: Record<'off' | 'left' | 'right' | 'hazard', string>\n wipers: string\n wiperModes: Record<'off' | 'slow' | 'fast', string>\n seatbelt: string\n refused: Record<string, string>\n }\n}\n\nexport const PROVING_TEXT: Record<string, ProvingText> = {\n 'pt-BR': {\n name: 'Banco de provas',\n controls: { vehicle: 'Veículo', test: 'Prova', camera: 'Câmera', time_scale: 'Velocidade da simulação', visual_check: 'Checagem visual', gearbox: 'Câmbio' },\n gearbox: { automatic: 'Automático', manual: 'Manual' },\n hints: {\n gearbox: 'Automático troca sozinho. Manual: E sobe e Q desce a marcha (abaixo da 1ª vêm o neutro e a ré). M alterna dirigindo',\n vehicle: 'Veículo da frota que vai para a pista',\n test: 'Prova medida que o botão Rodar prova executa',\n camera: 'Sala: a câmera do jogador. Perseguição, cabine e capô seguem o veículo',\n time_scale: 'Quantas vezes mais rápido que o tempo real a prova roda',\n visual_check: 'O que você olhou e vai aprovar ou reprovar',\n },\n actions: { drive: 'Dirigir (entrar / sair)', run_test: 'Rodar prova', run_all: 'Rodar todas na pista', certify_now: 'Homologar agora (sem animação)', reverse_park: 'Dar ré (câmera de ré)', sign_ok: 'Aprovar checagem visual', sign_fail: 'Reprovar checagem visual', reset: 'Limpar ficha' },\n layers: { mirrors: 'Retrovisores', reverse_camera: 'Câmera de ré', scoreboard: 'Painel da ficha' },\n metrics: { gear: 'Marcha (-1 ré, 0 neutro)', rpm: 'Rotação', speed: 'Velocidade', time: 'Tempo da prova', value: 'Medição', passed: 'Aprovadas', failed: 'Reprovadas', pending: 'Pendentes', status: 'Situação (0 pend., 1 aprov., -1 reprov.)' },\n cameras: { room: 'Sala', chase: 'Perseguição (3ª pessoa)', cockpit: 'Cabine (1ª pessoa)', hood: 'Capô' },\n tests: {\n accel_0_100: '0 a 100 km/h',\n top_speed: 'Velocidade máxima',\n brake_100_0: 'Frenagem 100 a 0',\n turn_circle: 'Diâmetro de giro',\n wet_brake_80_0: 'Frenagem molhada 80 a 0',\n mud_traction: 'Tração na lama',\n cabin: 'Cabine e personagem',\n cameras: 'Câmeras',\n mirrors: 'Retrovisores e ré',\n terrain: 'Terrenos',\n wind_tunnel: 'Túnel de vento',\n crash_test: 'Crash test',\n pedestrian: 'Atropelamento',\n performance: 'Desempenho',\n buoyancy: 'Flutuação',\n flight: 'Voo',\n },\n status: { approved: 'APROVADO', rejected: 'REPROVADO', pending: 'PENDENTE' },\n verdict: { pass: 'ok', fail: 'falhou', pending: '…' },\n board: { title: 'Ficha de homologação', test: 'Prova', value: 'Medido', range: 'Faixa', verdict: 'Resultado', notRun: 'não rodada', running: 'rodando', gear: 'Marcha {0} · {1} rpm · {2} km/h' },\n log: { start: 'Prova {0}: {1}', result: '{0} · {1}: {2} {3} (faixa {4}) → {5}', signed: '{0} · {1}: {2} na sala', certified: '{0}: {1}', drive: 'Dirigindo {0}: I liga o motor, F sai do carro', leave: 'Saiu do volante', shift: 'Marcha {0} → {1} a {2} km/h' },\n cabin: {\n keys: 'W ou ↑ acelera · S ou ↓ freia (parado, dá ré) · A/D ou ←/→ vira · Espaço freio de mão · P puxa o freio de mão · I liga e desliga · M câmbio manual/automático · E sobe e Q desce marcha · G tração 4x2/4x4/4x4 automática · L luzes (posição, baixa) · K farol alto · N neblina · U luz interna · vírgula e ponto setas · B pisca-alerta · O limpador · J cinto · H buzina · Y alarme · R rádio · T rádio/fita · F sai do carro',\n on: 'ligado',\n off: 'desligado',\n ignition: 'Motor',\n gearbox: 'Câmbio',\n gear: 'Marcha',\n parkingBrake: 'Freio de mão',\n driveMode: 'Tração',\n modes: { '4x2': '4x2', '4x4': '4x4', auto: '4x4 automática' },\n lights: 'Luzes',\n lampModes: { off: 'apagadas', position: 'posição', low: 'farol baixo', high: 'farol alto' },\n fog: 'Neblina',\n interior: 'Luz interna',\n alarm: 'Alarme',\n alarmStates: { off: 'desligado', armed: 'armado', ringing: 'disparado' },\n radio: 'Som',\n sources: { radio: 'rádio', tape: 'toca-fitas' },\n indicator: 'Setas',\n indicators: { off: 'desligadas', left: 'esquerda', right: 'direita', hazard: 'pisca-alerta' },\n wipers: 'Limpador',\n wiperModes: { off: 'desligado', slow: 'lento', fast: 'rápido' },\n seatbelt: 'Cinto',\n refused: { no_four_wheel_drive: 'Este veículo não tem tração 4x4', no_fog_lamps: 'Este veículo não tem farol de neblina', ignition_off: 'Ligue o motor primeiro' },\n },\n },\n en: {\n name: 'Proving ground',\n controls: { vehicle: 'Vehicle', test: 'Test', camera: 'Camera', time_scale: 'Simulation speed', visual_check: 'Visual check', gearbox: 'Gearbox' },\n gearbox: { automatic: 'Automatic', manual: 'Manual' },\n hints: {\n gearbox: 'Automatic shifts by itself. Manual: E shifts up and Q down (below 1st come neutral and reverse). M switches while driving',\n vehicle: 'Fleet vehicle that goes on the track',\n test: 'Measured test the Run test button runs',\n camera: 'Room: the player camera. Chase, cockpit and hood follow the vehicle',\n time_scale: 'How many times faster than real time the test runs',\n visual_check: 'What you looked at and will approve or refuse',\n },\n actions: { drive: 'Drive (get in / out)', run_test: 'Run test', run_all: 'Run all on the track', certify_now: 'Certify now (no animation)', reverse_park: 'Reverse (reversing camera)', sign_ok: 'Approve visual check', sign_fail: 'Refuse visual check', reset: 'Clear certificate' },\n layers: { mirrors: 'Mirrors', reverse_camera: 'Reversing camera', scoreboard: 'Certificate board' },\n metrics: { gear: 'Gear (-1 reverse, 0 neutral)', rpm: 'Engine speed', speed: 'Speed', time: 'Test time', value: 'Measured', passed: 'Passed', failed: 'Failed', pending: 'Pending', status: 'Status (0 pending, 1 approved, -1 rejected)' },\n cameras: { room: 'Room', chase: 'Chase (third person)', cockpit: 'Cockpit (first person)', hood: 'Hood' },\n tests: {\n accel_0_100: '0 to 100 km/h',\n top_speed: 'Top speed',\n brake_100_0: 'Braking 100 to 0',\n turn_circle: 'Turning circle',\n wet_brake_80_0: 'Wet braking 80 to 0',\n mud_traction: 'Mud traction',\n cabin: 'Cabin and character',\n cameras: 'Cameras',\n mirrors: 'Mirrors and reversing',\n terrain: 'Terrain',\n wind_tunnel: 'Wind tunnel',\n crash_test: 'Crash test',\n pedestrian: 'Pedestrian impact',\n performance: 'Performance',\n buoyancy: 'Buoyancy',\n flight: 'Flight',\n },\n status: { approved: 'APPROVED', rejected: 'REJECTED', pending: 'PENDING' },\n verdict: { pass: 'ok', fail: 'failed', pending: '…' },\n board: { title: 'Certificate', test: 'Test', value: 'Measured', range: 'Range', verdict: 'Result', notRun: 'not run', running: 'running', gear: 'Gear {0} · {1} rpm · {2} km/h' },\n log: { start: 'Test {0}: {1}', result: '{0} · {1}: {2} {3} (range {4}) → {5}', signed: '{0} · {1}: {2} in the room', certified: '{0}: {1}', drive: 'Driving {0}: I starts the engine, F gets out', leave: 'Left the wheel', shift: 'Gear {0} → {1} at {2} km/h' },\n cabin: {\n keys: 'W or ↑ accelerates · S or ↓ brakes (stopped, reverses) · A/D or ←/→ steer · Space handbrake · P pulls the handbrake · I ignition · M manual/automatic gearbox · E shifts up, Q down · G drive 4x2/4x4/auto 4x4 · L lamps (position, low) · K high beam · N fog · U cabin light · comma and period indicators · B hazard · O wipers · J seat belt · H horn · Y alarm · R radio · T radio/tape · F gets out',\n on: 'on',\n off: 'off',\n ignition: 'Engine',\n gearbox: 'Gearbox',\n gear: 'Gear',\n parkingBrake: 'Handbrake',\n driveMode: 'Drive',\n modes: { '4x2': '4x2', '4x4': '4x4', auto: 'automatic 4x4' },\n lights: 'Lamps',\n lampModes: { off: 'off', position: 'position', low: 'low beam', high: 'high beam' },\n fog: 'Fog lamps',\n interior: 'Cabin light',\n alarm: 'Alarm',\n alarmStates: { off: 'off', armed: 'armed', ringing: 'ringing' },\n radio: 'Sound',\n sources: { radio: 'radio', tape: 'tape' },\n indicator: 'Indicators',\n indicators: { off: 'off', left: 'left', right: 'right', hazard: 'hazard' },\n wipers: 'Wipers',\n wiperModes: { off: 'off', slow: 'slow', fast: 'fast' },\n seatbelt: 'Seat belt',\n refused: { no_four_wheel_drive: 'This vehicle has no 4x4', no_fog_lamps: 'This vehicle has no fog lamps', ignition_off: 'Start the engine first' },\n },\n },\n}\n\nexport const fillText = (template: string, ...values: Array<string | number>): string => template.replace(/\\{(\\d+)\\}/g, (_, i) => String(values[Number(i)] ?? ''))\n"],"mappings":"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","names":["createVehicleDestructible","createArcadeDriver","createSemiSimDriver","createSurfaces","vehicleCorners","colorFromSeed","fleetDims","paintPalettes","paletteOf","markKitOrigin","geometry","markKitOrigin","clamp01","layers","count","createVehicleDestructible","createSurfaces","createArcadeDriver","createSemiSimDriver","vehicleCorners","fx","count","markKitOrigin","LIBRARY_BANK","createSemiSimDriver","subjectSpec","discardObject3D","createSemiSimDriver","createVehicleDestructible","discardObject3D","draw","a","createSemiSimDriver","createVehicleDestructible","pose","markKitOrigin","live","discardObject3D","createSemiSimDriver","subjectSpec","LIBRARY_BANK"]}