@adatechnology/game-vehicles-three 0.3.0 → 0.3.1
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.
- package/dist/index.global.js +80 -71
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/package.json +7 -7
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/build.ts","../src/lite.ts","../src/test-area/module.ts","../src/test-area/scenarios.ts","../src/test-area/text.ts","../src/test-area/types.ts"],"sourcesContent":["import type { Damageable, VehicleContext, VehicleKit } from '@adatechnology/game-vehicles'\nimport { colorFromSeed, fleetDims, paintPalettes, paletteOf } from '@adatechnology/game-vehicles-fleet'\nimport type { FleetDims } from '@adatechnology/game-vehicles-fleet'\n\nimport { fuse, liteMaterials, liteMeshes } from './lite'\n\nexport type VehicleQuality = 'high' | 'lite'\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: any\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 dispose(): void\n}\n\nexport interface VehiclesThree {\n readonly THREE: any\n readonly kit: VehicleKit\n build(key: string, options?: BuildVehicleOptions): BuiltVehicle\n}\n\nexport interface VehiclesThreeOptions {\n kit: VehicleKit\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: any): { triangles: number; drawCalls: number } {\n let triangles = 0\n let drawCalls = 0\n root.traverse((o: any) => {\n if (!o.isMesh || !o.geometry) return\n for (let p = 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: any): any {\n let best: any = null\n let bestCount = -1\n const counts = new Map<any, number>()\n c.vehicle.traverse((o: any) => {\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\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 */\nexport function createVehiclesThree(THREE: any, options: VehiclesThreeOptions): VehiclesThree {\n const kit = options.kit\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: any = 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((m: any) => {\n if (!m.isMesh || !m.geometry || m.userData.ghost) return\n for (let p = 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 const damageables = kit.damageables(c, pivotMatrix)\n let pruned = 0\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 if (color && primary) {\n const repainted = primary.clone()\n repainted.color.set(color)\n c.vehicle.traverse((m: any) => {\n if (!m.isMesh) return\n if (Array.isArray(m.material)) m.material = m.material.map((x: any) => (x === primary ? repainted : x))\n else if (m.material === primary) m.material = repainted\n })\n }\n markDamageables(c, damageables)\n group.updateMatrixWorld(true)\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 dispose() {\n group.traverse((m: any) => {\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: any, 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: any) => 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 */\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\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: any\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: any, mesh: any, c: any): 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 >= 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: any, cls: LiteClass, primary: any, paintColor: any, out: any): any {\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: any, environment: any): Record<LiteClass, any> {\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: any, c: any, pivot: any, paintColor: any, primary: any, hidden: ReadonlySet<any>): 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((o: any) => {\n if (!o.isMesh || o.isInstancedMesh || o.isSkinnedMesh || !o.geometry || !o.geometry.attributes.position) return\n for (let p = 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: any) => {\n const mat = mats[gr.materialIndex] || 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: any, fusion: LiteFusion, materials: Record<LiteClass, any>): any[] {\n const meshes: any[] = []\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\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 type { AnimationClipSpec, BenchChange, ModuleArea, ModuleControl, ModuleHost, ModuleLayer, ModuleMetric, ModuleScenario, TestableItem, TestableModule, Vec3 } from '@adatechnology/game-contracts'\nimport { buildVehicleItem, createVehicleDestructible, createVehicleKit } from '@adatechnology/game-vehicles'\nimport type { VehicleContext, VehicleItem, VehicleKit } from '@adatechnology/game-vehicles'\nimport { createArcadeDriver, createSemiSimDriver, createSurfaces, vehicleCorners } from '@adatechnology/game-vehicles-driving'\nimport { colorFromSeed, fleetDims, installFleet, paintPalettes, paletteOf } from '@adatechnology/game-vehicles-fleet'\n\nimport { createVehiclesThree, primaryPaint } from '../build'\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, VehiclesTestOptions } from './types'\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 }\nconst MATERIAL_COLOURS: Record<string, number> = { metal: 0xcccccc, glass: 0x44aaff, rubber: 0xff9900, fuel: 0xff3300 }\nconst ZONE_COLOURS: Record<string, number> = { door: 0x55dd55, hood: 0xdddd33, lid: 0xdd9933, bumper: 0xdd55dd, glass: 0x44aaff, light: 0xffffff, wheel: 0xff7733 }\n\ntype Three = any\ntype Placed = {\n readonly root: any\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?: any\n size?: { length: number; width: number; height: number }\n helpers: any[]\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 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' }\n const kits = new WeakMap<object, VehicleKit>()\n const placed = new Map<string, Placed>()\n let host: ModuleHost | null = null\n let three: Three = null\n let counter = 0\n let helpersShown = ''\n let axes: any[] = []\n let lane: Lane | null = null\n\n type Lane = { car: any; group: any; wall: any; 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 let engineLoop: { set(state: { volume?: number; frequency?: number; position?: Vec3 }): void; stop(): void } | undefined\n const stopEngine = (): void => {\n engineLoop?.stop()\n engineLoop = undefined\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, ...(options.document ? { document: options.document as never } : {}) })\n installFleet(kit)\n }\n kits.set(THREE, kit)\n }\n return kit\n }\n\n const paletteFor = (key: string) => (settings.palette === 'civil' ? paintPalettes.civil : settings.palette === 'military' ? paintPalettes.military : paletteOf(key))\n const paintOf = (entry: Placed): void => {\n if (!settings.paint) return\n const color = colorFromSeed(settings.seed + entry.index, paletteFor(entry.key))\n if (!entry.paint) {\n const vehicle = entry.item.vehicle as unknown as { vehicle: any }\n const primary = primaryPaint(entry.item.vehicle)\n if (!primary) return\n entry.paint = primary.clone()\n vehicle.vehicle.traverse((mesh: any) => {\n if (!mesh.isMesh) return\n if (Array.isArray(mesh.material)) mesh.material = mesh.material.map((m: any) => (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 })\n tapEffects(d)\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): any => {\n const m = new three.Matrix4().copy(entry.root.matrixWorld).invert()\n return m.multiply((entry.item.vehicle as unknown as { vehicle: any }).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 piece = new three.Box3()\n const matrix = new three.Matrix4()\n entry.root.traverse((mesh: any) => {\n if (!mesh.isMesh || !mesh.geometry || mesh.userData.ghost) return\n for (let p = 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 })\n const size = bounds.getSize(new three.Vector3())\n entry.size = { length: size.z, width: size.x, height: size.y }\n return entry.size\n }\n const clearHelpers = (): void => {\n for (const entry of placed.values()) {\n for (const helper of entry.helpers) helper.parent?.remove(helper)\n entry.helpers = []\n }\n for (const axis of axes) axis.parent?.remove(axis)\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: any, 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: any }[]) 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 any).add(arrow)\n axes.push(arrow)\n }\n }\n helpersShown = boxKey()\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 })\n const built = vehicles.build('compact_hatch', { quality: 'lite', 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 any\n scene.add(built.group, wall)\n const mode = settings.driving === 'semi' ? 'semi' : 'arcade'\n const surfaces = createSurfaces()\n const idle = { throttle: 0, brake: 0, steer: 0, handbrake: false }\n const state = { time: 0, exhaust: 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 engineLoop = audio()?.loop?.(soundIds.engine, { position: [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 if (state.ended) return\n state.time += dt\n const braking = gap() < brakeAt() && state.time > 0.5\n const input = { ...idle, throttle: braking ? 0 : 1, brake: braking ? 1 : 0, steer: 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 audio()?.play({ sound: soundIds.crash, position: [driver.state.x, 0.5, driver.state.z], volume: Math.min(1, e.speed / 15) })\n }\n } else {\n semi.step(input, dt, { ground: () => ({ surface: settings.surface }) })\n if (gap() <= 0) {\n state.ended = true\n log('crash', Math.abs((semi.state as { u: number }).u))\n audio()?.play({ sound: soundIds.crash, position: [driver.state.x, 0.5, driver.state.z], volume: Math.min(1, Math.abs((semi.state as { u: number }).u) / 15) })\n }\n }\n pose()\n {\n const speed = Math.abs(lane?.speed() ?? 0)\n // the game's engine (jogo L70421): level 0.035 + speed x 0.003, frequency 38 + speed x 7\n engineLoop?.set({ volume: state.ended ? 0 : 0.035 + speed * 0.003, frequency: 38 + speed * 7, position: [driver.state.x, 0.5, driver.state.z] })\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 > 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 default: break\n }\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 }\n if (host?.bench && boxKey() !== helpersShown && (host.bench.layer('damageables') || host.bench.layer('zones') || helpersShown !== '')) refreshLayers()\n lane?.step(dt)\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((mesh: any) => {\n if (!mesh.isMesh || mesh.userData.helper) return\n for (let p = 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 = 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 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 = 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) => (fleetDims(e.key)?.width ?? 2) <= WIDE), 0)\n const back = rowOf(entries.filter((e) => (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: '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\n const stopChange = lent.bench?.onChange(onChange)\n const stopFrame = lent.onFrame(frame)\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 return () => {\n stopChange?.()\n stopFrame()\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 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', string>\n hints: Record<'quality' | 'paint_by_seed' | 'palette' | 'driving' | 'surface', string>\n options: { quality: Record<string, string>; palette: Record<string, string>; driving: Record<string, string>; surface: 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', 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' },\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 },\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 },\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' },\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' },\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 },\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 },\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' },\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","import type { EffectSink, Vec3 } from '@adatechnology/game-contracts'\nimport type { VehicleKit } from '@adatechnology/game-vehicles'\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/** The sounds the module asks of `host.audio`, by id of the host's banks. `engine` is a loop (the game's saw through a 400 Hz low-pass), `horn` and `crash` one-shots. */\nexport type VehicleSoundIds = { readonly engine: string; readonly horn: string; readonly crash: string }\n\nexport const defaultSoundIds: VehicleSoundIds = { engine: 'engine_saw', horn: 'horn', crash: 'sfx_impact' }\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 /** `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 (`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 are the `game-audio` ones: `engine_saw`, `horn`, `sfx_impact`). */\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"],"mappings":"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","names":["createArcadeDriver","createSemiSimDriver","createSurfaces","vehicleCorners","colorFromSeed","fleetDims","paintPalettes","paletteOf","paintPalettes","paletteOf","colorFromSeed","createSurfaces","createArcadeDriver","createSemiSimDriver","vehicleCorners","count","fleetDims"]}
|
|
1
|
+
{"version":3,"sources":["../src/build.ts","../src/lite.ts","../src/test-area/module.ts","../src/test-area/scenarios.ts","../src/test-area/text.ts","../src/test-area/types.ts"],"sourcesContent":["import { markKitOrigin } from '@adatechnology/game-contracts'\nimport type { Damageable, VehicleContext, VehicleKit } from '@adatechnology/game-vehicles'\nimport { colorFromSeed, fleetDims, paintPalettes, paletteOf } from '@adatechnology/game-vehicles-fleet'\nimport type { FleetDims } from '@adatechnology/game-vehicles-fleet'\n\nimport { fuse, liteMaterials, liteMeshes } from './lite'\n\nexport type VehicleQuality = 'high' | 'lite'\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: any\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 dispose(): void\n}\n\nexport interface VehiclesThree {\n readonly THREE: any\n readonly kit: VehicleKit\n build(key: string, options?: BuildVehicleOptions): BuiltVehicle\n}\n\nexport interface VehiclesThreeOptions {\n kit: VehicleKit\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: any): { triangles: number; drawCalls: number } {\n let triangles = 0\n let drawCalls = 0\n root.traverse((o: any) => {\n if (!o.isMesh || !o.geometry) return\n for (let p = 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: any): any {\n let best: any = null\n let bestCount = -1\n const counts = new Map<any, number>()\n c.vehicle.traverse((o: any) => {\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\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 */\nexport function createVehiclesThree(THREE: any, options: VehiclesThreeOptions): VehiclesThree {\n const kit = options.kit\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: any = 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((m: any) => {\n if (!m.isMesh || !m.geometry || m.userData.ghost) return\n for (let p = 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 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 if (color && primary) {\n const repainted = primary.clone()\n repainted.color.set(color)\n c.vehicle.traverse((m: any) => {\n if (!m.isMesh) return\n if (Array.isArray(m.material)) m.material = m.material.map((x: any) => (x === primary ? repainted : x))\n else if (m.material === primary) m.material = repainted\n })\n }\n markDamageables(c, damageables)\n group.updateMatrixWorld(true)\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 dispose() {\n group.traverse((m: any) => {\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: any, 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: any) => 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 */\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\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: any\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: any, mesh: any, c: any): 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 >= 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: any, cls: LiteClass, primary: any, paintColor: any, out: any): any {\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: any, environment: any): Record<LiteClass, any> {\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: any, c: any, pivot: any, paintColor: any, primary: any, hidden: ReadonlySet<any>): 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((o: any) => {\n if (!o.isMesh || o.isInstancedMesh || o.isSkinnedMesh || !o.geometry || !o.geometry.attributes.position) return\n for (let p = 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: any) => {\n const mat = mats[gr.materialIndex] || 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: any, fusion: LiteFusion, materials: Record<LiteClass, any>): any[] {\n const meshes: any[] = []\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\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 type { AnimationClipSpec, BenchChange, ModuleArea, ModuleControl, ModuleHost, ModuleLayer, ModuleMetric, ModuleScenario, TestableItem, TestableModule, Vec3 } from '@adatechnology/game-contracts'\nimport { buildVehicleItem, createVehicleDestructible, createVehicleKit } from '@adatechnology/game-vehicles'\nimport type { VehicleContext, VehicleItem, VehicleKit } from '@adatechnology/game-vehicles'\nimport { createArcadeDriver, createSemiSimDriver, createSurfaces, vehicleCorners } from '@adatechnology/game-vehicles-driving'\nimport { colorFromSeed, fleetDims, installFleet, paintPalettes, paletteOf } from '@adatechnology/game-vehicles-fleet'\n\nimport { createVehiclesThree, primaryPaint } from '../build'\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, VehiclesTestOptions } from './types'\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 }\nconst MATERIAL_COLOURS: Record<string, number> = { metal: 0xcccccc, glass: 0x44aaff, rubber: 0xff9900, fuel: 0xff3300 }\nconst ZONE_COLOURS: Record<string, number> = { door: 0x55dd55, hood: 0xdddd33, lid: 0xdd9933, bumper: 0xdd55dd, glass: 0x44aaff, light: 0xffffff, wheel: 0xff7733 }\n\ntype Three = any\ntype Placed = {\n readonly root: any\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?: any\n size?: { length: number; width: number; height: number }\n helpers: any[]\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 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' }\n const kits = new WeakMap<object, VehicleKit>()\n const placed = new Map<string, Placed>()\n let host: ModuleHost | null = null\n let three: Three = null\n let counter = 0\n let helpersShown = ''\n let axes: any[] = []\n let lane: Lane | null = null\n\n type Lane = { car: any; group: any; wall: any; 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 let engineLoop: { set(state: { volume?: number; frequency?: number; position?: Vec3 }): void; stop(): void } | undefined\n const stopEngine = (): void => {\n engineLoop?.stop()\n engineLoop = undefined\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, ...(options.document ? { document: options.document as never } : {}) })\n installFleet(kit)\n }\n kits.set(THREE, kit)\n }\n return kit\n }\n\n const paletteFor = (key: string) => (settings.palette === 'civil' ? paintPalettes.civil : settings.palette === 'military' ? paintPalettes.military : paletteOf(key))\n const paintOf = (entry: Placed): void => {\n if (!settings.paint) return\n const color = colorFromSeed(settings.seed + entry.index, paletteFor(entry.key))\n if (!entry.paint) {\n const vehicle = entry.item.vehicle as unknown as { vehicle: any }\n const primary = primaryPaint(entry.item.vehicle)\n if (!primary) return\n entry.paint = primary.clone()\n vehicle.vehicle.traverse((mesh: any) => {\n if (!mesh.isMesh) return\n if (Array.isArray(mesh.material)) mesh.material = mesh.material.map((m: any) => (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 })\n tapEffects(d)\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): any => {\n const m = new three.Matrix4().copy(entry.root.matrixWorld).invert()\n return m.multiply((entry.item.vehicle as unknown as { vehicle: any }).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 piece = new three.Box3()\n const matrix = new three.Matrix4()\n entry.root.traverse((mesh: any) => {\n if (!mesh.isMesh || !mesh.geometry || mesh.userData.ghost) return\n for (let p = 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 })\n const size = bounds.getSize(new three.Vector3())\n entry.size = { length: size.z, width: size.x, height: size.y }\n return entry.size\n }\n const clearHelpers = (): void => {\n for (const entry of placed.values()) {\n for (const helper of entry.helpers) helper.parent?.remove(helper)\n entry.helpers = []\n }\n for (const axis of axes) axis.parent?.remove(axis)\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: any, 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: any }[]) 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 any).add(arrow)\n axes.push(arrow)\n }\n }\n helpersShown = boxKey()\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 })\n const built = vehicles.build('compact_hatch', { quality: 'lite', 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 any\n scene.add(built.group, wall)\n const mode = settings.driving === 'semi' ? 'semi' : 'arcade'\n const surfaces = createSurfaces()\n const idle = { throttle: 0, brake: 0, steer: 0, handbrake: false }\n const state = { time: 0, exhaust: 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 engineLoop = audio()?.loop?.(soundIds.engine, { position: [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 if (state.ended) return\n state.time += dt\n const braking = gap() < brakeAt() && state.time > 0.5\n const input = { ...idle, throttle: braking ? 0 : 1, brake: braking ? 1 : 0, steer: 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 audio()?.play({ sound: soundIds.crash, position: [driver.state.x, 0.5, driver.state.z], volume: Math.min(1, e.speed / 15) })\n }\n } else {\n semi.step(input, dt, { ground: () => ({ surface: settings.surface }) })\n if (gap() <= 0) {\n state.ended = true\n log('crash', Math.abs((semi.state as { u: number }).u))\n audio()?.play({ sound: soundIds.crash, position: [driver.state.x, 0.5, driver.state.z], volume: Math.min(1, Math.abs((semi.state as { u: number }).u) / 15) })\n }\n }\n pose()\n {\n const speed = Math.abs(lane?.speed() ?? 0)\n // the game's engine (jogo L70421): level 0.035 + speed x 0.003, frequency 38 + speed x 7\n engineLoop?.set({ volume: state.ended ? 0 : 0.035 + speed * 0.003, frequency: 38 + speed * 7, position: [driver.state.x, 0.5, driver.state.z] })\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 > 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 default: break\n }\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 }\n if (host?.bench && boxKey() !== helpersShown && (host.bench.layer('damageables') || host.bench.layer('zones') || helpersShown !== '')) refreshLayers()\n lane?.step(dt)\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((mesh: any) => {\n if (!mesh.isMesh || mesh.userData.helper) return\n for (let p = 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 = 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 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 = 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) => (fleetDims(e.key)?.width ?? 2) <= WIDE), 0)\n const back = rowOf(entries.filter((e) => (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: '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\n const stopChange = lent.bench?.onChange(onChange)\n const stopFrame = lent.onFrame(frame)\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 return () => {\n stopChange?.()\n stopFrame()\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 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', string>\n hints: Record<'quality' | 'paint_by_seed' | 'palette' | 'driving' | 'surface', string>\n options: { quality: Record<string, string>; palette: Record<string, string>; driving: Record<string, string>; surface: 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', 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' },\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 },\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 },\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' },\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' },\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 },\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 },\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' },\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","import type { EffectSink, Vec3 } from '@adatechnology/game-contracts'\nimport type { VehicleKit } from '@adatechnology/game-vehicles'\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/** The sounds the module asks of `host.audio`, by id of the host's banks. `engine` is a loop (the game's saw through a 400 Hz low-pass), `horn` and `crash` one-shots. */\nexport type VehicleSoundIds = { readonly engine: string; readonly horn: string; readonly crash: string }\n\nexport const defaultSoundIds: VehicleSoundIds = { engine: 'engine_saw', horn: 'horn', crash: 'sfx_impact' }\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 /** `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 (`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 are the `game-audio` ones: `engine_saw`, `horn`, `sfx_impact`). */\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"],"mappings":"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","names":["createArcadeDriver","createSemiSimDriver","createSurfaces","vehicleCorners","colorFromSeed","fleetDims","paintPalettes","paletteOf","paintPalettes","paletteOf","colorFromSeed","createSurfaces","createArcadeDriver","createSemiSimDriver","vehicleCorners","count","fleetDims"]}
|