@adatechnology/game-destruction 0.19.0 → 0.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/chain.ts","../src/math.ts","../src/fracture.ts","../src/breach.ts","../src/layers.ts","../src/rebar.ts","../src/flexure.ts","../src/data/soils.json","../src/soil.ts","../src/data/wind-terrain.json","../src/wind.ts","../src/data/materials.json","../src/data/material-hints.json","../src/materials.ts","../../game-contracts/src/blast-shove.ts","../../game-contracts/src/blast-impulse.ts","../../game-contracts/src/blast-knock.ts","../../game-contracts/src/impact-cost.ts","../../game-contracts/src/impact.ts","../../game-contracts/src/body.ts","../../game-contracts/src/spec.ts","../../game-contracts/src/weapons.ts","../../game-contracts/src/ignition.ts","../../game-contracts/src/seal.ts","../../game-contracts/src/hands.ts","../../game-contracts/src/twist.ts","../../game-contracts/src/animation.ts","../../game-contracts/src/tool-animation.ts","../../game-contracts/src/frame.ts","../../game-contracts/src/warn.ts","../../game-contracts/src/registry.ts","../../game-contracts/src/bench.ts","../../game-contracts/src/environment.ts","../../game-contracts/src/categories.ts","../../game-contracts/src/origin.ts","../../game-contracts/src/footprint.ts","../../game-contracts/src/foley.ts","../../game-contracts/src/index.ts","../src/world.ts","../src/data/assemblies.json","../src/assemblies.ts","../src/frame.ts","../src/size.ts","../src/locale.ts","../src/contracts.ts"],"sourcesContent":["export type * from './types'\nexport { createDestruction, SHELTER_DEFAULTS, FRAGMENT_HIT_DEFAULTS, CONFINEMENT_DEFAULTS } from './world'\nexport { explosivePart, FIRE_PRIME_C } from './chain'\nexport type { ChainTrigger, ExplosivePartOptions, WorldExplosive } from './chain'\nexport { MATERIALS, JOINT_DEFAULTS, JOINT_BY_MATERIALS, inferJoints, guessMaterial, partVolume, partMass, partThickness, partCapacity, fragility } from './materials'\nexport { ASSEMBLIES, createAssemblies, defaultAssemblies, registerAssembly, getAssembly, assemblyPart, assemblyDepth } from './assemblies'\nexport type { Assemblies, AssembliesOptions, AssemblyDef, AssemblyPartOptions } from './assemblies'\nexport { buildFrame } from './frame'\nexport type { FrameOptions } from './frame'\nexport { sizeStructure, sizeRebar } from './size'\nexport {\n GRAVITY, FLEXURE_DEFAULTS, MASONRY_DEFAULTS, bearingWallThickness, bendGeometry, blastImpulse, crackingMoment, elasticEnergy, impulseEnergy, momentOfEnergy,\n sectionMoments, slendernessFactor, spanMoment, spanOf, steelMoment, tensionSteel,\n} from './flexure'\nexport type { BearingWallOptions, BendGeometry, BendSection, SectionMoments, TensionSteel } from './flexure'\nexport {\n SOILS, SOIL_DEFAULTS, footingArea, footingSoil, layersBetween, pileCapacity, pileLength, pileStiffness, profileOf, soilAt, solveFoundation, stiffnessCentre,\n subgradeModulus,\n} from './soil'\nexport type { FoundationSolve, SoilSpring } from './soil'\nexport { vec, quat, quatFromEuler, rotateVec, toLocal, toWorld } from './math'\nexport { resolveStrings, locales } from './locale'\nexport type { DestructionStrings, DestructionLocale } from './locale'\nexport { checkDestructible, checkHit, IMPACT_CONTRACT } from './contracts'\nexport type { DestructibleImpl, ImpactContract, CheckOptions } from './contracts'\nexport {\n WIND_DEFAULTS, WIND_TERRAIN, analyzeWind, damperAmplification, damperTuning, exposureOf, gustAt, heightFactor, makeGust, meanHeightFactor, momentNodes, resolveWind, shapeAt, shearNodes,\n solveWallFrame, stepSway, tBeamInertia, tensionCapacity, turbulenceIntensity, windClass, windPressure,\n} from './wind'\nexport type { Gust, ResolvedWind, SwayState, SwaySystem, WallFrameSolution, WindAnalysis, WindCase, WindPartInput } from './wind'\n","import type { ChainDelay, ExplosionChain, PartSpec } from './types'\n\n/** What can set an explosive part off from outside, in the order a hit can carry it. */\nexport type ChainTrigger = 'shot' | 'fire' | 'explosion'\n\n/** Temperature in °C that primes a part with `chain.fire` when its `explodes.atC` is not set. */\nexport const FIRE_PRIME_C = 300\n\n/** Seconds from a trigger to the blast: a number is fixed, `[min, max]` is drawn from the world seed (one draw). */\nexport const drawChainDelay = (delay: ChainDelay, random: () => number): number => {\n if (typeof delay === 'number') return delay\n const [min, max] = delay\n return min + random() * (max - min)\n}\n\n/** The delay `spec` gives for `trigger`, or undefined when the part does not answer to it. */\nexport const chainDelayOf = (spec: PartSpec, trigger: ChainTrigger): ChainDelay | undefined => spec.explodes?.chain?.[trigger]\n\n/** Fraction of the hit points a shot must have taken off before it primes the part. */\nexport const shotDamageFractionOf = (spec: PartSpec): number => spec.explodes?.chain?.shotDamageFraction ?? 0\n\n/** The numbers of an explosive that sits in the world, as `game-weapons` gives them (`ExplosiveDef` fits). */\nexport interface WorldExplosive {\n readonly energy: number\n /** Metres within which the blast reaches other parts (and primes theirs). */\n readonly injuryRadius: number\n readonly chain?: ExplosionChain\n}\n\nexport interface ExplosivePartOptions {\n /** Temperature in °C at which fire primes (or sets off) the part; default `FIRE_PRIME_C` when the explosive answers to fire. */\n readonly atC?: number\n}\n\n/**\n * A part that explodes with the energy and reach of `explosive` and answers to what `explosive.chain` says: a bullet, fire or a blast\n * nearby primes it and it goes off after the delay. `part` is everything else about the part (shape, material, position, fluid inside).\n */\nexport const explosivePart = (explosive: WorldExplosive, part: Omit<PartSpec, 'explodes'>, options: ExplosivePartOptions = {}): PartSpec => ({\n ...part,\n explodes: {\n energy: explosive.energy,\n radius: explosive.injuryRadius,\n ...(options.atC !== undefined ? { atC: options.atC } : {}),\n ...(explosive.chain ? { chain: { ...explosive.chain } } : {}),\n },\n})\n","import type { PartShape, Quat, Vec3 } from './types'\n\nconst EPS = 1e-9\n\n/** Small vector helpers (arrays of three numbers). Pure functions; they allocate a new array. */\nexport const vec = {\n add: (a: Vec3, b: Vec3): Vec3 => [a[0] + b[0], a[1] + b[1], a[2] + b[2]],\n sub: (a: Vec3, b: Vec3): Vec3 => [a[0] - b[0], a[1] - b[1], a[2] - b[2]],\n scale: (a: Vec3, s: number): Vec3 => [a[0] * s, a[1] * s, a[2] * s],\n dot: (a: Vec3, b: Vec3): number => a[0] * b[0] + a[1] * b[1] + a[2] * b[2],\n cross: (a: Vec3, b: Vec3): Vec3 => [a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0]],\n length: (a: Vec3): number => Math.sqrt(a[0] * a[0] + a[1] * a[1] + a[2] * a[2]),\n distance: (a: Vec3, b: Vec3): number => Math.hypot(a[0] - b[0], a[1] - b[1], a[2] - b[2]),\n normalize: (a: Vec3, fallback: Vec3 = [0, 1, 0]): Vec3 => {\n const l = Math.sqrt(a[0] * a[0] + a[1] * a[1] + a[2] * a[2])\n return l < EPS ? [fallback[0], fallback[1], fallback[2]] : [a[0] / l, a[1] / l, a[2] / l]\n },\n lerp: (a: Vec3, b: Vec3, t: number): Vec3 => [a[0] + (b[0] - a[0]) * t, a[1] + (b[1] - a[1]) * t, a[2] + (b[2] - a[2]) * t],\n /** `a + b * s` */\n madd: (a: Vec3, b: Vec3, s: number): Vec3 => [a[0] + b[0] * s, a[1] + b[1] * s, a[2] + b[2] * s],\n}\n\nconst IDENTITY: Quat = [0, 0, 0, 1]\n\n/** Quaternion helpers (`[x, y, z, w]`). */\nexport const quat = {\n identity: (): Quat => [IDENTITY[0], IDENTITY[1], IDENTITY[2], IDENTITY[3]],\n /** Hamilton product `a * b` (apply `b` first, then `a`). */\n mul: (a: Quat, b: Quat): Quat => [\n a[3] * b[0] + a[0] * b[3] + a[1] * b[2] - a[2] * b[1],\n a[3] * b[1] - a[0] * b[2] + a[1] * b[3] + a[2] * b[0],\n a[3] * b[2] + a[0] * b[1] - a[1] * b[0] + a[2] * b[3],\n a[3] * b[3] - a[0] * b[0] - a[1] * b[1] - a[2] * b[2],\n ],\n conjugate: (q: Quat): Quat => [-q[0], -q[1], -q[2], q[3]],\n normalize: (q: Quat): Quat => {\n const l = Math.hypot(q[0], q[1], q[2], q[3])\n return l < EPS ? [0, 0, 0, 1] : [q[0] / l, q[1] / l, q[2] / l, q[3] / l]\n },\n /** Rotation of `angle` radians around a unit `axis`. */\n fromAxisAngle: (axis: Vec3, angle: number): Quat => {\n const s = Math.sin(angle / 2)\n return [axis[0] * s, axis[1] * s, axis[2] * s, Math.cos(angle / 2)]\n },\n /** Rotation matrix, row-major 3x3. */\n toMatrix: (q: Quat): number[] => {\n const [x, y, z, w] = q\n const xx = x * x, yy = y * y, zz = z * z, xy = x * y, xz = x * z, yz = y * z, wx = w * x, wy = w * y, wz = w * z\n return [1 - 2 * (yy + zz), 2 * (xy - wz), 2 * (xz + wy), 2 * (xy + wz), 1 - 2 * (xx + zz), 2 * (yz - wx), 2 * (xz - wy), 2 * (yz + wx), 1 - 2 * (xx + yy)]\n },\n /** Quaternion from three orthonormal columns (the images of the x, y and z axes). */\n fromColumns: (cx: Vec3, cy: Vec3, cz: Vec3): Quat => {\n const m00 = cx[0], m10 = cx[1], m20 = cx[2]\n const m01 = cy[0], m11 = cy[1], m21 = cy[2]\n const m02 = cz[0], m12 = cz[1], m22 = cz[2]\n const tr = m00 + m11 + m22\n let q: Quat\n if (tr > 0) {\n const s = Math.sqrt(tr + 1) * 2\n q = [(m21 - m12) / s, (m02 - m20) / s, (m10 - m01) / s, 0.25 * s]\n } else if (m00 > m11 && m00 > m22) {\n const s = Math.sqrt(1 + m00 - m11 - m22) * 2\n q = [0.25 * s, (m01 + m10) / s, (m02 + m20) / s, (m21 - m12) / s]\n } else if (m11 > m22) {\n const s = Math.sqrt(1 + m11 - m00 - m22) * 2\n q = [(m01 + m10) / s, 0.25 * s, (m12 + m21) / s, (m02 - m20) / s]\n } else {\n const s = Math.sqrt(1 + m22 - m00 - m11) * 2\n q = [(m02 + m20) / s, (m12 + m21) / s, 0.25 * s, (m10 - m01) / s]\n }\n return quat.normalize(q)\n },\n}\n\n/** Quaternion from Euler angles in radians, order XYZ (the three.js default). */\nexport const quatFromEuler = (x: number, y: number, z: number): Quat => {\n const c1 = Math.cos(x / 2), c2 = Math.cos(y / 2), c3 = Math.cos(z / 2)\n const s1 = Math.sin(x / 2), s2 = Math.sin(y / 2), s3 = Math.sin(z / 2)\n return [s1 * c2 * c3 + c1 * s2 * s3, c1 * s2 * c3 - s1 * c2 * s3, c1 * c2 * s3 + s1 * s2 * c3, c1 * c2 * c3 - s1 * s2 * s3]\n}\n\n/** Rotate a vector by a quaternion. */\nexport const rotateVec = (q: Quat, v: Vec3): Vec3 => {\n const qx = q[0], qy = q[1], qz = q[2], qw = q[3]\n const tx = 2 * (qy * v[2] - qz * v[1])\n const ty = 2 * (qz * v[0] - qx * v[2])\n const tz = 2 * (qx * v[1] - qy * v[0])\n return [v[0] + qw * tx + (qy * tz - qz * ty), v[1] + qw * ty + (qz * tx - qx * tz), v[2] + qw * tz + (qx * ty - qy * tx)]\n}\n\n/** World point to the local space of a transform (`position`, `rotation`). */\nexport const toLocal = (position: Vec3, rotation: Quat, p: Vec3): Vec3 =>\n rotateVec([-rotation[0], -rotation[1], -rotation[2], rotation[3]], [p[0] - position[0], p[1] - position[1], p[2] - position[2]])\n\n/** Local point of a transform (`position`, `rotation`) to world space. */\nexport const toWorld = (position: Vec3, rotation: Quat, p: Vec3): Vec3 => {\n const r = rotateVec(rotation, p)\n return [r[0] + position[0], r[1] + position[1], r[2] + position[2]]\n}\n\n// ---------------------------------------------------------------------------------------------------------------------------------------------\n// Shapes (part space: centred on the origin, cylinders along +Y)\n// ---------------------------------------------------------------------------------------------------------------------------------------------\n\n/** Dimensions of the bounding box of a shape, in the shape's own axes. */\nexport const shapeDims = (s: PartShape): Vec3 => {\n if (s.kind === 'box') return [s.size[0], s.size[1], s.size[2]]\n if (s.kind === 'cylinder') return [s.radius * 2, s.height, s.radius * 2]\n return [s.radius * 2, s.radius * 2, s.radius * 2]\n}\n\n/** Radius of the sphere that encloses the shape. */\nexport const shapeBound = (s: PartShape): number => {\n if (s.kind === 'box') return 0.5 * Math.hypot(s.size[0], s.size[1], s.size[2])\n if (s.kind === 'cylinder') return Math.hypot(s.radius, s.height / 2)\n return s.radius\n}\n\nexport const shapeArea = (s: PartShape): number => {\n if (s.kind === 'box') return 2 * (s.size[0] * s.size[1] + s.size[1] * s.size[2] + s.size[0] * s.size[2])\n if (s.kind === 'cylinder') return 2 * Math.PI * s.radius * s.height + 2 * Math.PI * s.radius * s.radius\n return 4 * Math.PI * s.radius * s.radius\n}\n\nexport interface ShapeRay {\n /** Entry distance along the ray (negative when the origin is inside). */\n t0: number\n /** Normal at the entry, outward. */\n n0: Vec3\n /** Exit distance. */\n t1: number\n /** Normal at the exit, outward. */\n n1: Vec3\n}\n\n/** Exact ray intersection with a shape in part space. `d` need not be normalised but must be non-zero. */\nexport const rayShape = (s: PartShape, o: Vec3, d: Vec3): ShapeRay | null => {\n if (s.kind === 'box') {\n let tmin = -Infinity, tmax = Infinity\n let a0 = 0, a1 = 0, s0 = 1, s1 = 1\n for (let i = 0; i < 3; i++) {\n const h = s.size[i] / 2\n if (Math.abs(d[i]) < EPS) {\n if (Math.abs(o[i]) > h) return null\n continue\n }\n let ta = (-h - o[i]) / d[i]\n let tb = (h - o[i]) / d[i]\n let sa = -1, sb = 1\n if (ta > tb) {\n const t = ta\n ta = tb\n tb = t\n sa = 1\n sb = -1\n }\n if (ta > tmin) {\n tmin = ta\n a0 = i\n s0 = sa\n }\n if (tb < tmax) {\n tmax = tb\n a1 = i\n s1 = sb\n }\n if (tmin > tmax) return null\n }\n if (tmax < 0 || !Number.isFinite(tmin) || !Number.isFinite(tmax)) return null\n const n0: Vec3 = [0, 0, 0]\n const n1: Vec3 = [0, 0, 0]\n n0[a0] = s0\n n1[a1] = s1\n return { t0: tmin, n0, t1: tmax, n1 }\n }\n if (s.kind === 'sphere') {\n const b = vec.dot(o, d)\n const a = vec.dot(d, d)\n const c = vec.dot(o, o) - s.radius * s.radius\n const disc = b * b - a * c\n if (disc < 0) return null\n const sq = Math.sqrt(disc)\n const t0 = (-b - sq) / a\n const t1 = (-b + sq) / a\n if (t1 < 0) return null\n const p0 = vec.madd(o, d, t0)\n const p1 = vec.madd(o, d, t1)\n return { t0, n0: vec.normalize(p0), t1, n1: vec.normalize(p1) }\n }\n // cylinder along Y: intersection of the infinite cylinder interval and the y slab\n const r = s.radius\n const hh = s.height / 2\n const a = d[0] * d[0] + d[2] * d[2]\n const c = o[0] * o[0] + o[2] * o[2] - r * r\n let tA = -Infinity, tB = Infinity\n if (a > EPS) {\n const b = o[0] * d[0] + o[2] * d[2]\n const disc = b * b - a * c\n if (disc < 0) return null\n const sq = Math.sqrt(disc)\n tA = (-b - sq) / a\n tB = (-b + sq) / a\n } else if (c > 0) return null\n let yA = -Infinity, yB = Infinity\n if (Math.abs(d[1]) > EPS) {\n yA = (-hh - o[1]) / d[1]\n yB = (hh - o[1]) / d[1]\n if (yA > yB) {\n const t = yA\n yA = yB\n yB = t\n }\n } else if (Math.abs(o[1]) > hh) return null\n const t0 = Math.max(tA, yA)\n const t1 = Math.min(tB, yB)\n if (t0 > t1 || t1 < 0 || !Number.isFinite(t0) || !Number.isFinite(t1)) return null\n const normalAt = (t: number, fromSide: boolean, sign: number): Vec3 => {\n if (fromSide) {\n const p = vec.madd(o, d, t)\n return vec.normalize([p[0], 0, p[2]], [1, 0, 0])\n }\n return [0, sign, 0]\n }\n const n0 = normalAt(t0, tA >= yA, d[1] > 0 ? -1 : 1)\n const n1 = normalAt(t1, tB <= yB, d[1] > 0 ? 1 : -1)\n return { t0, n0, t1, n1 }\n}\n\n/** Distance from a part-space point to the shape (0 inside). */\nexport const distanceToShape = (s: PartShape, p: Vec3): number => {\n if (s.kind === 'box') {\n const dx = Math.max(Math.abs(p[0]) - s.size[0] / 2, 0)\n const dy = Math.max(Math.abs(p[1]) - s.size[1] / 2, 0)\n const dz = Math.max(Math.abs(p[2]) - s.size[2] / 2, 0)\n return Math.hypot(dx, dy, dz)\n }\n if (s.kind === 'sphere') return Math.max(0, vec.length(p) - s.radius)\n const dr = Math.max(0, Math.hypot(p[0], p[2]) - s.radius)\n const dy = Math.max(0, Math.abs(p[1]) - s.height / 2)\n return Math.hypot(dr, dy)\n}\n\n/** Nearest point on the surface of a shape to a part-space point, with the outward normal. */\nexport const surfacePoint = (s: PartShape, p: Vec3): { point: Vec3; normal: Vec3 } => {\n if (s.kind === 'box') {\n const h: Vec3 = [s.size[0] / 2, s.size[1] / 2, s.size[2] / 2]\n const inside = Math.abs(p[0]) <= h[0] && Math.abs(p[1]) <= h[1] && Math.abs(p[2]) <= h[2]\n if (!inside) {\n const c: Vec3 = [Math.max(-h[0], Math.min(h[0], p[0])), Math.max(-h[1], Math.min(h[1], p[1])), Math.max(-h[2], Math.min(h[2], p[2]))]\n return { point: c, normal: vec.normalize(vec.sub(p, c)) }\n }\n let axis = 0\n let best = Infinity\n for (let i = 0; i < 3; i++) {\n const g = h[i] - Math.abs(p[i])\n if (g < best) {\n best = g\n axis = i\n }\n }\n const sign = p[axis] >= 0 ? 1 : -1\n const point: Vec3 = [p[0], p[1], p[2]]\n point[axis] = sign * h[axis]\n const normal: Vec3 = [0, 0, 0]\n normal[axis] = sign\n return { point, normal }\n }\n if (s.kind === 'sphere') {\n const n = vec.normalize(p)\n return { point: vec.scale(n, s.radius), normal: n }\n }\n const rho = Math.hypot(p[0], p[2])\n const hh = s.height / 2\n const inside = rho <= s.radius && Math.abs(p[1]) <= hh\n if (!inside) {\n const k = rho > s.radius ? s.radius / rho : 1\n const c: Vec3 = [p[0] * k, Math.max(-hh, Math.min(hh, p[1])), p[2] * k]\n return { point: c, normal: vec.normalize(vec.sub(p, c)) }\n }\n if (s.radius - rho < hh - Math.abs(p[1])) {\n const k = rho < EPS ? 0 : s.radius / rho\n const point: Vec3 = rho < EPS ? [s.radius, p[1], 0] : [p[0] * k, p[1], p[2] * k]\n return { point, normal: vec.normalize([point[0], 0, point[2]], [1, 0, 0]) }\n }\n const sign = p[1] >= 0 ? 1 : -1\n return { point: [p[0], sign * hh, p[2]], normal: [0, sign, 0] }\n}\n\n/** Axis-aligned bounds of a shape with a given centre and orientation. */\nexport const aabbOf = (s: PartShape, center: Vec3, q: Quat): { min: Vec3; max: Vec3 } => {\n let hx: number, hy: number, hz: number\n if (s.kind === 'sphere') {\n hx = hy = hz = s.radius\n } else {\n const m = quat.toMatrix(q)\n if (s.kind === 'box') {\n const a = s.size[0] / 2, b = s.size[1] / 2, c = s.size[2] / 2\n hx = Math.abs(m[0]) * a + Math.abs(m[1]) * b + Math.abs(m[2]) * c\n hy = Math.abs(m[3]) * a + Math.abs(m[4]) * b + Math.abs(m[5]) * c\n hz = Math.abs(m[6]) * a + Math.abs(m[7]) * b + Math.abs(m[8]) * c\n } else {\n const ax = [m[1], m[4], m[7]]\n const hh = s.height / 2\n const e = (i: number) => s.radius * Math.sqrt(Math.max(0, 1 - ax[i] * ax[i])) + hh * Math.abs(ax[i])\n hx = e(0)\n hy = e(1)\n hz = e(2)\n }\n }\n return { min: [center[0] - hx, center[1] - hy, center[2] - hz], max: [center[0] + hx, center[1] + hy, center[2] + hz] }\n}\n\n/** Seeded generator (mulberry32). The state is a single int32, so it round-trips through JSON. */\nexport interface Rng {\n next(): number\n state(): number\n set(state: number): void\n}\n\nexport const createRng = (seed: number): Rng => {\n let s = seed | 0\n return {\n next() {\n s = (s + 0x6d2b79f5) | 0\n let t = Math.imul(s ^ (s >>> 15), 1 | s)\n t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296\n },\n state: () => s,\n set(v) {\n s = v | 0\n },\n }\n}\n","import { quat } from './math'\nimport type { Fragment, FractureStyle, Quat, SplitForm, Vec3 } from './types'\n\n/** A fragment in the part's local space (centre, size in the fragment's own axes, orientation relative to the part). */\nexport interface PlannedFragment {\n center: Vec3\n size: Vec3\n q: Quat\n shape: Fragment['shape']\n /** Share of the part's mass (unnormalised). */\n weight: number\n /** Cut from inside a stack of sheets (a page of a book), not from its cover. */\n inner?: boolean\n}\n\nexport interface PlanInput {\n style: FractureStyle\n /** Bounding box dimensions in part axes. */\n dims: Vec3\n thickness: number\n /** Index 0..2 of the grain axis, if any. */\n grain?: number\n /** Impact point in part space. */\n hit: Vec3\n fragmentSize: [number, number]\n maxFragments: number\n rnd: () => number\n /** Thickness of one sheet of the material (`MaterialDef.sheet`): a `tear` part thicker than a few sheets comes apart as loose sheets. */\n sheet?: number\n /**\n * The part broke across at this point of its long axis (part space), not everywhere at once (`sever`): two stubs either side of a band `gap`\n * wide that comes apart in splinters. Used by `splinter` (a board, a batten, a beam).\n */\n cut?: { at: number; gap: number }\n /** How the wood-based material comes apart (`MaterialDef.splitForm`): slivers of many sizes, peeling plies, or crumbly lumps. */\n form?: SplitForm\n}\n\ninterface Box {\n c: Vec3\n s: Vec3\n}\n\n/** Split a box into `count` pieces by cutting the largest piece along its longest allowed axis. */\nconst bsp = (root: Box, count: number, axes: number[], rnd: () => number): Box[] => {\n const pieces: Box[] = [root]\n const vol = (b: Box) => axes.reduce((v, a) => v * b.s[a], 1)\n while (pieces.length < count) {\n let bi = 0\n for (let i = 1; i < pieces.length; i++) if (vol(pieces[i]) > vol(pieces[bi])) bi = i\n const b = pieces[bi]\n let ax = axes[0]\n for (const a of axes) if (b.s[a] > b.s[ax]) ax = a\n if (b.s[ax] < 1e-4) break\n const r = 0.3 + 0.4 * rnd()\n const l1 = b.s[ax] * r\n const l2 = b.s[ax] - l1\n const c1: Vec3 = [b.c[0], b.c[1], b.c[2]]\n const c2: Vec3 = [b.c[0], b.c[1], b.c[2]]\n c1[ax] = b.c[ax] - b.s[ax] / 2 + l1 / 2\n c2[ax] = b.c[ax] + b.s[ax] / 2 - l2 / 2\n const s1: Vec3 = [b.s[0], b.s[1], b.s[2]]\n const s2: Vec3 = [b.s[0], b.s[1], b.s[2]]\n s1[ax] = l1\n s2[ax] = l2\n pieces[bi] = { c: c1, s: s1 }\n pieces.push({ c: c2, s: s2 })\n }\n return pieces\n}\n\nconst parity = (p: [number, number, number]): number => {\n let inv = 0\n for (let i = 0; i < 3; i++) for (let j = i + 1; j < 3; j++) if (p[i] > p[j]) inv++\n return inv % 2 === 0 ? 1 : -1\n}\n\n/** Orientation whose x, y, z axes are the part axes `ax`, `ay`, `az`, then rotated by `angle` around its own z. */\nconst frame = (ax: number, ay: number, az: number, angle = 0): Quat => {\n const e = (i: number): Vec3 => [i === 0 ? 1 : 0, i === 1 ? 1 : 0, i === 2 ? 1 : 0]\n const z = e(az)\n const sg = parity([ax, ay, az])\n const q = quat.fromColumns(e(ax), e(ay), [z[0] * sg, z[1] * sg, z[2] * sg])\n return angle === 0 ? q : quat.mul(q, quat.fromAxisAngle([0, 0, 1], angle))\n}\n\nconst clamp = (v: number, a: number, b: number) => Math.max(a, Math.min(b, v))\n\n/** Cut `box` into `count` pieces of uneven length along `axis`: each piece takes a random share between a quarter and seven quarters of the mean. */\nconst splitAlong = (box: Box, count: number, axis: number, rnd: () => number): Box[] => {\n const shares = Array.from({ length: count }, () => 0.25 + 1.5 * rnd())\n const total = shares.reduce((sum, share) => sum + share, 0)\n const out: Box[] = []\n let from = box.c[axis] - box.s[axis] / 2\n for (const share of shares) {\n const length = (box.s[axis] * share) / total\n const c: Vec3 = [box.c[0], box.c[1], box.c[2]]\n const size: Vec3 = [box.s[0], box.s[1], box.s[2]]\n c[axis] = from + length / 2\n size[axis] = length\n out.push({ c, s: size })\n from += length\n }\n return out\n}\n\n/**\n * Splinters along the grain (`grain`, default the longest axis) out of `box`: the cross-section is split into strands of uneven width, and each strand\n * breaks along the grain at uneven points, so the splinters come out long and short, thick and thin, never a stack of equal slats.\n */\nconst splinterBox = (inp: PlanInput, box: Box, limit = inp.maxFragments): PlannedFragment[] => {\n const { rnd } = inp\n const dims = box.s\n const [fmin, fmax] = inp.fragmentSize\n const g = inp.grain ?? [0, 1, 2].sort((a, b) => dims[b] - dims[a])[0]\n const [a, b] = [0, 1, 2].filter((i) => i !== g)\n const w = Math.max(fmin * 1.5, 0.01)\n const c = clamp(Math.round((dims[a] * dims[b]) / (w * w)), 3, Math.max(3, Math.floor(limit / 2)))\n const maxLen = fmax * 4\n const cells: Box[] = []\n // some strands split again unevenly across: thin needles beside thick splinters\n for (const cell of bsp(box, c, [a, b], rnd)) {\n const wide = cell.s[a] >= cell.s[b] ? a : b\n if (rnd() < 0.4 && cell.s[wide] > fmin * 0.5) for (const part of splitAlong(cell, 2, wide, rnd)) cells.push(part)\n else cells.push(cell)\n }\n const pieces: Box[] = []\n for (const cell of cells) {\n const extra = Math.floor(rnd() * 3)\n const k = Math.max(1, Math.ceil(dims[g] / maxLen)) + extra\n for (const p of splitAlong(cell, k, g, rnd)) pieces.push(p)\n }\n return pieces.slice(0, limit).map((p) => ({ center: p.c, size: [p.s[g], p.s[a], p.s[b]] as Vec3, q: frame(g, a, b), shape: 'splinter' as const, weight: p.s[0] * p.s[1] * p.s[2] }))\n}\n\n/**\n * Metres of plywood one ply stands for, and how far apart the peeled layers start (times their thickness). A sheet is at most `PLY_SHEET` thick: a part\n * of plywood thicker than a board (a kennel drawn as one box) is a hollow of panels, and comes apart in sheets that thin spread through its depth.\n */\nconst PLY = 0.003\nconst PLY_GAP = 0.6\nconst PLY_SHEET = 0.012\n\n/**\n * Plywood coming apart: the glue lines let go and the sheet splits into two or three layers that start apart from each other, each torn into ragged\n * sheets, and about one piece in three a thin splinter along the face grain.\n */\nconst plyBreak = (inp: PlanInput, root: Box, limit: number): PlannedFragment[] => {\n const { rnd } = inp\n const dims = root.s\n const sorted = [0, 1, 2].sort((x, y) => dims[x] - dims[y])\n const t = sorted[0]\n const [u, v] = [sorted[1], sorted[2]].sort((x, y) => x - y)\n const along = dims[u] >= dims[v] ? u : v\n const across = along === u ? v : u\n const layers = clamp(Math.round(dims[t] / PLY / 2), 2, 3)\n const pitch = dims[t] / layers\n const th = Math.min(pitch, PLY_SHEET)\n const per = Math.max(2, Math.floor(limit / layers))\n const out: PlannedFragment[] = []\n for (let k = 0; k < layers; k++) {\n const layer: Box = { c: [root.c[0], root.c[1], root.c[2]], s: [dims[0], dims[1], dims[2]] }\n layer.c[t] = root.c[t] + (-dims[t] / 2 + (k + 0.5) * pitch) * (pitch > PLY_SHEET ? 1 : 1 + PLY_GAP)\n layer.s[t] = th\n for (const cell of bsp(layer, per, [u, v], rnd)) {\n if (out.length >= limit) return out\n if (rnd() < 0.35) {\n const strand = cell.s[across] * (0.15 + 0.2 * rnd())\n out.push({ center: cell.c, size: [cell.s[along], strand, th * 0.7], q: frame(along, across, t), shape: 'splinter', weight: cell.s[along] * strand * th })\n } else {\n out.push({ center: cell.c, size: [cell.s[u], cell.s[v], th], q: frame(u, v, t, (rnd() - 0.5) * 0.5), shape: 'scrap', weight: cell.s[u] * cell.s[v] * th })\n }\n }\n }\n return out\n}\n\n/** Crumbly lumps of a board with no grain (MDF): `count` lumps of uneven size out of `box`. */\nconst granules = (inp: PlanInput, box: Box, count: number): PlannedFragment[] =>\n bsp(box, count, [0, 1, 2], inp.rnd).map((b) => ({ center: b.c, size: b.s, q: quat.identity(), shape: 'chunk' as const, weight: b.s[0] * b.s[1] * b.s[2] }))\n\n/** Lumps the broken edge of an MDF board crumbles into, besides its slabs. */\nconst CRUMBS = 6\n\n/** Broken across at `at` along the longest axis: a stub each side and splinters (lumps for `snap`) out of the band `gap` wide between them. */\nconst severAt = (inp: PlanInput, root: Box, at: number, gap: number): PlannedFragment[] => {\n const dims = root.s\n const L = [0, 1, 2].sort((x, y) => dims[y] - dims[x])[0]\n const half = dims[L] / 2\n const lo = clamp(at - gap / 2, -half, half), hi = clamp(at + gap / 2, -half, half)\n const out: PlannedFragment[] = []\n // a stub of wood with fibre is laid long along its own x with the break at +x, so the renderer can tear that end into strands\n const fibrous = inp.form === 'slivers' || inp.form === 'plies'\n const [a, b] = [0, 1, 2].filter((i) => i !== L)\n const stub = (from: number, to: number, breakAtEnd: boolean) => {\n if (to - from < 0.02) return\n const c: Vec3 = [root.c[0], root.c[1], root.c[2]], sz: Vec3 = [dims[0], dims[1], dims[2]]\n c[L] = (from + to) / 2\n sz[L] = to - from\n const weight = sz[0] * sz[1] * sz[2]\n if (fibrous) out.push({ center: c, size: [sz[L], sz[a], sz[b]], q: frame(L, a, b, breakAtEnd ? 0 : Math.PI), shape: 'slab', weight })\n else out.push({ center: c, size: sz, q: quat.identity(), shape: 'slab', weight })\n }\n stub(-half, lo, true)\n stub(hi, half, false)\n const band: Box = { c: [root.c[0], root.c[1], root.c[2]], s: [dims[0], dims[1], dims[2]] }\n band.c[L] = (lo + hi) / 2\n band.s[L] = Math.max(hi - lo, 0.01)\n // a snapping board (MDF, plastic) crumbles in the band; the splinters of a splintering one lie along the grain when it runs across the cut,\n // else they are short slivers of the band\n const room = inp.maxFragments - out.length\n if (inp.style === 'snap' && inp.form === 'plies') for (const p of plyBreak(inp, band, Math.max(3, room))) out.push(p)\n else if (inp.style === 'snap' && inp.form === 'granules') for (const p of granules(inp, band, clamp(room, 3, 12))) out.push(p)\n else if (inp.style === 'snap') {\n for (const b of bsp(band, Math.max(3, Math.min(6, room)), [0, 1, 2], inp.rnd)) out.push({ center: b.c, size: b.s, q: quat.identity(), shape: 'chunk', weight: b.s[0] * b.s[1] * b.s[2] })\n } else for (const p of splinterBox(inp, band, Math.max(3, inp.maxFragments - out.length))) out.push(p)\n return out\n}\n\n/** Leaves of a stack torn apart (a book, a ream): `layers` of thin scraps through the thickness, a little askew; one scrap in four is cover, the rest pages. */\nconst tearStack = (inp: PlanInput, root: Box, t: number, u: number, v: number, n: number, sheet: number): PlannedFragment[] => {\n const { dims, rnd, maxFragments } = inp\n const layers = clamp(Math.ceil(dims[t] / STACK_LAYER), 2, 4)\n const per = clamp(n, 3, Math.max(3, Math.floor(maxFragments / layers)))\n const out: PlannedFragment[] = []\n for (let k = 0; k < layers; k++) {\n const off = -dims[t] / 2 + ((k + 0.5) * dims[t]) / layers\n for (const b of bsp(root, per, [u, v], rnd)) {\n if (out.length >= maxFragments) return out\n const c: Vec3 = [b.c[0], b.c[1], b.c[2]]\n c[t] = off\n out.push({ center: c, size: [b.s[u], b.s[v], sheet], q: frame(u, v, t, (rnd() - 0.5) * 0.8), shape: 'scrap', weight: b.s[u] * b.s[v], inner: out.length % 4 !== 0 })\n }\n }\n return out\n}\n\n/** Metres of a stack of sheets that one layer of scraps stands for. */\nconst STACK_LAYER = 0.012\n\n/** Deterministic fragment layout for a failed part, in part space. */\nexport const planFragments = (inp: PlanInput): PlannedFragment[] => {\n const { style, dims, rnd, maxFragments } = inp\n const [fmin, fmax] = inp.fragmentSize\n const mean = (fmin + fmax) / 2\n const root: Box = { c: [0, 0, 0], s: [dims[0], dims[1], dims[2]] }\n const idq = quat.identity()\n const out: PlannedFragment[] = []\n const sorted = [0, 1, 2].sort((a, b) => dims[a] - dims[b])\n const t = sorted[0]\n const [u, v] = [sorted[1], sorted[2]].sort((a, b) => a - b)\n\n if (style === 'snap') {\n if (inp.cut) return severAt(inp, root, inp.cut.at, inp.cut.gap)\n if (inp.form === 'plies') return plyBreak(inp, root, maxFragments)\n const n = Math.min(maxFragments, 2 + Math.floor(rnd() * 3))\n for (const b of bsp(root, n, [0, 1, 2], rnd)) out.push({ center: b.c, size: b.s, q: idq, shape: 'slab', weight: b.s[0] * b.s[1] * b.s[2] })\n if (inp.form !== 'granules') return out\n // the broken edges of an MDF board crumble: lumps out of a band around the point it broke at, sharing the mass with the slabs\n const crumbs = Math.min(CRUMBS, maxFragments - out.length)\n if (crumbs <= 0) return out\n const band: Box = { c: [0, 0, 0], s: [0, 0, 0] }\n for (let i = 0; i < 3; i++) {\n band.s[i] = Math.min(dims[i], Math.max(fmin, dims[i] * 0.2))\n band.c[i] = clamp(inp.hit[i], -dims[i] / 2 + band.s[i] / 2, dims[i] / 2 - band.s[i] / 2)\n }\n for (const p of granules(inp, band, crumbs)) out.push({ ...p, weight: p.weight * 0.5 })\n return out\n }\n if (style === 'crumble' || style === 'none') {\n const n = clamp(Math.ceil((dims[0] * dims[1] * dims[2]) / (mean * mean * mean)), 4, maxFragments)\n for (const b of bsp(root, n, [0, 1, 2], rnd)) out.push({ center: b.c, size: b.s, q: idq, shape: 'chunk', weight: b.s[0] * b.s[1] * b.s[2] })\n return out\n }\n if (style === 'splinter') {\n if (inp.cut) return severAt(inp, root, inp.cut.at, inp.cut.gap)\n for (const p of splinterBox(inp, root)) out.push(p)\n return out\n }\n if (style === 'tear') {\n const n = clamp(Math.round((dims[u] * dims[v]) / (mean * mean)), 3, maxFragments)\n const sheet = inp.sheet ?? 0\n if (sheet > 0 && dims[t] > sheet * 4) return tearStack(inp, root, t, u, v, n, sheet)\n const th = Math.min(inp.thickness, dims[t])\n for (const b of bsp(root, n, [u, v], rnd)) {\n out.push({ center: [b.c[0], b.c[1], b.c[2]], size: [b.s[u], b.s[v], th], q: frame(u, v, t), shape: 'scrap', weight: b.s[u] * b.s[v] })\n }\n return out\n }\n // shatter: thin shards radiating from the impact\n const th = Math.min(inp.thickness, dims[t])\n const Hu = dims[u] / 2, Hv = dims[v] / 2\n const hu = clamp(inp.hit[u], -Hu * 0.95, Hu * 0.95)\n const hv = clamp(inp.hit[v], -Hv * 0.95, Hv * 0.95)\n const R = Math.max(Math.hypot(Hu + Math.abs(hu), Hv + Math.abs(hv)), 0.02)\n const n = clamp(Math.round((dims[u] * dims[v]) / (mean * mean)), 6, maxFragments)\n const sectors = clamp(Math.round(Math.sqrt(n * 1.6)), 5, 10)\n const rings = Math.max(1, Math.ceil(n / sectors))\n const radii: number[] = []\n for (let k = 0; k <= rings; k++) radii.push(R * Math.pow(k / rings, 1.3))\n const cap = fmax * 1.5\n for (let j = 0; j < sectors && out.length < maxFragments; j++) {\n const theta = (j + (rnd() - 0.5) * 0.4) * ((Math.PI * 2) / sectors)\n for (let k = 0; k < rings && out.length < maxFragments; k++) {\n const rm = (radii[k] + radii[k + 1]) / 2\n const cu = hu + rm * Math.cos(theta)\n const cv = hv + rm * Math.sin(theta)\n if (Math.abs(cu) > Hu + 0.01 || Math.abs(cv) > Hv + 0.01) continue\n const radial = clamp(radii[k + 1] - radii[k], 0.01, cap)\n const tang = clamp(radii[k + 1] * ((Math.PI * 2) / sectors) * 0.9, 0.01, cap)\n const c: Vec3 = [0, 0, 0]\n c[u] = clamp(cu, -Hu * 0.98, Hu * 0.98)\n c[v] = clamp(cv, -Hv * 0.98, Hv * 0.98)\n c[t] = 0\n out.push({ center: c, size: [radial, tang, th], q: frame(u, v, t, theta), shape: 'shard', weight: radial * tang })\n }\n }\n if (out.length === 0) out.push({ center: [0, 0, 0], size: [dims[u], dims[v], th], q: frame(u, v, t), shape: 'shard', weight: 1 })\n return out\n}\n","import { quat, rotateVec } from './math'\nimport type { FragmentMark, PartUnits, Quat, Vec3 } from './types'\n\n/** One masonry unit (or panel) cut out of a wall, in the part's own axes. */\nexport interface UnitCell {\n center: Vec3\n size: Vec3\n}\n\n/** The two axes a wall spreads along: height is local y unless the part is thin along y (a slab), then x and z. */\nexport const planeAxes = (thin: number): [number, number] => (thin === 1 ? [0, 2] : [thin === 0 ? 2 : 0, 1])\n\n/**\n * Every unit of the wall laid in `bond`: rows along the plane's second axis, running bond shifts odd rows by half a unit, edge units are cut to\n * the wall. More than `cap` units are merged into bigger ones (the same bond) so a whole wall stays a drawable number of fragments.\n */\nexport const unitGrid = (dims: Vec3, thin: number, units: Pick<PartUnits, 'size' | 'bond'>, cap: number): UnitCell[] => {\n const [u, v] = planeAxes(thin)\n let unitU = Math.min(units.size[0], dims[u]), unitV = Math.min(units.size[1], dims[v])\n const rowsFor = (h: number): number => Math.ceil(dims[v] / h - 1e-9)\n const colsFor = (w: number): number => Math.ceil(dims[u] / w - 1e-9) + (units.bond === 'running' ? 1 : 0)\n const merge = Math.ceil(Math.sqrt((rowsFor(unitV) * colsFor(unitU)) / cap))\n if (merge > 1) {\n unitU = Math.min(unitU * merge, dims[u])\n unitV = Math.min(unitV * merge, dims[v])\n }\n const cells: UnitCell[] = []\n for (let row = 0; row < rowsFor(unitV); row++) {\n const v0 = -dims[v] / 2 + row * unitV, v1 = Math.min(v0 + unitV, dims[v] / 2)\n const shift = units.bond === 'running' && row % 2 === 1 ? unitU / 2 : 0\n for (let col = 0; col < colsFor(unitU); col++) {\n const u0 = Math.max(-dims[u] / 2 + col * unitU - shift, -dims[u] / 2), u1 = Math.min(-dims[u] / 2 + (col + 1) * unitU - shift, dims[u] / 2)\n if (u1 - u0 < 0.01) continue\n const center: Vec3 = [0, 0, 0], size: Vec3 = [0, 0, 0]\n center[u] = (u0 + u1) / 2\n center[v] = (v0 + v1) / 2\n size[u] = u1 - u0\n size[v] = v1 - v0\n size[thin] = dims[thin]\n cells.push({ center, size })\n }\n }\n return cells\n}\n\nconst planeDistance = (cell: UnitCell, thin: number, point: Vec3): number => {\n const [u, v] = planeAxes(thin)\n const du = cell.center[u] - point[u], dv = cell.center[v] - point[v]\n return Math.sqrt(du * du + dv * dv)\n}\n\n/** Units whose centre is within `radius` of `point` (part-local) in the wall plane; at least the nearest one. */\nexport const cellsWithin = (cells: readonly UnitCell[], thin: number, point: Vec3, radius: number): UnitCell[] => {\n const inside = cells.filter((c) => planeDistance(c, thin, point) <= radius)\n if (inside.length > 0 || cells.length === 0) return inside\n return [cells.reduce((best, c) => (planeDistance(c, thin, point) < planeDistance(best, thin, point) ? c : best))]\n}\n\nexport const cellsOutside = (cells: readonly UnitCell[], thin: number, point: Vec3, radius: number): UnitCell[] => cells.filter((c) => planeDistance(c, thin, point) > radius)\n\n/** A hole in the part's own axes. */\nexport interface LocalHole {\n point: Vec3\n normal: Vec3\n diameter: number\n}\n\nexport const MAX_MARKS_PER_FRAGMENT = 12\n\n/** The holes that fall inside a fragment box (`rotation` is the fragment's orientation in the part), in the fragment's own axes. */\nexport const marksInBox = (center: Vec3, size: Vec3, rotation: Quat | undefined, holes: readonly LocalHole[]): FragmentMark[] => {\n const inverse = rotation ? quat.conjugate(rotation) : undefined\n const marks: FragmentMark[] = []\n for (const hole of holes) {\n const offset: Vec3 = [hole.point[0] - center[0], hole.point[1] - center[1], hole.point[2] - center[2]]\n const point = inverse ? rotateVec(inverse, offset) : offset\n const inside = point.every((value, k) => Math.abs(value) <= size[k]! / 2 + hole.diameter / 2)\n if (!inside) continue\n marks.push({ point, normal: inverse ? rotateVec(inverse, hole.normal) : hole.normal, diameter: hole.diameter })\n if (marks.length >= MAX_MARKS_PER_FRAGMENT) break\n }\n return marks\n}\n\nconst JOINT_GAP = 1e-4\n/** Share of the shorter of two units their bed has to overlap for one to bear on the other: a unit held by a corner does not stand. */\nconst MIN_BEARING_SHARE = 0.25\n\n/**\n * The units of a wall still standing (`standing(i)`) that no longer bear on its bottom through the units under them: a unit stands while its bed\n * overlaps a standing unit of the row below (the bottom row stands on what holds the wall). Masonry carries by bearing, and the mortar of a head\n * joint holds next to nothing in tension, so over a hole the courses step in by the bond (half a unit a course in running bond) and the triangle\n * above it comes down, as it does over an opening without a lintel; at the free end of a wall, all that hangs over the hole. A unit that keeps only a\n * corner of its bed (less than `MIN_BEARING_SHARE` of a unit) does not bear: the mortar of a joint does not hold its moment. A unit between two standing\n * units of its course is wedged by its head joints, so a gap of two units does not drop the one over it. A slab (thin along y)\n * has no bottom row: none.\n */\nexport const unsupportedCells = (cells: readonly UnitCell[], thin: number, dims: Vec3, standing: (index: number) => boolean): number[] => {\n if (thin === 1) return []\n const [u, v] = planeAxes(thin)\n const bottom = -dims[v] / 2\n const rowOf = (y: number): number => Math.round((y - bottom) * 1e4)\n const rows = new Map<number, number[]>()\n for (let i = 0; i < cells.length; i++) {\n if (!standing(i)) continue\n const cell = cells[i]!\n const key = rowOf(cell.center[v] - cell.size[v] / 2)\n const row = rows.get(key)\n if (row) row.push(i)\n else rows.set(key, [i])\n }\n const held = new Set<number>()\n const queue: number[] = []\n for (const i of rows.get(0) ?? []) {\n held.add(i)\n queue.push(i)\n }\n const overlap = (a: UnitCell, b: UnitCell): number =>\n Math.min(a.center[u] + a.size[u] / 2, b.center[u] + b.size[u] / 2) - Math.max(a.center[u] - a.size[u] / 2, b.center[u] - b.size[u] / 2)\n const climb = () => {\n while (queue.length > 0) {\n const cell = cells[queue.pop()!]!\n for (const j of rows.get(rowOf(cell.center[v] + cell.size[v] / 2)) ?? []) {\n const other = cells[j]!\n if (held.has(j) || overlap(cell, other) <= Math.max(JOINT_GAP, MIN_BEARING_SHARE * Math.min(cell.size[u], other.size[u]))) continue\n held.add(j)\n queue.push(j)\n }\n }\n }\n // the units of each course in order along the wall: a unit between two that stand is wedged between them by its head joints (it bridges a gap of\n // two units under it); one held on one side only would hang from its mortar, which does not hold the moment\n for (const row of rows.values()) row.sort((a, b) => cells[a]!.center[u] - cells[b]!.center[u])\n const touching = (a: UnitCell, b: UnitCell): boolean => Math.abs(a.center[u] + a.size[u] / 2 - (b.center[u] - b.size[u] / 2)) <= 1e-3\n for (let wedged = true; wedged;) {\n climb()\n wedged = false\n for (const row of rows.values()) {\n for (let k = 1; k < row.length - 1; k++) {\n const i = row[k]!\n if (held.has(i) || !held.has(row[k - 1]!) || !held.has(row[k + 1]!)) continue\n if (!touching(cells[row[k - 1]!]!, cells[i]!) || !touching(cells[i]!, cells[row[k + 1]!]!)) continue\n held.add(i)\n queue.push(i)\n wedged = true\n }\n }\n }\n const loose: number[] = []\n for (const row of rows.values()) for (const i of row) if (!held.has(i)) loose.push(i)\n return loose\n}\n\n/**\n * At most `cap` clumps of `cells` (part-local units of a wall): the units binned on a square grid of the wall plane, each bin the box around its units.\n * Masonry a blast throws comes out in clumps of a few units held by their mortar, not one by one.\n */\nexport const clumpCells = (cells: readonly UnitCell[], thin: number, cap: number): UnitCell[] => {\n if (cells.length <= cap) return [...cells]\n const [u, v] = planeAxes(thin)\n let lo0 = Infinity, lo1 = Infinity, hi0 = -Infinity, hi1 = -Infinity\n for (const cell of cells) {\n lo0 = Math.min(lo0, cell.center[u] - cell.size[u] / 2)\n hi0 = Math.max(hi0, cell.center[u] + cell.size[u] / 2)\n lo1 = Math.min(lo1, cell.center[v] - cell.size[v] / 2)\n hi1 = Math.max(hi1, cell.center[v] + cell.size[v] / 2)\n }\n let side = Math.sqrt(((hi0 - lo0) * (hi1 - lo1)) / cap)\n for (;;) {\n const bins = new Map<string, { lo: Vec3; hi: Vec3 }>()\n for (const cell of cells) {\n const key = `${Math.floor((cell.center[u] - lo0) / side)}:${Math.floor((cell.center[v] - lo1) / side)}`\n const bin = bins.get(key) ?? { lo: [Infinity, Infinity, Infinity] as Vec3, hi: [-Infinity, -Infinity, -Infinity] as Vec3 }\n for (let k = 0; k < 3; k++) {\n bin.lo[k] = Math.min(bin.lo[k]!, cell.center[k]! - cell.size[k]! / 2)\n bin.hi[k] = Math.max(bin.hi[k]!, cell.center[k]! + cell.size[k]! / 2)\n }\n bins.set(key, bin)\n }\n if (bins.size <= cap) {\n return [...bins.values()].map(({ lo, hi }) => ({ center: [(lo[0] + hi[0]) / 2, (lo[1] + hi[1]) / 2, (lo[2] + hi[2]) / 2] as Vec3, size: [hi[0] - lo[0], hi[1] - lo[1], hi[2] - lo[2]] as Vec3 }))\n }\n side *= 1.25\n }\n}\n","import type { MaterialDef, SurfaceLayer, Vec3 } from './types'\n\n/** A surface layer with its material resolved; `energy` is what a bullet spends crossing one face's worth of it, in joules. */\nexport interface LayerRT {\n index: number\n def: SurfaceLayer\n mat: MaterialDef\n energy: number\n}\n\n/** `[layer, face (+1 or -1), x, y, z, radius]`: a patch of a layer that came off, in object-local space. Saved with the part. */\nexport type Spall = readonly [number, number, number, number, number, number]\n\nexport const MAX_SPALLS = 64\n\n/** Index of the smallest dimension (the first one on a tie): the axis a wall is thin along. */\nexport const thinAxisOf = (dims: Vec3): number => (dims[0] <= dims[1] && dims[0] <= dims[2] ? 0 : dims[1] <= dims[2] ? 1 : 2)\n\nexport const resolveLayer = (def: SurfaceLayer, index: number, mat: MaterialDef): LayerRT => ({ index, def, mat, energy: mat.penetration * def.thickness * 1000 })\n\nconst onFace = (layer: LayerRT, face: number): boolean => layer.def.faces === 'both' || layer.def.faces === (face > 0 ? '+' : '-')\n\nconst isSpalled = (spalls: readonly Spall[] | undefined, layer: number, face: number, point: Vec3): boolean => {\n for (const s of spalls ?? []) {\n if (s[0] !== layer || s[1] !== face) continue\n const dx = s[2] - point[0], dy = s[3] - point[1], dz = s[4] - point[2]\n if (dx * dx + dy * dy + dz * dz <= s[5] * s[5]) return true\n }\n return false\n}\n\n/** The outermost layer still on `face` at `point` (layers are listed outermost first). */\nexport const outerLayer = (layers: readonly LayerRT[], spalls: readonly Spall[] | undefined, face: number, point: Vec3): LayerRT | undefined =>\n layers.find((l) => onFace(l, face) && !isSpalled(spalls, l.index, face, point))\n\n/** Joules a bullet spends crossing every layer still on `face` at `point`. */\nexport const layersEnergy = (layers: readonly LayerRT[], spalls: readonly Spall[] | undefined, face: number, point: Vec3): number => {\n let sum = 0\n for (const l of layers) if (onFace(l, face) && !isSpalled(spalls, l.index, face, point)) sum += l.energy\n return sum\n}\n\n/** Metres of layer a ray crosses on one face (full thickness, before obliquity). */\nexport const layersThickness = (layers: readonly LayerRT[], face: number): number => {\n let sum = 0\n for (const l of layers) if (onFace(l, face)) sum += l.def.thickness\n return sum\n}\n","import type { Vec3 } from './types'\n\n/** A bar as two end points. */\nexport type Bar = [Vec3, Vec3]\n\nconst COVER = 0.03\nconst MAX_BARS_PER_DIRECTION = 24\nconst MAX_MEMBER_BARS_PER_SIDE = 6\nconst STEEL_DENSITY = 7850\n\n/** Positions centred on 0 with exact `spacing`, as many as fit inside `length - 2 * cover` (at least two, at most `cap`). */\nconst spread = (length: number, cover: number, spacing: number, cap: number): number[] => {\n const room = Math.max(0, length - 2 * cover)\n const count = Math.min(cap, Math.max(2, Math.floor(room / spacing) + 1))\n const step = count > 1 && room / (count - 1) < spacing ? room / (count - 1) : spacing\n return Array.from({ length: count }, (_, i) => (i - (count - 1) / 2) * step)\n}\n\nconst bar = (axis: number, along: number, fixed: Array<[number, number]>): Bar => {\n const a: Vec3 = [0, 0, 0], b: Vec3 = [0, 0, 0]\n for (const [index, value] of fixed) {\n a[index] = value\n b[index] = value\n }\n a[axis] = -along\n b[axis] = along\n return [a, b]\n}\n\n/** Long members (columns, beams): two smaller dimensions close to each other and a much longer third one. */\nexport const isMember = (dims: Vec3): boolean => {\n const [a = 0, b = 0, c = 0] = [...dims].sort((x, y) => x - y)\n return b / a < 3 && c / b >= 3\n}\n\n/** Bars of a long member's perimeter that lie on one face of width `width` (the face's row of the cage). */\nexport const memberBarCount = (width: number, spacing: number): number => spread(width, COVER, spacing, MAX_MEMBER_BARS_PER_SIDE).length\n\n/**\n * Rebar of a box in the part's own axes. Plates (walls, slabs) get a grid along each of the two large axes at mid thickness; long members get\n * bars along their length at the perimeter of the section. `thin` is the axis the part is thinnest along.\n */\nexport const rebarBars = (dims: Vec3, thin: number, spacing: number): Bar[] => {\n const out: Bar[] = []\n if (isMember(dims)) {\n const long = dims.indexOf(Math.max(...dims))\n const [u = 0, v = 0] = [0, 1, 2].filter((i) => i !== long)\n const us = spread(dims[u], COVER, spacing, MAX_MEMBER_BARS_PER_SIDE)\n const vs = spread(dims[v], COVER, spacing, MAX_MEMBER_BARS_PER_SIDE)\n us.forEach((x, i) => vs.forEach((y, j) => {\n if (i === 0 || j === 0 || i === us.length - 1 || j === vs.length - 1) out.push(bar(long, dims[long] / 2 - 0.02, [[u, x], [v, y]]))\n }))\n return out\n }\n const [u = 0, v = 0] = [0, 1, 2].filter((i) => i !== thin)\n for (const y of spread(dims[v], COVER, spacing, MAX_BARS_PER_DIRECTION)) out.push(bar(u, dims[u] / 2 - 0.02, [[v, y], [thin, 0]]))\n for (const x of spread(dims[u], COVER, spacing, MAX_BARS_PER_DIRECTION)) out.push(bar(v, dims[v] / 2 - 0.02, [[u, x], [thin, 0]]))\n return out\n}\n\n/** The part of each bar that lies inside a box of `size` centred on `center` (part axes), in the plane of axes `u` and `v`; bars that miss it are dropped. */\nexport const clipBarsToBox = (bars: readonly Bar[], u: number, v: number, center: Vec3, size: Vec3): Bar[] => {\n const out: Bar[] = []\n for (const [a, b] of bars) {\n const axis = a[u] !== b[u] ? u : v\n const other = axis === u ? v : u\n if (Math.abs(a[other] - center[other]) > size[other] / 2) continue\n const lo = Math.max(Math.min(a[axis], b[axis]), center[axis] - size[axis] / 2), hi = Math.min(Math.max(a[axis], b[axis]), center[axis] + size[axis] / 2)\n if (hi - lo < 1e-6) continue\n const p: Vec3 = [a[0], a[1], a[2]], q: Vec3 = [b[0], b[1], b[2]]\n p[axis] = lo\n q[axis] = hi\n out.push([p, q])\n }\n return out\n}\n\n/** A bar bowed by `bow` metres per metre of its length out of the plane (along `thin`), as two segments meeting at the bowed middle; `i` alternates the side. */\nexport const bendBar = ([a, b]: Bar, thin: number, bow: number, i: number): Bar[] => {\n const length = Math.hypot(b[0] - a[0], b[1] - a[1], b[2] - a[2])\n const m: Vec3 = [(a[0] + b[0]) / 2, (a[1] + b[1]) / 2, (a[2] + b[2]) / 2]\n m[thin] += (i % 2 === 0 ? 1 : -1) * bow * length\n return [[a, m], [m, b]]\n}\n\n/** The part of each bar that lies within `radius` of `center` in the plane of axes `u` and `v` (bars that miss the disc are dropped). */\nexport const clipBarsToDisc = (bars: readonly Bar[], u: number, v: number, center: [number, number], radius: number): Bar[] => {\n const out: Bar[] = []\n for (const [a, b] of bars) {\n const axis = a[u] !== b[u] ? u : v\n const other = axis === u ? v : u\n const off = a[other] - center[other === u ? 0 : 1]\n if (Math.abs(off) >= radius) continue\n const half = Math.sqrt(radius * radius - off * off)\n const mid = center[axis === u ? 0 : 1]\n const lo = Math.max(Math.min(a[axis], b[axis]), mid - half), hi = Math.min(Math.max(a[axis], b[axis]), mid + half)\n if (hi - lo < 1e-6) continue\n const p: Vec3 = [a[0], a[1], a[2]], q: Vec3 = [b[0], b[1], b[2]]\n p[axis] = lo\n q[axis] = hi\n out.push([p, q])\n }\n return out\n}\n\n/**\n * How many bars of `rebarBars` run up the part (along its vertical axis), counted without the cap that keeps the drawn cage light: the steel that holds a\n * wall or a column in tension is all the bars its spacing puts in, not the 24 that are drawn. A long member lying on its side has none.\n */\nexport const verticalBarCount = (dims: Vec3, thin: number, spacing: number): number => {\n if (isMember(dims)) {\n if (dims.indexOf(Math.max(...dims)) !== 1) return 0\n const us = spread(dims[0], COVER, spacing, Infinity).length, vs = spread(dims[2], COVER, spacing, Infinity).length\n return 2 * us + 2 * Math.max(0, vs - 2)\n }\n const [u = 0, v = 0] = [0, 1, 2].filter((i) => i !== thin)\n if (u === 1) return spread(dims[v], COVER, spacing, Infinity).length\n if (v === 1) return spread(dims[u], COVER, spacing, Infinity).length\n return 0\n}\n\n/** Steel mass in kg of bars of `diameter` metres. */\nexport const rebarMass = (bars: readonly Bar[], diameter: number, density = STEEL_DENSITY): number => {\n let length = 0\n for (const [a, b] of bars) length += Math.abs(a[0] - b[0]) + Math.abs(a[1] - b[1]) + Math.abs(a[2] - b[2])\n return Math.PI * (diameter / 2) * (diameter / 2) * length * density\n}\n","import { planeAxes } from './breach'\nimport { thinAxisOf } from './layers'\nimport { quat, quatFromEuler, rotateVec, shapeDims } from './math'\nimport { isMember, memberBarCount } from './rebar'\nimport type { FlexureOptions, MasonryOptions, MaterialDef, PartSpec, StructureRole, Vec3 } from './types'\n\n/**\n * Real structural engineering of beams, slabs, walls and pillars: bending (the tension face cracks, the steel carries the pull, a member without\n * steel snaps) and crushing of slender bearing walls. Pure formulas in SI units (N, m, Pa, J); the world calls them with the parts' geometry.\n */\n\n/** Standard gravity, m/s². A physical constant. */\nexport const GRAVITY = 9.81\nconst MPA = 1e6\n\nexport const FLEXURE_DEFAULTS: Required<FlexureOptions> = {\n enabled: true,\n roles: ['beam', 'slab', 'roof', 'stair'],\n scope: 'rebar',\n crackFactor: 1.5,\n rebarYieldMPa: 500,\n cover: 0.03,\n neutralAxisLimit: 0.45,\n failRotationDeg: 10,\n loadFactor: 0.64,\n massFactor: 0.5,\n tntJoules: 4.184e6,\n impulse: 200,\n reflection: 2,\n reflectionNear: 4,\n nearScaled: 0.5,\n}\n\nexport const MASONRY_DEFAULTS: Required<MasonryOptions> = { minEccentricity: 0.05, slendernessLimit: 40, concreteFactor: 0.85 }\n\nexport const resolveFlexure = (o?: FlexureOptions): Required<FlexureOptions> => ({ ...FLEXURE_DEFAULTS, ...definedOf(o) })\nexport const resolveMasonry = (o?: MasonryOptions): Required<MasonryOptions> => ({ ...MASONRY_DEFAULTS, ...definedOf(o) })\nconst definedOf = <T extends object>(o?: T): Partial<T> => Object.fromEntries(Object.entries(o ?? {}).filter(([, v]) => v !== undefined)) as Partial<T>\n\n/** Bar diameter assumed for a `structure.rebar` ratio (it only sets where the bar centre is): 10 mm. */\nconst RATIO_BAR = 0.01\n\n/** Cracking moment of a rectangular section in N m: `alpha * fct * b * h^2 / 6` (NBR 6118 17.3.1). */\nexport const crackingMoment = (tensileMPa: number, b: number, h: number, alpha = FLEXURE_DEFAULTS.crackFactor): number => alpha * tensileMPa * MPA * (b * h * h) / 6\n\n/**\n * Moment the tension steel gives in N m, with the rectangular stress block of NBR 6118 17.2.2 (`0.85 * fck` over `0.8 x`): the steel pulls\n * `T = As * fy`, the block takes it at depth `x = T / (0.68 * fck * b)`, and `M = T * (d - 0.4 x)`. Past the ductility limit `x = limit * d` the\n * concrete would crush first, so the steel beyond what balances the block is taken as paired with compression steel (double reinforcement, NBR 6118\n * 17.2.4): it adds `T2 * (d - d')`, `d'` being the cover to the compression bars.\n */\nexport const steelMoment = (\n area: number, yieldMPa: number, d: number, b: number, compressiveMPa: number, options: Pick<FlexureOptions, 'neutralAxisLimit' | 'cover'> = {},\n): number => {\n if (area <= 0 || d <= 0 || b <= 0) return 0\n const T = area * yieldMPa * MPA\n const block = 0.68 * compressiveMPa * MPA * b\n const x = T / block\n const xl = (options.neutralAxisLimit ?? FLEXURE_DEFAULTS.neutralAxisLimit) * d\n if (x <= xl) return T * (d - 0.4 * x)\n const top = Math.min(d / 2, (options.cover ?? FLEXURE_DEFAULTS.cover) + RATIO_BAR / 2)\n return block * xl * (d - 0.4 * xl) + (T - block * xl) * (d - top)\n}\n\n/** Stiffness in N/m of a simply supported span under uniform load, at mid-span: `384 E I / (5 L^3)`. */\nexport const spanStiffness = (EI: number, span: number): number => (384 * EI) / (5 * span ** 3)\n\n/**\n * Strain energy in J of the equivalent one-degree-of-freedom system of a span whose peak moment is `M` (uniform load: `R = 8 M / L`): `KL * R^2 / (2 k)`.\n */\nexport const elasticEnergy = (moment: number, span: number, EI: number, loadFactor = FLEXURE_DEFAULTS.loadFactor): number => {\n const R = (8 * moment) / span\n return (loadFactor * R * R) / (2 * spanStiffness(EI, span))\n}\n\n/** Inverse of `elasticEnergy`: the peak moment in N m a span reaches when it takes `energy` J elastically. */\nexport const momentOfEnergy = (energy: number, span: number, EI: number, loadFactor = FLEXURE_DEFAULTS.loadFactor): number =>\n (span / 8) * Math.sqrt((2 * Math.max(0, energy) * spanStiffness(EI, span)) / loadFactor)\n\n/** Kinetic energy in J an impulse `I` (N s) gives the equivalent system of a span of mass `m` (kg): `(KL I)^2 / (2 KM m)` (Biggs 1964). */\nexport const impulseEnergy = (impulse: number, mass: number, options: Pick<FlexureOptions, 'loadFactor' | 'massFactor'> = {}): number => {\n const KL = options.loadFactor ?? FLEXURE_DEFAULTS.loadFactor\n const KM = options.massFactor ?? FLEXURE_DEFAULTS.massFactor\n return mass > 0 ? (KL * impulse) ** 2 / (2 * KM * mass) : 0\n}\n\n/**\n * Reflected impulse per area in Pa s of a charge of `tnt` kg at `distance` m on a face that looks at it. The incident impulse is Sadovsky's\n * `impulse * W^(2/3) / R`; the face reflects it by `reflection + reflectionNear / Z` (`Z = R / W^(1/3)`, m/kg^(1/3)): about 2 far away, 4 to 6 at\n * one or two metres per cube root kilogram, as the reflected-impulse curves of UFC 3-340-02 (fig. 2-7) rise towards the charge. Below `nearScaled`\n * the distance is held at that scaled distance.\n */\nexport const blastImpulse = (\n tnt: number, distance: number, options: Pick<FlexureOptions, 'impulse' | 'reflection' | 'reflectionNear' | 'nearScaled'> = {},\n): number => {\n if (tnt <= 0) return 0\n const o = { ...FLEXURE_DEFAULTS, ...definedOf(options) }\n const cube = Math.cbrt(tnt)\n const r = Math.max(distance, o.nearScaled * cube)\n return (o.reflection + o.reflectionNear / (r / cube)) * ((o.impulse * cube * cube) / r)\n}\n\n/**\n * Share of the compressive strength a wall or pillar of height `h` and thickness `t` keeps: the unavoidable eccentricity `(1 - 2 e)` times the\n * slenderness reduction `1 - (h / t / limit)^3` (NBR 16868-1), never below 0.\n */\nexport const slendernessFactor = (h: number, t: number, options: MasonryOptions = {}): number => {\n const o = resolveMasonry(options)\n const lambda = h / Math.max(t, 1e-3)\n return Math.max(0, (1 - 2 * o.minEccentricity) * (1 - (lambda / o.slendernessLimit) ** 3))\n}\n\n/** The part is reinforced for bending: a `reinforcement` cage or a `structure.rebar` ratio. */\nexport const isReinforced = (part: PartSpec): boolean => !!part.reinforcement || (part.structure?.rebar?.ratio ?? 0) > 0\n\n/** The part's material is slender masonry or plain concrete (`strength.slender`, default: tagged `masonry` and not reinforced). */\nexport const isSlender = (part: PartSpec, material: MaterialDef): boolean =>\n material.strength?.slender ?? (!!material.tags?.includes('masonry') && !isReinforced(part))\n\n/** The part takes part in the bending model. */\nexport const isFlexural = (part: PartSpec, material: MaterialDef, options: Required<FlexureOptions>): boolean =>\n options.enabled && material.strength?.tensileMPa !== undefined && !!part.structure && options.roles.includes(part.structure.role) &&\n (part.structure.rebar !== undefined || options.scope === 'all' || (options.scope === 'reinforced' && !!part.reinforcement))\n\n/** A bending section: width `b`, depth `h` (along the bending), in metres. */\nexport interface BendSection {\n b: number\n h: number\n}\n\n/** Tension steel of a section: area in m², effective depth in m, yield in MPa. */\nexport interface TensionSteel {\n area: number\n d: number\n yieldMPa: number\n}\n\n/**\n * Tension steel of the part for a section of width `b` and depth `h`: from `structure.rebar` (`ratio * b * d`), else from the `reinforcement` cage\n * (a plate's grid: one bar every `spacing` across `b`; a long member: the bars of the perimeter on the tension face). Zero for plain concrete.\n */\nexport const tensionSteel = (part: PartSpec, dims: Vec3, section: BendSection, options: Required<FlexureOptions>): TensionSteel => {\n const rebar = part.structure?.rebar\n const cage = part.reinforcement\n const bar = rebar ? RATIO_BAR : cage?.diameter ?? RATIO_BAR\n const d = Math.max(0.01, section.h - (rebar?.cover ?? options.cover) - bar / 2)\n const yieldMPa = rebar?.yieldMPa ?? options.rebarYieldMPa\n if (rebar && rebar.ratio > 0) return { area: rebar.ratio * section.b * d, d, yieldMPa }\n if (!cage) return { area: 0, d, yieldMPa }\n const one = (Math.PI * cage.diameter * cage.diameter) / 4\n const count = isMember(dims) ? memberBarCount(section.b, cage.spacing) : section.b / cage.spacing\n return { area: one * count, d, yieldMPa }\n}\n\n/**\n * Moments of a section in N m: `cracking` (the concrete's), `steel` (what the tension steel gives once the concrete has cracked; 0 for plain\n * concrete), `ultimate` (what the uncracked section holds: the larger of the two) and `reinforced` (it has steel: when it fails it hinges and its bars\n * keep it in one piece; without steel it snaps).\n */\nexport interface SectionMoments {\n cracking: number\n steel: number\n ultimate: number\n reinforced: boolean\n}\n\nexport const sectionMoments = (material: MaterialDef, section: BendSection, steel: TensionSteel, options: Required<FlexureOptions>): SectionMoments => {\n const s = material.strength!\n const cracking = crackingMoment(s.tensileMPa ?? 0, section.b, section.h, options.crackFactor)\n const steelM = steelMoment(steel.area, steel.yieldMPa, steel.d, section.b, s.compressiveMPa, options)\n return { cracking, steel: steelM, ultimate: Math.max(cracking, steelM), reinforced: steelM > 0 }\n}\n\n/** Static moment in N m at mid-span of a span `L` under a uniform load `w` (N/m): `w L^2 / 8`. */\nexport const spanMoment = (w: number, span: number): number => (w * span * span) / 8\n\n/**\n * How a box part bends, in its own axes. A long member (beam) spans along `long` and bends about either cross axis; a plate (slab) spans in the plane\n * of `plane` and bends across its thickness `thin`. `gravity` is the axis the weight bends it along (the local axis closest to the vertical among those\n * it can bend along, when it is within 45 degrees of it; -1 for a plate standing on edge). `up` is the world vertical in the part's axes.\n */\nexport interface BendGeometry {\n dims: Vec3\n member: boolean\n /** Axes the span is measured along: `[long]` for a member, the two plane axes for a plate. */\n spanAxes: number[]\n /** Axes the part can bend along (its depth): the two cross axes of a member, the thickness of a plate. */\n depthAxes: number[]\n gravity: number\n up: Vec3\n}\n\nexport const bendGeometry = (part: PartSpec): BendGeometry => {\n const dims = shapeDims(part.shape)\n const member = isMember(dims)\n const q = quatFromEuler(...(part.rotation ?? [0, 0, 0]))\n const up = rotateVec(quat.conjugate(q), [0, 1, 0])\n let spanAxes: number[]\n let depthAxes: number[]\n if (member) {\n const long = dims.indexOf(Math.max(...dims))\n spanAxes = [long]\n depthAxes = [0, 1, 2].filter((i) => i !== long)\n } else {\n const thin = thinAxisOf(dims)\n spanAxes = [...planeAxes(thin)]\n depthAxes = [thin]\n }\n let gravity = -1\n for (const a of depthAxes) if (Math.abs(up[a]) > Math.SQRT1_2 && (gravity < 0 || Math.abs(up[a]) > Math.abs(up[gravity]))) gravity = a\n return { dims, member, spanAxes, depthAxes, gravity, up }\n}\n\n/** Width of the section that bends along `axis`: the other cross axis of a member, a strip of 1 m of a plate. */\nexport const sectionWidth = (g: BendGeometry, axis: number): number => (g.member ? g.dims[g.depthAxes.find((a) => a !== axis) ?? axis] : 1)\n\n/**\n * Uniform load in N per metre of span of the bending section when the part carries `load` kg: per metre of a member's length, per metre-wide strip\n * of a plate (its load per square metre times 1 m).\n */\nexport const lineLoad = (g: BendGeometry, load: number): number => {\n const area = g.member ? g.dims[g.spanAxes[0]!] : g.dims[g.spanAxes[0]!] * g.dims[g.spanAxes[1]!]\n return (load * GRAVITY) / Math.max(area, 1e-6)\n}\n\n/**\n * Span in metres from the regions the part rests on (`contacts`: boxes `[min, max]` in the part's axes): twice the farthest any point of the part\n * is from its nearest support, measured along the span axes as the largest of the per-axis gaps. Two walls 4 m apart give 4 m, four columns at the\n * corners of a 5 x 4 m panel give 5 m (the long way), a cantilever of 1.5 m gives 3 m (the same moment, `w c^2 / 2`). 0 without contacts.\n */\nexport const spanOf = (g: BendGeometry, contacts: ReadonlyArray<readonly [Vec3, Vec3]>, samples = 9): number => {\n if (contacts.length === 0) return 0\n const axes = g.spanAxes\n const steps = (a: number) => Array.from({ length: samples }, (_, i) => (i / (samples - 1) - 0.5) * g.dims[a])\n const us = steps(axes[0]!)\n const vs = axes.length > 1 ? steps(axes[1]!) : [0]\n let far = 0\n for (const u of us) for (const v of vs) {\n let near = Infinity\n for (const [lo, hi] of contacts) {\n let gap = 0\n const x = [u, v]\n axes.forEach((a, k) => (gap = Math.max(gap, lo[a] - x[k]!, x[k]! - hi[a], 0)))\n if (gap < near) near = gap\n }\n if (near > far) far = near\n }\n return 2 * far\n}\n\n/** Roles that carry bending by default. */\nexport const FLEXURAL_ROLES: readonly StructureRole[] = FLEXURE_DEFAULTS.roles\n\nexport interface BearingWallOptions {\n /** Storeys the wall carries, the ground floor included. */\n storeys: number\n /** Height of one storey in metres. */\n storeyHeight: number\n /** Load each floor puts on one metre of wall, in N/m (dead and live load of the floor's share). */\n floorLoad: number\n /** Material of the wall (default the built-in `brick`): `strength.compressiveMPa` and `density`. */\n material: Pick<MaterialDef, 'density' | 'strength'>\n /** Load factor (1.4: NBR 8681, permanent and variable loads). */\n loadFactor?: number\n /** Material factor (2.0: NBR 16868-1, masonry). */\n materialFactor?: number\n /** Thinnest bearing wall in metres (0.14: NBR 16868-1). */\n minThickness?: number\n /** Thicknesses are rounded up to this many metres (0.01). */\n step?: number\n masonry?: MasonryOptions\n}\n\n/**\n * Thickness of a bearing masonry wall storey by storey, ground floor first, as a designer sizes it: the load from the top down (every floor plus the\n * walls above, times `loadFactor`) within `fk / materialFactor` times the slenderness factor of each storey's wall. `Infinity` when a storey cannot be\n * carried at any thickness (the wall's own weight per storey already uses up the strength).\n */\nexport const bearingWallThickness = (options: BearingWallOptions): number[] => {\n const gf = options.loadFactor ?? 1.4\n const gm = options.materialFactor ?? 2\n const min = options.minThickness ?? 0.14\n const step = options.step ?? 0.01\n const fd = ((options.material.strength?.compressiveMPa ?? 0) * MPA) / gm\n const own = options.material.density * GRAVITY * options.storeyHeight\n const out: number[] = []\n let above = 0\n for (let i = 0; i < options.storeys; i++) {\n const n = above + options.floorLoad\n let t = min\n for (let k = 0; k < 60; k++) {\n const room = fd * slendernessFactor(options.storeyHeight, t, options.masonry) - gf * own\n if (room <= 0) {\n // too slender (or too weak) at this thickness: try a thicker wall, give up past 20 m\n t *= 1.25\n if (t > 20) {\n t = Infinity\n break\n }\n continue\n }\n const next = Math.max(min, (gf * n) / room)\n if (Math.abs(next - t) < 1e-5) break\n t = next\n }\n t = Number.isFinite(t) ? Math.ceil(t / step - 1e-9) * step : Infinity\n out.push(t)\n above = n + own * (Number.isFinite(t) ? t : 0)\n }\n return out.reverse()\n}\n","[\n { \"id\": \"rock\", \"kind\": \"rock\", \"allowableKPa\": 3000, \"spt\": 50, \"elasticMPa\": 10000, \"poisson\": 0.2, \"pile\": { \"tipKPa\": 9000, \"skinKPa\": 500 } },\n { \"id\": \"rock_fractured\", \"kind\": \"rock\", \"allowableKPa\": 1500, \"spt\": 50, \"elasticMPa\": 2000, \"poisson\": 0.25, \"pile\": { \"tipKPa\": 4500, \"skinKPa\": 300 } },\n { \"id\": \"gravel_dense\", \"kind\": \"gravel\", \"allowableKPa\": 600, \"spt\": 40, \"elasticMPa\": 132, \"poisson\": 0.3 },\n { \"id\": \"gravel_loose\", \"kind\": \"gravel\", \"allowableKPa\": 300, \"spt\": 8, \"elasticMPa\": 26, \"poisson\": 0.3 },\n { \"id\": \"sand_very_dense\", \"kind\": \"sand\", \"allowableKPa\": 500, \"spt\": 45, \"elasticMPa\": 120, \"poisson\": 0.3 },\n { \"id\": \"sand_dense\", \"kind\": \"sand\", \"allowableKPa\": 400, \"spt\": 25, \"elasticMPa\": 68, \"poisson\": 0.3 },\n { \"id\": \"sand_medium\", \"kind\": \"sand\", \"allowableKPa\": 200, \"spt\": 12, \"elasticMPa\": 32, \"poisson\": 0.3 },\n { \"id\": \"sand_loose\", \"kind\": \"sand\", \"allowableKPa\": 50, \"spt\": 3, \"elasticMPa\": 8, \"poisson\": 0.3 },\n { \"id\": \"silt_hard\", \"kind\": \"silt\", \"allowableKPa\": 300, \"spt\": 25, \"elasticMPa\": 44, \"poisson\": 0.35 },\n { \"id\": \"silt_stiff\", \"kind\": \"silt\", \"allowableKPa\": 200, \"spt\": 15, \"elasticMPa\": 26, \"poisson\": 0.35 },\n { \"id\": \"silt_medium\", \"kind\": \"silt\", \"allowableKPa\": 100, \"spt\": 8, \"elasticMPa\": 14, \"poisson\": 0.35 },\n { \"id\": \"clay_hard\", \"kind\": \"clay\", \"allowableKPa\": 300, \"spt\": 25, \"elasticMPa\": 35, \"poisson\": 0.4 },\n { \"id\": \"clay_stiff\", \"kind\": \"clay\", \"allowableKPa\": 200, \"spt\": 15, \"elasticMPa\": 21, \"poisson\": 0.4 },\n { \"id\": \"clay_medium\", \"kind\": \"clay\", \"allowableKPa\": 100, \"spt\": 8, \"elasticMPa\": 11, \"poisson\": 0.4 },\n { \"id\": \"clay_soft\", \"kind\": \"clay\", \"allowableKPa\": 30, \"spt\": 3, \"elasticMPa\": 4.2, \"poisson\": 0.4 },\n { \"id\": \"clay_very_soft\", \"kind\": \"clay\", \"allowableKPa\": 15, \"spt\": 1, \"elasticMPa\": 1.4, \"poisson\": 0.4 }\n]\n","import soilsJson from './data/soils.json'\nimport type { PileSpec, SoilDef, SoilKind, SoilOptions, SoilProfile } from './types'\n\n/**\n * Soil and foundations. A footing bears on the soil under it as a bed of springs (the subgrade modulus of the elastic settlement of a rigid footing)\n * that give way at the soil's bearing capacity; a pile carries its load by end bearing and skin friction (Décourt-Quaresma) and gives way when the\n * load passes them. The whole object rests on those springs as a rigid body: it settles, leans with the out-of-plumb of the building and with its\n * own weight moving over as it leans (P-delta), and, when the springs cannot hold it, it keeps sinking and leaning until its centre of mass passes\n * the edge of its foundations and it tips over.\n */\n\n/** Built-in soil classes (data in `src/data/soils.json`): NBR 6122 basic pressures, SPT N, moduli from Teixeira & Godoy. */\nexport const SOILS: readonly SoilDef[] = soilsJson as SoilDef[]\n\nexport const SOIL_DEFAULTS = {\n safety: 3,\n pileSafety: 2,\n rigidity: 0.82,\n influence: 2,\n imperfection: 1 / 200,\n cells: 4,\n sinkRate: 0.05,\n tiltRate: 1.5,\n pileElasticGPa: 25,\n footingWidth: 0.6,\n} as const\n\nexport type ResolvedSoil = Required<Omit<SoilOptions, 'soils' | 'site'>> & { site?: string | SoilProfile; byId: Map<string, SoilDef> }\n\nexport const resolveSoil = (o: SoilOptions = {}): ResolvedSoil => {\n const byId = new Map(SOILS.map((s) => [s.id, s]))\n for (const s of o.soils ?? []) byId.set(s.id, s)\n const { soils: _soils, site, ...rest } = o\n return { ...SOIL_DEFAULTS, ...rest, ...(site !== undefined ? { site } : {}), byId }\n}\n\n/** A profile from a soil class id or a profile. */\nexport const profileOf = (soil: string | SoilProfile): SoilProfile => (typeof soil === 'string' ? { layers: [{ soil }] } : soil)\n\n/** The layers of a profile that lie between two depths (metres below the surface), with the thickness of each inside that range. */\nexport const layersBetween = (profile: SoilProfile, top: number, bottom: number, soils: ReadonlyMap<string, SoilDef>): Array<{ soil: SoilDef; thickness: number; top: number }> => {\n const out: Array<{ soil: SoilDef; thickness: number; top: number }> = []\n let z = 0\n const layers = profile.layers\n for (let i = 0; i < layers.length; i++) {\n const def = soils.get(layers[i].soil)\n if (!def) throw new Error(`unknown soil \"${layers[i].soil}\"`)\n const last = i === layers.length - 1\n const end = last ? Infinity : z + Math.max(0, layers[i].thickness ?? 0)\n const a = Math.max(z, top), b = Math.min(end, bottom)\n if (b > a) out.push({ soil: def, thickness: b - a, top: a })\n z = end\n if (z >= bottom) break\n }\n return out\n}\n\n/** The soil class at a depth (metres below the surface). */\nexport const soilAt = (profile: SoilProfile, depth: number, soils: ReadonlyMap<string, SoilDef>): SoilDef => {\n let z = 0\n for (let i = 0; i < profile.layers.length; i++) {\n const def = soils.get(profile.layers[i].soil)\n if (!def) throw new Error(`unknown soil \"${profile.layers[i].soil}\"`)\n z += Math.max(0, profile.layers[i].thickness ?? 0)\n if (i === profile.layers.length - 1 || depth < z) return def\n }\n throw new Error('a soil profile needs at least one layer')\n}\n\n/** The soil a footing of width `width` at `depth` bears on: the weakest allowable pressure and the mean modulus over `influence` widths below it. */\nexport const footingSoil = (profile: SoilProfile, depth: number, width: number, soils: ReadonlyMap<string, SoilDef>, influence: number = SOIL_DEFAULTS.influence) => {\n const zone = layersBetween(profile, depth, depth + Math.max(0.01, influence * width), soils)\n let allowable = Infinity, e = 0, nu = 0, t = 0\n for (const l of zone) {\n allowable = Math.min(allowable, l.soil.allowableKPa)\n e += l.soil.elasticMPa * l.thickness\n nu += l.soil.poisson * l.thickness\n t += l.thickness\n }\n if (t <= 0) {\n const l = soilAt(profile, depth, soils)\n return { allowableKPa: l.allowableKPa, elasticMPa: l.elasticMPa, poisson: l.poisson }\n }\n return { allowableKPa: allowable, elasticMPa: e / t, poisson: nu / t }\n}\n\n/** Décourt-Quaresma coefficient C of the end bearing in kPa per blow (clay 120, silt 200, sand and gravel 400). */\nconst DQ_C: Record<SoilKind, number> = { clay: 120, silt: 200, sand: 400, gravel: 400, rock: 400 }\n/** Décourt (1996) factors of a bored pile on the end bearing (alpha) and the skin friction (beta); a driven pile has 1 and 1. */\nconst BORED: Record<SoilKind, { alpha: number; beta: number }> = {\n clay: { alpha: 0.85, beta: 0.8 },\n silt: { alpha: 0.6, beta: 0.65 },\n sand: { alpha: 0.5, beta: 0.5 },\n gravel: { alpha: 0.5, beta: 0.5 },\n rock: { alpha: 1, beta: 1 },\n}\nconst clampN = (n: number) => Math.min(50, Math.max(3, n))\n\n/**\n * Ultimate resistance of one pile in newtons, by Décourt-Quaresma: end bearing `alpha C N A` at the tip and skin friction `beta 10 (N/3 + 1)` kPa\n * along the shaft in each layer (N limited to 3..50). Rock with `pile` resistances uses those instead. `top` is the depth of the pile head.\n */\nexport const pileCapacity = (profile: SoilProfile, pile: PileSpec, top: number, soils: ReadonlyMap<string, SoilDef>) => {\n const d = pile.diameter\n const area = (Math.PI * d * d) / 4\n const perimeter = Math.PI * d\n const driven = pile.method === 'driven'\n let skin = 0\n for (const l of layersBetween(profile, top, top + pile.length, soils)) {\n const f = driven ? 1 : BORED[l.soil.kind].beta\n const kPa = l.soil.pile?.skinKPa ?? f * 10 * (clampN(l.soil.spt) / 3 + 1)\n skin += kPa * 1000 * perimeter * l.thickness\n }\n const tipDepth = top + pile.length\n const tipSoil = soilAt(profile, tipDepth, soils)\n const alpha = driven ? 1 : BORED[tipSoil.kind].alpha\n const tipKPa = tipSoil.pile?.tipKPa ?? alpha * DQ_C[tipSoil.kind] * clampN(tipSoil.spt)\n const tip = tipKPa * 1000 * area\n return { tip, skin, ultimate: tip + skin, tipSoil }\n}\n\n/**\n * The shortest pile (to `step` metres) whose ultimate resistance over `safety` carries `load` newtons, going down from `top`; `maxLength` if none.\n * This is how a designer takes a pile down to firm ground.\n */\nexport const pileLength = (profile: SoilProfile, o: { load: number; diameter: number; top?: number; method?: PileSpec['method']; safety?: number; step?: number; maxLength?: number; soils?: ReadonlyMap<string, SoilDef> }): number => {\n const soils = o.soils ?? resolveSoil().byId\n const safety = o.safety ?? SOIL_DEFAULTS.pileSafety\n const step = o.step ?? 0.5\n const max = o.maxLength ?? 60\n for (let L = step; L <= max + 1e-9; L += step) {\n if (pileCapacity(profile, { length: L, diameter: o.diameter, ...(o.method ? { method: o.method } : {}) }, o.top ?? 0, soils).ultimate / safety >= o.load) return Math.round(L / step) * step\n }\n return max\n}\n\n/** Stiffness of one pile in N/m: the shaft shortens under the mean of its force (`L / (2 E A)`) in series with the tip as a rigid plate (`E d / (1 - nu^2)`). */\nexport const pileStiffness = (pile: PileSpec, pileElasticGPa: number, tipElasticMPa: number, tipPoisson: number): number => {\n const area = (Math.PI * pile.diameter * pile.diameter) / 4\n const shaft = pile.length / (2 * pileElasticGPa * 1e9 * area)\n const tip = (1 - tipPoisson * tipPoisson) / (tipElasticMPa * 1e6 * pile.diameter)\n return 1 / (shaft + tip)\n}\n\n/** Subgrade modulus in Pa/m of a rigid footing of width `width`: `E / (B (1 - nu^2) Iw)`, the elastic settlement of the footing as springs. */\nexport const subgradeModulus = (elasticMPa: number, poisson: number, width: number, rigidity: number = SOIL_DEFAULTS.rigidity): number =>\n (elasticMPa * 1e6) / (Math.max(0.05, width) * (1 - poisson * poisson) * rigidity)\n\n/**\n * Thickness-free design check of a shallow footing: the area a load of `load` newtons needs on `soil` (allowable pressure), as a designer sizes it.\n */\nexport const footingArea = (load: number, allowableKPa: number): number => load / (allowableKPa * 1000)\n\n/** One support of the object on the ground: a footing cell or a pile, at object-local `x, z`, `hx`/`hz` half its size. */\nexport interface SoilSpring {\n x: number\n z: number\n hx: number\n hz: number\n /** N/m. */\n k: number\n /** Newtons it carries before it gives way. */\n cap: number\n /** Permanent settlement of the soil under it from yielding, metres: it pushes back only past this (default 0). */\n set?: number\n}\n\n/** The springs' permanent settlement after the base moved to `(s, a, b)`: a spring pushed past its capacity keeps the extra (return mapping). */\nexport const yieldSprings = (springs: readonly SoilSpring[], s: number, a: number, b: number): number[] => {\n const [x0, z0] = stiffnessCentre(springs)\n return springs.map((sp) => {\n const set = sp.set ?? 0\n const w = s + a * (sp.x - x0) + b * (sp.z - z0)\n return sp.k * (w - set) > sp.cap ? w - sp.cap / sp.k : set\n })\n}\n\nexport interface FoundationSolve {\n /** Settlement at the centre of stiffness, metres. */\n s: number\n /** Slopes of the base: the foundations go down `a` per metre of x and `b` per metre of z. */\n a: number\n b: number\n /** An equilibrium was found and it is stable. */\n stable: boolean\n /** Some spring is at its capacity in that equilibrium. */\n yielded: boolean\n /** Weight over the sum of the capacities. */\n bearing: number\n /** Largest force over capacity of a spring, 0..1. */\n edge: number\n /** Residual of the vertical force and moments at the end, to tell which way an unstable object moves. */\n residual: [number, number, number]\n}\n\n/** Centre of stiffness of the springs. */\nexport const stiffnessCentre = (springs: readonly SoilSpring[]): [number, number] => {\n let k = 0, x = 0, z = 0\n for (const s of springs) {\n k += s.k\n x += s.k * s.x\n z += s.k * s.z\n }\n return k > 0 ? [x / k, z / k] : [0, 0]\n}\n\n/** Solves `J d = r` for a symmetric 3x3 by Cholesky; null when `J` is not positive definite. */\nconst cholesky3 = (J: number[][], r: number[]): number[] | null => {\n const L = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]\n for (let i = 0; i < 3; i++) {\n for (let j = 0; j <= i; j++) {\n let sum = J[i][j]\n for (let k = 0; k < j; k++) sum -= L[i][k] * L[j][k]\n if (i === j) {\n if (!(sum > 1e-9 * Math.max(1, Math.abs(J[i][i])))) return null\n L[i][i] = Math.sqrt(sum)\n } else L[i][j] = sum / L[j][j]\n }\n }\n const y = [0, 0, 0]\n for (let i = 0; i < 3; i++) {\n let sum = r[i]\n for (let k = 0; k < i; k++) sum -= L[i][k] * y[k]\n y[i] = sum / L[i][i]\n }\n const x = [0, 0, 0]\n for (let i = 2; i >= 0; i--) {\n let sum = y[i]\n for (let k = i + 1; k < 3; k++) sum -= L[k][i] * x[k]\n x[i] = sum / L[i][i]\n }\n return x\n}\n\n/**\n * Equilibrium of a rigid object of weight `weight` (N) on elastic-perfectly-plastic springs that carry no tension, with its centre of mass at\n * `(xg, zg)` and `height` metres above the base, leaning `imperfection` (radians, x and z) before any load and moving over as it leans (P-delta).\n * Newton iterations from `start`; where the tangent is not positive definite the elastic stiffness of the springs in contact is used instead.\n */\nexport const solveFoundation = (\n springs: readonly SoilSpring[],\n weight: number,\n xg: number,\n zg: number,\n height: number,\n imperfection: readonly [number, number],\n start: { s: number; a: number; b: number } = { s: 0, a: 0, b: 0 },\n): FoundationSolve => {\n const [x0, z0] = stiffnessCentre(springs)\n const capSum = springs.reduce((sum, s) => sum + s.cap, 0)\n const span = Math.max(1, ...springs.map((s) => Math.max(Math.abs(s.x - x0) + s.hx, Math.abs(s.z - z0) + s.hz)))\n let s = start.s, a = start.a, b = start.b\n // from a base that touches nothing, start at the elastic settlement of the whole bed\n if (springs.every((sp) => s + a * (sp.x - x0) + b * (sp.z - z0) - (sp.set ?? 0) <= 0)) {\n s = weight / Math.max(1e-9, springs.reduce((sum, sp) => sum + sp.k, 0))\n a = b = 0\n }\n const Wh = weight * height\n const evaluate = () => {\n let F = 0, Mx = 0, Mz = 0, edge = 0, yielded = false\n const Jt = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]\n const Je = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]\n const add = (J: number[][], k: number, dx: number, dz: number) => {\n J[0][0] += k; J[0][1] += k * dx; J[0][2] += k * dz\n J[1][1] += k * dx * dx; J[1][2] += k * dx * dz; J[2][2] += k * dz * dz\n }\n for (const sp of springs) {\n const dx = sp.x - x0, dz = sp.z - z0\n const w = s + a * dx + b * dz - (sp.set ?? 0)\n if (w <= 0) continue\n const f = sp.k * w\n add(Je, sp.k, dx, dz)\n let force = f\n if (f >= sp.cap) {\n force = sp.cap\n yielded = true\n } else add(Jt, sp.k, dx, dz)\n edge = Math.max(edge, force / sp.cap)\n F += force\n Mx += force * dx\n Mz += force * dz\n }\n for (const J of [Jt, Je]) {\n J[1][0] = J[0][1]; J[2][0] = J[0][2]; J[2][1] = J[1][2]\n J[1][1] -= Wh; J[2][2] -= Wh\n }\n const r = [weight - F, weight * (xg - x0 + height * (a + imperfection[0])) - Mx, weight * (zg - z0 + height * (b + imperfection[1])) - Mz]\n return { r, Jt, Je, edge, yielded }\n }\n let ev = evaluate()\n let converged = false\n const tol = 1e-7 * weight\n for (let it = 0; it < 120; it++) {\n if (Math.abs(ev.r[0]) < tol && Math.abs(ev.r[1]) < tol * span && Math.abs(ev.r[2]) < tol * span) {\n converged = true\n break\n }\n const d = cholesky3(ev.Jt, ev.r) ?? cholesky3(ev.Je, ev.r)\n if (!d) break\n s += d[0]\n a += d[1]\n b += d[2]\n if (!Number.isFinite(s + a + b) || Math.abs(a) > 2 || Math.abs(b) > 2) break\n ev = evaluate()\n }\n // a stable equilibrium keeps a positive definite tangent: with every spring under one side yielding the object has nothing left to stop it\n const stable = converged && cholesky3(ev.Jt, [0, 0, 0]) !== null\n return { s, a, b, stable, yielded: ev.yielded, bearing: capSum > 0 ? weight / capSum : Infinity, edge: ev.edge, residual: [ev.r[0], ev.r[1], ev.r[2]] }\n}\n","[\n { \"id\": \"I\", \"zg\": 250, \"b\": { \"A\": 1.1, \"B\": 1.11, \"C\": 1.12 }, \"p\": { \"A\": 0.06, \"B\": 0.065, \"C\": 0.07 }, \"z0\": 0.005 },\n { \"id\": \"II\", \"zg\": 300, \"b\": { \"A\": 1.0, \"B\": 1.0, \"C\": 1.0 }, \"p\": { \"A\": 0.085, \"B\": 0.09, \"C\": 0.1 }, \"z0\": 0.05 },\n { \"id\": \"III\", \"zg\": 350, \"b\": { \"A\": 0.94, \"B\": 0.94, \"C\": 0.93 }, \"p\": { \"A\": 0.1, \"B\": 0.105, \"C\": 0.115 }, \"z0\": 0.3 },\n { \"id\": \"IV\", \"zg\": 420, \"b\": { \"A\": 0.86, \"B\": 0.85, \"C\": 0.84 }, \"p\": { \"A\": 0.12, \"B\": 0.125, \"C\": 0.135 }, \"z0\": 1.0 },\n { \"id\": \"V\", \"zg\": 500, \"b\": { \"A\": 0.74, \"B\": 0.73, \"C\": 0.71 }, \"p\": { \"A\": 0.15, \"B\": 0.16, \"C\": 0.175 }, \"z0\": 2.5 }\n]\n","import windTerrainJson from './data/wind-terrain.json'\nimport { GRAVITY } from './flexure'\nimport { createRng } from './math'\nimport { thinAxisOf } from './layers'\nimport { verticalBarCount } from './rebar'\nimport type { Vec3, WindExposure, WindOptions, WindTerrainDef } from './types'\n\n/**\n * Wind on a building. The wind pressure grows with the height (NBR 6123), the building is cut into storey-high bands, each band takes the force of\n * its area, and the structure that resists it is the walls (a cantilever of composite section) working with the frame (storey shear stiffness) as\n * the wall-frame interaction of Heidebrecht & Stafford Smith. The same stiffness gives the first mode (Rayleigh), and a gust series moves the top\n * against it, with a tuned mass damper if there is one. Pure formulas in SI units (N, m, Pa, s); the world calls them with the parts' boxes.\n */\n\n/** Built-in terrain categories (data in `src/data/wind-terrain.json`): NBR 6123 table 1 and the roughness lengths. */\nexport const WIND_TERRAIN: readonly WindTerrainDef[] = windTerrainJson as WindTerrainDef[]\n\nexport const WIND_DEFAULTS = {\n speed: 40,\n direction: [1, 0, 0] as Vec3,\n terrain: 'III' as NonNullable<WindExposure['terrain']>,\n class: 'auto' as NonNullable<WindExposure['class']>,\n topography: 1,\n statistical: 1,\n drag: 1.3,\n damping: 0.016,\n airDensity: 1.226,\n minHeight: 5,\n bandHeight: 3,\n stiffnessFactor: 0.8,\n beamFactor: 0.4,\n flange: 0.1,\n driftLimit: 1 / 500,\n loadFactor: 1.4,\n chord: false,\n meanRatio: 0.69,\n gustFactor: { A: 1, B: 0.98, C: 0.95 },\n gust: { components: 400, maxHz: 2, scale: 1200, seed: 1 },\n peakDecay: 60,\n tuning: 'den-hartog' as NonNullable<WindOptions['tuning']>,\n} as const\n\nexport type ResolvedWind = Required<Omit<WindOptions, 'terrains' | 'gustFactor' | 'gust' | 'direction'>> & {\n direction: Vec3\n gustFactor: { A: number; B: number; C: number }\n gust: { components: number; maxHz: number; scale: number; seed: number }\n terrains: Map<string, WindTerrainDef>\n}\n\nconst definedOf = <T extends object>(o?: T): Partial<T> => Object.fromEntries(Object.entries(o ?? {}).filter(([, v]) => v !== undefined)) as Partial<T>\n\nexport const resolveWind = (o: WindOptions = {}): ResolvedWind => {\n const terrains = new Map(WIND_TERRAIN.map((t) => [t.id, t]))\n for (const t of o.terrains ?? []) terrains.set(t.id, t)\n const { terrains: _terrains, gustFactor, gust, ...rest } = o\n return {\n ...WIND_DEFAULTS,\n ...definedOf(rest),\n direction: o.direction ?? WIND_DEFAULTS.direction,\n gustFactor: { ...WIND_DEFAULTS.gustFactor, ...definedOf(gustFactor) },\n gust: { ...WIND_DEFAULTS.gust, ...definedOf(gust) },\n terrains,\n }\n}\n\n/** The world's wind with one object's `DestructibleSpec.wind` over it. */\nexport const exposureOf = (w: ResolvedWind, spec?: WindExposure | false): ResolvedWind => (spec ? { ...w, ...definedOf(spec) } : w)\n\n// ---------------------------------------------------------------------------------------------------------------------------------------------\n// Pressure and profile\n// ---------------------------------------------------------------------------------------------------------------------------------------------\n\n/** Dynamic pressure in N/m² of a wind of `speed` m/s: `q = rho V^2 / 2`, which is `0.613 V^2` for the air at 15 °C (NBR 6123 4.2). */\nexport const windPressure = (speed: number, density: number = WIND_DEFAULTS.airDensity): number => 0.5 * density * speed * speed\n\n/** Class of a building by its largest dimension (NBR 6123 table 1): `A` up to 20 m, `B` up to 50 m, `C` above. */\nexport const windClass = (largest: number): 'A' | 'B' | 'C' => (largest <= 20 ? 'A' : largest <= 50 ? 'B' : 'C')\n\n/**\n * Height factor of the gust `S2 = b * Fr * (z / 10)^p` (NBR 6123 5.3), `z` in metres above the ground: at least `minHeight` and at most the gradient\n * height of the category.\n */\nexport const heightFactor = (z: number, terrain: WindTerrainDef, cls: 'A' | 'B' | 'C', o: { gustFactor?: { A: number; B: number; C: number }; minHeight?: number } = {}): number => {\n const zz = Math.min(terrain.zg, Math.max(o.minHeight ?? WIND_DEFAULTS.minHeight, z))\n return terrain.b[cls] * (o.gustFactor ?? WIND_DEFAULTS.gustFactor)[cls] * (zz / 10) ** terrain.p[cls]\n}\n\n/** The same profile for the 10-minute mean wind: no gust factor, times `meanRatio` (the share of the gust the mean is). */\nexport const meanHeightFactor = (z: number, terrain: WindTerrainDef, cls: 'A' | 'B' | 'C', o: { meanRatio?: number; minHeight?: number } = {}): number =>\n (o.meanRatio ?? WIND_DEFAULTS.meanRatio) * heightFactor(z, terrain, cls, { gustFactor: { A: 1, B: 1, C: 1 }, ...(o.minHeight !== undefined ? { minHeight: o.minHeight } : {}) })\n\n/** Turbulence intensity at `z` over terrain of roughness length `z0`: `1 / ln(z / z0)` (EN 1991-1-4 4.4), no more than 0.5. */\nexport const turbulenceIntensity = (z: number, z0: number): number => Math.min(0.5, 1 / Math.log(Math.max(z, 1.5 * z0) / z0))\n\n// ---------------------------------------------------------------------------------------------------------------------------------------------\n// Wall-frame cantilever\n// ---------------------------------------------------------------------------------------------------------------------------------------------\n\nexport interface WallFrameSolution {\n /** Rotation `w'` at the n + 1 nodes. */\n psi: number[]\n /** Deflection at the nodes (0 at the base). */\n w: number[]\n}\n\n/**\n * A cantilever with bending stiffness `ei[j]` (N m²) and shear stiffness `ga[j]` (N) in each band of height `hb[j]`, loaded by the shear `V` at the\n * n + 1 nodes (from the base up; `V[n]` is the shear at the top, 0 when nothing hangs there). The wall and the frame share the load as\n * `-(EI psi')' + GA psi = V`, `psi(0) = 0` (as far as there is a wall), zero moment at the top: linear elements, one per band, a tridiagonal system. Without the frame\n * (`ga` 0) it is the bending cantilever (`w = w H^4 / (8 EI)` for a uniform load), without the wall (`ei` 0) the shear beam (`w' = V / GA`).\n */\nexport const solveWallFrame = (hb: readonly number[], ei: readonly number[], ga: readonly number[], V: readonly number[]): WallFrameSolution => {\n const n = hb.length\n const diag = new Array<number>(n + 1).fill(0)\n const off = new Array<number>(n).fill(0)\n const rhs = new Array<number>(n + 1).fill(0)\n for (let j = 0; j < n; j++) {\n const h = hb[j], e = ei[j], g = ga[j]\n diag[j] += e / h + (g * h) / 3\n diag[j + 1] += e / h + (g * h) / 3\n off[j] = -e / h + (g * h) / 6\n rhs[j] += (h / 6) * (2 * V[j] + V[j + 1])\n rhs[j + 1] += (h / 6) * (V[j] + 2 * V[j + 1])\n }\n // the wall is clamped at the base (psi = 0) as far as there is a wall: a stiff spring on the base node whose weight is the wall's share of the\n // stiffness over one band, so a frame alone is not held back by a boundary layer that no band resolves\n const wall = ei[0] / (ei[0] + ga[0] * hb[0] * hb[0])\n diag[0] += 1e6 * (ei[0] / hb[0] + ga[0] * hb[0]) * wall\n // Thomas algorithm on the nodes 0..n\n const c = new Array<number>(n + 1).fill(0)\n const d = new Array<number>(n + 1).fill(0)\n const psi = new Array<number>(n + 1).fill(0)\n c[0] = off[0] / diag[0]\n d[0] = rhs[0] / diag[0]\n for (let i = 1; i <= n; i++) {\n const m = diag[i] - off[i - 1] * c[i - 1]\n c[i] = i < n ? off[i] / m : 0\n d[i] = (rhs[i] - off[i - 1] * d[i - 1]) / m\n }\n psi[n] = d[n]\n for (let i = n - 1; i >= 0; i--) psi[i] = d[i] - c[i] * psi[i + 1]\n const w = new Array<number>(n + 1).fill(0)\n for (let j = 0; j < n; j++) w[j + 1] = w[j] + (hb[j] * (psi[j] + psi[j + 1])) / 2\n return { psi, w }\n}\n\n/** Shear at the n + 1 nodes of loads `f[j]` spread over each band (the load of the bands above, from the top). */\nexport const shearNodes = (f: readonly number[]): number[] => {\n const V = new Array<number>(f.length + 1).fill(0)\n for (let j = f.length - 1; j >= 0; j--) V[j] = V[j + 1] + f[j]\n return V\n}\n\n/** Moment at the n + 1 nodes from the shear at the nodes (linear inside each band, so the trapezoid is exact). */\nexport const momentNodes = (hb: readonly number[], V: readonly number[]): number[] => {\n const M = new Array<number>(V.length).fill(0)\n for (let j = hb.length - 1; j >= 0; j--) M[j] = M[j + 1] + (hb[j] * (V[j] + V[j + 1])) / 2\n return M\n}\n\n// ---------------------------------------------------------------------------------------------------------------------------------------------\n// Analysis of a building\n// ---------------------------------------------------------------------------------------------------------------------------------------------\n\n/** Factor on the stiffness of the bands above the lateral system, which move as a rigid body with its top. */\nconst RIGID = 1e3\n\nexport interface WindPartInput {\n /** Object-local box of the part (`aabbOf`). */\n min: Vec3\n max: Vec3\n /** `wall` and `column` resist, `beam` frames into the columns, `foundation` is the footprint, `other` only weighs and shows area. */\n kind: 'wall' | 'column' | 'beam' | 'foundation' | 'other'\n /** Young's modulus in Pa (walls, columns, beams). */\n elasticPa?: number\n /** Mass in kg (what rests on it is counted by the parts that rest). */\n mass: number\n /** A tuned mass damper: weighs, but is not part of the modal mass of the building. */\n damper?: boolean\n /** Indices of the beams that frame into this column (closed joints). */\n beams?: readonly number[]\n /** Thickness of the slab that rests on this beam and works with it as a T section (0: none). */\n slab?: number\n}\n\n/** Everything `analyzeWind` needs once it is resolved for one building (`ResolvedWind` with its terrain and direction). */\nexport interface WindCase {\n speed: number\n /** Horizontal unit vector the wind blows towards, object-local `[x, z]`. */\n direction: readonly [number, number]\n terrain: WindTerrainDef\n cls: 'auto' | 'A' | 'B' | 'C'\n topography: number\n statistical: number\n drag: number\n damping: number\n airDensity: number\n minHeight: number\n bandHeight: number\n stiffnessFactor: number\n beamFactor: number\n flange: number\n loadFactor: number\n chord: boolean\n meanRatio: number\n gustFactor: { A: number; B: number; C: number }\n}\n\nexport interface WindAnalysis {\n /** Height of the top above the ground and the class used. */\n height: number\n cls: 'A' | 'B' | 'C'\n /** Largest width across the wind. */\n width: number\n /** Band heights and the height of the middle of each above the ground. */\n bands: number[]\n mid: number[]\n /** Design force on each band, N, and the force of the 10-minute mean wind. */\n forces: number[]\n meanForces: number[]\n /** Design pressure at the top, N/m². */\n pressure: number\n /** Design base shear (N) and overturning moment (N m). */\n shear: number\n moment: number\n /** Top deflection under the design wind (m), over the height, and under the mean wind. */\n deflection: number\n drift: number\n lean: number\n /** Weight, N, and the overturning moment (factored) over the stabilizing moment `W e`. */\n weight: number\n overturn: number\n /** Share of the base moment the walls carry (the rest is the frame's couple). */\n wallShare: number\n /** Bending and shear stiffness of each band (cracked). */\n ei: number[]\n ga: number[]\n /** First mode (Rayleigh): frequency in Hz, angular frequency, modal mass and stiffness, shape at the nodes. */\n frequency: number\n omega: number\n modalMass: number\n modalStiffness: number\n shape: { z: number[]; phi: number[] }\n /** Modal force of the mean wind, N; turbulence intensity for the gust. */\n modalForce: number\n intensity: number\n /** Axial force the design wind adds to each input part, N (compression positive), without the load factor. */\n axial: number[]\n}\n\n/**\n * Second moment of area of a beam of web `bw` and depth `h` with a slab flange of width `bf` and thickness `tf` on top (a T section, about its own\n * centroid); the web alone when there is no flange.\n */\nexport const tBeamInertia = (bw: number, h: number, bf: number, tf: number): number => {\n const web = bw * h\n const fl = Math.max(0, bf - bw) * Math.min(tf, h)\n const t = Math.min(tf, h)\n const yc = (web * (h / 2) + fl * (h - t / 2)) / (web + fl)\n return (bw * h ** 3) / 12 + web * (h / 2 - yc) ** 2 + (Math.max(0, bf - bw) * t ** 3) / 12 + fl * (h - t / 2 - yc) ** 2\n}\n\n/** The shape of the first mode at height `z` above the ground (linear between the nodes). */\nexport const shapeAt = (a: Pick<WindAnalysis, 'shape'>, z: number): number => {\n const { z: zs, phi } = a.shape\n if (z <= zs[0]) return phi[0]\n for (let i = 1; i < zs.length; i++) if (z <= zs[i]) return phi[i - 1] + ((phi[i] - phi[i - 1]) * (z - zs[i - 1])) / (zs[i] - zs[i - 1])\n return phi[phi.length - 1]\n}\n\n/**\n * Wind on a building of `parts` standing on the ground at `ground` (the y of the top of the foundations). Null when it has no wall or column.\n * Bands of `bandHeight`; a part gives to a band the share of itself that lies inside it.\n */\nexport const analyzeWind = (parts: readonly WindPartInput[], c: WindCase, ground: number): WindAnalysis | null => {\n const [dx, dz] = c.direction\n const along = (p: WindPartInput) => {\n const cx = (p.min[0] + p.max[0]) / 2, cz = (p.min[2] + p.max[2]) / 2\n const hx = (p.max[0] - p.min[0]) / 2, hz = (p.max[2] - p.min[2]) / 2\n return {\n u: cx * dx + cz * dz, v: -cx * dz + cz * dx,\n du: 2 * (Math.abs(dx) * hx + Math.abs(dz) * hz), dv: 2 * (Math.abs(dz) * hx + Math.abs(dx) * hz),\n }\n }\n const g = parts.map(along)\n let topY = ground\n let resists = false\n for (const p of parts) {\n if (p.kind === 'foundation') continue\n topY = Math.max(topY, p.max[1])\n if ((p.kind === 'wall' || p.kind === 'column') && p.elasticPa) resists = true\n }\n const height = topY - ground\n if (!(height > 0) || !resists) return null\n const n = Math.max(1, Math.ceil(height / c.bandHeight - 1e-9))\n const bands = Array.from({ length: n }, (_, j) => Math.min(c.bandHeight, height - j * c.bandHeight))\n const z0 = Array.from({ length: n }, (_, j) => j * c.bandHeight)\n const mid = bands.map((h, j) => z0[j] + h / 2)\n const share = (p: WindPartInput, j: number): number => {\n const a = Math.max(p.min[1] - ground, z0[j]), b = Math.min(p.max[1] - ground, z0[j] + bands[j])\n return Math.max(0, b - a)\n }\n\n // the building across the wind, the weight and the section of walls and columns\n const vmin = new Array<number>(n).fill(Infinity), vmax = new Array<number>(n).fill(-Infinity)\n const mass = new Array<number>(n).fill(0)\n let weight = 0, wu = 0\n let footEnd = -Infinity\n let anyFoundation = false\n for (let i = 0; i < parts.length; i++) {\n const p = parts[i]\n weight += p.mass * GRAVITY\n wu += p.mass * g[i].u\n if (p.kind === 'foundation') {\n anyFoundation = true\n footEnd = Math.max(footEnd, g[i].u + g[i].du / 2)\n continue\n }\n const full = Math.max(1e-6, p.max[1] - p.min[1])\n for (let j = 0; j < n; j++) {\n const ov = share(p, j)\n if (ov <= 0) continue\n vmin[j] = Math.min(vmin[j], g[i].v - g[i].dv / 2)\n vmax[j] = Math.max(vmax[j], g[i].v + g[i].dv / 2)\n if (!p.damper) mass[j] += (p.mass * ov) / full\n }\n }\n if (!anyFoundation) for (let i = 0; i < parts.length; i++) if (parts[i].min[1] - ground < 0.1) footEnd = Math.max(footEnd, g[i].u + g[i].du / 2)\n const totalMass = weight / GRAVITY\n const uCg = totalMass > 0 ? wu / totalMass : 0\n const width = vmax.map((hi, j) => (hi > vmin[j] ? hi - vmin[j] : 0))\n const widest = Math.max(...width)\n const cls = c.cls === 'auto' ? windClass(Math.max(height, widest)) : c.cls\n\n // forces on the bands\n const k0 = c.speed * c.topography * c.statistical\n const pressure = mid.map((z) => windPressure(k0 * heightFactor(z, c.terrain, cls, { gustFactor: c.gustFactor, minHeight: c.minHeight }), c.airDensity))\n const meanPressure = mid.map((z) => windPressure(k0 * meanHeightFactor(z, c.terrain, cls, { meanRatio: c.meanRatio, minHeight: c.minHeight }), c.airDensity))\n const forces = bands.map((h, j) => pressure[j] * c.drag * width[j] * h)\n const meanForces = bands.map((h, j) => meanPressure[j] * c.drag * width[j] * h)\n const V = shearNodes(forces)\n const M = momentNodes(bands, V)\n\n // the lateral system: walls as one section, columns as a shear frame\n const ea = new Array<number>(n).fill(0), eau = new Array<number>(n).fill(0)\n const vertical: number[] = []\n for (let i = 0; i < parts.length; i++) {\n const p = parts[i]\n if ((p.kind !== 'wall' && !(p.kind === 'column' && c.chord)) || !p.elasticPa) continue\n vertical.push(i)\n const area = g[i].du * g[i].dv\n const e = p.elasticPa * c.stiffnessFactor\n for (let j = 0; j < n; j++) {\n const w = share(p, j) / bands[j]\n if (w <= 0) continue\n ea[j] += e * area * w\n eau[j] += e * area * g[i].u * w\n }\n }\n const centre = ea.map((v, j) => (v > 0 ? eau[j] / v : 0))\n const ei = new Array<number>(n).fill(0)\n const ga = new Array<number>(n).fill(0)\n for (const i of vertical) {\n const p = parts[i]\n const e = p.elasticPa! * c.stiffnessFactor\n for (let j = 0; j < n; j++) {\n const w = share(p, j) / bands[j]\n if (w <= 0) continue\n ei[j] += e * ((g[i].du ** 3 * g[i].dv) / 12 + g[i].du * g[i].dv * (g[i].u - centre[j]) ** 2) * w\n }\n }\n for (let i = 0; i < parts.length; i++) {\n const p = parts[i]\n if (p.kind !== 'column' || !p.elasticPa) continue\n const h = Math.max(1e-6, p.max[1] - p.min[1])\n const kc = (p.elasticPa * c.stiffnessFactor * (g[i].du ** 3 * g[i].dv) / 12) / h\n let beams = 0\n for (const b of p.beams ?? []) {\n const q = parts[b]\n if (!q?.elasticPa) continue\n const hx = q.max[0] - q.min[0], hz = q.max[2] - q.min[2]\n const long = Math.max(hx, hz), short = Math.min(hx, hz)\n const cos = hx >= hz ? Math.abs(dx) : Math.abs(dz)\n const depth = q.max[1] - q.min[1]\n const inertia = tBeamInertia(short, depth, short + 2 * c.flange * long, q.slab ?? 0)\n beams += (cos * cos * q.elasticPa * c.beamFactor * inertia) / Math.max(long, 1e-6)\n }\n const k = beams / kc\n const base = p.min[1] - ground < 0.05\n const a = base ? (0.5 + k) / (2 + k) : k / (2 + k)\n const stiffness = (a * 12 * (p.elasticPa * c.stiffnessFactor) * ((g[i].du ** 3 * g[i].dv) / 12)) / (h * h)\n for (let j = 0; j < n; j++) ga[j] += (stiffness * share(p, j)) / bands[j]\n }\n // what stands above the highest wall or column (a roof, its trusses) is carried by them and moves with their top: nothing bends there\n let last = -1\n for (let j = 0; j < n; j++) if (ei[j] > 0 || ga[j] > 0) last = j\n for (let j = last + 1; j < n && last >= 0; j++) {\n ei[j] = ei[last] * RIGID\n ga[j] = ga[last] * RIGID\n }\n const tiny = 1\n const eiS = ei.map((v) => Math.max(v, tiny))\n const gaS = ga.map((v) => Math.max(v, tiny))\n const sol = solveWallFrame(bands, eiS, gaS, V)\n const deflection = sol.w[n]\n const lean = solveWallFrame(bands, eiS, gaS, shearNodes(meanForces)).w[n]\n\n // what the walls and the frame each carry\n const kappa = bands.map((h, j) => (sol.psi[j + 1] - sol.psi[j]) / h)\n const Mmid = bands.map((h, j) => M[j + 1] + (h / 2) * (V[j + 1] + (V[j] + V[j + 1]) / 2) / 2)\n const Mwall = ei.map((v, j) => Math.min(Mmid[j], Math.max(0, v * kappa[j])))\n const axial = new Array<number>(parts.length).fill(0)\n for (const i of vertical) {\n const p = parts[i]\n let sum = 0, tot = 0\n for (let j = 0; j < n; j++) {\n const w = share(p, j)\n if (w <= 0) continue\n sum += w * p.elasticPa! * c.stiffnessFactor * kappa[j] * g[i].du * g[i].dv * (g[i].u - centre[j])\n tot += w\n }\n axial[i] = tot > 0 ? sum / tot : 0\n }\n if (!c.chord) {\n // the frame carries the rest of the moment as a couple of the columns: forces in proportion to `A d` from their centroid\n const colA = new Array<number>(n).fill(0), colAu = new Array<number>(n).fill(0)\n const cols: number[] = []\n for (let i = 0; i < parts.length; i++) {\n if (parts[i].kind !== 'column') continue\n cols.push(i)\n for (let j = 0; j < n; j++) {\n const w = share(parts[i], j) / bands[j]\n colA[j] += g[i].du * g[i].dv * w\n colAu[j] += g[i].du * g[i].dv * g[i].u * w\n }\n }\n const colC = colA.map((a, j) => (a > 0 ? colAu[j] / a : 0))\n const colI = new Array<number>(n).fill(0)\n for (const i of cols) for (let j = 0; j < n; j++) colI[j] += (g[i].du * g[i].dv * (g[i].u - colC[j]) ** 2 * share(parts[i], j)) / bands[j]\n for (const i of cols) {\n let sum = 0, tot = 0\n for (let j = 0; j < n; j++) {\n const w = share(parts[i], j)\n if (w <= 0 || colI[j] <= 0) continue\n sum += w * (Math.max(0, Mmid[j] - Mwall[j]) * g[i].du * g[i].dv * (g[i].u - colC[j])) / colI[j]\n tot += w\n }\n axial[i] = tot > 0 ? sum / tot : 0\n }\n }\n\n // stability: overturning moment against the weight over the leeward edge of the foundations\n const arm = footEnd - uCg\n const overturn = arm > 0 ? (c.loadFactor * M[0]) / (weight * arm) : Infinity\n\n // first mode, Rayleigh: the shape under a load equal to the mass of each band\n const mode = solveWallFrame(bands, eiS, gaS, shearNodes(mass))\n const top = mode.w[n]\n const um = bands.map((_, j) => (mode.w[j] + mode.w[j + 1]) / 2)\n let mu = 0, muu = 0\n mass.forEach((m, j) => {\n mu += m * um[j]\n muu += m * um[j] * um[j]\n })\n const omega = muu > 0 ? Math.sqrt(mu / muu) : 0\n const phi = um.map((u) => (top > 0 ? u / top : 0))\n const modalMass = mass.reduce((s, m, j) => s + m * phi[j] * phi[j], 0)\n const modalForce = meanForces.reduce((s, f, j) => s + f * phi[j], 0)\n const z = [0, ...bands.map((_, j) => z0[j] + bands[j])]\n const intensity = turbulenceIntensity(Math.max(0.6 * height, c.minHeight), c.terrain.z0)\n\n return {\n height, cls, width: widest, bands, mid, forces, meanForces, pressure: pressure[n - 1], shear: V[0], moment: M[0], deflection, drift: deflection / height, lean,\n weight, overturn, wallShare: M[0] > 0 ? Mwall[0] / M[0] : 0, ei, ga, frequency: omega / (2 * Math.PI), omega, modalMass, modalStiffness: omega * omega * modalMass,\n shape: { z, phi: mode.w.map((w) => (top > 0 ? w / top : 0)) }, modalForce, intensity, axial,\n }\n}\n\n// ---------------------------------------------------------------------------------------------------------------------------------------------\n// Tuned mass damper\n// ---------------------------------------------------------------------------------------------------------------------------------------------\n\n/**\n * Optimal tuning of a damper of mass ratio `mu` (damper mass over the modal mass): its frequency over the building's and its damping ratio.\n * `den-hartog` (1956): `1 / (1 + mu)` and `sqrt(3 mu / (8 (1 + mu)^3))`, for a harmonic force on an undamped structure. `warburton` (1982): for a random\n * force, `sqrt(1 - mu / 2) / (1 + mu)` and `sqrt(mu (1 - mu / 4) / (4 (1 + mu) (1 - mu / 2)))`.\n */\nexport const damperTuning = (mu: number, kind: 'den-hartog' | 'warburton' = 'den-hartog'): { frequency: number; damping: number } =>\n kind === 'warburton'\n ? { frequency: Math.sqrt(1 - mu / 2) / (1 + mu), damping: Math.sqrt((mu * (1 - mu / 4)) / (4 * (1 + mu) * (1 - mu / 2))) }\n : { frequency: 1 / (1 + mu), damping: Math.sqrt((3 * mu) / (8 * (1 + mu) ** 3)) }\n\n/**\n * Amplitude of the structure under a harmonic force over its static deflection, with a damper: `r` the forcing frequency over the structure's,\n * `mu` the mass ratio, `g` the damper's frequency over the structure's, `damper` and `structure` the damping ratios. Solves\n * `[(1 - r^2 + 2 i zs r) - mu A r^2 / (A - r^2)] X = 1` with `A = g^2 + 2 i zd g r`. `mu` 0 is the structure alone (`1 / (2 zs)` at resonance).\n */\nexport const damperAmplification = (r: number, mu: number, g: number, damper: number, structure = 0): number => {\n // complex arithmetic by hand: numbers as [re, im]\n const mul = (a: [number, number], b: [number, number]): [number, number] => [a[0] * b[0] - a[1] * b[1], a[0] * b[1] + a[1] * b[0]]\n const div = (a: [number, number], b: [number, number]): [number, number] => {\n const d = b[0] * b[0] + b[1] * b[1]\n return [(a[0] * b[0] + a[1] * b[1]) / d, (a[1] * b[0] - a[0] * b[1]) / d]\n }\n const A: [number, number] = [g * g, 2 * damper * g * r]\n const main: [number, number] = [1 - r * r, 2 * structure * r]\n const coupling = mu > 0 ? mul([mu * r * r, 0], div(A, [A[0] - r * r, A[1]])) : ([0, 0] as [number, number])\n const total: [number, number] = [main[0] - coupling[0], main[1] - coupling[1]]\n return 1 / Math.hypot(total[0], total[1])\n}\n\n// ---------------------------------------------------------------------------------------------------------------------------------------------\n// Gust and sway\n// ---------------------------------------------------------------------------------------------------------------------------------------------\n\n/** A gust series: sines of equal frequency spacing whose amplitudes follow the Davenport spectrum, normalized to unit variance. */\nexport interface Gust {\n freq: number[]\n amp: number[]\n phase: number[]\n}\n\n/**\n * The turbulence at the 10 m mean speed `v10`: `components` sines up to `maxHz`, amplitudes from the Davenport spectrum `f S(f) / u*^2 = 4 x^2 / (1 + x^2)^(4/3)`,\n * `x = scale f / v10` (NBR 6123 chapter 9, Simiu & Scanlan), phases from the seed.\n */\nexport const makeGust = (v10: number, o: { components: number; maxHz: number; scale: number; seed: number }): Gust => {\n const rng = createRng(o.seed)\n const n = Math.max(1, Math.floor(o.components))\n const df = o.maxHz / n\n const freq = Array.from({ length: n }, (_, k) => (k + 0.5) * df)\n const weight = freq.map((f) => {\n const x = (o.scale * f) / Math.max(v10, 1e-6)\n return ((4 * x * x) / (1 + x * x) ** (4 / 3) / f) * df\n })\n const sum = weight.reduce((s, w) => s + w, 0)\n return { freq, amp: weight.map((w) => Math.sqrt((2 * w) / sum)), phase: freq.map(() => rng.next() * 2 * Math.PI) }\n}\n\n/** The gust at time `t`: zero mean, unit variance. */\nexport const gustAt = (gust: Gust, t: number): number => {\n let s = 0\n for (let k = 0; k < gust.freq.length; k++) s += gust.amp[k] * Math.cos(2 * Math.PI * gust.freq[k] * t + gust.phase[k])\n return s\n}\n\n/** The first mode of a building with an optional tuned mass damper: modal mass, stiffness and damping, and the damper's mass, stiffness and dashpot. */\nexport interface SwaySystem {\n M: number\n K: number\n C: number\n damper?: { m: number; k: number; c: number }\n}\n\n/** Displacement and velocity of the top, and of the damper's mass (absolute). */\nexport interface SwayState {\n x: number\n v: number\n y: number\n w: number\n}\n\n/** Advances `s` by `dt` seconds under the force `force(t)` (N, on the modal mass), RK4 with steps no longer than `maxStep`. */\nexport const stepSway = (s: SwayState, sys: SwaySystem, t: number, dt: number, force: (t: number) => number, maxStep = Infinity): void => {\n const steps = Math.max(1, Math.ceil(dt / maxStep - 1e-9))\n const h = dt / steps\n const d = sys.damper\n const f = (x: number, v: number, y: number, w: number, tt: number): [number, number, number, number] => {\n const fd = d ? d.k * (y - x) + d.c * (w - v) : 0\n return [v, (force(tt) - sys.K * x - sys.C * v + fd) / sys.M, d ? w : 0, d ? -fd / d.m : 0]\n }\n for (let i = 0; i < steps; i++) {\n const tt = t + i * h\n const k1 = f(s.x, s.v, s.y, s.w, tt)\n const k2 = f(s.x + (h / 2) * k1[0], s.v + (h / 2) * k1[1], s.y + (h / 2) * k1[2], s.w + (h / 2) * k1[3], tt + h / 2)\n const k3 = f(s.x + (h / 2) * k2[0], s.v + (h / 2) * k2[1], s.y + (h / 2) * k2[2], s.w + (h / 2) * k2[3], tt + h / 2)\n const k4 = f(s.x + h * k3[0], s.v + h * k3[1], s.y + h * k3[2], s.w + h * k3[3], tt + h)\n s.x += (h / 6) * (k1[0] + 2 * k2[0] + 2 * k3[0] + k4[0])\n s.v += (h / 6) * (k1[1] + 2 * k2[1] + 2 * k3[1] + k4[1])\n s.y += (h / 6) * (k1[2] + 2 * k2[2] + 2 * k3[2] + k4[2])\n s.w += (h / 6) * (k1[3] + 2 * k2[3] + 2 * k3[3] + k4[3])\n }\n}\n\n// ---------------------------------------------------------------------------------------------------------------------------------------------\n// Tension of walls and columns\n// ---------------------------------------------------------------------------------------------------------------------------------------------\n\n/**\n * Force in newtons a wall or column holds in tension: its vertical rebar at yield (`reinforcement` bars, or `ratio` of the section) when it has any,\n * else the tensile strength of its material times the section, else nothing (a masonry wall does not pull).\n */\nexport const tensionCapacity = (\n dims: Vec3, o: { reinforcement?: { spacing: number; diameter: number }; ratio?: number; yieldMPa: number; tensileMPa?: number },\n): number => {\n const section = dims[0] * dims[2]\n if (o.reinforcement) {\n const bars = verticalBarCount(dims, thinAxisOf(dims), o.reinforcement.spacing)\n return bars * Math.PI * (o.reinforcement.diameter / 2) ** 2 * o.yieldMPa * 1e6\n }\n if (o.ratio) return o.ratio * section * o.yieldMPa * 1e6\n return (o.tensileMPa ?? 0) * 1e6 * section\n}\n","[\n {\n \"id\": \"steel\",\n \"density\": 7850,\n \"hpPerKg\": 400,\n \"penetration\": 110,\n \"penetrationClass\": \"steel\",\n \"penetrationScale\": 1.3,\n \"ductility\": 0.9,\n \"fracture\": \"none\",\n \"damageScale\": {\n \"slash\": 0.1,\n \"blunt\": 0.8\n },\n \"hitDebris\": \"sparks\",\n \"breakDebris\": \"sparks\",\n \"ricochetDeg\": 20,\n \"thermal\": {\n \"meltC\": 1450,\n \"meltRate\": 0.05,\n \"conductivity\": 0.5,\n \"heatCapacity\": 3\n },\n \"visual\": {\n \"glows\": true\n },\n \"tags\": [\n \"metal\",\n \"conductive\"\n ],\n \"compressive\": 2000000\n },\n {\n \"id\": \"cast_iron\",\n \"density\": 7200,\n \"hpPerKg\": 150,\n \"penetration\": 160,\n \"penetrationClass\": \"steel\",\n \"penetrationScale\": 1.0,\n \"ductility\": 0.2,\n \"fracture\": \"snap\",\n \"fragmentSize\": [\n 0.08,\n 0.3\n ],\n \"damageScale\": {\n \"slash\": 0.1,\n \"blunt\": 1.2\n },\n \"hitDebris\": \"sparks\",\n \"breakDebris\": \"chips\",\n \"ricochetDeg\": 15,\n \"thermal\": {\n \"meltC\": 1200,\n \"meltRate\": 0.05,\n \"conductivity\": 0.45,\n \"heatCapacity\": 3\n },\n \"visual\": {\n \"glows\": true\n },\n \"tags\": [\n \"metal\",\n \"conductive\"\n ],\n \"compressive\": 1500000\n },\n {\n \"id\": \"aluminium\",\n \"density\": 2700,\n \"hpPerKg\": 250,\n \"penetration\": 60,\n \"penetrationClass\": \"steel\",\n \"penetrationScale\": 3,\n \"ductility\": 0.85,\n \"fracture\": \"none\",\n \"damageScale\": {\n \"slash\": 0.2\n },\n \"hitDebris\": \"sparks\",\n \"breakDebris\": \"sparks\",\n \"ricochetDeg\": 15,\n \"thermal\": {\n \"meltC\": 660,\n \"meltRate\": 0.06,\n \"conductivity\": 0.8,\n \"heatCapacity\": 1.5\n },\n \"visual\": {\n \"glows\": true\n },\n \"tags\": [\n \"metal\",\n \"conductive\"\n ],\n \"compressive\": 800000\n },\n {\n \"id\": \"copper\",\n \"density\": 8960,\n \"hpPerKg\": 300,\n \"penetration\": 70,\n \"penetrationClass\": \"steel\",\n \"penetrationScale\": 1.5,\n \"ductility\": 0.95,\n \"fracture\": \"none\",\n \"damageScale\": {\n \"slash\": 0.2\n },\n \"hitDebris\": \"sparks\",\n \"breakDebris\": \"sparks\",\n \"ricochetDeg\": 15,\n \"thermal\": {\n \"meltC\": 1085,\n \"meltRate\": 0.05,\n \"conductivity\": 1,\n \"heatCapacity\": 2.5\n },\n \"visual\": {\n \"glows\": true\n },\n \"tags\": [\n \"metal\",\n \"conductive\"\n ],\n \"compressive\": 1000000\n },\n {\n \"id\": \"wood_soft\",\n \"splitForm\": \"slivers\",\n \"density\": 500,\n \"hpPerKg\": 90,\n \"penetration\": 9,\n \"penetrationClass\": \"wood\",\n \"penetrationScale\": 1.5,\n \"ductility\": 0.35,\n \"fracture\": \"splinter\",\n \"fragmentSize\": [\n 0.03,\n 0.15\n ],\n \"damageScale\": {\n \"blunt\": 1.2,\n \"slash\": 1.5\n },\n \"hitDebris\": \"splinters\",\n \"breakDebris\": \"splinters\",\n \"thermal\": {\n \"ignitionC\": 300,\n \"flameC\": 800,\n \"fuelFraction\": 0.9,\n \"burnRate\": 0.012,\n \"conductivity\": 0.05,\n \"heatCapacity\": 1.2,\n \"smoke\": \"grey\"\n },\n \"visual\": {\n \"charColor\": 1709072,\n \"innerColor\": 14730131\n },\n \"tags\": [\n \"wood\",\n \"organic\",\n \"flammable\"\n ],\n \"compressive\": 100000,\n \"hits\": {\n \"blunt\": {\n \"tear\": \"splinters\",\n \"tearJoules\": 60\n }\n }\n },\n {\n \"id\": \"wood_hard\",\n \"splitForm\": \"slivers\",\n \"density\": 750,\n \"hpPerKg\": 140,\n \"penetration\": 14,\n \"penetrationClass\": \"wood\",\n \"penetrationScale\": 1,\n \"ductility\": 0.3,\n \"fracture\": \"splinter\",\n \"fragmentSize\": [\n 0.03,\n 0.2\n ],\n \"damageScale\": {\n \"slash\": 1.2\n },\n \"hitDebris\": \"splinters\",\n \"breakDebris\": \"splinters\",\n \"thermal\": {\n \"ignitionC\": 330,\n \"flameC\": 800,\n \"fuelFraction\": 0.9,\n \"burnRate\": 0.01,\n \"conductivity\": 0.06,\n \"heatCapacity\": 1.4,\n \"smoke\": \"grey\"\n },\n \"visual\": {\n \"charColor\": 1709072,\n \"innerColor\": 13213802\n },\n \"tags\": [\n \"wood\",\n \"organic\",\n \"flammable\"\n ],\n \"compressive\": 150000,\n \"hits\": {\n \"blunt\": {\n \"tear\": \"splinters\",\n \"tearJoules\": 150\n }\n }\n },\n {\n \"id\": \"plywood\",\n \"splitForm\": \"plies\",\n \"density\": 600,\n \"hpPerKg\": 70,\n \"penetration\": 7,\n \"penetrationClass\": \"wood\",\n \"penetrationScale\": 2,\n \"ductility\": 0.3,\n \"fracture\": \"snap\",\n \"fragmentSize\": [\n 0.1,\n 0.4\n ],\n \"damageScale\": {\n \"slash\": 1.3\n },\n \"hitDebris\": \"splinters\",\n \"breakDebris\": \"splinters\",\n \"thermal\": {\n \"ignitionC\": 300,\n \"flameC\": 800,\n \"fuelFraction\": 0.85,\n \"burnRate\": 0.013,\n \"conductivity\": 0.05,\n \"heatCapacity\": 1.2,\n \"smoke\": \"grey\"\n },\n \"visual\": {\n \"charColor\": 1709072,\n \"innerColor\": 14862234\n },\n \"tags\": [\n \"wood\",\n \"organic\",\n \"flammable\"\n ],\n \"compressive\": 60000,\n \"hits\": {\n \"ballistic\": {\n \"tear\": \"splinters\"\n },\n \"blunt\": {\n \"tear\": \"splinters\",\n \"tearJoules\": 80\n }\n }\n },\n {\n \"id\": \"mdf\",\n \"splitForm\": \"granules\",\n \"density\": 750,\n \"hpPerKg\": 45,\n \"penetration\": 6,\n \"penetrationClass\": \"wood\",\n \"penetrationScale\": 2.5,\n \"ductility\": 0.15,\n \"fracture\": \"snap\",\n \"fragmentSize\": [\n 0.08,\n 0.35\n ],\n \"hitDebris\": \"chips\",\n \"breakDebris\": \"dust\",\n \"thermal\": {\n \"ignitionC\": 290,\n \"flameC\": 750,\n \"fuelFraction\": 0.85,\n \"burnRate\": 0.014,\n \"conductivity\": 0.05,\n \"heatCapacity\": 1.2,\n \"smoke\": \"grey\"\n },\n \"visual\": {\n \"charColor\": 1709072,\n \"innerColor\": 12096362\n },\n \"tags\": [\n \"wood\",\n \"organic\",\n \"flammable\"\n ],\n \"compressive\": 30000,\n \"hits\": {\n \"ballistic\": {\n \"tear\": \"lumps\",\n \"tearJoules\": 120\n },\n \"blunt\": {\n \"tear\": \"lumps\",\n \"tearJoules\": 20\n }\n }\n },\n {\n \"id\": \"glass\",\n \"density\": 2500,\n \"hpPerKg\": 12,\n \"penetration\": 6,\n \"ductility\": 0.02,\n \"fracture\": \"shatter\",\n \"fragmentSize\": [\n 0.05,\n 0.25\n ],\n \"damageScale\": {\n \"blunt\": 1.5,\n \"shelter\": 3\n },\n \"hitDebris\": \"shards\",\n \"breakDebris\": \"shards\",\n \"ricochetDeg\": 8,\n \"thermal\": {\n \"meltC\": 1400,\n \"meltRate\": 0.03,\n \"conductivity\": 0.1,\n \"heatCapacity\": 1.5,\n \"thermalShockC\": 150\n },\n \"visual\": {\n \"glows\": true,\n \"transparent\": true\n },\n \"tags\": [\n \"glass\",\n \"brittle\"\n ],\n \"compressive\": 100000\n },\n {\n \"id\": \"tempered_glass\",\n \"density\": 2500,\n \"hpPerKg\": 30,\n \"penetration\": 9,\n \"ductility\": 0.02,\n \"fracture\": \"crumble\",\n \"fragmentSize\": [\n 0.006,\n 0.02\n ],\n \"hitDebris\": \"shards\",\n \"breakDebris\": \"shards\",\n \"ricochetDeg\": 8,\n \"thermal\": {\n \"meltC\": 1400,\n \"meltRate\": 0.03,\n \"conductivity\": 0.1,\n \"heatCapacity\": 1.5,\n \"thermalShockC\": 250\n },\n \"visual\": {\n \"glows\": true,\n \"transparent\": true\n },\n \"tags\": [\n \"glass\",\n \"brittle\"\n ],\n \"compressive\": 200000,\n \"damageScale\": {\n \"shelter\": 3\n }\n },\n {\n \"id\": \"ceramic\",\n \"density\": 2400,\n \"hpPerKg\": 25,\n \"penetration\": 12,\n \"ductility\": 0.02,\n \"fracture\": \"shatter\",\n \"fragmentSize\": [\n 0.03,\n 0.12\n ],\n \"damageScale\": {\n \"blunt\": 1.3\n },\n \"hitDebris\": \"chips\",\n \"breakDebris\": \"shards\",\n \"thermal\": {\n \"conductivity\": 0.1,\n \"heatCapacity\": 1.5,\n \"thermalShockC\": 200\n },\n \"tags\": [\n \"ceramic\",\n \"brittle\"\n ],\n \"compressive\": 150000\n },\n {\n \"id\": \"concrete\",\n \"density\": 2300,\n \"hpPerKg\": 14,\n \"penetration\": 18,\n \"penetrationClass\": \"concrete\",\n \"penetrationScale\": 1,\n \"ductility\": 0.03,\n \"fracture\": \"crumble\",\n \"fragmentSize\": [\n 0.05,\n 0.25\n ],\n \"damageScale\": {\n \"explosive\": 1.2\n },\n \"hits\": {\n \"ballistic\": {\n \"unitJoules\": 500,\n \"floor\": 900,\n \"crater\": true\n },\n \"blunt\": {\n \"unitJoules\": 1500,\n \"floor\": 60\n }\n },\n \"ricochetDeg\": 12,\n \"hitDebris\": \"chips\",\n \"breakDebris\": \"dust\",\n \"visual\": { \"innerColor\": 10197652 },\n \"thermal\": {\n \"conductivity\": 0.15,\n \"heatCapacity\": 2.5\n },\n \"tags\": [\n \"masonry\",\n \"brittle\"\n ],\n \"compressive\": 444000,\n \"strength\": {\n \"compressiveMPa\": 25,\n \"tensileMPa\": 2.56,\n \"elasticGPa\": 28\n }\n },\n {\n \"id\": \"brick\",\n \"density\": 1900,\n \"hpPerKg\": 12,\n \"penetration\": 14,\n \"penetrationClass\": \"brick\",\n \"penetrationScale\": 1,\n \"ductility\": 0.05,\n \"fracture\": \"crumble\",\n \"fragmentSize\": [\n 0.04,\n 0.12\n ],\n \"ricochetDeg\": 10,\n \"hitDebris\": \"chips\",\n \"breakDebris\": \"dust\",\n \"visual\": { \"innerColor\": 12085567 },\n \"thermal\": {\n \"conductivity\": 0.15,\n \"heatCapacity\": 2.5\n },\n \"tags\": [\n \"masonry\",\n \"brittle\"\n ],\n \"compressive\": 40000,\n \"strength\": {\n \"compressiveMPa\": 2.35,\n \"tensileMPa\": 0.1,\n \"elasticGPa\": 2.35\n }\n },\n {\n \"id\": \"plaster\",\n \"density\": 850,\n \"hpPerKg\": 18,\n \"penetration\": 3,\n \"penetrationClass\": \"brick\",\n \"penetrationScale\": 3,\n \"ductility\": 0.05,\n \"fracture\": \"crumble\",\n \"fragmentSize\": [\n 0.05,\n 0.3\n ],\n \"hitDebris\": \"dust\",\n \"breakDebris\": \"dust\",\n \"visual\": { \"innerColor\": 14999507 },\n \"thermal\": {\n \"conductivity\": 0.1,\n \"heatCapacity\": 1.5\n },\n \"tags\": [\n \"masonry\",\n \"brittle\"\n ],\n \"compressive\": 8000\n },\n {\n \"id\": \"stone\",\n \"density\": 2700,\n \"hpPerKg\": 25,\n \"penetration\": 25,\n \"penetrationClass\": \"concrete\",\n \"penetrationScale\": 0.9,\n \"ductility\": 0.03,\n \"fracture\": \"crumble\",\n \"fragmentSize\": [\n 0.06,\n 0.3\n ],\n \"ricochetDeg\": 15,\n \"hitDebris\": \"chips\",\n \"breakDebris\": \"dust\",\n \"visual\": { \"innerColor\": 9407364 },\n \"thermal\": {\n \"conductivity\": 0.2,\n \"heatCapacity\": 2.5\n },\n \"tags\": [\n \"masonry\",\n \"brittle\"\n ],\n \"compressive\": 300000\n },\n {\n \"id\": \"plastic\",\n \"density\": 1100,\n \"hpPerKg\": 60,\n \"penetration\": 8,\n \"ductility\": 0.5,\n \"fracture\": \"snap\",\n \"fragmentSize\": [\n 0.05,\n 0.3\n ],\n \"hitDebris\": \"chips\",\n \"breakDebris\": \"chips\",\n \"thermal\": {\n \"ignitionC\": 400,\n \"flameC\": 700,\n \"fuelFraction\": 0.8,\n \"burnRate\": 0.02,\n \"meltC\": 200,\n \"meltRate\": 0.06,\n \"conductivity\": 0.05,\n \"heatCapacity\": 1,\n \"smoke\": \"black\"\n },\n \"visual\": {\n \"charColor\": 855309\n },\n \"tags\": [\n \"plastic\",\n \"flammable\"\n ],\n \"compressive\": 40000\n },\n {\n \"id\": \"rubber\",\n \"density\": 1100,\n \"hpPerKg\": 80,\n \"penetration\": 12,\n \"ductility\": 0.9,\n \"fracture\": \"tear\",\n \"fragmentSize\": [\n 0.05,\n 0.2\n ],\n \"hitDebris\": \"chips\",\n \"breakDebris\": \"fibers\",\n \"thermal\": {\n \"ignitionC\": 350,\n \"flameC\": 750,\n \"fuelFraction\": 0.6,\n \"burnRate\": 0.015,\n \"conductivity\": 0.05,\n \"heatCapacity\": 1.2,\n \"smoke\": \"black\"\n },\n \"visual\": {\n \"charColor\": 855309\n },\n \"tags\": [\n \"rubber\",\n \"flammable\"\n ],\n \"compressive\": 20000\n },\n {\n \"id\": \"fabric\",\n \"density\": 400,\n \"hpPerKg\": 20,\n \"penetration\": 0.8,\n \"ductility\": 0.8,\n \"fracture\": \"tear\",\n \"fragmentSize\": [\n 0.05,\n 0.25\n ],\n \"damageScale\": {\n \"slash\": 4,\n \"ballistic\": 0.5\n },\n \"hitDebris\": \"fibers\",\n \"breakDebris\": \"fibers\",\n \"thermal\": {\n \"ignitionC\": 230,\n \"flameC\": 600,\n \"fuelFraction\": 1,\n \"burnRate\": 0.05,\n \"conductivity\": 0.03,\n \"heatCapacity\": 0.6,\n \"smoke\": \"grey\"\n },\n \"visual\": {\n \"charColor\": 1709072\n },\n \"tags\": [\n \"fabric\",\n \"organic\",\n \"flammable\"\n ],\n \"compressive\": 500\n },\n {\n \"id\": \"foam\",\n \"density\": 30,\n \"hpPerKg\": 15,\n \"penetration\": 0.5,\n \"ductility\": 0.7,\n \"fracture\": \"tear\",\n \"fragmentSize\": [\n 0.03,\n 0.15\n ],\n \"damageScale\": {\n \"slash\": 2,\n \"ballistic\": 0.4\n },\n \"hitDebris\": \"fibers\",\n \"breakDebris\": \"fibers\",\n \"thermal\": {\n \"ignitionC\": 250,\n \"flameC\": 900,\n \"fuelFraction\": 0.95,\n \"burnRate\": 0.09,\n \"conductivity\": 0.02,\n \"heatCapacity\": 0.5,\n \"smoke\": \"black\"\n },\n \"visual\": {\n \"charColor\": 855309\n },\n \"tags\": [\n \"fabric\",\n \"flammable\"\n ],\n \"compressive\": 100\n },\n {\n \"id\": \"leather\",\n \"density\": 900,\n \"hpPerKg\": 50,\n \"penetration\": 4,\n \"ductility\": 0.8,\n \"fracture\": \"tear\",\n \"fragmentSize\": [\n 0.05,\n 0.25\n ],\n \"damageScale\": {\n \"slash\": 2\n },\n \"hitDebris\": \"fibers\",\n \"breakDebris\": \"fibers\",\n \"thermal\": {\n \"ignitionC\": 320,\n \"flameC\": 650,\n \"fuelFraction\": 0.7,\n \"burnRate\": 0.01,\n \"conductivity\": 0.05,\n \"heatCapacity\": 1,\n \"smoke\": \"grey\"\n },\n \"visual\": {\n \"charColor\": 1709072\n },\n \"tags\": [\n \"fabric\",\n \"organic\",\n \"flammable\"\n ],\n \"compressive\": 2000\n },\n {\n \"id\": \"paper\",\n \"density\": 700,\n \"hpPerKg\": 8,\n \"penetration\": 0.3,\n \"ductility\": 0.5,\n \"fracture\": \"tear\",\n \"fragmentSize\": [\n 0.03,\n 0.15\n ],\n \"sheet\": 0.001,\n \"damageScale\": {\n \"slash\": 3\n },\n \"hitDebris\": \"fibers\",\n \"breakDebris\": \"fibers\",\n \"thermal\": {\n \"ignitionC\": 230,\n \"flameC\": 600,\n \"fuelFraction\": 1,\n \"burnRate\": 0.06,\n \"conductivity\": 0.03,\n \"heatCapacity\": 0.5,\n \"smoke\": \"grey\"\n },\n \"visual\": {\n \"charColor\": 1709072,\n \"innerColor\": 15524048\n },\n \"tags\": [\n \"fabric\",\n \"organic\",\n \"flammable\"\n ],\n \"compressive\": 500\n },\n {\n \"id\": \"foliage\",\n \"density\": 150,\n \"hpPerKg\": 20,\n \"penetration\": 0.5,\n \"ductility\": 0.6,\n \"fracture\": \"tear\",\n \"fragmentSize\": [\n 0.03,\n 0.1\n ],\n \"damageScale\": {\n \"slash\": 4\n },\n \"hitDebris\": \"leaves\",\n \"breakDebris\": \"leaves\",\n \"thermal\": {\n \"ignitionC\": 300,\n \"flameC\": 700,\n \"fuelFraction\": 0.8,\n \"burnRate\": 0.08,\n \"conductivity\": 0.03,\n \"heatCapacity\": 0.8,\n \"smoke\": \"white\"\n },\n \"visual\": {\n \"charColor\": 1709072\n },\n \"tags\": [\n \"plant\",\n \"organic\",\n \"flammable\"\n ],\n \"compressive\": 500\n },\n {\n \"id\": \"green_wood\",\n \"splitForm\": \"slivers\",\n \"density\": 650,\n \"hpPerKg\": 5,\n \"penetration\": 10,\n \"penetrationClass\": \"wood\",\n \"penetrationScale\": 1.2,\n \"ductility\": 0.5,\n \"fracture\": \"splinter\",\n \"fragmentSize\": [\n 0.03,\n 0.2\n ],\n \"damageScale\": {\n \"slash\": 1.3,\n \"ballistic\": 0.1\n },\n \"hitDebris\": \"splinters\",\n \"breakDebris\": \"leaves\",\n \"thermal\": {\n \"ignitionC\": 400,\n \"flameC\": 700,\n \"fuelFraction\": 0.8,\n \"burnRate\": 0.006,\n \"conductivity\": 0.06,\n \"heatCapacity\": 2,\n \"smoke\": \"white\"\n },\n \"visual\": {\n \"charColor\": 1709072,\n \"innerColor\": 14207126\n },\n \"tags\": [\n \"plant\",\n \"wood\",\n \"organic\",\n \"flammable\"\n ],\n \"compressive\": 60000,\n \"hits\": {\n \"blunt\": {\n \"tear\": \"none\"\n }\n }\n },\n {\n \"id\": \"cactus\",\n \"density\": 900,\n \"hpPerKg\": 30,\n \"penetration\": 2,\n \"ductility\": 0.6,\n \"fracture\": \"tear\",\n \"fragmentSize\": [\n 0.04,\n 0.15\n ],\n \"damageScale\": {\n \"slash\": 3\n },\n \"hitDebris\": \"fibers\",\n \"breakDebris\": \"fibers\",\n \"thermal\": {\n \"ignitionC\": 450,\n \"flameC\": 650,\n \"fuelFraction\": 0.3,\n \"burnRate\": 0.01,\n \"conductivity\": 0.05,\n \"heatCapacity\": 3,\n \"smoke\": \"white\"\n },\n \"visual\": {\n \"charColor\": 1709072\n },\n \"tags\": [\n \"plant\",\n \"organic\",\n \"flammable\"\n ],\n \"compressive\": 5000\n },\n {\n \"id\": \"flesh_fruit\",\n \"density\": 950,\n \"hpPerKg\": 15,\n \"penetration\": 1.5,\n \"ductility\": 0.7,\n \"fracture\": \"tear\",\n \"fragmentSize\": [\n 0.02,\n 0.08\n ],\n \"damageScale\": {\n \"slash\": 2\n },\n \"hitDebris\": \"drips\",\n \"breakDebris\": \"drips\",\n \"thermal\": {\n \"conductivity\": 0.05,\n \"heatCapacity\": 3\n },\n \"tags\": [\n \"plant\",\n \"organic\"\n ],\n \"compressive\": 1000\n },\n {\n \"id\": \"wax\",\n \"density\": 900,\n \"hpPerKg\": 30,\n \"penetration\": 3,\n \"ductility\": 0.5,\n \"fracture\": \"snap\",\n \"fragmentSize\": [\n 0.05,\n 0.2\n ],\n \"hitDebris\": \"chips\",\n \"breakDebris\": \"chips\",\n \"thermal\": {\n \"ignitionC\": 230,\n \"flameC\": 700,\n \"fuelFraction\": 0.9,\n \"burnRate\": 0.02,\n \"meltC\": 60,\n \"meltRate\": 0.2,\n \"conductivity\": 0.05,\n \"heatCapacity\": 0.8,\n \"smoke\": \"grey\"\n },\n \"tags\": [\n \"wax\",\n \"flammable\"\n ],\n \"compressive\": 5000\n },\n {\n \"id\": \"soil\",\n \"density\": 1300,\n \"hpPerKg\": 3,\n \"penetration\": 5,\n \"ductility\": 0.3,\n \"fracture\": \"crumble\",\n \"fragmentSize\": [\n 0.03,\n 0.12\n ],\n \"hitDebris\": \"dust\",\n \"breakDebris\": \"dust\",\n \"thermal\": {\n \"conductivity\": 0.1,\n \"heatCapacity\": 2.5\n },\n \"tags\": [\n \"soil\",\n \"masonry\"\n ],\n \"compressive\": 20000\n },\n {\n \"id\": \"asphalt\",\n \"density\": 2350,\n \"hpPerKg\": 10,\n \"penetration\": 14,\n \"penetrationClass\": \"concrete\",\n \"penetrationScale\": 0.8,\n \"ductility\": 0.1,\n \"fracture\": \"crumble\",\n \"fragmentSize\": [\n 0.03,\n 0.15\n ],\n \"ricochetDeg\": 8,\n \"hitDebris\": \"chips\",\n \"breakDebris\": \"dust\",\n \"thermal\": {\n \"conductivity\": 0.1,\n \"heatCapacity\": 2,\n \"ignitionC\": 400,\n \"burnRate\": 0.002,\n \"smoke\": \"black\"\n },\n \"tags\": [\n \"masonry\",\n \"brittle\"\n ],\n \"compressive\": 30000\n },\n {\n \"id\": \"sand\",\n \"density\": 1600,\n \"hpPerKg\": 2,\n \"penetration\": 6,\n \"ductility\": 0.4,\n \"fracture\": \"crumble\",\n \"fragmentSize\": [\n 0.01,\n 0.04\n ],\n \"hitDebris\": \"dust\",\n \"breakDebris\": \"dust\",\n \"thermal\": {\n \"conductivity\": 0.1,\n \"heatCapacity\": 2\n },\n \"tags\": [\n \"soil\"\n ],\n \"compressive\": 10000\n },\n {\n \"id\": \"gravel\",\n \"density\": 1800,\n \"hpPerKg\": 3,\n \"penetration\": 8,\n \"ductility\": 0.3,\n \"fracture\": \"crumble\",\n \"fragmentSize\": [\n 0.02,\n 0.06\n ],\n \"hitDebris\": \"chips\",\n \"breakDebris\": \"dust\",\n \"thermal\": {\n \"conductivity\": 0.1,\n \"heatCapacity\": 2\n },\n \"tags\": [\n \"soil\",\n \"masonry\"\n ],\n \"compressive\": 20000\n },\n {\n \"id\": \"turf\",\n \"density\": 900,\n \"hpPerKg\": 3,\n \"penetration\": 4,\n \"ductility\": 0.5,\n \"fracture\": \"crumble\",\n \"fragmentSize\": [\n 0.03,\n 0.1\n ],\n \"hitDebris\": \"dust\",\n \"breakDebris\": \"dust\",\n \"thermal\": {\n \"conductivity\": 0.1,\n \"heatCapacity\": 1.5,\n \"ignitionC\": 250,\n \"burnRate\": 0.03,\n \"smoke\": \"white\"\n },\n \"tags\": [\n \"soil\",\n \"organic\"\n ],\n \"compressive\": 15000\n },\n {\n \"id\": \"mortar\",\n \"density\": 1900,\n \"hpPerKg\": 10,\n \"penetration\": 12,\n \"penetrationClass\": \"concrete\",\n \"penetrationScale\": 1.2,\n \"ductility\": 0.03,\n \"fracture\": \"crumble\",\n \"fragmentSize\": [\n 0.02,\n 0.08\n ],\n \"ricochetDeg\": 8,\n \"hitDebris\": \"chips\",\n \"breakDebris\": \"dust\",\n \"thermal\": {\n \"conductivity\": 0.15,\n \"heatCapacity\": 2.5\n },\n \"tags\": [\n \"masonry\",\n \"brittle\"\n ],\n \"compressive\": 100000\n },\n {\n \"id\": \"mud\",\n \"density\": 1700,\n \"hpPerKg\": 1,\n \"penetration\": 5,\n \"ductility\": 0.8,\n \"fracture\": \"crumble\",\n \"fragmentSize\": [\n 0.02,\n 0.08\n ],\n \"hitDebris\": \"dust\",\n \"breakDebris\": \"dust\",\n \"thermal\": {\n \"conductivity\": 0.5,\n \"heatCapacity\": 3.2\n },\n \"tags\": [\n \"soil\",\n \"wet\"\n ],\n \"compressive\": 5000\n },\n {\n \"id\": \"clay\",\n \"density\": 1800,\n \"hpPerKg\": 5,\n \"penetration\": 7,\n \"ductility\": 0.05,\n \"fracture\": \"crumble\",\n \"fragmentSize\": [\n 0.02,\n 0.1\n ],\n \"hitDebris\": \"chips\",\n \"breakDebris\": \"dust\",\n \"thermal\": {\n \"conductivity\": 0.15,\n \"heatCapacity\": 2.2\n },\n \"tags\": [\n \"soil\",\n \"brittle\"\n ],\n \"compressive\": 60000\n },\n {\n \"id\": \"snow\",\n \"density\": 300,\n \"hpPerKg\": 1,\n \"penetration\": 3,\n \"ductility\": 0.6,\n \"fracture\": \"crumble\",\n \"fragmentSize\": [\n 0.01,\n 0.05\n ],\n \"hitDebris\": \"dust\",\n \"breakDebris\": \"dust\",\n \"thermal\": {\n \"conductivity\": 0.1,\n \"heatCapacity\": 2.1\n },\n \"tags\": [\n \"soil\",\n \"frozen\"\n ],\n \"compressive\": 1000\n },\n {\n \"id\": \"cobble\",\n \"density\": 2650,\n \"hpPerKg\": 25,\n \"penetration\": 25,\n \"penetrationClass\": \"concrete\",\n \"penetrationScale\": 0.9,\n \"ductility\": 0.03,\n \"fracture\": \"crumble\",\n \"fragmentSize\": [\n 0.05,\n 0.15\n ],\n \"ricochetDeg\": 15,\n \"hitDebris\": \"chips\",\n \"breakDebris\": \"chips\",\n \"thermal\": {\n \"conductivity\": 0.2,\n \"heatCapacity\": 2.5\n },\n \"tags\": [\n \"masonry\",\n \"brittle\"\n ],\n \"compressive\": 300000\n },\n {\n \"id\": \"paver\",\n \"density\": 2300,\n \"hpPerKg\": 14,\n \"penetration\": 18,\n \"penetrationClass\": \"concrete\",\n \"penetrationScale\": 1,\n \"ductility\": 0.03,\n \"fracture\": \"crumble\",\n \"fragmentSize\": [\n 0.04,\n 0.12\n ],\n \"ricochetDeg\": 12,\n \"hitDebris\": \"chips\",\n \"breakDebris\": \"chips\",\n \"thermal\": {\n \"conductivity\": 0.15,\n \"heatCapacity\": 2.5\n },\n \"tags\": [\n \"masonry\",\n \"brittle\"\n ],\n \"compressive\": 350000\n }\n]\n","{\n \"cast iron\": \"cast_iron\",\n \"cast_iron\": \"cast_iron\",\n \"castiron\": \"cast_iron\",\n \"metal\": \"steel\",\n \"steel\": \"steel\",\n \"iron\": \"steel\",\n \"chrome\": \"steel\",\n \"alumin\": \"aluminium\",\n \"alu_\": \"aluminium\",\n \"alu-\": \"aluminium\",\n \"alu \": \"aluminium\",\n \"copper\": \"copper\",\n \"brass\": \"copper\",\n \"bronze\": \"copper\",\n \"wood\": \"wood_soft\",\n \"timber\": \"wood_soft\",\n \"plank\": \"wood_soft\",\n \"lumber\": \"wood_soft\",\n \"pine\": \"wood_soft\",\n \"hardwood\": \"wood_hard\",\n \"oak\": \"wood_hard\",\n \"plywood\": \"plywood\",\n \"mdf\": \"mdf\",\n \"chipboard\": \"mdf\",\n \"glass\": \"glass\",\n \"window\": \"glass\",\n \"mirror\": \"glass\",\n \"tempered\": \"tempered_glass\",\n \"windshield\": \"tempered_glass\",\n \"fabric\": \"fabric\",\n \"cloth\": \"fabric\",\n \"cushion\": \"fabric\",\n \"sofa\": \"fabric\",\n \"curtain\": \"fabric\",\n \"carpet\": \"fabric\",\n \"textile\": \"fabric\",\n \"canvas\": \"fabric\",\n \"foam\": \"foam\",\n \"sponge\": \"foam\",\n \"mattress\": \"foam\",\n \"leather\": \"leather\",\n \"paper\": \"paper\",\n \"cardboard\": \"paper\",\n \"leaf\": \"foliage\",\n \"leaves\": \"foliage\",\n \"foliage\": \"foliage\",\n \"bush\": \"foliage\",\n \"grass\": \"foliage\",\n \"trunk\": \"green_wood\",\n \"branch\": \"green_wood\",\n \"twig\": \"green_wood\",\n \"cactus\": \"cactus\",\n \"fruit\": \"flesh_fruit\",\n \"apple\": \"flesh_fruit\",\n \"melon\": \"flesh_fruit\",\n \"wax\": \"wax\",\n \"candle\": \"wax\",\n \"concrete\": \"concrete\",\n \"cement\": \"concrete\",\n \"brick\": \"brick\",\n \"tile\": \"ceramic\",\n \"ceramic\": \"ceramic\",\n \"porcelain\": \"ceramic\",\n \"stone\": \"stone\",\n \"rock\": \"stone\",\n \"marble\": \"stone\",\n \"plaster\": \"plaster\",\n \"drywall\": \"plaster\",\n \"gypsum\": \"plaster\",\n \"plastic\": \"plastic\",\n \"pvc\": \"plastic\",\n \"acrylic\": \"plastic\",\n \"rubber\": \"rubber\",\n \"tire\": \"rubber\",\n \"tyre\": \"rubber\",\n \"soil\": \"soil\",\n \"dirt\": \"soil\",\n \"potting\": \"soil\",\n \"mud\": \"soil\"\n}","import materialsJson from './data/materials.json'\nimport hintsJson from './data/material-hints.json'\nimport { aabbOf, quatFromEuler, shapeDims } from './math'\nimport { GRAVITY, isSlender, resolveFlexure, resolveMasonry, slendernessFactor } from './flexure'\nimport { thinAxisOf } from './layers'\nimport { rebarBars } from './rebar'\nimport type { FlexureOptions, JointKind, JointSpec, MasonryOptions, MaterialDef, MaterialId, PartShape, PartSpec, ToolKind } from './types'\n\n/** Built-in materials (data in `src/data/materials.json`). Override or extend with the `materials` option of `createDestruction`. */\nexport const MATERIALS: MaterialDef[] = materialsJson as unknown as MaterialDef[]\n\n/** Default joint strength (joint hit points), tools that undo it and seconds of tool work. */\nexport const JOINT_DEFAULTS: Record<JointKind, { strength: number; tools: ToolKind[]; seconds: number }> = {\n screw: { strength: 80, tools: ['screwdriver'], seconds: 2.5 },\n bolt: { strength: 200, tools: ['wrench'], seconds: 4 },\n nail: { strength: 60, tools: ['pry_bar', 'hammer'], seconds: 2 },\n weld: { strength: 600, tools: ['cutting_torch', 'saw'], seconds: 8 },\n glue: { strength: 50, tools: ['pry_bar', 'knife'], seconds: 3 },\n hinge: { strength: 120, tools: ['screwdriver'], seconds: 3 },\n clip: { strength: 20, tools: ['hand'], seconds: 0.6 },\n tie: { strength: 15, tools: ['knife', 'hand'], seconds: 1 },\n mortar: { strength: 400, tools: ['hammer'], seconds: 6 },\n fused: { strength: 1000, tools: [], seconds: 0 },\n stem: { strength: 40, tools: ['knife', 'saw', 'hand'], seconds: 1.5 },\n rebar: { strength: 1500, tools: ['cutting_torch', 'saw'], seconds: 20 },\n resting: { strength: 30, tools: ['hand'], seconds: 1 },\n}\n\nconst has = (m: MaterialDef, tag: string) => !!m.tags && m.tags.includes(tag)\n\n/**\n * The joint kind that fits two materials: glass is glued (clipped to plastic), soft things are tied, plants share a stem, masonry gets mortar,\n * metal is welded, wood is screwed, plastic clips. `inferJoints` refines weld to bolt for thick metal and screw to nail for thin wood.\n */\nexport const JOINT_BY_MATERIALS = (a: MaterialDef, b: MaterialDef): JointKind => {\n const any = (tag: string) => has(a, tag) || has(b, tag)\n const both = (tag: string) => has(a, tag) && has(b, tag)\n if (any('glass')) return any('plastic') ? 'clip' : 'glue'\n if (any('fabric')) return 'tie'\n if (both('plant')) return 'stem'\n if (any('plant')) return 'tie'\n if (both('masonry')) return 'mortar'\n if (any('masonry') && any('metal')) return 'bolt'\n if (both('metal')) return 'weld'\n if (any('plastic')) return 'clip'\n if (any('rubber') || any('wax')) return 'glue'\n return 'screw'\n}\n\nconst MATERIAL_MAP: ReadonlyMap<MaterialId, MaterialDef> = new Map(MATERIALS.map((m) => [m.id, m]))\n\nconst HINTS = Object.entries(hintsJson as Record<string, string>).sort((x, y) => y[0].length - x[0].length)\n\n/** Guess a material id from a mesh or node name (case-insensitive substring; the longest keyword wins). */\nexport const guessMaterial = (name: string): MaterialId | undefined => {\n const n = name.toLowerCase()\n for (const [key, id] of HINTS) if (n.includes(key)) return id\n return undefined\n}\n\n/** Volume of a shape in m³. */\nexport const partVolume = (shape: PartShape): number => {\n if (shape.kind === 'box') return shape.size[0] * shape.size[1] * shape.size[2]\n if (shape.kind === 'cylinder') return Math.PI * shape.radius * shape.radius * shape.height\n return (4 / 3) * Math.PI * shape.radius ** 3\n}\n\n/** Mass of a part in kg: its `mass`, or density × volume × fill. */\nexport const partMass = (part: PartSpec, material: MaterialDef): number => part.mass ?? material.density * partVolume(part.shape) * (part.fill ?? 1)\n\n/** Wall thickness of a part in metres (see `PartSpec.thickness`). */\nexport const partThickness = (part: PartSpec): number => {\n const dims = shapeDims(part.shape)\n const min = Math.min(dims[0], dims[1], dims[2])\n return Math.max(1e-4, Math.min(part.thickness ?? min * (part.fill ?? 1), min))\n}\n\n/**\n * Joints for touching parts. Two parts touch when their axis-aligned bounds (after rotation), grown by `tolerance` metres, overlap. The kind comes\n * from `JOINT_BY_MATERIALS`; thick metal pairs (smallest dimension of both >= 2 cm) get a `bolt` instead of a `weld`, and thin wood pairs (either\n * under 2 cm) a `nail` instead of a `screw`.\n */\nexport const inferJoints = (parts: PartSpec[], tolerance = 0.01, materials: ReadonlyMap<string, MaterialDef> = MATERIAL_MAP): JointSpec[] => {\n const boxes = parts.map((p) => aabbOf(p.shape, p.position, quatFromEuler(...(p.rotation ?? [0, 0, 0]))))\n const out: JointSpec[] = []\n for (let i = 0; i < parts.length; i++) {\n for (let j = i + 1; j < parts.length; j++) {\n const a = boxes[i], b = boxes[j]\n let touch = true\n for (let k = 0; k < 3 && touch; k++) if (a.min[k] - tolerance > b.max[k] || b.min[k] - tolerance > a.max[k]) touch = false\n if (!touch) continue\n const ma = materials.get(parts[i].material)\n const mb = materials.get(parts[j].material)\n let kind: JointKind = ma && mb ? JOINT_BY_MATERIALS(ma, mb) : 'screw'\n const thin = Math.min(partThickness(parts[i]), partThickness(parts[j]))\n if (kind === 'weld' && thin >= 0.02) kind = 'bolt'\n if (kind === 'screw' && ma && mb && has(ma, 'wood') && has(mb, 'wood') && thin < 0.02) kind = 'nail'\n out.push({ id: `${parts[i].id}~${parts[j].id}`, a: parts[i].id, b: parts[j].id, kind })\n }\n }\n return out\n}\n\n/**\n * Load in kg a structural part carries before it fails in compression: `structure.capacity`, else the section times the material's strength. The\n * section is the product of the two smallest dimensions (thickness times longest dimension for slabs; thickness times horizontal length for walls);\n * foundations get x10. With `material.strength` (real values) the strength is `compressiveMPa`: a slender masonry or plain concrete wall or pillar keeps\n * `slendernessFactor` of it (the unavoidable eccentricity and its height over thickness), a reinforced pillar carries `0.85 * fck * Ac + As * fy`\n * (NBR 6118). Without it, the game-tuned `material.compressive` (default 20 000 kg/m²).\n */\nexport const partCapacity = (part: PartSpec, material: MaterialDef, options: { masonry?: MasonryOptions; flexure?: FlexureOptions } = {}): number => {\n if (part.structure?.capacity !== undefined) return part.structure.capacity\n const d = shapeDims(part.shape).sort((a, b) => a - b)\n const role = part.structure?.role\n const sh = shapeDims(part.shape)\n const section = role === 'wall' || role === 'partition' ? Math.min(sh[0], sh[2]) * Math.max(sh[0], sh[2]) : role === 'slab' ? d[0] * d[2] : d[0] * d[1]\n const foundation = role === 'foundation' ? 10 : 1\n const strength = material.strength\n if (!strength) return Math.max(1, section * (material.compressive ?? 20000) * foundation)\n const fc = strength.compressiveMPa * 1e6\n let newtons = fc * section\n const upright = role === 'wall' || role === 'partition' || role === 'column'\n if (upright && isSlender(part, material)) newtons *= slendernessFactor(sh[1], Math.min(sh[0], sh[2]), options.masonry)\n else if (role === 'column' && part.reinforcement) {\n const m = resolveMasonry(options.masonry)\n const bars = rebarBars(sh, thinAxisOf(sh), part.reinforcement.spacing).length\n const steel = bars * Math.PI * (part.reinforcement.diameter / 2) ** 2\n newtons = m.concreteFactor * fc * section + steel * resolveFlexure(options.flexure).rebarYieldMPa * 1e6\n }\n return Math.max(1, (newtons / GRAVITY) * foundation)\n}\n\n\n/**\n * Multiplier of blunt damage on brittle parts (ductility < 0.3): up to x4.7 for fully brittle materials (glass, ceramic, stone), times a thinness\n * term that follows bending stress (1 / thickness squared, x1 at 2 cm or more, at most x25). A 3 mm glass bottle breaks from a 1.5 m drop; a\n * concrete block (thick) is only ever x4.4.\n */\nexport const fragility = (ductility: number, thickness: number): number => {\n if (ductility >= 0.3) return 1\n return (1 + (4 * (0.3 - ductility)) / 0.3) * Math.min(25, Math.max(1, (0.02 / Math.max(thickness, 1e-4)) ** 2))\n}\n","import type { Vec3 } from './destruction'\n\n/**\n * The numbers of the shove a blast gives to a body that moves (a loose item, a piece of furniture, a person): all of them a game value, with a default that reads well in a room,\n * not a physical table. A host reads them once and lends them to the modules that move their own bodies (`ModuleHost.blastShove`).\n */\nexport interface BlastShoveOptions {\n /**\n * The share of the blast energy that reaches a body as motion: the speed at the centre is `sqrt(2 * energy * coupling / mass)`, before the falloff (default 0.02).\n */\n readonly coupling?: number\n /** Fastest a body is thrown, in m/s, at the centre of the blast (default 20). */\n readonly maxSpeed?: number\n /** How much of the push goes up: the direction is `(away, lift)` normalised from the horizontal outward direction (default 0.3). */\n readonly lift?: number\n /** Below this speed (m/s) nothing moves: a heavy thing far from a small blast stays where it is (default 0.3). */\n readonly minSpeed?: number\n /** Exponent of the falloff `(1 - distance / radius) ^ power`, the same as the damage of the destruction world (default 2). */\n readonly falloffPower?: number\n}\n\n/** The defaults of `BlastShoveOptions`. */\nexport const DEFAULT_BLAST_SHOVE: Readonly<Required<BlastShoveOptions>> = { coupling: 0.02, maxSpeed: 20, lift: 0.3, minSpeed: 0.3, falloffPower: 2 }\n\n/** A blast as the shove reads it: where, how much energy (J) and how far it reaches (m). `reach` (0..1) is the share that got through what stood in the way. */\nexport interface BlastSource {\n readonly point: Vec3\n readonly energy: number\n readonly radius: number\n readonly reach?: number\n /**\n * Kilograms of TNT equivalent of the charge. With it a body is pushed by the blast wave itself (`blast-impulse`), and the shove of loose items keeps this module's rule; without it the body\n * takes the charge from `energy` by `BlastImpulseOptions.tntPerJoule`.\n */\n readonly tnt?: number\n /** Inside this radius (metres) the blast is lethal: a body there that the blast reaches (not behind cover) goes down, wounded, wherever the wave pushed it. */\n readonly lethalRadius?: number\n}\n\n/** What a blast does to one body: how fast it leaves (m/s), the unit direction it leaves in, and how far from the centre it was. */\nexport interface BlastShove {\n readonly speed: number\n readonly direction: Vec3\n readonly distance: number\n /** The falloff applied, 0..1. */\n readonly falloff: number\n}\n\nconst clampShare = (share: number): number => Math.min(1, Math.max(0, share))\n\n/**\n * The shove a blast gives to a body of `mass` kg whose centre is at `position`: away from the centre, lifted a little, with the speed\n * `sqrt(reach) * min(maxSpeed, sqrt(2 * energy * coupling / mass)) * (1 - distance / radius) ^ 2`. Undefined when the body is outside the radius or the speed is under `minSpeed`.\n * The same rule moves the loose items and furniture of the test room and the people of the characters module, so a game that tunes the options tunes all of them.\n */\nexport function blastShove(blast: BlastSource, target: { readonly position: Vec3; readonly mass: number }, options: BlastShoveOptions = {}): BlastShove | undefined {\n const o = { ...DEFAULT_BLAST_SHOVE, ...options }\n const dx = target.position[0] - blast.point[0]\n const dy = target.position[1] - blast.point[1]\n const dz = target.position[2] - blast.point[2]\n const distance = Math.hypot(dx, dy, dz)\n if (!(blast.radius > 0) || distance > blast.radius) return undefined\n const falloff = (1 - distance / blast.radius) ** o.falloffPower\n const mass = Math.max(target.mass, 0.05)\n // cover takes its share off the push itself, past the cap too: a light thing behind a cupboard is not thrown as fast as one in the open\n const reach = clampShare(blast.reach ?? 1)\n const speed = Math.sqrt(reach) * Math.min(o.maxSpeed, Math.sqrt((2 * blast.energy * o.coupling) / mass)) * falloff\n if (!(speed >= o.minSpeed)) return undefined\n // straight above or below the centre there is no \"away\": the push goes up\n const direction: Vec3 = distance > 1e-4 ? [dx / distance, dy / distance + o.lift, dz / distance] : [0, 1, 0]\n const length = Math.hypot(direction[0], direction[1], direction[2])\n return { speed, direction: [direction[0] / length, direction[1] / length, direction[2] / length], distance, falloff }\n}\n","/**\n * The push a blast gives a standing body, from the physics of the blast wave and not from a game coupling: the impulse of the wave per square metre at a distance from a charge of\n * `tnt` kg of TNT equivalent (Kinney and Graham's fit of the side-on impulse, scaled by the cube root of the charge), reflected on the body, over the area the body shows the wave,\n * divided by its mass. A hand grenade at 3 m gives a person a few tenths of a metre per second; what floors that person is the fragments, not the wave. A big charge close throws.\n */\n\n/** The numbers of the body a blast wave pushes. All have a default for a standing adult. */\nexport interface BlastImpulseOptions {\n /** Square metres of the body the wave meets: about 1.75 m tall by 0.4 m wide (default 0.7). */\n readonly bodyArea?: number\n /** How much of the push goes up: the direction is `(away, lift)` normalised (default 0.15: the wave runs along the ground). */\n readonly lift?: number\n /** Below this speed (m/s) the body does not move (default 0.3). */\n readonly minSpeed?: number\n /**\n * Kilograms of TNT per joule of the blast `energy`, for a blast that does not say its charge (`BlastSource.tnt`). Default 0.24 / 200000: the arsenal's energy scale, where the M67 (180 g\n * of Composition B, 0.24 kg of TNT) is 200 kJ. It is a game equivalence for blasts without a charge, not a physical constant.\n */\n readonly tntPerJoule?: number\n}\n\nexport const DEFAULT_BLAST_IMPULSE: Readonly<Required<BlastImpulseOptions>> = { bodyArea: 0.7, lift: 0.15, minSpeed: 0.3, tntPerJoule: 0.24 / 200000 }\n\n/** Closest distance (m) the fit is read at: inside it the charge is in contact and the body is torn apart anyway. */\nconst NEAREST = 0.3\n\n/**\n * Side-on (incident) specific impulse of the wave, in Pa·s, at `distance` metres from `tnt` kg of TNT in free air: Kinney and Graham, \"Explosive Shocks in Air\" (1985),\n * `I/W^(1/3) = 0.067 sqrt(1 + (Z/0.23)^4) / (Z^2 (1 + (Z/1.55)^3)^(1/3))` bar·ms per kg^(1/3), with the scaled distance `Z = R / W^(1/3)`.\n */\nexport function sideOnImpulse(tnt: number, distance: number): number {\n if (!(tnt > 0)) return 0\n const w3 = Math.cbrt(tnt)\n const z = Math.max(distance, NEAREST) / w3\n const scaled = (0.067 * Math.sqrt(1 + (z / 0.23) ** 4)) / (z * z * Math.cbrt(1 + (z / 1.55) ** 3))\n return scaled * w3 * 100 // bar·ms to Pa·s\n}\n\n/** Sea-level atmospheric pressure, Pa. */\nconst ATMOSPHERE = 101325\n\n/**\n * Peak side-on (incident) overpressure of the wave, in Pa, at `distance` metres from `tnt` kg of TNT in free air: Kinney and Graham, \"Explosive Shocks in Air\" (1985),\n * `Ps/Pa = 808 (1 + (Z/4.5)^2) / (sqrt(1 + (Z/0.048)^2) sqrt(1 + (Z/0.32)^2) sqrt(1 + (Z/1.35)^2))`, with the scaled distance `Z = R / W^(1/3)` (m/kg^(1/3)).\n * What a wall takes from a blast is read against it: about 7 kPa cracks plaster and breaks windows, 14 to 20 kPa knocks parts of a brick wall out, 35 kPa and over brings an\n * unreinforced brick wall down (Glasstone and Dolan, \"The Effects of Nuclear Weapons\", 1977, table 5.139; UFC 3-340-02).\n */\nexport function sideOnOverpressure(tnt: number, distance: number): number {\n if (!(tnt > 0)) return 0\n const z = Math.max(distance, NEAREST) / Math.cbrt(tnt)\n const ratio = (808 * (1 + (z / 4.5) ** 2)) / (Math.sqrt(1 + (z / 0.048) ** 2) * Math.sqrt(1 + (z / 0.32) ** 2) * Math.sqrt(1 + (z / 1.35) ** 2))\n return ratio * ATMOSPHERE\n}\n\n/**\n * The impulse per square metre a body facing the wave takes, Pa·s: the side-on impulse reflected. The reflection doubles a weak wave and grows up to about six times close to the charge,\n * where the wave is strong (the ratio of reflected to side-on impulse of the Kingery-Bulmash charts, fitted as `2 + 4 / (1 + Z^2)`).\n */\nexport function bodyImpulse(tnt: number, distance: number): number {\n if (!(tnt > 0)) return 0\n const z = Math.max(distance, NEAREST) / Math.cbrt(tnt)\n return sideOnImpulse(tnt, distance) * (2 + 4 / (1 + z * z))\n}\n\n/** The speed (m/s) a blast wave gives a free body of `mass` kg at `distance` metres from `tnt` kg of TNT, `reach` (0..1) of it getting through what stands in the way. */\nexport function blastBodySpeed(tnt: number, distance: number, mass: number, reach = 1, options: BlastImpulseOptions = {}): number {\n const area = options.bodyArea ?? DEFAULT_BLAST_IMPULSE.bodyArea\n return (bodyImpulse(tnt, distance) * area * Math.max(0, reach)) / Math.max(mass, 1)\n}\n","import { blastBodySpeed, DEFAULT_BLAST_IMPULSE } from './blast-impulse'\nimport type { BlastImpulseOptions } from './blast-impulse'\nimport type { BlastShoveOptions, BlastSource } from './blast-shove'\nimport type { Vec3 } from './destruction'\n\n/** From this speed (m/s) a blast takes a standing body off its feet. Below it the body is only pushed. */\nexport const KNOCK_DOWN_SPEED = 2.5\n/** The angle of a body lying where it fell (the same tilt a dead body takes). */\nexport const KNOCKED_DOWN_ANGLE = 1.35\n/** Seconds the body lies after it lands: this plus the landing speed times `STAND_UP_PER_SPEED`. */\nconst LIE_SECONDS = 1.6\n/** Seconds a body floored by its wounds (inside the lethal radius) lies before it gets up, when it is not dead. */\nconst WOUNDED_LIE_SECONDS = 6\n/** The share of the blast that has to get through for its fragments to reach a body: behind cover that stops half of it the fragments stop too. */\nexport const FRAGMENT_COVER = 0.5\n/** Seconds a body is stunned at the edge of the lethal radius (the ringing ears, the dizziness); it falls with the square of the way to the edge of the blast. */\nconst STUN_SECONDS = 4\nconst STAND_UP_PER_SPEED = 0.25\nconst FALL_SECONDS = 0.25\nconst RISE_SECONDS = 0.6\n/** m/s squared that slows a body sliding on the ground. */\nconst GROUND_FRICTION = 7\nconst GRAVITY = 9.81\n/** Height of the chest above the feet: where the blast takes the body. */\nexport const KNOCK_CHEST = 1.1\nconst CHEST = KNOCK_CHEST\n\n/** What a blast is doing to one body: its velocity (m/s), whether it is in the air, and how far down it is (0 on its feet, 1 lying). */\nexport interface Knock {\n velocity: [number, number, number]\n airborne: boolean\n /** 0..1 */\n lying: number\n /** Seconds left to lie on the ground after it stopped. */\n lieLeft: number\n /** Knocked off its feet by this blast. */\n down: boolean\n /** Floored by its wounds: inside the lethal radius and not behind cover. It lies longer and falls where it stood. */\n wounded?: boolean\n /** Seconds of stun the blast gave the body: dizziness and ringing ears. */\n stunSeconds?: number\n /** The horizontal unit direction away from the blast, even when the push is too weak to move the body: the way it falls. */\n away?: Vec3\n}\n\n/** The mass of a body in kg from its height (m) and its build (1 = average): 70 kg at 1.75 m. */\nexport const bodyMass = (height: number, build = 1): number => 70 * (height / 1.75) ** 2 * build\n\n/**\n * What a blast does to a body standing at `feet`, of `mass` kg. Undefined when the blast does not reach it or does nothing to it.\n *\n * The body is pushed by the blast wave (`blastBodySpeed`, from the charge `blast.tnt`, or from `energy` by `tntPerJoule`), taken at the chest and cut by `reach`, the share that got through\n * cover. It is floored when that push is `KNOCK_DOWN_SPEED` or more, or when it stands inside `lethalRadius` with the blast reaching it (the fragments and the overpressure fell it where it\n * stands). It is stunned for a while inside the radius. `options` are the shove numbers of the host's loose items; only their `minSpeed` applies to a body.\n */\nexport function knockOf(blast: BlastSource, feet: Vec3, mass: number, options?: BlastShoveOptions, impulse: BlastImpulseOptions = {}): Knock | undefined {\n const o = { ...DEFAULT_BLAST_IMPULSE, ...impulse }\n const chest: Vec3 = [feet[0], feet[1] + CHEST, feet[2]]\n const dx = chest[0] - blast.point[0]\n const dy = chest[1] - blast.point[1]\n const dz = chest[2] - blast.point[2]\n const distance = Math.hypot(dx, dy, dz)\n if (!(blast.radius > 0) || distance > blast.radius) return undefined\n const reach = Math.max(0, Math.min(1, blast.reach ?? 1))\n const tnt = blast.tnt ?? blast.energy * o.tntPerJoule\n let speed = blastBodySpeed(tnt, distance, mass, reach, o)\n const minSpeed = impulse.minSpeed ?? options?.minSpeed ?? o.minSpeed\n if (speed < minSpeed) speed = 0\n const struck = reach >= FRAGMENT_COVER\n const wounded = struck && blast.lethalRadius !== undefined && distance <= blast.lethalRadius\n const edge = 1 - distance / blast.radius\n const stunSeconds = struck ? STUN_SECONDS * edge * edge * reach : 0\n if (speed === 0 && !wounded && stunSeconds < 0.25) return undefined\n // straight above or below the centre there is no \"away\": the push goes up\n const horizontal = Math.hypot(dx, dz)\n const away: Vec3 = horizontal > 1e-4 ? [dx / horizontal, o.lift, dz / horizontal] : [0, 1, 0]\n const length = Math.hypot(away[0], away[1], away[2])\n const velocity: [number, number, number] = [(away[0] / length) * speed, (away[1] / length) * speed, (away[2] / length) * speed]\n return {\n velocity,\n airborne: velocity[1] > 0.5,\n lying: 0,\n lieLeft: wounded ? WOUNDED_LIE_SECONDS : 0,\n away: horizontal > 1e-4 ? [dx / horizontal, 0, dz / horizontal] : [0, 0, 0],\n down: speed >= KNOCK_DOWN_SPEED || wounded,\n ...(wounded ? { wounded } : {}),\n ...(stunSeconds >= 0.25 ? { stunSeconds } : {}),\n }\n}\n\n/**\n * Moves a body one step: it slides on the ground and slows, falls when it was knocked down, lies a while and gets up (a dead body stays down). Moves `position` in place; returns true when the\n * body is on its feet and still, and the knock can be dropped.\n */\nexport function stepKnock(knock: Knock, position: { x: number; y: number; z: number }, dt: number, groundAt: (x: number, z: number) => number, alive: boolean): boolean {\n const v = knock.velocity\n position.x += v[0] * dt\n position.z += v[2] * dt\n const ground = groundAt(position.x, position.z)\n if (knock.airborne || position.y > ground + 1e-4) {\n v[1] -= GRAVITY * dt\n position.y += v[1] * dt\n if (position.y <= ground) {\n position.y = ground\n v[1] = 0\n knock.airborne = false\n }\n } else position.y = ground\n const horizontal = Math.hypot(v[0], v[2])\n if (!knock.airborne && horizontal > 0) {\n const slowed = Math.max(0, horizontal - GROUND_FRICTION * dt)\n v[0] *= slowed / horizontal\n v[2] *= slowed / horizontal\n }\n const moving = horizontal > 0.05 || knock.airborne\n if (knock.down) {\n // a body floored where it stands (its wounds, not the push) still takes the time of a fall to reach the ground\n if (moving || knock.lying < 1) knock.lying = Math.min(1, knock.lying + dt / FALL_SECONDS)\n else if (alive) {\n knock.lieLeft = knock.lieLeft > 0 ? knock.lieLeft : LIE_SECONDS + Math.hypot(v[0], v[2]) * STAND_UP_PER_SPEED\n knock.lieLeft -= dt\n if (knock.lieLeft <= 0) knock.down = false\n }\n } else if (knock.lying > 0) knock.lying = Math.max(0, knock.lying - dt / RISE_SECONDS)\n return !moving && !knock.down && knock.lying === 0\n}\n\n/** Where `launchBody` leaves the throw on the body's root until the module that animates it takes it. */\nconst LAUNCHED = 'launched'\n\n/**\n * Throws a body at `velocity` (m/s, world): an occupant leaving a car through the glass, a pedestrian run over. The module that animates the body\n * takes it on its next frame (`takeLaunch`) and moves it as it moves a body a blast knocked down: flying, landing, sliding, lying, getting up.\n */\nexport function launchBody(root: { userData: Record<string, unknown> }, velocity: Vec3): void {\n root.userData[LAUNCHED] = [velocity[0], velocity[1], velocity[2]]\n}\n\n/** The throw `launchBody` left on the root, as a knock (knocked down, in the air), once; undefined when nothing threw it. */\nexport function takeLaunch(root: { userData: Record<string, unknown> }): Knock | undefined {\n const velocity = root.userData[LAUNCHED] as Vec3 | undefined\n if (!velocity) return undefined\n delete root.userData[LAUNCHED]\n return { velocity: [velocity[0], velocity[1], velocity[2]], airborne: true, lying: 0, lieLeft: 0, down: true }\n}\n","export interface CostOptions {\n /** Reads of `state()` and of `describe()` to time. Default 10 000. */\n reads?: number\n /** Ceiling, in milliseconds, for all the reads of one method. Default 50 (5 microseconds per read). */\n ceilingMs?: number\n /** Ceiling of heap growth, in bytes, over all the reads of one method (only where `process.memoryUsage` exists). Default 1 MiB. */\n allocationBytes?: number\n}\n\nconst DEFAULT_COST_READS = 10_000\nconst DEFAULT_COST_CEILING_MS = 50\nconst DEFAULT_COST_ALLOCATION_BYTES = 1024 * 1024\n\nconst heapUsedBytes = (): number | undefined => {\n const nodeProcess = (globalThis as { process?: { memoryUsage?: () => { heapUsed: number } } }).process\n return nodeProcess?.memoryUsage?.().heapUsed\n}\n\ntype CheckReadCostParams = { readonly name: string; readonly read: () => unknown; readonly options: CostOptions; readonly problems: string[] }\n\nexport const checkReadCost = ({ name, read, options, problems }: CheckReadCostParams): void => {\n const reads = options.reads ?? DEFAULT_COST_READS\n const ceilingMs = options.ceilingMs ?? DEFAULT_COST_CEILING_MS\n const allocationBytes = options.allocationBytes ?? DEFAULT_COST_ALLOCATION_BYTES\n if (read() !== read()) problems.push(`${name}() returns a new object on each read: cache it between changes (cost contract)`)\n // a first pass lets the engine compile and optimise the loop: that code and its feedback are heap too, and would read as the method allocating\n for (let i = 0; i < reads; i++) read()\n const heapBefore = heapUsedBytes()\n const started = performance.now()\n for (let i = 0; i < reads; i++) read()\n const elapsedMs = performance.now() - started\n const heapAfter = heapUsedBytes()\n if (elapsedMs > ceilingMs) problems.push(`${name}() took ${elapsedMs.toFixed(1)} ms for ${reads} reads, over the ${ceilingMs} ms ceiling (cost contract)`)\n if (heapBefore !== undefined && heapAfter !== undefined && heapAfter - heapBefore > allocationBytes)\n problems.push(`${name}() grew the heap by ${heapAfter - heapBefore} bytes over ${reads} reads, over the ${allocationBytes} byte ceiling (cost contract)`)\n}\n","import { checkReadCost } from './impact-cost'\nimport type { CostOptions } from './impact-cost'\nimport type { DamageType, DestructibleSpec, DestructionEvent, Hit, JointSpec, ObjectState, ToolKind, Vec3 } from './destruction'\n\n/**\n * What a game module implements for an object whose behaviour it owns (a vehicle with its own panel deformation, a creature, a machine). The\n * world (`DestructionWorld.register`) hosts it next to its own objects: raycast, shoot, explode, hit, disassemble, extinguish, update, state,\n * reset and `on` all route to it.\n *\n * Space: the impl receives hits in WORLD space and returns events in WORLD space (it owns its transform; the transform given to `register` or\n * `setTransform` is only used by the world for raycasts and blast range). Every event must carry `object === id` and name parts listed by\n * `describe()`.\n */\n/** World-space ray for `DestructibleImpl.surfaceRay`. */\nexport interface SurfaceRay {\n readonly origin: Vec3\n readonly direction: Vec3\n readonly maxDistance: number\n ignored?(part: string): boolean\n}\n\nexport interface SurfaceRayHit {\n readonly part: string\n readonly point: Vec3\n readonly normal: Vec3\n readonly distance: number\n /** Thickness the ray crosses in this part, metres. */\n readonly pathLen: number\n}\n\nexport interface DestructibleImpl {\n readonly id: string\n readonly name?: string\n /**\n * Parts, joints and structure in the impl's local space, for raycast, inspector and log.\n * COST CONTRACT (D8): called per frame by the renderer, so it is O(1), allocation-free and cached between changes: the same object comes\n * back until a hit, tool, fire or pose change alters it. `checkDestructible(impl, { cost: true })` measures it.\n */\n describe(): DestructibleSpec\n /** Apply one hit (see `IMPACT_CONTRACT` for the fields per type) and return the events it caused. */\n hit(hit: Hit): DestructionEvent[]\n /**\n * The real surface a ray meets, for an impl whose drawn shape is not its boxes (a car body): the boxes of `describe()` only say where to look, and a shot that crosses\n * them without touching the drawn surface goes on. `ignored` answers for the parts the round already went through. Null when the ray meets nothing.\n */\n surfaceRay?(ray: SurfaceRay): SurfaceRayHit | null\n /** Advance fire, melting, collapse and other timed behaviour. */\n update?(dt: number): DestructionEvent[]\n /**\n * COST CONTRACT (D8): the host reads it per part per frame, so it is O(1), allocation-free and cached between changes (see `describe()`).\n * The cached object is shared with every reader: treat it as read-only, copy before changing it.\n */\n state(): Readonly<ObjectState>\n reset?(): void\n /** The world took the object out (`DestructionWorld.remove`): the impl lets go of what it joined (shared queues, listeners). */\n dispose?(): void\n /** Same contract as `DestructionWorld.disassemble`: progress 0..1, or -1 when the tool cannot undo the joint. */\n disassemble?(jointId: string, tool: ToolKind, dt: number): number\n extinguish?(partId?: string): void\n /** Optional: an animation moved a part; `position` / `rotation` (Euler XYZ, radians) are object-local. Keep raycast and hit shapes in sync. */\n setPartPose?(partId: string, position: Vec3, rotation?: Vec3): void\n /** Plain JSON of the impl's own state, stored in `DestructionSnapshot.impls`. */\n serialize?(): unknown\n load?(data: unknown): void\n}\n\n/** The fields a weapon or hazard must put in a `Hit`, per damage type. THE impact contract. */\nexport interface ImpactContract {\n required: string[]\n optional: string[]\n note: string\n}\n\nexport const IMPACT_CONTRACT: Record<DamageType, ImpactContract> = {\n ballistic: { required: ['type', 'point', 'direction', 'energy', 'caliber'], optional: ['space', 'source'], note: 'bullets and pellets: joules and diameter in millimetres' },\n blunt: { required: ['type', 'point', 'energy'], optional: ['direction', 'radius', 'space', 'source'], note: 'contact radius in metres (default 3 cm)' },\n slash: { required: ['type', 'point', 'energy'], optional: ['direction', 'radius', 'space', 'source'], note: 'axes, knives, machetes' },\n explosive: { required: ['type', 'point', 'energy', 'radius'], optional: ['lethalRadius', 'space', 'source'], note: 'point is the centre of the blast, radius the range in metres' },\n fire: { required: ['type', 'point', 'temperature', 'radius'], optional: ['duration', 'space', 'source'], note: 'flame temperature in °C; duration in seconds (call every frame with `dt`)' },\n heat: { required: ['type', 'point', 'temperature', 'radius'], optional: ['duration', 'space', 'source'], note: 'heat without flame (cutting torch, hot plate)' },\n}\n\n/** Problems with a hit according to the impact contract (empty when it is valid). */\nexport const checkHit = (hit: Hit): string[] => {\n const c = IMPACT_CONTRACT[hit.type]\n if (!c) return [`unknown damage type \"${String(hit.type)}\"`]\n const out: string[] = []\n for (const f of c.required) {\n const v = (hit as unknown as Record<string, unknown>)[f]\n if (v === undefined || (Array.isArray(v) ? v.some((n) => !Number.isFinite(n)) : typeof v === 'number' && !Number.isFinite(v))) out.push(`${hit.type} hit needs \"${f}\"`)\n }\n return out\n}\n\nexport interface CheckOptions {\n /**\n * Ids of every material the impl may use (the contracts package does not know the materials of your world: pass the ids of\n * `world.materials`, or the built-in plus your own). When omitted, the material check is skipped.\n */\n materials?: Iterable<string>\n /** Opt-in cost measurement (D8): `true` for the defaults, or the limits to use. */\n cost?: boolean | CostOptions\n}\n\nconst finiteJson = (v: unknown, path: string, out: string[]) => {\n if (typeof v === 'number') {\n if (!Number.isFinite(v)) out.push(`${path} is not a finite number`)\n } else if (Array.isArray(v)) v.forEach((x, i) => finiteJson(x, `${path}[${i}]`, out))\n else if (v && typeof v === 'object') for (const [k, x] of Object.entries(v)) finiteJson(x, `${path}.${k}`, out)\n else if (typeof v === 'function' || typeof v === 'symbol' || typeof v === 'bigint') out.push(`${path} is not JSON`)\n}\n\n/**\n * Contract checker for the test room (it needs no world): `describe()` is valid, a 500 J ballistic hit at a part centre returns well-formed events of this impl, `state()`\n * matches `describe()`, hit points never go negative, `update(0.016)` returns an array and every event is JSON-serializable. It hits the impl\n * (and calls `reset()` afterwards when there is one). With `options.cost` it also times `state()` and `describe()` (the cost contract of D8).\n */\nexport const checkDestructible = (impl: DestructibleImpl, options: CheckOptions = {}): { ok: boolean; problems: string[] } => {\n const problems: string[] = []\n const known = options.materials ? new Set(options.materials) : null\n let spec: DestructibleSpec | undefined\n try {\n spec = impl.describe()\n } catch (e) {\n return { ok: false, problems: [`describe() threw: ${String(e)}`] }\n }\n if (!spec || !Array.isArray(spec.parts) || spec.parts.length === 0) return { ok: false, problems: ['describe() must return at least one part'] }\n const ids = new Set<string>()\n for (const p of spec.parts) {\n if (ids.has(p.id)) problems.push(`duplicate part id \"${p.id}\"`)\n ids.add(p.id)\n if (known && !known.has(p.material)) problems.push(`part \"${p.id}\" has unknown material \"${p.material}\"`)\n if (!p.shape || !['box', 'cylinder', 'sphere'].includes(p.shape.kind)) problems.push(`part \"${p.id}\" has no valid shape`)\n if (!Array.isArray(p.position) || p.position.length !== 3) problems.push(`part \"${p.id}\" has no position`)\n }\n const jointIds = new Set<string>()\n for (const j of (spec.joints ?? []) as JointSpec[]) {\n if (!ids.has(j.a) || !ids.has(j.b)) problems.push(`joint \"${j.id ?? `${j.a}~${j.b}`}\" references an unknown part`)\n const jid = j.id ?? `${j.a}~${j.b}`\n if (jointIds.has(jid)) problems.push(`duplicate joint id \"${jid}\"`)\n jointIds.add(jid)\n }\n const checkState = (label: string) => {\n let st: ObjectState\n try {\n st = impl.state()\n } catch (e) {\n problems.push(`state() threw ${label}: ${String(e)}`)\n return\n }\n const sids = st.parts.map((p) => p.id).sort().join(',')\n if (sids !== [...ids].sort().join(',')) problems.push(`state() part ids do not match describe() ${label}`)\n for (const p of st.parts) if (!(p.hp >= 0)) problems.push(`part \"${p.id}\" has negative or invalid hp ${label}`)\n }\n const checkEvents = (events: unknown, label: string) => {\n if (!Array.isArray(events)) {\n problems.push(`${label} must return an array`)\n return\n }\n const evs = events as DestructionEvent[]\n evs.forEach((e, i) => {\n if (e.object !== impl.id) problems.push(`${label} event ${i} (${e.type}) has object \"${String(e.object)}\", expected \"${impl.id}\"`)\n const part = (e as { part?: string }).part\n if (part !== undefined && !ids.has(part)) problems.push(`${label} event ${i} (${e.type}) names unknown part \"${part}\"`)\n })\n const bad: string[] = []\n finiteJson(evs, 'events', bad)\n problems.push(...bad.map((b) => `${label}: ${b}`))\n try {\n const s = JSON.stringify(evs)\n if (JSON.stringify(JSON.parse(s)) !== s) problems.push(`${label} events do not survive a JSON round trip`)\n } catch (e) {\n problems.push(`${label} events are not JSON-serializable: ${String(e)}`)\n }\n }\n checkState('before the hit')\n const target = spec.parts[0]\n try {\n const hit: Hit = { type: 'ballistic', point: [target.position[0], target.position[1], target.position[2]], direction: [0, 0, -1], energy: 500, caliber: 9 }\n checkEvents(impl.hit(hit), 'hit()')\n } catch (e) {\n problems.push(`hit() threw: ${String(e)}`)\n }\n checkState('after the hit')\n if (impl.update) {\n try {\n checkEvents(impl.update(0.016), 'update()')\n } catch (e) {\n problems.push(`update() threw: ${String(e)}`)\n }\n checkState('after update')\n }\n try {\n impl.reset?.()\n } catch (e) {\n problems.push(`reset() threw: ${String(e)}`)\n }\n if (options.cost) {\n const cost = options.cost === true ? {} : options.cost\n try {\n checkReadCost({ name: 'state', read: () => impl.state(), options: cost, problems })\n checkReadCost({ name: 'describe', read: () => impl.describe(), options: cost, problems })\n } catch (e) {\n problems.push(`cost measurement threw: ${String(e)}`)\n }\n }\n return { ok: problems.length === 0, problems }\n}\n","/** The slots of a body an item can cover (the item slot vocabulary: game-items imports it from here). */\nexport type BodySlot = 'head' | 'eyes' | 'torso' | 'arms' | 'hands' | 'legs' | 'feet' | 'over'\n\n/** The 11 segments of the detailed body model (the Arsenal ids). */\nexport type SegmentKind = 'head' | 'jaw' | 'neck' | 'torso' | 'pelvis' | 'upperArm' | 'forearm' | 'hand' | 'thigh' | 'shin' | 'foot'\n\n/** The 6 regions of the crowd model (the game regions 0..5). */\nexport type BodyRegion = 'head' | 'torso' | 'armL' | 'armR' | 'legL' | 'legR'\n\n/** Bits of the `missing` mask of a body. The instanced body shader reads them, so the values are part of the contract. */\nexport const MISSING_BITS = {\n head: 1,\n armL: 2,\n armR: 4,\n legL: 8,\n legR: 16,\n armLBroken: 32,\n armRBroken: 64,\n legLBroken: 128,\n legRBroken: 256,\n jaw: 512,\n} as const\n","import type { DestructibleSpec, PartSpec } from './destruction'\n\nexport interface CheckSpecOptions {\n /** Known material ids. When given, every part's material must be one of them. */\n materials?: Iterable<string>\n}\n\nexport interface SpecReport {\n /** False when there is at least one problem (warnings do not count). */\n ok: boolean\n problems: string[]\n /** Things that are legal but probably wrong, e.g. structural parts that cannot reach an anchored part. */\n warnings: string[]\n}\n\nconst STRUCTURE_ROLES = ['foundation', 'column', 'beam', 'slab', 'wall', 'partition', 'roof', 'stair', 'none']\nconst BEARS = [true, false, 'a_on_b', 'b_on_a']\n\nconst finite = (n: unknown): n is number => typeof n === 'number' && Number.isFinite(n)\nconst positive = (n: unknown): boolean => finite(n) && n > 0\nconst vec3 = (v: unknown): boolean => Array.isArray(v) && v.length === 3 && v.every(finite)\nconst nonNegative = (n: unknown): boolean => n === undefined || (finite(n) && n >= 0)\n\nconst FACES = ['both', '+', '-']\nconst BONDS = ['running', 'stack']\n\n/** Layers, reinforcement, units and breach: known materials, finite positive sizes. */\nconst checkStagedFields = (p: PartSpec | undefined, label: string, materials: Set<string> | null, problems: string[]): void => {\n const known = (m: unknown, what: string): void => {\n if (materials && !materials.has(m as string)) problems.push(`${label} ${what} has unknown material \"${String(m)}\"`)\n }\n ;(p?.layers ?? []).forEach((l, i) => {\n known(l?.material, `layer ${i}`)\n if (!positive(l?.thickness)) problems.push(`${label} layer ${i} thickness must be finite and positive`)\n if (!FACES.includes(l?.faces)) problems.push(`${label} layer ${i} has an invalid faces \"${String(l?.faces)}\"`)\n })\n const r = p?.reinforcement\n if (r) {\n known(r.material, 'reinforcement')\n if (!positive(r.spacing) || !positive(r.diameter)) problems.push(`${label} reinforcement spacing and diameter must be finite and positive`)\n if (r.residualCapacity !== undefined && !(finite(r.residualCapacity) && r.residualCapacity >= 0 && r.residualCapacity <= 1)) problems.push(`${label} reinforcement residualCapacity must be between 0 and 1`)\n }\n const u = p?.units\n if (u) {\n known(u.mortar, 'units mortar')\n if (!vec3(u.size) || !u.size.every(positive)) problems.push(`${label} units size must be three finite positive numbers`)\n if (!BONDS.includes(u.bond)) problems.push(`${label} units has an invalid bond \"${String(u.bond)}\"`)\n }\n if (p?.breach && p.breach.area !== undefined && !positive(p.breach.area)) problems.push(`${label} breach area must be finite and positive`)\n}\n\n/**\n * Static checks on a `DestructibleSpec` (no world needed), for items that give a `spec` instead of an `impl`: unique part ids, known materials\n * (when `options.materials` is given), joints that reference existing, different parts, finite positive sizes, non-negative mass / hp / capacity,\n * valid structure roles and `bears` directions. A structural part with no path of joints to an anchored part is a warning, not a problem: it\n * is allowed, it just falls.\n */\nexport const checkSpec = (spec: DestructibleSpec, options: CheckSpecOptions = {}): SpecReport => {\n const problems: string[] = []\n const warnings: string[] = []\n const materials = options.materials ? new Set(options.materials) : null\n const parts = Array.isArray(spec?.parts) ? spec.parts : []\n if (!Array.isArray(spec?.parts) || parts.length === 0) problems.push('the spec needs at least one part')\n const ids = new Set<string>()\n for (const p of parts) {\n const id = String(p?.id ?? '')\n const label = `part \"${id}\"`\n if (id === '') problems.push('a part has no id')\n else if (ids.has(id)) problems.push(`duplicate part id \"${id}\"`)\n ids.add(id)\n if (materials && !materials.has(p?.material)) problems.push(`${label} has unknown material \"${String(p?.material)}\"`)\n else if (typeof p?.material !== 'string' || p.material === '') problems.push(`${label} needs a material`)\n const s = p?.shape\n if (s?.kind === 'box') {\n if (!Array.isArray(s.size) || s.size.length !== 3 || !s.size.every(positive)) problems.push(`${label} box size must be three finite positive numbers`)\n } else if (s?.kind === 'cylinder') {\n if (!positive(s.radius) || !positive(s.height)) problems.push(`${label} cylinder radius and height must be finite and positive`)\n } else if (s?.kind === 'sphere') {\n if (!positive(s.radius)) problems.push(`${label} sphere radius must be finite and positive`)\n } else problems.push(`${label} has an unknown shape`)\n if (!vec3(p?.position)) problems.push(`${label} needs a finite position [x, y, z]`)\n if (p?.rotation !== undefined && !vec3(p.rotation)) problems.push(`${label} has an invalid rotation`)\n for (const f of ['mass', 'hp', 'thickness'] as const) if (!nonNegative(p?.[f])) problems.push(`${label} ${f} must be a finite number >= 0`)\n if (p?.fill !== undefined && !(finite(p.fill) && p.fill >= 0 && p.fill <= 1)) problems.push(`${label} fill must be between 0 and 1`)\n if (p?.structure) {\n if (!STRUCTURE_ROLES.includes(p.structure.role)) problems.push(`${label} has an invalid structure role \"${String(p.structure.role)}\"`)\n if (!nonNegative(p.structure.capacity)) problems.push(`${label} structure capacity must be a finite number >= 0`)\n }\n if (p?.contains && !nonNegative(p.contains.liters)) problems.push(`${label} contains.liters must be a finite number >= 0`)\n checkStagedFields(p, label, materials, problems)\n }\n\n const jointIds = new Set<string>()\n const edges: Array<[string, string]> = []\n for (const j of spec?.joints ?? []) {\n const id = j.id ?? `${j.a}~${j.b}`\n const label = `joint \"${id}\"`\n if (jointIds.has(id)) problems.push(`duplicate joint id \"${id}\"`)\n jointIds.add(id)\n if (!ids.has(j.a)) problems.push(`${label} references unknown part \"${String(j.a)}\"`)\n if (!ids.has(j.b)) problems.push(`${label} references unknown part \"${String(j.b)}\"`)\n if (j.a === j.b) problems.push(`${label} joins part \"${String(j.a)}\" to itself`)\n if (j.bears !== undefined && !BEARS.includes(j.bears)) problems.push(`${label} has an invalid bears \"${String(j.bears)}\"`)\n if (!nonNegative(j.strength)) problems.push(`${label} strength must be a finite number >= 0`)\n if (!nonNegative(j.seconds)) problems.push(`${label} seconds must be a finite number >= 0`)\n if (j.bears !== false && ids.has(j.a) && ids.has(j.b) && j.a !== j.b) edges.push([j.a, j.b])\n }\n\n // structural parts must reach an anchored part over the joints (only when the spec lists its joints: otherwise they are inferred later)\n const structural = parts.filter((p) => p?.structure && p.structure.role !== 'none')\n if (structural.length && spec.joints) {\n const anchored = parts.filter((p) => p.anchored || p.structure?.role === 'foundation').map((p) => p.id)\n const adj = new Map<string, string[]>()\n for (const [a, b] of edges) {\n adj.set(a, [...(adj.get(a) ?? []), b])\n adj.set(b, [...(adj.get(b) ?? []), a])\n }\n const seen = new Set(anchored)\n const queue = [...anchored]\n while (queue.length) {\n for (const n of adj.get(queue.pop()!) ?? []) {\n if (seen.has(n)) continue\n seen.add(n)\n queue.push(n)\n }\n }\n const lost = structural.filter((p) => !seen.has(p.id)).map((p) => p.id)\n if (lost.length) warnings.push(`structural part(s) ${lost.map((i) => `\"${i}\"`).join(', ')} cannot reach an anchored part, so they will fall`)\n }\n return { ok: problems.length === 0, problems, warnings }\n}\n","import type { BallisticExtras, Hit, HitIgnition, Vec3 } from './destruction'\n\n/**\n * A ballistic shot (one per pellet) as a weapon module produces it. Plain data: any damage model can consume it (`shotToHit` makes the `Hit`).\n */\nexport interface Shot {\n origin: Vec3\n /** Unit vector. */\n direction: Vec3\n /** Muzzle energy in joules. */\n energy: number\n /** Bullet diameter in millimetres. */\n caliber: number\n /** snake_case calibre id, e.g. `9x19`. */\n caliberId: string\n /** Muzzle speed in m/s. */\n speed: number\n /** Projectile mass in grams (one pellet for a shotgun load). */\n mass?: number\n /** Energy at a distance in metres, with the calibre's drag. */\n energyAt(distance: number): number\n pellet: number\n /** snake_case weapon id. */\n weapon: string\n source?: string\n /** Kind of the round that was loaded (`fmj`, `hp`, `ap`, `buck`, `slug`, `incendiary`, `tracer`...). */\n ammo?: string\n /** Millimetres of steel, concrete, brick and wood the round goes through at the muzzle (the ammo table of the weapons module). `shotToHit` scales it by the energy left. */\n penetration?: Readonly<Record<string, number>>\n incendiary?: boolean\n tracer?: boolean\n /** Chances that the round lights flammable vapour or fuel. */\n ignition?: HitIgnition\n}\n\n/**\n * The fields of the round that a damage model takes besides the geometry: the penetration by material scaled by the energy that is left at `distance`\n * (linear in the energy: half the energy goes through half as much), the incendiary and tracer flags and the ignition chances. Pass it as the sixth\n * argument of `DestructionWorld.shoot` or spread it in a `Hit`.\n */\nexport const shotExtras = (shot: Shot, distance = 0): BallisticExtras => {\n const out: { -readonly [K in keyof BallisticExtras]: BallisticExtras[K] } = {}\n if (shot.penetration) {\n const k = shot.energy > 0 ? Math.min(1, Math.max(0, shot.energyAt(distance) / shot.energy)) : 1\n const scaled: Record<string, number> = {}\n for (const key of Object.keys(shot.penetration)) scaled[key] = shot.penetration[key]! * k\n out.penetration = scaled\n }\n if (shot.incendiary) out.incendiary = true\n if (shot.tracer) out.tracer = true\n if (shot.ignition) out.ignition = { spark: shot.ignition.spark, flame: shot.ignition.flame }\n return out\n}\n\n/** One use of a non-firearm (melee swing, flame tick, heat tick, throw, tool tick, extinguisher tick). */\nexport type Use =\n | { kind: 'melee'; damage: 'blunt' | 'slash'; energy: number; radius: number; reach: number; origin: Vec3; direction: Vec3 }\n | { kind: 'flame'; temperature: number; radius: number; range: number; cone: boolean; duration: number; origin: Vec3; direction: Vec3 }\n | { kind: 'heat'; temperature: number; radius: number; range: number; duration: number; origin: Vec3; direction: Vec3 }\n | {\n kind: 'throw'\n energy: number\n radius: number\n fuse: number\n velocity: Vec3\n origin: Vec3\n fire?: { temperature: number; radius: number; seconds: number }\n /** Explosive id (`m67`, `molotov`, `pg7v`...): the host looks the numbers up in the arsenal. Absent on a plain thrown object. */\n explosive?: string\n /** What sets it off: `timer` after `fuse` seconds, `impact` on the first hit once armed. */\n trigger?: 'timer' | 'impact'\n /** Metres the projectile must fly before an impact sets it off; closer, it hits without exploding (rocket launchers). */\n armDistance?: number\n /** Radius in metres of the wounding area (`radius` is the lethal one). */\n injuryRadius?: number\n /** Seconds the blast stuns whoever is inside the injury radius (flashbang). */\n stunSeconds?: number\n /** Seconds the thrower held it after pulling the pin: `fuse` is what was left of the full fuse when it left the hand. */\n cooked?: number\n /** Went off in the thrower's hand (held past the fuse): no velocity, `fuse` is 0 and the blast is at `origin`. */\n inHand?: boolean\n }\n /** An explosive set down where the trigger is pulled (mine, C4, charge): it waits for its trigger instead of flying. */\n | {\n kind: 'place'\n explosive: string\n /** `wire`: something trips it; `remote`: the player fires it; `timer`: after `fuse` seconds. */\n triggers: readonly ('timer' | 'wire' | 'remote')[]\n energy: number\n /** Lethal radius in metres. */\n radius: number\n injuryRadius: number\n /** Cone the blast goes through, in front of `direction` (mine); absent for a blast in every direction. */\n cone?: { halfAngleDeg: number; length: number }\n /** The wire a `wire` charge stretches from where it is set down: metres out, degrees from its facing (counter-clockwise from above) and metres above it. */\n tripwire?: { length: number; angleDeg: number; height: number }\n fuse?: number\n origin: Vec3\n direction: Vec3\n }\n /** The blast behind a rocket launcher: dangerous inside `radius` metres, in the cone around `direction` (pointing away from the target). */\n | { kind: 'backblast'; radius: number; halfAngleDeg: number; origin: Vec3; direction: Vec3 }\n | { kind: 'tool'; tool: string; reach: number; duration: number; origin: Vec3; direction: Vec3 }\n | { kind: 'extinguish'; range: number; coolC: number; duration: number; origin: Vec3; direction: Vec3 }\n | { kind: 'hand'; reach: number; origin: Vec3; direction: Vec3 }\n\n/**\n * The `Hit` a ballistic shot makes at `point` (world space): the energy is what is left of the shot at that distance from its origin\n * (`shot.energyAt`), the direction and calibre come from the shot. `normal` (the surface normal at the point, when the caller knows it) does not\n * change the hit; it is accepted so that callers can pass what their raycast returned and so that a stricter implementation could use it.\n */\nexport const shotToHit = (shot: Shot, point: Vec3, normal?: Vec3): Hit => {\n void normal\n const dx = point[0] - shot.origin[0]\n const dy = point[1] - shot.origin[1]\n const dz = point[2] - shot.origin[2]\n const distance = Math.hypot(dx, dy, dz)\n return {\n type: 'ballistic',\n point: [point[0], point[1], point[2]],\n direction: [shot.direction[0], shot.direction[1], shot.direction[2]],\n energy: shot.energyAt(distance),\n caliber: shot.caliber,\n ...(shot.mass === undefined ? {} : { mass: shot.mass }),\n ...shotExtras(shot, distance),\n source: shot.source ?? shot.weapon,\n }\n}\n\n/**\n * The `Hit` a non-firearm `Use` makes at `point` (world space), or `null` for uses that do not damage by themselves.\n *\n * - `melee` -> `blunt` / `slash` with the swing's `energy`, contact `radius` and `direction`;\n * - `flame` -> `fire` and `heat` -> `heat`, with `temperature`, `duration` and a contact radius of at most 0.3 m (one ray of the cone);\n * - `throw` -> the blast (`explosive`, `energy`, `radius`, centred on `point`, the place it detonates). A thrown item with no blast energy but\n * a `fire` patch (a molotov) gives that patch as a `fire` hit (`temperature`, `radius`, `seconds` as `duration`). No energy and no fire -> `null`;\n * - `tool`, `extinguish` and `hand` -> `null` (tools work on joints, the extinguisher cools, the hand only grabs).\n *\n * `normal` does not change the hit (same as `shotToHit`).\n */\nexport const useToHit = (use: Use, point: Vec3, normal?: Vec3): Hit | null => {\n void normal\n const p: Vec3 = [point[0], point[1], point[2]]\n switch (use.kind) {\n case 'melee':\n return { type: use.damage, point: p, direction: [use.direction[0], use.direction[1], use.direction[2]], energy: use.energy, radius: use.radius }\n case 'flame':\n case 'heat':\n return {\n type: use.kind === 'flame' ? 'fire' : 'heat',\n point: p,\n direction: [use.direction[0], use.direction[1], use.direction[2]],\n temperature: use.temperature,\n radius: Math.min(use.radius, 0.3),\n duration: use.duration,\n }\n case 'throw':\n if (use.energy > 0) return { type: 'explosive', point: p, energy: use.energy, radius: use.radius }\n if (use.fire) return { type: 'fire', point: p, temperature: use.fire.temperature, radius: use.fire.radius, duration: use.fire.seconds }\n return null\n default:\n return null\n }\n}\n","import type { Hit } from './destruction'\n\n/**\n * How a container of flammable fluid (a fuel tank, a jerrycan, a gas bottle) is set alight by what hits it. A normal bullet that goes through only\n * makes a leak; the leak lights when something supplies a flame: a spark of a hard round on metal, an incendiary or tracer round, a fire nearby\n * or a blast. These are the numbers of the target side; the numbers of the round (core, jacket, incendiary, tracer) are in the weapons module\n * (`rules.ignition` of `@adatechnology/game-weapons`) and reach the target in `Hit.ignition`. Every number is a default to be changed per game.\n */\nexport interface IgnitionRules {\n /**\n * How much of the spark and of the flame of a round reaches the vapour, by how full the container is: points `[filled, factor]`, `filled` 0..1\n * (litres over capacity), `factor` 0..1, linear between points. A full container holds a mixture too rich to burn (the vapour has no air) and\n * mostly leaks; a nearly empty one holds the vapour/air mixture of a flammable range and lights the easiest; a dry one has little vapour left.\n * Default: 0.6 empty, 1 at 10 percent, 0.6 at 35, 0.3 at 65, 0.15 at 90 and 0.12 full.\n */\n fillCurve: ReadonlyArray<readonly [number, number]>\n /** 0..1: how much of the fill factor also weighs on the flame of an incendiary or tracer (1: as much as on a spark; 0: not at all). Default 0.5. */\n flameFillInfluence: number\n /** Chance of the flame of a round that is flagged `incendiary` or `tracer` but carries no `ignition` numbers (a host that passes only the flags). */\n flameDefaults: { incendiary: number; tracer: number }\n /**\n * What a spark needs to strike: a factor 0..1 by material id of the struck part. A material that is not listed but is metal takes\n * `sparkMetalDefault`; a part that is not metal never sparks. Default: steel and iron 1, aluminium 0.25.\n */\n sparkTarget: Readonly<Record<string, number>>\n sparkMetalDefault: number\n /**\n * Factor 0..1 on the spark by fluid (default 1): diesel has a flash point of 52 degrees C and more, so a spark that lights petrol vapour does\n * not light it (a flame does). Default: diesel 0.15.\n */\n sparkFluid: Readonly<Record<string, number>>\n /** A leaking container of flammable fluid within `radius` metres of a burning part or a burning fuel stain lights at `chancePerSecond`. */\n fireNear: { radius: number; chancePerSecond: number }\n}\n\n/** Defaults of `IgnitionRules`. */\nexport const DEFAULT_IGNITION_RULES: IgnitionRules = {\n fillCurve: [\n [0, 0.6],\n [0.1, 1],\n [0.35, 0.6],\n [0.65, 0.3],\n [0.9, 0.15],\n [1, 0.12],\n ],\n flameFillInfluence: 0.5,\n flameDefaults: { incendiary: 0.7, tracer: 0.2 },\n sparkTarget: { steel: 1, iron: 1, aluminium: 0.25 },\n sparkMetalDefault: 0.5,\n sparkFluid: { diesel: 0.15 },\n fireNear: { radius: 1.5, chancePerSecond: 0.5 },\n}\n\n/** Merges a partial `IgnitionRules` over the defaults (an object is merged one level deep). */\nexport const resolveIgnitionRules = (rules?: Partial<IgnitionRules>): IgnitionRules => ({\n ...DEFAULT_IGNITION_RULES,\n ...rules,\n flameDefaults: { ...DEFAULT_IGNITION_RULES.flameDefaults, ...rules?.flameDefaults },\n sparkTarget: { ...DEFAULT_IGNITION_RULES.sparkTarget, ...rules?.sparkTarget },\n sparkFluid: { ...DEFAULT_IGNITION_RULES.sparkFluid, ...rules?.sparkFluid },\n fireNear: { ...DEFAULT_IGNITION_RULES.fireNear, ...rules?.fireNear },\n})\n\n/** Linear interpolation of the fill curve at `fill` (0..1); outside the points it keeps the first or the last. */\nexport const fillFactor = (fill: number, curve: IgnitionRules['fillCurve'] = DEFAULT_IGNITION_RULES.fillCurve): number => {\n if (curve.length === 0) return 1\n const f = Math.min(1, Math.max(0, fill))\n if (f <= curve[0]![0]) return curve[0]![1]\n for (let i = 1; i < curve.length; i++) {\n const [x1, y1] = curve[i]!\n const [x0, y0] = curve[i - 1]!\n if (f <= x1) return x1 === x0 ? y1 : y0 + ((y1 - y0) * (f - x0)) / (x1 - x0)\n }\n return curve[curve.length - 1]![1]\n}\n\n/** The factor of what a spark strikes: 0 when the struck part is not metal. */\nexport const sparkTargetFactor = (materialId: string, metal: boolean, rules: IgnitionRules = DEFAULT_IGNITION_RULES): number =>\n !metal ? 0 : rules.sparkTarget[materialId] ?? rules.sparkMetalDefault\n\n/**\n * Chance that one round that went through the wall of a container lights the fluid that leaks: the spark (only on metal) and the flame (any\n * wall), each weighed by the fill of the container; the two are independent. 0 when the round carries nothing (`Hit.ignition` absent and not\n * flagged `incendiary` or `tracer`): a plain bullet on a plain wall only leaks.\n */\nexport const ignitionChance = (hit: Pick<Hit, 'incendiary' | 'tracer' | 'ignition'>, target: { sparkTarget: number; fill: number; fluid?: string }, rules: IgnitionRules = DEFAULT_IGNITION_RULES): number => {\n const k = fillFactor(target.fill, rules.fillCurve)\n const spark = (hit.ignition?.spark ?? 0) * target.sparkTarget * (target.fluid === undefined ? 1 : rules.sparkFluid[target.fluid] ?? 1) * k\n const flameBase = hit.ignition?.flame ?? Math.max(hit.incendiary ? rules.flameDefaults.incendiary : 0, hit.tracer ? rules.flameDefaults.tracer : 0)\n const flame = flameBase * (1 - rules.flameFillInfluence * (1 - k))\n return 1 - (1 - Math.min(1, Math.max(0, spark))) * (1 - Math.min(1, Math.max(0, flame)))\n}\n","/**\n * The seal of a closed container (a food tin, a drink can, a jar, a bottle with a cap): what opens it and whether a breach spoils what is inside.\n * Plain data and one pure check, shared by the item rules (`resolveUse` of game-items) and any host that lets the player open and eat (the test room).\n */\nexport interface SealSpec {\n /** Ids of the tools that open it (items or weapons: `can_opener`, `knife`); any one of them is enough. */\n readonly openWith?: readonly string[]\n /** It opens by hand (a pull tab, a ring pull, a screw cap): no tool needed. */\n readonly byHand?: boolean\n /** A hole through the container or a leak spoils what is inside: it can no longer be eaten or drunk. */\n readonly spoilsWhenBreached?: boolean\n}\n\n/** The state of one container: opened, holed through (a shot, a blade) or leaking. */\nexport interface SealState {\n readonly opened?: boolean\n readonly breached?: boolean\n readonly leaked?: boolean\n}\n\n/** Why a sealed container cannot be eaten or drunk now. */\nexport type SealBlock = 'sealed' | 'breached' | 'leaked'\n\n/** Whether it can be opened with the tools at hand, and with which one (undefined when it opens by hand). */\nexport const sealOpener = (seal: SealSpec, tools: Iterable<string>): { readonly ok: boolean; readonly tool?: string } => {\n if (seal.byHand || !seal.openWith || seal.openWith.length === 0) return { ok: true }\n const have = new Set(tools)\n const tool = seal.openWith.find((id) => have.has(id))\n return tool === undefined ? { ok: false } : { ok: true, tool }\n}\n\n/** What stops eating or drinking it now, or undefined when nothing does. A spoiled container (breached, leaked) is blocked even once open. */\nexport const sealBlock = (seal: SealSpec, state: SealState): SealBlock | undefined => {\n if (seal.spoilsWhenBreached && state.breached) return 'breached'\n if (seal.spoilsWhenBreached && state.leaked) return 'leaked'\n if (!state.opened) return 'sealed'\n return undefined\n}\n","import type { Vec3 } from './destruction'\n\n/**\n * Where a hand should be, in world space. `position` is the middle of the palm; the orientation follows one convention for every hand: the hand-local +x runs from the wrist to the\n * knuckles (the way the fingers point when open), +y is the back of the hand and +z completes the frame (for a right hand the little finger side; the thumb is at -z). A left hand is the\n * mirror image of a right one, so the same numbers describe the same grip: its thumb is at +z.\n */\nexport interface HandPose {\n position: Vec3\n /** Unit quaternion `[x, y, z, w]`, hand-local to world. */\n quaternion: [number, number, number, number]\n}\n\n/**\n * What a tool in the hands asks of the hands that hold it (a weapon asks for a grip on its grip and handguard, a carried item for a hand under it). A side left out or null is not held:\n * the hand stays in its rest stance. Nothing here knows what the tool is.\n */\nexport interface HandTargets {\n R?: HandPose | null\n L?: HandPose | null\n /** How closed the fingers are, 0 open to 1 closed on a grip. Default 1. */\n grip?: number\n /** The same for the left hand, when it differs from `grip` (a hand laid on a forend is looser than the one on the trigger). */\n gripL?: number\n /** The size of the hands against life size (a tool drawn smaller than real takes smaller hands). Default 1. */\n scale?: number\n /** Fingers of the right hand that curl by themselves, 0 extended to 1 fully curled (the index finger of a trigger hand); the others follow `grip`. */\n fingers?: { index?: number }\n /** The same for the left hand (its index on the trigger of a tool of its own, with a tool in each hand); absent, the left hand's fingers all follow `gripL`. */\n fingersL?: { index?: number }\n /**\n * Where the elbows go: `view` puts them on screen beside the hand, out to the side, as a tool held out in front (default); `body` lets them hang down and back by the body, as an item\n * carried close (a can, a bottle), where an elbow out to the side would lift it above the shoulder.\n */\n elbows?: 'view' | 'body'\n}\n\n/** Read every frame by whoever draws the arms; answers null while nothing is held. */\nexport type HandTargetSource = () => HandTargets | null\n\n/** The muzzle of the tool in the hands as it is drawn now (world space): where a shot's flash and tracer leave, and which way the barrel points. */\nexport interface MuzzlePose {\n readonly position: Vec3\n /** Unit vector along the barrel, out of the muzzle. */\n readonly direction: Vec3\n /** The module draws the muzzle flash itself: the host draws none of its own. */\n readonly drawsFlash: boolean\n}\n\n/** A hand of the body: `R` the right, `L` the left. A tool in one hand alone is in the right; the left holds one of its own only with a tool in each hand (`HostTool.offHand`). */\nexport type ToolHand = 'R' | 'L'\n\n/**\n * Read by the host at each shot; null while the tool in the hands has no muzzle (a knife, a bare hand). `hand` is the hand that fired (absent: the right one); a source that draws\n * one tool only answers the same for both.\n */\nexport type MuzzleSource = (hand?: ToolHand) => MuzzlePose | null\n\n/**\n * The layer of what the first-person view draws over the world (three.js `Object3D.layers`): the tool in the hands and the arms that hold it. A host with a first-person view draws\n * the world without this layer, then this layer alone over it with the depth cleared and its own field of view (`ModuleHost.setViewmodelFov`), as shooters draw the weapon in the hands:\n * it never goes into a wall, and the gun and the arms are framed by the lens chosen for them. Seen from outside (third person) nothing is on it.\n */\nexport const FIRST_PERSON_LAYER = 9\n","/** How a hand turns something round in strokes (a screw cap, a tap handle, a knob): what `twistStroke` answers for one moment of the turning. */\nexport interface TwistStroke {\n /** Radians the wrist is turned from the middle of its stroke, positive the way the part turns. */\n readonly angle: number\n /** Radians the part has turned in all, from 0 to `strokes * reach`. */\n readonly turned: number\n /** How closed the fingers are, 0 open to 1 closed: closed on the part while it turns, open while the wrist turns back. */\n readonly grip: number\n /** 0..1, how far the hand rises off the part while the wrist turns back (1 is `TWIST_LIFT` metres). */\n readonly lift: number\n}\n\nexport interface TwistOptions {\n /** Strokes of the wrist. Default 3. */\n readonly strokes?: number\n /** Radians the part turns in one stroke (a wrist turns about a quarter round with its hold). Default 1.6. */\n readonly reach?: number\n}\n\n/** Metres a hand rises off the part between two strokes. */\nexport const TWIST_LIFT = 0.012\n/** Share of each stroke spent turning the part; the rest turns the wrist back open. */\nconst TURNING = 0.7\n\nconst smooth = (k: number): number => k * k * (3 - 2 * k)\n\n/**\n * The hand turning a part round at `share` (0..1) of the whole turning: in each stroke the wrist turns with the part, then lets go, rises a little and turns back.\n * Pure and the same for every host, so first and third person turn the same hand the same way.\n */\nexport const twistStroke = (share: number, options: TwistOptions = {}): TwistStroke => {\n const strokes = Math.max(1, Math.round(options.strokes ?? 3))\n const reach = options.reach ?? 1.6\n const along = Math.min(1, Math.max(0, share)) * strokes\n const index = Math.min(strokes - 1, Math.floor(along))\n const phase = along - index\n if (phase <= TURNING) {\n const k = smooth(phase / TURNING)\n return { angle: reach * (k - 0.5), turned: reach * (index + k), grip: 1, lift: 0 }\n }\n const k = (phase - TURNING) / (1 - TURNING)\n return { angle: reach * (0.5 - smooth(k)), turned: reach * (index + 1), grip: 0.35, lift: Math.sin(k * Math.PI) }\n}\n","import type { Vec3 } from './destruction'\n\n/** Pose of one part (or of the whole item) at a key: position offset in metres and Euler XYZ rotation in radians, both relative to the rest pose. */\nexport interface AnimationPose {\n position?: Vec3\n rotation?: Vec3\n}\n\nexport interface AnimationKey {\n /** Seconds from the start of the clip. */\n t: number\n /** Pose of the item's root. */\n position?: Vec3\n rotation?: Vec3\n /** Poses of named parts: the key is a destruction part id (a pistol `reload` moves `mag`; a car door `open` rotates `door_l`). */\n parts?: Record<string, AnimationPose>\n}\n\nexport interface AnimationEventSpec {\n /** Seconds from the start of the clip. */\n t: number\n /** snake_case type the host maps (`sound`, `eject_casing`, `door_latch`...). */\n type: string\n data?: Record<string, unknown>\n /**\n * Seconds of real time the event fires before `t`, not stretched with the clip: a recorded sound whose hit comes that long after its start\n * (the click of a magazine seating) starts early so the hit lands on `t`. The player passes the lead it could apply as `data.lead`.\n */\n lead?: number\n}\n\n/** A use animation a module brings with its item. Poses between keys are interpolated by the player (the test room does it linearly). */\nexport interface AnimationClipSpec {\n /** snake_case: `reload`, `open`, `drink`... Unique within the item. */\n id: string\n /** Seconds. */\n duration: number\n keys: AnimationKey[]\n events?: AnimationEventSpec[]\n}\n\n/** What an item exposes when it brings its own animations. */\nexport interface ItemAnimationContract {\n animations: AnimationClipSpec[]\n}\n\nconst finite3 = (v: unknown): boolean => Array.isArray(v) && v.length === 3 && v.every((n) => typeof n === 'number' && Number.isFinite(n))\n\n/**\n * Problems with a clip (empty when it is valid): a snake_case id, a positive finite duration, at least one key, key and event times inside\n * `[0, duration]` and not going backwards, finite vectors, every named part one of `partIds`, event types that are non-empty strings and\n * JSON-serializable event data.\n */\nexport const checkAnimation = (clip: AnimationClipSpec, partIds: Iterable<string>): { ok: boolean; problems: string[] } => {\n const problems: string[] = []\n const parts = new Set(partIds)\n const id = String(clip?.id ?? '')\n if (!/^[a-z][a-z0-9_]*$/.test(id)) problems.push(`clip id \"${id}\" must be snake_case`)\n const label = `clip \"${id}\"`\n if (!(typeof clip?.duration === 'number' && Number.isFinite(clip.duration) && clip.duration > 0)) problems.push(`${label} needs a positive finite duration`)\n const dur = typeof clip?.duration === 'number' && clip.duration > 0 ? clip.duration : Infinity\n if (!Array.isArray(clip?.keys) || clip.keys.length === 0) {\n problems.push(`${label} needs at least one key`)\n return { ok: false, problems }\n }\n let prev = -Infinity\n clip.keys.forEach((k, i) => {\n if (!(typeof k.t === 'number' && Number.isFinite(k.t)) || k.t < 0 || k.t > dur + 1e-9) problems.push(`${label} key ${i} has t=${String(k.t)} outside 0..${dur}`)\n else if (k.t < prev) problems.push(`${label} key ${i} goes back in time (${k.t} < ${prev})`)\n else prev = k.t\n for (const f of ['position', 'rotation'] as const) if (k[f] !== undefined && !finite3(k[f])) problems.push(`${label} key ${i} has an invalid ${f}`)\n for (const [pid, pose] of Object.entries(k.parts ?? {})) {\n if (!parts.has(pid)) problems.push(`${label} key ${i} moves unknown part \"${pid}\"`)\n for (const f of ['position', 'rotation'] as const) if (pose?.[f] !== undefined && !finite3(pose[f])) problems.push(`${label} key ${i} part \"${pid}\" has an invalid ${f}`)\n }\n })\n let prevEv = -Infinity\n ;(clip.events ?? []).forEach((e, i) => {\n if (!(typeof e.t === 'number' && Number.isFinite(e.t)) || e.t < 0 || e.t > dur + 1e-9) problems.push(`${label} event ${i} has t=${String(e.t)} outside 0..${dur}`)\n else if (e.t < prevEv) problems.push(`${label} event ${i} goes back in time`)\n else prevEv = e.t\n if (typeof e.type !== 'string' || e.type === '') problems.push(`${label} event ${i} needs a type`)\n try {\n JSON.stringify(e.data ?? {})\n } catch {\n problems.push(`${label} event ${i} data is not JSON`)\n }\n })\n return { ok: problems.length === 0, problems }\n}\n","import type { AnimationClipSpec, AnimationEventSpec, AnimationPose } from './animation'\nimport { checkAnimation } from './animation'\nimport type { HostEvent } from './module'\n\n/** Clips a tool can bring, one per move of its cycle. A tool brings the ones it has; a missing clip is simply not played. */\nexport const TOOL_CLIP = {\n DRAW: 'draw',\n SHOT: 'shot',\n MISFIRE: 'misfire',\n EMPTY: 'empty',\n CYCLE: 'cycle',\n RELOAD: 'reload',\n FEED: 'feed',\n FAULT: 'fault',\n CLEAR: 'clear',\n SAFETY_ON: 'safety_on',\n SAFETY_OFF: 'safety_off',\n MODE: 'mode',\n /** A throwable with the pin out, held until it is thrown. */\n COOK: 'cook',\n /** The stock folds, unfolds, slides in or out (variants `fold`, `unfold`, `collapse`, `extend`). */\n STOCK: 'stock',\n /** A light or a laser is switched (variants `on`, `off`). */\n TOGGLE: 'toggle',\n} as const\nexport type ToolClipId = (typeof TOOL_CLIP)[keyof typeof TOOL_CLIP]\n\n/** What a renderer does when a rule event arrives. `variant` picks `<clip>_<variant>` when the tool has it, else `<clip>`. */\nexport type ToolAnimationStep =\n | { readonly type: 'play'; readonly clip: ToolClipId; readonly variant?: string; readonly duration?: number; readonly repeat?: number }\n /** Move the clip that is playing to the marker (a clip event `stage` with `data.stage`) the rule just reached. */\n | { readonly type: 'sync'; readonly stage: string }\n /** The rule says the phase is over: the clip jumps to its end if it is still running. */\n | { readonly type: 'finish'; readonly clip: ToolClipId }\n\nconst stockVariant = (event: Extract<HostEvent, { type: 'stock' }>): string => {\n const isFolding = event.kind === undefined ? false : event.kind.includes('fold')\n if (event.state === 'collapsed') return isFolding ? 'fold' : 'collapse'\n return isFolding ? 'unfold' : 'extend'\n}\n\n/** The move a host event asks of the tool in hand, or null when it has no motion. */\nexport const toolAnimationStep = (event: HostEvent): ToolAnimationStep | null => {\n switch (event.type) {\n case 'tool':\n return { type: 'play', clip: TOOL_CLIP.DRAW, ...(event.duration === undefined ? {} : { duration: event.duration }) }\n case 'shot':\n return { type: 'play', clip: TOOL_CLIP.SHOT, repeat: Math.max(1, event.rounds ?? 1) }\n case 'misfire':\n return { type: 'play', clip: TOOL_CLIP.MISFIRE }\n case 'empty':\n return { type: 'play', clip: TOOL_CLIP.EMPTY }\n case 'mode':\n return { type: 'play', clip: TOOL_CLIP.MODE, variant: event.mode }\n case 'fault':\n return { type: 'play', clip: TOOL_CLIP.FAULT, variant: event.fault }\n case 'clear':\n if (event.phase === 'end') return { type: 'finish', clip: TOOL_CLIP.CLEAR }\n return { type: 'play', clip: TOOL_CLIP.CLEAR, variant: event.fault, ...(event.duration === undefined ? {} : { duration: event.duration }) }\n case 'safety':\n return { type: 'play', clip: event.on ? TOOL_CLIP.SAFETY_ON : TOOL_CLIP.SAFETY_OFF }\n case 'cycle':\n if (event.phase === 'end') return { type: 'finish', clip: TOOL_CLIP.CYCLE }\n return { type: 'play', clip: TOOL_CLIP.CYCLE, ...(event.duration === undefined ? {} : { duration: event.duration }) }\n case 'reload':\n if (event.phase === 'end') return { type: 'finish', clip: TOOL_CLIP.RELOAD }\n return { type: 'play', clip: TOOL_CLIP.RELOAD, ...(event.kind === undefined ? {} : { variant: event.kind }), ...(event.duration === undefined ? {} : { duration: event.duration }) }\n case 'stage':\n return { type: 'sync', stage: event.stage }\n case 'feed':\n return { type: 'play', clip: TOOL_CLIP.FEED }\n case 'cook':\n if (event.phase === 'start') return { type: 'play', clip: TOOL_CLIP.COOK, duration: event.fuse }\n return { type: 'finish', clip: TOOL_CLIP.COOK }\n case 'stock':\n return { type: 'play', clip: TOOL_CLIP.STOCK, variant: stockVariant(event), ...(event.duration === undefined ? {} : { duration: event.duration }) }\n case 'toggle':\n return { type: 'play', clip: TOOL_CLIP.TOGGLE, variant: event.on ? 'on' : 'off' }\n default:\n return null\n }\n}\n\n/** Where a renderer puts the poses: every part of the tool by id (the ids the clips move), and the whole tool. Poses are offsets from rest. */\nexport interface ToolRig {\n setPartPose(partId: string, pose: AnimationPose): void\n setRootPose?(pose: AnimationPose): void\n}\n\n/** Clips by id, with the variants as `<clip>_<variant>`. */\nexport type ToolClipSet = Readonly<Record<string, AnimationClipSpec>>\n\n/** A renderer's tool animator: feed it the host events and the frame time. */\nexport interface ToolAnimator {\n handle(event: HostEvent): void\n update(dt: number): void\n /** Ids of the clips playing now. */\n readonly playing: readonly string[]\n dispose(): void\n}\n\nexport const STAGE_EVENT = 'stage'\n\n/** The clip with its times (keys and events) scaled so that it lasts `duration` seconds. */\nexport const scaleClip = (clip: AnimationClipSpec, duration: number): AnimationClipSpec => {\n const factor = clip.duration > 0 ? duration / clip.duration : 1\n return {\n ...clip,\n duration,\n keys: clip.keys.map((key) => ({ ...key, t: key.t * factor })),\n ...(clip.events ? { events: clip.events.map((event) => ({ ...event, t: event.t * factor })) } : {}),\n }\n}\n\nconst ZERO: [number, number, number] = [0, 0, 0]\nconst mix = (from: readonly number[], to: readonly number[], fraction: number): [number, number, number] => [\n (from[0] ?? 0) + ((to[0] ?? 0) - (from[0] ?? 0)) * fraction,\n (from[1] ?? 0) + ((to[1] ?? 0) - (from[1] ?? 0)) * fraction,\n (from[2] ?? 0) + ((to[2] ?? 0) - (from[2] ?? 0)) * fraction,\n]\n\n/** Pose of the whole tool (`partId` undefined) or of one part at `time`, linear between keys; a key that does not name it means rest. */\nexport const sampleClip = (clip: AnimationClipSpec, partId: string | undefined, time: number): { position: [number, number, number]; rotation: [number, number, number] } => {\n const points = clip.keys.map((key) => {\n const pose = partId === undefined ? key : key.parts?.[partId]\n return { t: key.t, position: pose?.position ?? ZERO, rotation: pose?.rotation ?? ZERO }\n })\n const first = points[0]\n if (!first || first.t > 0) points.unshift({ t: 0, position: ZERO, rotation: ZERO })\n const last = points[points.length - 1]\n if (!last) return { position: ZERO, rotation: ZERO }\n if (time >= last.t) return { position: mix(last.position, last.position, 0), rotation: mix(last.rotation, last.rotation, 0) }\n const index = Math.max(0, points.findIndex((point, i) => time >= point.t && time < (points[i + 1]?.t ?? Infinity)))\n const from = points[index]\n const to = points[index + 1]\n if (!from || !to) return { position: ZERO, rotation: ZERO }\n const fraction = to.t > from.t ? (time - from.t) / (to.t - from.t) : 0\n return { position: mix(from.position, to.position, fraction), rotation: mix(from.rotation, to.rotation, fraction) }\n}\n\n/** Problems with a clip set (empty when valid): each key is the clip id (or `<clip>_<variant>`), every clip passes `checkAnimation`, and a `stage` event names its stage. */\nexport const checkToolClips = (clips: ToolClipSet, partIds: Iterable<string>): { ok: boolean; problems: string[] } => {\n const parts = [...partIds]\n const problems: string[] = []\n for (const [key, clip] of Object.entries(clips)) {\n if (clip.id !== key) problems.push(`clip \"${key}\" has the id \"${clip.id}\"`)\n if (!(clip.duration > 0)) problems.push(`clip \"${key}\" has no duration`)\n problems.push(...checkAnimation(clip, parts).problems)\n for (const event of clip.events ?? []) if (event.type === STAGE_EVENT && typeof event.data?.stage !== 'string') problems.push(`clip \"${key}\" has a stage event without data.stage`)\n }\n return { ok: problems.length === 0, problems }\n}\n\ninterface Instance {\n readonly name: string\n readonly clip: AnimationClipSpec\n time: number\n delay: number\n fired: number\n}\n\nexport interface ToolClipPlayerOptions {\n clips: ToolClipSet\n rig: ToolRig\n /** Called for each clip event as its time passes (`eject_casing`, `drop_magazine`, `stage`...). */\n onEvent?(event: AnimationEventSpec, clip: string): void\n /** Seconds between the rounds of a `repeat` (a burst): default 0.1. */\n repeatInterval?(): number\n}\n\n/** The default player of a tool's clips: runs the steps of `toolAnimationStep` against a rig, scaled to the duration the rule gives. */\nexport interface ToolClipPlayer {\n apply(step: ToolAnimationStep): void\n update(dt: number): void\n readonly playing: readonly string[]\n /** The clips being played with the time each has reached and the clip itself (scaled to the duration the rule gave), for a renderer that has to follow what the clip does now (the hands working a part). */\n readonly running: ReadonlyArray<{ readonly name: string; readonly time: number; readonly clip: AnimationClipSpec }>\n}\n\n/**\n * The clip with every event that has a `lead` moved that many seconds earlier, the lead it got in `data.lead`. A led event never goes before 0\n * nor before the event written ahead of it (a fast clip keeps its order: the lead shrinks). Run after `scaleClip`: the lead is real time, the\n * clip's stretch does not touch it.\n */\nexport const leadClipEvents = (clip: AnimationClipSpec): AnimationClipSpec => {\n const events = clip.events ?? []\n if (!events.some((event) => (event.lead ?? 0) > 0)) return clip\n let floor = 0\n const led = events.map((event) => {\n const lead = Math.max(0, Math.min(event.t - floor, event.lead ?? 0))\n const t = event.t - lead\n floor = Math.max(floor, t)\n if (event.lead === undefined) return event\n const moved: AnimationEventSpec = { ...event, t, data: lead > 0 ? { ...event.data, lead } : { ...event.data } }\n delete moved.lead\n return moved\n })\n return { ...clip, events: led }\n}\n\nexport const createToolClipPlayer = (options: ToolClipPlayerOptions): ToolClipPlayer => {\n const { clips, rig, onEvent } = options\n let instances: Instance[] = []\n\n const find = (clip: string, variant?: string): { name: string; clip: AnimationClipSpec } | undefined => {\n const name = variant !== undefined && clips[`${clip}_${variant}`] ? `${clip}_${variant}` : clip\n const found = clips[name]\n return found ? { name, clip: found } : undefined\n }\n\n const render = (instance: Instance): void => {\n const time = Math.min(instance.time, instance.clip.duration)\n const root = sampleClip(instance.clip, undefined, time)\n if (instance.clip.keys.some((key) => key.position || key.rotation)) rig.setRootPose?.(root)\n const touched = new Set(instance.clip.keys.flatMap((key) => Object.keys(key.parts ?? {})))\n for (const id of touched) rig.setPartPose(id, sampleClip(instance.clip, id, time))\n }\n\n const fireEvents = (instance: Instance, upTo: number): void => {\n const events = instance.clip.events ?? []\n while (instance.fired < events.length && (events[instance.fired]?.t ?? Infinity) <= upTo + 1e-9) {\n const event = events[instance.fired]\n instance.fired += 1\n if (event) onEvent?.(event, instance.name)\n }\n }\n\n return {\n apply(step) {\n if (step.type === 'sync') {\n for (const instance of instances) {\n const marker = (instance.clip.events ?? []).find((event) => event.type === STAGE_EVENT && event.data?.stage === step.stage)\n if (marker && instance.time < marker.t) instance.time = marker.t\n }\n return\n }\n if (step.type === 'finish') {\n for (const instance of instances) {\n if (instance.name !== step.clip && !instance.name.startsWith(`${step.clip}_`)) continue\n fireEvents(instance, instance.clip.duration)\n instance.time = instance.clip.duration\n }\n return\n }\n const found = find(step.clip, step.variant)\n if (!found) return\n const clip = leadClipEvents(step.duration && step.duration > 0 ? scaleClip(found.clip, step.duration) : found.clip)\n const interval = options.repeatInterval?.() ?? 0.1\n instances = instances.filter((existing) => existing.name !== found.name || existing.delay > 0)\n for (let round = 0; round < (step.repeat ?? 1); round++) {\n instances.push({ name: found.name, clip, time: 0, delay: round * interval, fired: 0 })\n }\n },\n update(dt) {\n for (const instance of instances) {\n const carried = instance.delay > 0 ? dt - instance.delay : dt\n if (instance.delay > 0) {\n instance.delay = Math.max(0, instance.delay - dt)\n if (instance.delay > 0) continue\n }\n instance.time += carried\n fireEvents(instance, instance.time)\n render(instance)\n }\n instances = instances.filter((instance) => instance.delay > 0 || instance.time < instance.clip.duration)\n },\n get playing() {\n return instances.map((instance) => instance.name)\n },\n get running() {\n return instances.filter((instance) => instance.delay <= 0).map((instance) => ({ name: instance.name, time: instance.time, clip: instance.clip }))\n },\n }\n}\n","export const FRAME_PHASES = ['input', 'fixedSimulate', 'lateSimulate', 'present', 'render', 'idle'] as const\nexport type FramePhase = (typeof FRAME_PHASES)[number]\n\n/**\n * Presentation work a system leaves for later frames, run in small units within a shared time budget.\n * Never simulation: nothing that consumes a seeded generator or decides an outcome may wait in a queue.\n */\nexport interface DeferredQueue {\n /** Stable name for stats and logs (see `DEFERRED_QUEUE_ID`). */\n readonly id: string\n /**\n * Units waiting. 0 means idle; the budget skips the queue without calling `run`. `frame` is the budget's frame counter: a queue may\n * report 0 for the rest of a frame (the crease queue does in the frame a panel was torn). Same value for repeated calls in one frame.\n */\n pending(frame?: number): number\n /**\n * Runs units in order until `clock() >= deadline`. Contract: when `pending() > 0` it runs **at least one** unit, even with a deadline\n * already past; it never runs a unit after it saw the deadline pass. Returns how many units it ran.\n */\n run(deadline: number, clock: () => number): number\n /** Runs everything now (synchronous step, clear, dispose). */\n flush(): void\n /**\n * Called by `budget.register`: from now on the owner stops draining on its own (no MessageChannel, no drain inside `update`).\n * Never called by a getter; a queue nobody registered keeps today's internal draining.\n */\n attach?(): void\n /** Called by the unregister function and by `budget.dispose`: the owner goes back to its internal draining. */\n detach?(): void\n}\n\n/** Where a module registers a deferred queue with the host's budget. */\nexport interface DeferredQueueOptions {\n /** Higher runs first. See DEFERRED_PRIORITY. */\n readonly priority: number\n /** `present` runs before the render (the work must show this frame); `idle` runs after it. Default `idle`. */\n readonly phase?: 'present' | 'idle'\n /** Starvation guard: the queue runs at least one unit every this many frames, even with the budget spent. Default 4. */\n readonly minEveryFrames?: number\n /** Milliseconds of every frame kept for this queue before the others share the rest (when it has work). Default 0. */\n readonly reserveMs?: number\n}\n\n/** The ids of the kit's queues: what `DeferredQueue.id` says and what `DEFERRED_PRIORITY` is keyed by. */\nexport const DEFERRED_QUEUE_ID = {\n DESTRUCTION_EVENTS: 'destruction.events',\n BREACH_PAINT: 'floorplan.breach-paint',\n AUDIO_VOICES: 'audio.voices',\n VEHICLE_CREASE: 'vehicles.crease',\n} as const\n\n/** Default priorities and reserves of the kit's queues; a host may override any of them. */\nexport const DEFERRED_PRIORITY = {\n [DEFERRED_QUEUE_ID.DESTRUCTION_EVENTS]: { priority: 300, phase: 'present' },\n [DEFERRED_QUEUE_ID.BREACH_PAINT]: { priority: 250, phase: 'present' },\n [DEFERRED_QUEUE_ID.AUDIO_VOICES]: { priority: 200, phase: 'idle', reserveMs: 1 },\n [DEFERRED_QUEUE_ID.VEHICLE_CREASE]: { priority: 100, phase: 'idle' },\n} as const satisfies Readonly<Record<string, DeferredQueueOptions>>\n\nexport interface DeferredQueueReport {\n readonly ok: boolean\n readonly problems: readonly string[]\n}\n\n/**\n * Checks the `DeferredQueue` contract. `fill` leaves the queue with at least two units waiting (the same call is made on a fresh queue).\n * It cannot prove the queue only carries presentation work: that is a rule of review.\n */\nexport function checkDeferredQueue(queue: DeferredQueue, fill: () => void): DeferredQueueReport {\n const problems: string[] = []\n fill()\n const waiting = queue.pending(1)\n if (waiting < 2) problems.push(`fill() must leave at least 2 units waiting (pending is ${waiting})`)\n if (queue.pending(1) !== waiting) problems.push('pending(frame) changed between two calls in the same frame')\n const ran = queue.run(0, () => 1)\n if (ran !== 1) problems.push(`run with a deadline already past must run exactly one unit (ran ${ran})`)\n if (waiting >= 2 && queue.pending(2) !== waiting - 1) problems.push(`one unit ran but pending went from ${waiting} to ${queue.pending(2)}`)\n try {\n queue.attach?.()\n queue.attach?.()\n queue.detach?.()\n queue.detach?.()\n } catch (error) {\n problems.push(`attach/detach must be idempotent: ${error instanceof Error ? error.message : String(error)}`)\n }\n queue.flush()\n if (queue.pending(3) !== 0) problems.push(`flush must leave nothing pending (pending is ${queue.pending(3)})`)\n if (queue.run(0, () => 1) !== 0) problems.push('run on an empty queue must run no unit')\n return { ok: problems.length === 0, problems }\n}\n","const WARNED_KEY = Symbol.for('@adatechnology/game-contracts.warned')\n\ntype WarnedHolder = { [WARNED_KEY]?: Set<string> }\n\nconst warnedKeys = (): Set<string> => {\n const holder = globalThis as WarnedHolder\n return (holder[WARNED_KEY] ??= new Set<string>())\n}\n\ndeclare const process: { readonly env: { readonly NODE_ENV?: string } }\n\n// The literal `process.env.NODE_ENV` is what bundlers replace; where there is no `process` the reference throws and counts as development.\nconst isProduction = (): boolean => {\n try {\n return process.env.NODE_ENV === 'production'\n } catch {\n return false\n }\n}\n\nconst isQuiet = (): boolean => (globalThis as { __GAME_KIT_QUIET__?: unknown }).__GAME_KIT_QUIET__ === true\n\n/**\n * Warns on the console the first time `key` is seen, and only outside production and when `globalThis.__GAME_KIT_QUIET__` is not `true`: for a silent fallback that keeps working (an adapter that made its own effects\n * world or audio engine because the host lent none). The seen keys live on `globalThis`, so several bundles of the kit on one page warn once together.\n */\nexport const warnOnce = (key: string, message: string): void => {\n if (isQuiet() || isProduction()) return\n const seen = warnedKeys()\n if (seen.has(key)) return\n seen.add(key)\n console.warn(`[game-kit] ${message}`)\n}\n\n/** Forgets what `warnOnce` has seen (tests that count warnings). */\nexport const resetWarnOnce = (): void => warnedKeys().clear()\n","import { warnOnce } from './warn'\n\ntype PlainObject = Record<string, unknown>\ntype Entry = { readonly id: string }\n\n/** Keys that would reach the prototype of the result when a patch comes from parsed JSON. */\nconst UNSAFE_KEYS: ReadonlySet<string> = new Set(['__proto__', 'constructor', 'prototype'])\n\nconst isPlainObject = (value: unknown): value is PlainObject =>\n typeof value === 'object' && value !== null && !Array.isArray(value) && Object.getPrototypeOf(value) === Object.prototype\n\n/** Recursively optional; arrays and functions are replaced as a whole, objects are merged. */\nexport type DeepPartial<TValue> = TValue extends (...args: never[]) => unknown\n ? TValue\n : TValue extends readonly unknown[]\n ? TValue\n : TValue extends object\n ? { [TKey in keyof TValue]?: DeepPartial<TValue[TKey]> }\n : TValue\n\n/** Merges `patch` over `base`: plain objects merge field by field, arrays, functions and primitives replace. `undefined` in the patch is ignored. */\nexport const deepMerge = <TBase extends object>(base: TBase, patch: object | undefined): TBase => {\n if (!patch) return base\n const result: PlainObject = { ...(base as PlainObject) }\n for (const [key, value] of Object.entries(patch)) {\n if (value === undefined || UNSAFE_KEYS.has(key)) continue\n const current = result[key]\n result[key] = isPlainObject(current) && isPlainObject(value) ? deepMerge(current, value) : value\n }\n return result as TBase\n}\n\n/** The shipped entries with the ones from `extra` added or, when the id exists, replaced. */\nexport const mergeById = <TEntry extends Entry>(shipped: readonly TEntry[], extra: readonly TEntry[] | undefined): Map<string, TEntry> => {\n const entries = new Map<string, TEntry>()\n for (const entry of [...shipped, ...(extra ?? [])]) entries.set(entry.id, entry)\n return entries\n}\n\n/** Applies `patch` by id; a patch for an id that does not exist is ignored (and warned about once, in development). */\nexport const applyPatches = <TEntry extends Entry>(entries: Map<string, TEntry>, patches: Readonly<Record<string, DeepPartial<TEntry> | Partial<TEntry>>> | undefined): void => {\n for (const [id, patch] of Object.entries(patches ?? {})) {\n const entry = entries.get(id)\n if (entry) entries.set(id, deepMerge(entry, patch))\n else warnOnce(`registry.patch.${id}`, `patch for \"${id}\" ignored: no entry has that id`)\n }\n}\n\n/** Takes the ids out; an id that does not exist is ignored (and warned about once, in development). */\nexport const removeIds = (entries: Map<string, unknown>, ids: readonly string[] | undefined): void => {\n for (const id of ids ?? []) {\n if (!entries.delete(id)) warnOnce(`registry.remove.${id}`, `remove of \"${id}\" ignored: no entry has that id`)\n }\n}\n","import type { Vec3 } from './destruction'\n\n/**\n * The bench of a module: controls, layers and counters it declares as data. The host keeps the values, draws them in a generic way and hands\n * every change back through `ModuleHost.bench`. Nothing here is specific to a kind of module.\n */\nexport type ControlValue = number | boolean | string\n\nexport interface ChoiceOption {\n readonly id: string\n readonly name: string\n /** Heading the host lists the option under (`optgroup`, a grouped row of buttons). Options of a group must sit next to each other. */\n readonly group?: string\n}\n\ninterface ControlBase {\n /** snake_case, unique across the module's controls, layers and metrics. */\n readonly id: string\n /** Display name, already translated for the locale the host asked for. */\n readonly name: string\n readonly hint?: string\n readonly hidden?: boolean\n /**\n * The change (or the press, for an action) takes a noticeable time, a third of a second or more: the host shows its loading indicator while it works, with this text, or the control's name for `true`.\n * Only the host's own controls panel does it; a change made through `TestRoom.bench().set / act` runs at once.\n */\n readonly slow?: boolean | string\n}\n\nexport interface NumberControl extends ControlBase {\n readonly kind: 'number'\n readonly min: number\n readonly max: number\n readonly step?: number\n readonly unit?: string\n readonly default: number\n}\n\nexport interface BooleanControl extends ControlBase {\n readonly kind: 'boolean'\n readonly default: boolean\n}\n\nexport interface ChoiceControl extends ControlBase {\n readonly kind: 'choice'\n readonly options: readonly ChoiceOption[]\n readonly default: string\n}\n\n/** A button: no value, only the press. */\nexport interface ActionControl extends ControlBase {\n readonly kind: 'action'\n}\n\nexport type ModuleControl = NumberControl | BooleanControl | ChoiceControl | ActionControl\n\n/** Something of the module the viewer turns on or off (smoke, flash, casings). */\nexport interface ModuleLayer {\n readonly id: string\n readonly name: string\n /** On unless `false`. */\n readonly default?: boolean\n}\n\n/** Pulled: the room calls read only when it samples (~4 Hz, or on TestRoom.metrics()). */\nexport interface ModuleMetric {\n readonly id: string\n readonly name: string\n readonly unit?: string\n /** Budget: the host shows a bar and warns past it. */\n readonly max?: number\n readonly digits?: number\n read(): number | string\n}\n\nexport type BenchChange =\n | { readonly kind: 'control'; readonly id: string; readonly value: ControlValue }\n | { readonly kind: 'layer'; readonly id: string; readonly on: boolean }\n | { readonly kind: 'action'; readonly id: string }\n\nexport interface ControlPatch {\n readonly hidden?: boolean\n readonly disabled?: boolean\n readonly options?: readonly ChoiceOption[]\n readonly value?: ControlValue\n}\n\n/** What the host lends a module that declares a bench: the current values and the changes. */\nexport interface ModuleBench {\n value(id: string): ControlValue | undefined\n layer(id: string): boolean\n /** Right after attach returns, the host sends one change per control (not actions) and per layer, in declaration order. */\n onChange(listener: (change: BenchChange) => void): () => void\n /** `value` sets without emitting (no echo loops); `options` falls back to the first option if the value is no longer offered. */\n patch(id: string, patch: ControlPatch): void\n /** Move the host camera (a near / middle / far choice). */\n look(eye: Vec3, target: Vec3): void\n /** Shows a sheet on the host's panel, or takes it down with `null`. A host without a sheet area ignores it. */\n sheet?(sheet: BenchSheet | null): void\n}\n\n/**\n * A card of text the module puts on the host's panel (the sheet of an effect, of a weapon): what it is, its numbers, its steps, its colours and,\n * optionally, a strip of segments over time. Names and texts are already translated for the host's locale.\n */\nexport interface BenchSheet {\n readonly kicker?: string\n readonly title: string\n readonly body?: string\n readonly facts?: readonly { readonly label: string; readonly value: string }[]\n readonly steps?: readonly { readonly at: string; readonly text: string }[]\n readonly swatches?: readonly { readonly color: string; readonly name: string }[]\n readonly note?: string\n /** A picture of the real thing the card is about, with its author and licence: the host shows it on the card, linked to `page`. */\n readonly image?: { readonly url: string; readonly alt: string; readonly credit?: string; readonly page?: string }\n /** A strip of named segments (seconds), with tick marks and a playhead that follows the module metric `metric`. */\n readonly timeline?: {\n readonly segments: readonly { readonly name: string; readonly start: number; readonly end: number; readonly color: string }[]\n readonly ticks: readonly number[]\n readonly metric: string\n }\n}\n\nexport interface BenchReport {\n readonly ok: boolean\n readonly problems: readonly string[]\n}\n\nexport interface BenchDeclaration {\n readonly controls?: readonly ModuleControl[]\n readonly layers?: readonly ModuleLayer[]\n readonly metrics?: readonly ModuleMetric[]\n}\n\nconst SNAKE_CASE = /^[a-z][a-z0-9_]*$/\nconst finite = (n: unknown): n is number => typeof n === 'number' && Number.isFinite(n)\n\nfunction checkControl(control: ModuleControl, problems: string[]): void {\n const label = `control \"${control.id}\"`\n if (control.kind === 'number') {\n if (!finite(control.min) || !finite(control.max) || control.min >= control.max) problems.push(`${label} needs min < max`)\n if (control.step !== undefined && !(finite(control.step) && control.step > 0)) problems.push(`${label} needs a step > 0`)\n if (!finite(control.default) || control.default < control.min || control.default > control.max) problems.push(`${label} default ${String(control.default)} is outside ${control.min}..${control.max}`)\n return\n }\n if (control.kind !== 'choice') return\n if (control.options.length === 0) {\n problems.push(`${label} needs at least one option`)\n return\n }\n const seen = new Set<string>()\n const groups = new Set<string>()\n let previousGroup: string | undefined\n for (const option of control.options) {\n if (seen.has(option.id)) problems.push(`${label} repeats option \"${option.id}\"`)\n seen.add(option.id)\n if (option.group !== undefined && (typeof option.group !== 'string' || option.group === '')) problems.push(`${label} option \"${option.id}\" has an empty group`)\n else if (option.group !== undefined && option.group !== previousGroup && groups.has(option.group)) problems.push(`${label} group \"${option.group}\" is split: its options must be next to each other`)\n if (typeof option.group === 'string' && option.group !== '') groups.add(option.group)\n previousGroup = option.group\n }\n if (!seen.has(control.default)) problems.push(`${label} default \"${control.default}\" is not among its options`)\n}\n\n/** snake_case ids unique across controls, layers and metrics; min < max; step > 0; default in range; options non-empty, unique, default among them, each group in one run; metric max > 0. */\nexport function checkBench(declared: BenchDeclaration): BenchReport {\n const problems: string[] = []\n const ids = new Set<string>()\n const claim = (kind: string, id: string): void => {\n if (!SNAKE_CASE.test(id)) problems.push(`${kind} id \"${id}\" must be snake_case`)\n if (ids.has(id)) problems.push(`duplicate id \"${id}\" across controls, layers and metrics`)\n ids.add(id)\n }\n for (const control of declared.controls ?? []) {\n claim('control', control.id)\n checkControl(control, problems)\n }\n for (const layer of declared.layers ?? []) claim('layer', layer.id)\n for (const metric of declared.metrics ?? []) {\n claim('metric', metric.id)\n if (metric.max !== undefined && !(finite(metric.max) && metric.max > 0)) problems.push(`metric \"${metric.id}\" needs a max > 0`)\n }\n return { ok: problems.length === 0, problems }\n}\n","/** The weather, light and ground as the world is right now. Written by whoever drives the weather, read by whoever reacts to it. */\nexport interface EnvironmentState {\n /** Rain in mm/h; 0 is dry. */\n readonly rain: number\n /** Wind in m/s along x and z, and its strength (the length of that vector). */\n readonly windX: number\n readonly windZ: number\n readonly windSpeed: number\n /** Strongest gust in m/s. */\n readonly gust: number\n /** Render fog far distance in metres. */\n readonly fogFar: number\n /** How far one can see for gameplay, in metres (not the render fog). */\n readonly visibility: number\n /** 0 is full daylight, 1 is the darkest night. */\n readonly nightFactor: number\n readonly temperatureC: number\n /** Wet ground, 0..1: rises with rain and dries after it stops. */\n readonly wetness: number\n}\n\nexport type EnvironmentKey = keyof EnvironmentState\n\n/** A calm dry day (the normal world, before anything went wrong). */\nexport const DEFAULT_ENVIRONMENT: EnvironmentState = {\n rain: 0,\n windX: 0,\n windZ: 0,\n windSpeed: 0,\n gust: 0,\n fogFar: 220,\n visibility: 220,\n nightFactor: 0,\n temperatureC: 20,\n wetness: 0,\n}\n\n/** The host's environment (`ModuleHost.environment`): a store the weather module writes to and the others read. */\nexport interface EnvironmentBus {\n get(): EnvironmentState\n /** Merges `patch` into the state; listeners hear it only when a value really changed. */\n set(patch: Partial<EnvironmentState>): void\n /** Hears every change with the keys that changed. Returns the unsubscribe function. */\n on(listener: (state: EnvironmentState, changed: readonly EnvironmentKey[]) => void): () => void\n}\n\n/** A plain store that implements the bus; the test room and tests use it, a game may bring its own. */\nexport function createEnvironmentBus(initial: Partial<EnvironmentState> = {}): EnvironmentBus {\n let state: EnvironmentState = { ...DEFAULT_ENVIRONMENT, ...initial }\n const listeners = new Set<(state: EnvironmentState, changed: readonly EnvironmentKey[]) => void>()\n return {\n get: () => state,\n set(patch) {\n const changed = (Object.keys(patch) as EnvironmentKey[]).filter((key) => patch[key] !== undefined && patch[key] !== state[key])\n if (changed.length === 0) return\n const next = { ...state } as { -readonly [Key in EnvironmentKey]: number }\n for (const key of changed) next[key] = patch[key] as number\n state = next\n for (const listener of [...listeners]) listener(state, changed)\n },\n on(listener) {\n listeners.add(listener)\n return () => void listeners.delete(listener)\n },\n }\n}\n","import { applyPatches, deepMerge, mergeById, removeIds } from './registry'\nimport type { DeepPartial } from './registry'\n\n/** One category (kind) of items. Defaults and required contracts are inherited from the `extends` chain. */\nexport interface CategoryDef<TDefaults extends object = Record<string, unknown>> {\n readonly id: string\n /** Parent category id; the child inherits its defaults and its required contracts. */\n readonly extends?: string\n /** Field values every entry of this kind starts with; objects merge down the chain, arrays replace. */\n readonly defaults?: DeepPartial<TDefaults>\n /** Contract ids (`ContractChecker.id`) every entry of this kind, or of a descendant, must satisfy. */\n readonly requires?: readonly string[]\n /** An abstract category only groups: entries cannot declare it directly, only its descendants. */\n readonly abstract?: boolean\n}\n\n/** Where a checker is being run: the entry's kind and the chain of categories root first. */\nexport interface ContractContext {\n readonly kind: string\n readonly chain: readonly string[]\n}\n\n/** A named contract: returns the problems of an entry, each a short phrase like `missing leftover.despawnSeconds`. Empty means it holds. */\nexport interface ContractChecker<TEntry> {\n readonly id: string\n check(entry: TEntry, ctx: ContractContext): string[]\n}\n\nexport interface CategoryOptions {\n /** Categories added to the shipped ones; the same id replaces. */\n readonly extra?: readonly CategoryDef[]\n /** Partial changes by id, applied after `extra`. */\n readonly patches?: Readonly<Record<string, DeepPartial<CategoryDef> | Partial<CategoryDef>>>\n /** Ids taken out of the tree (their children are then reported by `check()`). */\n readonly remove?: readonly string[]\n}\n\nexport interface CategoryRegistry {\n get(id: string): CategoryDef | undefined\n has(id: string): boolean\n ids(): string[]\n /** Root first, ending at `id`. Throws on an unknown id, an unknown parent or a cycle. */\n chain(id: string): string[]\n /** `defaults` merged along the chain, root first, so the closest category wins. */\n defaults(id: string): Record<string, unknown>\n /** Union of `requires` along the chain, order kept, without duplicates. */\n requires(id: string): string[]\n /** True when `id` is `ancestorId` or descends from it. */\n isA(id: string, ancestorId: string): boolean\n /** Problems in the tree itself: duplicate ids, unknown `extends`, cycles. */\n check(): string[]\n}\n\nexport interface CategorizedOptions {\n /** Field of the entry that names its category. Default `kind`. */\n readonly kindField?: string\n /** Known gaps by entry id: problems starting with one of these texts go to `allowed`, so the list can shrink over time. */\n readonly allow?: Readonly<Record<string, readonly string[]>>\n}\n\nexport interface CategorizedReport {\n readonly ok: boolean\n readonly problems: string[]\n readonly allowed: string[]\n}\n\nexport const defineCategories = (defs: readonly CategoryDef[], options: CategoryOptions = {}): CategoryRegistry => {\n const problems: string[] = []\n const duplicates = (list: readonly CategoryDef[]): void => {\n const ids = new Set<string>()\n for (const def of list) {\n if (ids.has(def.id)) problems.push(`duplicate category \"${def.id}\"`)\n ids.add(def.id)\n }\n }\n duplicates(defs)\n duplicates(options.extra ?? [])\n\n const entries = mergeById(defs, options.extra)\n applyPatches(entries, options.patches)\n removeIds(entries, options.remove)\n\n const chain = (id: string): string[] => {\n const path: string[] = []\n let current: string | undefined = id\n while (current !== undefined) {\n const def = entries.get(current)\n if (!def) throw new Error(path.length === 0 ? `unknown category \"${current}\"` : `category \"${path[0]}\" has unknown parent \"${current}\"`)\n if (path.includes(current)) throw new Error(`category cycle: ${[...path, current].reverse().join(' -> ')}`)\n path.push(current)\n current = def.extends\n }\n return path.reverse()\n }\n\n const registry: CategoryRegistry = {\n get: (id) => entries.get(id),\n has: (id) => entries.has(id),\n ids: () => [...entries.keys()],\n chain,\n defaults: (id) => chain(id).reduce<Record<string, unknown>>((acc, ancestor) => deepMerge(acc, entries.get(ancestor)?.defaults), {}),\n requires: (id) => {\n const out: string[] = []\n for (const ancestor of chain(id)) for (const contract of entries.get(ancestor)?.requires ?? []) if (!out.includes(contract)) out.push(contract)\n return out\n },\n isA: (id, ancestorId) => {\n try {\n return chain(id).includes(ancestorId)\n } catch {\n return false\n }\n },\n check: () => {\n const found = [...problems]\n for (const [id, def] of entries) {\n if (def.extends !== undefined && !entries.has(def.extends)) found.push(`category \"${id}\" extends unknown \"${def.extends}\"`)\n else {\n try {\n chain(id)\n } catch (error) {\n const message = (error as Error).message\n // The same cycle is found from each of its members; the dedupe keeps one line per distinct message.\n if (message.startsWith('category cycle') && !found.includes(message)) found.push(message)\n }\n }\n }\n return found\n },\n }\n return registry\n}\n\n/** The entry with the defaults of its category underneath: the entry wins, objects merge, arrays replace. */\nexport const resolveEntry = <TEntry extends object>(registry: CategoryRegistry, entry: TEntry, kindField = 'kind'): TEntry =>\n deepMerge(registry.defaults(String((entry as Record<string, unknown>)[kindField])) as TEntry, entry)\n\n/** Checks that each entry has a known, concrete kind and satisfies every contract its chain requires. */\nexport const checkCategorized = <TEntry extends { readonly id: string }>(\n entries: readonly TEntry[],\n registry: CategoryRegistry,\n checkers: readonly ContractChecker<TEntry>[],\n options: CategorizedOptions = {},\n): CategorizedReport => {\n const kindField = options.kindField ?? 'kind'\n const byId = new Map(checkers.map((checker) => [checker.id, checker]))\n const problems: string[] = [...registry.check()]\n const allowed: string[] = []\n\n for (const entry of entries) {\n const kind = String((entry as Record<string, unknown>)[kindField])\n if (!registry.has(kind)) {\n problems.push(`\"${entry.id}\" has unknown kind \"${kind}\"`)\n continue\n }\n if (registry.get(kind)?.abstract) {\n problems.push(`\"${entry.id}\" has abstract kind \"${kind}\"`)\n continue\n }\n let path: string[]\n try {\n path = registry.chain(kind)\n } catch (error) {\n problems.push(`\"${entry.id}\" (${kind}): ${(error as Error).message}`)\n continue\n }\n const resolved = resolveEntry(registry, entry, kindField)\n for (const contract of registry.requires(kind)) {\n const owner = path.find((ancestor) => registry.get(ancestor)?.requires?.includes(contract)) ?? kind\n const checker = byId.get(contract)\n if (!checker) {\n problems.push(`kind \"${kind}\" requires contract \"${contract}\" but no checker is registered`)\n continue\n }\n const prefix = `\"${entry.id}\" (${kind}): `\n for (const problem of checker.check(resolved, { kind, chain: path })) {\n const text = `${prefix}${problem}, required by ${owner}`\n if ((options.allow?.[entry.id] ?? []).some((start) => problem.startsWith(start))) allowed.push(text)\n else problems.push(text)\n }\n }\n }\n return { ok: problems.length === 0, problems: [...new Set(problems)], allowed }\n}\n","/**\n * Where a drawn object comes from. Every builder of the kit that draws a piece (a car of the fleet, a house or a wall, a piece of furniture, a person, an\n * animal, a plant, an item, a weapon) marks the root it returns, and every renderer that draws for the room (effects, debris, liquids, the room itself)\n * marks its own roots, so a host can tell a piece of the kit from something drawn on the spot. Duck-typed on three.js objects (`userData`, `parent`,\n * `children`), so the contracts stay free of three.js.\n */\nexport const KIT_ORIGIN_KEY = 'kitOrigin'\n\n/** What drew an object: the package and the kind of piece (`vehicle`, `structure`, `furniture`, `person`... or `effect`, `room` for what is not a piece). */\nexport interface KitOrigin {\n readonly owner: string\n readonly kind: string\n /** The catalogue id of the piece, when it has one. */\n readonly id?: string\n /** Drawn as a simple stand-in shape because the kit has no model of the piece yet (an item with no team model): a model still to make. */\n readonly standIn?: boolean\n}\n\ninterface Node {\n userData?: Record<string, unknown>\n parent?: Node | null\n children?: readonly Node[]\n name?: string\n visible?: boolean\n isMesh?: boolean\n isPoints?: boolean\n isLine?: boolean\n isSprite?: boolean\n}\n\n/** Marks `object` as drawn by `origin.owner` and returns it. */\nexport function markKitOrigin<T>(object: T, origin: KitOrigin): T {\n const node = object as unknown as Node\n node.userData = node.userData ?? {}\n node.userData[KIT_ORIGIN_KEY] = { ...origin }\n return object\n}\n\n/** The origin of the object or of its nearest marked ancestor; null when nothing up the tree is marked. */\nexport function kitOriginOf(object: unknown): KitOrigin | null {\n for (let node = object as Node | null | undefined; node; node = node.parent) {\n const origin = node.userData?.[KIT_ORIGIN_KEY] as KitOrigin | undefined\n if (origin && typeof origin.owner === 'string') return origin\n }\n return null\n}\n\n/** A drawn thing that no builder of the kit marked: what was drawn on the spot. */\nexport interface UnmarkedDrawing {\n /** The names of the object and its named ancestors, outermost first. */\n readonly path: string\n readonly object: unknown\n}\n\n/** Every visible mesh, line, point cloud or sprite under `root` with no marked ancestor (`root` itself not counted as one). */\nexport function unmarkedDrawings(root: unknown): UnmarkedDrawing[] {\n const out: UnmarkedDrawing[] = []\n const pathOf = (node: Node): string => {\n const names: string[] = []\n for (let n: Node | null | undefined = node; n && n !== root; n = n.parent) if (n.name) names.push(n.name)\n return names.reverse().join(' > ') || '(no name)'\n }\n const walk = (node: Node, marked: boolean): void => {\n if (node.visible === false) return\n const here = marked || (node !== root && Boolean((node.userData?.[KIT_ORIGIN_KEY] as KitOrigin | undefined)?.owner))\n if (!here && (node.isMesh || node.isPoints || node.isLine || node.isSprite)) out.push({ path: pathOf(node), object: node })\n for (const child of node.children ?? []) walk(child, here)\n }\n walk(root as Node, false)\n return out\n}\n","/** A floor rectangle in an object's own space, metres (x across, z along). */\nexport interface Footprint {\n readonly minX: number\n readonly maxX: number\n readonly minZ: number\n readonly maxZ: number\n}\n\n/** What `footprintBlocker` reads of an object: its world matrix (three.js `Object3D`, duck-typed so the contracts stay free of three.js). */\nexport interface FootprintObject {\n readonly matrixWorld: { readonly elements: ArrayLike<number> }\n readonly parent?: unknown\n updateWorldMatrix?(updateParents: boolean, updateChildren: boolean): void\n}\n\n/**\n * The `ModuleHost.addBlocker` function of a solid object standing on the floor: the walking player stays out of `footprint`, a rectangle in the object's own space,\n * so the object blocks turned with it and follows it when it moves. An object out of the scene (no parent) blocks nothing.\n */\nexport function footprintBlocker(object: FootprintObject | (() => FootprintObject | null | undefined), footprint: Footprint | (() => Footprint | null | undefined)): (x: number, z: number, radius: number) => boolean {\n return (x, z, radius) => {\n const o = typeof object === 'function' ? object() : object\n const fp = typeof footprint === 'function' ? footprint() : footprint\n if (!o || !fp || !o.parent) return false\n o.updateWorldMatrix?.(true, false)\n const e = o.matrixWorld.elements\n // the world point in the object's own floor axes: its x and z columns are at right angles, so a projection on each (over its squared length, for a scale) inverts the matrix\n const dx = x - (e[12] as number)\n const dz = z - (e[14] as number)\n const ax = (e[0] as number) ** 2 + (e[1] as number) ** 2 + (e[2] as number) ** 2\n const az = (e[8] as number) ** 2 + (e[9] as number) ** 2 + (e[10] as number) ** 2\n const lx = (dx * (e[0] as number) + dz * (e[2] as number)) / (ax || 1)\n const lz = (dx * (e[8] as number) + dz * (e[10] as number)) / (az || 1)\n return lx > fp.minX - radius && lx < fp.maxX + radius && lz > fp.minZ - radius && lz < fp.maxZ + radius\n }\n}\n","/**\n * The sounds of a body (footsteps, jumps, landings, blows, hurt), as ids every package agrees on: the rule that knows what the body did\n * (`game-player`, a host's own player) names the sound, and the bank that knows how it sounds (`game-audio`'s `BODY_FOLEY_BANK`) answers it.\n * A game swaps the sound of an id (a sample instead of the synthesis) without touching the rule.\n */\n\n/** What the feet touch, by how it sounds (not by what it is made of: a wooden floor and a plywood board both sound `wood`). */\nexport const SURFACE_IDS = ['concrete', 'asphalt', 'wood', 'tile', 'dirt', 'grass', 'gravel', 'sand', 'metal', 'water', 'glass', 'carpet'] as const\nexport type SurfaceId = (typeof SURFACE_IDS)[number]\n\n/** The surface a body stands on when nobody says (the test room's floor is a concrete slab). */\nexport const DEFAULT_SURFACE: SurfaceId = 'concrete'\n\n/** How the feet move: a run hits harder and shorter; a crouched step is the walk, quieter. */\nexport const GAIT_IDS = ['walk', 'run'] as const\nexport type GaitId = (typeof GAIT_IDS)[number]\n\n/** How hard a landing is: `light` for a jump on the spot or a step down (up to about 5 m/s), `heavy` for a drop of more than a metre and a half. */\nexport const LANDING_IDS = ['light', 'heavy'] as const\nexport type LandingId = (typeof LANDING_IDS)[number]\n\n/** The fall speed (m/s) from which a landing is `heavy`. */\nexport const HEAVY_LANDING_SPEED = 5.5\n\nexport type FootstepSoundId = `footstep_${SurfaceId}_${GaitId}`\nexport type LandSoundId = `land_${SurfaceId}_${LandingId}`\n\n/**\n * How a blow is struck, by the body part or the tool that does it. `blade` stabs or slashes, `blunt` is a club, a bat, a pipe or a hammer, `chop` an\n * axe or a machete driven down.\n */\nexport const BLOW_IDS = ['punch', 'kick', 'shove', 'blade', 'blunt', 'chop'] as const\nexport type BlowId = (typeof BLOW_IDS)[number]\n\n/** What the blow meets: a body (flesh and bone, the head apart), something else (the material answers with its own impact), or nothing. */\nexport type BlowTarget = 'body' | 'head' | 'object' | 'air'\n\n/** The sounds of the body that are not a footstep or a landing. */\nexport const BODY_SOUND_IDS = [\n 'jump',\n 'cloth_rustle',\n 'body_fall',\n 'fall_damage',\n 'player_hurt',\n 'player_breath_run',\n 'player_death',\n 'bite',\n 'grab',\n 'punch_swing',\n 'punch_hit_body',\n 'punch_hit_face',\n 'punch_hit_object',\n 'kick_swing',\n 'kick_hit',\n 'kick_hit_object',\n 'shove_two_hands',\n 'knife_swing',\n 'knife_stab',\n 'knife_slash',\n 'knife_hit_object',\n 'blunt_swing',\n 'blunt_hit',\n 'blunt_hit_object',\n 'axe_swing',\n 'axe_chop',\n 'axe_hit_object',\n] as const\nexport type BodySoundId = (typeof BODY_SOUND_IDS)[number]\n\n/** Every sound of a body: what a host plays for the player, a survivor or a zombie. */\nexport type BodyFoleyId = FootstepSoundId | LandSoundId | BodySoundId\n\nexport const footstepSoundId = (surface: SurfaceId, gait: GaitId): FootstepSoundId => `footstep_${surface}_${gait}`\nexport const landSoundId = (surface: SurfaceId, fallSpeed: number): LandSoundId => `land_${surface}_${fallSpeed >= HEAVY_LANDING_SPEED ? 'heavy' : 'light'}`\n\n/** Every footstep and landing id, in the order of the surfaces. */\nexport const FOOTSTEP_SOUND_IDS: readonly FootstepSoundId[] = SURFACE_IDS.flatMap((surface) => GAIT_IDS.map((gait) => footstepSoundId(surface, gait)))\nexport const LAND_SOUND_IDS: readonly LandSoundId[] = SURFACE_IDS.flatMap((surface) => LANDING_IDS.map((landing): LandSoundId => `land_${surface}_${landing}`))\nexport const BODY_FOLEY_IDS: readonly BodyFoleyId[] = [...FOOTSTEP_SOUND_IDS, ...LAND_SOUND_IDS, ...BODY_SOUND_IDS]\n\nconst SWING: Readonly<Record<BlowId, BodySoundId | null>> = {\n punch: 'punch_swing',\n kick: 'kick_swing',\n // two hands pushed out do not whistle: the shove is one sound, at the contact\n shove: null,\n blade: 'knife_swing',\n blunt: 'blunt_swing',\n chop: 'axe_swing',\n}\n\n/**\n * Seconds from the start of a swing's sound to its loudest point (the limb or the tool at full speed, just before the contact). A host that knows when the\n * blow lands starts the swing this long before; one that does not plays the swing now and the hit this long after.\n */\nexport const SWING_LEAD_SECONDS: Readonly<Record<BlowId, number>> = { punch: 0.07, kick: 0.09, shove: 0, blade: 0.05, blunt: 0.1, chop: 0.11 }\n\n/** The swing through the air, played as the blow starts (`null`: the blow has none). */\nexport const swingSoundId = (blow: BlowId): BodySoundId | null => SWING[blow]\n\nconst HIT: Readonly<Record<BlowId, Readonly<Record<Exclude<BlowTarget, 'air'>, BodySoundId>>>> = {\n punch: { body: 'punch_hit_body', head: 'punch_hit_face', object: 'punch_hit_object' },\n kick: { body: 'kick_hit', head: 'kick_hit', object: 'kick_hit_object' },\n shove: { body: 'shove_two_hands', head: 'shove_two_hands', object: 'shove_two_hands' },\n blade: { body: 'knife_stab', head: 'knife_stab', object: 'knife_hit_object' },\n blunt: { body: 'blunt_hit', head: 'blunt_hit', object: 'blunt_hit_object' },\n chop: { body: 'axe_chop', head: 'axe_chop', object: 'axe_hit_object' },\n}\n\n/**\n * The body's side of a blow that lands: the knuckles, the shoe, the blade or the club meeting what it hit. On an object the material's own impact\n * plays too (the wood, the metal); this is the part that says it was a punch and not a shot.\n */\nexport const hitSoundId = (blow: BlowId, target: Exclude<BlowTarget, 'air'>): BodySoundId => HIT[blow][target]\n\n/**\n * The surface a material sounds like underfoot, by the material ids of `game-destruction` and `game-terrain` (unknown ids: `fallback`). Data, so\n * a game with its own materials passes its own table to `surfaceOfMaterial`.\n */\nexport const MATERIAL_SURFACES: Readonly<Record<string, SurfaceId>> = {\n concrete: 'concrete',\n mortar: 'concrete',\n stone: 'concrete',\n brick: 'concrete',\n cobble: 'concrete',\n paver: 'concrete',\n plaster: 'concrete',\n asphalt: 'asphalt',\n wood_soft: 'wood',\n wood_hard: 'wood',\n green_wood: 'wood',\n plywood: 'wood',\n mdf: 'wood',\n ceramic: 'tile',\n plastic: 'tile',\n soil: 'dirt',\n mud: 'dirt',\n clay: 'dirt',\n wax: 'dirt',\n flesh_fruit: 'dirt',\n turf: 'grass',\n foliage: 'grass',\n cactus: 'grass',\n gravel: 'gravel',\n sand: 'sand',\n // no snow surface yet: packed snow crunches closest to sand underfoot\n snow: 'sand',\n steel: 'metal',\n cast_iron: 'metal',\n aluminium: 'metal',\n copper: 'metal',\n water: 'water',\n glass: 'glass',\n tempered_glass: 'glass',\n fabric: 'carpet',\n foam: 'carpet',\n leather: 'carpet',\n rubber: 'carpet',\n paper: 'carpet',\n}\n\nexport const isSurfaceId = (value: unknown): value is SurfaceId => typeof value === 'string' && (SURFACE_IDS as readonly string[]).includes(value)\n\n/** The surface of a material id; a surface id passes through. */\nexport function surfaceOfMaterial(material: string | undefined, table: Readonly<Record<string, SurfaceId>> = MATERIAL_SURFACES, fallback: SurfaceId = DEFAULT_SURFACE): SurfaceId {\n if (material === undefined) return fallback\n if (isSurfaceId(material)) return material\n return table[material] ?? fallback\n}\n","/**\n * @adatechnology/game-contracts: the contracts every game module (vehicles, furniture, plants, houses, weapons) depends on, and nothing else.\n * Types plus tiny pure checkers, no runtime dependencies. The default destruction world, the renderers and the test room are optional.\n */\nexport type {\n ChainDelay,\n Crack,\n DamageStage,\n DamageType,\n DebrisKind,\n Dent,\n DestructibleSpec,\n BlastOptions,\n BlastReport,\n ConfinementOptions,\n ExplosionChain,\n FragmentHitOptions,\n ShelterOptions,\n DestructionEvent,\n DestructionEventType,\n FluidKind,\n Fragment,\n FragmentMark,\n FractureStyle,\n BallisticExtras,\n Hit,\n HitIgnition,\n HitResult,\n Hole,\n JointKind,\n JointSpec,\n JointState,\n MaterialId,\n ObjectState,\n PartShape,\n PartSpec,\n PartBreach,\n PartState,\n PartStatus,\n PartUnits,\n Quat,\n RayHit,\n Reinforcement,\n TensionRebar,\n TunedMassDamper,\n WindExposure,\n WindState,\n PileSpec,\n SoilLayer,\n SoilProfile,\n SoilState,\n StructureRole,\n SurfaceLayer,\n ToolKind,\n Vec3,\n} from './destruction'\nexport type { BusyOptions, BusySink, BusyTask } from './busy'\nexport { blastShove, DEFAULT_BLAST_SHOVE } from './blast-shove'\nexport { bodyMass, FRAGMENT_COVER, KNOCK_CHEST, KNOCK_DOWN_SPEED, KNOCKED_DOWN_ANGLE, knockOf, launchBody, stepKnock, takeLaunch } from './blast-knock'\nexport { blastBodySpeed, bodyImpulse, DEFAULT_BLAST_IMPULSE, sideOnImpulse, sideOnOverpressure } from './blast-impulse'\nexport type { BlastImpulseOptions } from './blast-impulse'\nexport type { Knock } from './blast-knock'\nexport type { BlastShove, BlastShoveOptions, BlastSource } from './blast-shove'\nexport { IMPACT_CONTRACT, checkDestructible, checkHit } from './impact'\nexport type { CheckOptions, DestructibleImpl, ImpactContract, SurfaceRay, SurfaceRayHit } from './impact'\nexport type { CostOptions } from './impact-cost'\nexport { MISSING_BITS } from './body'\nexport type { BodyRegion, BodySlot, SegmentKind } from './body'\nexport { checkSpec } from './spec'\nexport type { CheckSpecOptions, SpecReport } from './spec'\nexport { shotToHit, shotExtras, useToHit } from './weapons'\nexport { DEFAULT_IGNITION_RULES, fillFactor, ignitionChance, resolveIgnitionRules, sparkTargetFactor } from './ignition'\nexport type { IgnitionRules } from './ignition'\nexport type { Shot, Use } from './weapons'\nexport type { ContainerSpec, ItemUseDef, LiquidId } from './fluids'\nexport { sealBlock, sealOpener } from './seal'\nexport type { SealBlock, SealSpec, SealState } from './seal'\nexport type { HandPose, HandTargetSource, HandTargets, MuzzlePose, MuzzleSource, ToolHand } from './hands'\nexport { FIRST_PERSON_LAYER } from './hands'\nexport { TWIST_LIFT, twistStroke } from './twist'\nexport type { TwistOptions, TwistStroke } from './twist'\nexport type { EffectHandle, EffectRequest, EffectSink, Enclosure, EnclosureBox } from './effects'\nexport type { WarmUpProbes } from './warm-up'\nexport { checkAnimation } from './animation'\nexport type { AnimationClipSpec, AnimationEventSpec, AnimationKey, AnimationPose, ItemAnimationContract } from './animation'\nexport { STAGE_EVENT, TOOL_CLIP, checkToolClips, createToolClipPlayer, leadClipEvents, sampleClip, scaleClip, toolAnimationStep } from './tool-animation'\nexport type { ToolAnimationStep, ToolAnimator, ToolClipId, ToolClipPlayer, ToolClipPlayerOptions, ToolClipSet, ToolRig } from './tool-animation'\nexport { DEFERRED_PRIORITY, DEFERRED_QUEUE_ID, FRAME_PHASES, checkDeferredQueue } from './frame'\nexport type { DeferredQueue, DeferredQueueOptions, DeferredQueueReport, FramePhase } from './frame'\nexport type { FrameOptions, AreaPlacement, GroundLayout, GroundZone, HostEvent, HostGraphics, HostTool, HostToolAttachment, ModuleArea, ModuleHost, ModuleView, ModuleItemFluid, ModuleItemSeal, ModuleScenario, PlayerState, ItemSeat, ItemSounds, TestableItem, TestableModule, Thumbnail, ToolCommand, ToolCommandResult, HostReach } from './module'\nexport { applyPatches, deepMerge, mergeById, removeIds } from './registry'\nexport type { DeepPartial } from './registry'\nimport { resetWarnOnce as resetWarnOnceForTests } from './warn'\n\nexport { warnOnce } from './warn'\n/** @deprecated Import it from `@adatechnology/game-contracts/testing`. */\nexport const resetWarnOnce = resetWarnOnceForTests\nexport { checkBench } from './bench'\nexport type {\n ActionControl,\n BenchChange,\n BenchDeclaration,\n BenchReport,\n BenchSheet,\n BooleanControl,\n ChoiceControl,\n ChoiceOption,\n ControlPatch,\n ControlValue,\n ModuleBench,\n ModuleControl,\n ModuleLayer,\n ModuleMetric,\n NumberControl,\n} from './bench'\nexport type { AudioListener, AudioSink, LoopHandle, SoundHandle, SoundRequest } from './audio'\nexport { DEFAULT_ENVIRONMENT, createEnvironmentBus } from './environment'\nexport type { EnvironmentBus, EnvironmentKey, EnvironmentState } from './environment'\nexport { checkCategorized, defineCategories, resolveEntry } from './categories'\nexport type { CategorizedOptions, CategorizedReport, CategoryDef, CategoryOptions, CategoryRegistry, ContractChecker, ContractContext } from './categories'\nexport { KIT_ORIGIN_KEY, kitOriginOf, markKitOrigin, unmarkedDrawings } from './origin'\nexport type { KitOrigin, UnmarkedDrawing } from './origin'\nexport { footprintBlocker } from './footprint'\nexport type { Footprint, FootprintObject } from './footprint'\nexport {\n BLOW_IDS,\n BODY_FOLEY_IDS,\n BODY_SOUND_IDS,\n DEFAULT_SURFACE,\n FOOTSTEP_SOUND_IDS,\n GAIT_IDS,\n HEAVY_LANDING_SPEED,\n LANDING_IDS,\n LAND_SOUND_IDS,\n MATERIAL_SURFACES,\n SURFACE_IDS,\n SWING_LEAD_SECONDS,\n footstepSoundId,\n hitSoundId,\n isSurfaceId,\n landSoundId,\n surfaceOfMaterial,\n swingSoundId,\n} from './foley'\nexport type { BlowId, BlowTarget, BodyFoleyId, BodySoundId, FootstepSoundId, GaitId, LandSoundId, LandingId, SurfaceId } from './foley'\n","import { chainDelayOf, drawChainDelay, FIRE_PRIME_C, shotDamageFractionOf } from './chain'\nimport type { ChainTrigger } from './chain'\nimport { planFragments } from './fracture'\nimport type { PlannedFragment } from './fracture'\nimport { cellsOutside, cellsWithin, clumpCells, marksInBox, planeAxes, unitGrid, unsupportedCells } from './breach'\nimport type { LocalHole, UnitCell } from './breach'\nimport { layersEnergy, layersThickness, MAX_SPALLS, outerLayer, resolveLayer, thinAxisOf } from './layers'\nimport type { LayerRT } from './layers'\nimport { bendBar, clipBarsToBox, clipBarsToDisc, rebarBars, rebarMass } from './rebar'\nimport {\n GRAVITY, bendGeometry, blastImpulse, isReinforced, elasticEnergy, impulseEnergy, isFlexural, lineLoad, momentOfEnergy, resolveFlexure, resolveMasonry, sectionMoments, sectionWidth,\n spanMoment, spanOf, tensionSteel,\n} from './flexure'\nimport type { BendGeometry } from './flexure'\nimport { footingSoil, pileCapacity, pileStiffness, profileOf, resolveSoil, soilAt, solveFoundation, stiffnessCentre, subgradeModulus, yieldSprings } from './soil'\nimport type { SoilSpring } from './soil'\nimport { analyzeWind, damperTuning, exposureOf, gustAt, makeGust, meanHeightFactor, resolveWind, shapeAt, stepSway, tensionCapacity } from './wind'\nimport type { Gust, ResolvedWind, SwayState, SwaySystem, WindAnalysis, WindCase, WindPartInput } from './wind'\nimport { JOINT_DEFAULTS, inferJoints, MATERIALS, partCapacity, partMass, partThickness, partVolume, fragility } from './materials'\nimport { aabbOf, createRng, distanceToShape, quat, quatFromEuler, rayShape, rotateVec, shapeArea, shapeBound, shapeDims, surfacePoint, toLocal, toWorld, vec } from './math'\nimport type { DestructibleImpl } from './contracts'\nimport type {\n AddOptions, Crack, DamageType, DebrisKind, DestructibleSpec, Dent, DestructionEvent, DestructionEventType, DestructionOptions, DestructionSnapshot,\n DamageStage, DestructionWorld, Fragment, FractureStyle, Hit, HitResult, Hole, JointSpec, JointState, MaterialDef, MaterialId, ObjectRuntime, ObjectState, PartRuntime, PartSpec,\n PartState, Quat, RayHit, ToolKind, Vec3, SoilProfile, SoilState, WindOptions, WindState,\n BlastOptions, BlastReport, ConfinementOptions, FragmentHitOptions, ShelterOptions,\n BallisticExtras,\n} from './types'\nimport { ignitionChance, resolveIgnitionRules, sparkTargetFactor } from '@adatechnology/game-contracts'\n\n/** Hit points removed per joule (before the material's `damageScale`). */\n/** Metres: a ductile part this thin or thinner dishes around a bullet hole. */\nconst THIN_SHEET_DISHING = 0.005\n/** Rays of a box sweep start this far inside its face, so that a box touching a wall still sees it. */\nconst SWEEP_BACK = 0.01\n\n/** Where the rays of a box sweep leave from: a grid on each face the box moves toward. */\nfunction sweepOrigins(box: { readonly min: Vec3; readonly max: Vec3 }, d: Vec3, spacing: number): Vec3[] {\n const origins: Vec3[] = []\n const line = (from: number, to: number): number[] => {\n const n = Math.max(1, Math.ceil((to - from) / spacing))\n return Array.from({ length: n + 1 }, (_, i) => from + ((to - from) * i) / n)\n }\n for (const axis of [0, 1, 2] as const) {\n if (Math.abs(d[axis]) < 1e-3) continue\n const lead = d[axis] > 0 ? box.max[axis] - SWEEP_BACK : box.min[axis] + SWEEP_BACK\n const u = ((axis + 1) % 3) as 0 | 1 | 2\n const v = ((axis + 2) % 3) as 0 | 1 | 2\n for (const a of line(box.min[u], box.max[u])) {\n for (const b of line(box.min[v], box.max[v])) {\n const point: Vec3 = [0, 0, 0]\n point[axis] = lead\n point[u] = a\n point[v] = b\n origins.push(point)\n }\n }\n }\n return origins\n}\n/** Metres: a ductile part this thin or thinner is a foil-like sheet (a drink can, a food tin): a blow folds it where it lands, a blade cuts through it. */\nconst THIN_SHEET_CRUSH = 0.0005\n/** Metres: the widest dent a blow leaves on such a sheet; the sheet folds under the fist, the shoe or the corner it lands on, not under the whole reach of the blow. */\nconst THIN_SHEET_CONTACT = 0.025\nconst DMG_PER_J = 0.02\n/** Fraction of a blast's energy that reaches a part at distance 0. */\nconst BLAST_COUPLING = 0.1\n/**\n * Blast options (all off until asked for). Shelter: a part the line from the blast to the target crosses lets through `exp(-r / k)`, `r` being the\n * hit points of the slab it crosses per square metre (`hpPerKg * density * path * damageScale.shelter`). Fragment hits: up to 24 fragments, half their\n * kinetic energy lands as a blunt hit, thrown at most 6 m (and `speed * 0.4 s`) within 10 degrees of their aim. Confinement: 26 rays reaching\n * `1.5 * radius`, multiplier `1 + 1.5 * closedShare^2 * clamp(radius / meanDistance, 0, 2)` up to 3.\n */\nexport const SHELTER_DEFAULTS: Required<ShelterOptions> = { k: 2800, brokenTransmission: 0.5, minPath: 0.005 }\nexport const FRAGMENT_HIT_DEFAULTS: Required<FragmentHitOptions> = { max: 24, energyFactor: 0.5, hitType: 'blunt', range: 6, flightTime: 0.4, spread: 10, aim: 40 }\nexport const CONFINEMENT_DEFAULTS: Required<ConfinementOptions> = { rays: 26, reach: 1.5, gain: 1.5, power: 2, max: 3 }\nconst FLAMMABLE_FLUIDS = ['gas', 'fuel']\n/** Diameter in metres of the opening `vent` makes when none is given: a cylinder valve (about 8 mm). */\nconst VENT_DIAMETER = 0.008\n/** A flame lights a flammable leak when it reaches this temperature (the auto-ignition of propane in air is about 470 °C; a lighter flame is above 1000 °C). */\nconst FLAME_LIGHTS_LEAK_C = 470\n/** Cosine of the tilt past which a `resting` joint lets go: what only lies on a part (a book on a shelf) slides off once it leans past about 30°. */\nconst RESTING_HOLD_COS = Math.cos(Math.PI / 6)\n/** Staged parts: default breach radius (m), blast multiplier on the breach area, area a part must lose to open (m²), and the share of capacity the bare cage keeps. */\nconst BREACH_RADIUS = 0.55\nconst BREACH_BLAST_FACTOR = 6\nconst BREACH_AREA = 0.25\n/** Metres of reach per cube root of kilojoule for a blast to open a breach. */\nconst BREACH_BLAST_REACH = 0.12\n/** Share of the breach reach within which a blast cuts a reinforced member through (a charge at or near contact strips it to its cage); further off it blows its concrete out block by block. */\nconst MEMBER_CUT_REACH = 0.5\n/**\n * What a wall resists a blast with, J/m² (joules per kg that knock a unit out, times its density and thickness), for which `BREACH_BLAST_REACH` holds:\n * the houses' 13 cm brick wall (200 J/kg, 1900 kg/m³). A stronger wall breaks over less, by the cube root (the scaled distance of a blast).\n */\nconst BLAST_REFERENCE_RESISTANCE = 200 * 1900 * 0.13\n/** The edge of what a blast knocks out of a wall of units is ragged: its radius varies by this share around the hole and from unit to unit. */\nconst BLAST_EDGE_RAGGED = 0.3\n/** Out to this many times the radius of the hole, the units are loosened: they take `BLAST_EDGE_WEAR` of what knocks them out, so the next blow finishes them. */\nconst BLAST_EDGE_LOOSE = 1.35\nconst BLAST_EDGE_WEAR = 0.6\nconst RESIDUAL_CAPACITY = 0.15\n/** Long wooden parts break where they are hit: band length along the part (m) and how much longer than wide a part must be. */\nconst SEVER_BAND = 0.1\nconst SEVER_ASPECT = 3\n/** A round that goes through wood tears its exit out in splinters: its damage counts this many times over in the band it crosses. */\nconst SEVER_BALLISTIC = 2\n/** Joules per piece a blow tears out of a material that tears (`MaterialHit.tearJoules` default): a round leaving wood tears 2 to 7 splinters. */\nconst TEAR_JOULES = 150\n/** Running number of the torn pieces (their ids). */\nlet tears = 0\n/** Metres two parts may be apart and still rest on each other, for the span of a beam or a slab. */\nconst SUPPORT_TOLERANCE = 0.05\n/** Unit-sized fragments of a whole wall: at most this many times `maxFragments`. A breach picks its units from a grid of up to `BREACH_GRID_CAP`. */\nconst UNIT_FRAGMENT_FACTOR = 4\nconst BREACH_GRID_CAP = 4096\n/** Joules per kilogram of a masonry unit that knock it out of its wall (a 4 kg brick: two 9 mm rounds, one rifle round). */\nconst CHIP_ENERGY = 200\n/** Share of a hit's energy the units next to the one hit take, at the edge of the unit hit (falls to 0 at the hit's radius). */\nconst CHIP_SPLASH = 0.5\n/** Share of a unit's face the craters of shots take before the rest of the unit comes out. */\nconst CRATER_SPENT = 0.6\n/** Crater widths from a free edge of a wall (its ends, its top) within which a shot tears the corner off out to the edge. */\nconst EDGE_REACH = 1.5\n/** Metres a bar of an exposed cage bows out of the part's plane at full overload (stress 1.5 and up), per metre of bar. */\nconst BAR_BOW = 0.08\n/** Metres of a joint one bullet shakes loose: a joint longer than this takes only its share of the wear. */\nconst BULLET_JOINT_SPAN = 0.3\n\n/** A cut only goes through a slice of the part, so a part longer than `CUT_SLICE` costs no more to cut than a 1 m piece of the same section. */\nconst CUT_SLICE = 1\nconst cutFactorOf = (shape: PartSpec['shape']): number => clamp(Math.max(...shapeDims(shape)) / CUT_SLICE, 1, 50)\n\ninterface PartRT {\n spec: PartSpec\n mat: MaterialDef\n st: PartState\n q: Quat\n /** Current object-local position (the spec's, unless moved by `setPartPose`). */\n pos: Vec3\n mass0: number\n fuel0: number\n area: number\n thickness: number\n /** Slash damage multiplier: longest dimension / 1 m (1..50). */\n cutFactor: number\n dims: Vec3\n bound: number\n rt: PartRuntime\n /** Structural role other than `none`. */\n structural: boolean\n anchored: boolean\n cap: number\n /** Structural part that never had a support path (the spec itself leaves it floating): it is held by its joints like a non-structural part and does not collapse by itself. */\n orphan: boolean\n /** The part has layers, units, reinforcement or a breach: it goes through damage stages. */\n staged: boolean\n /** Axis the part is thinnest along (the wall's depth). */\n thin: number\n layers: LayerRT[]\n /** Bending geometry, for parts in the bending model (`structure.flexure`). */\n bend?: BendGeometry\n /** Span in metres between the supports it rests on now (0: it rests along its whole length, or on nothing). */\n span: number\n /** Supports the span was measured for (indices joined), to measure it again only when they change. */\n spanKey: string\n /** Moment at rest in N m of the section that bends under its weight. */\n restMoment: number\n /** Load in kg that bends it: its own mass and what rests on it away from its supports. */\n bendLoad: number\n /** Overloaded in bending without steel that holds: when it fails it snaps in two instead of crumbling. */\n snap: boolean\n}\n\n/** A crater in the unit `cell` of `p`, along its axis `a` (`b` is the other axis of the plane), from the hit at `at` (part-local). */\ninterface TornToEdgeOptions {\n readonly p: PartRT\n readonly cell: UnitCell\n readonly a: number\n readonly b: number\n readonly at: number\n readonly crater: [number, number]\n readonly reach: number\n /** The unit at this index of the part's grid was knocked out. */\n readonly gone: (index: number) => boolean\n}\n\ninterface JointRT {\n spec: Required<JointSpec>\n st: JointState\n ia: number\n ib: number\n bears: boolean | 'a_on_b' | 'b_on_a'\n /** Object-local position. */\n pos: Vec3\n step: number\n}\n\ninterface ObjRT {\n id: string\n spec: DestructibleSpec\n st: ObjectState\n parts: PartRT[]\n byId: Map<string, PartRT>\n idx: Map<string, number>\n joints: JointRT[]\n jointMap: Map<string, JointRT>\n byPart: Map<string, JointRT[]>\n /** Local bounding sphere. */\n bc: Vec3\n br: number\n active: boolean\n tmp: number[]\n hasStructure: boolean\n /** Set only while `build` solves the structure for the first time. */\n seeding?: boolean\n dirty: boolean\n maxStress: number\n collapsed: Set<string>\n /** Structural parts with no support path to an anchored part (they fall). */\n unsup: boolean[]\n anyAnchor: boolean\n /** Creation order of the object in this world: breaks ties between parts that go off at the same time. */\n order: number\n /** The pose the host gave (`add`, `setTransform`); `st.position`/`st.rotation` are this with the soil's settlement and tilt on top. */\n base: { pos: Vec3; rot: Quat }\n /** The ground under the object (`DestructibleSpec.soil`), when it has foundations on it. */\n soil?: SoilRT\n /** The wind on the object (`DestructionOptions.wind`), when the world has wind and the object is a structure. */\n wind?: WindRT\n}\n\ninterface WindRT {\n /** The wind of the world with this object's `DestructibleSpec.wind` over it, as of the last analysis. */\n cfg: ResolvedWind\n gust: Gust\n /** What the gust was made for (speed, terrain), to make it again when the wind changes. */\n gustKey: string\n analysis: WindAnalysis | null\n /** Parts of the object that went into the analysis, by input index. */\n parts: number[]\n sys: SwaySystem | null\n /** Mass ratio of the damper and its modal weight in the system (0 without one). */\n mu: number\n dyn: SwayState & { peak: number }\n /** Tension capacity of each wall and column, by part index. */\n tension: Map<number, number>\n /** Time and values of the last `sway` event. */\n emitted: { t: number; peak: number; status: WindState['status'] }\n}\n\ninterface SoilRT {\n profile: SoilProfile\n s: number\n a: number\n b: number\n /** Out-of-plumb of the building, as slopes along x and z. */\n imp: [number, number]\n /** Pivot of the tilt: the centre of stiffness at the level of the base, object-local. */\n pivot: Vec3\n /** The structure changed since the soil was last solved. */\n dirty: boolean\n /** Permanent settlement of the soil under each spring (by `SoilSpring` key) from yielding. */\n sets: Map<string, number>\n /** Time and values of the last `settle` event. */\n emitted: { t: number; s: number; tilt: number; status: SoilState['status'] }\n}\n\ninterface Carry {\n parts: Map<string, { st: PartState; rt: PartRuntime }>\n joints: Map<string, { st: JointState; step: number }>\n collapsed?: string[]\n soil?: SoilState\n soilSets?: Record<string, number>\n wind?: [number, number, number, number, number]\n}\n\n\ninterface Loc {\n p: PartRT\n point: Vec3\n normal: Vec3\n dir: Vec3\n pathLen: number\n}\n\ninterface ImplRT {\n impl: DestructibleImpl\n position: Vec3\n rotation: Quat\n /** Part pose overrides set by `setPartPose` (object-local). */\n poses: Map<string, { pos: Vec3; q: Quat }>\n}\n\ninterface Blast {\n point: Vec3\n energy: number\n radius: number\n lethalRadius?: number\n source?: string\n}\n\nconst clamp = (v: number, a: number, b: number) => Math.max(a, Math.min(b, v))\n/** Millimetres of this material a round goes through: the entry of `Hit.penetration` for its `penetrationClass` (else its id) times the material's `penetrationScale`; undefined when the round has none. */\nconst penetrationOf = (mat: MaterialDef, table: Readonly<Record<string, number>> | undefined): number | undefined => {\n if (!table) return undefined\n const v = table[mat.penetrationClass ?? mat.id] ?? table[mat.id]\n return v === undefined ? undefined : v * (mat.penetrationScale ?? 1)\n}\n/** Share of its capacity a structural part still has: a bare rebar cage keeps the reinforcement's residual, a breached part loses what left it. */\n/** Metres from a buried part of the foundation (a footing, a ground beam) within which a blast still reaches it: a charge laid against it. */\nconst BURIED_BLAST_REACH = 0.5\n/** Share of its hit points a part that gave at its cut keeps: it stands, as damaged as the shots left it. */\nconst GIVE_AT_CUT_HP = 0.5\nconst capacityScale = (p: PartRT, borne?: BorneAt, through?: ThroughAt): number => {\n const residual = p.spec.reinforcement?.residualCapacity ?? RESIDUAL_CAPACITY\n if (p.st.stripped) return residual\n const kept = Math.min(p.rt.removed ? 1 - p.rt.removed / p.mass0 : 1, sectionKept(p, residual, borne, through))\n // the cage keeps its share where the concrete is gone\n return Math.max(p.spec.reinforcement ? residual : 0.05, kept)\n}\n/**\n * Largest share of the cross-section the units knocked out of a part took at one place along its length (`PartState.chipped`): a column with half its\n * width shot away at one height carries half. A wall, a partition or a column carries its load down, so its section is across at one height (a wall\n * with a slot shot along its base stands on what is left of it); any other part's length runs along the longer of the two axes of its face. Where `borne`\n * says a lying part rests on what is under it (a bond beam on its wall), its load goes straight down there and a section shot away at that place takes\n * nothing from what it carries.\n */\ntype BorneAt = (local: Vec3, along: number) => boolean\n/** Share of a standing part's load that goes through the place `local` along `along` (part space): what rests on it, and its own weight above that place. */\ntype ThroughAt = (local: Vec3, along: number) => number\n/**\n * The section a part still has for what it carries: at each place a shot took units out, what is left of the section over the share of the load that\n * goes through there (`through`; a column cut just under its top carries the little that is above the cut), the cage's `residual` at least where the\n * concrete is gone. The smallest of them; 1 when nothing was taken out.\n */\nconst sectionKept = (p: PartRT, residual: number, borne?: BorneAt, through?: ThroughAt): number => {\n let kept = 1\n forEachSection(p, borne, (c, along, gone) => {\n const share = through?.(c.center, along) ?? 1\n if (share <= 0) return\n kept = Math.min(kept, Math.max(p.spec.reinforcement ? residual : 0, 1 - gone) / share)\n })\n return kept\n}\nconst sectionLoss = (p: PartRT, borne?: BorneAt): number => {\n let worst = 0\n forEachSection(p, borne, (_c, _along, gone) => {\n worst = Math.max(worst, gone)\n })\n return Math.min(1, worst)\n}\n/** Calls `visit` with each place along a part's length where units were taken out, the axis of its length and the share of the section gone there. */\nconst forEachSection = (p: PartRT, borne: BorneAt | undefined, visit: (c: { readonly center: Vec3 }, along: number, gone: number) => void): void => {\n const cells = p.st.chipped\n if (!cells?.length) return\n const [u, v] = planeAxes(p.thin)\n const role = p.spec.structure?.role\n const up = rotateVec(p.q, [0, 0, 0].map((_, k) => (k === v ? 1 : 0)) as Vec3)\n const upright = Math.abs(up[1]) > 0.7 ? v : Math.abs(rotateVec(p.q, [0, 0, 0].map((_, k) => (k === u ? 1 : 0)) as Vec3)[1]) > 0.7 ? u : -1\n const along = (role === 'wall' || role === 'partition' || role === 'column') && upright >= 0 ? upright : p.dims[u] >= p.dims[v] ? u : v\n const across = along === u ? v : u\n const lying = along !== upright || upright < 0\n for (const c of cells) {\n if (lying && borne?.(c.center, along)) continue\n // the pieces whose span along the length overlaps this one's centre: what is gone across the section there (overlapping pieces count once)\n const spans: Array<[number, number]> = []\n for (const d of cells) if (Math.abs(d.center[along] - c.center[along]) < d.size[along] / 2 + 1e-6) spans.push([d.center[across] - d.size[across] / 2, d.center[across] + d.size[across] / 2])\n spans.sort((a, b) => a[0] - b[0])\n let gone = 0, end = -Infinity\n for (const [a, b] of spans) {\n if (b <= end) continue\n gone += b - Math.max(a, end)\n end = b\n }\n visit(c, along, Math.min(1, gone / Math.max(p.dims[across], 1e-6)))\n }\n}\nconst isLost = (p: PartRT) => p.st.status === 'broken' || p.st.status === 'melted' || p.st.status === 'ashes'\nconst clone = <T>(v: T): T => structuredClone(v)\n/**\n * Fraction of a structural part's hit points lost per second while its stress is above 1. A floor of 0.12 makes even a barely overloaded part\n * give way in about 8 s (a rate proportional to the excess alone never finishes: stress 1.02 would take two minutes), then it grows with the\n * excess and tops out at 0.6: stress 1.1 fails in ~4.5 s, 1.5 in ~1.9 s and anything above 1.7 in ~1.7 s. Deterministic: depends only on stress.\n */\nconst overloadRate = (stress: number) => Math.min(0.6, 0.12 + 0.8 * (stress - 1))\nconst updateBound = (o: ObjRT) => {\n if (!o.parts.length) return\n const c: Vec3 = [0, 0, 0]\n for (const p of o.parts) for (let k = 0; k < 3; k++) c[k] += p.pos[k] / o.parts.length\n let r = 0\n for (const p of o.parts) r = Math.max(r, vec.distance(c, p.pos) + p.bound)\n o.bc = c\n o.br = r\n}\nconst AXIS = { x: 0, y: 1, z: 2 } as const\n\nexport const createDestruction = (options: DestructionOptions = {}): DestructionWorld => {\n const materials = new Map<MaterialId, MaterialDef>()\n for (const m of MATERIALS) materials.set(m.id, m)\n for (const m of options.materials ?? []) materials.set(m.id, m)\n const ambient = options.ambientC ?? 20\n const maxFragments = options.maxFragments ?? 24\n const maxDents = options.maxDents ?? 24\n const maxHoles = options.maxHoles ?? 32\n const fireSpread = options.fireSpread ?? 0.6\n const breachRadius = options.breach?.radius ?? BREACH_RADIUS\n const structureSafety = options.structure?.safetyFactor ?? 1\n const flexure = resolveFlexure(options.structure?.flexure)\n const masonry = resolveMasonry(options.structure?.masonry)\n const soilCfg = resolveSoil(options.soil)\n let windOpts: WindOptions | undefined = options.wind\n let windCfg: ResolvedWind | null = windOpts ? resolveWind(windOpts) : null\n const ignitionRules = resolveIgnitionRules(options.ignition)\n const breachBlastFactor = options.breach?.blastFactor ?? BREACH_BLAST_FACTOR\n const chipEnergy = options.breach?.chipEnergy ?? CHIP_ENERGY\n const chainLinkCap = options.chainLinksPerUpdate !== undefined && options.chainLinksPerUpdate >= 1 ? Math.floor(options.chainLinksPerUpdate) : Infinity\n const rng = createRng(options.seed ?? 1)\n const rnd = () => rng.next()\n\n let time = 0\n let counter = 0\n const objects = new Map<string, ObjRT>()\n const listeners = new Map<string, Set<(e: DestructionEvent) => void>>()\n let cur: DestructionEvent[] = []\n const blasts: Blast[] = []\n /** Glass the blast front has not reached yet: the damage lands when it does (`blastFrontSpeed`). */\n const frontQueue: Array<{ o: ObjRT; p: PartRT; due: number; amount: number; fragEnergy: number; point: Vec3; src?: string }> = []\n const blastFrontSpeed = options.blastFrontSpeed ?? 0\n /** Explosive parts that were primed and wait for their delay. */\n const primed = new Map<PartRT, ObjRT>()\n let orderCounter = 0\n const impls = new Map<string, ImplRT>()\n const taken = (id: string) => objects.has(id) || impls.has(id)\n\n // -------------------------------------------------------------------------------------------------------------------------------------------\n // Events\n // -------------------------------------------------------------------------------------------------------------------------------------------\n\n const emit = (e: DestructionEvent) => {\n cur.push(e)\n options.onEvent?.(e)\n const all = listeners.get('*')\n if (all) for (const fn of [...all]) fn(e)\n const typed = listeners.get(e.type)\n if (typed) for (const fn of [...typed]) fn(e)\n }\n // the kind of the hit being resolved now (`doHit`): every event it emits carries it as `blow`\n let blow: DamageType | undefined\n const base = (o: ObjRT, source?: string): { object: string; time: number; source?: string; blow?: DamageType } => ({\n object: o.id,\n time,\n ...(source === undefined ? {} : { source }),\n ...(blow === undefined ? {} : { blow }),\n })\n\n const pendingCollapse = new Map<ObjRT, string | undefined>()\n let runDepth = 0\n\n /** Blasts queued by parts that exploded; each can prime or set off more parts. It ends: a part goes off once and is primed once, so the queue only grows by parts not yet lost. */\n const drainBlasts = () => {\n for (let blast = blasts.shift(); blast; blast = blasts.shift()) blastWorld(blast.point, blast.energy, blast.radius, blast.source, undefined, undefined, blast.lethalRadius)\n }\n\n const run = <T>(fn: () => T): { value: T; events: DestructionEvent[] } => {\n const prev = cur\n const mine: DestructionEvent[] = []\n cur = mine\n runDepth++\n try {\n const value = fn()\n drainBlasts()\n if (runDepth === 1) flushCollapse()\n return { value, events: mine }\n } finally {\n runDepth--\n cur = prev\n }\n }\n\n // -------------------------------------------------------------------------------------------------------------------------------------------\n // Building objects\n // -------------------------------------------------------------------------------------------------------------------------------------------\n\n const nextId = () => {\n let id: string\n do id = `obj_${++counter}`\n while (taken(id))\n return id\n }\n\n const freshRuntime = (): PartRuntime => ({ meltEmitted: 0, dripT: 0, prevTemp: ambient, shockT: 0, jet: false })\n\n const resolveSpec = (spec: DestructibleSpec): DestructibleSpec => {\n const out = clone(spec)\n const joints = out.joints ?? inferJoints(out.parts, 0.01, materials)\n const structural = (id: string) => {\n const role = out.parts.find((p) => p.id === id)?.structure?.role\n return role !== undefined && role !== 'none'\n }\n out.joints = joints.map((j) => {\n const def = JOINT_DEFAULTS[j.kind]\n return {\n id: j.id ?? `${j.a}~${j.b}`, a: j.a, b: j.b, kind: j.kind, strength: j.strength ?? def.strength, tools: j.tools ?? [...def.tools], seconds: j.seconds ?? def.seconds,\n bears: j.bears ?? (structural(j.a) && structural(j.b)),\n }\n })\n return out\n }\n\n const build = (spec: DestructibleSpec, id: string, pos: Vec3, rot: Quat, carry?: Carry): ObjRT => {\n const st: ObjectState = { id, position: [pos[0], pos[1], pos[2]], rotation: [rot[0], rot[1], rot[2], rot[3]], parts: [], joints: [], groups: [], destroyed: false }\n if (spec.name !== undefined) st.name = spec.name\n const o: ObjRT = {\n id, spec, st, parts: [], byId: new Map(), idx: new Map(), joints: [], jointMap: new Map(), byPart: new Map(), bc: [0, 0, 0], br: 0, active: false, tmp: [], hasStructure: false, dirty: false, maxStress: 0, collapsed: new Set(carry?.collapsed ?? []), unsup: [], anyAnchor: false, order: ++orderCounter,\n base: { pos: [pos[0], pos[1], pos[2]], rot: [rot[0], rot[1], rot[2], rot[3]] },\n }\n for (const ps of spec.parts) {\n if (o.byId.has(ps.id)) throw new Error(`duplicate part id \"${ps.id}\"`)\n const mat = materials.get(ps.material)\n if (!mat) throw new Error(`unknown material \"${ps.material}\" on part \"${ps.id}\"`)\n const mass0 = partMass(ps, mat)\n const maxHp = Math.max(1, ps.hp ?? mass0 * mat.hpPerKg)\n const fuel0 = mat.thermal.ignitionC !== undefined ? mass0 * (mat.thermal.fuelFraction ?? 0) : 0\n const c = carry?.parts.get(ps.id)\n const staged = !!(ps.layers?.length || ps.reinforcement || ps.units || ps.breach)\n const layers = (ps.layers ?? []).map((l, i) => {\n const lm = materials.get(l.material)\n if (!lm) throw new Error(`unknown material \"${l.material}\" on layer ${i} of part \"${ps.id}\"`)\n return resolveLayer(l, i, lm)\n })\n if (ps.reinforcement && !materials.has(ps.reinforcement.material)) throw new Error(`unknown material \"${ps.reinforcement.material}\" on the reinforcement of part \"${ps.id}\"`)\n const pst: PartState = c?.st ?? {\n id: ps.id, material: ps.material, status: 'intact', hp: maxHp, maxHp, mass: mass0, temperature: ambient, burning: false, fuel: fuel0, char: 0, melt: 0,\n dents: [], holes: [], cracks: [], group: 0, ...(staged ? { stage: 0 as DamageStage } : {}),\n }\n if (!c && ps.contains) pst.liters = ps.contains.liters\n const p: PartRT = {\n spec: ps, mat, st: pst, q: quatFromEuler(...(ps.rotation ?? [0, 0, 0])), pos: [ps.position[0], ps.position[1], ps.position[2]], mass0, fuel0, area: shapeArea(ps.shape), thickness: partThickness(ps), cutFactor: cutFactorOf(ps.shape),\n dims: shapeDims(ps.shape), bound: shapeBound(ps.shape), rt: c?.rt ?? { ...freshRuntime(), prevTemp: pst.temperature },\n structural: !!ps.structure && ps.structure.role !== 'none', anchored: !!ps.anchored || ps.structure?.role === 'foundation', cap: ps.structure ? partCapacity(ps, mat, { masonry, flexure }) : 0, orphan: false,\n staged, thin: thinAxisOf(shapeDims(ps.shape)), layers, span: 0, spanKey: '', restMoment: 0, bendLoad: 0, snap: false,\n ...(ps.shape.kind === 'box' && isFlexural(ps, mat, flexure) ? { bend: bendGeometry(ps) } : {}),\n }\n if (p.structural) o.hasStructure = true\n if (p.rt.chainDue !== undefined && !isLost(p)) primed.set(p, o)\n o.idx.set(ps.id, o.parts.length)\n o.parts.push(p)\n o.byId.set(ps.id, p)\n o.st.parts.push(pst)\n o.byPart.set(ps.id, [])\n }\n for (const js of spec.joints ?? []) {\n const r = js as Required<JointSpec>\n const ia = o.idx.get(r.a), ib = o.idx.get(r.b)\n if (ia === undefined || ib === undefined) throw new Error(`joint \"${r.id}\" references an unknown part`)\n if (o.jointMap.has(r.id)) throw new Error(`duplicate joint id \"${r.id}\"`)\n const pa = o.parts[ia], pb = o.parts[ib]\n const A = aabbOf(pa.spec.shape, pa.spec.position, pa.q)\n const B = aabbOf(pb.spec.shape, pb.spec.position, pb.q)\n const pos: Vec3 = [0, 0, 0]\n for (let k = 0; k < 3; k++) pos[k] = (Math.max(A.min[k], B.min[k]) + Math.min(A.max[k], B.max[k])) / 2\n const bears: JointRT['bears'] = r.bears ?? (pa.structural && pb.structural)\n const c = carry?.joints.get(r.id)\n const jst: JointState = c?.st ?? { id: r.id, a: r.a, b: r.b, kind: r.kind, hp: r.strength, maxHp: r.strength, progress: 0, open: false }\n const j: JointRT = { spec: r, st: jst, ia, ib, bears, pos, step: c?.step ?? 0 }\n o.joints.push(j)\n o.jointMap.set(r.id, j)\n o.byPart.get(r.a)!.push(j)\n o.byPart.get(r.b)!.push(j)\n o.st.joints.push(jst)\n }\n // open joints whose parts are no longer both here (left behind by `splitGroup`) stay listed, inert, so callers still see them open\n for (const [jid, c] of carry?.joints ?? []) if (c.st.open && !o.jointMap.has(jid)) o.st.joints.push(c.st)\n updateBound(o)\n o.anyAnchor = o.parts.some((p) => p.anchored)\n o.unsup = o.parts.map(() => false)\n if (windCfg && o.hasStructure && spec.wind !== false) o.wind = newWind(o, carry?.wind)\n const ground = spec.soil ?? soilCfg.site\n if (ground !== undefined && o.parts.some((p) => p.spec.structure?.role === 'foundation')) initSoil(o, profileOf(ground), carry?.soil, carry?.soilSets)\n o.seeding = true\n solveStructure(o)\n o.seeding = false\n if (o.soil && !carry?.soil) settleSoil(o, 0)\n if (o.soil) o.soil.dirty = false\n recomputeGroups(o)\n o.st.destroyed = o.parts.length > 0 && o.parts.every(isLost)\n o.active = o.maxStress > 0.8 || o.parts.some((p) => p.st.burning || p.st.temperature > ambient + 0.5 || (p.st.liters ?? 0) > 0)\n return o\n }\n\n const recomputeGroups = (o: ObjRT) => {\n const n = o.parts.length\n const parent = Array.from({ length: n }, (_, i) => i)\n const find = (i: number): number => {\n while (parent[i] !== i) {\n parent[i] = parent[parent[i]]\n i = parent[i]\n }\n return i\n }\n const union = (a: number, b: number) => {\n parent[find(a)] = find(b)\n }\n const live = (j: JointRT) => !j.st.open && !isLost(o.parts[j.ia]) && !isLost(o.parts[j.ib])\n if (o.unsup.some(Boolean)) {\n // parts that lost every support fall: cut them from the supported pieces; loose non-structural parts follow the part they hang on\n for (const j of o.joints) if (live(j) && !o.unsup[j.ia] && !o.unsup[j.ib]) union(j.ia, j.ib)\n const supported = new Set<number>()\n for (let i = 0; i < n; i++) if (!isLost(o.parts[i]) && !o.unsup[i] && (o.parts[i].structural || o.parts[i].anchored)) supported.add(find(i))\n for (const j of o.joints) {\n if (!live(j) || !(o.unsup[j.ia] || o.unsup[j.ib])) continue\n if (o.unsup[j.ia] && o.unsup[j.ib]) union(j.ia, j.ib)\n else {\n const u = o.unsup[j.ia] ? j.ia : j.ib\n const other = u === j.ia ? j.ib : j.ia\n if (!o.parts[other].structural && !supported.has(find(other))) union(u, other)\n }\n }\n } else for (const j of o.joints) if (live(j)) union(j.ia, j.ib)\n const comps = new Map<number, number[]>()\n for (let i = 0; i < n; i++) {\n if (isLost(o.parts[i])) continue\n const r = find(i)\n const l = comps.get(r)\n if (l) l.push(i)\n else comps.set(r, [i])\n }\n const list = [...comps.values()].map((ix) => ({\n ix,\n anchored: ix.some((i) => o.parts[i].anchored),\n mass: ix.reduce((s, i) => s + o.parts[i].st.mass, 0),\n }))\n list.sort((a, b) => (a.anchored === b.anchored ? (b.mass - a.mass) || (a.ix[0] - b.ix[0]) : a.anchored ? -1 : 1))\n o.st.groups = list.map((g) => g.ix.map((i) => o.parts[i].spec.id))\n for (const p of o.parts) if (isLost(p)) p.st.group = -1\n list.forEach((g, gi) => g.ix.forEach((i) => (o.parts[i].st.group = gi)))\n }\n\n /**\n * Which part `r` rests on over joint `j` (index), or -1 when the joint does not let `r` rest on its other end. A `tie` is a rope: it only pulls,\n * so it holds `r` up only when `r` hangs below the part it is tied to (a lamp from a ceiling), never when that part is beside or under it\n * (a guy rope to a stake in the ground).\n */\n const restsOn = (o: ObjRT, j: JointRT, r: number): number => {\n const b = j.bears\n if (!b) return -1\n const k = b === true ? (j.ia === r ? j.ib : j.ia) : b === 'a_on_b' ? (j.ia === r ? j.ib : -1) : j.ib === r ? j.ia : -1\n if (k < 0 || j.spec.kind !== 'tie') return k\n return partXf(o, o.parts[k]).c[1] > partXf(o, o.parts[r]).c[1] + 1e-6 ? k : -1\n }\n\n // -------------------------------------------------------------------------------------------------------------------------------------------\n // Bending (`structure.flexure`): span from the supports, moment at rest, blast impulse on the span\n // -------------------------------------------------------------------------------------------------------------------------------------------\n\n /** Bumped when a part is posed again, which is what makes a remembered contact box stale. */\n let poseVersion = 0\n const contactMemo = new WeakMap<PartRT, Map<PartRT, { version: number; box: [Vec3, Vec3] }>>()\n\n /** Where `p` touches `support`, as a box in `p`'s own axes (remembered per pair: the solver asks for the same pairs again at every joint that breaks). */\n const contactBox = (p: PartRT, support: PartRT): [Vec3, Vec3] => {\n let byTouching = contactMemo.get(p)\n if (!byTouching) contactMemo.set(p, (byTouching = new Map()))\n const known = byTouching.get(support)\n if (known && known.version === poseVersion) return known.box\n const box = measureContact(p, support)\n byTouching.set(support, { version: poseVersion, box })\n return box\n }\n\n /**\n * The share of a standing part's load that goes through a place along its height: what rests on it plus its own weight above that place, over all it\n * carries. Undefined for a lying part (its length is across the load).\n */\n const throughOf = (p: PartRT): ThroughAt | undefined => {\n const load = p.st.load ?? 0\n if (load <= 0) return undefined\n const above = Math.max(0, load - p.st.mass)\n const up = rotateVec(p.q, [0, 1, 0])\n return (local, along) => {\n const axis: Vec3 = [0, 0, 0]\n axis[along] = 1\n const sign = Math.sign(rotateVec(p.q, axis)[1])\n // only an upright length carries its load down through a section\n if (Math.abs(up[1]) < 0.7 && Math.abs(rotateVec(p.q, axis)[1]) < 0.7) return 1\n const half = p.dims[along] / 2\n const share = clamp((half - sign * local[along]) / Math.max(p.dims[along], 1e-6), 0, 1)\n return (above + p.st.mass * share) / load\n }\n }\n\n /** Where a part rests on its supports: a place along its length (part space) over the contact of one of them. */\n const borneOn = (p: PartRT, supports: readonly PartRT[]): BorneAt | undefined => {\n if (supports.length === 0) return undefined\n const boxes = supports.map((support) => contactBox(p, support))\n return (local, along) => boxes.some(([lo, hi]) => local[along] >= lo[along] - SUPPORT_TOLERANCE && local[along] <= hi[along] + SUPPORT_TOLERANCE)\n }\n\n const measureContact = (p: PartRT, support: PartRT): [Vec3, Vec3] => {\n const A = aabbOf(p.spec.shape, p.pos, p.q), B = aabbOf(support.spec.shape, support.pos, support.q)\n const lo: Vec3 = [0, 0, 0], hi: Vec3 = [0, 0, 0]\n for (let k = 0; k < 3; k++) {\n const a = Math.max(A.min[k], B.min[k]) - SUPPORT_TOLERANCE, b = Math.min(A.max[k], B.max[k]) + SUPPORT_TOLERANCE\n lo[k] = Math.min(a, b)\n hi[k] = Math.max(a, b)\n }\n const out: [Vec3, Vec3] = [[Infinity, Infinity, Infinity], [-Infinity, -Infinity, -Infinity]]\n for (let c = 0; c < 8; c++) {\n const l = toLocal(p.pos, p.q, [c & 1 ? hi[0] : lo[0], c & 2 ? hi[1] : lo[1], c & 4 ? hi[2] : lo[2]])\n for (let k = 0; k < 3; k++) {\n out[0][k] = Math.min(out[0][k], l[k])\n out[1][k] = Math.max(out[1][k], l[k])\n }\n }\n return out\n }\n\n /** The centre of where `above` touches `p`, in object space. */\n const contactCentre = (p: PartRT, above: PartRT): Vec3 => {\n const [lo, hi] = contactBox(p, above)\n return toWorld(p.pos, p.q, [(lo[0] + hi[0]) / 2, (lo[1] + hi[1]) / 2, (lo[2] + hi[2]) / 2])\n }\n\n /**\n * The support of `p` (index into the object's parts, among `lower`) that a load standing at `at` (object space) is over: within one depth of `p` of\n * where `p` rests on it, so the load goes straight down by a strut instead of bending `p` (a load that near a support is not carried in bending,\n * EN 1992-1-1 6.2.2(6)). -1 when it is over none.\n */\n const overSupportAt = (o: ObjRT, p: PartRT, at: Vec3, lower: readonly number[]): number => {\n const g = p.bend!\n const local = toLocal(p.pos, p.q, at)\n const depth = g.gravity >= 0 ? g.dims[g.gravity] : Math.min(...g.depthAxes.map((a) => g.dims[a]))\n let best = -1\n let bestGap = depth\n for (const k of lower) {\n const [a, b] = contactBox(p, o.parts[k])\n let gap = 0\n for (const ax of g.spanAxes) gap = Math.max(gap, a[ax] - local[ax], local[ax] - b[ax])\n if (gap <= bestGap) {\n best = k\n bestGap = gap - 1e-9\n }\n }\n return best\n }\n\n /** The section of `p` that bends along `axis`, with its tension steel and moments (a bare cage keeps only the steel's residual). */\n const sectionOf = (p: PartRT, axis: number) => {\n const g = p.bend!\n const section = { b: sectionWidth(g, axis), h: g.dims[axis] }\n const rebar = tensionSteel(p.spec, g.dims, section, flexure)\n return { section, rebar, ...sectionMoments(p.mat, section, rebar, flexure) }\n }\n\n /** Moment at rest over the moment the section holds, for the supports `lower` (indices) `p` rests on now. Sets `p.span` and `p.restMoment`. */\n const restFlexure = (o: ObjRT, p: PartRT, lower: readonly number[]): number => {\n const g = p.bend!\n const key = lower.join(',')\n if (key !== p.spanKey) {\n p.spanKey = key\n p.span = spanOf(g, lower.map((k) => contactBox(p, o.parts[k])))\n }\n p.restMoment = 0\n if (g.gravity < 0 || p.span <= 0) return 0\n const sec = sectionOf(p, g.gravity)\n p.restMoment = spanMoment(lineLoad(g, p.bendLoad) * Math.abs(g.up[g.gravity]), p.span)\n // once the tension face has cracked only the steel holds; a bare cage keeps its residual share\n const holds = (p.st.cracked ? sec.steel : sec.ultimate) * capacityScale(p)\n return (p.restMoment * structureSafety) / Math.max(holds, 1)\n }\n\n /**\n * A blast bends a beam or a slab: the reflected impulse over the span (`blastImpulse`, averaged over points of the face that takes it) gives the\n * span kinetic energy (`impulseEnergy`), which it takes as strain energy up to a peak moment (`momentOfEnergy`), added to or taken from the moment at\n * rest when the blast pushes along the weight. Past the cracking moment the tension face cracks; a section whose steel does not hold more than that\n * snaps; a reinforced one yields and fails when its plastic rotation (`(U(M) - U(Mu)) / (2 Mu)` per blast, added up) reaches `failRotationDeg`.\n */\n const bendByBlast = (o: ObjRT, p: PartRT, point: Vec3, energy: number, radius: number, reach: number, src?: string) => {\n const g = p.bend\n if (!g || p.span <= 0 || isLost(p) || p.st.stripped || reach <= 0) return\n const s = p.mat.strength!\n if (!s.elasticGPa) return\n const { c, q } = partXf(o, p)\n const near = surfacePoint(p.spec.shape, toLocal(c, q, point))\n const local = toLocal(c, q, point)\n const away = vec.normalize(vec.sub(near.point, local), vec.scale(near.normal, -1))\n let axis = g.depthAxes[0]!\n for (const a of g.depthAxes) if (Math.abs(away[a]) > Math.abs(away[axis])) axis = a\n const cos = Math.abs(away[axis])\n if (cos < 1e-3) return\n const tnt = energy / flexure.tntJoules\n const L = p.span\n const offsets = g.member ? [[-0.5], [-0.25], [0], [0.25], [0.5]] : [[0, 0], [-0.25, 0], [0.25, 0], [0, -0.25], [0, 0.25]]\n const face = -Math.sign(away[axis]) * g.dims[axis] / 2\n let sum = 0\n for (const off of offsets) {\n const sp: Vec3 = [near.point[0], near.point[1], near.point[2]]\n g.spanAxes.forEach((a, k) => (sp[a] = Math.max(-g.dims[a] / 2, Math.min(g.dims[a] / 2, sp[a] + off[k]! * L))))\n sp[axis] = face\n const r = vec.distance(toWorld(c, q, sp), point)\n if (r < radius) sum += blastImpulse(tnt, r, flexure)\n }\n const width = sectionWidth(g, axis)\n const impulse = (sum / offsets.length) * cos * reach * width * L\n const weight = axis === g.gravity ? p.bendLoad : p.st.mass\n const kinetic = impulseEnergy(impulse, (lineLoad(g, weight) / GRAVITY) * L, flexure)\n const sec = sectionOf(p, axis)\n const EI = (s.elasticGPa * 1e9 * sec.section.b * sec.section.h ** 3) / 12\n const along = axis === g.gravity ? -Math.sign(away[axis] * g.up[axis]) : 0\n const dynamic = momentOfEnergy(kinetic, L, EI, flexure.loadFactor)\n const peak = Math.abs(dynamic + along * p.restMoment)\n if (peak <= sec.cracking) return\n if (!p.st.cracked) {\n p.st.cracked = true\n const tension: Vec3 = [near.point[0], near.point[1], near.point[2]]\n tension[axis] = dynamic + along * p.restMoment >= 0 ? -face : face\n const n: Vec3 = [0, 0, 0]\n n[axis] = Math.sign(tension[axis]) || 1\n addCrack(o, p, toWorld(c, q, tension), rotateVec(q, n), sec.section.b, src)\n }\n if (!sec.reinforced) {\n p.snap = true\n failPart(o, p, point, away, kinetic, 12, src, 'snap')\n return\n }\n // a lightly reinforced section (its steel holds less than the concrete did) now carries only what the steel gives\n solveStructure(o)\n if (peak <= sec.steel) return\n const rotation = (elasticEnergy(peak, L, EI, flexure.loadFactor) - elasticEnergy(sec.steel, L, EI, flexure.loadFactor)) / (2 * sec.steel)\n p.rt.hinge = (p.rt.hinge ?? 0) + rotation\n markDamaged(p)\n if (p.rt.hinge >= (flexure.failRotationDeg * Math.PI) / 180) hingeDrop(o, p, src)\n }\n\n /** Span a part is left with on `supports` along its longest axis: twice the farthest any point of it is from a support (a cantilever's is twice its overhang). */\n const freeSpan = (p: PartRT, supports: readonly PartRT[]): number => {\n if (supports.length === 0) return Infinity\n const d = p.dims\n const L = [0, 1, 2].sort((a, b) => d[b] - d[a])[0]\n const spans = supports.map((k) => contactBox(p, k)).map(([lo, hi]) => [lo[L], hi[L]] as const)\n let far = 0\n for (let i = 0; i <= 16; i++) {\n const x = (i / 16 - 0.5) * d[L]\n let near = Infinity\n for (const [lo, hi] of spans) near = Math.min(near, Math.max(lo - x, x - hi, 0))\n far = Math.max(far, near)\n }\n return 2 * far\n }\n\n /** Distribute own mass plus carried load down the bearing graph to the anchored parts; mark parts without any support path. */\n const solveStructure = (o: ObjRT) => {\n o.maxStress = 0\n if (!o.hasStructure) return\n const parts = o.parts\n const n = parts.length\n const dist = new Array<number>(n).fill(-1)\n const ok = (i: number) => parts[i].structural && !isLost(parts[i])\n const isPartition = (i: number) => parts[i].spec.structure?.role === 'partition'\n // a part whose supports leave it a longer span than it holds (`structure.maxSpan`) is out, and so is what stood on it only through it\n const out = new Set<number>()\n let queue: number[] = []\n let lowerOf = new Map<number, number[]>()\n for (;;) {\n dist.fill(-1)\n queue = []\n for (let i = 0; i < n; i++) if (ok(i) && !out.has(i) && parts[i].anchored) {\n dist[i] = 0\n queue.push(i)\n }\n for (let h = 0; h < queue.length; h++) {\n const s = queue[h]\n if (isPartition(s)) continue\n for (const j of o.byPart.get(parts[s].spec.id)!) {\n if (j.st.open || !j.bears) continue\n const r = j.ia === s ? j.ib : j.ia\n if (dist[r] >= 0 || !ok(r) || out.has(r) || restsOn(o, j, r) !== s) continue\n dist[r] = dist[s] + 1\n queue.push(r)\n }\n }\n lowerOf = new Map<number, number[]>()\n let dropped = false\n for (const i of queue) {\n const lower: number[] = []\n for (const j of o.byPart.get(parts[i].spec.id)!) {\n if (j.st.open || !j.bears) continue\n const k = restsOn(o, j, i)\n if (k >= 0 && dist[k] >= 0 && dist[k] < dist[i] && !isPartition(k)) lower.push(k)\n }\n lowerOf.set(i, lower)\n const max = parts[i].spec.structure?.maxSpan\n if (max !== undefined && !parts[i].anchored && freeSpan(parts[i], lower.map((k) => parts[k])) > max) {\n out.add(i)\n dropped = true\n }\n }\n if (!dropped) break\n }\n const incoming = new Array<number>(n).fill(0)\n // the part of the load that bends a beam or a slab: what rests on it away from its supports. A load that stands over a support (a column\n // standing on a slab right over the beam below, a wall right over the wall below) goes straight down to that support with where it stands,\n // and bends that one only if it is away from its own supports\n const bending = new Array<number>(n).fill(0)\n const through: Array<Array<{ at: Vec3; mass: number; over: number }>> = parts.map(() => [])\n const pass = (k: number, at: Vec3, mass: number) => {\n const over = overSupportAt(o, parts[k], at, lowerOf.get(k) ?? [])\n if (over < 0) bending[k] += mass\n else through[k].push({ at, mass, over })\n }\n for (let h = queue.length - 1; h >= 0; h--) {\n const i = queue[h]\n const total = parts[i].st.mass + incoming[i]\n parts[i].st.load = total\n const lower = lowerOf.get(i)!\n for (const k of lower) incoming[k] += total / lower.length\n if (lower.length === 0) continue\n const bulk = parts[i].bend ? parts[i].st.mass + bending[i] : total\n for (const k of lower) if (parts[k].bend) pass(k, contactCentre(parts[k], parts[i]), bulk / lower.length)\n if (parts[i].bend) for (const item of through[i]) if (parts[item.over]?.bend) pass(item.over, item.at, item.mass)\n }\n for (let i = 0; i < n; i++) {\n const p = parts[i]\n o.unsup[i] = false\n if (!p.structural) continue\n if (dist[i] < 0 || isLost(p)) {\n p.st.load = p.st.mass\n p.st.stress = 0\n if (o.seeding && !p.anchored && !isLost(p) && p.st.status !== 'collapsed' && !o.collapsed.has(p.spec.id)) p.orphan = true\n o.unsup[i] = o.anyAnchor && !isLost(p) && !p.orphan\n continue\n }\n p.st.stress = (p.st.load! * structureSafety) / (p.cap * capacityScale(p, borneOn(p, (lowerOf.get(i) ?? []).map((k) => parts[k])), throughOf(p)))\n if (p.bend) {\n p.bendLoad = p.st.mass + bending[i]\n const bent = restFlexure(o, p, lowerOf.get(i) ?? [])\n p.st.flexure = bent\n p.snap = bent > 1 && !p.st.stripped && !sectionOf(p, p.bend.gravity).reinforced\n // a beam or slab carries its load in bending: the load the solver routes through it is not a compression it takes, unless a designer gave\n // it a capacity (`structure.capacity`, `sizeStructure`), which then holds as well\n if (p.spec.structure?.capacity === undefined || bent > p.st.stress) p.st.stress = bent\n }\n if (p.st.stress > o.maxStress) o.maxStress = p.st.stress\n }\n if (o.wind) applyWind(o)\n if (o.maxStress > 0.8) o.active = true\n if (o.soil) o.soil.dirty = true\n }\n\n // -------------------------------------------------------------------------------------------------------------------------------------------\n // Wind (`DestructionOptions.wind`): lateral load that grows with height, the walls and frame that resist it, the sway of the top\n // -------------------------------------------------------------------------------------------------------------------------------------------\n\n const newWind = (o: ObjRT, carried?: [number, number, number, number, number]): WindRT => {\n const cfg = exposureOf(windCfg!, o.spec.wind)\n const [x = 0, v = 0, y = 0, w = 0, peak = 0] = carried ?? []\n return {\n cfg, gust: { freq: [], amp: [], phase: [] }, gustKey: '', analysis: null, parts: [], sys: null, mu: 0, dyn: { x, v, y, w, peak }, tension: new Map(),\n emitted: { t: -Infinity, peak: 0, status: 'ok' },\n }\n }\n\n /** The wind direction in the object's own axes: the horizontal unit vector `[x, z]`. */\n const windDirection = (o: ObjRT, cfg: ResolvedWind): [number, number] => {\n const d = rotateVec(quat.conjugate(o.base.rot), cfg.direction)\n const h = Math.hypot(d[0], d[2])\n return h > 1e-9 ? [d[0] / h, d[2] / h] : [1, 0]\n }\n\n /** Axial force the wind adds to the walls and columns, the design drift and the first mode of the object as it stands now. */\n const applyWind = (o: ObjRT) => {\n const w = o.wind!\n const cfg = (w.cfg = exposureOf(windCfg!, o.spec.wind))\n const terrain = cfg.terrains.get(cfg.terrain)\n if (!terrain) throw new Error(`unknown wind terrain \"${cfg.terrain}\"`)\n const inputs: WindPartInput[] = []\n const at = new Map<number, number>()\n const keep: number[] = []\n let ground = Infinity, foundationTop = -Infinity\n o.parts.forEach((p, i) => {\n if (isLost(p) || isTerrain(p) || o.collapsed.has(p.spec.id) || o.unsup[i]) return\n const box = aabbOf(p.spec.shape, p.pos, p.q)\n const role = p.spec.structure?.role\n const e = p.mat.strength?.elasticGPa\n const kind: WindPartInput['kind'] = role === 'wall' ? 'wall' : role === 'column' ? 'column' : role === 'beam' ? 'beam' : role === 'foundation' ? 'foundation' : 'other'\n at.set(i, inputs.length)\n keep.push(i)\n ground = Math.min(ground, box.min[1])\n if (kind === 'foundation') foundationTop = Math.max(foundationTop, box.max[1])\n inputs.push({ min: box.min, max: box.max, kind, ...(e ? { elasticPa: e * 1e9 } : {}), mass: p.st.mass, ...(p.spec.damper ? { damper: true } : {}) })\n })\n keep.forEach((i, k) => {\n if (inputs[k].kind !== 'column') return\n const beams: number[] = []\n for (const j of o.byPart.get(o.parts[i].spec.id)!) {\n if (j.st.open) continue\n const b = at.get(j.ia === i ? j.ib : j.ia)\n if (b !== undefined && inputs[b].kind === 'beam') beams.push(b)\n }\n inputs[k].beams = beams\n })\n // a slab that rests on a beam works with it as a flange\n keep.forEach((i, k) => {\n if (inputs[k].kind !== 'beam') return\n for (const j of o.byPart.get(o.parts[i].spec.id)!) {\n if (j.st.open) continue\n const q = o.parts[j.ia === i ? j.ib : j.ia]\n const role = q.spec.structure?.role\n if ((role === 'slab' || role === 'roof') && !isLost(q) && q.spec.shape.kind === 'box') {\n inputs[k].slab = q.dims[1]\n break\n }\n }\n })\n const c: WindCase = {\n speed: cfg.speed, direction: windDirection(o, cfg), terrain, cls: cfg.class, topography: cfg.topography, statistical: cfg.statistical, drag: cfg.drag, damping: cfg.damping,\n airDensity: cfg.airDensity, minHeight: cfg.minHeight, bandHeight: cfg.bandHeight, stiffnessFactor: cfg.stiffnessFactor, beamFactor: cfg.beamFactor, loadFactor: cfg.loadFactor,\n chord: cfg.chord, meanRatio: cfg.meanRatio, gustFactor: cfg.gustFactor, flange: cfg.flange,\n }\n const a = inputs.length && cfg.speed > 0 ? analyzeWind(inputs, c, foundationTop > -Infinity ? foundationTop : ground) : null\n w.analysis = a\n w.parts = keep\n for (const p of o.parts) delete p.st.wind\n if (!a) {\n w.sys = null\n delete o.st.wind\n return\n }\n // the load on the walls and columns: compression adds to their load, tension takes from it (and pulls on the part when it passes the dead load)\n keep.forEach((i, k) => {\n const N = a.axial[k]\n const p = o.parts[i]\n if (!N || !p.structural || o.unsup[i]) return\n p.st.wind = N\n const dead = p.st.load ?? p.st.mass\n const force = N * cfg.loadFactor\n let stress = 0\n if (force >= 0) stress = (dead * structureSafety + force / GRAVITY) / (p.cap * capacityScale(p))\n else if (dead + force / GRAVITY < 0) {\n let cap = w.tension.get(i)\n if (cap === undefined) {\n const r = p.spec.reinforcement\n const ratio = p.spec.structure?.rebar?.ratio\n cap = tensionCapacity(p.dims, {\n ...(r ? { reinforcement: r } : {}), ...(ratio ? { ratio } : {}), yieldMPa: flexure.rebarYieldMPa,\n ...(p.mat.strength?.tensileMPa !== undefined ? { tensileMPa: p.mat.strength.tensileMPa } : {}),\n })\n w.tension.set(i, cap)\n }\n stress = Math.min(10, (-(dead + force / GRAVITY) * GRAVITY) / Math.max(cap * capacityScale(p), 1))\n }\n if (stress > (p.st.stress ?? 0)) p.st.stress = stress\n if ((p.st.stress ?? 0) > o.maxStress) o.maxStress = p.st.stress ?? 0\n })\n // the first mode, with the tuned mass damper if there is one\n const key = `${cfg.speed}|${cfg.terrain}|${cfg.topography}|${cfg.statistical}|${cfg.meanRatio}|${cfg.gust.components}|${cfg.gust.maxHz}|${cfg.gust.scale}|${cfg.gust.seed}`\n if (key !== w.gustKey) {\n w.gustKey = key\n const v10 = cfg.speed * cfg.topography * cfg.statistical * meanHeightFactor(10, terrain, a.cls, { meanRatio: cfg.meanRatio, minHeight: cfg.minHeight })\n w.gust = makeGust(v10, cfg.gust)\n }\n let md = 0, spec: PartSpec['damper'] | undefined\n for (const i of keep) {\n const p = o.parts[i]\n if (!p.spec.damper) continue\n const phi = shapeAt(a, p.pos[1] - (foundationTop > -Infinity ? foundationTop : ground))\n md += p.st.mass * phi * phi\n spec ??= p.spec.damper\n }\n const sys: SwaySystem = { M: a.modalMass, K: a.modalStiffness, C: 2 * cfg.damping * a.omega * a.modalMass }\n w.mu = 0\n if (md > 0 && a.modalMass > 0) {\n w.mu = md / a.modalMass\n const tuned = damperTuning(w.mu, cfg.tuning)\n const f = spec?.frequency ?? tuned.frequency * a.frequency\n const zeta = spec?.damping ?? tuned.damping\n sys.damper = { m: md, k: md * (2 * Math.PI * f) ** 2, c: 2 * zeta * md * 2 * Math.PI * f }\n }\n w.sys = a.modalMass > 0 && a.omega > 0 ? sys : null\n const st: WindState = {\n speed: cfg.speed, pressure: a.pressure, shear: a.shear, moment: a.moment, deflection: a.deflection, drift: a.drift, limit: cfg.driftLimit, overturn: Math.min(a.overturn, 1000),\n frequency: a.frequency, lean: a.lean, sway: w.dyn.x, peak: w.dyn.peak, status: a.overturn > 1 ? 'overturn' : a.drift > cfg.driftLimit ? 'drift' : 'ok',\n }\n if (sys.damper) st.damper = { ratio: w.mu, travel: w.dyn.y - w.dyn.x }\n o.st.wind = st\n }\n\n /** Moves the top of the building with the gust (the first mode and the damper, integrated together) and reports `sway` when it changes. */\n const stepWind = (o: ObjRT, dt: number) => {\n const w = o.wind!\n const a = w.analysis\n const st = o.st.wind\n if (!a || !st || !w.sys) return\n const gust = w.gust\n const I = a.intensity\n const force = (t: number) => {\n const n = gustAt(gust, t)\n return a.modalForce * (2 * I * n + I * I * (n * n - 1))\n }\n const wn = Math.max(a.omega, w.sys.damper ? Math.sqrt(w.sys.damper.k / w.sys.damper.m) : 0)\n stepSway(w.dyn, w.sys, time - dt, dt, force, (2 * Math.PI) / wn / 20)\n const d = w.dyn\n d.peak = Math.max(Math.abs(d.x), d.peak * Math.exp(-dt / w.cfg.peakDecay))\n st.sway = d.x\n st.peak = d.peak\n if (st.damper) st.damper.travel = d.y - d.x\n const e = w.emitted\n if (d.peak < e.peak * 0.8) e.peak = d.peak\n if (st.status !== e.status || (time - e.t >= 0.5 && d.peak > e.peak * 1.05 + 1e-3)) {\n w.emitted = { t: time, peak: d.peak, status: st.status }\n const dir = windDirection(o, w.cfg)\n const world = rotateVec(o.base.rot, [dir[0], 0, dir[1]])\n emit({ ...base(o), type: 'sway', sway: d.x, peak: d.peak, drift: st.drift, overturn: st.overturn, frequency: st.frequency, direction: world, status: st.status })\n }\n }\n\n // -------------------------------------------------------------------------------------------------------------------------------------------\n // Soil (`DestructibleSpec.soil`): footings and piles on the ground, settlement, tilt and tipping over\n // -------------------------------------------------------------------------------------------------------------------------------------------\n\n const isTerrain = (p: PartRT) => !!p.spec.tags?.includes('terrain')\n const isFoundation = (p: PartRT) => p.spec.structure?.role === 'foundation' && !isLost(p)\n const slopeTilt = (a: number, b: number) => Math.atan(Math.hypot(a, b))\n\n /** The springs the object stands on: a grid of cells under each footing, one per pile, and a footing under each part that rests on the terrain. */\n const soilSprings = (o: ObjRT, profile: SoilProfile): { springs: Array<SoilSpring & { key: string }>; baseY: number } => {\n const found = o.parts.filter(isFoundation)\n const box = (p: PartRT) => aabbOf(p.spec.shape, p.pos, p.q)\n const surface = profile.surface ?? Math.max(...found.map((p) => box(p).max[1]))\n const prints: Array<{ x0: number; x1: number; z0: number; z1: number; bottom: number; part: PartRT }> = []\n for (const f of found) {\n const b = box(f)\n if (!isTerrain(f)) {\n prints.push({ x0: b.min[0], x1: b.max[0], z0: b.min[2], z1: b.max[2], bottom: b.min[1], part: f })\n continue\n }\n // the ground itself: each structural part that rests on it gets a footing at least `footingWidth` wide (a strip under a wall, a pad under a pillar)\n const fi = o.idx.get(f.spec.id)!\n const width = profile.footingWidth ?? soilCfg.footingWidth\n for (const j of o.byPart.get(f.spec.id)!) {\n if (j.st.open || !j.bears) continue\n const r = j.ia === fi ? j.ib : j.ia\n const q = o.parts[r]\n if (!q.structural || isLost(q) || restsOn(o, j, r) !== fi) continue\n const c = box(q)\n const x0 = Math.max(c.min[0], b.min[0]), x1 = Math.min(c.max[0], b.max[0]), z0 = Math.max(c.min[2], b.min[2]), z1 = Math.min(c.max[2], b.max[2])\n const cx = (x0 + x1) / 2, cz = (z0 + z1) / 2\n const wx = Math.max(width, x1 - x0), wz = Math.max(width, z1 - z0)\n prints.push({ x0: cx - wx / 2, x1: cx + wx / 2, z0: cz - wz / 2, z1: cz + wz / 2, bottom: c.min[1], part: q })\n }\n }\n const springs: Array<SoilSpring & { key: string }> = []\n for (const fp of prints) {\n const wx = Math.max(0.01, fp.x1 - fp.x0), wz = Math.max(0.01, fp.z1 - fp.z0)\n const depth = Math.max(0, surface - fp.bottom)\n const pile = fp.part.spec.structure?.role === 'foundation' ? fp.part.spec.structure.pile : undefined\n if (pile) {\n const count = Math.max(1, Math.round(pile.count ?? 1))\n const nx = Math.ceil(Math.sqrt(count)), nz = Math.ceil(count / nx)\n const cap = pileCapacity(profile, pile, depth, soilCfg.byId).ultimate\n const tip = soilAt(profile, depth + pile.length, soilCfg.byId)\n const k = pileStiffness(pile, fp.part.mat.strength?.elasticGPa ?? soilCfg.pileElasticGPa, tip.elasticMPa, tip.poisson)\n for (let i = 0; i < count; i++) {\n const col = i % nx, row = Math.floor(i / nx)\n springs.push({ key: `${fp.part.spec.id}#${i}`, x: fp.x0 + ((col + 0.5) * wx) / nx, z: fp.z0 + ((row + 0.5) * wz) / nz, hx: wx / (2 * nx), hz: wz / (2 * nz), k, cap })\n }\n continue\n }\n const B = Math.min(wx, wz)\n const g = footingSoil(profile, depth, B, soilCfg.byId, soilCfg.influence)\n const ks = subgradeModulus(g.elasticMPa, g.poisson, B, soilCfg.rigidity)\n const size = Math.max(wx, wz) / Math.max(1, soilCfg.cells)\n const nx = Math.max(1, Math.round(wx / size)), nz = Math.max(1, Math.round(wz / size))\n const area = (wx * wz) / (nx * nz)\n for (let i = 0; i < nx; i++) {\n for (let k = 0; k < nz; k++) {\n springs.push({ key: `${fp.part.spec.id}#${i}.${k}`, x: fp.x0 + ((i + 0.5) * wx) / nx, z: fp.z0 + ((k + 0.5) * wz) / nz, hx: wx / (2 * nx), hz: wz / (2 * nz), k: ks * area, cap: soilCfg.safety * g.allowableKPa * 1000 * area })\n }\n }\n }\n return { springs, baseY: prints.length ? Math.min(...prints.map((fp) => fp.bottom)) : 0 }\n }\n\n /** Weight (N) and centre of mass of what stands on the ground: every part left that is not the terrain and has not fallen. */\n const soilWeight = (o: ObjRT): { w: number; c: Vec3 } => {\n let m = 0\n const c: Vec3 = [0, 0, 0]\n for (const p of o.parts) {\n if (isLost(p) || isTerrain(p) || o.collapsed.has(p.spec.id) || o.unsup[o.idx.get(p.spec.id)!]) continue\n m += p.st.mass\n for (let k = 0; k < 3; k++) c[k] += p.st.mass * p.pos[k]\n }\n return { w: m * GRAVITY, c: m > 0 ? [c[0] / m, c[1] / m, c[2] / m] : c }\n }\n\n const initSoil = (o: ObjRT, profile: SoilProfile, carried?: SoilState, carrySets?: Record<string, number>) => {\n const so: SoilRT = { profile, s: 0, a: 0, b: 0, imp: [0, 0], pivot: [0, 0, 0], dirty: true, sets: new Map(), emitted: { t: -Infinity, s: 0, tilt: 0, status: 'stable' } }\n const { springs, baseY } = soilSprings(o, profile)\n if (!springs.length) return\n const [x0, z0] = stiffnessCentre(springs)\n so.pivot = [x0, baseY, z0]\n // the out-of-plumb is taken the unfavourable way: about the axis the foundations are weakest in, toward the side the weight already leans to\n let ix = 0, iz = 0\n for (const sp of springs) {\n ix += sp.k * (sp.x - x0) ** 2\n iz += sp.k * (sp.z - z0) ** 2\n }\n const { c } = soilWeight(o)\n const along = ix <= iz ? 0 : 1\n const off = along === 0 ? c[0] - x0 : c[2] - z0\n const sign = Math.abs(off) > 1e-6 ? Math.sign(off) : 1\n so.imp = along === 0 ? [sign * soilCfg.imperfection, 0] : [0, sign * soilCfg.imperfection]\n if (carried) {\n const t = Math.tan((carried.tilt * Math.PI) / 180)\n so.s = carried.settlement\n so.a = t * carried.direction[0]\n so.b = t * carried.direction[2]\n so.emitted = { t: -Infinity, s: carried.settlement, tilt: carried.tilt, status: carried.status }\n o.st.soil = clone(carried)\n for (const [k, v] of Object.entries(carrySets ?? {})) so.sets.set(k, v)\n if (carried.status === 'toppled') for (const p of o.parts) p.anchored = false\n }\n o.soil = so\n applySoilPose(o)\n }\n\n /** The settled pose: tilted about the pivot by the slopes of the base, then down by the settlement; `st.position`/`rotation` follow. */\n const applySoilPose = (o: ObjRT) => {\n const so = o.soil\n if (!so) {\n o.st.position = [o.base.pos[0], o.base.pos[1], o.base.pos[2]]\n o.st.rotation = [o.base.rot[0], o.base.rot[1], o.base.rot[2], o.base.rot[3]]\n return\n }\n const angle = slopeTilt(so.a, so.b)\n // the side that goes down `a` per metre of x turns +x toward -y: a rotation about (b, 0, -a)\n const R = angle > 1e-12 ? quat.fromAxisAngle(vec.normalize([so.b, 0, -so.a]), angle) : quat.identity()\n const t = vec.sub(vec.sub(so.pivot, rotateVec(R, so.pivot)), [0, so.s, 0])\n o.st.rotation = quat.normalize(quat.mul(o.base.rot, R))\n o.st.position = vec.add(o.base.pos, rotateVec(o.base.rot, t))\n const lean = Math.hypot(so.a, so.b)\n const st: SoilState = o.st.soil ?? { settlement: 0, tilt: 0, direction: [0, 0, 0], bearing: 0, edge: 0, status: 'stable', offset: { position: [0, 0, 0], rotation: [0, 0, 0, 1] } }\n st.settlement = so.s\n st.tilt = (angle * 180) / Math.PI\n st.direction = lean > 1e-12 ? [so.a / lean, 0, so.b / lean] : [0, 0, 0]\n st.offset = { position: t, rotation: R }\n o.st.soil = st\n }\n\n /** The object tipped over: nothing holds it to the ground any more, everything falls. */\n const topple = (o: ObjRT, src?: string) => {\n for (const p of o.parts) p.anchored = false\n solveStructure(o)\n recomputeGroups(o)\n if (!pendingCollapse.has(o)) pendingCollapse.set(o, src)\n }\n\n /**\n * Solve the ground under the object and move it toward the equilibrium. `dt` 0 (the object is placed): it takes the equilibrium at once, as a\n * building that has stood there. In `update` an elastic change is taken at once and a yielding soil moves the object at `sinkRate`/`tiltRate`;\n * with no stable equilibrium it keeps sinking and leaning until its centre of mass passes the edge of its foundations and it tips over.\n */\n const settleSoil = (o: ObjRT, dt: number) => {\n const so = o.soil!\n const st = o.st.soil\n if (st?.status === 'toppled') return\n const { springs } = soilSprings(o, so.profile)\n for (const sp of springs) sp.set = so.sets.get(sp.key) ?? 0\n const { w, c } = soilWeight(o)\n if (!springs.length || w <= 0) {\n if (springs.length === 0 && w > 0) {\n so.s += soilCfg.sinkRate * dt\n applySoilPose(o)\n o.st.soil!.status = 'yielding'\n }\n return\n }\n const height = Math.max(0, c[1] - so.pivot[1])\n // the wind overturns the building as if its centre of mass stood `M / W` further downwind\n const wa = o.wind?.analysis\n const push = wa ? windDirection(o, o.wind!.cfg) : [0, 0]\n const shift = wa ? wa.moment / w : 0\n const r = solveFoundation(springs, w, c[0] + shift * push[0], c[2] + shift * push[1], height, so.imp, { s: so.s, a: so.a, b: so.b })\n let status: SoilState['status'] = 'stable'\n const sinkStep = soilCfg.sinkRate * dt\n const tiltStep = Math.tan((soilCfg.tiltRate * Math.PI) / 180) * dt\n if (r.stable && (!r.yielded || dt === 0)) {\n so.s = r.s\n so.a = r.a\n so.b = r.b\n } else if (r.stable) {\n const ds = r.s - so.s, da = r.a - so.a, db = r.b - so.b\n const fs = Math.abs(ds) > sinkStep ? sinkStep / Math.abs(ds) : 1\n const lean = Math.hypot(da, db)\n const ft = lean > tiltStep ? tiltStep / lean : 1\n so.s += ds * fs\n so.a += da * ft\n so.b += db * ft\n if (fs < 1 || ft < 1) status = 'yielding'\n } else {\n status = 'yielding'\n if (dt === 0) {\n // placed where the ground cannot hold it: it starts from the elastic settlement and moves from there in `update`\n so.s = w / springs.reduce((sum, sp) => sum + sp.k, 0)\n } else {\n so.s += sinkStep * (r.bearing >= 1 ? 1 : 0.25)\n const lean = Math.hypot(so.a, so.b)\n const ux = lean > 1e-9 ? so.a / lean : Math.sign(so.imp[0]), uz = lean > 1e-9 ? so.b / lean : Math.sign(so.imp[1])\n so.a += ux * tiltStep\n so.b += uz * tiltStep\n }\n }\n if (so.s !== 0 || so.a !== 0 || so.b !== 0) {\n const sets = yieldSprings(springs, so.s, so.a, so.b)\n springs.forEach((sp, i) => {\n if (sets[i] > 0) so.sets.set(sp.key, sets[i])\n })\n }\n applySoilPose(o)\n const out = o.st.soil!\n out.bearing = r.bearing\n out.edge = r.edge\n out.status = status\n // tipped over: the centre of mass, moved over by the lean, passed the edge of the foundations in the direction it leans\n const lean = Math.hypot(so.a, so.b)\n if (lean > 1e-9) {\n const [x0, z0] = [so.pivot[0], so.pivot[2]]\n const ux = so.a / lean, uz = so.b / lean\n const e = (c[0] - x0 + height * (so.a + so.imp[0])) * ux + (c[2] - z0 + height * (so.b + so.imp[1])) * uz\n let edge = 0\n for (const sp of springs) edge = Math.max(edge, (sp.x - x0) * ux + (sp.z - z0) * uz + sp.hx * Math.abs(ux) + sp.hz * Math.abs(uz))\n if (e > edge || slopeTilt(so.a, so.b) > Math.PI / 3) out.status = 'toppled'\n }\n }\n\n const stepSoil = (o: ObjRT, dt: number) => {\n const so = o.soil!\n if (o.st.soil?.status === 'toppled') return\n if (!so.dirty && o.st.soil?.status !== 'yielding') return\n so.dirty = false\n settleSoil(o, dt)\n const st = o.st.soil!\n const e = so.emitted\n const changed = st.status !== e.status || ((time - e.t >= 0.5 || e.t === -Infinity) && (Math.abs(st.tilt - e.tilt) > 0.01 || Math.abs(st.settlement - e.s) > 0.002))\n if (changed) {\n so.emitted = { t: time, s: st.settlement, tilt: st.tilt, status: st.status }\n emit({ ...base(o), type: 'settle', settlement: st.settlement, tilt: st.tilt, direction: rotateVec(o.base.rot, st.direction), bearing: st.bearing, status: st.status })\n }\n if (st.status === 'toppled') topple(o)\n }\n\n /**\n * Ask for a collapse report. It is not computed right away: a blow can break several parts in one go (a column and the roof's supports, or a\n * column whose joint opens just before the column itself fractures), so the groups are examined once, after every loss of the operation.\n */\n const collapseCheck = (o: ObjRT, src?: string) => {\n if (!o.hasStructure || !o.parts.some((p) => p.anchored)) return\n if (!pendingCollapse.has(o)) pendingCollapse.set(o, src)\n }\n\n /** Report the groups of remaining structural parts that lost every anchor (each part is reported once). */\n const flushCollapse = () => {\n for (const [o, src] of [...pendingCollapse]) {\n pendingCollapse.delete(o)\n if (!objects.has(o.id) || objects.get(o.id) !== o) continue\n for (const g of o.st.groups) {\n const ps = g.map((id) => o.byId.get(id)!).filter((p) => !isLost(p) && !o.collapsed.has(p.spec.id))\n if (ps.length === 0 || g.some((id) => o.byId.get(id)!.anchored) || !ps.some((p) => p.structural)) continue\n for (const p of ps) {\n o.collapsed.add(p.spec.id)\n p.st.status = 'collapsed'\n setStage(o, p, 3, {}, src)\n }\n emit({ ...base(o, src), type: 'collapse', parts: ps.map((p) => p.spec.id), mass: ps.reduce((sum, p) => sum + p.st.mass, 0) })\n }\n }\n }\n\n const getObj = (id: string): ObjRT => {\n const o = objects.get(id)\n if (!o) throw new Error(`unknown object \"${id}\"`)\n return o\n }\n const getPart = (o: ObjRT, id: string): PartRT => {\n const p = o.byId.get(id)\n if (!p) throw new Error(`unknown part \"${id}\" in object \"${o.id}\"`)\n return p\n }\n\n // -------------------------------------------------------------------------------------------------------------------------------------------\n // Geometry in world space\n // -------------------------------------------------------------------------------------------------------------------------------------------\n\n const partXf = (o: ObjRT, p: PartRT): { c: Vec3; q: Quat } => ({ c: toWorld(o.st.position, o.st.rotation, p.pos), q: quat.mul(o.st.rotation, p.q) })\n const objLocal = (o: ObjRT, w: Vec3) => toLocal(o.st.position, o.st.rotation, w)\n const objLocalDir = (o: ObjRT, w: Vec3) => rotateVec(quat.conjugate(o.st.rotation), w)\n const jointWorld = (o: ObjRT, j: JointRT) => toWorld(o.st.position, o.st.rotation, j.pos)\n const distToPart = (o: ObjRT, p: PartRT, w: Vec3) => {\n const { c, q } = partXf(o, p)\n return distanceToShape(p.spec.shape, toLocal(c, q, w))\n }\n const partWorldAabb = (o: ObjRT, p: PartRT) => {\n const { c, q } = partXf(o, p)\n return aabbOf(p.spec.shape, c, q)\n }\n\n interface PartRay { t0: number; t1: number; n: Vec3 }\n const rayPartRaw = (pos: Vec3, rot: Quat, spec: PartSpec, pq: Quat, origin: Vec3, d: Vec3, lp: Vec3 = spec.position): PartRay | null => {\n const c = toWorld(pos, rot, lp)\n const q = quat.mul(rot, pq)\n const qi = quat.conjugate(q)\n const r = rayShape(spec.shape, rotateVec(qi, vec.sub(origin, c)), rotateVec(qi, d))\n return r ? { t0: r.t0, t1: r.t1, n: rotateVec(q, r.n0) } : null\n }\n const rayPart = (o: ObjRT, p: PartRT, origin: Vec3, d: Vec3): PartRay | null => rayPartRaw(o.st.position, o.st.rotation, p.spec, p.q, origin, d, p.pos)\n\n const raySphereMiss = (origin: Vec3, d: Vec3, c: Vec3, r: number, maxDist: number): boolean => {\n const oc = vec.sub(origin, c)\n const b = vec.dot(oc, d)\n const cc = vec.dot(oc, oc) - r * r\n if (cc > 0 && b > 0) return true\n const disc = b * b - cc\n if (disc < 0) return true\n return -b - Math.sqrt(disc) > maxDist\n }\n\n const raycastInternal = (origin: Vec3, dir: Vec3, maxDist: number, ignore?: Set<string>, worldOnly = false, precise = false): (RayHit & { pathLen: number }) | null => {\n const d = vec.normalize(dir)\n let best: (RayHit & { pathLen: number }) | null = null\n for (const o of objects.values()) {\n if (raySphereMiss(origin, d, toWorld(o.st.position, o.st.rotation, o.bc), o.br, best ? Math.min(maxDist, best.distance) : maxDist)) continue\n for (const p of o.parts) {\n if (isLost(p) || ignore?.has(`${o.id}\\0${p.spec.id}`)) continue\n const r = rayPart(o, p, origin, d)\n if (!r || r.t0 < 0 || r.t0 > maxDist) continue\n if (p.st.opening && insideOpening(o, p, vec.madd(origin, d, r.t0))) continue\n if (p.st.chipped && insideChip(p, objLocal(o, vec.madd(origin, d, r.t0)))) continue\n if (!best || r.t0 < best.distance) best = { object: o.id, part: p.spec.id, point: vec.madd(origin, d, r.t0), normal: r.n, distance: r.t0, pathLen: r.t1 - r.t0 }\n }\n }\n for (const im of worldOnly ? [] : impls.values()) {\n let boxHit: (RayHit & { pathLen: number }) | null = null\n for (const ps of im.impl.describe().parts) {\n if (ignore?.has(`${im.impl.id}\\0${ps.id}`)) continue\n const ov = im.poses.get(ps.id)\n const r = rayPartRaw(im.position, im.rotation, ps, ov?.q ?? quatFromEuler(...(ps.rotation ?? [0, 0, 0])), origin, d, ov?.pos)\n if (!r || r.t1 < 0 || r.t0 > maxDist) continue\n if (r.t0 < 0) {\n // from inside a box (a round in the cabin): only the impl's own surface says what it meets\n if (precise && im.impl.surfaceRay) boxHit = boxHit ?? { object: im.impl.id, part: ps.id, point: origin, normal: r.n, distance: 0, pathLen: r.t1 }\n continue\n }\n if (!boxHit || r.t0 < boxHit.distance) boxHit = { object: im.impl.id, part: ps.id, point: vec.madd(origin, d, r.t0), normal: r.n, distance: r.t0, pathLen: r.t1 - r.t0 }\n }\n if (!boxHit) continue\n if (precise && im.impl.surfaceRay) {\n const far = best ? Math.min(maxDist, best.distance) : maxDist\n const implId = im.impl.id\n const s = im.impl.surfaceRay({ origin, direction: d, maxDistance: far, ...(ignore ? { ignored: (part: string) => ignore.has(`${implId}\\0${part}`) } : {}) })\n if (s && (!best || s.distance < best.distance)) best = { object: implId, part: s.part, point: s.point, normal: s.normal, distance: s.distance, pathLen: s.pathLen }\n } else if (!best || boxHit.distance < best.distance) best = boxHit\n }\n return best\n }\n\n // impl hosting\n const implHit = (im: ImplRT, hit: Hit): HitResult => {\n let h = hit\n if (hit.space === 'local') {\n h = { ...hit, space: 'world', point: toWorld(im.position, im.rotation, hit.point) }\n if (hit.direction) h.direction = rotateVec(im.rotation, hit.direction)\n }\n const start = cur.length\n for (const e of im.impl.hit(h) ?? []) emit(e.time === undefined ? { ...e, time } : e)\n const mine = cur.slice(start)\n const res: HitResult = { object: im.impl.id, damage: 0, penetrated: false, exitEnergy: 0, events: mine, point: hit.point }\n for (const e of mine) {\n if (e.type === 'damage') res.damage += e.amount\n if (e.type === 'hole' && e.hole.through) res.penetrated = true\n if (res.part === undefined && 'part' in e) res.part = (e as { part: string }).part\n }\n return res\n }\n\n const implJointPos = (im: ImplRT, a: string, b: string): Vec3 | null => {\n const parts = im.impl.describe().parts\n const pa = parts.find((p) => p.id === a), pb = parts.find((p) => p.id === b)\n if (!pa || !pb) return null\n const A = aabbOf(pa.shape, pa.position, quatFromEuler(...(pa.rotation ?? [0, 0, 0])))\n const B = aabbOf(pb.shape, pb.position, quatFromEuler(...(pb.rotation ?? [0, 0, 0])))\n const pos: Vec3 = [0, 0, 0]\n for (let k = 0; k < 3; k++) pos[k] = (Math.max(A.min[k], B.min[k]) + Math.min(A.max[k], B.max[k])) / 2\n return toWorld(im.position, im.rotation, pos)\n }\n\n /** Find the part a hit lands on: a short ray along `dir`, else the nearest part within `tol`. */\n const locate = (o: ObjRT, point: Vec3, dir: Vec3 | undefined, tol: number, only?: PartRT): Loc | null => {\n const cands = only ? [only] : o.parts\n if (dir && vec.length(dir) > 1e-9) {\n const d = vec.normalize(dir)\n const origin = vec.madd(point, d, -0.05)\n let best: Loc | null = null\n let bestT = Infinity\n let inside: Loc | null = null\n for (const p of cands) {\n if (isLost(p)) continue\n const r = rayPart(o, p, origin, d)\n if (!r) continue\n if (r.t0 >= 0 && r.t0 <= 0.15) {\n if (r.t0 < bestT) {\n bestT = r.t0\n best = { p, point: vec.madd(origin, d, r.t0), normal: r.n, dir: d, pathLen: Math.max(r.t1 - r.t0, 1e-4) }\n }\n } else if (r.t0 < 0 && r.t1 > 0 && !inside) {\n inside = { p, point, normal: vec.scale(d, -1), dir: d, pathLen: Math.max(r.t1 - 0.05, p.thickness) }\n }\n }\n if (best) return best\n if (inside) return inside\n }\n let np: PartRT | null = null\n let nd = Infinity\n for (const p of cands) {\n if (isLost(p)) continue\n const dd = distToPart(o, p, point)\n if (dd < nd) {\n nd = dd\n np = p\n }\n }\n if (!np || nd > tol) return null\n const { c, q } = partXf(o, np)\n const sp = surfacePoint(np.spec.shape, toLocal(c, q, point))\n const normal = rotateVec(q, sp.normal)\n return { p: np, point: toWorld(c, q, sp.point), normal, dir: dir && vec.length(dir) > 1e-9 ? vec.normalize(dir) : vec.scale(normal, -1), pathLen: np.thickness }\n }\n\n // -------------------------------------------------------------------------------------------------------------------------------------------\n // Marks on parts\n // -------------------------------------------------------------------------------------------------------------------------------------------\n\n const markDamaged = (p: PartRT) => {\n if (p.st.status === 'intact') p.st.status = 'damaged'\n }\n\n const addDent = (o: ObjRT, p: PartRT, wp: Vec3, wn: Vec3, radius: number, depth: number, src?: string) => {\n const dent: Dent = { point: objLocal(o, wp), normal: objLocalDir(o, wn), radius, depth }\n const arr = p.st.dents\n let ni = -1, nd = Infinity\n for (let i = 0; i < arr.length; i++) {\n const dd = vec.distance(arr[i].point, dent.point)\n if (dd < nd) {\n nd = dd\n ni = i\n }\n }\n if (ni >= 0 && (arr.length >= maxDents || nd < arr[ni].radius * 0.6)) {\n arr[ni].depth = Math.min(0.1, Math.max(arr[ni].depth, depth) + depth * 0.3)\n arr[ni].radius = Math.max(arr[ni].radius, radius)\n } else arr.push(dent)\n markDamaged(p)\n emit({ ...base(o, src), type: 'dent', part: p.spec.id, dent, worldPoint: wp })\n }\n\n const addHole = (o: ObjRT, p: PartRT, wp: Vec3, wn: Vec3, diameter: number, through: boolean, exit?: Vec3, src?: string) => {\n const hole: Hole = { point: objLocal(o, wp), normal: objLocalDir(o, wn), diameter, through }\n p.st.holes.push(hole)\n if (p.st.holes.length > maxHoles) p.st.holes.shift()\n markDamaged(p)\n emit({ ...base(o, src), type: 'hole', part: p.spec.id, hole, worldPoint: wp, ...(exit ? { exitPoint: exit } : {}), ...(p.spec.powder ? { powder: { ...p.spec.powder } } : {}) })\n setStage(o, p, 1, {}, src)\n return hole\n }\n\n const addCrack = (o: ObjRT, p: PartRT, wp: Vec3, wn: Vec3, length: number, src?: string) => {\n const crack: Crack = { point: objLocal(o, wp), normal: objLocalDir(o, wn), length: Math.min(length, Math.max(p.bound, 0.05)), rays: 5 + Math.floor(rnd() * 5) }\n p.st.cracks.push(crack)\n if (p.st.cracks.length > 16) p.st.cracks.shift()\n markDamaged(p)\n emit({ ...base(o, src), type: 'crack', part: p.spec.id, crack, worldPoint: wp })\n setStage(o, p, 1, {}, src)\n }\n\n const debris = (o: ObjRT, p: PartRT, kind: DebrisKind, point: Vec3, normal: Vec3, count: number, speed: number, src?: string, material?: MaterialId) =>\n emit({ ...base(o, src), type: 'debris', part: p.spec.id, kind, point, normal, count, speed, ...(material && material !== p.spec.material ? { material } : {}) })\n\n const holeRate = (hole: Hole, pressurized: boolean) => (pressurized ? 0.5 : 0.1) * (hole.diameter / 0.009)\n\n // -------------------------------------------------------------------------------------------------------------------------------------------\n // Failure, joints\n // -------------------------------------------------------------------------------------------------------------------------------------------\n\n const detachEvents = (o: ObjRT, opened: JointRT[], by: 'break' | 'tool' | 'part_lost', src?: string) => {\n for (const j of opened) emit({ ...base(o, src), type: 'detach', joint: j.spec.id, parts: [j.spec.a, j.spec.b], by, groups: o.st.groups.map((g) => [...g]) })\n }\n\n /** Gravity is all that holds a `resting` joint: tipped past `RESTING_HOLD_COS` (the object's up axis leaning away from the world's), what lay on a part falls off. */\n const slideOffResting = (o: ObjRT, rotation: Quat) => {\n const upY = 1 - 2 * (rotation[0] * rotation[0] + rotation[2] * rotation[2])\n if (upY >= RESTING_HOLD_COS) return\n const opened = o.joints.filter((j) => j.spec.kind === 'resting' && !j.st.open)\n if (opened.length === 0) return\n run(() => {\n for (const j of opened) {\n j.st.open = true\n j.st.openedBy = 'break'\n }\n solveStructure(o)\n recomputeGroups(o)\n detachEvents(o, opened, 'break')\n collapseCheck(o)\n })\n }\n\n const checkDestroyed = (o: ObjRT, src?: string) => {\n if (!o.st.destroyed && o.parts.length > 0 && o.parts.every(isLost)) {\n o.st.destroyed = true\n emit({ ...base(o, src), type: 'destroyed' })\n }\n }\n\n const partLost = (o: ObjRT, p: PartRT, src?: string) => {\n const opened: JointRT[] = []\n for (const j of o.byPart.get(p.spec.id) ?? []) {\n if (j.st.open) continue\n j.st.open = true\n j.st.openedBy = 'part_lost'\n opened.push(j)\n }\n solveStructure(o)\n recomputeGroups(o)\n detachEvents(o, opened, 'part_lost', src)\n collapseCheck(o, src)\n checkDestroyed(o, src)\n }\n\n /**\n * Distance from a world point to the joint's contact region: the overlap box of the two parts' bounds (or, when they only nearly touch, the box\n * of the gap between them). Measuring to the joint centre would make a thick part untouchable: a blow on a trunk's surface is half the trunk's\n * width away from a joint that sits on its axis.\n */\n const jointReach = (o: ObjRT, j: JointRT, point: Vec3): number => {\n const A = partWorldAabb(o, o.parts[j.ia]), B = partWorldAabb(o, o.parts[j.ib])\n let d2 = 0\n for (let k = 0; k < 3; k++) {\n const lo = Math.min(Math.max(A.min[k], B.min[k]), Math.min(A.max[k], B.max[k]))\n const hi = Math.max(Math.max(A.min[k], B.min[k]), Math.min(A.max[k], B.max[k]))\n const d = point[k] < lo ? lo - point[k] : point[k] > hi ? point[k] - hi : 0\n d2 += d * d\n }\n return Math.sqrt(d2)\n }\n /** How far from the contact region a blow still counts: half the smallest dimension of the smaller part, at least 6 cm. */\n const jointReachLimit = (o: ObjRT, j: JointRT): number => {\n const pa = o.parts[j.ia], pb = o.parts[j.ib]\n const small = pa.dims[0] * pa.dims[1] * pa.dims[2] <= pb.dims[0] * pb.dims[1] * pb.dims[2] ? pa : pb\n return Math.max(0.06, 0.5 * Math.min(small.dims[0], small.dims[1], small.dims[2]))\n }\n\n /** Length of the joint's contact region: the longest side of the overlap box of the two parts' bounds (a wall's bed runs the whole wall). */\n const jointLength = (o: ObjRT, j: JointRT): number => {\n const A = partWorldAabb(o, o.parts[j.ia]), B = partWorldAabb(o, o.parts[j.ib])\n let len = 0\n for (let k = 0; k < 3; k++) len = Math.max(len, Math.min(A.max[k], B.max[k]) - Math.max(A.min[k], B.min[k]))\n return len\n }\n\n /**\n * Wears the joints of `p` by `amount`. `span` (metres) is how much of a joint's length the blow reaches: a joint longer than that takes only its share\n * (a bullet loosens the mortar bed under it, not the whole bed of a ten-metre wall), so a row of shots does not bring a wall down. A blow breaks at\n * most that stretch: however hard, it takes no more than its share of the joint's strength, so the bed of a wall gives way once blows broke it all along.\n */\n const wearJoints = (o: ObjRT, p: PartRT, amount: number, near?: Vec3, radius = 0.06, src?: string, split = false, span?: number) => {\n if (amount <= 0) return\n const mine = (o.byPart.get(p.spec.id) ?? []).filter((j) => !j.st.open)\n if (split && mine.length) amount /= mine.length\n for (const j of mine) {\n if (j.st.open) continue\n // the rebar of a reinforced part (a cage, or the tension steel of `structure.rebar`) ties it to the next one: blows do not wear it, only a torch\n // or a saw cuts it (or the part itself giving way)\n if (j.spec.kind === 'rebar' && (isReinforced(o.parts[j.ia].spec) || isReinforced(o.parts[j.ib].spec))) continue\n if (near && jointReach(o, j, near) > Math.max(radius, jointReachLimit(o, j))) continue\n j.st.hp -= span === undefined ? amount : Math.min(amount, j.st.maxHp) * Math.min(1, span / Math.max(jointLength(o, j), 1e-6))\n if (j.st.hp <= 0) {\n j.st.hp = 0\n j.st.open = true\n j.st.openedBy = 'break'\n solveStructure(o)\n recomputeGroups(o)\n detachEvents(o, [j], 'break', src)\n collapseCheck(o, src)\n }\n }\n }\n\n // -------------------------------------------------------------------------------------------------------------------------------------------\n // Damage stages: spall, breach, reinforcement cage\n // -------------------------------------------------------------------------------------------------------------------------------------------\n\n const setStage = (o: ObjRT, p: PartRT, stage: DamageStage, extra: { opening?: { center: Vec3; radius: number }; fragments?: Fragment[] } = {}, src?: string) => {\n if (!p.staged || (p.st.stage ?? 0) >= stage) return\n p.st.stage = stage\n emit({ ...base(o, src), type: 'stage', part: p.spec.id, stage, ...extra })\n }\n\n /** `1` when the outward normal points along the part's local +thin axis, else `-1`. */\n const faceOf = (o: ObjRT, p: PartRT, worldNormal: Vec3): number => (rotateVec(quat.conjugate(partXf(o, p).q), worldNormal)[p.thin] >= 0 ? 1 : -1)\n\n const spallOuter = (o: ObjRT, p: PartRT, wp: Vec3, face: number, normal: Vec3, radius: number, src?: string) => {\n if (p.layers.length === 0) return\n const lp = objLocal(o, wp)\n const layer = outerLayer(p.layers, p.rt.spalls, face, lp)\n if (!layer) return\n const spalls = (p.rt.spalls ??= [])\n spalls.push([layer.index, face, lp[0], lp[1], lp[2], radius])\n if (spalls.length > MAX_SPALLS) spalls.shift()\n markDamaged(p)\n emit({ ...base(o, src), type: 'spall', part: p.spec.id, layer: layer.index, point: wp, area: Math.PI * radius * radius })\n debris(o, p, layer.mat.hitDebris, wp, normal, 5, 2, src, layer.mat.id)\n setStage(o, p, 1, {}, src)\n }\n\n /** A crater in the bare surface of a part (concrete): the surface around the hit flakes off with its dust, drawn as a spall of the core (`layer` -1). */\n const crater = (o: ObjRT, p: PartRT, wp: Vec3, normal: Vec3, radius: number, src?: string) => {\n markDamaged(p)\n emit({ ...base(o, src), type: 'spall', part: p.spec.id, layer: -1, point: wp, area: Math.PI * radius * radius })\n debris(o, p, p.mat.breakDebris, wp, normal, 6, 1.5, src)\n setStage(o, p, 1, {}, src)\n }\n\n const insideOpening = (o: ObjRT, p: PartRT, objectPoint: Vec3): boolean => {\n const op = p.st.opening\n if (!op) return false\n const [u, v] = planeAxes(p.thin)\n const lp = toLocal(p.pos, p.q, objectPoint)\n const lc = toLocal(p.pos, p.q, op.center)\n return Math.hypot(lp[u] - lc[u], lp[v] - lc[v]) <= op.radius\n }\n\n /** Square metres of wall a blow removes: the volume its damage takes out, over the thickness it crosses. */\n const breachAreaOf = (p: PartRT, damage: number, blast: boolean): number =>\n (damage / (p.mat.hpPerKg * p.mat.density) / Math.max(p.thickness, 0.005)) * (blast ? breachBlastFactor : 1)\n\n const localHolesOf = (p: PartRT): LocalHole[] =>\n p.st.holes.map((h) => ({ point: toLocal(p.pos, p.q, h.point), normal: rotateVec(quat.conjugate(p.q), h.normal), diameter: h.diameter }))\n\n const unitsOf = (p: PartRT) => p.spec.units ?? { size: [p.mat.fragmentSize?.[1] ?? 0.2, p.mat.fragmentSize?.[1] ?? 0.2, p.thickness] as Vec3, bond: 'stack' as const }\n\n const FRAGMENT_SHAPE = { shatter: 'shard', splinter: 'splinter', tear: 'scrap' } as const\n\n /**\n * Unit-sized fragments of `cells` (part-local), thrown from `hitW`; the holes that fell on a unit stay on it as `marks`. `inner`: drawn in the colour of\n * the inside of the material (a brick knocked out of its plaster), not the part's paint.\n */\n const cellFragments = (o: ObjRT, p: PartRT, cells: readonly UnitCell[], hitW: Vec3, dir: Vec3 | null, speed: number, mass: number, tag: string, inner = false): Fragment[] => {\n const { c, q } = partXf(o, p)\n const holes = p.st.holes.length > 0 ? localHolesOf(p) : []\n const [u, v] = planeAxes(p.thin)\n const faceArea = (cell: UnitCell) => cell.size[u] * cell.size[v]\n const total = cells.reduce((sum, cell) => sum + faceArea(cell), 0) || 1\n const shape = p.spec.units ? 'chunk' : FRAGMENT_SHAPE[p.mat.fracture as keyof typeof FRAGMENT_SHAPE] ?? 'chunk'\n return cells.map((cell, i) => {\n const cw = toWorld(c, q, cell.center)\n const out = vec.normalize(vec.sub(cw, hitW), [0, 1, 0])\n const dv = dir ? vec.normalize(vec.madd(out, dir, 0.6)) : out\n const k = speed * (0.6 + 0.8 * rnd())\n const marks = marksInBox(cell.center, cell.size, undefined, holes)\n return {\n id: `${p.spec.id}#${tag}${i}`, part: p.spec.id, material: p.spec.material, shape, center: cw, size: [cell.size[0], cell.size[1], cell.size[2]], rotation: q,\n velocity: [dv[0] * k, dv[1] * k + 0.5 * rnd(), dv[2] * k], angularVelocity: [(rnd() - 0.5) * 8, (rnd() - 0.5) * 8, (rnd() - 0.5) * 8],\n mass: (mass * faceArea(cell)) / total, ...(marks.length > 0 ? { marks } : {}), ...(inner ? { inner } : {}),\n }\n })\n }\n\n const worldBars = (o: ObjRT, p: PartRT, bars: ReadonlyArray<readonly [Vec3, Vec3]>): Array<[Vec3, Vec3]> => {\n const { c, q } = partXf(o, p)\n return bars.map(([a, b]) => [toWorld(c, q, a), toWorld(c, q, b)])\n }\n\n /** A blow that made through damage of `area` m² at `wp` (world): adds up with the earlier ones within the breach radius, and opens the part past its threshold. */\n const addBreach = (o: ObjRT, p: PartRT, wp: Vec3, area: number, energy: number, dir: Vec3 | null, src?: string) => {\n if (!p.staged || area <= 0 || (p.st.stage ?? 0) >= 2 || p.st.stripped || isLost(p)) return\n const lp = objLocal(o, wp)\n const list = (p.rt.breach ??= [])\n list.push([lp[0], lp[1], lp[2], area])\n if (list.length > MAX_SPALLS) list.shift()\n let total = 0\n const sum: Vec3 = [0, 0, 0]\n for (const [x, y, z, a] of list) {\n if (vec.distance([x, y, z], lp) > breachRadius) continue\n total += a\n sum[0] += x * a\n sum[1] += y * a\n sum[2] += z * a\n }\n if (total < (p.spec.breach?.area ?? BREACH_AREA)) return\n openBreach(o, p, [sum[0] / total, sum[1] / total, sum[2] / total], total, energy, dir, src)\n }\n\n /** The unit grid of a part with `units`, at the cap a breach uses (the same cells every time, so a unit keeps its index). Not saved: it is rebuilt from the spec. */\n const unitGrids = new WeakMap<PartRT, UnitCell[]>()\n const gridOf = (p: PartRT): UnitCell[] => {\n let grid = unitGrids.get(p)\n if (!grid) unitGrids.set(p, (grid = unitGrid(p.dims, p.thin, unitsOf(p), BREACH_GRID_CAP)))\n return grid\n }\n\n /** The object-local point falls in a unit that was knocked out of the part (`PartState.chipped`). */\n const insideChip = (p: PartRT, objectPoint: Vec3): boolean => {\n const cells = p.st.chipped\n if (!cells?.length) return false\n const [u, v] = planeAxes(p.thin)\n const lp = toLocal(p.pos, p.q, objectPoint)\n return cells.some((c) => Math.abs(lp[u] - c.center[u]) <= c.size[u] / 2 && Math.abs(lp[v] - c.center[v]) <= c.size[v] / 2)\n }\n\n /**\n * A shot or a blow on a wall of units (`PartSpec.units`) wears the unit it lands on, and a little the ones around it within `radius`, until it gives\n * way at `chipEnergy` joules per kilogram of its mass. A blow knocks the whole unit out; a shot breaks it where it lands: a crater a few centimetres across\n * (`craterAcross`) goes through the unit, the rest of it stays in the wall, and its bits fly out of both faces (most out of the far one, along the shot). A unit whose\n * craters took most of its face (`CRATER_SPENT`) lets its rest go. Each gives a `chip` event with the piece that came out and its fragments\n * (`PartState.chipped`), and what goes through it passes. The face area that came out adds up like through damage (`addBreach`), so enough of it\n * close together opens the part. A reinforced part keeps its units (the cage holds them: it crumbles in a breach).\n */\n const chipUnits = (o: ObjRT, p: PartRT, kind: 'ballistic' | 'blunt', wp: Vec3, hitEnergy: number, dir: Vec3 | null, radius: number, src?: string) => {\n if (!p.spec.units || !p.staged || chipEnergy <= 0 || p.st.stripped || isLost(p) || (p.st.stage ?? 0) >= 2) return\n // the material says what a blow of this kind takes out of it: joules per kg of a unit, and the part of each blow that only scars the surface\n const rule = p.mat.hits?.[kind]\n const perKg = rule?.unitJoules ?? chipEnergy\n const energy = hitEnergy - (rule?.floor ?? 0)\n if (perKg <= 0 || energy <= 0) return\n const [u, v] = planeAxes(p.thin)\n const lp = toLocal(p.pos, p.q, objLocal(o, wp))\n const grid = gridOf(p)\n const worn = (p.rt.chips ??= {})\n const cut = (p.rt.craters ??= {})\n const out: UnitCell[] = []\n const wholeBefore = Object.values(worn).filter((w) => w === -1).length\n const shot = kind === 'ballistic'\n for (let i = 0; i < grid.length; i++) {\n const cell = grid[i]!\n if (worn[i] === -1) continue\n const gap = Math.hypot(Math.max(0, Math.abs(lp[u] - cell.center[u]) - cell.size[u] / 2), Math.max(0, Math.abs(lp[v] - cell.center[v]) - cell.size[v] / 2))\n if (gap > radius) continue\n const share = gap === 0 ? 1 : CHIP_SPLASH * (1 - gap / radius)\n const total = (worn[i] ?? 0) + energy * share\n const mass = p.mat.density * cell.size[0] * cell.size[1] * cell.size[2]\n if (total < perKg * mass) {\n worn[i] = total\n continue\n }\n if (!shot) {\n // a blow knocks the unit out\n worn[i] = -1\n out.push(cell)\n continue\n }\n // the shot breaks the unit where it lands (the point nearest to it on the unit): a crater through it, the rest stays\n const size: Vec3 = [cell.size[0], cell.size[1], cell.size[2]]\n const center: Vec3 = [cell.center[0], cell.center[1], cell.center[2]]\n for (const a of [u, v]) {\n const w = Math.min(cell.size[a], craterAcross(hitEnergy) * (0.85 + 0.3 * rnd()))\n const lo = cell.center[a] - cell.size[a] / 2 + w / 2, hi = cell.center[a] + cell.size[a] / 2 - w / 2\n size[a] = w\n center[a] = clamp(lp[a], lo, hi)\n // at a free edge of the part (its ends, its top) nothing holds the corner: the crater tears off the piece out to the edge\n const [from, to] = tornToEdge({ p, cell, a, b: a === u ? v : u, at: lp[a], crater: [center[a] - w / 2, center[a] + w / 2], reach: w * EDGE_REACH, gone: (k) => worn[k] === -1 })\n size[a] = to - from\n center[a] = (from + to) / 2\n }\n const taken = (cut[i] ?? 0) + size[u] * size[v]\n if (taken >= cell.size[u] * cell.size[v] * CRATER_SPENT) {\n // a shot that would leave little of it takes the rest too, broken in pieces\n worn[i] = -1\n out.push({ ...cell, crater: true } as UnitCell)\n continue\n }\n worn[i] = 0\n cut[i] = taken\n out.push({ center, size, crater: true } as UnitCell)\n }\n if (out.length === 0) return\n const { c, q } = partXf(o, p)\n const chipped = (p.st.chipped ??= [])\n const holes = localHolesOf(p)\n for (const cell of out) {\n const mass = Math.min(p.st.mass, p.mat.density * cell.size[0] * cell.size[1] * cell.size[2])\n const center = toWorld(c, q, cell.center)\n const speed = clamp(Math.sqrt((2 * energy * 0.05) / Math.max(mass, 0.05)), 0.5, 6)\n const tag = `c${chipped.length}_`\n const fragments = (cell as { crater?: boolean }).crater ? craterFragments(o, p, cell, dir, speed, mass, tag) : cellFragments(o, p, [cell], wp, dir, speed, mass, tag, true)\n p.st.holes = p.st.holes.filter((_, k) => marksInBox(cell.center, cell.size, undefined, [holes[k]!]).length === 0)\n chipped.push({ center: [cell.center[0], cell.center[1], cell.center[2]], size: [cell.size[0], cell.size[1], cell.size[2]] })\n p.st.mass = Math.max(0, p.st.mass - mass)\n p.rt.removed = (p.rt.removed ?? 0) + mass\n markDamaged(p)\n setStage(o, p, 1, {}, src)\n emit({ ...base(o, src), type: 'chip', part: p.spec.id, center, size: [cell.size[0], cell.size[1], cell.size[2]], rotation: q, fragments })\n debris(o, p, p.mat.breakDebris, center, vec.scale(dir ?? [0, 1, 0], -1), 6, 2, src)\n }\n // what the units that came out held up and nothing else holds comes down\n if (Object.values(worn).filter((w) => w === -1).length > wholeBefore) dropUnsupported(o, p, src)\n if (p.spec.reinforcement) exposeRebar(o, p, src)\n for (const cell of out) addBreach(o, p, toWorld(c, q, cell.center), cell.size[u] * cell.size[v], energy, dir, src)\n if (p.structural && !isLost(p)) {\n solveStructure(o)\n collapseCheck(o, src)\n }\n }\n\n /**\n * The span of a crater along axis `a` of the part (`crater`, inside the unit `cell`), carried out to the side of the unit when that side is free and the\n * hit lands within `reach` of it: nothing holds that corner, so the shot tears the piece off. A side is free at the ends of the wall, at its top (not at\n * its bottom, which stands on what holds it) and where the unit next to it was knocked out, so the edge a torn corner leaves tears off in turn.\n */\n const tornToEdge = (o: TornToEdgeOptions): [number, number] => {\n const { p, cell, a, b, at, crater, reach, gone } = o\n const half = p.dims[a] / 2\n const lo = cell.center[a] - cell.size[a] / 2, hi = cell.center[a] + cell.size[a] / 2\n const free = (side: number, sign: number): boolean => {\n if (sign > 0 ? side >= half - 1e-6 : side <= -half + 1e-6) return sign > 0 || a !== planeAxes(p.thin)[1]\n const probe = side + sign * 1e-3\n return gridOf(p).some((c, k) => gone(k) && Math.abs(probe - c.center[a]) <= c.size[a] / 2 && Math.abs(cell.center[b] - c.center[b]) <= c.size[b] / 2)\n }\n if (at - lo <= reach && free(lo, -1)) return [lo, Math.max(crater[1], lo)]\n if (hi - at <= reach && free(hi, 1)) return [Math.min(crater[0], hi), hi]\n return crater\n }\n\n /** Metres across the crater a round of `energy` joules breaks through a unit: 6 cm for a pistol round, 10 for a rifle round. */\n const craterAcross = (energy: number): number => clamp(0.03 + 0.0012 * Math.sqrt(Math.max(0, energy)), 0.03, 0.14)\n\n /**\n * The bits of a unit a shot broke through (`cell`, part-local: the crater, or the rest of a unit the craters spent): small irregular pieces of the\n * inside of the material, two in three thrown out of the far face along the shot, the rest back out of the face it hit.\n */\n const craterFragments = (o: ObjRT, p: PartRT, cell: UnitCell, dir: Vec3 | null, speed: number, mass: number, tag: string): Fragment[] => {\n const { c, q } = partXf(o, p)\n const [u, v] = planeAxes(p.thin)\n const d = dir ?? rotateVec(q, [p.thin === 0 ? 1 : 0, p.thin === 1 ? 1 : 0, p.thin === 2 ? 1 : 0])\n // which face of the part the shot leaves by, in part axes\n const exitSign = Math.sign(rotateVec(quat.conjugate(q), d)[p.thin]) || 1\n const bit = Math.max(0.01, Math.min(cell.size[u], cell.size[v]) / 3)\n const n = clamp(Math.round((cell.size[u] * cell.size[v]) / (bit * bit * 3)), 4, 10) + Math.floor(rnd() * 3)\n const out: Fragment[] = []\n for (let i = 0; i < n; i++) {\n const back = i % 3 === 2\n const lc: Vec3 = [cell.center[0], cell.center[1], cell.center[2]]\n lc[u] += (rnd() - 0.5) * cell.size[u] * 0.7\n lc[v] += (rnd() - 0.5) * cell.size[v] * 0.7\n lc[p.thin] += (back ? -exitSign : exitSign) * (p.thickness / 2 + 0.01)\n const size: Vec3 = [0, 0, 0]\n size[u] = bit * (0.6 + 0.8 * rnd())\n size[v] = bit * (0.5 + 0.7 * rnd())\n size[p.thin] = bit * (0.4 + 0.6 * rnd())\n const spread: Vec3 = [(rnd() - 0.5) * 0.9, (rnd() - 0.3) * 0.9, (rnd() - 0.5) * 0.9]\n const k = speed * (back ? 0.4 + 0.4 * rnd() : 0.7 + 0.8 * rnd())\n const vdir = vec.normalize(vec.add(back ? vec.scale(d, -1) : d, spread))\n out.push({\n id: `${p.spec.id}#${tag}${i}`, part: p.spec.id, material: p.spec.material, shape: 'chunk', center: toWorld(c, q, lc), size, rotation: q,\n velocity: [vdir[0] * k, vdir[1] * k + 0.5 * rnd(), vdir[2] * k], angularVelocity: [(rnd() - 0.5) * 20, (rnd() - 0.5) * 20, (rnd() - 0.5) * 20],\n mass: mass / n, inner: true,\n })\n }\n return out\n }\n\n /**\n * The bars of a reinforced part that show (all of them once it is stripped, else those inside its opening and its knocked-out units), bowed out of the\n * part's plane by its overload (`stress` past 1) so the cage bends under the load it carries until the part gives way. Emitted as one `expose` with\n * every bar that shows, so a renderer can replace the part's cage with it.\n */\n const exposeRebar = (o: ObjRT, p: PartRT, src?: string) => {\n const r = p.spec.reinforcement\n if (!r) return\n const [u, v] = planeAxes(p.thin)\n const all = rebarBars(p.dims, p.thin, r.spacing)\n let bars: Array<[Vec3, Vec3]>\n if (p.st.stripped) bars = all\n else {\n bars = []\n for (const cell of p.st.chipped ?? []) bars.push(...clipBarsToBox(all, u, v, cell.center, cell.size))\n const op = p.st.opening\n if (op) {\n const lc = toLocal(p.pos, p.q, op.center)\n bars.push(...clipBarsToDisc(all, u, v, [lc[u], lc[v]], op.radius + 0.05))\n }\n }\n const bow = clamp(((p.st.stress ?? 0) - 1) / 0.5, 0, 1)\n if (bow > 0) bars = bars.flatMap((bar, i) => bendBar(bar, p.thin, bow * BAR_BOW, i))\n emit({ ...base(o, src), type: 'expose', part: p.spec.id, bars: worldBars(o, p, bars) })\n }\n\n /**\n * Stage 2: the units around `center` (object-local) come out as fragments the size of one unit, the part keeps an opening and its mass drops. An\n * opening as wide as the part cuts it in two (a column, a lintel): that is a fracture instead.\n */\n const openBreach = (o: ObjRT, p: PartRT, center: Vec3, total: number, energy: number, dir: Vec3 | null, src?: string) => {\n const [u, v] = planeAxes(p.thin)\n const radius = clamp(Math.sqrt(total / Math.PI), Math.sqrt((p.spec.breach?.area ?? BREACH_AREA) / Math.PI), breachRadius)\n const lc = toLocal(p.pos, p.q, center)\n lc[p.thin] = 0\n const { c, q } = partXf(o, p)\n const worldCenter = toWorld(c, q, lc)\n if (2 * radius >= Math.min(p.dims[u], p.dims[v])) {\n failPart(o, p, worldCenter, dir, energy, 12, src)\n return\n }\n const worn = p.rt.chips\n const cells = cellsWithin(gridOf(p).filter((_, i) => worn?.[i] !== -1), p.thin, lc, radius)\n const removed = (p.st.mass * cells.reduce((sum, cell) => sum + cell.size[u] * cell.size[v], 0)) / (p.dims[u] * p.dims[v])\n const speed = clamp(Math.sqrt((2 * energy * 0.1) / Math.max(removed, 0.05)), 0.5, 8)\n const fragments = cellFragments(o, p, cells, worldCenter, dir, speed, removed, 'b')\n const holes = localHolesOf(p)\n p.st.holes = p.st.holes.filter((_, i) => !cells.some((cell) => marksInBox(cell.center, cell.size, undefined, [holes[i]!]).length > 0))\n p.st.mass = Math.max(0, p.st.mass - removed)\n p.rt.removed = (p.rt.removed ?? 0) + removed\n p.st.opening = { center: objLocal(o, worldCenter), radius }\n markDamaged(p)\n setStage(o, p, 1, {}, src)\n setStage(o, p, 2, { opening: { center: worldCenter, radius }, fragments }, src)\n debris(o, p, p.mat.breakDebris, worldCenter, vec.scale(dir ?? [0, 1, 0], -1), 14, 3, src)\n dropUnsupported(o, p, src)\n const reinforcement = p.spec.reinforcement\n if (reinforcement) exposeRebar(o, p, src)\n if (p.structural) solveStructure(o)\n }\n\n /**\n * Metres from a blast of `energy` joules within which it breaks a wall of units through: `BREACH_BLAST_REACH` by the cube root of the kilojoules, for\n * the reference wall, and by the cube root of how much less or more that wall resists (`BLAST_REFERENCE_RESISTANCE`).\n */\n const blastReachOf = (p: PartRT, energy: number): number => {\n const perKg = p.mat.hits?.blunt?.unitJoules ?? chipEnergy\n const resistance = Math.max(1, perKg * p.mat.density * p.thickness)\n return BREACH_BLAST_REACH * Math.cbrt(Math.max(0, energy) / 1000) * clamp(Math.cbrt(BLAST_REFERENCE_RESISTANCE / resistance), 0.3, 2)\n }\n\n /**\n * A blast on a wall of units (`PartSpec.units`): the units where the wall is within its reach (`blastReachOf`) come out, the circle the sphere of\n * that reach cuts on the wall, its edge ragged as masonry breaks along its joints; the units just past it are loosened for the next blow, and the\n * units the hole leaves with nothing under them (`unsupportedCells`: the corner over a hole at the free end of a wall) come down with them. The rest\n * of the wall stands. Everything that came out is one `chip` with `units`, and it adds up in `PartState.chipped`, so later shots and blasts go on\n * cutting the same wall. Returns whether any unit came out.\n */\n const blastUnits = (o: ObjRT, p: PartRT, wp: Vec3, energy: number, dist: number, src?: string): boolean => {\n if (!p.staged || p.st.stripped || isLost(p) || chipEnergy <= 0) return false\n const reach = blastReachOf(p, energy)\n if (dist >= reach) return false\n const radius = Math.sqrt(reach * reach - dist * dist)\n const [u, v] = planeAxes(p.thin)\n const lp = toLocal(p.pos, p.q, objLocal(o, wp))\n const op = p.st.opening ? toLocal(p.pos, p.q, p.st.opening.center) : null\n const grid = gridOf(p)\n const worn = (p.rt.chips ??= {})\n const perKg = p.mat.hits?.blunt?.unitJoules ?? chipEnergy\n const lobes = [rnd() * 2 * Math.PI, rnd() * 2 * Math.PI]\n const out: number[] = []\n for (let i = 0; i < grid.length; i++) {\n const cell = grid[i]!\n if (worn[i] === -1) continue\n if (op && p.st.opening && Math.hypot(cell.center[u] - op[u], cell.center[v] - op[v]) <= p.st.opening.radius) continue\n const du = cell.center[u] - lp[u], dv = cell.center[v] - lp[v]\n const angle = Math.atan2(dv, du)\n const edge = radius * (1 + BLAST_EDGE_RAGGED * (0.5 * Math.sin(3 * angle + lobes[0]!) + 0.3 * Math.sin(5 * angle + lobes[1]!) + 0.4 * (rnd() - 0.5)))\n const d = Math.hypot(du, dv)\n if (d <= edge) {\n worn[i] = -1\n out.push(i)\n } else if (d <= edge * BLAST_EDGE_LOOSE) {\n const mass = p.mat.density * cell.size[0] * cell.size[1] * cell.size[2]\n worn[i] = Math.max(worn[i] ?? 0, perKg * mass * BLAST_EDGE_WEAR)\n }\n }\n if (out.length === 0) return false\n const loose = unsupportedCells(grid, p.thin, p.dims, (i) => worn[i] !== -1 && !(op && p.st.opening && Math.hypot(grid[i]!.center[u] - op[u], grid[i]!.center[v] - op[v]) <= p.st.opening.radius))\n for (const i of loose) worn[i] = -1\n const blown = out.map((i) => grid[i]!), fallen = loose.map((i) => grid[i]!)\n const volume = (cells: readonly UnitCell[]) => cells.reduce((sum, cell) => sum + cell.size[0] * cell.size[1] * cell.size[2], 0)\n const blownMass = Math.min(p.st.mass, p.mat.density * volume(blown))\n const fallenMass = Math.min(p.st.mass - blownMass, p.mat.density * volume(fallen))\n const speed = clamp(Math.sqrt((2 * energy * 0.02) / Math.max(blownMass, 0.05)), 1, 12)\n // what flies is clumps of units still held by their mortar, at most `maxFragments` of them (and a quarter of that for what comes down), so a blast\n // costs a renderer about as many pieces as a fracture does\n const { c, q } = partXf(o, p)\n const chipped = (p.st.chipped ??= [])\n const tag = `x${chipped.length}_`\n const fragments = [\n ...cellFragments(o, p, clumpCells(blown, p.thin, maxFragments), wp, null, speed, blownMass, tag, true),\n ...(fallen.length > 0 ? cellFragments(o, p, clumpCells(fallen, p.thin, Math.max(2, Math.round(maxFragments / 4))), wp, null, 0.3, fallenMass, `${tag}f`, true) : []),\n ]\n const cells = [...blown, ...fallen]\n const holes = localHolesOf(p)\n p.st.holes = p.st.holes.filter((_, k) => !cells.some((cell) => marksInBox(cell.center, cell.size, undefined, [holes[k]!]).length > 0))\n const lo: Vec3 = [Infinity, Infinity, Infinity], hi: Vec3 = [-Infinity, -Infinity, -Infinity]\n for (const cell of cells) {\n chipped.push({ center: [cell.center[0], cell.center[1], cell.center[2]], size: [cell.size[0], cell.size[1], cell.size[2]] })\n for (let k = 0; k < 3; k++) {\n lo[k] = Math.min(lo[k]!, cell.center[k]! - cell.size[k]! / 2)\n hi[k] = Math.max(hi[k]!, cell.center[k]! + cell.size[k]! / 2)\n }\n }\n p.st.mass = Math.max(0, p.st.mass - blownMass - fallenMass)\n p.rt.removed = (p.rt.removed ?? 0) + blownMass + fallenMass\n markDamaged(p)\n setStage(o, p, 1, {}, src)\n const center = toWorld(c, q, [(lo[0] + hi[0]) / 2, (lo[1] + hi[1]) / 2, (lo[2] + hi[2]) / 2])\n const units = cells.map((cell) => ({ center: toWorld(c, q, cell.center), size: [cell.size[0], cell.size[1], cell.size[2]] as Vec3 }))\n emit({ ...base(o, src), type: 'chip', part: p.spec.id, center, size: [hi[0] - lo[0], hi[1] - lo[1], hi[2] - lo[2]], rotation: q, fragments, units })\n debris(o, p, p.mat.breakDebris, center, vec.normalize(vec.sub(center, wp), [0, 1, 0]), 14, 3, src)\n if (p.spec.reinforcement) exposeRebar(o, p, src)\n if (p.structural && !isLost(p)) {\n solveStructure(o)\n collapseCheck(o, src)\n }\n return true\n }\n\n /**\n * The units of a wall of laid units (brick or block in its mortar) that a removal left with no bearing down to the bottom of the wall (`unsupportedCells`):\n * an island of bricks over the edge of a hole, a unit held by a corner. They come down as debris (one `chip` with `units`, the pieces clumped as they\n * fall), leave the part (`PartState.chipped`, so shots and rays pass where they were) and their marks go with them. Returns how many units fell.\n */\n const dropUnsupported = (o: ObjRT, p: PartRT, src?: string): number => {\n if (!p.spec.units || p.spec.units.mortar === p.spec.material || p.st.stripped || isLost(p)) return 0\n const [u, v] = planeAxes(p.thin)\n const grid = gridOf(p)\n const worn = (p.rt.chips ??= {})\n const op = p.st.opening ? toLocal(p.pos, p.q, p.st.opening.center) : null\n const opened = (cell: UnitCell): boolean => !!op && !!p.st.opening && Math.hypot(cell.center[u] - op[u], cell.center[v] - op[v]) <= p.st.opening.radius\n const loose = unsupportedCells(grid, p.thin, p.dims, (i) => worn[i] !== -1 && !opened(grid[i]!))\n if (loose.length === 0) return 0\n for (const i of loose) worn[i] = -1\n const fallen = loose.map((i) => grid[i]!)\n const mass = Math.min(p.st.mass, p.mat.density * fallen.reduce((sum, cell) => sum + cell.size[0] * cell.size[1] * cell.size[2], 0))\n const { c, q } = partXf(o, p)\n const chipped = (p.st.chipped ??= [])\n const lo: Vec3 = [Infinity, Infinity, Infinity], hi: Vec3 = [-Infinity, -Infinity, -Infinity]\n for (const cell of fallen) {\n for (let k = 0; k < 3; k++) {\n lo[k] = Math.min(lo[k]!, cell.center[k]! - cell.size[k]! / 2)\n hi[k] = Math.max(hi[k]!, cell.center[k]! + cell.size[k]! / 2)\n }\n }\n const center = toWorld(c, q, [(lo[0] + hi[0]) / 2, (lo[1] + hi[1]) / 2, (lo[2] + hi[2]) / 2])\n const fragments = cellFragments(o, p, clumpCells(fallen, p.thin, Math.max(2, Math.round(maxFragments / 4))), vec.add(center, [0, 1, 0]), null, 0.3, mass, `u${chipped.length}_`, true)\n const holes = localHolesOf(p)\n p.st.holes = p.st.holes.filter((_, k) => !fallen.some((cell) => marksInBox(cell.center, cell.size, undefined, [holes[k]!]).length > 0))\n for (const cell of fallen) chipped.push({ center: [cell.center[0], cell.center[1], cell.center[2]], size: [cell.size[0], cell.size[1], cell.size[2]] })\n p.st.mass = Math.max(0, p.st.mass - mass)\n p.rt.removed = (p.rt.removed ?? 0) + mass\n markDamaged(p)\n const units = fallen.map((cell) => ({ center: toWorld(c, q, cell.center), size: [cell.size[0], cell.size[1], cell.size[2]] as Vec3 }))\n emit({ ...base(o, src), type: 'chip', part: p.spec.id, center, size: [hi[0] - lo[0], hi[1] - lo[1], hi[2] - lo[2]], rotation: q, fragments, units })\n debris(o, p, p.mat.breakDebris, center, [0, -1, 0], 6, 1, src)\n return loose.length\n }\n\n /**\n * A reinforced concrete part with a place shot away gives there, not as a whole: what rests on it no longer bears on it (the bond beam on a pillar cut\n * under its top goes on resting on its wall and the other pillars), and the part stays as it is, the concrete above the cut held by the cage. Returns\n * false when nothing rested on it, for the whole part to break as before.\n */\n const giveAtCut = (o: ObjRT, p: PartRT, src?: string): boolean => {\n if (!p.spec.reinforcement || !p.spec.units || !p.st.chipped?.length || sectionLoss(p) <= 0) return false\n const opened: JointRT[] = []\n for (const j of o.byPart.get(p.spec.id) ?? []) {\n if (j.st.open) continue\n const onIt = (j.bears === 'a_on_b' && j.spec.b === p.spec.id) || (j.bears === 'b_on_a' && j.spec.a === p.spec.id)\n if (!onIt) continue\n j.st.open = true\n j.st.openedBy = 'break'\n opened.push(j)\n }\n if (opened.length === 0) return false\n p.st.hp = Math.max(p.st.hp, p.st.maxHp * GIVE_AT_CUT_HP)\n markDamaged(p)\n solveStructure(o)\n recomputeGroups(o)\n detachEvents(o, opened, 'break', src)\n exposeRebar(o, p, src)\n collapseCheck(o, src)\n return true\n }\n\n /** The concrete of a reinforced part is gone: the part stays as its rebar cage, with the capacity the reinforcement leaves it. */\n const stripPart = (o: ObjRT, p: PartRT, reinforcement: NonNullable<PartSpec['reinforcement']>, src?: string) => {\n const bars = rebarBars(p.dims, p.thin, reinforcement.spacing)\n p.st.stripped = true\n p.st.hp = p.st.maxHp\n p.st.mass = rebarMass(bars, reinforcement.diameter, materials.get(reinforcement.material)?.density)\n p.st.holes = []\n p.st.burning = false\n p.rt.jet = false\n markDamaged(p)\n solveStructure(o)\n exposeRebar(o, p, src)\n collapseCheck(o, src)\n }\n\n /** The units of the part that are still there (the opening of a breach is already gone), as a fragment plan. */\n const unitFragmentPlan = (p: PartRT, cap: number): PlannedFragment[] => {\n const grid = unitGrid(p.dims, p.thin, unitsOf(p), cap)\n const op = p.st.opening\n const cells = op ? cellsOutside(grid, p.thin, toLocal(p.pos, p.q, op.center), op.radius) : grid\n const [u, v] = planeAxes(p.thin)\n return cells.map((cell) => ({ center: cell.center, size: cell.size, q: quat.identity(), shape: 'chunk' as const, weight: cell.size[u] * cell.size[v] }))\n }\n\n /** The bare cage gives way (overload, a blast, a cut that finishes): the part is lost for good. */\n const loseCage = (o: ObjRT, p: PartRT, src?: string) => {\n p.st.status = 'broken'\n p.st.hp = 0\n p.st.mass = 0\n emit({ ...base(o, src), type: 'expose', part: p.spec.id, bars: [] })\n debris(o, p, 'sparks', partXf(o, p).c, [0, 1, 0], 6, 3, src)\n partLost(o, p, src)\n }\n\n /**\n * A reinforced beam or slab that fails in bending folds at the hinge and comes down in one piece, held together by its bars: the joints it rests on\n * open, it keeps what rests on it, and it falls (a `collapse` follows) instead of turning to rubble.\n */\n const hingeDrop = (o: ObjRT, p: PartRT, src?: string) => {\n const i = o.idx.get(p.spec.id)!\n const opened: JointRT[] = []\n for (const j of o.byPart.get(p.spec.id) ?? []) {\n if (j.st.open || restsOn(o, j, i) < 0) continue\n j.st.open = true\n j.st.hp = 0\n j.st.openedBy = 'break'\n opened.push(j)\n }\n p.st.hp = Math.max(1, p.st.maxHp * 0.1)\n p.st.cracked = true\n markDamaged(p)\n debris(o, p, p.mat.breakDebris, partXf(o, p).c, [0, -1, 0], 12, 2, src)\n solveStructure(o)\n recomputeGroups(o)\n detachEvents(o, opened, 'break', src)\n collapseCheck(o, src)\n }\n\n /** Part hit points reached 0 (or it was forced to explode): fragments, debris, joints open. */\n const failPart = (o: ObjRT, p: PartRT, origin: Vec3 | null, dir: Vec3 | null, fragEnergy: number, cap: number, src?: string, force?: FractureStyle) => {\n if (isLost(p)) return\n if (p.st.stripped) {\n loseCage(o, p, src)\n return\n }\n if (!force && p.bend && (p.st.flexure ?? 0) > 1 && sectionOf(p, p.bend.gravity).reinforced) {\n hingeDrop(o, p, src)\n return\n }\n if (!force && giveAtCut(o, p, src)) return\n const ex = p.spec.explodes\n const style = force ?? (p.snap ? 'snap' : p.mat.fracture === 'none' ? 'snap' : p.mat.fracture)\n const { c, q } = partXf(o, p)\n const hitW = origin ?? c\n const grain = p.spec.grain ? AXIS[p.spec.grain] : undefined\n const hitLocal = toLocal(c, q, hitW)\n const unitPlan = p.spec.units ? unitFragmentPlan(p, maxFragments * UNIT_FRAGMENT_FACTOR) : []\n const axis = style === 'splinter' || style === 'snap' ? severAxis(p) : -1\n const cutAt = axis < 0 ? undefined : p.rt.cutAt ?? (origin ? hitLocal[axis] : undefined)\n // wood plans its splinters, sheets and lumps on a stream of its own: how a board comes apart never moves the cracks and spalls the world draws after it\n const planRnd = p.mat.splitForm ? splitStream(o.id, p.spec.id, hitLocal) : rnd\n const plan = unitPlan.length > 0 ? unitPlan : planFragments({\n style, dims: p.dims, thickness: p.thickness, grain, hit: hitLocal, fragmentSize: p.mat.fragmentSize ?? [0.04, 0.2], maxFragments, rnd: planRnd, sheet: p.mat.sheet,\n ...(p.mat.splitForm ? { form: p.mat.splitForm } : {}),\n ...(cutAt !== undefined ? { cut: { at: cutAt, gap: SEVER_BAND } } : {}),\n })\n const holes = p.st.holes.length > 0 ? localHolesOf(p) : []\n const mass = p.st.mass\n const totW = plan.reduce((s, f) => s + f.weight, 0) || 1\n const energy = ex ? ex.energy * 0.2 : fragEnergy\n const speed = clamp(Math.sqrt((2 * energy) / Math.max(mass, 0.05)), 0.3, ex ? 40 : cap)\n const fragments: Fragment[] = plan.map((f, i) => {\n const cw = toWorld(c, q, f.center)\n const out = vec.normalize(vec.sub(cw, hitW), [0, 1, 0])\n const dv = dir ? vec.normalize(vec.madd(out, dir, 0.6)) : out\n const k = speed * (0.6 + 0.8 * rnd())\n const marks = marksInBox(f.center, f.size, f.q, holes)\n return {\n id: `${p.spec.id}#${i}`, part: p.spec.id, material: p.spec.material, shape: f.shape, center: cw, size: f.size, rotation: quat.mul(q, f.q),\n velocity: [dv[0] * k, dv[1] * k + 0.5 * rnd(), dv[2] * k],\n angularVelocity: [(rnd() - 0.5) * 12, (rnd() - 0.5) * 12, (rnd() - 0.5) * 12],\n mass: (mass * f.weight) / totW, ...(marks.length > 0 ? { marks } : {}), ...(f.inner ? { inner: true } : {}),\n }\n })\n const reinforcement = p.spec.reinforcement\n if (!reinforcement) {\n p.st.status = 'broken'\n p.st.hp = 0\n p.st.mass = 0\n p.st.burning = false\n p.rt.jet = false\n }\n emit({ ...base(o, src), type: 'fracture', part: p.spec.id, style, fragments, point: hitW })\n debris(o, p, p.mat.breakDebris, c, [0, 1, 0], clamp(Math.round(Math.cbrt(partVolume(p.spec.shape)) * 30), 3, 20), 2, src)\n setStage(o, p, 3, {}, src)\n if (reinforcement) {\n stripPart(o, p, reinforcement, src)\n return\n }\n if (ex) {\n emit({ ...base(o, src), type: 'explode', part: p.spec.id, point: c, energy: ex.energy, radius: ex.radius, ...(ex.lethalRadius !== undefined ? { lethalRadius: ex.lethalRadius } : {}), ...(ex.tnt !== undefined ? { tnt: ex.tnt } : {}), ...(ex.effect !== undefined ? { effect: ex.effect } : {}) })\n blasts.push({ point: c, energy: ex.energy, radius: ex.radius, ...(ex.lethalRadius !== undefined ? { lethalRadius: ex.lethalRadius } : {}), source: src })\n }\n partLost(o, p, src)\n }\n\n /**\n * Sets an explosive part off from outside (`explodes.chain`): it will explode after the delay of `trigger`, once. The delay is one draw\n * from the world seed, so the same inputs give the same order of blasts.\n */\n const prime = (o: ObjRT, p: PartRT, trigger: ChainTrigger, src?: string) => {\n const spec = chainDelayOf(p.spec, trigger)\n if (spec === undefined || isLost(p) || p.rt.chainDue !== undefined) return\n const delay = drawChainDelay(spec, rnd)\n p.rt.chainDue = time + delay\n primed.set(p, o)\n o.active = true\n emit({ ...base(o, src), type: 'primed', part: p.spec.id, point: partXf(o, p).c, trigger, delay })\n }\n\n const CHAIN_TRIGGER_OF: Partial<Record<DamageType, ChainTrigger>> = { ballistic: 'shot', explosive: 'explosion' }\n\n /** Remove hit points. Returns the amount actually removed. */\n /**\n * A long wooden part (a board, a batten, a beam: `splinter`, box, at least `SEVER_ASPECT` times longer than it is wide) breaks where it is hit: its\n * length is cut in bands `SEVER_BAND` long, each with its share of the hit points, and the band whose share runs out breaks it across there. A thin\n * board has little in each band and goes in a few shots; a beam or a log carries its whole section in each band and takes many.\n */\n const severAxis = (p: PartRT): number => {\n // boards and beams break where they are hit: wood along the grain, a snapping board (MDF, plastic) across\n if ((p.mat.fracture !== 'splinter' && p.mat.fracture !== 'snap') || p.spec.shape.kind !== 'box') return -1\n const d = p.dims\n const order = [0, 1, 2].sort((a, b) => d[b] - d[a])\n return d[order[0]] >= SEVER_ASPECT * d[order[1]] && d[order[0]] >= 3 * SEVER_BAND ? order[0] : -1\n }\n const bandOf = (o: ObjRT, p: PartRT, axis: number, origin: Vec3): number => {\n const { c, q } = partXf(o, p)\n const along = toLocal(c, q, origin)[axis]\n const L = p.dims[axis]\n return clamp(Math.floor((along + L / 2) / SEVER_BAND), 0, Math.ceil(L / SEVER_BAND) - 1)\n }\n\n const applyDamage = (o: ObjRT, p: PartRT, amount: number, type: DamageType, origin: Vec3 | null, dir: Vec3 | null, fragEnergy: number, cap: number, src?: string): number => {\n if (isLost(p) || amount <= 0) return 0\n const prev = p.st.hp\n p.st.hp -= amount\n const axis = origin && type !== 'fire' && type !== 'heat' ? severAxis(p) : -1\n if (axis >= 0 && p.st.hp > 0) {\n const band = bandOf(o, p, axis, origin!)\n const cuts = (p.rt.cuts ??= {})\n cuts[band] = (cuts[band] ?? 0) + amount * (type === 'ballistic' ? SEVER_BALLISTIC : 1)\n if (cuts[band] >= (p.st.maxHp * SEVER_BAND) / p.dims[axis]) {\n p.rt.cutAt = -p.dims[axis] / 2 + (band + 0.5) * SEVER_BAND\n p.st.hp = 0\n }\n }\n markDamaged(p)\n const trigger = CHAIN_TRIGGER_OF[type]\n const chained = trigger !== undefined && chainDelayOf(p.spec, trigger) !== undefined\n // a bullet or a blast sets a chained part off after its delay instead of tearing it apart on the spot\n if (chained && p.st.hp <= 0 && p.rt.chainDue === undefined) p.st.hp = Math.min(prev, 1)\n if (p.st.hp <= 0 && p.mat.fracture === 'none' && !p.spec.explodes) p.st.hp = Math.min(prev, 1)\n const done = prev - p.st.hp\n if (done > 0) emit({ ...base(o, src), type: 'damage', part: p.spec.id, amount: done, hp: Math.max(0, p.st.hp), damageType: type })\n if (p.st.hp <= 0) failPart(o, p, origin, dir, fragEnergy, cap, src)\n else if (chained && (trigger === 'explosion' || 1 - p.st.hp / p.st.maxHp >= shotDamageFractionOf(p.spec))) prime(o, p, trigger, src)\n return done\n }\n\n // -------------------------------------------------------------------------------------------------------------------------------------------\n // Hits\n // -------------------------------------------------------------------------------------------------------------------------------------------\n\n /** A container of flammable fluid with a hole that goes through: it leaks. */\n const leaksFlammable = (p: PartRT): boolean => {\n const c = p.spec.contains\n return !!c && FLAMMABLE_FLUIDS.includes(c.fluid) && (p.st.liters ?? 0) > 0 && p.st.holes.some((h) => h.through)\n }\n\n /**\n * A round that went through the wall of a container of flammable fluid lights the leak or does not: the spark of a hard round on metal and the\n * flame of an incendiary or tracer (`Hit.ignition`, `Hit.incendiary`, `Hit.tracer`), weighed by how full the container is (`options.ignition`).\n * A plain bullet carries neither and only leaks. The part burns or goes off at the next `update` (`rt.lit`).\n */\n const rollIgnition = (o: ObjRT, p: PartRT, round: BallisticExtras) => {\n const c = p.spec.contains\n if (!c || !FLAMMABLE_FLUIDS.includes(c.fluid) || p.rt.jet || p.rt.lit) return\n const fill = c.liters > 0 ? (p.st.liters ?? 0) / c.liters : 0\n const chance = ignitionChance(round, { sparkTarget: sparkTargetFactor(p.mat.id, !!p.mat.tags?.includes('metal'), ignitionRules), fill, fluid: c.fluid }, ignitionRules)\n if (chance > 0 && rnd() < chance) {\n p.rt.lit = true\n o.active = true\n }\n }\n\n /** What is lit by a fire or a blast near: the leaks of flammable fluid within `radius` of `centre` (object parts only). */\n const lightLeaksNear = (centre: Vec3, radius: number) => {\n for (const o of objects.values()) {\n for (const q of o.parts) {\n if (isLost(q) || q.rt.lit || q.rt.jet || !leaksFlammable(q)) continue\n if (vec.distance(partXf(o, q).c, centre) - q.bound > radius) continue\n q.rt.lit = true\n o.active = true\n }\n }\n }\n\n /** What a blow of `kind` tears out of the material (`MaterialDef.hits`): a round into wood tears splinters by default. */\n const tearOf = (mat: MaterialDef, kind: DamageType): { tear: 'splinters' | 'lumps' | 'none'; joules: number } => {\n const h = mat.hits?.[kind]\n const tear = h?.tear ?? (kind === 'ballistic' && mat.penetrationClass === 'wood' ? 'splinters' : 'none')\n return { tear, joules: h?.tearJoules ?? TEAR_JOULES }\n }\n\n /**\n * Pieces torn out where a blow lands, as the material answers that kind of blow (`MaterialDef.hits`): splinters of fresh wood, lumps of MDF.\n * A round (`exit` when it went through) throws most out of the exit along the shot and one in three back out of the entry, two out of the entry\n * when it stayed; a blow knocks them out of the face it hits, one per `tearJoules`, none below. `scale` is the calibre or the contact size (m).\n * Reported as a `chip` where they came off. The part stays: its hit points take the blow apart.\n */\n const tearAt = (o: ObjRT, p: PartRT, kind: DamageType, entry: Vec3, exit: Vec3 | undefined, d: Vec3, E: number, scale: number, src?: string) => {\n const { tear, joules } = tearOf(p.mat, kind)\n if (tear === 'none') return\n const shot = kind === 'ballistic'\n const n = shot ? (exit ? clamp(Math.round(E / joules), 1, 7) : 1) : clamp(Math.floor(E / joules), 0, 5)\n if (n === 0) return\n const fibre = tear === 'lumps'\n const { q } = partXf(o, p)\n const along = (p.spec.grain ? AXIS[p.spec.grain] : undefined) ?? [0, 1, 2].sort((a, b) => p.dims[b] - p.dims[a])[0]\n const fragments: Fragment[] = []\n for (let i = 0; i < n; i++) {\n // out of the entry (back towards the shooter or the fist), or out of the exit along the shot\n const back = !exit || i % 3 === 2\n // plywood tears thin flat splinters off its face veneer; solid wood thicker ones; MDF short lumps\n const plies = p.mat.splitForm === 'plies'\n const len = scale * (fibre ? 1.2 + 1.2 * rnd() : 3 + 4 * rnd()), w = scale * (0.8 + 0.8 * rnd()), t = scale * (fibre ? 0.7 + 0.6 * rnd() : plies ? 0.15 + 0.15 * rnd() : 0.4 + 0.4 * rnd())\n const size: Vec3 = [w, w, w]\n size[along] = len\n size[(along + 1) % 3] = w\n size[(along + 2) % 3] = t\n const spread: Vec3 = [(rnd() - 0.5) * 0.8, (rnd() - 0.2) * 0.8, (rnd() - 0.5) * 0.8]\n const speed = shot ? (back ? 1.5 + 2 * rnd() : 2 + 4 * rnd()) : 0.8 + 1.2 * rnd()\n const v = vec.scale(vec.normalize(vec.add(back ? vec.scale(d, -1) : d, spread)), speed)\n const mass = size[0] * size[1] * size[2] * p.mat.density\n fragments.push({\n id: `${p.spec.id}#t${tears++}-${i}`, part: p.spec.id, material: p.spec.material, shape: fibre ? 'chunk' : 'splinter',\n center: back || !exit ? vec.madd(entry, d, -0.01) : vec.madd(exit, d, 0.01), size, rotation: q, velocity: v, inner: true,\n angularVelocity: [(rnd() - 0.5) * 30, (rnd() - 0.5) * 30, (rnd() - 0.5) * 30], mass,\n })\n }\n const patch: Vec3 = [scale * 4, scale * 4, scale * 4]\n emit({ ...base(o, src), type: 'chip', part: p.spec.id, center: exit ?? entry, size: patch, rotation: q, fragments, torn: true })\n }\n\n interface BallisticOut { penetrated: boolean; exitEnergy: number; exitPoint?: Vec3; damage: number }\n\n const ballistic = (o: ObjRT, p: PartRT, entry: Vec3, n: Vec3, d: Vec3, E: number, caliber: number, pathLen: number, src?: string, round: BallisticExtras = {}): BallisticOut => {\n const mat = p.mat\n const piercing = round.piercing ?? 1\n // a bare cage and an opening do not stop a bullet\n if (p.st.stripped || (p.st.opening && insideOpening(o, p, objLocal(o, entry))) || insideChip(p, objLocal(o, entry))) {\n return { penetrated: true, exitEnergy: E, exitPoint: vec.madd(entry, d, Math.min(pathLen, p.thickness)), damage: 0 }\n }\n const sin = Math.min(1, Math.abs(vec.dot(d, n)))\n const angle = (Math.asin(sin) * 180) / Math.PI\n const slant = Math.max(sin, 0.3)\n const effM = p.thickness / slant\n const face = p.layers.length > 0 ? faceOf(o, p, n) : 1\n const exitLocal = objLocal(o, vec.madd(entry, d, Math.min(pathLen, effM)))\n const coats = p.layers.length > 0 ? layersEnergy(p.layers, p.rt.spalls, face, objLocal(o, entry)) + layersEnergy(p.layers, p.rt.spalls, -face, exitLocal) : 0\n // each coat adds penetration x thickness to the core's; a part without layers keeps the plain formula\n const thr = coats > 0 ? (mat.penetration * p.thickness * 1000 + coats) / slant : mat.penetration * effM * 1000\n // the bullet's kind matters against hard targets (steel, masonry); wood, flesh and the like take every bullet for its energy\n const hard = mat.tags?.includes('metal') || mat.tags?.includes('masonry')\n // a round that carries its penetration (mm by material class) goes through a part as thick as that, whatever the energy says; else the energy rule with `piercing`\n const penMm = penetrationOf(mat, round.penetration)\n const Ep = penMm !== undefined ? penMm * mat.penetration : piercing === 1 || !hard ? E : E * piercing\n const penetrated = Ep > thr\n // a thin brittle shell that shatters (a pane, a bottle) is lost to one bullet that a thick block of the same glass shrugs off: the same\n // fragility factor that melee uses for blunt hits (1 for ductile materials and for shells 2 cm or thicker, up to x118 for 3 mm glass)\n const scale = (mat.damageScale?.ballistic ?? 1) * (mat.fracture === 'shatter' ? fragility(mat.ductility, p.thickness) : 1)\n const id = p.spec.id\n if (!penetrated && mat.ricochetDeg && angle < mat.ricochetDeg) {\n const r = vec.sub(d, vec.scale(n, 2 * vec.dot(d, n)))\n emit({ ...base(o, src), type: 'ricochet', part: id, point: entry, direction: vec.normalize(r), energy: E * 0.4 })\n debris(o, p, mat.hitDebris, entry, n, 3, 3, src)\n const dmg = applyDamage(o, p, E * DMG_PER_J * scale * 0.2, 'ballistic', entry, d, E * 0.1, 12, src)\n return { penetrated: false, exitEnergy: 0, damage: dmg }\n }\n if (p.layers.length > 0) spallOuter(o, p, entry, face, n, Math.max(0.03, (caliber / 1000) * 4), src)\n else if (mat.hits?.ballistic?.crater) crater(o, p, entry, n, clamp(0.02 + Math.sqrt(E) * 0.0015, 0.02, 0.15), src)\n const brittle = mat.ductility < 0.3\n const ratio = Ep / Math.max(thr, 1e-6)\n const crackLen = clamp(0.03 + ratio * 0.2, 0.03, 0.8)\n let exitPoint: Vec3 | undefined\n if (penetrated) {\n const exitDist = (p.spec.contains || (p.spec.fill !== undefined && p.spec.fill < 0.5) || p.thickness < pathLen * 0.5)\n ? pathLen\n : Math.min(pathLen, effM + layersThickness(p.layers, face) / slant + layersThickness(p.layers, -face) / slant)\n exitPoint = vec.madd(entry, d, exitDist)\n const hole = addHole(o, p, entry, n, (caliber / 1000) * (mat.ductility >= 0.3 ? 1 : 1.5), true, exitPoint, src)\n if (p.layers.length > 0) spallOuter(o, p, exitPoint, -face, vec.scale(n, -1), Math.max(0.03, (caliber / 1000) * 4), src)\n addBreach(o, p, entry, Math.PI * (hole.diameter / 2) * (hole.diameter / 2), E, d, src)\n // a thin ductile sheet is dished around the hole it is punched through: deeper the more energy the shot carries\n if (mat.ductility >= 0.5 && p.thickness <= THIN_SHEET_DISHING) addDent(o, p, entry, n, Math.max((caliber * 3) / 1000, 0.012), clamp(E * 0.00002, 0.001, 0.03), src)\n if (brittle && mat.fracture === 'shatter') addCrack(o, p, entry, n, crackLen, src)\n if (p.spec.contains && (p.st.liters ?? 0) > 1e-4) {\n emit({\n ...base(o, src), type: 'leak', part: id, fluid: p.spec.contains.fluid, point: entry,\n direction: p.spec.contains.outflow ? vec.normalize(rotateVec(o.st.rotation, rotateVec(p.q, p.spec.contains.outflow))) : n, rate: holeRate(hole, !!p.spec.contains.pressurized),\n pressurized: !!p.spec.contains.pressurized,\n })\n rollIgnition(o, p, round)\n }\n } else if (mat.ductility >= 0.5) {\n addDent(o, p, entry, n, Math.max((caliber * 3) / 1000, 0.012), clamp(Math.min(Math.max(p.thickness * 3, 0.003), ratio * 0.01), 0.001, 0.05), src)\n } else if (brittle) {\n // a wall of units (brick, block) takes a round in a crater, not a star of cracks: those are glass's and a slab's\n if (!p.spec.units) addCrack(o, p, entry, n, crackLen, src)\n if (mat.fracture !== 'shatter') addHole(o, p, entry, n, caliber / 1000, false, undefined, src)\n } else addHole(o, p, entry, n, caliber / 1000, false, undefined, src)\n debris(o, p, mat.hitDebris, entry, n, clamp(Math.round(E / 60) + 2, 2, 14), clamp(Math.sqrt(E) / 6, 1, 8), src)\n // a bullet only wears the joints of the part it hits, by the energy the part absorbed (a through-and-through shot transfers little), and only along\n // the stretch of each joint it shakes\n wearJoints(o, p, (penetrated ? thr : E) * 0.02, undefined, 0, src, true, BULLET_JOINT_SPAN)\n // a round that goes through a ductile shell (sheet metal, a plastic wall) punches a clean hole and leaves in it only the energy it took to cross it: a 9 mm through a\n // 3 mm plastic bin leaves 24 of its 500 J. So does a hollow shell of a material that tears (a cardboard box, a carton): the round punches through its thin wall and\n // leaves a hole, it does not shred the box. Brittle, fibrous and layered materials (glass, wood, a solid stack of paper, masonry) take the whole shock, as before.\n const hollowTear = mat.fracture === 'tear' && p.spec.fill !== undefined && p.spec.fill < 0.5\n const absorbed = penetrated && ((mat.ductility >= 0.5 && mat.fracture !== 'tear') || hollowTear) ? Math.min(E, thr) : E\n const dmg = applyDamage(o, p, absorbed * DMG_PER_J * scale, 'ballistic', entry, d, absorbed * 0.1, 12, src)\n if (!isLost(p)) tearAt(o, p, 'ballistic', entry, penetrated ? exitPoint : undefined, d, E, caliber / 1000, src)\n // a wall of units: the unit hit takes what the bullet left in it (all of it when the bullet stopped), and comes out when it took enough\n chipUnits(o, p, 'ballistic', entry, penetrated ? Math.min(E, Math.max(thr, E * 0.5)) : E, d, Math.max(0.05, (caliber / 1000) * 8), src)\n return { penetrated, exitEnergy: penetrated ? (penMm !== undefined ? E * (1 - thr / Ep) : E - thr / (hard ? piercing : 1)) : 0, exitPoint, damage: dmg }\n }\n\n const melee = (o: ObjRT, p: PartRT, kind: 'blunt' | 'slash', E: number, point: Vec3, n: Vec3, d: Vec3, contactR: number, src?: string): number => {\n const mat = p.mat\n const thrMm = mat.penetration * p.thickness * 1000\n // brittle thin shells (a bottle, a mug, a pane) break from a knock that a thick block shrugs off\n const fragile = kind === 'blunt' ? fragility(mat.ductility, p.thickness) : 1\n const Ec = E * fragile\n // a foil-like sheet folds deeper than a plate for the same blow (up to 4 times for a tenth of a millimetre), on the patch the blow touches\n const sheet = mat.ductility >= 0.5 && p.thickness <= THIN_SHEET_CRUSH\n const fold = sheet ? Math.min(4, Math.sqrt(0.001 / p.thickness)) : 1\n const patch = sheet ? Math.min(contactR, THIN_SHEET_CONTACT) : contactR\n if (E > 0) {\n if (kind === 'blunt') {\n // a sheet folds in at most to near its middle, never through its far wall\n if (mat.ductility >= 0.5) addDent(o, p, point, n, Math.max(patch, 0.015), clamp(E * 0.0001 * fold, 0.001, sheet ? Math.min(0.06, Math.min(...p.dims) * 0.45) : 0.06), src)\n else if (mat.ductility < 0.3) {\n if (Ec >= 5) addCrack(o, p, point, n, clamp(0.04 + Math.min(Ec, E * 6) * 0.0008, 0.04, 0.6), src)\n } else if (E >= thrMm * 0.2) addDent(o, p, point, n, Math.max(contactR, 0.015), clamp(E * 0.00006, 0.001, 0.04), src)\n } else if (mat.fracture === 'tear') {\n addHole(o, p, point, n, clamp(0.02 + E * 0.0005, 0.02, 0.3), true, undefined, src)\n } else if (mat.ductility >= 0.3 && E >= thrMm) {\n // a blade with more energy than the wall takes to cross goes through it and leaves a slit the width of the blade (a knife into a 3 mm plastic bin or a\n // drink can, an axe through a thin board); brittle walls (glass, ceramic, masonry, MDF) are only scratched\n addHole(o, p, point, n, clamp(contactR, 0.01, 0.08), true, undefined, src)\n // a foil-thin sheet (a can) is pushed in around the slit\n if (sheet) addDent(o, p, point, n, Math.max(patch * 0.6, 0.01), clamp(E * 0.00004 * fold, 0.0005, 0.02), src)\n } else if (mat.ductility >= 0.5) {\n addDent(o, p, point, n, Math.max(contactR, 0.01), clamp(E * 0.00004, 0.0005, 0.02), src)\n }\n debris(o, p, mat.hitDebris, point, n, clamp(Math.round(E / 25) + 1, 1, 10), clamp(Math.sqrt(E) / 8, 1, 6), src)\n }\n // a blow shakes the joints of the part it lands on, except on the terrain a structure stands on (an anchored part tagged `terrain`): a piece that lands on the\n // ground does not loosen every wall that stands on it\n if (kind === 'blunt') {\n if (!(p.anchored && p.spec.tags?.includes('terrain'))) wearJoints(o, p, E * 0.3, undefined, 0, src)\n } else wearJoints(o, p, E * 0.3, point, 0.06, src)\n if (kind === 'blunt' && E > 0 && p.layers.length > 0) spallOuter(o, p, point, faceOf(o, p, n), n, Math.max(contactR, 0.05), src)\n const scale = mat.damageScale?.[kind] ?? 1\n const done = applyDamage(o, p, Ec * DMG_PER_J * scale * (kind === 'slash' ? p.cutFactor : 1), kind, point, d, E * 0.1, 12, src)\n addBreach(o, p, point, breachAreaOf(p, done, false), E, d, src)\n // a blow that did not open the wall wears the units it lands on\n if (kind === 'blunt') chipUnits(o, p, 'blunt', point, E, d, Math.max(contactR, 0.03), src)\n if (E > 0 && !isLost(p)) tearAt(o, p, kind, point, undefined, d, E, clamp(contactR * 0.2, 0.006, 0.02), src)\n return done\n }\n\n /**\n * What one part takes of a blast: dents, cracks, debris, heat, joint wear and the hit points. `reach` is the share of the blast that gets to the\n * part (`blast.shelter`; 1 without it) and it comes back, so a caller can report it. It is computed from the point of the part nearest to the centre.\n */\n const blastPart = (o: ObjRT, p: PartRT, point: Vec3, energy: number, radius: number, src: string | undefined, res: HitResult, reachAt?: (wp: Vec3, p: PartRT) => number): number | null => {\n if (isLost(p)) return null\n const { c, q } = partXf(o, p)\n const lp = toLocal(c, q, point)\n const dist = distanceToShape(p.spec.shape, lp)\n if (dist >= radius) return null\n const sp = surfacePoint(p.spec.shape, lp)\n const wp = toWorld(c, q, sp.point)\n const reach = reachAt ? reachAt(wp, p) : 1\n const f = (1 - dist / radius) ** 2 * reach\n const Ein = energy * f * BLAST_COUPLING\n const wn = rotateVec(q, sp.normal)\n if (!res.part) {\n res.part = p.spec.id\n res.point = wp\n }\n const mat = p.mat\n if (Ein > 20) {\n if (mat.ductility >= 0.5) addDent(o, p, wp, wn, clamp(0.05 + Math.sqrt(Ein) * 0.002, 0.05, 0.4), clamp(0.004 + Ein * 0.00002, 0.004, 0.08), src)\n else if (mat.ductility < 0.3 && Ein > 60) addCrack(o, p, wp, wn, clamp(0.05 + Ein * 0.0005, 0.05, 1), src)\n debris(o, p, mat.hitDebris, wp, wn, clamp(Math.round(Ein / 80) + 1, 1, 12), clamp(Math.sqrt(Ein) / 4, 2, 15), src)\n }\n const th = mat.thermal\n if (th.ignitionC !== undefined && p.st.fuel > 0) {\n p.st.temperature += 300 * f\n o.active = true\n if (f >= 0.25 && !p.st.burning) {\n p.st.temperature = Math.max(p.st.temperature, th.ignitionC + 1)\n checkIgnite(o, p, src)\n }\n }\n // a blast loosens a long joint (the mortar bed of a wall) over the stretch it breaks, not all along it\n wearJoints(o, p, Ein * 0.5, undefined, 0, src, false, 2 * BREACH_BLAST_REACH * Math.cbrt(Math.max(0, energy) / 1000))\n const amount = Ein * DMG_PER_J * (mat.damageScale?.explosive ?? 1)\n if (blastFrontSpeed > 0 && dist > 0 && mat.tags?.includes('glass')) {\n frontQueue.push({ o, p, due: time + dist / blastFrontSpeed, amount, fragEnergy: Ein * 0.3, point, ...(src !== undefined ? { src } : {}) })\n return reach\n }\n if (Ein > 20 && p.layers.length > 0) spallOuter(o, p, wp, faceOf(o, p, wn), wn, clamp(0.05 + Math.sqrt(Ein) * 0.002, 0.05, 0.4), src)\n const dealt = applyDamage(o, p, amount, 'explosive', point, null, Ein * 0.3, 40, src)\n res.damage += dealt\n if (p.bend && flexure.enabled) bendByBlast(o, p, point, energy, radius, reach, src)\n // laid units (brick, block in their mortar) come out by the unit; a cast part (its units are of its own material) opens as one breach\n const breachReach = BREACH_BLAST_REACH * Math.cbrt(Math.max(0, energy) / 1000)\n if (p.spec.units && p.spec.units.mortar !== p.spec.material) blastUnits(o, p, wp, energy, dist, src)\n // a reinforced member (a pillar, a beam) is cut through only by a charge at or near contact; further off the blast takes the concrete it reaches\n // out of it, block by block, the bars show there and the cage holds the member to what it rests on\n else if (p.spec.reinforcement && p.spec.units && dist > MEMBER_CUT_REACH * breachReach) blastUnits(o, p, wp, energy, dist, src)\n else if (dist <= breachReach) addBreach(o, p, wp, breachAreaOf(p, dealt, true), Ein, null, src)\n return reach\n }\n\n const blastProbe = { partsTested: 0, partsNear: 0 }\n\n /** Broad phase: the blast centre in object space against each part's bounding sphere, so a part out of reach costs three subtractions and no allocation. */\n const blastCandidates = (o: ObjRT, point: Vec3, radius: number): PartRT[] => {\n const local = toLocal(o.st.position, o.st.rotation, point)\n const near: PartRT[] = []\n for (const p of o.parts) {\n const reach = radius + p.bound\n const dx = local[0] - p.pos[0]\n const dy = local[1] - p.pos[1]\n const dz = local[2] - p.pos[2]\n if (dx * dx + dy * dy + dz * dz >= reach * reach) continue\n // a footing or a ground beam is in the soil: the air blast reaches it only from a charge against it\n if (p.spec.anchored && p.spec.structure?.role === 'foundation' && distToPart(o, p, point) > BURIED_BLAST_REACH) continue\n near.push(p)\n }\n blastProbe.partsTested += o.parts.length\n blastProbe.partsNear += near.length\n return near\n }\n\n const blastObject = (o: ObjRT, point: Vec3, energy: number, radius: number, src?: string): HitResult => {\n const start = cur.length\n const res: HitResult = { object: o.id, damage: 0, penetrated: false, exitEnergy: 0, events: [] }\n for (const p of blastCandidates(o, point, radius)) blastPart(o, p, point, energy, radius, src, res)\n res.events = cur.slice(start)\n return res\n }\n\n // -------------------------------------------------------------------------------------------------------------------------------------------\n // Blast options: shelter, fragment hits, confinement (all off by default)\n // -------------------------------------------------------------------------------------------------------------------------------------------\n\n interface BlastCfg {\n shelter: Required<ShelterOptions> | null\n frag: Required<FragmentHitOptions> | null\n /** A number is the multiplier itself. */\n conf: Required<ConfinementOptions> | number | null\n }\n\n const blastCfg = (call?: BlastOptions): BlastCfg => {\n const pick = <K extends keyof BlastOptions>(key: K): BlastOptions[K] => (call && call[key] !== undefined ? call[key] : options.blast?.[key])\n const merge = <T extends object>(v: boolean | T | undefined, defaults: Required<T>): Required<T> | null => {\n if (!v) return null\n const out = { ...defaults }\n if (v !== true) for (const [key, value] of Object.entries(v)) if (value !== undefined) (out as Record<string, unknown>)[key] = value\n return out\n }\n const conf = pick('confinement')\n return {\n shelter: merge(pick('shelter'), SHELTER_DEFAULTS),\n frag: merge(pick('fragmentHits'), FRAGMENT_HIT_DEFAULTS),\n conf: typeof conf === 'number' ? (Number.isFinite(conf) ? Math.max(0, conf) : 1) : merge(conf, CONFINEMENT_DEFAULTS),\n }\n }\n\n /** Same directions in every blast of this world: a Fibonacci lattice turned by the world seed. */\n const confinementRays = new Map<number, Vec3[]>()\n const raysOf = (n: number): Vec3[] => {\n let rays = confinementRays.get(n)\n if (rays) return rays\n const r = createRng((options.seed ?? 1) ^ 0x5bd1e995)\n const off = r.next()\n const phi0 = r.next() * Math.PI * 2\n rays = []\n for (let i = 0; i < n; i++) {\n const y = 1 - (2 * (i + off)) / n\n const s = Math.sqrt(Math.max(0, 1 - y * y))\n const phi = phi0 + i * 2.399963229728653\n rays.push([Math.cos(phi) * s, y, Math.sin(phi) * s])\n }\n confinementRays.set(n, rays)\n return rays\n }\n\n /** Pressure multiplier of a blast at `point`: the host's number, or an estimate from rays that hit parts (never the ones that are lost or open). */\n const confinementOf = (conf: BlastCfg['conf'], point: Vec3, radius: number): number => {\n if (conf === null) return 1\n if (typeof conf === 'number') return conf\n let hits = 0\n let sum = 0\n for (const d of raysOf(Math.max(1, Math.round(conf.rays)))) {\n const h = raycastInternal(point, d, radius * conf.reach, undefined, true)\n if (h) {\n hits++\n sum += h.distance\n }\n }\n if (hits === 0) return 1\n const closed = hits / Math.max(1, Math.round(conf.rays))\n const ratio = clamp(radius / Math.max(sum / hits, 1e-3), 0, 2)\n return Math.min(Math.max(1, conf.max), 1 + conf.gain * closed ** conf.power * ratio)\n }\n\n const FLAG_LOST = 1\n const FLAG_OPEN = 2\n\n /** The legacy blast: every part of every object, then every impl, each at full strength. */\n const blastPlain = (point: Vec3, energy: number, radius: number, src?: string, lethal?: number): HitResult[] => {\n const out: HitResult[] = []\n for (const o of [...objects.values()]) {\n if (vec.distance(toWorld(o.st.position, o.st.rotation, o.bc), point) - o.br >= radius) continue\n const r = blastObject(o, point, energy, radius, src)\n if (r.part) out.push(r)\n }\n for (const im of [...impls.values()]) {\n if (implInRange(im, point, radius)) out.push(implHit(im, { type: 'explosive', point, energy, radius, ...(lethal !== undefined ? { lethalRadius: lethal } : {}), ...(src !== undefined ? { source: src } : {}) }))\n }\n return out\n }\n\n const implParts = (im: ImplRT) =>\n im.impl.describe().parts.map((ps) => {\n const ov = im.poses.get(ps.id)\n return { ps, c: toWorld(im.position, im.rotation, ov?.pos ?? ps.position), q: quat.mul(im.rotation, ov?.q ?? quatFromEuler(...(ps.rotation ?? [0, 0, 0]))) }\n })\n\n const implInRange = (im: ImplRT, point: Vec3, radius: number): boolean => implParts(im).some(({ ps, c, q }) => distanceToShape(ps.shape, toLocal(c, q, point)) < radius)\n\n /** A blast with shelter, fragment hits or confinement. Parts are served from the nearest to the farthest, so a wall takes the blast (and may break) before what is behind it. */\n const blastScene = (point: Vec3, energy: number, radius: number, src: string | undefined, cfg: BlastCfg, only?: ObjRT | ImplRT, lethal?: number): HitResult[] => {\n const mult = confinementOf(cfg.conf, point, radius)\n const E = energy * mult\n const shelter = cfg.shelter\n const flags = new Map<PartRT, number>()\n const inRange: ObjRT[] = []\n for (const o of objects.values()) {\n if (vec.distance(toWorld(o.st.position, o.st.rotation, o.bc), point) - o.br >= radius) continue\n inRange.push(o)\n if (shelter) for (const p of o.parts) flags.set(p, (isLost(p) ? FLAG_LOST : 0) | (p.st.opening || p.st.stripped ? FLAG_OPEN : 0))\n }\n // what each blocker stands in front of, to aim its fragments\n const shields = new Map<PartRT, Vec3[]>()\n /** Share of the blast that gets to `tp` (world) through everything between it and the centre; `self` never blocks. */\n const reachAt = (tp: Vec3, self: PartRT | null): number => {\n if (!shelter) return 1\n const L = vec.distance(point, tp)\n if (L < 1e-4) return 1\n const d = vec.scale(vec.sub(tp, point), 1 / L)\n let t = 1\n for (const o of inRange) {\n if (raySphereMiss(point, d, toWorld(o.st.position, o.st.rotation, o.bc), o.br, L)) continue\n for (const p of o.parts) {\n if (p === self) continue\n const was = flags.get(p) ?? 0\n if (was & FLAG_LOST) continue\n const r = rayPart(o, p, point, d)\n if (!r) continue\n const t0 = Math.max(r.t0, 0)\n const path = Math.min(r.t1, L) - t0\n if (path < shelter.minPath) continue\n const mid = vec.madd(point, d, t0 + path / 2)\n const opening = p.st.opening && insideOpening(o, p, mid)\n if (opening && was & FLAG_OPEN) continue\n if (p.st.stripped && was & FLAG_OPEN) continue\n const resistance = p.mat.hpPerKg * p.mat.density * path * (p.mat.damageScale?.shelter ?? 1)\n let ti = Math.exp(-resistance / shelter.k)\n // destroyed or breached by this same blast: part of what it held back goes through\n if (isLost(p) || opening || (p.st.stripped && !(was & FLAG_OPEN))) ti += (1 - ti) * shelter.brokenTransmission\n t *= ti\n if (cfg.frag) {\n let list = shields.get(p)\n if (!list) shields.set(p, (list = []))\n list.push(tp)\n }\n }\n }\n return t\n }\n\n interface Item { dist: number; order: number; o?: ObjRT; p?: PartRT; im?: ImplRT }\n const items: Item[] = []\n let order = 0\n for (const o of inRange) {\n if (only && only !== o) continue\n for (const p of blastCandidates(o, point, radius)) {\n if (isLost(p)) continue\n const dist = distToPart(o, p, point)\n if (dist < radius) items.push({ dist, order: order++, o, p })\n }\n }\n for (const im of impls.values()) {\n if (only && only !== im) continue\n let dist = Infinity\n for (const { ps, c, q } of implParts(im)) dist = Math.min(dist, distanceToShape(ps.shape, toLocal(c, q, point)))\n if (dist < radius) items.push({ dist, order: order++, im })\n }\n items.sort((a, b) => a.dist - b.dist || a.order - b.order)\n\n const results = new Map<ObjRT | ImplRT, HitResult>()\n const reports = new Map<ObjRT | ImplRT, BlastReport>()\n const report = (key: ObjRT | ImplRT): BlastReport => {\n let r = reports.get(key)\n if (!r) reports.set(key, (r = { shelter: 0, confinement: mult, fragmentHits: 0 }))\n return r\n }\n const thrown: Array<{ frag: Fragment; object: string; part: PartRT | null }> = []\n const sweep = (from: number) => {\n if (!cfg.frag) return\n for (let i = from; i < cur.length; i++) {\n const e = cur[i]!\n if (e.type !== 'fracture' && e.type !== 'stage') continue\n for (const frag of e.fragments ?? []) thrown.push({ frag, object: e.object, part: objects.get(e.object)?.byId.get(e.part) ?? null })\n }\n }\n\n for (const it of items) {\n if (it.o && it.p) {\n const o = it.o\n let res = results.get(o)\n if (!res) results.set(o, (res = { object: o.id, damage: 0, penetrated: false, exitEnergy: 0, events: [] }))\n const start = cur.length\n const k = blastPart(o, it.p, point, E, radius, src, res, shelter ? reachAt : undefined)\n res.events.push(...cur.slice(start))\n sweep(start)\n if (k !== null) {\n const rep = report(o)\n rep.shelter = Math.max(rep.shelter, k)\n if (shelter) (rep.parts ??= {})[it.p.spec.id] = k\n }\n } else if (it.im) {\n const im = it.im\n // the impl takes one hit: the share of the blast that gets to its parts, weighted by how hard the blast hits each\n let num = 0\n let den = 0\n for (const { ps, c, q } of implParts(im)) {\n const lp = toLocal(c, q, point)\n const dist = distanceToShape(ps.shape, lp)\n if (dist >= radius) continue\n const f = (1 - dist / radius) ** 2\n const sp = surfacePoint(ps.shape, lp)\n num += f * reachAt(toWorld(c, q, sp.point), null)\n den += f\n }\n const k = den > 0 ? num / den : 1\n const res = implHit(im, { type: 'explosive', point, energy: E * k, radius, ...(lethal !== undefined ? { lethalRadius: lethal } : {}), ...(shelter ? { shelter: k } : {}), ...(src !== undefined ? { source: src } : {}) })\n results.set(im, res)\n report(im).shelter = k\n }\n }\n\n if (cfg.frag && thrown.length > 0) {\n const g = cfg.frag\n const energyOf = (f: Fragment) => 0.5 * f.mass * (f.velocity[0] ** 2 + f.velocity[1] ** 2 + f.velocity[2] ** 2)\n const list = thrown\n .map((t, i) => ({ ...t, i, e: energyOf(t.frag) }))\n .sort((a, b) => b.e - a.e || a.i - b.i)\n .slice(0, Math.max(0, Math.floor(g.max)))\n list.forEach((t, i) => throwFragment(t.frag, t.object, t.part, g, point, i, src, shields, results, reports, mult))\n }\n\n const out: HitResult[] = []\n const reportShelter = (key: ObjRT | ImplRT, res: HitResult) => {\n res.blast = reports.get(key) ?? { shelter: 1, confinement: mult, fragmentHits: 0 }\n }\n const summary: Array<{ object: string; part?: string; factor: number }> = []\n let fragmentHits = 0\n for (const o of objects.values()) {\n const r = results.get(o)\n if (!r?.part) continue\n reportShelter(o, r)\n out.push(r)\n for (const [part, factor] of Object.entries(r.blast?.parts ?? {})) summary.push({ object: o.id, part, factor })\n fragmentHits += r.blast?.fragmentHits ?? 0\n }\n for (const im of impls.values()) {\n const r = results.get(im)\n if (!r) continue\n reportShelter(im, r)\n out.push(r)\n if (shelter) summary.push({ object: im.impl.id, factor: r.blast?.shelter ?? 1 })\n fragmentHits += r.blast?.fragmentHits ?? 0\n }\n emit({ type: 'blast', object: '', time, ...(src !== undefined ? { source: src } : {}), point, energy: E, radius, confinement: mult, shelter: summary, fragmentHits })\n return out\n }\n\n /** Integer seed from numbers: a fragment's flight depends only on the blast and on the fragment, not on what the world did before. */\n const seedOf = (...nums: number[]): number => {\n let h = 2166136261\n for (const n of nums) {\n h = Math.imul(h ^ (Math.round(n * 1000) | 0), 16777619)\n h ^= h >>> 15\n }\n return h | 0\n }\n\n /**\n * The stream a wood part plans its break on: read off the world's stream without drawing from it (so a save carries it), and mixed with the object,\n * the part and where it was hit.\n */\n const splitStream = (objectId: string, partId: string, hit: Vec3): (() => number) => {\n const codes = Array.from(`${objectId}|${partId}`, (char) => char.charCodeAt(0) / 1000)\n const stream = createRng(seedOf(rng.state() / 1000, ...codes, hit[0], hit[1], hit[2]))\n return () => stream.next()\n }\n\n /** One fragment of a part the blast broke flies on: a low-energy hit on the first part or impl it reaches within its throw. */\n const throwFragment = (\n frag: Fragment, objectId: string, from: PartRT | null, g: Required<FragmentHitOptions>, centre: Vec3, index: number, src: string | undefined,\n shields: Map<PartRT, Vec3[]>, results: Map<ObjRT | ImplRT, HitResult>, reports: Map<ObjRT | ImplRT, BlastReport>, mult: number,\n ) => {\n const v = frag.velocity\n const speed = Math.hypot(v[0], v[1], v[2])\n const energy = g.energyFactor * 0.5 * frag.mass * speed * speed\n if (speed < 0.5 || energy < 1) return\n const r = createRng(seedOf(options.seed ?? 1, centre[0], centre[1], centre[2], index, frag.center[0], frag.center[1], frag.center[2]))\n let dir = vec.scale(v, 1 / speed)\n // a fragment of a blocker whose flight points at a target behind it goes for that target\n const behind = from ? shields.get(from) : undefined\n if (behind) {\n let best = Math.cos((g.aim * Math.PI) / 180)\n for (const tp of behind) {\n const to = vec.sub(tp, frag.center)\n const len = vec.length(to)\n if (len < 1e-4) continue\n const cos = vec.dot(dir, to) / len\n if (cos >= best) {\n best = cos\n dir = vec.scale(to, 1 / len)\n }\n }\n }\n const spread = Math.tan((g.spread * Math.PI) / 180)\n dir = vec.normalize([dir[0] + (r.next() - 0.5) * 2 * spread, dir[1] + (r.next() - 0.5) * 2 * spread, dir[2] + (r.next() - 0.5) * 2 * spread], dir)\n const range = Math.min(g.range, speed * g.flightTime)\n const origin = vec.madd(frag.center, dir, 0.02)\n const rh = raycastInternal(origin, dir, range, from ? new Set([`${objectId}\\0${from.spec.id}`]) : undefined)\n if (!rh) return\n const hit: Hit = {\n type: g.hitType, point: rh.point, direction: dir, energy, radius: 0.05, part: rh.part,\n ...(g.hitType === 'ballistic' ? { caliber: clamp(Math.max(...frag.size) * 1000, 3, 30), mass: frag.mass * 1000 } : {}),\n ...(src !== undefined ? { source: src } : {}),\n }\n emit({ type: 'fragment_hit', object: objectId, time, ...(src !== undefined ? { source: src } : {}), from: { object: objectId, part: frag.part }, target: { object: rh.object, part: rh.part }, point: rh.point, direction: dir, energy, mass: frag.mass, speed })\n const im = impls.get(rh.object)\n const o = im ? undefined : objects.get(rh.object)\n const key = im ?? o\n if (!key) return\n const res = im ? implHit(im, hit) : doHit(o!, hit, o!.byId.get(rh.part))\n const have = results.get(key)\n if (have) {\n have.damage += res.damage\n have.events.push(...res.events)\n if (!have.part) have.part = res.part\n if (res.penetrated) have.penetrated = true\n } else results.set(key, { ...res, events: [...res.events] })\n let rep = reports.get(key)\n if (!rep) reports.set(key, (rep = { shelter: 1, confinement: mult, fragmentHits: 0 }))\n rep.fragmentHits++\n }\n\n const blastWorld = (point: Vec3, energy: number, radius: number, src?: string, call?: BlastOptions, only?: ObjRT | ImplRT, lethal?: number): HitResult[] => {\n const cfg = blastCfg(call)\n const res = !cfg.shelter && !cfg.frag && cfg.conf === null ? blastPlain(point, energy, radius, src, lethal) : blastScene(point, energy, radius, src, cfg, only, lethal)\n // a blast is a flame: a container that leaks flammable fluid inside it catches\n lightLeaksNear(point, radius)\n return res\n }\n\n const heatObject = (o: ObjRT, point: Vec3, T: number, radius: number, duration: number, src?: string): HitResult => {\n const start = cur.length\n const res: HitResult = { object: o.id, damage: 0, penetrated: false, exitEnergy: 0, events: [] }\n for (const p of o.parts) {\n if (isLost(p)) continue\n const dist = distToPart(o, p, point)\n if (dist >= radius) continue\n const f = clamp(1 - dist / radius, 0.25, 1)\n if (!res.part) {\n res.part = p.spec.id\n res.point = point\n }\n if (T > p.st.temperature) {\n const k = (0.8 * f) / (p.mat.thermal.heatCapacity ?? 1)\n p.st.temperature += (T - p.st.temperature) * (1 - Math.exp(-k * duration))\n }\n o.active = true\n // a flame held against a flammable leak lights it: it burns, or goes off by its chain, at the next update\n if (T >= FLAME_LIGHTS_LEAK_C && !p.rt.jet && !p.rt.lit && leaksFlammable(p)) p.rt.lit = true\n checkIgnite(o, p, src)\n }\n res.events = cur.slice(start)\n return res\n }\n\n /** `fn` with every event it emits tagged with the blow `type` (a shot, a hit). */\n const withBlow =\n <T>(type: DamageType, fn: () => T) =>\n (): T => {\n const outer = blow\n blow = type\n try {\n return fn()\n } finally {\n blow = outer\n }\n }\n\n const doHit = (o: ObjRT, hit: Hit, only?: PartRT): HitResult => withBlow(hit.type, () => resolveHit(o, hit, only))()\n\n const resolveHit = (o: ObjRT, hit: Hit, only?: PartRT): HitResult => {\n let point = hit.point\n let dir = hit.direction\n if (hit.space === 'local') {\n point = toWorld(o.st.position, o.st.rotation, point)\n if (dir) dir = rotateVec(o.st.rotation, dir)\n }\n const src = hit.source\n const start = cur.length\n let res: HitResult = { object: o.id, damage: 0, penetrated: false, exitEnergy: 0, events: [] }\n const E = hit.energy ?? 0\n if (hit.type === 'ballistic') {\n const loc = locate(o, point, dir, 0.05, only)\n if (loc) {\n const out = ballistic(o, loc.p, loc.point, loc.normal, loc.dir, E, hit.caliber ?? 9, loc.pathLen, src, hit)\n res = { ...res, part: loc.p.spec.id, point: loc.point, damage: out.damage, penetrated: out.penetrated, exitEnergy: out.exitEnergy }\n }\n } else if (hit.type === 'blunt' || hit.type === 'slash') {\n const radius = hit.radius ?? 0\n const loc = locate(o, point, dir, Math.max(0.05, radius), only)\n if (loc) {\n res.part = loc.p.spec.id\n res.point = loc.point\n res.damage += melee(o, loc.p, hit.type, E, loc.point, loc.normal, loc.dir, radius || 0.03, src)\n if (radius > 0.1 && !only) {\n for (const p of o.parts) {\n if (p === loc.p || isLost(p)) continue\n const dd = distToPart(o, p, point)\n if (dd >= radius) continue\n const { c, q } = partXf(o, p)\n const sp = surfacePoint(p.spec.shape, toLocal(c, q, point))\n res.damage += melee(o, p, hit.type, E * (1 - dd / radius) ** 2, toWorld(c, q, sp.point), rotateVec(q, sp.normal), loc.dir, radius, src)\n }\n }\n }\n } else if (hit.type === 'explosive') {\n const call = hit.blast || hit.confinement !== undefined ? { ...hit.blast, ...(hit.confinement !== undefined ? { confinement: hit.confinement } : {}) } : undefined\n const cfg = blastCfg(call)\n if (!cfg.shelter && !cfg.frag && cfg.conf === null) res = blastObject(o, point, E, hit.radius ?? 2, src)\n else {\n res = blastWorld(point, E, hit.radius ?? 2, src, call, o)[0] ?? res\n res.events = cur.slice(start)\n }\n } else {\n res = heatObject(o, point, hit.temperature ?? 800, hit.radius ?? 0.25, hit.duration ?? 1, src)\n }\n res.events = cur.slice(start)\n return res\n }\n\n // -------------------------------------------------------------------------------------------------------------------------------------------\n // Fire, heat, melting, leaks\n // -------------------------------------------------------------------------------------------------------------------------------------------\n\n const checkIgnite = (o: ObjRT, p: PartRT, src?: string) => {\n const th = p.mat.thermal\n if (isLost(p) || p.st.burning || th.ignitionC === undefined || p.st.fuel <= 0 || p.st.temperature < th.ignitionC) return\n p.st.burning = true\n p.st.temperature = Math.max(p.st.temperature, th.flameC ?? 800)\n o.active = true\n markDamaged(p)\n emit({ ...base(o, src), type: 'ignite', part: p.spec.id, point: partXf(o, p).c })\n }\n\n const syncMass = (p: PartRT) => {\n p.st.mass = Math.max(0, p.mass0 * (1 - p.st.melt) - (p.fuel0 - p.st.fuel))\n }\n\n const burnStep = (o: ObjRT, p: PartRT, dt: number) => {\n const th = p.mat.thermal\n const use = Math.min((th.burnRate ?? 0.01) * p.area * dt, p.st.fuel)\n p.st.fuel -= use\n syncMass(p)\n if (p.structural) o.dirty = true\n p.st.temperature = th.flameC ?? 800\n markDamaged(p)\n if (p.fuel0 > 0) {\n p.st.char = clamp(1 - p.st.fuel / p.fuel0, 0, 1)\n p.st.hp = Math.min(p.st.hp, Math.max(1, p.st.maxHp * (p.st.fuel / p.fuel0)))\n }\n if (p.st.fuel <= 1e-9) {\n p.st.fuel = 0\n p.st.burning = false\n p.st.char = 1\n const c = partXf(o, p).c\n if ((th.fuelFraction ?? 0) >= 0.8) {\n p.st.status = 'ashes'\n p.st.hp = 0\n p.st.mass = p.mass0 * (1 - (th.fuelFraction ?? 0))\n emit({ ...base(o), type: 'burnout', part: p.spec.id, point: c })\n debris(o, p, 'ash', c, [0, 1, 0], clamp(Math.round(Math.cbrt(partVolume(p.spec.shape)) * 30), 3, 20), 1)\n partLost(o, p)\n } else {\n emit({ ...base(o), type: 'burnout', part: p.spec.id, point: c })\n }\n }\n }\n\n const meltStep = (o: ObjRT, p: PartRT, dt: number) => {\n const th = p.mat.thermal\n if (th.meltC === undefined || p.st.temperature <= th.meltC) return\n const rate = (th.meltRate ?? 0.05) * ((p.st.temperature - th.meltC) / 100)\n p.st.melt = Math.min(1, p.st.melt + rate * dt)\n syncMass(p)\n if (p.structural) o.dirty = true\n markDamaged(p)\n p.rt.dripT += dt\n if (p.rt.dripT >= 0.25) {\n p.rt.dripT -= 0.25\n const b = partWorldAabb(o, p)\n const pt: Vec3 = [b.min[0] + (b.max[0] - b.min[0]) * (0.2 + 0.6 * rnd()), b.min[1], b.min[2] + (b.max[2] - b.min[2]) * (0.2 + 0.6 * rnd())]\n emit({ ...base(o), type: 'drip', part: p.spec.id, point: pt, material: p.mat.id })\n }\n if (p.st.melt - p.rt.meltEmitted >= 0.05 || p.st.melt >= 1) {\n p.rt.meltEmitted = p.st.melt\n emit({ ...base(o), type: 'melt', part: p.spec.id, melt: p.st.melt })\n }\n if (p.st.melt >= 1) {\n p.st.status = 'melted'\n p.st.hp = 0\n p.st.mass = 0\n p.st.burning = false\n p.rt.jet = false\n partLost(o, p)\n }\n }\n\n const stepObject = (o: ObjRT, dt: number, sources: Array<{ o: ObjRT; p: PartRT; flame: number }>) => {\n const parts = o.parts\n const T0 = o.tmp\n T0.length = parts.length\n for (let i = 0; i < parts.length; i++) T0[i] = parts[i].st.temperature\n let hot = false\n for (let i = 0; i < parts.length; i++) {\n const p = parts[i]\n if (isLost(p)) continue\n const th = p.mat.thermal\n const hc = th.heatCapacity ?? 1\n const s = p.st\n if (p.rt.jet) {\n s.temperature = Math.max(s.temperature, 900)\n } else if (s.burning) {\n burnStep(o, p, dt)\n if (isLost(p)) continue\n }\n if (!s.burning && !p.rt.jet) {\n // conduction from hotter neighbours through closed joints, then cooling\n let dT = 0\n let maxN = s.temperature\n for (const j of o.byPart.get(p.spec.id)!) {\n if (j.st.open) continue\n const k = j.ia === i ? j.ib : j.ia\n if (isLost(parts[k]) || T0[k] <= T0[i]) continue\n const c = (th.conductivity + parts[k].mat.thermal.conductivity) / 2\n dT += (T0[k] - T0[i]) * (1 - Math.exp((-1.2 * c * dt) / hc))\n if (T0[k] > maxN) maxN = T0[k]\n }\n if (dT > 0) s.temperature = Math.min(s.temperature + dT, maxN)\n s.temperature += (ambient - s.temperature) * (1 - Math.exp(-dt / (20 * hc)))\n if (Math.abs(s.temperature - ambient) < 0.05) s.temperature = ambient\n }\n meltStep(o, p, dt)\n if (isLost(p)) continue\n checkIgnite(o, p)\n const ex = p.spec.explodes\n if (ex && chainDelayOf(p.spec, 'fire') !== undefined) {\n if (s.temperature >= (ex.atC ?? FIRE_PRIME_C)) prime(o, p, 'fire')\n } else if (ex && ex.atC !== undefined && s.temperature >= ex.atC) {\n failPart(o, p, null, null, 0, 40)\n continue\n }\n // leaks\n const cont = p.spec.contains\n if (cont && (s.liters ?? 0) > 0) {\n let rate = 0\n for (const h of s.holes) if (h.through) rate += holeRate(h, !!cont.pressurized)\n if (rate > 0) {\n s.liters = Math.max(0, (s.liters ?? 0) - rate * dt)\n hot = true\n if (FLAMMABLE_FLUIDS.includes(cont.fluid) && (s.temperature >= 350 || p.rt.lit) && !p.rt.jet) {\n p.rt.lit = false\n if (ex && chainDelayOf(p.spec, 'fire') !== undefined) {\n prime(o, p, 'fire')\n continue\n }\n if (ex) {\n failPart(o, p, null, null, 0, 40)\n continue\n }\n p.rt.jet = true\n s.burning = true\n emit({ ...base(o), type: 'ignite', part: p.spec.id, point: partXf(o, p).c })\n }\n }\n }\n if ((s.liters ?? 0) <= 0) p.rt.lit = false\n if (p.rt.jet && (s.liters ?? 0) <= 0) {\n p.rt.jet = false\n s.burning = false\n emit({ ...base(o), type: 'extinguish', part: p.spec.id })\n }\n // thermal shock\n const sc = th.thermalShockC\n if (sc !== undefined) {\n p.rt.shockT = Math.max(0, p.rt.shockT - dt)\n const rate = Math.abs(s.temperature - p.rt.prevTemp) / dt\n p.rt.prevTemp = s.temperature\n if (rate > sc && p.rt.shockT <= 0) {\n p.rt.shockT = 1\n const { c, q } = partXf(o, p)\n const lp: Vec3 = [(rnd() - 0.5) * p.dims[0], (rnd() - 0.5) * p.dims[1], (rnd() - 0.5) * p.dims[2]]\n const sp = surfacePoint(p.spec.shape, lp)\n addCrack(o, p, toWorld(c, q, sp.point), rotateVec(q, sp.normal), 0.1 + (rate / sc) * 0.1)\n applyDamage(o, p, p.st.maxHp * 0.25, 'heat', null, null, 5, 3)\n if (isLost(p)) continue\n }\n }\n if (s.burning || p.rt.jet) sources.push({ o, p, flame: p.rt.jet ? 900 : th.flameC ?? 800 })\n if (s.burning || p.rt.jet || s.temperature > ambient + 0.5) hot = true\n }\n if (o.hasStructure) {\n if (o.dirty) {\n o.dirty = false\n solveStructure(o)\n }\n for (const p of parts) {\n if (!p.structural || isLost(p)) continue\n const stress = p.st.stress ?? 0\n p.rt.stressT = Math.max(0, (p.rt.stressT ?? 0) - dt)\n if (stress > 1) {\n if (p.rt.stressT <= 0) {\n p.rt.stressT = 0.5\n emit({ ...base(o), type: 'stress', part: p.spec.id, stress, load: p.st.load ?? 0 })\n // the bare steel of an overloaded part bends further each time\n if (p.spec.reinforcement && (p.st.stripped || p.st.chipped?.length || p.st.opening)) exposeRebar(o, p)\n }\n applyDamage(o, p, overloadRate(stress) * p.st.maxHp * dt, 'blunt', null, null, 5, 3)\n } else if (stress > 0.8 && p.mat.ductility < 0.3 && p.rt.stressT <= 0 && p.st.cracks.length < 6) {\n p.rt.stressT = 0.5\n const { c, q } = partXf(o, p)\n const sp = surfacePoint(p.spec.shape, [(rnd() - 0.5) * p.dims[0], (rnd() - 0.5) * p.dims[1], (rnd() - 0.5) * p.dims[2]])\n addCrack(o, p, toWorld(c, q, sp.point), rotateVec(q, sp.normal), 0.1 + (stress - 0.8) * 0.5)\n }\n }\n if (o.maxStress > 0.8) hot = true\n }\n o.active = hot\n }\n\n /** A leak of flammable fluid within `ignition.fireNear.radius` of a burning part (or of a jet) lights at `chancePerSecond`. */\n const igniteLeaksNearFire = (sources: Array<{ o: ObjRT; p: PartRT; flame: number }>, dt: number) => {\n const { radius, chancePerSecond } = ignitionRules.fireNear\n if (chancePerSecond <= 0) return\n const chance = 1 - Math.exp(-chancePerSecond * dt)\n for (const src of sources) {\n if (!src.p.st.burning && !src.p.rt.jet) continue\n const sc = partXf(src.o, src.p).c\n for (const o of objects.values()) {\n for (const q of o.parts) {\n if (q === src.p || isLost(q) || q.rt.lit || q.rt.jet || !leaksFlammable(q)) continue\n if (vec.distance(partXf(o, q).c, sc) - q.bound - src.p.bound > radius) continue\n if (rnd() < chance) {\n q.rt.lit = true\n o.active = true\n }\n }\n }\n }\n }\n\n const spread = (sources: Array<{ o: ObjRT; p: PartRT; flame: number }>, dt: number) => {\n for (const src of sources) {\n if (!src.p.st.burning && !src.p.rt.jet) continue\n const sc = toWorld(src.o.st.position, src.o.st.rotation, src.p.pos)\n const A = partWorldAabb(src.o, src.p)\n for (const o of objects.values()) {\n if (o === src.o) continue\n if (vec.distance(toWorld(o.st.position, o.st.rotation, o.bc), sc) > o.br + src.p.bound + fireSpread) continue\n for (const q of o.parts) {\n if (isLost(q) || q.st.burning) continue\n const B = partWorldAabb(o, q)\n const gap = Math.hypot(\n Math.max(0, A.min[0] - B.max[0], B.min[0] - A.max[0]),\n Math.max(0, A.min[1] - B.max[1], B.min[1] - A.max[1]),\n Math.max(0, A.min[2] - B.max[2], B.min[2] - A.max[2]),\n )\n if (gap >= fireSpread || src.flame <= q.st.temperature) continue\n const f = 1 - gap / fireSpread\n q.st.temperature += (src.flame - q.st.temperature) * (1 - Math.exp((-0.6 * f * dt) / (q.mat.thermal.heatCapacity ?? 1)))\n o.active = true\n }\n }\n }\n }\n\n // -------------------------------------------------------------------------------------------------------------------------------------------\n // World API\n // -------------------------------------------------------------------------------------------------------------------------------------------\n\n /** The primed part that goes off first: earliest due time, then the older object, then the part listed first. */\n const nextPrimed = (until: number): { o: ObjRT; p: PartRT } | null => {\n let best: { o: ObjRT; p: PartRT } | null = null\n for (const [p, o] of primed) {\n if (objects.get(o.id) !== o || isLost(p)) {\n primed.delete(p)\n continue\n }\n const due = p.rt.chainDue as number\n if (due > until) continue\n if (!best) best = { o, p }\n else {\n const bestDue = best.p.rt.chainDue as number\n if (due < bestDue || (due === bestDue && (o.order < best.o.order || (o.order === best.o.order && (o.idx.get(p.spec.id) ?? 0) < (best.o.idx.get(best.p.spec.id) ?? 0))))) best = { o, p }\n }\n }\n return best\n }\n\n /**\n * Explodes the primed parts whose delay ran out by `until`, one at a time in order of time; each blast is resolved before the next part goes off,\n * so a part it primes counts its delay from that moment, not from the end of the frame.\n */\n const detonatePrimed = (until: number) => {\n const end = time\n let fired = 0\n for (let next = nextPrimed(until); next && fired < chainLinkCap; next = nextPrimed(until)) {\n fired++\n primed.delete(next.p)\n time = Math.max(0, Math.min(end, next.p.rt.chainDue as number))\n next.p.rt.chainDue = undefined\n failPart(next.o, next.p, null, null, 0, 40)\n drainBlasts()\n }\n time = end\n }\n\n /** Lands the damage of the glass the blast front has reached by `time`, the nearest first. */\n const releaseFront = () => {\n if (frontQueue.length === 0) return\n frontQueue.sort((a, b) => a.due - b.due)\n while (frontQueue.length > 0 && frontQueue[0]!.due <= time) {\n const hit = frontQueue.shift()!\n if (objects.get(hit.o.id) !== hit.o) continue\n applyDamage(hit.o, hit.p, hit.amount, 'explosive', hit.point, null, hit.fragEnergy, 40, hit.src)\n }\n }\n\n /** Collapse events are produced after the whole operation: make sure the result of the operation carries them. */\n const withCollapses = (r: { value: HitResult[]; events: DestructionEvent[] }): HitResult[] => {\n const last = r.value[r.value.length - 1]\n if (!last) return r.value\n for (const e of r.events) if (e.type === 'collapse' && !r.value.some((h) => h.events.includes(e))) last.events.push(e)\n return r.value\n }\n\n /** An explosive hit on an impl: a blast of its own when blast options are on, else the plain hit. */\n const blastImpl = (im: ImplRT, h: Hit): HitResult => {\n const call = h.blast || h.confinement !== undefined ? { ...h.blast, ...(h.confinement !== undefined ? { confinement: h.confinement } : {}) } : undefined\n const cfg = blastCfg(call)\n if (!cfg.shelter && !cfg.frag && cfg.conf === null) return implHit(im, h)\n const world = h.space === 'local' ? toWorld(im.position, im.rotation, h.point) : h.point\n const r = blastWorld(world, h.energy ?? 0, h.radius ?? 2, h.source, call, im)\n return r.find((x) => x.object === im.impl.id) ?? implHit(im, h)\n }\n\n const whole = (fn: () => HitResult): HitResult => {\n const r = run(fn)\n r.value.events = r.events\n return r.value\n }\n\n const world: DestructionWorld = {\n materials,\n get time() {\n return time\n },\n add(spec, opts: AddOptions = {}) {\n const id = opts.id ?? nextId()\n if (taken(id)) throw new Error(`object \"${id}\" already exists`)\n objects.set(id, build(resolveSpec(spec), id, opts.position ?? [0, 0, 0], opts.rotation ?? [0, 0, 0, 1]))\n return id\n },\n register(impl, opts: AddOptions = {}) {\n const id = opts.id ?? impl.id\n if (taken(id)) throw new Error(`object \"${id}\" already exists`)\n impls.set(id, { impl, position: opts.position ?? [0, 0, 0], rotation: opts.rotation ?? [0, 0, 0, 1], poses: new Map() })\n return id\n },\n setPartPose(objectId, partId, position, rotation) {\n const q = quatFromEuler(...(rotation ?? [0, 0, 0]))\n const im = impls.get(objectId)\n if (im) {\n im.impl.setPartPose?.(partId, position, rotation)\n im.poses.set(partId, { pos: [position[0], position[1], position[2]], q })\n return\n }\n const o = getObj(objectId)\n const p = getPart(o, partId)\n p.pos = [position[0], position[1], position[2]]\n p.q = q\n poseVersion++\n updateBound(o)\n },\n remove(id) {\n impls.get(id)?.impl.dispose?.()\n objects.delete(id)\n impls.delete(id)\n },\n has: (id) => taken(id),\n ids: () => [...objects.keys(), ...impls.keys()],\n setTransform(id, position, rotation) {\n const im = impls.get(id)\n if (im) {\n im.position = [position[0], position[1], position[2]]\n im.rotation = [rotation[0], rotation[1], rotation[2], rotation[3]]\n return\n }\n const o = getObj(id)\n o.base = { pos: [position[0], position[1], position[2]], rot: [rotation[0], rotation[1], rotation[2], rotation[3]] }\n applySoilPose(o)\n slideOffResting(o, rotation)\n },\n splitGroup(id, group, newId) {\n if (impls.has(id)) throw new Error(`object \"${id}\" is a registered DestructibleImpl and cannot be split; its module owns its pieces`)\n const o = getObj(id)\n if (o.st.groups.length < 2) return id\n const names = o.st.groups[group]\n if (!names) throw new Error(`object \"${id}\" has no group ${group}`)\n const moved = new Set(names)\n const nid = newId ?? nextId()\n if (objects.has(nid)) throw new Error(`object \"${nid}\" already exists`)\n // an open joint between the two objects stays with the original\n const carryFor = (keep: (pid: string) => boolean, keepOpen: (a: string, b: string) => boolean = () => false): Carry => ({\n parts: new Map(o.parts.filter((p) => keep(p.spec.id)).map((p) => [p.spec.id, { st: p.st, rt: p.rt }])),\n joints: new Map([\n ...o.joints.filter((j) => (keep(j.spec.a) && keep(j.spec.b)) || (j.st.open && keepOpen(j.spec.a, j.spec.b))).map((j): [string, { st: JointState; step: number }] => [j.spec.id, { st: j.st, step: j.step }]),\n ...o.st.joints.filter((st) => st.open && !o.jointMap.has(st.id) && keepOpen(st.a, st.b)).map((st): [string, { st: JointState; step: number }] => [st.id, { st, step: 0 }]),\n ]),\n collapsed: [...o.collapsed].filter(keep),\n })\n const sub = (keep: (pid: string) => boolean): DestructibleSpec => {\n const s: DestructibleSpec = { parts: o.spec.parts.filter((p) => keep(p.id)), joints: (o.spec.joints ?? []).filter((j) => keep(j.a) && keep(j.b)) }\n if (o.spec.name !== undefined) s.name = o.spec.name\n if (o.spec.tags) s.tags = [...o.spec.tags]\n if (o.spec.soil !== undefined) s.soil = o.spec.soil\n // the part and joint specs are never written after `add`, so the halves share them instead of deep-copying a whole house twice\n return s\n }\n const inNew = (pid: string) => moved.has(pid)\n const inOld = (pid: string) => !moved.has(pid)\n const pos = o.st.position, rot = o.st.rotation\n const fresh = build(sub(inNew), nid, pos, rot, carryFor(inNew, (a, b) => inNew(a) && inNew(b)))\n const restCarry = carryFor(inOld, (a, b) => !(inNew(a) && inNew(b)))\n if (o.st.soil) restCarry.soil = o.st.soil\n if (o.soil?.sets.size) restCarry.soilSets = Object.fromEntries(o.soil.sets)\n const rest = build(sub(inOld), id, o.soil ? o.base.pos : pos, o.soil ? o.base.rot : rot, restCarry)\n objects.set(id, rest)\n objects.set(nid, fresh)\n return nid\n },\n hit(objectId, h) {\n const im = impls.get(objectId)\n if (im) return whole(() => (h.type === 'explosive' ? blastImpl(im, h) : implHit(im, h)))\n const o = getObj(objectId)\n return whole(() => doHit(o, h))\n },\n hitPart(objectId, partId, h) {\n const im = impls.get(objectId)\n if (im) return whole(() => implHit(im, h))\n const o = getObj(objectId)\n const p = getPart(o, partId)\n return whole(() => doHit(o, h, p))\n },\n blastProbe() {\n return { ...blastProbe }\n },\n blastReach(point, target, options = {}) {\n const L = vec.distance(point, target)\n if (L < 1e-4) return 1\n const shelter: Required<ShelterOptions> = { ...SHELTER_DEFAULTS, ...options.shelter }\n const ignore = new Set(options.ignore ?? [])\n const d = vec.scale(vec.sub(target, point), 1 / L)\n let t = 1\n for (const o of objects.values()) {\n if (ignore.has(o.id) || raySphereMiss(point, d, toWorld(o.st.position, o.st.rotation, o.bc), o.br, L)) continue\n for (const p of o.parts) {\n if (isLost(p) || p.st.stripped) continue\n const r = rayPart(o, p, point, d)\n if (!r) continue\n const t0 = Math.max(r.t0, 0)\n const path = Math.min(r.t1, L) - t0\n if (path < shelter.minPath) continue\n // a hole the line goes through (a breached wall, an open window) lets the blast by\n if (p.st.opening && insideOpening(o, p, toLocal(o.st.position, o.st.rotation, vec.madd(point, d, t0 + path / 2)))) continue\n t *= Math.exp(-(p.mat.hpPerKg * p.mat.density * path * (p.mat.damageScale?.shelter ?? 1)) / shelter.k)\n if (t < 1e-4) return 0\n }\n }\n // hosted bodies (a vehicle): a part with a thickness is a shell, crossed through its two walls, not through the air inside it\n for (const im of impls.values()) {\n if (ignore.has(im.impl.id)) continue\n for (const ps of im.impl.describe().parts) {\n const mat = materials.get(ps.material)\n if (!mat) continue\n const ov = im.poses.get(ps.id)\n const r = rayPartRaw(im.position, im.rotation, ps, ov?.q ?? quatFromEuler(...(ps.rotation ?? [0, 0, 0])), point, d, ov?.pos)\n if (!r || r.t1 < 0 || r.t0 > L) continue\n let path = Math.min(r.t1, L) - Math.max(r.t0, 0)\n if (ps.thickness !== undefined && ps.thickness > 0) path = Math.min(path, 2 * ps.thickness)\n else if (path < shelter.minPath) continue\n t *= Math.exp(-(mat.hpPerKg * mat.density * path * (mat.damageScale?.shelter ?? 1)) / shelter.k)\n if (t < 1e-4) return 0\n }\n }\n return t\n },\n explode(point, energy, radius, source, blast) {\n blastProbe.partsTested = 0\n blastProbe.partsNear = 0\n return withCollapses(run(() => blastWorld(point, energy, radius, source, blast)))\n },\n raycast(origin, direction, maxDistance = Infinity) {\n const r = raycastInternal(origin, direction, maxDistance, undefined, false, true)\n return r ? { object: r.object, part: r.part, point: r.point, normal: r.normal, distance: r.distance } : null\n },\n sweepBox(box, direction, distance, options = {}) {\n const d = vec.normalize(direction)\n const ignored = options.ignore === undefined ? undefined : objects.get(options.ignore)\n // an object hosted by an impl (a vehicle) is ignored by its own parts too\n const hosted = options.ignore === undefined || ignored ? undefined : impls.get(options.ignore)\n const ignore = ignored\n ? new Set(ignored.parts.map((p) => `${ignored.id}\\0${p.spec.id}`))\n : hosted\n ? new Set(hosted.impl.describe().parts.map((p) => `${hosted.impl.id}\\0${p.id}`))\n : undefined\n let best: RayHit | null = null\n for (const origin of sweepOrigins(box, d, options.spacing ?? 0.2)) {\n const r = raycastInternal(origin, d, distance + SWEEP_BACK, ignore)\n if (!r || (best && r.distance >= best.distance)) continue\n best = { object: r.object, part: r.part, point: r.point, normal: r.normal, distance: Math.max(0, r.distance - SWEEP_BACK) }\n }\n return best\n },\n shoot(origin, direction, energy, caliber, source, round) {\n const extras: BallisticExtras = typeof round === 'number' ? { piercing: round } : round ?? {}\n return withCollapses(run(withBlow('ballistic', () => {\n const results: HitResult[] = []\n const d = vec.normalize(direction)\n const ignore = new Set<string>()\n let org = origin\n let E = energy\n for (let i = 0; i < 4 && E > 0; i++) {\n const rh = raycastInternal(org, d, Infinity, ignore, false, true)\n if (!rh) break\n const im = impls.get(rh.object)\n if (im) {\n // the penetration a weapon gives is for the muzzle energy: past each part the round goes through less\n const scaled = extras.penetration && E < energy ? { ...extras, penetration: Object.fromEntries(Object.entries(extras.penetration).map(([k, mm]) => [k, mm * (E / energy)])) } : extras\n const r = implHit(im, { type: 'ballistic', point: rh.point, part: rh.part, normal: rh.normal, direction: d, energy: E, caliber, ...scaled, ...(source !== undefined ? { source } : {}) })\n r.part = rh.part\n r.point = rh.point\n // the part says what the round keeps (a sheet takes little, a block all of it); else half, as before\n const left = r.events.find((e) => e.type === 'hole' && (e as { energyLeft?: number }).energyLeft !== undefined) as { energyLeft?: number } | undefined\n r.exitEnergy = r.penetrated ? (left?.energyLeft ?? E * 0.5) : 0\n results.push(r)\n ignore.add(`${im.impl.id}\\0${rh.part}`)\n if (!r.penetrated) break\n org = vec.madd(rh.point, d, Math.min(rh.pathLen, 0.05) + 0.001)\n E = r.exitEnergy\n continue\n }\n const o = getObj(rh.object)\n const p = getPart(o, rh.part)\n const start = cur.length\n const out = ballistic(o, p, rh.point, rh.normal, d, E, caliber, rh.pathLen, source, extras)\n results.push({ object: o.id, part: p.spec.id, point: rh.point, damage: out.damage, penetrated: out.penetrated, exitEnergy: out.exitEnergy, events: cur.slice(start) })\n ignore.add(`${o.id}\\0${p.spec.id}`)\n if (!out.penetrated || !out.exitPoint) break\n org = vec.madd(out.exitPoint, d, 0.001)\n E = out.exitEnergy\n }\n return results\n })))\n },\n disassemble(objectId, jointId, tool: ToolKind, dt) {\n const im = impls.get(objectId)\n if (im) return im.impl.disassemble ? im.impl.disassemble(jointId, tool, dt) : -1\n const o = getObj(objectId)\n const j = o.jointMap.get(jointId)\n if (!j || !j.spec.tools.includes(tool)) return -1\n if (j.st.open) return 1\n return run(() => {\n j.st.progress = Math.min(1, j.st.progress + (j.spec.seconds > 0 ? dt / j.spec.seconds : 1))\n if (j.st.progress >= 1 - 1e-9) j.st.progress = 1\n const step = Math.floor(j.st.progress * 10 + 1e-9)\n if (step > j.step || j.st.progress >= 1) {\n j.step = step\n emit({ ...base(o), type: 'disassemble_progress', joint: j.spec.id, tool, progress: j.st.progress })\n }\n if (j.st.progress >= 1) {\n j.st.open = true\n j.st.openedBy = 'tool'\n solveStructure(o)\n recomputeGroups(o)\n detachEvents(o, [j], 'tool')\n collapseCheck(o)\n }\n return j.st.progress\n }).value\n },\n workableJoints(objectId, tool) {\n const im = impls.get(objectId)\n if (im) {\n const spec = im.impl.describe()\n return im.impl.state().joints.filter((js) => {\n const j = (spec.joints ?? []).find((x) => (x.id ?? `${x.a}~${x.b}`) === js.id)\n return !js.open && !!j && (j.tools ?? JOINT_DEFAULTS[j.kind].tools).includes(tool)\n })\n }\n return getObj(objectId).joints.filter((j) => !j.st.open && j.spec.tools.includes(tool)).map((j) => j.st)\n },\n nearestJoint(objectId, point, maxDistance = 0.3, tool) {\n const im = impls.get(objectId)\n // Candidates: closed joints with their world position and whether `tool` can undo them.\n const cands: { st: JointState; d: number; ok: boolean }[] = []\n if (im) {\n const spec = im.impl.describe()\n for (const js of im.impl.state().joints) {\n if (js.open) continue\n const pos = implJointPos(im, js.a, js.b)\n const j = (spec.joints ?? []).find((x) => (x.id ?? `${x.a}~${x.b}`) === js.id)\n cands.push({ st: js, d: pos ? vec.distance(pos, point) : Infinity, ok: !!j && (j.tools ?? JOINT_DEFAULTS[j.kind].tools).includes(tool as ToolKind) })\n }\n } else {\n const o = getObj(objectId)\n for (const j of o.joints) {\n if (j.st.open) continue\n cands.push({ st: j.st, d: vec.distance(jointWorld(o, j), point), ok: tool ? j.spec.tools.includes(tool) : true })\n }\n }\n const pick = (only: boolean): JointState | null => {\n let best: JointState | null = null\n let bd = maxDistance\n for (const c of cands) {\n if (only && !c.ok) continue\n if (c.d <= bd) {\n bd = c.d\n best = c.st\n }\n }\n return best\n }\n return (tool ? pick(true) : null) ?? pick(false)\n },\n extinguish(objectId, partId, coolC = 200) {\n const im = impls.get(objectId)\n if (im) {\n run(() => im.impl.extinguish?.(partId))\n return\n }\n const o = getObj(objectId)\n run(() => {\n for (const p of partId ? [getPart(o, partId)] : o.parts) {\n if (isLost(p)) continue\n if (p.st.burning) {\n p.st.burning = false\n p.rt.jet = false\n emit({ ...base(o), type: 'extinguish', part: p.spec.id })\n }\n p.st.temperature = Math.max(ambient, p.st.temperature - coolC)\n }\n o.active = true\n })\n },\n setWind(next) {\n windOpts = { ...windOpts, ...Object.fromEntries(Object.entries(next).filter(([, v]) => v !== undefined)) }\n windCfg = resolveWind(windOpts)\n for (const o of objects.values()) {\n if (!o.hasStructure || o.spec.wind === false) continue\n o.wind ??= newWind(o)\n o.dirty = true\n o.active = true\n }\n },\n vent(objectId, partId, opening = {}) {\n if (impls.has(objectId)) return false\n const o = getObj(objectId)\n const p = getPart(o, partId)\n const c = p.spec.contains\n if (!c || isLost(p) || (p.st.liters ?? 0) <= 0) return false\n if (p.st.holes.some((h) => h.vent)) return true\n return run(() => {\n const wp = opening.point ?? partXf(o, p).c\n const wn = vec.normalize(opening.normal ?? [0, 1, 0])\n const hole: Hole = { point: objLocal(o, wp), normal: objLocalDir(o, wn), diameter: opening.diameter ?? VENT_DIAMETER, through: true, vent: true }\n p.st.holes.push(hole)\n if (p.st.holes.length > maxHoles) p.st.holes.shift()\n o.active = true\n emit({\n ...base(o), type: 'leak', part: partId, fluid: c.fluid, point: wp,\n direction: c.outflow ? vec.normalize(rotateVec(o.st.rotation, rotateVec(p.q, c.outflow))) : wn, rate: holeRate(hole, !!c.pressurized), pressurized: !!c.pressurized,\n })\n return true\n }).value\n },\n seal(objectId, partId) {\n if (impls.has(objectId)) return 0\n const o = getObj(objectId)\n const p = getPart(o, partId)\n const before = p.st.holes.length\n p.st.holes = p.st.holes.filter((h) => !h.vent)\n o.active = true\n return before - p.st.holes.length\n },\n setLiters(objectId, partId, liters) {\n if (impls.has(objectId)) return\n const p = getPart(getObj(objectId), partId)\n if (!p.spec.contains) return\n p.st.liters = clamp(liters, 0, p.spec.contains.liters)\n getObj(objectId).active = true\n },\n update(dt) {\n if (!(dt > 0)) return []\n return run(() => {\n time += dt\n const sources: Array<{ o: ObjRT; p: PartRT; flame: number }> = []\n for (const o of [...objects.values()]) if (o.active) stepObject(o, dt, sources)\n for (const o of [...objects.values()]) if (o.soil && objects.get(o.id) === o) stepSoil(o, dt)\n for (const o of [...objects.values()]) if (o.wind && objects.get(o.id) === o) stepWind(o, dt)\n if (sources.length) {\n spread(sources, dt)\n igniteLeaksNearFire(sources, dt)\n }\n detonatePrimed(time)\n releaseFront()\n for (const im of [...impls.values()]) {\n if (!im.impl.update) continue\n for (const e of im.impl.update(dt) ?? []) emit(e.time === undefined ? { ...e, time } : e)\n }\n }).events\n },\n state: (id) => objects.get(id)?.st ?? impls.get(id)?.impl.state() ?? null,\n snapshot: (id) => {\n const st = objects.get(id)?.st ?? impls.get(id)?.impl.state()\n return st ? clone(st) : null\n },\n part: (id, partId) => objects.get(id)?.byId.get(partId)?.st ?? impls.get(id)?.impl.state().parts.find((p) => p.id === partId) ?? null,\n reset(id) {\n const im = impls.get(id)\n if (im) {\n im.impl.reset?.()\n return\n }\n const o = getObj(id)\n objects.set(id, build(o.spec, id, o.base.pos, o.base.rot))\n },\n on(type: DestructionEventType | '*', fn) {\n let set = listeners.get(type)\n if (!set) listeners.set(type, (set = new Set()))\n set.add(fn)\n return () => {\n set!.delete(fn)\n }\n },\n serialize(): DestructionSnapshot {\n return {\n version: 1,\n time,\n rng: rng.state(),\n counter,\n objects: [...objects.values()].map((o) => {\n const runtime: ObjectRuntime = { parts: {}, joints: {}, collapsed: [...o.collapsed], ...(o.soil?.sets.size ? { soil: Object.fromEntries(o.soil.sets) } : {}), ...(o.wind ? { wind: [o.wind.dyn.x, o.wind.dyn.v, o.wind.dyn.y, o.wind.dyn.w, o.wind.dyn.peak] as [number, number, number, number, number] } : {}) }\n for (const p of o.parts) runtime.parts[p.spec.id] = clone(p.rt)\n for (const j of o.joints) runtime.joints[j.spec.id] = j.step\n return { id: o.id, spec: clone(o.spec), state: clone(o.st), runtime }\n }),\n ...(impls.size\n ? { impls: [...impls.values()].map((im) => ({ id: im.impl.id, position: [...im.position] as Vec3, rotation: [...im.rotation] as Quat, data: im.impl.serialize?.() })) }\n : {}),\n }\n },\n load(snap) {\n if (snap.version !== 1) throw new Error(`unsupported snapshot version ${String(snap.version)}`)\n objects.clear()\n time = snap.time\n rng.set(snap.rng)\n counter = snap.counter ?? 0\n for (const e of snap.objects) {\n const state = clone(e.state)\n const carry: Carry = {\n parts: new Map(\n state.parts.map((st) => [st.id, { st, rt: e.runtime?.parts[st.id] ? clone(e.runtime.parts[st.id]) : { ...freshRuntime(), prevTemp: st.temperature } }]),\n ),\n joints: new Map(state.joints.map((st) => [st.id, { st, step: e.runtime?.joints[st.id] ?? 0 }])),\n collapsed: e.runtime?.collapsed,\n ...(e.runtime?.wind ? { wind: e.runtime.wind } : {}),\n }\n let pos = state.position, rot = state.rotation\n if (state.soil) {\n // the saved pose has the settlement on top of the host's: take it off to get the host's back\n carry.soil = state.soil\n if (e.runtime?.soil) carry.soilSets = e.runtime.soil\n rot = quat.normalize(quat.mul(state.rotation, quat.conjugate(state.soil.offset.rotation)))\n pos = vec.sub(state.position, rotateVec(rot, state.soil.offset.position))\n }\n objects.set(e.id, build(clone(e.spec), e.id, pos, rot, carry))\n }\n for (const e of snap.impls ?? []) {\n const im = impls.get(e.id)\n if (!im) continue\n im.position = [e.position[0], e.position[1], e.position[2]]\n im.rotation = [e.rotation[0], e.rotation[1], e.rotation[2], e.rotation[3]]\n if (e.data !== undefined) im.impl.load?.(e.data)\n }\n },\n }\n return world\n}\n","[\n {\n \"id\": \"brick_wall_plastered\",\n \"name\": \"Plastered brick wall\",\n \"core\": { \"material\": \"brick\", \"thickness\": 0.09 },\n \"layers\": [{ \"material\": \"plaster\", \"thickness\": 0.02, \"faces\": \"both\" }],\n \"units\": { \"size\": [0.23, 0.075, 0.11], \"bond\": \"running\", \"mortar\": \"plaster\" },\n \"breach\": { \"area\": 0.25 }\n },\n {\n \"id\": \"concrete_block_wall\",\n \"name\": \"Concrete block wall\",\n \"core\": { \"material\": \"concrete\", \"thickness\": 0.14 },\n \"fill\": 0.55,\n \"units\": { \"size\": [0.39, 0.19, 0.14], \"bond\": \"running\", \"mortar\": \"plaster\" },\n \"breach\": { \"area\": 0.25 }\n },\n {\n \"id\": \"reinforced_concrete\",\n \"name\": \"Reinforced concrete wall\",\n \"core\": { \"material\": \"concrete\", \"thickness\": 0.2 },\n \"reinforcement\": { \"material\": \"steel\", \"spacing\": 0.18, \"diameter\": 0.008, \"residualCapacity\": 0.15 },\n \"units\": { \"size\": [0.6, 0.42, 0.2], \"bond\": \"stack\", \"mortar\": \"concrete\" },\n \"breach\": { \"area\": 0.25 }\n },\n {\n \"id\": \"drywall\",\n \"name\": \"Drywall partition on steel studs\",\n \"core\": { \"material\": \"plaster\", \"thickness\": 0.0125 },\n \"layers\": [{ \"material\": \"plaster\", \"thickness\": 0.0125, \"faces\": \"+\" }],\n \"depth\": 0.095,\n \"breach\": { \"area\": 0.25 }\n },\n {\n \"id\": \"wood_frame_wall\",\n \"name\": \"Wood frame wall\",\n \"core\": { \"material\": \"plywood\", \"thickness\": 0.012 },\n \"layers\": [{ \"material\": \"plaster\", \"thickness\": 0.0125, \"faces\": \"-\" }],\n \"depth\": 0.1135,\n \"breach\": { \"area\": 0.25 }\n },\n {\n \"id\": \"log_wall\",\n \"name\": \"Log wall\",\n \"core\": { \"material\": \"wood_soft\", \"thickness\": 0.2 },\n \"fill\": 0.785,\n \"breach\": { \"area\": 0.25 }\n },\n {\n \"id\": \"sheet_metal_shack\",\n \"name\": \"Corrugated sheet metal wall\",\n \"core\": { \"material\": \"steel\", \"thickness\": 0.0006 },\n \"depth\": 0.02,\n \"breach\": { \"area\": 0.25 }\n },\n {\n \"id\": \"glass_pane\",\n \"name\": \"Glass pane\",\n \"core\": { \"material\": \"glass\", \"thickness\": 0.006 },\n \"breach\": { \"area\": 0.1 }\n }\n]\n","import { applyPatches, mergeById, removeIds } from '@adatechnology/game-contracts'\nimport type { DeepPartial } from '@adatechnology/game-contracts'\n\nimport assembliesJson from './data/assemblies.json'\nimport { MATERIALS } from './materials'\nimport type { MaterialDef, MaterialId, PartBreach, PartSpec, PartUnits, Reinforcement, SurfaceLayer, Vec3 } from './types'\n\n/**\n * A wall as a builder builds it: a core with coats, the masonry unit it is laid in, its rebar and when it breaches. Dimensions are metres (data in\n * `src/data/assemblies.json`); `assemblyPart` turns one into a `PartSpec`. Extend or override with `registerAssembly`.\n */\nexport interface AssemblyDef {\n id: string\n name: string\n /** `thickness` is the core's, in metres: what a bullet has to get through besides the coats. */\n core: { material: MaterialId; thickness: number }\n /** Coats, outermost first. */\n layers?: readonly SurfaceLayer[]\n /** Physical depth of the wall when it is not core plus coats (a drywall partition is mostly air between the boards). */\n depth?: number\n /** Solid fraction of the core (hollow blocks, round logs): scales its mass and the thickness a bullet crosses. Default 1. */\n fill?: number\n units?: PartUnits\n reinforcement?: Reinforcement\n breach?: PartBreach\n}\n\nexport interface AssemblyPartOptions {\n id: string\n /** Along the part's x axis. */\n width: number\n /** Along the part's y axis. */\n height: number\n position: Vec3\n rotation?: Vec3\n structure?: PartSpec['structure']\n /** Other `PartSpec` fields (tags, anchored, hp...). */\n extra?: Partial<PartSpec>\n /** Materials to read densities from (default the built-in `MATERIALS`). */\n materials?: ReadonlyMap<MaterialId, MaterialDef>\n}\n\n// What the JSON held at load, before any `registerAssembly` changed the shared list.\nconst SHIPPED: readonly AssemblyDef[] = structuredClone(assembliesJson as unknown as AssemblyDef[])\n\n/**\n * Built-in assemblies; `registerAssembly` adds to this list.\n * @deprecated the list every page shares. Use `createAssemblies({ packs, patch, remove })`, or `defaultAssemblies()` for this one.\n */\nexport const ASSEMBLIES: AssemblyDef[] = assembliesJson as unknown as AssemblyDef[]\n\nexport interface AssembliesOptions {\n /** Assemblies added to the built-in ones; one with the id of a built-in replaces it. */\n readonly packs?: readonly (readonly AssemblyDef[])[]\n /** Changes by id, merged field by field over what is there. */\n readonly patch?: Readonly<Record<string, DeepPartial<AssemblyDef>>>\n /** Ids taken out. */\n readonly remove?: readonly string[]\n}\n\nexport interface Assemblies {\n list(): readonly AssemblyDef[]\n get(id: string): AssemblyDef | undefined\n /** Adds an assembly, or replaces the one with the same id. */\n register(def: AssemblyDef): void\n /** The wall as a `PartSpec`; throws for an id this set does not have. */\n part(assemblyId: string, options: AssemblyPartOptions): PartSpec\n}\n\nconst assembliesOver = (defs: AssemblyDef[]): Assemblies => {\n const get = (id: string): AssemblyDef | undefined => defs.find((a) => a.id === id)\n return {\n list: () => defs,\n get,\n register(def) {\n const at = defs.findIndex((a) => a.id === def.id)\n if (at >= 0) defs[at] = def\n else defs.push(def)\n },\n part: (assemblyId, options) => buildAssemblyPart(get(assemblyId), assemblyId, options),\n }\n}\n\n/** A set of assemblies of its own: the built-in ones (copied) plus `packs`, `patch` and `remove`. Nothing is shared with any other set on the page. */\nexport const createAssemblies = (options: AssembliesOptions = {}): Assemblies => {\n const entries = mergeById(SHIPPED.map((def) => structuredClone(def)), (options.packs ?? []).flat())\n applyPatches(entries, options.patch)\n removeIds(entries, options.remove)\n return assembliesOver([...entries.values()])\n}\n\nlet defaultSet: Assemblies | undefined\n\n/** The set behind `ASSEMBLIES`, `registerAssembly`, `getAssembly` and `assemblyPart`, created on first use. */\nexport const defaultAssemblies = (): Assemblies => (defaultSet ??= assembliesOver(ASSEMBLIES))\n\n/** @deprecated use `createAssemblies(...).register`. */\nexport const registerAssembly = (def: AssemblyDef): void => defaultAssemblies().register(def)\n\n/** @deprecated use `createAssemblies(...).get`. */\nexport const getAssembly = (id: string): AssemblyDef | undefined => defaultAssemblies().get(id)\n\nconst faceCount = (layer: SurfaceLayer): number => (layer.faces === 'both' ? 2 : 1)\n\n/** Physical depth of the wall in metres. */\nexport const assemblyDepth = (def: AssemblyDef): number => def.depth ?? def.core.thickness + (def.layers ?? []).reduce((sum, l) => sum + l.thickness * faceCount(l), 0)\n\n/**\n * The wall as a box `[width, height, depth]` (thin along local z) with the assembly's layers, units, rebar and breach. Mass is the core (times `fill`)\n * plus the coats; `thickness` is the core's, so each coat adds its own `penetration x thickness` to what a bullet must cross.\n */\nconst buildAssemblyPart = (def: AssemblyDef | undefined, assemblyId: string, options: AssemblyPartOptions): PartSpec => {\n if (!def) throw new Error(`unknown assembly \"${assemblyId}\"`)\n const densityOf = (id: MaterialId): number => {\n const m = options.materials?.get(id) ?? MATERIALS.find((x) => x.id === id)\n if (!m) throw new Error(`unknown material \"${id}\" in assembly \"${assemblyId}\"`)\n return m.density\n }\n const fill = def.fill ?? 1\n const area = options.width * options.height\n const coreMass = area * def.core.thickness * fill * densityOf(def.core.material)\n const layerMass = (def.layers ?? []).reduce((sum, l) => sum + area * l.thickness * faceCount(l) * densityOf(l.material), 0)\n return {\n id: options.id,\n material: def.core.material,\n shape: { kind: 'box', size: [options.width, options.height, assemblyDepth(def)] },\n position: options.position,\n ...(options.rotation ? { rotation: options.rotation } : {}),\n mass: coreMass + layerMass,\n thickness: def.core.thickness * fill,\n ...(def.layers ? { layers: def.layers.map((l) => ({ ...l })) } : {}),\n ...(def.units ? { units: { ...def.units, size: [...def.units.size] as Vec3 } } : {}),\n ...(def.reinforcement ? { reinforcement: { ...def.reinforcement } } : {}),\n ...(def.breach ? { breach: { ...def.breach } } : {}),\n ...(options.structure ? { structure: options.structure } : {}),\n ...options.extra,\n }\n}\n\n/** @deprecated use `createAssemblies(...).part`. */\nexport const assemblyPart = (assemblyId: string, options: AssemblyPartOptions): PartSpec => defaultAssemblies().part(assemblyId, options)\n","import type { DestructibleSpec, JointSpec, MaterialId, PartSpec, PileSpec, Reinforcement, SoilProfile } from './types'\n\nexport interface FrameOptions {\n /** Total length along x between the outer column centres, metres (default 8). */\n spanX?: number\n /** Total length along z (default 8). */\n spanZ?: number\n /** Columns along x (at least 2, default 3). */\n columnsX?: number\n /** Columns along z (at least 2, default 3). */\n columnsZ?: number\n /** Height of one floor from slab top to the underside of the next slab, metres (default 3). */\n height?: number\n /** Number of floors (default 1). */\n floors?: number\n /** Brick walls on every perimeter bay of every floor; the first bay of the ground floor on the -z side gets a door opening (default false). */\n walls?: boolean\n /** A thin roof slab resting on the top beams (default true); without it the top floor is open. */\n roof?: boolean\n columnSize?: number\n beamHeight?: number\n slabThickness?: number\n wallThickness?: number\n doorWidth?: number\n doorHeight?: number\n /** Material of foundations, columns, beams, slabs and roof (default `concrete`). */\n material?: MaterialId\n wallMaterial?: MaterialId\n /** Override the load capacity of every column, kg (see `PartState.load`). */\n columnCapacity?: number\n /**\n * Tension steel ratio of the beams and slabs (`structure.rebar.ratio`; default beams 1%, slabs and roof 0.5%, inside the ranges of NBR 6118);\n * `false` makes them plain concrete (they snap when they bend past cracking).\n */\n rebar?: { beam?: number; slab?: number } | false\n /** Side of the square pad under each column in metres (default 2.2 x `columnSize`), 0.3 m thick. */\n footing?: number\n /** One raft under the whole frame instead of a pad per column (`raft`, the footprint plus `footing` / 2 each side, 0.4 m thick). */\n raft?: boolean\n /** Piles under each pad (or under the raft): the pad becomes a pile cap. */\n piles?: PileSpec\n /**\n * Columns run from storey to storey: each one rests on the column below (through the slab, as a cast-in-place column does) instead of on the slab,\n * so the slab carries only its own floor. Default false (the column of each storey stands on the slab below, as before).\n */\n continuousColumns?: boolean\n /** Rebar cage of the columns (`PartSpec.reinforcement`; default none). A caged column carries `0.85 fck Ac + As fy` and its `rebar` joints are monolithic. */\n columnCage?: Reinforcement\n /** Thickness of the roof slab (default 0.75 x `slabThickness`; a flat roof that carries a screed and equipment is as thick as a floor). */\n roofThickness?: number\n /** The ground the frame stands on (`DestructibleSpec.soil`). */\n soil?: string | SoilProfile\n}\n\n/**\n * A parametric test structure: a grid of columns on foundations, beams between the column tops, one slab per floor (the last one a roof), and\n * optional brick walls with a door. Joints are explicit and directional: columns rest on foundations (or on the slab below) with `rebar`, beams on\n * columns, slabs on beams, the roof rests on the top beams, walls hang on their columns with `mortar`. Part ids: `foundation_i_j`, `column_f_i_j`,\n * `beam_x_f_i_j`, `beam_z_f_i_j`, `slab_f`, `roof`, `wall_*`, `door`. Ground is y = 0 (the top of the foundations).\n */\nexport const buildFrame = (o: FrameOptions = {}): DestructibleSpec => {\n const spanX = o.spanX ?? 8, spanZ = o.spanZ ?? 8\n const nx = Math.max(2, o.columnsX ?? 3), nz = Math.max(2, o.columnsZ ?? 3)\n const H = o.height ?? 3, floors = Math.max(1, o.floors ?? 1)\n const cs = o.columnSize ?? 0.3, bh = o.beamHeight ?? 0.3, bw = 0.2, T = o.slabThickness ?? 0.2, wt = o.wallThickness ?? 0.2\n const dw = o.doorWidth ?? 1, dh = o.doorHeight ?? 2.1\n const mat = o.material ?? 'concrete', wmat = o.wallMaterial ?? 'brick'\n const roof = o.roof ?? true\n const rebarOf = (kind: 'beam' | 'slab') => (o.rebar === false ? {} : { rebar: { ratio: o.rebar?.[kind] ?? (kind === 'beam' ? 0.01 : 0.005) } })\n const xs = Array.from({ length: nx }, (_, i) => -spanX / 2 + (i * spanX) / (nx - 1))\n const zs = Array.from({ length: nz }, (_, j) => -spanZ / 2 + (j * spanZ) / (nz - 1))\n const parts: PartSpec[] = []\n const joints: JointSpec[] = []\n const on = (a: string, b: string, kind: JointSpec['kind']) => joints.push({ id: `${a}~${b}`, a, b, kind, bears: 'a_on_b' })\n\n const pad = o.footing ?? cs * 2.2\n const pile = o.piles ? { pile: { ...o.piles } } : {}\n if (o.raft) {\n parts.push({\n id: 'raft', material: mat, shape: { kind: 'box', size: [spanX + pad, 0.4, spanZ + pad] }, position: [0, -0.2, 0],\n structure: { role: 'foundation', ...pile }, anchored: true,\n })\n } else {\n for (let i = 0; i < nx; i++) {\n for (let j = 0; j < nz; j++) {\n parts.push({\n id: `foundation_${i}_${j}`, material: mat, shape: { kind: 'box', size: [pad, 0.3, pad] }, position: [xs[i], -0.15, zs[j]],\n structure: { role: 'foundation', ...pile }, anchored: true,\n })\n }\n }\n }\n for (let f = 0; f < floors; f++) {\n const yb = f * (H + T)\n const top = yb + H\n const last = f === floors - 1\n const slabId = last && roof ? 'roof' : `slab_${f}`\n for (let i = 0; i < nx; i++) {\n for (let j = 0; j < nz; j++) {\n const id = `column_${f}_${i}_${j}`\n parts.push({\n id, material: mat, shape: { kind: 'box', size: [cs, H, cs] }, position: [xs[i], yb + H / 2, zs[j]],\n structure: o.columnCapacity === undefined ? { role: 'column' } : { role: 'column', capacity: o.columnCapacity },\n ...(o.columnCage ? { reinforcement: { ...o.columnCage } } : {}),\n })\n on(id, f === 0 ? (o.raft ? 'raft' : `foundation_${i}_${j}`) : o.continuousColumns ? `column_${f - 1}_${i}_${j}` : `slab_${f - 1}`, 'rebar')\n }\n }\n const beams: string[] = []\n const beam = (id: string, size: [number, number, number], pos: [number, number, number], c1: string, c2: string) => {\n parts.push({ id, material: mat, shape: { kind: 'box', size }, position: pos, structure: { role: 'beam', ...rebarOf('beam') } })\n on(id, c1, 'rebar')\n on(id, c2, 'rebar')\n beams.push(id)\n }\n for (let j = 0; j < nz; j++) {\n for (let i = 0; i < nx - 1; i++) {\n beam(`beam_x_${f}_${i}_${j}`, [xs[i + 1] - xs[i] - cs, bh, bw], [(xs[i] + xs[i + 1]) / 2, top - bh / 2, zs[j]], `column_${f}_${i}_${j}`, `column_${f}_${i + 1}_${j}`)\n }\n }\n for (let i = 0; i < nx; i++) {\n for (let j = 0; j < nz - 1; j++) {\n beam(`beam_z_${f}_${i}_${j}`, [bw, bh, zs[j + 1] - zs[j] - cs], [xs[i], top - bh / 2, (zs[j] + zs[j + 1]) / 2], `column_${f}_${i}_${j}`, `column_${f}_${i}_${j + 1}`)\n }\n }\n const thick = last && roof ? o.roofThickness ?? T * 0.75 : T\n parts.push({\n id: slabId, material: mat, shape: { kind: 'box', size: [spanX + cs + 0.2, thick, spanZ + cs + 0.2] }, position: [0, top + thick / 2, 0],\n structure: { role: last && roof ? 'roof' : 'slab', ...rebarOf('slab') },\n })\n for (const b of beams) on(slabId, b, last && roof ? 'resting' : 'rebar')\n\n if (o.walls) {\n const wh = H - bh\n const wy = yb + wh / 2\n const wall = (id: string, size: [number, number, number], pos: [number, number, number], supports: string[]) => {\n parts.push({ id, material: wmat, shape: { kind: 'box', size }, position: pos, structure: { role: 'wall' } })\n for (const s of supports) on(id, s, 'mortar')\n }\n for (const j of [0, nz - 1]) {\n for (let i = 0; i < nx - 1; i++) {\n const c1 = `column_${f}_${i}_${j}`, c2 = `column_${f}_${i + 1}_${j}`\n const avail = xs[i + 1] - xs[i] - cs\n if (f === 0 && j === 0 && i === 0 && avail > dw + 0.4) {\n const side = (avail - dw) / 2\n const lx = xs[i] + cs / 2 + side / 2, rx = xs[i + 1] - cs / 2 - side / 2\n wall(`wall_door_left`, [side, wh, wt], [lx, wy, zs[j]], [c1])\n wall(`wall_door_right`, [side, wh, wt], [rx, wy, zs[j]], [c2])\n const lh = wh - dh\n wall(`wall_door_lintel`, [dw, lh, wt], [xs[i] + cs / 2 + side + dw / 2, yb + dh + lh / 2, zs[j]], ['wall_door_left', 'wall_door_right'])\n parts.push({ id: 'door', material: 'wood_hard', shape: { kind: 'box', size: [dw - 0.04, dh, 0.05] }, position: [xs[i] + cs / 2 + side + dw / 2, yb + dh / 2, zs[j]], tags: ['door'] })\n joints.push({ id: 'door~wall_door_left', a: 'door', b: 'wall_door_left', kind: 'hinge', bears: false })\n } else wall(`wall_x_${f}_${i}_${j}`, [avail, wh, wt], [(xs[i] + xs[i + 1]) / 2, wy, zs[j]], [c1, c2])\n }\n }\n for (const i of [0, nx - 1]) {\n for (let j = 0; j < nz - 1; j++) {\n wall(`wall_z_${f}_${i}_${j}`, [wt, wh, zs[j + 1] - zs[j] - cs], [xs[i], wy, (zs[j] + zs[j + 1]) / 2], [`column_${f}_${i}_${j}`, `column_${f}_${i}_${j + 1}`])\n }\n }\n }\n }\n return { name: 'frame', parts, joints, tags: ['structure'], ...(o.soil !== undefined ? { soil: o.soil } : {}) }\n}\n","import { createDestruction } from './world'\nimport { GRAVITY, bendGeometry, isFlexural, isReinforced, resolveFlexure, sectionMoments, sectionWidth, steelMoment, tensionSteel } from './flexure'\nimport { MATERIALS } from './materials'\nimport { shapeDims } from './math'\nimport { resolveWind, tensionCapacity } from './wind'\nimport type { DestructibleSpec, MaterialDef, SizeStructureOptions, StructureRole } from './types'\n\n/** Highest tension steel ratio a designer puts in a beam or slab (NBR 6118 17.3.5.2.4: 4% of the section). */\nconst MAX_REBAR_RATIO = 0.04\n\n/** The spec as the sizing worlds see it: the ground does not change the loads, so the soil is left out. */\nconst onRock = (spec: DestructibleSpec): DestructibleSpec => {\n if (spec.soil === undefined) return spec\n const { soil: _soil, ...rest } = spec\n return rest\n}\n\n/** The spec without one part (and its joints; inferred joints are inferred again without it). */\nconst without = (spec: DestructibleSpec, id: string): DestructibleSpec => {\n const reduced: DestructibleSpec = { ...spec, parts: spec.parts.filter((p) => p.id !== id), joints: (spec.joints ?? []).filter((j) => j.a !== id && j.b !== id) }\n if (!spec.joints) delete reduced.joints\n return reduced\n}\n\n/**\n * Sizes the tension steel of the reinforced beams, slabs, roofs and stairs of a structure (a `reinforcement` cage or a `structure.rebar`), the way\n * `sizeStructure` sizes the capacities: each one gets the `structure.rebar.ratio` that keeps its bending at rest (`PartState.flexure`) at `safety`\n * (`safetyByRole`) and, with `redundancy`, at most `redundancy` after the loss of any part of `redundancyRoles`. Steel is only added (up to 4% of the\n * section) and plain concrete stays plain: a beam the spec makes without steel is a beam without steel. Returns a copy.\n */\nexport const sizeRebar = (spec: DestructibleSpec, options: SizeStructureOptions = {}): DestructibleSpec => {\n const flexure = resolveFlexure(options.flexure)\n const materials = new Map<string, MaterialDef>(MATERIALS.map((m) => [m.id, m]))\n for (const m of options.materials ?? []) materials.set(m.id, m)\n const out = structuredClone(spec)\n const targets = out.parts.filter((p) => {\n const m = materials.get(p.material)\n return p.shape.kind === 'box' && !!m && isReinforced(p) && isFlexural(p, m, flexure)\n })\n if (targets.length === 0) return out\n const safety = options.safety ?? 0.65\n const safetyOf = (role: StructureRole): number => options.safetyByRole?.[role] ?? safety\n const bending = (s: DestructibleSpec): Map<string, number> => {\n const w = createDestruction({ ...(options.materials ? { materials: options.materials } : {}), structure: { flexure: options.flexure } })\n const id = w.add(onRock(s))\n return new Map(w.state(id)!.parts.map((p) => [p.id, p.flexure ?? 0]))\n }\n const base = bending(out)\n const factor = new Map(targets.map((p) => [p.id, (base.get(p.id) ?? 0) / safetyOf(p.structure!.role)]))\n if (options.redundancy !== undefined) {\n const roles: readonly StructureRole[] = options.redundancyRoles ?? ['column']\n for (const lost of out.parts) {\n if (!lost.structure || !roles.includes(lost.structure.role)) continue\n const l = bending(without(out, lost.id))\n for (const p of targets) if (p.id !== lost.id) factor.set(p.id, Math.max(factor.get(p.id)!, (l.get(p.id) ?? 0) / options.redundancy))\n }\n }\n for (const p of targets) {\n const f = factor.get(p.id)!\n const g = bendGeometry(p)\n if (f <= 1 || g.gravity < 0) continue\n const section = { b: sectionWidth(g, g.gravity), h: g.dims[g.gravity] }\n const steel = tensionSteel(p, g.dims, section, flexure)\n const m = materials.get(p.material)!\n const need = f * sectionMoments(m, section, steel, flexure).ultimate\n const momentOf = (area: number) => steelMoment(area, steel.yieldMPa, steel.d, section.b, m.strength!.compressiveMPa, flexure)\n // the smallest steel area whose moment reaches the need (the moment grows with the area), found by bisection, at most the 4% cap\n const cap = MAX_REBAR_RATIO * section.b * steel.d\n if (steel.area >= cap) continue\n let lo = steel.area, hi = cap\n if (momentOf(hi) > need) {\n for (let k = 0; k < 60; k++) {\n const mid = (lo + hi) / 2\n if (momentOf(mid) < need) lo = mid\n else hi = mid\n }\n }\n const ratio = hi / (section.b * steel.d)\n p.structure = { ...p.structure!, rebar: { ...p.structure!.rebar, ratio } }\n }\n return out\n}\n\n/**\n * Sizes the load capacity of a structure the way an engineer would, from the loads the world itself computes. The intact spec goes through the\n * same load solver `createDestruction` uses, and each structural part (`structure.role` other than `none`) gets `structure.capacity = load / safety`,\n * so its at-rest stress is exactly `safety` (`safetyByRole` overrides it per role). With `redundancy` set, every part whose role is in\n * `redundancyRoles` (default `column`) is also removed in turn and the capacity of the parts that would carry more is raised so they stay at or below\n * `redundancy`. Parts without `structure`, with role `none`, or with no support path to an\n * anchored part are left as they are. The spec is not modified; a copy is returned.\n */\nexport const sizeStructure = (spec: DestructibleSpec, options: SizeStructureOptions = {}): DestructibleSpec => {\n const safety = options.safety ?? 0.65\n const redundancy = options.redundancy\n const redundancyRoles: readonly StructureRole[] = options.redundancyRoles ?? ['column']\n const safetyOf = (role: StructureRole): number => options.safetyByRole?.[role] ?? safety\n const loads = (s: DestructibleSpec, wind?: SizeStructureOptions['wind']): Map<string, { load: number; stress: number; wind: number }> => {\n const w = createDestruction({ ...(options.materials ? { materials: options.materials } : {}), ...(wind ? { wind } : {}) })\n const id = w.add(onRock(s))\n return new Map(w.state(id)!.parts.map((p) => [p.id, { load: p.load ?? 0, stress: p.stress ?? 0, wind: p.wind ?? 0 }]))\n }\n const out = structuredClone(spec)\n const base = loads(out, options.wind)\n const gamma = options.wind ? resolveWind(options.wind).loadFactor : 0\n const need = new Map<string, number>()\n for (const p of out.parts) {\n if (!p.structure || p.structure.role === 'none') continue\n const b = base.get(p.id)\n if (!b || b.stress <= 0) continue\n // the wind adds its factored axial force to the dead load (compression side); on the tension side the bars are sized below\n need.set(p.id, (b.load + (b.wind > 0 ? (gamma * b.wind) / GRAVITY : 0)) / safetyOf(p.structure.role))\n }\n if (redundancy !== undefined) {\n for (const col of out.parts) {\n if (!col.structure || !redundancyRoles.includes(col.structure.role)) continue\n const reduced: DestructibleSpec = {\n ...out,\n parts: out.parts.filter((p) => p.id !== col.id),\n joints: (out.joints ?? []).filter((j) => j.a !== col.id && j.b !== col.id),\n }\n // joints are inferred when the spec has none; removing a part then removes its joints with it\n if (!out.joints) delete reduced.joints\n const l = loads(reduced)\n for (const [id, n] of need) {\n const r = l.get(id)\n if (r && r.stress > 0) need.set(id, Math.max(n, r.load / redundancy))\n }\n }\n }\n for (const p of out.parts) {\n const n = need.get(p.id)\n if (n !== undefined) p.structure = { ...p.structure!, capacity: n }\n }\n if (options.wind) {\n // a wall or column that the wind pulls past its dead load needs bars for the pull: thicker bars, to the 40 mm of NBR 7480\n const yieldMPa = resolveFlexure(options.flexure).rebarYieldMPa\n for (const p of out.parts) {\n const b = base.get(p.id)\n if (!b || b.wind >= 0 || !p.reinforcement || p.shape.kind !== 'box') continue\n const pull = (-(b.load + (gamma * b.wind) / GRAVITY) * GRAVITY)\n if (pull <= 0) continue\n const dims = shapeDims(p.shape)\n const have = tensionCapacity(dims, { reinforcement: p.reinforcement, yieldMPa })\n const want = pull / safetyOf(p.structure?.role ?? 'wall')\n if (have > 0 && want > have) p.reinforcement = { ...p.reinforcement, diameter: Math.min(0.04, p.reinforcement.diameter * Math.sqrt(want / have)) }\n }\n }\n return sizeRebar(out, options)\n}\n","import type { DamageType, DestructionEventType, FractureStyle, JointKind, PartStatus, StructureRole, ToolKind } from './types'\n\n/** Locales shipped with the package. Unknown locales fall back to `en`. */\nexport type DestructionLocale = 'en' | 'pt-BR'\n\nexport interface DestructionStrings {\n /** Display name per material id (see `MATERIALS`). Unknown ids are not listed. */\n materialNames: Record<string, string>\n partStatus: Record<PartStatus, string>\n jointKinds: Record<JointKind, string>\n toolKinds: Record<ToolKind, string>\n damageTypes: Record<DamageType, string>\n /** Short label per event type, for logs and kill-feed style text. */\n eventLabels: Record<DestructionEventType, string>\n fractureStyles: Record<FractureStyle, string>\n structureRoles: Record<StructureRole, string>\n}\n\nexport const locales: Record<DestructionLocale, DestructionStrings> = {\n en: {\n materialNames: {\n steel: 'steel', cast_iron: 'cast iron', aluminium: 'aluminium', copper: 'copper', wood_soft: 'softwood', wood_hard: 'hardwood', plywood: 'plywood',\n mdf: 'MDF', glass: 'glass', tempered_glass: 'tempered glass', ceramic: 'ceramic', concrete: 'concrete', brick: 'brick', plaster: 'plaster',\n stone: 'stone', plastic: 'plastic', rubber: 'rubber', fabric: 'fabric', foam: 'foam', leather: 'leather', paper: 'paper', foliage: 'foliage',\n green_wood: 'green wood', cactus: 'cactus', flesh_fruit: 'fruit', wax: 'wax', soil: 'soil', asphalt: 'asphalt', sand: 'sand', gravel: 'gravel', turf: 'turf', mortar: 'mortar', mud: 'mud', clay: 'dry clay', snow: 'snow', cobble: 'cobblestone', paver: 'concrete paver',\n },\n partStatus: { intact: 'intact', damaged: 'damaged', collapsed: 'collapsed', broken: 'broken', melted: 'melted', ashes: 'ashes' },\n jointKinds: {\n screw: 'screw', bolt: 'nut and bolt', nail: 'nail', weld: 'weld', glue: 'glue', hinge: 'hinge', clip: 'clip', tie: 'tie', mortar: 'mortar',\n fused: 'fused', stem: 'stem', rebar: 'rebar', resting: 'resting',\n },\n toolKinds: {\n hand: 'hand', screwdriver: 'screwdriver', wrench: 'wrench', pry_bar: 'pry bar', saw: 'saw', cutting_torch: 'cutting torch', knife: 'knife', hammer: 'hammer',\n },\n damageTypes: { ballistic: 'ballistic', blunt: 'blunt', slash: 'slash', explosive: 'explosive', fire: 'fire', heat: 'heat' },\n eventLabels: {\n damage: 'damage', dent: 'dent', hole: 'hole', crack: 'crack', ricochet: 'ricochet', debris: 'debris', fracture: 'broke', detach: 'came loose',\n disassemble_progress: 'taking apart', ignite: 'caught fire', extinguish: 'put out', burnout: 'burned to ash', melt: 'melting', drip: 'dripping',\n leak: 'leak', explode: 'exploded', primed: 'about to explode', stress: 'overload', collapse: 'collapsed', settle: 'ground gave way', sway: 'sway', spall: 'plaster came off', stage: 'damage stage', chip: 'brick knocked out', expose: 'rebar bare', body: 'body', blast: 'blast', fragment_hit: 'fragment hit', destroyed: 'destroyed',\n },\n fractureStyles: { shatter: 'shatter', crumble: 'crumble', splinter: 'splinter', tear: 'tear', snap: 'snap', none: 'none' },\n structureRoles: { foundation: 'foundation', column: 'column', beam: 'beam', slab: 'slab', wall: 'wall', partition: 'partition', roof: 'roof', stair: 'stairs', none: 'none' },\n },\n 'pt-BR': {\n materialNames: {\n steel: 'aço', cast_iron: 'ferro fundido', aluminium: 'alumínio', copper: 'cobre', wood_soft: 'madeira macia', wood_hard: 'madeira de lei',\n plywood: 'compensado', mdf: 'MDF', glass: 'vidro', tempered_glass: 'vidro temperado', ceramic: 'cerâmica', concrete: 'concreto', brick: 'tijolo',\n plaster: 'gesso', stone: 'pedra', plastic: 'plástico', rubber: 'borracha', fabric: 'tecido', foam: 'espuma', leather: 'couro', paper: 'papel',\n foliage: 'folhagem', green_wood: 'madeira verde', cactus: 'cacto', flesh_fruit: 'fruta', wax: 'cera', soil: 'terra', asphalt: 'asfalto', sand: 'areia', gravel: 'brita', turf: 'grama', mortar: 'argamassa', mud: 'lama', clay: 'barro seco', snow: 'neve', cobble: 'paralelepípedo', paver: 'bloquete',\n },\n partStatus: { intact: 'intacto', damaged: 'danificado', collapsed: 'desabado', broken: 'quebrado', melted: 'derretido', ashes: 'cinzas' },\n jointKinds: {\n screw: 'parafuso', bolt: 'porca e parafuso', nail: 'prego', weld: 'solda', glue: 'cola', hinge: 'dobradiça', clip: 'encaixe', tie: 'amarração',\n mortar: 'argamassa', fused: 'fundido', stem: 'caule', rebar: 'vergalhão', resting: 'apoiado',\n },\n toolKinds: {\n hand: 'mão', screwdriver: 'chave de fenda', wrench: 'chave inglesa', pry_bar: 'pé de cabra', saw: 'serra', cutting_torch: 'maçarico', knife: 'faca', hammer: 'martelo',\n },\n damageTypes: { ballistic: 'tiro', blunt: 'impacto', slash: 'corte', explosive: 'explosão', fire: 'fogo', heat: 'calor' },\n eventLabels: {\n damage: 'dano', dent: 'amassado', hole: 'furo', crack: 'trinca', ricochet: 'ricochete', debris: 'estilhaços', fracture: 'quebrou', detach: 'soltou',\n disassemble_progress: 'desmontando', ignite: 'pegou fogo', extinguish: 'apagou', burnout: 'virou cinza', melt: 'derretendo', drip: 'pingando',\n leak: 'vazamento', explode: 'explodiu', primed: 'prestes a explodir', stress: 'sobrecarga', collapse: 'desabou', settle: 'recalque do solo', sway: 'balanço', spall: 'reboco soltou', stage: 'estágio de dano', chip: 'tijolo arrancado', expose: 'vergalhão à mostra', body: 'corpo', blast: 'explosão', fragment_hit: 'estilhaço atingiu', destroyed: 'destruído',\n },\n fractureStyles: { shatter: 'estilhaçar', crumble: 'esfarelar', splinter: 'lascar', tear: 'rasgar', snap: 'partir', none: 'nenhuma' },\n structureRoles: { foundation: 'fundação', column: 'pilar', beam: 'viga', slab: 'laje', wall: 'parede', partition: 'divisória', roof: 'telhado', stair: 'escada', none: 'nenhum' },\n },\n}\n\nexport const resolveStrings = (locale: string | undefined): DestructionStrings => locales[(locale as DestructionLocale) ?? 'en'] ?? locales.en\n","import { checkDestructible as check } from '@adatechnology/game-contracts'\nimport type { CheckOptions as ContractCheckOptions, CostOptions, DestructibleImpl } from '@adatechnology/game-contracts'\nimport { MATERIALS } from './materials'\n\n// The contract itself lives in @adatechnology/game-contracts (a module depends only on that); re-exported here so that no import breaks.\nexport { IMPACT_CONTRACT, checkHit } from '@adatechnology/game-contracts'\nexport type { DestructibleImpl, ImpactContract } from '@adatechnology/game-contracts'\n\nexport interface CheckOptions {\n /** Ids of custom materials the impl uses besides the built-in `MATERIALS`. */\n materials?: string[]\n /** Opt-in cost measurement of `state()` and `describe()` (D8). */\n cost?: boolean | CostOptions\n}\n\n/**\n * `checkDestructible` of `@adatechnology/game-contracts`, with the built-in `MATERIALS` (plus `options.materials`) as the known material ids.\n * It hits the impl (and calls `reset()` afterwards when there is one).\n */\nexport const checkDestructible = (impl: DestructibleImpl, options: CheckOptions = {}): { ok: boolean; problems: string[] } => {\n const contractOptions: ContractCheckOptions = { materials: [...MATERIALS.map((m) => m.id), ...(options.materials ?? [])], ...(options.cost === undefined ? {} : { cost: options.cost }) }\n return check(impl, contractOptions)\n}\n"],"mappings":"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","names":["checkDestructible","n0","n1","a","c","t0","t1","dy","inside","sign","a","b","n","th","u","v","bar","s","definedOf","z","clamp","pos","world","nx","nz","lean","taken","crater","spread","bar","cells","dmg","options","checkDestructible"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/chain.ts","../src/math.ts","../src/fracture.ts","../src/breach.ts","../src/layers.ts","../src/rebar.ts","../src/flexure.ts","../src/data/soils.json","../src/soil.ts","../src/data/wind-terrain.json","../src/wind.ts","../src/data/materials.json","../src/data/material-hints.json","../src/materials.ts","../../game-contracts/src/blast-shove.ts","../../game-contracts/src/blast-impulse.ts","../../game-contracts/src/blast-knock.ts","../../game-contracts/src/impact-cost.ts","../../game-contracts/src/impact.ts","../../game-contracts/src/body.ts","../../game-contracts/src/spec.ts","../../game-contracts/src/weapons.ts","../../game-contracts/src/ignition.ts","../../game-contracts/src/seal.ts","../../game-contracts/src/hands.ts","../../game-contracts/src/twist.ts","../../game-contracts/src/animation.ts","../../game-contracts/src/tool-animation.ts","../../game-contracts/src/frame.ts","../../game-contracts/src/warn.ts","../../game-contracts/src/registry.ts","../../game-contracts/src/bench.ts","../../game-contracts/src/environment.ts","../../game-contracts/src/categories.ts","../../game-contracts/src/origin.ts","../../game-contracts/src/footprint.ts","../../game-contracts/src/foley.ts","../../game-contracts/src/index.ts","../src/world.ts","../src/data/assemblies.json","../src/assemblies.ts","../src/frame.ts","../src/size.ts","../src/locale.ts","../src/contracts.ts"],"sourcesContent":["export type * from './types'\nexport { createDestruction, SHELTER_DEFAULTS, FRAGMENT_HIT_DEFAULTS, CONFINEMENT_DEFAULTS } from './world'\nexport { explosivePart, FIRE_PRIME_C } from './chain'\nexport type { ChainTrigger, ExplosivePartOptions, WorldExplosive } from './chain'\nexport { MATERIALS, JOINT_DEFAULTS, JOINT_BY_MATERIALS, inferJoints, guessMaterial, partVolume, partMass, partThickness, partCapacity, fragility } from './materials'\nexport { ASSEMBLIES, createAssemblies, defaultAssemblies, registerAssembly, getAssembly, assemblyPart, assemblyDepth } from './assemblies'\nexport type { Assemblies, AssembliesOptions, AssemblyDef, AssemblyPartOptions } from './assemblies'\nexport { buildFrame } from './frame'\nexport type { FrameOptions } from './frame'\nexport { sizeStructure, sizeRebar } from './size'\nexport {\n GRAVITY, FLEXURE_DEFAULTS, MASONRY_DEFAULTS, bearingWallThickness, bendGeometry, blastImpulse, crackingMoment, elasticEnergy, impulseEnergy, momentOfEnergy,\n sectionMoments, slendernessFactor, spanMoment, spanOf, steelMoment, tensionSteel,\n} from './flexure'\nexport type { BearingWallOptions, BendGeometry, BendSection, SectionMoments, TensionSteel } from './flexure'\nexport {\n SOILS, SOIL_DEFAULTS, footingArea, footingSoil, layersBetween, pileCapacity, pileLength, pileStiffness, profileOf, soilAt, solveFoundation, stiffnessCentre,\n subgradeModulus,\n} from './soil'\nexport type { FoundationSolve, SoilSpring } from './soil'\nexport { vec, quat, quatFromEuler, rotateVec, toLocal, toWorld } from './math'\nexport { resolveStrings, locales } from './locale'\nexport type { DestructionStrings, DestructionLocale } from './locale'\nexport { checkDestructible, checkHit, IMPACT_CONTRACT } from './contracts'\nexport type { DestructibleImpl, ImpactContract, CheckOptions } from './contracts'\nexport {\n WIND_DEFAULTS, WIND_TERRAIN, analyzeWind, damperAmplification, damperTuning, exposureOf, gustAt, heightFactor, makeGust, meanHeightFactor, momentNodes, resolveWind, shapeAt, shearNodes,\n solveWallFrame, stepSway, tBeamInertia, tensionCapacity, turbulenceIntensity, windClass, windPressure,\n} from './wind'\nexport type { Gust, ResolvedWind, SwayState, SwaySystem, WallFrameSolution, WindAnalysis, WindCase, WindPartInput } from './wind'\n","import type { ChainDelay, ExplosionChain, PartSpec } from './types'\n\n/** What can set an explosive part off from outside, in the order a hit can carry it. */\nexport type ChainTrigger = 'shot' | 'fire' | 'explosion'\n\n/** Temperature in °C that primes a part with `chain.fire` when its `explodes.atC` is not set. */\nexport const FIRE_PRIME_C = 300\n\n/** Seconds from a trigger to the blast: a number is fixed, `[min, max]` is drawn from the world seed (one draw). */\nexport const drawChainDelay = (delay: ChainDelay, random: () => number): number => {\n if (typeof delay === 'number') return delay\n const [min, max] = delay\n return min + random() * (max - min)\n}\n\n/** The delay `spec` gives for `trigger`, or undefined when the part does not answer to it. */\nexport const chainDelayOf = (spec: PartSpec, trigger: ChainTrigger): ChainDelay | undefined => spec.explodes?.chain?.[trigger]\n\n/** Fraction of the hit points a shot must have taken off before it primes the part. */\nexport const shotDamageFractionOf = (spec: PartSpec): number => spec.explodes?.chain?.shotDamageFraction ?? 0\n\n/** The numbers of an explosive that sits in the world, as `game-weapons` gives them (`ExplosiveDef` fits). */\nexport interface WorldExplosive {\n readonly energy: number\n /** Metres within which the blast reaches other parts (and primes theirs). */\n readonly injuryRadius: number\n readonly chain?: ExplosionChain\n}\n\nexport interface ExplosivePartOptions {\n /** Temperature in °C at which fire primes (or sets off) the part; default `FIRE_PRIME_C` when the explosive answers to fire. */\n readonly atC?: number\n}\n\n/**\n * A part that explodes with the energy and reach of `explosive` and answers to what `explosive.chain` says: a bullet, fire or a blast\n * nearby primes it and it goes off after the delay. `part` is everything else about the part (shape, material, position, fluid inside).\n */\nexport const explosivePart = (explosive: WorldExplosive, part: Omit<PartSpec, 'explodes'>, options: ExplosivePartOptions = {}): PartSpec => ({\n ...part,\n explodes: {\n energy: explosive.energy,\n radius: explosive.injuryRadius,\n ...(options.atC !== undefined ? { atC: options.atC } : {}),\n ...(explosive.chain ? { chain: { ...explosive.chain } } : {}),\n },\n})\n","import type { PartShape, Quat, Vec3 } from './types'\n\nconst EPS = 1e-9\n\n/** Small vector helpers (arrays of three numbers). Pure functions; they allocate a new array. */\nexport const vec = {\n add: (a: Vec3, b: Vec3): Vec3 => [a[0] + b[0], a[1] + b[1], a[2] + b[2]],\n sub: (a: Vec3, b: Vec3): Vec3 => [a[0] - b[0], a[1] - b[1], a[2] - b[2]],\n scale: (a: Vec3, s: number): Vec3 => [a[0] * s, a[1] * s, a[2] * s],\n dot: (a: Vec3, b: Vec3): number => a[0] * b[0] + a[1] * b[1] + a[2] * b[2],\n cross: (a: Vec3, b: Vec3): Vec3 => [a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0]],\n length: (a: Vec3): number => Math.sqrt(a[0] * a[0] + a[1] * a[1] + a[2] * a[2]),\n distance: (a: Vec3, b: Vec3): number => Math.hypot(a[0] - b[0], a[1] - b[1], a[2] - b[2]),\n normalize: (a: Vec3, fallback: Vec3 = [0, 1, 0]): Vec3 => {\n const l = Math.sqrt(a[0] * a[0] + a[1] * a[1] + a[2] * a[2])\n return l < EPS ? [fallback[0], fallback[1], fallback[2]] : [a[0] / l, a[1] / l, a[2] / l]\n },\n lerp: (a: Vec3, b: Vec3, t: number): Vec3 => [a[0] + (b[0] - a[0]) * t, a[1] + (b[1] - a[1]) * t, a[2] + (b[2] - a[2]) * t],\n /** `a + b * s` */\n madd: (a: Vec3, b: Vec3, s: number): Vec3 => [a[0] + b[0] * s, a[1] + b[1] * s, a[2] + b[2] * s],\n}\n\nconst IDENTITY: Quat = [0, 0, 0, 1]\n\n/** Quaternion helpers (`[x, y, z, w]`). */\nexport const quat = {\n identity: (): Quat => [IDENTITY[0], IDENTITY[1], IDENTITY[2], IDENTITY[3]],\n /** Hamilton product `a * b` (apply `b` first, then `a`). */\n mul: (a: Quat, b: Quat): Quat => [\n a[3] * b[0] + a[0] * b[3] + a[1] * b[2] - a[2] * b[1],\n a[3] * b[1] - a[0] * b[2] + a[1] * b[3] + a[2] * b[0],\n a[3] * b[2] + a[0] * b[1] - a[1] * b[0] + a[2] * b[3],\n a[3] * b[3] - a[0] * b[0] - a[1] * b[1] - a[2] * b[2],\n ],\n conjugate: (q: Quat): Quat => [-q[0], -q[1], -q[2], q[3]],\n normalize: (q: Quat): Quat => {\n const l = Math.hypot(q[0], q[1], q[2], q[3])\n return l < EPS ? [0, 0, 0, 1] : [q[0] / l, q[1] / l, q[2] / l, q[3] / l]\n },\n /** Rotation of `angle` radians around a unit `axis`. */\n fromAxisAngle: (axis: Vec3, angle: number): Quat => {\n const s = Math.sin(angle / 2)\n return [axis[0] * s, axis[1] * s, axis[2] * s, Math.cos(angle / 2)]\n },\n /** Rotation matrix, row-major 3x3. */\n toMatrix: (q: Quat): number[] => {\n const [x, y, z, w] = q\n const xx = x * x, yy = y * y, zz = z * z, xy = x * y, xz = x * z, yz = y * z, wx = w * x, wy = w * y, wz = w * z\n return [1 - 2 * (yy + zz), 2 * (xy - wz), 2 * (xz + wy), 2 * (xy + wz), 1 - 2 * (xx + zz), 2 * (yz - wx), 2 * (xz - wy), 2 * (yz + wx), 1 - 2 * (xx + yy)]\n },\n /** Quaternion from three orthonormal columns (the images of the x, y and z axes). */\n fromColumns: (cx: Vec3, cy: Vec3, cz: Vec3): Quat => {\n const m00 = cx[0], m10 = cx[1], m20 = cx[2]\n const m01 = cy[0], m11 = cy[1], m21 = cy[2]\n const m02 = cz[0], m12 = cz[1], m22 = cz[2]\n const tr = m00 + m11 + m22\n let q: Quat\n if (tr > 0) {\n const s = Math.sqrt(tr + 1) * 2\n q = [(m21 - m12) / s, (m02 - m20) / s, (m10 - m01) / s, 0.25 * s]\n } else if (m00 > m11 && m00 > m22) {\n const s = Math.sqrt(1 + m00 - m11 - m22) * 2\n q = [0.25 * s, (m01 + m10) / s, (m02 + m20) / s, (m21 - m12) / s]\n } else if (m11 > m22) {\n const s = Math.sqrt(1 + m11 - m00 - m22) * 2\n q = [(m01 + m10) / s, 0.25 * s, (m12 + m21) / s, (m02 - m20) / s]\n } else {\n const s = Math.sqrt(1 + m22 - m00 - m11) * 2\n q = [(m02 + m20) / s, (m12 + m21) / s, 0.25 * s, (m10 - m01) / s]\n }\n return quat.normalize(q)\n },\n}\n\n/** Quaternion from Euler angles in radians, order XYZ (the three.js default). */\nexport const quatFromEuler = (x: number, y: number, z: number): Quat => {\n const c1 = Math.cos(x / 2), c2 = Math.cos(y / 2), c3 = Math.cos(z / 2)\n const s1 = Math.sin(x / 2), s2 = Math.sin(y / 2), s3 = Math.sin(z / 2)\n return [s1 * c2 * c3 + c1 * s2 * s3, c1 * s2 * c3 - s1 * c2 * s3, c1 * c2 * s3 + s1 * s2 * c3, c1 * c2 * c3 - s1 * s2 * s3]\n}\n\n/** Rotate a vector by a quaternion. */\nexport const rotateVec = (q: Quat, v: Vec3): Vec3 => {\n const qx = q[0], qy = q[1], qz = q[2], qw = q[3]\n const tx = 2 * (qy * v[2] - qz * v[1])\n const ty = 2 * (qz * v[0] - qx * v[2])\n const tz = 2 * (qx * v[1] - qy * v[0])\n return [v[0] + qw * tx + (qy * tz - qz * ty), v[1] + qw * ty + (qz * tx - qx * tz), v[2] + qw * tz + (qx * ty - qy * tx)]\n}\n\n/** World point to the local space of a transform (`position`, `rotation`). */\nexport const toLocal = (position: Vec3, rotation: Quat, p: Vec3): Vec3 =>\n rotateVec([-rotation[0], -rotation[1], -rotation[2], rotation[3]], [p[0] - position[0], p[1] - position[1], p[2] - position[2]])\n\n/** Local point of a transform (`position`, `rotation`) to world space. */\nexport const toWorld = (position: Vec3, rotation: Quat, p: Vec3): Vec3 => {\n const r = rotateVec(rotation, p)\n return [r[0] + position[0], r[1] + position[1], r[2] + position[2]]\n}\n\n// ---------------------------------------------------------------------------------------------------------------------------------------------\n// Shapes (part space: centred on the origin, cylinders along +Y)\n// ---------------------------------------------------------------------------------------------------------------------------------------------\n\n/** Dimensions of the bounding box of a shape, in the shape's own axes. */\nexport const shapeDims = (s: PartShape): Vec3 => {\n if (s.kind === 'box') return [s.size[0], s.size[1], s.size[2]]\n if (s.kind === 'cylinder') return [s.radius * 2, s.height, s.radius * 2]\n return [s.radius * 2, s.radius * 2, s.radius * 2]\n}\n\n/** Radius of the sphere that encloses the shape. */\nexport const shapeBound = (s: PartShape): number => {\n if (s.kind === 'box') return 0.5 * Math.hypot(s.size[0], s.size[1], s.size[2])\n if (s.kind === 'cylinder') return Math.hypot(s.radius, s.height / 2)\n return s.radius\n}\n\nexport const shapeArea = (s: PartShape): number => {\n if (s.kind === 'box') return 2 * (s.size[0] * s.size[1] + s.size[1] * s.size[2] + s.size[0] * s.size[2])\n if (s.kind === 'cylinder') return 2 * Math.PI * s.radius * s.height + 2 * Math.PI * s.radius * s.radius\n return 4 * Math.PI * s.radius * s.radius\n}\n\nexport interface ShapeRay {\n /** Entry distance along the ray (negative when the origin is inside). */\n t0: number\n /** Normal at the entry, outward. */\n n0: Vec3\n /** Exit distance. */\n t1: number\n /** Normal at the exit, outward. */\n n1: Vec3\n}\n\n/** Exact ray intersection with a shape in part space. `d` need not be normalised but must be non-zero. */\nexport const rayShape = (s: PartShape, o: Vec3, d: Vec3): ShapeRay | null => {\n if (s.kind === 'box') {\n let tmin = -Infinity, tmax = Infinity\n let a0 = 0, a1 = 0, s0 = 1, s1 = 1\n for (let i = 0; i < 3; i++) {\n const h = s.size[i] / 2\n if (Math.abs(d[i]) < EPS) {\n if (Math.abs(o[i]) > h) return null\n continue\n }\n let ta = (-h - o[i]) / d[i]\n let tb = (h - o[i]) / d[i]\n let sa = -1, sb = 1\n if (ta > tb) {\n const t = ta\n ta = tb\n tb = t\n sa = 1\n sb = -1\n }\n if (ta > tmin) {\n tmin = ta\n a0 = i\n s0 = sa\n }\n if (tb < tmax) {\n tmax = tb\n a1 = i\n s1 = sb\n }\n if (tmin > tmax) return null\n }\n if (tmax < 0 || !Number.isFinite(tmin) || !Number.isFinite(tmax)) return null\n const n0: Vec3 = [0, 0, 0]\n const n1: Vec3 = [0, 0, 0]\n n0[a0] = s0\n n1[a1] = s1\n return { t0: tmin, n0, t1: tmax, n1 }\n }\n if (s.kind === 'sphere') {\n const b = vec.dot(o, d)\n const a = vec.dot(d, d)\n const c = vec.dot(o, o) - s.radius * s.radius\n const disc = b * b - a * c\n if (disc < 0) return null\n const sq = Math.sqrt(disc)\n const t0 = (-b - sq) / a\n const t1 = (-b + sq) / a\n if (t1 < 0) return null\n const p0 = vec.madd(o, d, t0)\n const p1 = vec.madd(o, d, t1)\n return { t0, n0: vec.normalize(p0), t1, n1: vec.normalize(p1) }\n }\n // cylinder along Y: intersection of the infinite cylinder interval and the y slab\n const r = s.radius\n const hh = s.height / 2\n const a = d[0] * d[0] + d[2] * d[2]\n const c = o[0] * o[0] + o[2] * o[2] - r * r\n let tA = -Infinity, tB = Infinity\n if (a > EPS) {\n const b = o[0] * d[0] + o[2] * d[2]\n const disc = b * b - a * c\n if (disc < 0) return null\n const sq = Math.sqrt(disc)\n tA = (-b - sq) / a\n tB = (-b + sq) / a\n } else if (c > 0) return null\n let yA = -Infinity, yB = Infinity\n if (Math.abs(d[1]) > EPS) {\n yA = (-hh - o[1]) / d[1]\n yB = (hh - o[1]) / d[1]\n if (yA > yB) {\n const t = yA\n yA = yB\n yB = t\n }\n } else if (Math.abs(o[1]) > hh) return null\n const t0 = Math.max(tA, yA)\n const t1 = Math.min(tB, yB)\n if (t0 > t1 || t1 < 0 || !Number.isFinite(t0) || !Number.isFinite(t1)) return null\n const normalAt = (t: number, fromSide: boolean, sign: number): Vec3 => {\n if (fromSide) {\n const p = vec.madd(o, d, t)\n return vec.normalize([p[0], 0, p[2]], [1, 0, 0])\n }\n return [0, sign, 0]\n }\n const n0 = normalAt(t0, tA >= yA, d[1] > 0 ? -1 : 1)\n const n1 = normalAt(t1, tB <= yB, d[1] > 0 ? 1 : -1)\n return { t0, n0, t1, n1 }\n}\n\n/** Distance from a part-space point to the shape (0 inside). */\nexport const distanceToShape = (s: PartShape, p: Vec3): number => {\n if (s.kind === 'box') {\n const dx = Math.max(Math.abs(p[0]) - s.size[0] / 2, 0)\n const dy = Math.max(Math.abs(p[1]) - s.size[1] / 2, 0)\n const dz = Math.max(Math.abs(p[2]) - s.size[2] / 2, 0)\n return Math.hypot(dx, dy, dz)\n }\n if (s.kind === 'sphere') return Math.max(0, vec.length(p) - s.radius)\n const dr = Math.max(0, Math.hypot(p[0], p[2]) - s.radius)\n const dy = Math.max(0, Math.abs(p[1]) - s.height / 2)\n return Math.hypot(dr, dy)\n}\n\n/** Nearest point on the surface of a shape to a part-space point, with the outward normal. */\nexport const surfacePoint = (s: PartShape, p: Vec3): { point: Vec3; normal: Vec3 } => {\n if (s.kind === 'box') {\n const h: Vec3 = [s.size[0] / 2, s.size[1] / 2, s.size[2] / 2]\n const inside = Math.abs(p[0]) <= h[0] && Math.abs(p[1]) <= h[1] && Math.abs(p[2]) <= h[2]\n if (!inside) {\n const c: Vec3 = [Math.max(-h[0], Math.min(h[0], p[0])), Math.max(-h[1], Math.min(h[1], p[1])), Math.max(-h[2], Math.min(h[2], p[2]))]\n return { point: c, normal: vec.normalize(vec.sub(p, c)) }\n }\n let axis = 0\n let best = Infinity\n for (let i = 0; i < 3; i++) {\n const g = h[i] - Math.abs(p[i])\n if (g < best) {\n best = g\n axis = i\n }\n }\n const sign = p[axis] >= 0 ? 1 : -1\n const point: Vec3 = [p[0], p[1], p[2]]\n point[axis] = sign * h[axis]\n const normal: Vec3 = [0, 0, 0]\n normal[axis] = sign\n return { point, normal }\n }\n if (s.kind === 'sphere') {\n const n = vec.normalize(p)\n return { point: vec.scale(n, s.radius), normal: n }\n }\n const rho = Math.hypot(p[0], p[2])\n const hh = s.height / 2\n const inside = rho <= s.radius && Math.abs(p[1]) <= hh\n if (!inside) {\n const k = rho > s.radius ? s.radius / rho : 1\n const c: Vec3 = [p[0] * k, Math.max(-hh, Math.min(hh, p[1])), p[2] * k]\n return { point: c, normal: vec.normalize(vec.sub(p, c)) }\n }\n if (s.radius - rho < hh - Math.abs(p[1])) {\n const k = rho < EPS ? 0 : s.radius / rho\n const point: Vec3 = rho < EPS ? [s.radius, p[1], 0] : [p[0] * k, p[1], p[2] * k]\n return { point, normal: vec.normalize([point[0], 0, point[2]], [1, 0, 0]) }\n }\n const sign = p[1] >= 0 ? 1 : -1\n return { point: [p[0], sign * hh, p[2]], normal: [0, sign, 0] }\n}\n\n/** Axis-aligned bounds of a shape with a given centre and orientation. */\nexport const aabbOf = (s: PartShape, center: Vec3, q: Quat): { min: Vec3; max: Vec3 } => {\n let hx: number, hy: number, hz: number\n if (s.kind === 'sphere') {\n hx = hy = hz = s.radius\n } else {\n const m = quat.toMatrix(q)\n if (s.kind === 'box') {\n const a = s.size[0] / 2, b = s.size[1] / 2, c = s.size[2] / 2\n hx = Math.abs(m[0]) * a + Math.abs(m[1]) * b + Math.abs(m[2]) * c\n hy = Math.abs(m[3]) * a + Math.abs(m[4]) * b + Math.abs(m[5]) * c\n hz = Math.abs(m[6]) * a + Math.abs(m[7]) * b + Math.abs(m[8]) * c\n } else {\n const ax = [m[1], m[4], m[7]]\n const hh = s.height / 2\n const e = (i: number) => s.radius * Math.sqrt(Math.max(0, 1 - ax[i] * ax[i])) + hh * Math.abs(ax[i])\n hx = e(0)\n hy = e(1)\n hz = e(2)\n }\n }\n return { min: [center[0] - hx, center[1] - hy, center[2] - hz], max: [center[0] + hx, center[1] + hy, center[2] + hz] }\n}\n\n/** Seeded generator (mulberry32). The state is a single int32, so it round-trips through JSON. */\nexport interface Rng {\n next(): number\n state(): number\n set(state: number): void\n}\n\nexport const createRng = (seed: number): Rng => {\n let s = seed | 0\n return {\n next() {\n s = (s + 0x6d2b79f5) | 0\n let t = Math.imul(s ^ (s >>> 15), 1 | s)\n t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296\n },\n state: () => s,\n set(v) {\n s = v | 0\n },\n }\n}\n","import { quat } from './math'\nimport type { Fragment, FractureStyle, Quat, SplitForm, Vec3 } from './types'\n\n/** A fragment in the part's local space (centre, size in the fragment's own axes, orientation relative to the part). */\nexport interface PlannedFragment {\n center: Vec3\n size: Vec3\n q: Quat\n shape: Fragment['shape']\n /** Share of the part's mass (unnormalised). */\n weight: number\n /** Cut from inside a stack of sheets (a page of a book), not from its cover. */\n inner?: boolean\n}\n\nexport interface PlanInput {\n style: FractureStyle\n /** Bounding box dimensions in part axes. */\n dims: Vec3\n thickness: number\n /** Index 0..2 of the grain axis, if any. */\n grain?: number\n /** Impact point in part space. */\n hit: Vec3\n fragmentSize: [number, number]\n maxFragments: number\n rnd: () => number\n /** Thickness of one sheet of the material (`MaterialDef.sheet`): a `tear` part thicker than a few sheets comes apart as loose sheets. */\n sheet?: number\n /**\n * The part broke across at this point of its long axis (part space), not everywhere at once (`sever`): two stubs either side of a band `gap`\n * wide that comes apart in splinters. Used by `splinter` (a board, a batten, a beam).\n */\n cut?: { at: number; gap: number }\n /** How the wood-based material comes apart (`MaterialDef.splitForm`): slivers of many sizes, peeling plies, or crumbly lumps. */\n form?: SplitForm\n}\n\ninterface Box {\n c: Vec3\n s: Vec3\n}\n\n/** Split a box into `count` pieces by cutting the largest piece along its longest allowed axis. */\nconst bsp = (root: Box, count: number, axes: number[], rnd: () => number): Box[] => {\n const pieces: Box[] = [root]\n const vol = (b: Box) => axes.reduce((v, a) => v * b.s[a], 1)\n while (pieces.length < count) {\n let bi = 0\n for (let i = 1; i < pieces.length; i++) if (vol(pieces[i]) > vol(pieces[bi])) bi = i\n const b = pieces[bi]\n let ax = axes[0]\n for (const a of axes) if (b.s[a] > b.s[ax]) ax = a\n if (b.s[ax] < 1e-4) break\n const r = 0.3 + 0.4 * rnd()\n const l1 = b.s[ax] * r\n const l2 = b.s[ax] - l1\n const c1: Vec3 = [b.c[0], b.c[1], b.c[2]]\n const c2: Vec3 = [b.c[0], b.c[1], b.c[2]]\n c1[ax] = b.c[ax] - b.s[ax] / 2 + l1 / 2\n c2[ax] = b.c[ax] + b.s[ax] / 2 - l2 / 2\n const s1: Vec3 = [b.s[0], b.s[1], b.s[2]]\n const s2: Vec3 = [b.s[0], b.s[1], b.s[2]]\n s1[ax] = l1\n s2[ax] = l2\n pieces[bi] = { c: c1, s: s1 }\n pieces.push({ c: c2, s: s2 })\n }\n return pieces\n}\n\nconst parity = (p: [number, number, number]): number => {\n let inv = 0\n for (let i = 0; i < 3; i++) for (let j = i + 1; j < 3; j++) if (p[i] > p[j]) inv++\n return inv % 2 === 0 ? 1 : -1\n}\n\n/** Orientation whose x, y, z axes are the part axes `ax`, `ay`, `az`, then rotated by `angle` around its own z. */\nconst frame = (ax: number, ay: number, az: number, angle = 0): Quat => {\n const e = (i: number): Vec3 => [i === 0 ? 1 : 0, i === 1 ? 1 : 0, i === 2 ? 1 : 0]\n const z = e(az)\n const sg = parity([ax, ay, az])\n const q = quat.fromColumns(e(ax), e(ay), [z[0] * sg, z[1] * sg, z[2] * sg])\n return angle === 0 ? q : quat.mul(q, quat.fromAxisAngle([0, 0, 1], angle))\n}\n\nconst clamp = (v: number, a: number, b: number) => Math.max(a, Math.min(b, v))\n\n/** Cut `box` into `count` pieces of uneven length along `axis`: each piece takes a random share between a quarter and seven quarters of the mean. */\nconst splitAlong = (box: Box, count: number, axis: number, rnd: () => number): Box[] => {\n const shares = Array.from({ length: count }, () => 0.25 + 1.5 * rnd())\n const total = shares.reduce((sum, share) => sum + share, 0)\n const out: Box[] = []\n let from = box.c[axis] - box.s[axis] / 2\n for (const share of shares) {\n const length = (box.s[axis] * share) / total\n const c: Vec3 = [box.c[0], box.c[1], box.c[2]]\n const size: Vec3 = [box.s[0], box.s[1], box.s[2]]\n c[axis] = from + length / 2\n size[axis] = length\n out.push({ c, s: size })\n from += length\n }\n return out\n}\n\n/**\n * Splinters along the grain (`grain`, default the longest axis) out of `box`: the cross-section is split into strands of uneven width, and each strand\n * breaks along the grain at uneven points, so the splinters come out long and short, thick and thin, never a stack of equal slats.\n */\nconst splinterBox = (inp: PlanInput, box: Box, limit = inp.maxFragments): PlannedFragment[] => {\n const { rnd } = inp\n const dims = box.s\n const [fmin, fmax] = inp.fragmentSize\n const g = inp.grain ?? [0, 1, 2].sort((a, b) => dims[b] - dims[a])[0]\n const [a, b] = [0, 1, 2].filter((i) => i !== g)\n const w = Math.max(fmin * 1.5, 0.01)\n const c = clamp(Math.round((dims[a] * dims[b]) / (w * w)), 3, Math.max(3, Math.floor(limit / 2)))\n const maxLen = fmax * 4\n const cells: Box[] = []\n // some strands split again unevenly across: thin needles beside thick splinters\n for (const cell of bsp(box, c, [a, b], rnd)) {\n const wide = cell.s[a] >= cell.s[b] ? a : b\n if (rnd() < 0.4 && cell.s[wide] > fmin * 0.5) for (const part of splitAlong(cell, 2, wide, rnd)) cells.push(part)\n else cells.push(cell)\n }\n const pieces: Box[] = []\n for (const cell of cells) {\n const extra = Math.floor(rnd() * 3)\n const k = Math.max(1, Math.ceil(dims[g] / maxLen)) + extra\n for (const p of splitAlong(cell, k, g, rnd)) pieces.push(p)\n }\n return pieces.slice(0, limit).map((p) => ({ center: p.c, size: [p.s[g], p.s[a], p.s[b]] as Vec3, q: frame(g, a, b), shape: 'splinter' as const, weight: p.s[0] * p.s[1] * p.s[2] }))\n}\n\n/**\n * Metres of plywood one ply stands for, and how far apart the peeled layers start (times their thickness). A sheet is at most `PLY_SHEET` thick: a part\n * of plywood thicker than a board (a kennel drawn as one box) is a hollow of panels, and comes apart in sheets that thin spread through its depth.\n */\nconst PLY = 0.003\nconst PLY_GAP = 0.6\nconst PLY_SHEET = 0.012\n\n/**\n * Plywood coming apart: the glue lines let go and the sheet splits into two or three layers that start apart from each other, each torn into ragged\n * sheets, and about one piece in three a thin splinter along the face grain.\n */\nconst plyBreak = (inp: PlanInput, root: Box, limit: number): PlannedFragment[] => {\n const { rnd } = inp\n const dims = root.s\n const sorted = [0, 1, 2].sort((x, y) => dims[x] - dims[y])\n const t = sorted[0]\n const [u, v] = [sorted[1], sorted[2]].sort((x, y) => x - y)\n const along = dims[u] >= dims[v] ? u : v\n const across = along === u ? v : u\n const layers = clamp(Math.round(dims[t] / PLY / 2), 2, 3)\n const pitch = dims[t] / layers\n const th = Math.min(pitch, PLY_SHEET)\n const per = Math.max(2, Math.floor(limit / layers))\n const out: PlannedFragment[] = []\n for (let k = 0; k < layers; k++) {\n const layer: Box = { c: [root.c[0], root.c[1], root.c[2]], s: [dims[0], dims[1], dims[2]] }\n layer.c[t] = root.c[t] + (-dims[t] / 2 + (k + 0.5) * pitch) * (pitch > PLY_SHEET ? 1 : 1 + PLY_GAP)\n layer.s[t] = th\n for (const cell of bsp(layer, per, [u, v], rnd)) {\n if (out.length >= limit) return out\n if (rnd() < 0.35) {\n const strand = cell.s[across] * (0.15 + 0.2 * rnd())\n out.push({ center: cell.c, size: [cell.s[along], strand, th * 0.7], q: frame(along, across, t), shape: 'splinter', weight: cell.s[along] * strand * th })\n } else {\n out.push({ center: cell.c, size: [cell.s[u], cell.s[v], th], q: frame(u, v, t, (rnd() - 0.5) * 0.5), shape: 'scrap', weight: cell.s[u] * cell.s[v] * th })\n }\n }\n }\n return out\n}\n\n/** Crumbly lumps of a board with no grain (MDF): `count` lumps of uneven size out of `box`. */\nconst granules = (inp: PlanInput, box: Box, count: number): PlannedFragment[] =>\n bsp(box, count, [0, 1, 2], inp.rnd).map((b) => ({ center: b.c, size: b.s, q: quat.identity(), shape: 'chunk' as const, weight: b.s[0] * b.s[1] * b.s[2] }))\n\n/** Lumps the broken edge of an MDF board crumbles into, besides its slabs. */\nconst CRUMBS = 6\n\n/** Broken across at `at` along the longest axis: a stub each side and splinters (lumps for `snap`) out of the band `gap` wide between them. */\nconst severAt = (inp: PlanInput, root: Box, at: number, gap: number): PlannedFragment[] => {\n const dims = root.s\n const L = [0, 1, 2].sort((x, y) => dims[y] - dims[x])[0]\n const half = dims[L] / 2\n const lo = clamp(at - gap / 2, -half, half), hi = clamp(at + gap / 2, -half, half)\n const out: PlannedFragment[] = []\n // a stub of wood with fibre is laid long along its own x with the break at +x, so the renderer can tear that end into strands\n const fibrous = inp.form === 'slivers' || inp.form === 'plies'\n const [a, b] = [0, 1, 2].filter((i) => i !== L)\n const stub = (from: number, to: number, breakAtEnd: boolean) => {\n if (to - from < 0.02) return\n const c: Vec3 = [root.c[0], root.c[1], root.c[2]], sz: Vec3 = [dims[0], dims[1], dims[2]]\n c[L] = (from + to) / 2\n sz[L] = to - from\n const weight = sz[0] * sz[1] * sz[2]\n if (fibrous) out.push({ center: c, size: [sz[L], sz[a], sz[b]], q: frame(L, a, b, breakAtEnd ? 0 : Math.PI), shape: 'slab', weight })\n else out.push({ center: c, size: sz, q: quat.identity(), shape: 'slab', weight })\n }\n stub(-half, lo, true)\n stub(hi, half, false)\n const band: Box = { c: [root.c[0], root.c[1], root.c[2]], s: [dims[0], dims[1], dims[2]] }\n band.c[L] = (lo + hi) / 2\n band.s[L] = Math.max(hi - lo, 0.01)\n // a snapping board (MDF, plastic) crumbles in the band; the splinters of a splintering one lie along the grain when it runs across the cut,\n // else they are short slivers of the band\n const room = inp.maxFragments - out.length\n if (inp.style === 'snap' && inp.form === 'plies') for (const p of plyBreak(inp, band, Math.max(3, room))) out.push(p)\n else if (inp.style === 'snap' && inp.form === 'granules') for (const p of granules(inp, band, clamp(room, 3, 12))) out.push(p)\n else if (inp.style === 'snap') {\n for (const b of bsp(band, Math.max(3, Math.min(6, room)), [0, 1, 2], inp.rnd)) out.push({ center: b.c, size: b.s, q: quat.identity(), shape: 'chunk', weight: b.s[0] * b.s[1] * b.s[2] })\n } else for (const p of splinterBox(inp, band, Math.max(3, inp.maxFragments - out.length))) out.push(p)\n return out\n}\n\n/** Leaves of a stack torn apart (a book, a ream): `layers` of thin scraps through the thickness, a little askew; one scrap in four is cover, the rest pages. */\nconst tearStack = (inp: PlanInput, root: Box, t: number, u: number, v: number, n: number, sheet: number): PlannedFragment[] => {\n const { dims, rnd, maxFragments } = inp\n const layers = clamp(Math.ceil(dims[t] / STACK_LAYER), 2, 4)\n const per = clamp(n, 3, Math.max(3, Math.floor(maxFragments / layers)))\n const out: PlannedFragment[] = []\n for (let k = 0; k < layers; k++) {\n const off = -dims[t] / 2 + ((k + 0.5) * dims[t]) / layers\n for (const b of bsp(root, per, [u, v], rnd)) {\n if (out.length >= maxFragments) return out\n const c: Vec3 = [b.c[0], b.c[1], b.c[2]]\n c[t] = off\n out.push({ center: c, size: [b.s[u], b.s[v], sheet], q: frame(u, v, t, (rnd() - 0.5) * 0.8), shape: 'scrap', weight: b.s[u] * b.s[v], inner: out.length % 4 !== 0 })\n }\n }\n return out\n}\n\n/** Metres of a stack of sheets that one layer of scraps stands for. */\nconst STACK_LAYER = 0.012\n\n/** Deterministic fragment layout for a failed part, in part space. */\nexport const planFragments = (inp: PlanInput): PlannedFragment[] => {\n const { style, dims, rnd, maxFragments } = inp\n const [fmin, fmax] = inp.fragmentSize\n const mean = (fmin + fmax) / 2\n const root: Box = { c: [0, 0, 0], s: [dims[0], dims[1], dims[2]] }\n const idq = quat.identity()\n const out: PlannedFragment[] = []\n const sorted = [0, 1, 2].sort((a, b) => dims[a] - dims[b])\n const t = sorted[0]\n const [u, v] = [sorted[1], sorted[2]].sort((a, b) => a - b)\n\n if (style === 'snap') {\n if (inp.cut) return severAt(inp, root, inp.cut.at, inp.cut.gap)\n if (inp.form === 'plies') return plyBreak(inp, root, maxFragments)\n const n = Math.min(maxFragments, 2 + Math.floor(rnd() * 3))\n for (const b of bsp(root, n, [0, 1, 2], rnd)) out.push({ center: b.c, size: b.s, q: idq, shape: 'slab', weight: b.s[0] * b.s[1] * b.s[2] })\n if (inp.form !== 'granules') return out\n // the broken edges of an MDF board crumble: lumps out of a band around the point it broke at, sharing the mass with the slabs\n const crumbs = Math.min(CRUMBS, maxFragments - out.length)\n if (crumbs <= 0) return out\n const band: Box = { c: [0, 0, 0], s: [0, 0, 0] }\n for (let i = 0; i < 3; i++) {\n band.s[i] = Math.min(dims[i], Math.max(fmin, dims[i] * 0.2))\n band.c[i] = clamp(inp.hit[i], -dims[i] / 2 + band.s[i] / 2, dims[i] / 2 - band.s[i] / 2)\n }\n for (const p of granules(inp, band, crumbs)) out.push({ ...p, weight: p.weight * 0.5 })\n return out\n }\n if (style === 'crumble' || style === 'none') {\n const n = clamp(Math.ceil((dims[0] * dims[1] * dims[2]) / (mean * mean * mean)), 4, maxFragments)\n for (const b of bsp(root, n, [0, 1, 2], rnd)) out.push({ center: b.c, size: b.s, q: idq, shape: 'chunk', weight: b.s[0] * b.s[1] * b.s[2] })\n return out\n }\n if (style === 'splinter') {\n if (inp.cut) return severAt(inp, root, inp.cut.at, inp.cut.gap)\n for (const p of splinterBox(inp, root)) out.push(p)\n return out\n }\n if (style === 'tear') {\n const n = clamp(Math.round((dims[u] * dims[v]) / (mean * mean)), 3, maxFragments)\n const sheet = inp.sheet ?? 0\n if (sheet > 0 && dims[t] > sheet * 4) return tearStack(inp, root, t, u, v, n, sheet)\n const th = Math.min(inp.thickness, dims[t])\n for (const b of bsp(root, n, [u, v], rnd)) {\n out.push({ center: [b.c[0], b.c[1], b.c[2]], size: [b.s[u], b.s[v], th], q: frame(u, v, t), shape: 'scrap', weight: b.s[u] * b.s[v] })\n }\n return out\n }\n // shatter: thin shards radiating from the impact\n const th = Math.min(inp.thickness, dims[t])\n const Hu = dims[u] / 2, Hv = dims[v] / 2\n const hu = clamp(inp.hit[u], -Hu * 0.95, Hu * 0.95)\n const hv = clamp(inp.hit[v], -Hv * 0.95, Hv * 0.95)\n const R = Math.max(Math.hypot(Hu + Math.abs(hu), Hv + Math.abs(hv)), 0.02)\n const n = clamp(Math.round((dims[u] * dims[v]) / (mean * mean)), 6, maxFragments)\n const sectors = clamp(Math.round(Math.sqrt(n * 1.6)), 5, 10)\n const rings = Math.max(1, Math.ceil(n / sectors))\n const radii: number[] = []\n for (let k = 0; k <= rings; k++) radii.push(R * Math.pow(k / rings, 1.3))\n const cap = fmax * 1.5\n for (let j = 0; j < sectors && out.length < maxFragments; j++) {\n const theta = (j + (rnd() - 0.5) * 0.4) * ((Math.PI * 2) / sectors)\n for (let k = 0; k < rings && out.length < maxFragments; k++) {\n const rm = (radii[k] + radii[k + 1]) / 2\n const cu = hu + rm * Math.cos(theta)\n const cv = hv + rm * Math.sin(theta)\n if (Math.abs(cu) > Hu + 0.01 || Math.abs(cv) > Hv + 0.01) continue\n const radial = clamp(radii[k + 1] - radii[k], 0.01, cap)\n const tang = clamp(radii[k + 1] * ((Math.PI * 2) / sectors) * 0.9, 0.01, cap)\n const c: Vec3 = [0, 0, 0]\n c[u] = clamp(cu, -Hu * 0.98, Hu * 0.98)\n c[v] = clamp(cv, -Hv * 0.98, Hv * 0.98)\n c[t] = 0\n out.push({ center: c, size: [radial, tang, th], q: frame(u, v, t, theta), shape: 'shard', weight: radial * tang })\n }\n }\n if (out.length === 0) out.push({ center: [0, 0, 0], size: [dims[u], dims[v], th], q: frame(u, v, t), shape: 'shard', weight: 1 })\n return out\n}\n","import { quat, rotateVec } from './math'\nimport type { FragmentMark, PartUnits, Quat, Vec3 } from './types'\n\n/** One masonry unit (or panel) cut out of a wall, in the part's own axes. */\nexport interface UnitCell {\n center: Vec3\n size: Vec3\n}\n\n/** The two axes a wall spreads along: height is local y unless the part is thin along y (a slab), then x and z. */\nexport const planeAxes = (thin: number): [number, number] => (thin === 1 ? [0, 2] : [thin === 0 ? 2 : 0, 1])\n\n/**\n * Every unit of the wall laid in `bond`: rows along the plane's second axis, running bond shifts odd rows by half a unit, edge units are cut to\n * the wall. More than `cap` units are merged into bigger ones (the same bond) so a whole wall stays a drawable number of fragments.\n */\nexport const unitGrid = (dims: Vec3, thin: number, units: Pick<PartUnits, 'size' | 'bond'>, cap: number): UnitCell[] => {\n const [u, v] = planeAxes(thin)\n let unitU = Math.min(units.size[0], dims[u]), unitV = Math.min(units.size[1], dims[v])\n const rowsFor = (h: number): number => Math.ceil(dims[v] / h - 1e-9)\n const colsFor = (w: number): number => Math.ceil(dims[u] / w - 1e-9) + (units.bond === 'running' ? 1 : 0)\n const merge = Math.ceil(Math.sqrt((rowsFor(unitV) * colsFor(unitU)) / cap))\n if (merge > 1) {\n unitU = Math.min(unitU * merge, dims[u])\n unitV = Math.min(unitV * merge, dims[v])\n }\n const cells: UnitCell[] = []\n for (let row = 0; row < rowsFor(unitV); row++) {\n const v0 = -dims[v] / 2 + row * unitV, v1 = Math.min(v0 + unitV, dims[v] / 2)\n const shift = units.bond === 'running' && row % 2 === 1 ? unitU / 2 : 0\n for (let col = 0; col < colsFor(unitU); col++) {\n const u0 = Math.max(-dims[u] / 2 + col * unitU - shift, -dims[u] / 2), u1 = Math.min(-dims[u] / 2 + (col + 1) * unitU - shift, dims[u] / 2)\n if (u1 - u0 < 0.01) continue\n const center: Vec3 = [0, 0, 0], size: Vec3 = [0, 0, 0]\n center[u] = (u0 + u1) / 2\n center[v] = (v0 + v1) / 2\n size[u] = u1 - u0\n size[v] = v1 - v0\n size[thin] = dims[thin]\n cells.push({ center, size })\n }\n }\n return cells\n}\n\nconst planeDistance = (cell: UnitCell, thin: number, point: Vec3): number => {\n const [u, v] = planeAxes(thin)\n const du = cell.center[u] - point[u], dv = cell.center[v] - point[v]\n return Math.sqrt(du * du + dv * dv)\n}\n\n/** Units whose centre is within `radius` of `point` (part-local) in the wall plane; at least the nearest one. */\nexport const cellsWithin = (cells: readonly UnitCell[], thin: number, point: Vec3, radius: number): UnitCell[] => {\n const inside = cells.filter((c) => planeDistance(c, thin, point) <= radius)\n if (inside.length > 0 || cells.length === 0) return inside\n return [cells.reduce((best, c) => (planeDistance(c, thin, point) < planeDistance(best, thin, point) ? c : best))]\n}\n\nexport const cellsOutside = (cells: readonly UnitCell[], thin: number, point: Vec3, radius: number): UnitCell[] => cells.filter((c) => planeDistance(c, thin, point) > radius)\n\n/** A hole in the part's own axes. */\nexport interface LocalHole {\n point: Vec3\n normal: Vec3\n diameter: number\n}\n\nexport const MAX_MARKS_PER_FRAGMENT = 12\n\n/** The holes that fall inside a fragment box (`rotation` is the fragment's orientation in the part), in the fragment's own axes. */\nexport const marksInBox = (center: Vec3, size: Vec3, rotation: Quat | undefined, holes: readonly LocalHole[]): FragmentMark[] => {\n const inverse = rotation ? quat.conjugate(rotation) : undefined\n const marks: FragmentMark[] = []\n for (const hole of holes) {\n const offset: Vec3 = [hole.point[0] - center[0], hole.point[1] - center[1], hole.point[2] - center[2]]\n const point = inverse ? rotateVec(inverse, offset) : offset\n const inside = point.every((value, k) => Math.abs(value) <= size[k]! / 2 + hole.diameter / 2)\n if (!inside) continue\n marks.push({ point, normal: inverse ? rotateVec(inverse, hole.normal) : hole.normal, diameter: hole.diameter })\n if (marks.length >= MAX_MARKS_PER_FRAGMENT) break\n }\n return marks\n}\n\nconst JOINT_GAP = 1e-4\n/** Share of the shorter of two units their bed has to overlap for one to bear on the other: a unit held by a corner does not stand. */\nconst MIN_BEARING_SHARE = 0.25\n\n/**\n * The units of a wall still standing (`standing(i)`) that no longer bear on its bottom through the units under them: a unit stands while its bed\n * overlaps a standing unit of the row below (the bottom row stands on what holds the wall). Masonry carries by bearing, and the mortar of a head\n * joint holds next to nothing in tension, so over a hole the courses step in by the bond (half a unit a course in running bond) and the triangle\n * above it comes down, as it does over an opening without a lintel; at the free end of a wall, all that hangs over the hole. A unit that keeps only a\n * corner of its bed (less than `MIN_BEARING_SHARE` of a unit) does not bear: the mortar of a joint does not hold its moment. A unit between two standing\n * units of its course is wedged by its head joints, so a gap of two units does not drop the one over it. A slab (thin along y)\n * has no bottom row: none.\n */\nexport const unsupportedCells = (cells: readonly UnitCell[], thin: number, dims: Vec3, standing: (index: number) => boolean): number[] => {\n if (thin === 1) return []\n const [u, v] = planeAxes(thin)\n const bottom = -dims[v] / 2\n const rowOf = (y: number): number => Math.round((y - bottom) * 1e4)\n const rows = new Map<number, number[]>()\n for (let i = 0; i < cells.length; i++) {\n if (!standing(i)) continue\n const cell = cells[i]!\n const key = rowOf(cell.center[v] - cell.size[v] / 2)\n const row = rows.get(key)\n if (row) row.push(i)\n else rows.set(key, [i])\n }\n const held = new Set<number>()\n const queue: number[] = []\n for (const i of rows.get(0) ?? []) {\n held.add(i)\n queue.push(i)\n }\n const overlap = (a: UnitCell, b: UnitCell): number =>\n Math.min(a.center[u] + a.size[u] / 2, b.center[u] + b.size[u] / 2) - Math.max(a.center[u] - a.size[u] / 2, b.center[u] - b.size[u] / 2)\n const climb = () => {\n while (queue.length > 0) {\n const cell = cells[queue.pop()!]!\n for (const j of rows.get(rowOf(cell.center[v] + cell.size[v] / 2)) ?? []) {\n const other = cells[j]!\n if (held.has(j) || overlap(cell, other) <= Math.max(JOINT_GAP, MIN_BEARING_SHARE * Math.min(cell.size[u], other.size[u]))) continue\n held.add(j)\n queue.push(j)\n }\n }\n }\n // the units of each course in order along the wall: a unit between two that stand is wedged between them by its head joints (it bridges a gap of\n // two units under it); one held on one side only would hang from its mortar, which does not hold the moment\n for (const row of rows.values()) row.sort((a, b) => cells[a]!.center[u] - cells[b]!.center[u])\n const touching = (a: UnitCell, b: UnitCell): boolean => Math.abs(a.center[u] + a.size[u] / 2 - (b.center[u] - b.size[u] / 2)) <= 1e-3\n for (let wedged = true; wedged;) {\n climb()\n wedged = false\n for (const row of rows.values()) {\n for (let k = 1; k < row.length - 1; k++) {\n const i = row[k]!\n if (held.has(i) || !held.has(row[k - 1]!) || !held.has(row[k + 1]!)) continue\n if (!touching(cells[row[k - 1]!]!, cells[i]!) || !touching(cells[i]!, cells[row[k + 1]!]!)) continue\n held.add(i)\n queue.push(i)\n wedged = true\n }\n }\n }\n const loose: number[] = []\n for (const row of rows.values()) for (const i of row) if (!held.has(i)) loose.push(i)\n return loose\n}\n\n/**\n * At most `cap` clumps of `cells` (part-local units of a wall): the units binned on a square grid of the wall plane, each bin the box around its units.\n * Masonry a blast throws comes out in clumps of a few units held by their mortar, not one by one.\n */\nexport const clumpCells = (cells: readonly UnitCell[], thin: number, cap: number): UnitCell[] => {\n if (cells.length <= cap) return [...cells]\n const [u, v] = planeAxes(thin)\n let lo0 = Infinity, lo1 = Infinity, hi0 = -Infinity, hi1 = -Infinity\n for (const cell of cells) {\n lo0 = Math.min(lo0, cell.center[u] - cell.size[u] / 2)\n hi0 = Math.max(hi0, cell.center[u] + cell.size[u] / 2)\n lo1 = Math.min(lo1, cell.center[v] - cell.size[v] / 2)\n hi1 = Math.max(hi1, cell.center[v] + cell.size[v] / 2)\n }\n let side = Math.sqrt(((hi0 - lo0) * (hi1 - lo1)) / cap)\n for (;;) {\n const bins = new Map<string, { lo: Vec3; hi: Vec3 }>()\n for (const cell of cells) {\n const key = `${Math.floor((cell.center[u] - lo0) / side)}:${Math.floor((cell.center[v] - lo1) / side)}`\n const bin = bins.get(key) ?? { lo: [Infinity, Infinity, Infinity] as Vec3, hi: [-Infinity, -Infinity, -Infinity] as Vec3 }\n for (let k = 0; k < 3; k++) {\n bin.lo[k] = Math.min(bin.lo[k]!, cell.center[k]! - cell.size[k]! / 2)\n bin.hi[k] = Math.max(bin.hi[k]!, cell.center[k]! + cell.size[k]! / 2)\n }\n bins.set(key, bin)\n }\n if (bins.size <= cap) {\n return [...bins.values()].map(({ lo, hi }) => ({ center: [(lo[0] + hi[0]) / 2, (lo[1] + hi[1]) / 2, (lo[2] + hi[2]) / 2] as Vec3, size: [hi[0] - lo[0], hi[1] - lo[1], hi[2] - lo[2]] as Vec3 }))\n }\n side *= 1.25\n }\n}\n","import type { MaterialDef, SurfaceLayer, Vec3 } from './types'\n\n/** A surface layer with its material resolved; `energy` is what a bullet spends crossing one face's worth of it, in joules. */\nexport interface LayerRT {\n index: number\n def: SurfaceLayer\n mat: MaterialDef\n energy: number\n}\n\n/** `[layer, face (+1 or -1), x, y, z, radius]`: a patch of a layer that came off, in object-local space. Saved with the part. */\nexport type Spall = readonly [number, number, number, number, number, number]\n\nexport const MAX_SPALLS = 64\n\n/** Index of the smallest dimension (the first one on a tie): the axis a wall is thin along. */\nexport const thinAxisOf = (dims: Vec3): number => (dims[0] <= dims[1] && dims[0] <= dims[2] ? 0 : dims[1] <= dims[2] ? 1 : 2)\n\nexport const resolveLayer = (def: SurfaceLayer, index: number, mat: MaterialDef): LayerRT => ({ index, def, mat, energy: mat.penetration * def.thickness * 1000 })\n\nconst onFace = (layer: LayerRT, face: number): boolean => layer.def.faces === 'both' || layer.def.faces === (face > 0 ? '+' : '-')\n\nconst isSpalled = (spalls: readonly Spall[] | undefined, layer: number, face: number, point: Vec3): boolean => {\n for (const s of spalls ?? []) {\n if (s[0] !== layer || s[1] !== face) continue\n const dx = s[2] - point[0], dy = s[3] - point[1], dz = s[4] - point[2]\n if (dx * dx + dy * dy + dz * dz <= s[5] * s[5]) return true\n }\n return false\n}\n\n/** The outermost layer still on `face` at `point` (layers are listed outermost first). */\nexport const outerLayer = (layers: readonly LayerRT[], spalls: readonly Spall[] | undefined, face: number, point: Vec3): LayerRT | undefined =>\n layers.find((l) => onFace(l, face) && !isSpalled(spalls, l.index, face, point))\n\n/** Joules a bullet spends crossing every layer still on `face` at `point`. */\nexport const layersEnergy = (layers: readonly LayerRT[], spalls: readonly Spall[] | undefined, face: number, point: Vec3): number => {\n let sum = 0\n for (const l of layers) if (onFace(l, face) && !isSpalled(spalls, l.index, face, point)) sum += l.energy\n return sum\n}\n\n/** Metres of layer a ray crosses on one face (full thickness, before obliquity). */\nexport const layersThickness = (layers: readonly LayerRT[], face: number): number => {\n let sum = 0\n for (const l of layers) if (onFace(l, face)) sum += l.def.thickness\n return sum\n}\n","import type { Vec3 } from './types'\n\n/** A bar as two end points. */\nexport type Bar = [Vec3, Vec3]\n\nconst COVER = 0.03\nconst MAX_BARS_PER_DIRECTION = 24\nconst MAX_MEMBER_BARS_PER_SIDE = 6\nconst STEEL_DENSITY = 7850\n\n/** Positions centred on 0 with exact `spacing`, as many as fit inside `length - 2 * cover` (at least two, at most `cap`). */\nconst spread = (length: number, cover: number, spacing: number, cap: number): number[] => {\n const room = Math.max(0, length - 2 * cover)\n const count = Math.min(cap, Math.max(2, Math.floor(room / spacing) + 1))\n const step = count > 1 && room / (count - 1) < spacing ? room / (count - 1) : spacing\n return Array.from({ length: count }, (_, i) => (i - (count - 1) / 2) * step)\n}\n\nconst bar = (axis: number, along: number, fixed: Array<[number, number]>): Bar => {\n const a: Vec3 = [0, 0, 0], b: Vec3 = [0, 0, 0]\n for (const [index, value] of fixed) {\n a[index] = value\n b[index] = value\n }\n a[axis] = -along\n b[axis] = along\n return [a, b]\n}\n\n/** Long members (columns, beams): two smaller dimensions close to each other and a much longer third one. */\nexport const isMember = (dims: Vec3): boolean => {\n const [a = 0, b = 0, c = 0] = [...dims].sort((x, y) => x - y)\n return b / a < 3 && c / b >= 3\n}\n\n/** Bars of a long member's perimeter that lie on one face of width `width` (the face's row of the cage). */\nexport const memberBarCount = (width: number, spacing: number): number => spread(width, COVER, spacing, MAX_MEMBER_BARS_PER_SIDE).length\n\n/**\n * Rebar of a box in the part's own axes. Plates (walls, slabs) get a grid along each of the two large axes at mid thickness; long members get\n * bars along their length at the perimeter of the section. `thin` is the axis the part is thinnest along.\n */\nexport const rebarBars = (dims: Vec3, thin: number, spacing: number): Bar[] => {\n const out: Bar[] = []\n if (isMember(dims)) {\n const long = dims.indexOf(Math.max(...dims))\n const [u = 0, v = 0] = [0, 1, 2].filter((i) => i !== long)\n const us = spread(dims[u], COVER, spacing, MAX_MEMBER_BARS_PER_SIDE)\n const vs = spread(dims[v], COVER, spacing, MAX_MEMBER_BARS_PER_SIDE)\n us.forEach((x, i) => vs.forEach((y, j) => {\n if (i === 0 || j === 0 || i === us.length - 1 || j === vs.length - 1) out.push(bar(long, dims[long] / 2 - 0.02, [[u, x], [v, y]]))\n }))\n return out\n }\n const [u = 0, v = 0] = [0, 1, 2].filter((i) => i !== thin)\n for (const y of spread(dims[v], COVER, spacing, MAX_BARS_PER_DIRECTION)) out.push(bar(u, dims[u] / 2 - 0.02, [[v, y], [thin, 0]]))\n for (const x of spread(dims[u], COVER, spacing, MAX_BARS_PER_DIRECTION)) out.push(bar(v, dims[v] / 2 - 0.02, [[u, x], [thin, 0]]))\n return out\n}\n\n/** The part of each bar that lies inside a box of `size` centred on `center` (part axes), in the plane of axes `u` and `v`; bars that miss it are dropped. */\nexport const clipBarsToBox = (bars: readonly Bar[], u: number, v: number, center: Vec3, size: Vec3): Bar[] => {\n const out: Bar[] = []\n for (const [a, b] of bars) {\n const axis = a[u] !== b[u] ? u : v\n const other = axis === u ? v : u\n if (Math.abs(a[other] - center[other]) > size[other] / 2) continue\n const lo = Math.max(Math.min(a[axis], b[axis]), center[axis] - size[axis] / 2), hi = Math.min(Math.max(a[axis], b[axis]), center[axis] + size[axis] / 2)\n if (hi - lo < 1e-6) continue\n const p: Vec3 = [a[0], a[1], a[2]], q: Vec3 = [b[0], b[1], b[2]]\n p[axis] = lo\n q[axis] = hi\n out.push([p, q])\n }\n return out\n}\n\n/** A bar bowed by `bow` metres per metre of its length out of the plane (along `thin`), as two segments meeting at the bowed middle; `i` alternates the side. */\nexport const bendBar = ([a, b]: Bar, thin: number, bow: number, i: number): Bar[] => {\n const length = Math.hypot(b[0] - a[0], b[1] - a[1], b[2] - a[2])\n const m: Vec3 = [(a[0] + b[0]) / 2, (a[1] + b[1]) / 2, (a[2] + b[2]) / 2]\n m[thin] += (i % 2 === 0 ? 1 : -1) * bow * length\n return [[a, m], [m, b]]\n}\n\n/** The part of each bar that lies within `radius` of `center` in the plane of axes `u` and `v` (bars that miss the disc are dropped). */\nexport const clipBarsToDisc = (bars: readonly Bar[], u: number, v: number, center: [number, number], radius: number): Bar[] => {\n const out: Bar[] = []\n for (const [a, b] of bars) {\n const axis = a[u] !== b[u] ? u : v\n const other = axis === u ? v : u\n const off = a[other] - center[other === u ? 0 : 1]\n if (Math.abs(off) >= radius) continue\n const half = Math.sqrt(radius * radius - off * off)\n const mid = center[axis === u ? 0 : 1]\n const lo = Math.max(Math.min(a[axis], b[axis]), mid - half), hi = Math.min(Math.max(a[axis], b[axis]), mid + half)\n if (hi - lo < 1e-6) continue\n const p: Vec3 = [a[0], a[1], a[2]], q: Vec3 = [b[0], b[1], b[2]]\n p[axis] = lo\n q[axis] = hi\n out.push([p, q])\n }\n return out\n}\n\n/**\n * How many bars of `rebarBars` run up the part (along its vertical axis), counted without the cap that keeps the drawn cage light: the steel that holds a\n * wall or a column in tension is all the bars its spacing puts in, not the 24 that are drawn. A long member lying on its side has none.\n */\nexport const verticalBarCount = (dims: Vec3, thin: number, spacing: number): number => {\n if (isMember(dims)) {\n if (dims.indexOf(Math.max(...dims)) !== 1) return 0\n const us = spread(dims[0], COVER, spacing, Infinity).length, vs = spread(dims[2], COVER, spacing, Infinity).length\n return 2 * us + 2 * Math.max(0, vs - 2)\n }\n const [u = 0, v = 0] = [0, 1, 2].filter((i) => i !== thin)\n if (u === 1) return spread(dims[v], COVER, spacing, Infinity).length\n if (v === 1) return spread(dims[u], COVER, spacing, Infinity).length\n return 0\n}\n\n/** Steel mass in kg of bars of `diameter` metres. */\nexport const rebarMass = (bars: readonly Bar[], diameter: number, density = STEEL_DENSITY): number => {\n let length = 0\n for (const [a, b] of bars) length += Math.abs(a[0] - b[0]) + Math.abs(a[1] - b[1]) + Math.abs(a[2] - b[2])\n return Math.PI * (diameter / 2) * (diameter / 2) * length * density\n}\n","import { planeAxes } from './breach'\nimport { thinAxisOf } from './layers'\nimport { quat, quatFromEuler, rotateVec, shapeDims } from './math'\nimport { isMember, memberBarCount } from './rebar'\nimport type { FlexureOptions, MasonryOptions, MaterialDef, PartSpec, StructureRole, Vec3 } from './types'\n\n/**\n * Real structural engineering of beams, slabs, walls and pillars: bending (the tension face cracks, the steel carries the pull, a member without\n * steel snaps) and crushing of slender bearing walls. Pure formulas in SI units (N, m, Pa, J); the world calls them with the parts' geometry.\n */\n\n/** Standard gravity, m/s². A physical constant. */\nexport const GRAVITY = 9.81\nconst MPA = 1e6\n\nexport const FLEXURE_DEFAULTS: Required<FlexureOptions> = {\n enabled: true,\n roles: ['beam', 'slab', 'roof', 'stair'],\n scope: 'rebar',\n crackFactor: 1.5,\n rebarYieldMPa: 500,\n cover: 0.03,\n neutralAxisLimit: 0.45,\n failRotationDeg: 10,\n loadFactor: 0.64,\n massFactor: 0.5,\n tntJoules: 4.184e6,\n impulse: 200,\n reflection: 2,\n reflectionNear: 4,\n nearScaled: 0.5,\n}\n\nexport const MASONRY_DEFAULTS: Required<MasonryOptions> = { minEccentricity: 0.05, slendernessLimit: 40, concreteFactor: 0.85 }\n\nexport const resolveFlexure = (o?: FlexureOptions): Required<FlexureOptions> => ({ ...FLEXURE_DEFAULTS, ...definedOf(o) })\nexport const resolveMasonry = (o?: MasonryOptions): Required<MasonryOptions> => ({ ...MASONRY_DEFAULTS, ...definedOf(o) })\nconst definedOf = <T extends object>(o?: T): Partial<T> => Object.fromEntries(Object.entries(o ?? {}).filter(([, v]) => v !== undefined)) as Partial<T>\n\n/** Bar diameter assumed for a `structure.rebar` ratio (it only sets where the bar centre is): 10 mm. */\nconst RATIO_BAR = 0.01\n\n/** Cracking moment of a rectangular section in N m: `alpha * fct * b * h^2 / 6` (NBR 6118 17.3.1). */\nexport const crackingMoment = (tensileMPa: number, b: number, h: number, alpha = FLEXURE_DEFAULTS.crackFactor): number => alpha * tensileMPa * MPA * (b * h * h) / 6\n\n/**\n * Moment the tension steel gives in N m, with the rectangular stress block of NBR 6118 17.2.2 (`0.85 * fck` over `0.8 x`): the steel pulls\n * `T = As * fy`, the block takes it at depth `x = T / (0.68 * fck * b)`, and `M = T * (d - 0.4 x)`. Past the ductility limit `x = limit * d` the\n * concrete would crush first, so the steel beyond what balances the block is taken as paired with compression steel (double reinforcement, NBR 6118\n * 17.2.4): it adds `T2 * (d - d')`, `d'` being the cover to the compression bars.\n */\nexport const steelMoment = (\n area: number, yieldMPa: number, d: number, b: number, compressiveMPa: number, options: Pick<FlexureOptions, 'neutralAxisLimit' | 'cover'> = {},\n): number => {\n if (area <= 0 || d <= 0 || b <= 0) return 0\n const T = area * yieldMPa * MPA\n const block = 0.68 * compressiveMPa * MPA * b\n const x = T / block\n const xl = (options.neutralAxisLimit ?? FLEXURE_DEFAULTS.neutralAxisLimit) * d\n if (x <= xl) return T * (d - 0.4 * x)\n const top = Math.min(d / 2, (options.cover ?? FLEXURE_DEFAULTS.cover) + RATIO_BAR / 2)\n return block * xl * (d - 0.4 * xl) + (T - block * xl) * (d - top)\n}\n\n/** Stiffness in N/m of a simply supported span under uniform load, at mid-span: `384 E I / (5 L^3)`. */\nexport const spanStiffness = (EI: number, span: number): number => (384 * EI) / (5 * span ** 3)\n\n/**\n * Strain energy in J of the equivalent one-degree-of-freedom system of a span whose peak moment is `M` (uniform load: `R = 8 M / L`): `KL * R^2 / (2 k)`.\n */\nexport const elasticEnergy = (moment: number, span: number, EI: number, loadFactor = FLEXURE_DEFAULTS.loadFactor): number => {\n const R = (8 * moment) / span\n return (loadFactor * R * R) / (2 * spanStiffness(EI, span))\n}\n\n/** Inverse of `elasticEnergy`: the peak moment in N m a span reaches when it takes `energy` J elastically. */\nexport const momentOfEnergy = (energy: number, span: number, EI: number, loadFactor = FLEXURE_DEFAULTS.loadFactor): number =>\n (span / 8) * Math.sqrt((2 * Math.max(0, energy) * spanStiffness(EI, span)) / loadFactor)\n\n/** Kinetic energy in J an impulse `I` (N s) gives the equivalent system of a span of mass `m` (kg): `(KL I)^2 / (2 KM m)` (Biggs 1964). */\nexport const impulseEnergy = (impulse: number, mass: number, options: Pick<FlexureOptions, 'loadFactor' | 'massFactor'> = {}): number => {\n const KL = options.loadFactor ?? FLEXURE_DEFAULTS.loadFactor\n const KM = options.massFactor ?? FLEXURE_DEFAULTS.massFactor\n return mass > 0 ? (KL * impulse) ** 2 / (2 * KM * mass) : 0\n}\n\n/**\n * Reflected impulse per area in Pa s of a charge of `tnt` kg at `distance` m on a face that looks at it. The incident impulse is Sadovsky's\n * `impulse * W^(2/3) / R`; the face reflects it by `reflection + reflectionNear / Z` (`Z = R / W^(1/3)`, m/kg^(1/3)): about 2 far away, 4 to 6 at\n * one or two metres per cube root kilogram, as the reflected-impulse curves of UFC 3-340-02 (fig. 2-7) rise towards the charge. Below `nearScaled`\n * the distance is held at that scaled distance.\n */\nexport const blastImpulse = (\n tnt: number, distance: number, options: Pick<FlexureOptions, 'impulse' | 'reflection' | 'reflectionNear' | 'nearScaled'> = {},\n): number => {\n if (tnt <= 0) return 0\n const o = { ...FLEXURE_DEFAULTS, ...definedOf(options) }\n const cube = Math.cbrt(tnt)\n const r = Math.max(distance, o.nearScaled * cube)\n return (o.reflection + o.reflectionNear / (r / cube)) * ((o.impulse * cube * cube) / r)\n}\n\n/**\n * Share of the compressive strength a wall or pillar of height `h` and thickness `t` keeps: the unavoidable eccentricity `(1 - 2 e)` times the\n * slenderness reduction `1 - (h / t / limit)^3` (NBR 16868-1), never below 0.\n */\nexport const slendernessFactor = (h: number, t: number, options: MasonryOptions = {}): number => {\n const o = resolveMasonry(options)\n const lambda = h / Math.max(t, 1e-3)\n return Math.max(0, (1 - 2 * o.minEccentricity) * (1 - (lambda / o.slendernessLimit) ** 3))\n}\n\n/** The part is reinforced for bending: a `reinforcement` cage or a `structure.rebar` ratio. */\nexport const isReinforced = (part: PartSpec): boolean => !!part.reinforcement || (part.structure?.rebar?.ratio ?? 0) > 0\n\n/** The part's material is slender masonry or plain concrete (`strength.slender`, default: tagged `masonry` and not reinforced). */\nexport const isSlender = (part: PartSpec, material: MaterialDef): boolean =>\n material.strength?.slender ?? (!!material.tags?.includes('masonry') && !isReinforced(part))\n\n/** The part takes part in the bending model. */\nexport const isFlexural = (part: PartSpec, material: MaterialDef, options: Required<FlexureOptions>): boolean =>\n options.enabled && material.strength?.tensileMPa !== undefined && !!part.structure && options.roles.includes(part.structure.role) &&\n (part.structure.rebar !== undefined || options.scope === 'all' || (options.scope === 'reinforced' && !!part.reinforcement))\n\n/** A bending section: width `b`, depth `h` (along the bending), in metres. */\nexport interface BendSection {\n b: number\n h: number\n}\n\n/** Tension steel of a section: area in m², effective depth in m, yield in MPa. */\nexport interface TensionSteel {\n area: number\n d: number\n yieldMPa: number\n}\n\n/**\n * Tension steel of the part for a section of width `b` and depth `h`: from `structure.rebar` (`ratio * b * d`), else from the `reinforcement` cage\n * (a plate's grid: one bar every `spacing` across `b`; a long member: the bars of the perimeter on the tension face). Zero for plain concrete.\n */\nexport const tensionSteel = (part: PartSpec, dims: Vec3, section: BendSection, options: Required<FlexureOptions>): TensionSteel => {\n const rebar = part.structure?.rebar\n const cage = part.reinforcement\n const bar = rebar ? RATIO_BAR : cage?.diameter ?? RATIO_BAR\n const d = Math.max(0.01, section.h - (rebar?.cover ?? options.cover) - bar / 2)\n const yieldMPa = rebar?.yieldMPa ?? options.rebarYieldMPa\n if (rebar && rebar.ratio > 0) return { area: rebar.ratio * section.b * d, d, yieldMPa }\n if (!cage) return { area: 0, d, yieldMPa }\n const one = (Math.PI * cage.diameter * cage.diameter) / 4\n const count = isMember(dims) ? memberBarCount(section.b, cage.spacing) : section.b / cage.spacing\n return { area: one * count, d, yieldMPa }\n}\n\n/**\n * Moments of a section in N m: `cracking` (the concrete's), `steel` (what the tension steel gives once the concrete has cracked; 0 for plain\n * concrete), `ultimate` (what the uncracked section holds: the larger of the two) and `reinforced` (it has steel: when it fails it hinges and its bars\n * keep it in one piece; without steel it snaps).\n */\nexport interface SectionMoments {\n cracking: number\n steel: number\n ultimate: number\n reinforced: boolean\n}\n\nexport const sectionMoments = (material: MaterialDef, section: BendSection, steel: TensionSteel, options: Required<FlexureOptions>): SectionMoments => {\n const s = material.strength!\n const cracking = crackingMoment(s.tensileMPa ?? 0, section.b, section.h, options.crackFactor)\n const steelM = steelMoment(steel.area, steel.yieldMPa, steel.d, section.b, s.compressiveMPa, options)\n return { cracking, steel: steelM, ultimate: Math.max(cracking, steelM), reinforced: steelM > 0 }\n}\n\n/** Static moment in N m at mid-span of a span `L` under a uniform load `w` (N/m): `w L^2 / 8`. */\nexport const spanMoment = (w: number, span: number): number => (w * span * span) / 8\n\n/**\n * How a box part bends, in its own axes. A long member (beam) spans along `long` and bends about either cross axis; a plate (slab) spans in the plane\n * of `plane` and bends across its thickness `thin`. `gravity` is the axis the weight bends it along (the local axis closest to the vertical among those\n * it can bend along, when it is within 45 degrees of it; -1 for a plate standing on edge). `up` is the world vertical in the part's axes.\n */\nexport interface BendGeometry {\n dims: Vec3\n member: boolean\n /** Axes the span is measured along: `[long]` for a member, the two plane axes for a plate. */\n spanAxes: number[]\n /** Axes the part can bend along (its depth): the two cross axes of a member, the thickness of a plate. */\n depthAxes: number[]\n gravity: number\n up: Vec3\n}\n\nexport const bendGeometry = (part: PartSpec): BendGeometry => {\n const dims = shapeDims(part.shape)\n const member = isMember(dims)\n const q = quatFromEuler(...(part.rotation ?? [0, 0, 0]))\n const up = rotateVec(quat.conjugate(q), [0, 1, 0])\n let spanAxes: number[]\n let depthAxes: number[]\n if (member) {\n const long = dims.indexOf(Math.max(...dims))\n spanAxes = [long]\n depthAxes = [0, 1, 2].filter((i) => i !== long)\n } else {\n const thin = thinAxisOf(dims)\n spanAxes = [...planeAxes(thin)]\n depthAxes = [thin]\n }\n let gravity = -1\n for (const a of depthAxes) if (Math.abs(up[a]) > Math.SQRT1_2 && (gravity < 0 || Math.abs(up[a]) > Math.abs(up[gravity]))) gravity = a\n return { dims, member, spanAxes, depthAxes, gravity, up }\n}\n\n/** Width of the section that bends along `axis`: the other cross axis of a member, a strip of 1 m of a plate. */\nexport const sectionWidth = (g: BendGeometry, axis: number): number => (g.member ? g.dims[g.depthAxes.find((a) => a !== axis) ?? axis] : 1)\n\n/**\n * Uniform load in N per metre of span of the bending section when the part carries `load` kg: per metre of a member's length, per metre-wide strip\n * of a plate (its load per square metre times 1 m).\n */\nexport const lineLoad = (g: BendGeometry, load: number): number => {\n const area = g.member ? g.dims[g.spanAxes[0]!] : g.dims[g.spanAxes[0]!] * g.dims[g.spanAxes[1]!]\n return (load * GRAVITY) / Math.max(area, 1e-6)\n}\n\n/**\n * Span in metres from the regions the part rests on (`contacts`: boxes `[min, max]` in the part's axes): twice the farthest any point of the part\n * is from its nearest support, measured along the span axes as the largest of the per-axis gaps. Two walls 4 m apart give 4 m, four columns at the\n * corners of a 5 x 4 m panel give 5 m (the long way), a cantilever of 1.5 m gives 3 m (the same moment, `w c^2 / 2`). 0 without contacts.\n */\nexport const spanOf = (g: BendGeometry, contacts: ReadonlyArray<readonly [Vec3, Vec3]>, samples = 9): number => {\n if (contacts.length === 0) return 0\n const axes = g.spanAxes\n const steps = (a: number) => Array.from({ length: samples }, (_, i) => (i / (samples - 1) - 0.5) * g.dims[a])\n const us = steps(axes[0]!)\n const vs = axes.length > 1 ? steps(axes[1]!) : [0]\n let far = 0\n for (const u of us) for (const v of vs) {\n let near = Infinity\n for (const [lo, hi] of contacts) {\n let gap = 0\n const x = [u, v]\n axes.forEach((a, k) => (gap = Math.max(gap, lo[a] - x[k]!, x[k]! - hi[a], 0)))\n if (gap < near) near = gap\n }\n if (near > far) far = near\n }\n return 2 * far\n}\n\n/** Roles that carry bending by default. */\nexport const FLEXURAL_ROLES: readonly StructureRole[] = FLEXURE_DEFAULTS.roles\n\nexport interface BearingWallOptions {\n /** Storeys the wall carries, the ground floor included. */\n storeys: number\n /** Height of one storey in metres. */\n storeyHeight: number\n /** Load each floor puts on one metre of wall, in N/m (dead and live load of the floor's share). */\n floorLoad: number\n /** Material of the wall (default the built-in `brick`): `strength.compressiveMPa` and `density`. */\n material: Pick<MaterialDef, 'density' | 'strength'>\n /** Load factor (1.4: NBR 8681, permanent and variable loads). */\n loadFactor?: number\n /** Material factor (2.0: NBR 16868-1, masonry). */\n materialFactor?: number\n /** Thinnest bearing wall in metres (0.14: NBR 16868-1). */\n minThickness?: number\n /** Thicknesses are rounded up to this many metres (0.01). */\n step?: number\n masonry?: MasonryOptions\n}\n\n/**\n * Thickness of a bearing masonry wall storey by storey, ground floor first, as a designer sizes it: the load from the top down (every floor plus the\n * walls above, times `loadFactor`) within `fk / materialFactor` times the slenderness factor of each storey's wall. `Infinity` when a storey cannot be\n * carried at any thickness (the wall's own weight per storey already uses up the strength).\n */\nexport const bearingWallThickness = (options: BearingWallOptions): number[] => {\n const gf = options.loadFactor ?? 1.4\n const gm = options.materialFactor ?? 2\n const min = options.minThickness ?? 0.14\n const step = options.step ?? 0.01\n const fd = ((options.material.strength?.compressiveMPa ?? 0) * MPA) / gm\n const own = options.material.density * GRAVITY * options.storeyHeight\n const out: number[] = []\n let above = 0\n for (let i = 0; i < options.storeys; i++) {\n const n = above + options.floorLoad\n let t = min\n for (let k = 0; k < 60; k++) {\n const room = fd * slendernessFactor(options.storeyHeight, t, options.masonry) - gf * own\n if (room <= 0) {\n // too slender (or too weak) at this thickness: try a thicker wall, give up past 20 m\n t *= 1.25\n if (t > 20) {\n t = Infinity\n break\n }\n continue\n }\n const next = Math.max(min, (gf * n) / room)\n if (Math.abs(next - t) < 1e-5) break\n t = next\n }\n t = Number.isFinite(t) ? Math.ceil(t / step - 1e-9) * step : Infinity\n out.push(t)\n above = n + own * (Number.isFinite(t) ? t : 0)\n }\n return out.reverse()\n}\n","[\n { \"id\": \"rock\", \"kind\": \"rock\", \"allowableKPa\": 3000, \"spt\": 50, \"elasticMPa\": 10000, \"poisson\": 0.2, \"pile\": { \"tipKPa\": 9000, \"skinKPa\": 500 } },\n { \"id\": \"rock_fractured\", \"kind\": \"rock\", \"allowableKPa\": 1500, \"spt\": 50, \"elasticMPa\": 2000, \"poisson\": 0.25, \"pile\": { \"tipKPa\": 4500, \"skinKPa\": 300 } },\n { \"id\": \"gravel_dense\", \"kind\": \"gravel\", \"allowableKPa\": 600, \"spt\": 40, \"elasticMPa\": 132, \"poisson\": 0.3 },\n { \"id\": \"gravel_loose\", \"kind\": \"gravel\", \"allowableKPa\": 300, \"spt\": 8, \"elasticMPa\": 26, \"poisson\": 0.3 },\n { \"id\": \"sand_very_dense\", \"kind\": \"sand\", \"allowableKPa\": 500, \"spt\": 45, \"elasticMPa\": 120, \"poisson\": 0.3 },\n { \"id\": \"sand_dense\", \"kind\": \"sand\", \"allowableKPa\": 400, \"spt\": 25, \"elasticMPa\": 68, \"poisson\": 0.3 },\n { \"id\": \"sand_medium\", \"kind\": \"sand\", \"allowableKPa\": 200, \"spt\": 12, \"elasticMPa\": 32, \"poisson\": 0.3 },\n { \"id\": \"sand_loose\", \"kind\": \"sand\", \"allowableKPa\": 50, \"spt\": 3, \"elasticMPa\": 8, \"poisson\": 0.3 },\n { \"id\": \"silt_hard\", \"kind\": \"silt\", \"allowableKPa\": 300, \"spt\": 25, \"elasticMPa\": 44, \"poisson\": 0.35 },\n { \"id\": \"silt_stiff\", \"kind\": \"silt\", \"allowableKPa\": 200, \"spt\": 15, \"elasticMPa\": 26, \"poisson\": 0.35 },\n { \"id\": \"silt_medium\", \"kind\": \"silt\", \"allowableKPa\": 100, \"spt\": 8, \"elasticMPa\": 14, \"poisson\": 0.35 },\n { \"id\": \"clay_hard\", \"kind\": \"clay\", \"allowableKPa\": 300, \"spt\": 25, \"elasticMPa\": 35, \"poisson\": 0.4 },\n { \"id\": \"clay_stiff\", \"kind\": \"clay\", \"allowableKPa\": 200, \"spt\": 15, \"elasticMPa\": 21, \"poisson\": 0.4 },\n { \"id\": \"clay_medium\", \"kind\": \"clay\", \"allowableKPa\": 100, \"spt\": 8, \"elasticMPa\": 11, \"poisson\": 0.4 },\n { \"id\": \"clay_soft\", \"kind\": \"clay\", \"allowableKPa\": 30, \"spt\": 3, \"elasticMPa\": 4.2, \"poisson\": 0.4 },\n { \"id\": \"clay_very_soft\", \"kind\": \"clay\", \"allowableKPa\": 15, \"spt\": 1, \"elasticMPa\": 1.4, \"poisson\": 0.4 }\n]\n","import soilsJson from './data/soils.json'\nimport type { PileSpec, SoilDef, SoilKind, SoilOptions, SoilProfile } from './types'\n\n/**\n * Soil and foundations. A footing bears on the soil under it as a bed of springs (the subgrade modulus of the elastic settlement of a rigid footing)\n * that give way at the soil's bearing capacity; a pile carries its load by end bearing and skin friction (Décourt-Quaresma) and gives way when the\n * load passes them. The whole object rests on those springs as a rigid body: it settles, leans with the out-of-plumb of the building and with its\n * own weight moving over as it leans (P-delta), and, when the springs cannot hold it, it keeps sinking and leaning until its centre of mass passes\n * the edge of its foundations and it tips over.\n */\n\n/** Built-in soil classes (data in `src/data/soils.json`): NBR 6122 basic pressures, SPT N, moduli from Teixeira & Godoy. */\nexport const SOILS: readonly SoilDef[] = soilsJson as SoilDef[]\n\nexport const SOIL_DEFAULTS = {\n safety: 3,\n pileSafety: 2,\n rigidity: 0.82,\n influence: 2,\n imperfection: 1 / 200,\n cells: 4,\n sinkRate: 0.05,\n tiltRate: 1.5,\n pileElasticGPa: 25,\n footingWidth: 0.6,\n} as const\n\nexport type ResolvedSoil = Required<Omit<SoilOptions, 'soils' | 'site'>> & { site?: string | SoilProfile; byId: Map<string, SoilDef> }\n\nexport const resolveSoil = (o: SoilOptions = {}): ResolvedSoil => {\n const byId = new Map(SOILS.map((s) => [s.id, s]))\n for (const s of o.soils ?? []) byId.set(s.id, s)\n const { soils: _soils, site, ...rest } = o\n return { ...SOIL_DEFAULTS, ...rest, ...(site !== undefined ? { site } : {}), byId }\n}\n\n/** A profile from a soil class id or a profile. */\nexport const profileOf = (soil: string | SoilProfile): SoilProfile => (typeof soil === 'string' ? { layers: [{ soil }] } : soil)\n\n/** The layers of a profile that lie between two depths (metres below the surface), with the thickness of each inside that range. */\nexport const layersBetween = (profile: SoilProfile, top: number, bottom: number, soils: ReadonlyMap<string, SoilDef>): Array<{ soil: SoilDef; thickness: number; top: number }> => {\n const out: Array<{ soil: SoilDef; thickness: number; top: number }> = []\n let z = 0\n const layers = profile.layers\n for (let i = 0; i < layers.length; i++) {\n const def = soils.get(layers[i].soil)\n if (!def) throw new Error(`unknown soil \"${layers[i].soil}\"`)\n const last = i === layers.length - 1\n const end = last ? Infinity : z + Math.max(0, layers[i].thickness ?? 0)\n const a = Math.max(z, top), b = Math.min(end, bottom)\n if (b > a) out.push({ soil: def, thickness: b - a, top: a })\n z = end\n if (z >= bottom) break\n }\n return out\n}\n\n/** The soil class at a depth (metres below the surface). */\nexport const soilAt = (profile: SoilProfile, depth: number, soils: ReadonlyMap<string, SoilDef>): SoilDef => {\n let z = 0\n for (let i = 0; i < profile.layers.length; i++) {\n const def = soils.get(profile.layers[i].soil)\n if (!def) throw new Error(`unknown soil \"${profile.layers[i].soil}\"`)\n z += Math.max(0, profile.layers[i].thickness ?? 0)\n if (i === profile.layers.length - 1 || depth < z) return def\n }\n throw new Error('a soil profile needs at least one layer')\n}\n\n/** The soil a footing of width `width` at `depth` bears on: the weakest allowable pressure and the mean modulus over `influence` widths below it. */\nexport const footingSoil = (profile: SoilProfile, depth: number, width: number, soils: ReadonlyMap<string, SoilDef>, influence: number = SOIL_DEFAULTS.influence) => {\n const zone = layersBetween(profile, depth, depth + Math.max(0.01, influence * width), soils)\n let allowable = Infinity, e = 0, nu = 0, t = 0\n for (const l of zone) {\n allowable = Math.min(allowable, l.soil.allowableKPa)\n e += l.soil.elasticMPa * l.thickness\n nu += l.soil.poisson * l.thickness\n t += l.thickness\n }\n if (t <= 0) {\n const l = soilAt(profile, depth, soils)\n return { allowableKPa: l.allowableKPa, elasticMPa: l.elasticMPa, poisson: l.poisson }\n }\n return { allowableKPa: allowable, elasticMPa: e / t, poisson: nu / t }\n}\n\n/** Décourt-Quaresma coefficient C of the end bearing in kPa per blow (clay 120, silt 200, sand and gravel 400). */\nconst DQ_C: Record<SoilKind, number> = { clay: 120, silt: 200, sand: 400, gravel: 400, rock: 400 }\n/** Décourt (1996) factors of a bored pile on the end bearing (alpha) and the skin friction (beta); a driven pile has 1 and 1. */\nconst BORED: Record<SoilKind, { alpha: number; beta: number }> = {\n clay: { alpha: 0.85, beta: 0.8 },\n silt: { alpha: 0.6, beta: 0.65 },\n sand: { alpha: 0.5, beta: 0.5 },\n gravel: { alpha: 0.5, beta: 0.5 },\n rock: { alpha: 1, beta: 1 },\n}\nconst clampN = (n: number) => Math.min(50, Math.max(3, n))\n\n/**\n * Ultimate resistance of one pile in newtons, by Décourt-Quaresma: end bearing `alpha C N A` at the tip and skin friction `beta 10 (N/3 + 1)` kPa\n * along the shaft in each layer (N limited to 3..50). Rock with `pile` resistances uses those instead. `top` is the depth of the pile head.\n */\nexport const pileCapacity = (profile: SoilProfile, pile: PileSpec, top: number, soils: ReadonlyMap<string, SoilDef>) => {\n const d = pile.diameter\n const area = (Math.PI * d * d) / 4\n const perimeter = Math.PI * d\n const driven = pile.method === 'driven'\n let skin = 0\n for (const l of layersBetween(profile, top, top + pile.length, soils)) {\n const f = driven ? 1 : BORED[l.soil.kind].beta\n const kPa = l.soil.pile?.skinKPa ?? f * 10 * (clampN(l.soil.spt) / 3 + 1)\n skin += kPa * 1000 * perimeter * l.thickness\n }\n const tipDepth = top + pile.length\n const tipSoil = soilAt(profile, tipDepth, soils)\n const alpha = driven ? 1 : BORED[tipSoil.kind].alpha\n const tipKPa = tipSoil.pile?.tipKPa ?? alpha * DQ_C[tipSoil.kind] * clampN(tipSoil.spt)\n const tip = tipKPa * 1000 * area\n return { tip, skin, ultimate: tip + skin, tipSoil }\n}\n\n/**\n * The shortest pile (to `step` metres) whose ultimate resistance over `safety` carries `load` newtons, going down from `top`; `maxLength` if none.\n * This is how a designer takes a pile down to firm ground.\n */\nexport const pileLength = (profile: SoilProfile, o: { load: number; diameter: number; top?: number; method?: PileSpec['method']; safety?: number; step?: number; maxLength?: number; soils?: ReadonlyMap<string, SoilDef> }): number => {\n const soils = o.soils ?? resolveSoil().byId\n const safety = o.safety ?? SOIL_DEFAULTS.pileSafety\n const step = o.step ?? 0.5\n const max = o.maxLength ?? 60\n for (let L = step; L <= max + 1e-9; L += step) {\n if (pileCapacity(profile, { length: L, diameter: o.diameter, ...(o.method ? { method: o.method } : {}) }, o.top ?? 0, soils).ultimate / safety >= o.load) return Math.round(L / step) * step\n }\n return max\n}\n\n/** Stiffness of one pile in N/m: the shaft shortens under the mean of its force (`L / (2 E A)`) in series with the tip as a rigid plate (`E d / (1 - nu^2)`). */\nexport const pileStiffness = (pile: PileSpec, pileElasticGPa: number, tipElasticMPa: number, tipPoisson: number): number => {\n const area = (Math.PI * pile.diameter * pile.diameter) / 4\n const shaft = pile.length / (2 * pileElasticGPa * 1e9 * area)\n const tip = (1 - tipPoisson * tipPoisson) / (tipElasticMPa * 1e6 * pile.diameter)\n return 1 / (shaft + tip)\n}\n\n/** Subgrade modulus in Pa/m of a rigid footing of width `width`: `E / (B (1 - nu^2) Iw)`, the elastic settlement of the footing as springs. */\nexport const subgradeModulus = (elasticMPa: number, poisson: number, width: number, rigidity: number = SOIL_DEFAULTS.rigidity): number =>\n (elasticMPa * 1e6) / (Math.max(0.05, width) * (1 - poisson * poisson) * rigidity)\n\n/**\n * Thickness-free design check of a shallow footing: the area a load of `load` newtons needs on `soil` (allowable pressure), as a designer sizes it.\n */\nexport const footingArea = (load: number, allowableKPa: number): number => load / (allowableKPa * 1000)\n\n/** One support of the object on the ground: a footing cell or a pile, at object-local `x, z`, `hx`/`hz` half its size. */\nexport interface SoilSpring {\n x: number\n z: number\n hx: number\n hz: number\n /** N/m. */\n k: number\n /** Newtons it carries before it gives way. */\n cap: number\n /** Permanent settlement of the soil under it from yielding, metres: it pushes back only past this (default 0). */\n set?: number\n}\n\n/** The springs' permanent settlement after the base moved to `(s, a, b)`: a spring pushed past its capacity keeps the extra (return mapping). */\nexport const yieldSprings = (springs: readonly SoilSpring[], s: number, a: number, b: number): number[] => {\n const [x0, z0] = stiffnessCentre(springs)\n return springs.map((sp) => {\n const set = sp.set ?? 0\n const w = s + a * (sp.x - x0) + b * (sp.z - z0)\n return sp.k * (w - set) > sp.cap ? w - sp.cap / sp.k : set\n })\n}\n\nexport interface FoundationSolve {\n /** Settlement at the centre of stiffness, metres. */\n s: number\n /** Slopes of the base: the foundations go down `a` per metre of x and `b` per metre of z. */\n a: number\n b: number\n /** An equilibrium was found and it is stable. */\n stable: boolean\n /** Some spring is at its capacity in that equilibrium. */\n yielded: boolean\n /** Weight over the sum of the capacities. */\n bearing: number\n /** Largest force over capacity of a spring, 0..1. */\n edge: number\n /** Residual of the vertical force and moments at the end, to tell which way an unstable object moves. */\n residual: [number, number, number]\n}\n\n/** Centre of stiffness of the springs. */\nexport const stiffnessCentre = (springs: readonly SoilSpring[]): [number, number] => {\n let k = 0, x = 0, z = 0\n for (const s of springs) {\n k += s.k\n x += s.k * s.x\n z += s.k * s.z\n }\n return k > 0 ? [x / k, z / k] : [0, 0]\n}\n\n/** Solves `J d = r` for a symmetric 3x3 by Cholesky; null when `J` is not positive definite. */\nconst cholesky3 = (J: number[][], r: number[]): number[] | null => {\n const L = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]\n for (let i = 0; i < 3; i++) {\n for (let j = 0; j <= i; j++) {\n let sum = J[i][j]\n for (let k = 0; k < j; k++) sum -= L[i][k] * L[j][k]\n if (i === j) {\n if (!(sum > 1e-9 * Math.max(1, Math.abs(J[i][i])))) return null\n L[i][i] = Math.sqrt(sum)\n } else L[i][j] = sum / L[j][j]\n }\n }\n const y = [0, 0, 0]\n for (let i = 0; i < 3; i++) {\n let sum = r[i]\n for (let k = 0; k < i; k++) sum -= L[i][k] * y[k]\n y[i] = sum / L[i][i]\n }\n const x = [0, 0, 0]\n for (let i = 2; i >= 0; i--) {\n let sum = y[i]\n for (let k = i + 1; k < 3; k++) sum -= L[k][i] * x[k]\n x[i] = sum / L[i][i]\n }\n return x\n}\n\n/**\n * Equilibrium of a rigid object of weight `weight` (N) on elastic-perfectly-plastic springs that carry no tension, with its centre of mass at\n * `(xg, zg)` and `height` metres above the base, leaning `imperfection` (radians, x and z) before any load and moving over as it leans (P-delta).\n * Newton iterations from `start`; where the tangent is not positive definite the elastic stiffness of the springs in contact is used instead.\n */\nexport const solveFoundation = (\n springs: readonly SoilSpring[],\n weight: number,\n xg: number,\n zg: number,\n height: number,\n imperfection: readonly [number, number],\n start: { s: number; a: number; b: number } = { s: 0, a: 0, b: 0 },\n): FoundationSolve => {\n const [x0, z0] = stiffnessCentre(springs)\n const capSum = springs.reduce((sum, s) => sum + s.cap, 0)\n const span = Math.max(1, ...springs.map((s) => Math.max(Math.abs(s.x - x0) + s.hx, Math.abs(s.z - z0) + s.hz)))\n let s = start.s, a = start.a, b = start.b\n // from a base that touches nothing, start at the elastic settlement of the whole bed\n if (springs.every((sp) => s + a * (sp.x - x0) + b * (sp.z - z0) - (sp.set ?? 0) <= 0)) {\n s = weight / Math.max(1e-9, springs.reduce((sum, sp) => sum + sp.k, 0))\n a = b = 0\n }\n const Wh = weight * height\n const evaluate = () => {\n let F = 0, Mx = 0, Mz = 0, edge = 0, yielded = false\n const Jt = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]\n const Je = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]\n const add = (J: number[][], k: number, dx: number, dz: number) => {\n J[0][0] += k; J[0][1] += k * dx; J[0][2] += k * dz\n J[1][1] += k * dx * dx; J[1][2] += k * dx * dz; J[2][2] += k * dz * dz\n }\n for (const sp of springs) {\n const dx = sp.x - x0, dz = sp.z - z0\n const w = s + a * dx + b * dz - (sp.set ?? 0)\n if (w <= 0) continue\n const f = sp.k * w\n add(Je, sp.k, dx, dz)\n let force = f\n if (f >= sp.cap) {\n force = sp.cap\n yielded = true\n } else add(Jt, sp.k, dx, dz)\n edge = Math.max(edge, force / sp.cap)\n F += force\n Mx += force * dx\n Mz += force * dz\n }\n for (const J of [Jt, Je]) {\n J[1][0] = J[0][1]; J[2][0] = J[0][2]; J[2][1] = J[1][2]\n J[1][1] -= Wh; J[2][2] -= Wh\n }\n const r = [weight - F, weight * (xg - x0 + height * (a + imperfection[0])) - Mx, weight * (zg - z0 + height * (b + imperfection[1])) - Mz]\n return { r, Jt, Je, edge, yielded }\n }\n let ev = evaluate()\n let converged = false\n const tol = 1e-7 * weight\n for (let it = 0; it < 120; it++) {\n if (Math.abs(ev.r[0]) < tol && Math.abs(ev.r[1]) < tol * span && Math.abs(ev.r[2]) < tol * span) {\n converged = true\n break\n }\n const d = cholesky3(ev.Jt, ev.r) ?? cholesky3(ev.Je, ev.r)\n if (!d) break\n s += d[0]\n a += d[1]\n b += d[2]\n if (!Number.isFinite(s + a + b) || Math.abs(a) > 2 || Math.abs(b) > 2) break\n ev = evaluate()\n }\n // a stable equilibrium keeps a positive definite tangent: with every spring under one side yielding the object has nothing left to stop it\n const stable = converged && cholesky3(ev.Jt, [0, 0, 0]) !== null\n return { s, a, b, stable, yielded: ev.yielded, bearing: capSum > 0 ? weight / capSum : Infinity, edge: ev.edge, residual: [ev.r[0], ev.r[1], ev.r[2]] }\n}\n","[\n { \"id\": \"I\", \"zg\": 250, \"b\": { \"A\": 1.1, \"B\": 1.11, \"C\": 1.12 }, \"p\": { \"A\": 0.06, \"B\": 0.065, \"C\": 0.07 }, \"z0\": 0.005 },\n { \"id\": \"II\", \"zg\": 300, \"b\": { \"A\": 1.0, \"B\": 1.0, \"C\": 1.0 }, \"p\": { \"A\": 0.085, \"B\": 0.09, \"C\": 0.1 }, \"z0\": 0.05 },\n { \"id\": \"III\", \"zg\": 350, \"b\": { \"A\": 0.94, \"B\": 0.94, \"C\": 0.93 }, \"p\": { \"A\": 0.1, \"B\": 0.105, \"C\": 0.115 }, \"z0\": 0.3 },\n { \"id\": \"IV\", \"zg\": 420, \"b\": { \"A\": 0.86, \"B\": 0.85, \"C\": 0.84 }, \"p\": { \"A\": 0.12, \"B\": 0.125, \"C\": 0.135 }, \"z0\": 1.0 },\n { \"id\": \"V\", \"zg\": 500, \"b\": { \"A\": 0.74, \"B\": 0.73, \"C\": 0.71 }, \"p\": { \"A\": 0.15, \"B\": 0.16, \"C\": 0.175 }, \"z0\": 2.5 }\n]\n","import windTerrainJson from './data/wind-terrain.json'\nimport { GRAVITY } from './flexure'\nimport { createRng } from './math'\nimport { thinAxisOf } from './layers'\nimport { verticalBarCount } from './rebar'\nimport type { Vec3, WindExposure, WindOptions, WindTerrainDef } from './types'\n\n/**\n * Wind on a building. The wind pressure grows with the height (NBR 6123), the building is cut into storey-high bands, each band takes the force of\n * its area, and the structure that resists it is the walls (a cantilever of composite section) working with the frame (storey shear stiffness) as\n * the wall-frame interaction of Heidebrecht & Stafford Smith. The same stiffness gives the first mode (Rayleigh), and a gust series moves the top\n * against it, with a tuned mass damper if there is one. Pure formulas in SI units (N, m, Pa, s); the world calls them with the parts' boxes.\n */\n\n/** Built-in terrain categories (data in `src/data/wind-terrain.json`): NBR 6123 table 1 and the roughness lengths. */\nexport const WIND_TERRAIN: readonly WindTerrainDef[] = windTerrainJson as WindTerrainDef[]\n\nexport const WIND_DEFAULTS = {\n speed: 40,\n direction: [1, 0, 0] as Vec3,\n terrain: 'III' as NonNullable<WindExposure['terrain']>,\n class: 'auto' as NonNullable<WindExposure['class']>,\n topography: 1,\n statistical: 1,\n drag: 1.3,\n damping: 0.016,\n airDensity: 1.226,\n minHeight: 5,\n bandHeight: 3,\n stiffnessFactor: 0.8,\n beamFactor: 0.4,\n flange: 0.1,\n driftLimit: 1 / 500,\n loadFactor: 1.4,\n chord: false,\n meanRatio: 0.69,\n gustFactor: { A: 1, B: 0.98, C: 0.95 },\n gust: { components: 400, maxHz: 2, scale: 1200, seed: 1 },\n peakDecay: 60,\n tuning: 'den-hartog' as NonNullable<WindOptions['tuning']>,\n} as const\n\nexport type ResolvedWind = Required<Omit<WindOptions, 'terrains' | 'gustFactor' | 'gust' | 'direction'>> & {\n direction: Vec3\n gustFactor: { A: number; B: number; C: number }\n gust: { components: number; maxHz: number; scale: number; seed: number }\n terrains: Map<string, WindTerrainDef>\n}\n\nconst definedOf = <T extends object>(o?: T): Partial<T> => Object.fromEntries(Object.entries(o ?? {}).filter(([, v]) => v !== undefined)) as Partial<T>\n\nexport const resolveWind = (o: WindOptions = {}): ResolvedWind => {\n const terrains = new Map(WIND_TERRAIN.map((t) => [t.id, t]))\n for (const t of o.terrains ?? []) terrains.set(t.id, t)\n const { terrains: _terrains, gustFactor, gust, ...rest } = o\n return {\n ...WIND_DEFAULTS,\n ...definedOf(rest),\n direction: o.direction ?? WIND_DEFAULTS.direction,\n gustFactor: { ...WIND_DEFAULTS.gustFactor, ...definedOf(gustFactor) },\n gust: { ...WIND_DEFAULTS.gust, ...definedOf(gust) },\n terrains,\n }\n}\n\n/** The world's wind with one object's `DestructibleSpec.wind` over it. */\nexport const exposureOf = (w: ResolvedWind, spec?: WindExposure | false): ResolvedWind => (spec ? { ...w, ...definedOf(spec) } : w)\n\n// ---------------------------------------------------------------------------------------------------------------------------------------------\n// Pressure and profile\n// ---------------------------------------------------------------------------------------------------------------------------------------------\n\n/** Dynamic pressure in N/m² of a wind of `speed` m/s: `q = rho V^2 / 2`, which is `0.613 V^2` for the air at 15 °C (NBR 6123 4.2). */\nexport const windPressure = (speed: number, density: number = WIND_DEFAULTS.airDensity): number => 0.5 * density * speed * speed\n\n/** Class of a building by its largest dimension (NBR 6123 table 1): `A` up to 20 m, `B` up to 50 m, `C` above. */\nexport const windClass = (largest: number): 'A' | 'B' | 'C' => (largest <= 20 ? 'A' : largest <= 50 ? 'B' : 'C')\n\n/**\n * Height factor of the gust `S2 = b * Fr * (z / 10)^p` (NBR 6123 5.3), `z` in metres above the ground: at least `minHeight` and at most the gradient\n * height of the category.\n */\nexport const heightFactor = (z: number, terrain: WindTerrainDef, cls: 'A' | 'B' | 'C', o: { gustFactor?: { A: number; B: number; C: number }; minHeight?: number } = {}): number => {\n const zz = Math.min(terrain.zg, Math.max(o.minHeight ?? WIND_DEFAULTS.minHeight, z))\n return terrain.b[cls] * (o.gustFactor ?? WIND_DEFAULTS.gustFactor)[cls] * (zz / 10) ** terrain.p[cls]\n}\n\n/** The same profile for the 10-minute mean wind: no gust factor, times `meanRatio` (the share of the gust the mean is). */\nexport const meanHeightFactor = (z: number, terrain: WindTerrainDef, cls: 'A' | 'B' | 'C', o: { meanRatio?: number; minHeight?: number } = {}): number =>\n (o.meanRatio ?? WIND_DEFAULTS.meanRatio) * heightFactor(z, terrain, cls, { gustFactor: { A: 1, B: 1, C: 1 }, ...(o.minHeight !== undefined ? { minHeight: o.minHeight } : {}) })\n\n/** Turbulence intensity at `z` over terrain of roughness length `z0`: `1 / ln(z / z0)` (EN 1991-1-4 4.4), no more than 0.5. */\nexport const turbulenceIntensity = (z: number, z0: number): number => Math.min(0.5, 1 / Math.log(Math.max(z, 1.5 * z0) / z0))\n\n// ---------------------------------------------------------------------------------------------------------------------------------------------\n// Wall-frame cantilever\n// ---------------------------------------------------------------------------------------------------------------------------------------------\n\nexport interface WallFrameSolution {\n /** Rotation `w'` at the n + 1 nodes. */\n psi: number[]\n /** Deflection at the nodes (0 at the base). */\n w: number[]\n}\n\n/**\n * A cantilever with bending stiffness `ei[j]` (N m²) and shear stiffness `ga[j]` (N) in each band of height `hb[j]`, loaded by the shear `V` at the\n * n + 1 nodes (from the base up; `V[n]` is the shear at the top, 0 when nothing hangs there). The wall and the frame share the load as\n * `-(EI psi')' + GA psi = V`, `psi(0) = 0` (as far as there is a wall), zero moment at the top: linear elements, one per band, a tridiagonal system. Without the frame\n * (`ga` 0) it is the bending cantilever (`w = w H^4 / (8 EI)` for a uniform load), without the wall (`ei` 0) the shear beam (`w' = V / GA`).\n */\nexport const solveWallFrame = (hb: readonly number[], ei: readonly number[], ga: readonly number[], V: readonly number[]): WallFrameSolution => {\n const n = hb.length\n const diag = new Array<number>(n + 1).fill(0)\n const off = new Array<number>(n).fill(0)\n const rhs = new Array<number>(n + 1).fill(0)\n for (let j = 0; j < n; j++) {\n const h = hb[j], e = ei[j], g = ga[j]\n diag[j] += e / h + (g * h) / 3\n diag[j + 1] += e / h + (g * h) / 3\n off[j] = -e / h + (g * h) / 6\n rhs[j] += (h / 6) * (2 * V[j] + V[j + 1])\n rhs[j + 1] += (h / 6) * (V[j] + 2 * V[j + 1])\n }\n // the wall is clamped at the base (psi = 0) as far as there is a wall: a stiff spring on the base node whose weight is the wall's share of the\n // stiffness over one band, so a frame alone is not held back by a boundary layer that no band resolves\n const wall = ei[0] / (ei[0] + ga[0] * hb[0] * hb[0])\n diag[0] += 1e6 * (ei[0] / hb[0] + ga[0] * hb[0]) * wall\n // Thomas algorithm on the nodes 0..n\n const c = new Array<number>(n + 1).fill(0)\n const d = new Array<number>(n + 1).fill(0)\n const psi = new Array<number>(n + 1).fill(0)\n c[0] = off[0] / diag[0]\n d[0] = rhs[0] / diag[0]\n for (let i = 1; i <= n; i++) {\n const m = diag[i] - off[i - 1] * c[i - 1]\n c[i] = i < n ? off[i] / m : 0\n d[i] = (rhs[i] - off[i - 1] * d[i - 1]) / m\n }\n psi[n] = d[n]\n for (let i = n - 1; i >= 0; i--) psi[i] = d[i] - c[i] * psi[i + 1]\n const w = new Array<number>(n + 1).fill(0)\n for (let j = 0; j < n; j++) w[j + 1] = w[j] + (hb[j] * (psi[j] + psi[j + 1])) / 2\n return { psi, w }\n}\n\n/** Shear at the n + 1 nodes of loads `f[j]` spread over each band (the load of the bands above, from the top). */\nexport const shearNodes = (f: readonly number[]): number[] => {\n const V = new Array<number>(f.length + 1).fill(0)\n for (let j = f.length - 1; j >= 0; j--) V[j] = V[j + 1] + f[j]\n return V\n}\n\n/** Moment at the n + 1 nodes from the shear at the nodes (linear inside each band, so the trapezoid is exact). */\nexport const momentNodes = (hb: readonly number[], V: readonly number[]): number[] => {\n const M = new Array<number>(V.length).fill(0)\n for (let j = hb.length - 1; j >= 0; j--) M[j] = M[j + 1] + (hb[j] * (V[j] + V[j + 1])) / 2\n return M\n}\n\n// ---------------------------------------------------------------------------------------------------------------------------------------------\n// Analysis of a building\n// ---------------------------------------------------------------------------------------------------------------------------------------------\n\n/** Factor on the stiffness of the bands above the lateral system, which move as a rigid body with its top. */\nconst RIGID = 1e3\n\nexport interface WindPartInput {\n /** Object-local box of the part (`aabbOf`). */\n min: Vec3\n max: Vec3\n /** `wall` and `column` resist, `beam` frames into the columns, `foundation` is the footprint, `other` only weighs and shows area. */\n kind: 'wall' | 'column' | 'beam' | 'foundation' | 'other'\n /** Young's modulus in Pa (walls, columns, beams). */\n elasticPa?: number\n /** Mass in kg (what rests on it is counted by the parts that rest). */\n mass: number\n /** A tuned mass damper: weighs, but is not part of the modal mass of the building. */\n damper?: boolean\n /** Indices of the beams that frame into this column (closed joints). */\n beams?: readonly number[]\n /** Thickness of the slab that rests on this beam and works with it as a T section (0: none). */\n slab?: number\n}\n\n/** Everything `analyzeWind` needs once it is resolved for one building (`ResolvedWind` with its terrain and direction). */\nexport interface WindCase {\n speed: number\n /** Horizontal unit vector the wind blows towards, object-local `[x, z]`. */\n direction: readonly [number, number]\n terrain: WindTerrainDef\n cls: 'auto' | 'A' | 'B' | 'C'\n topography: number\n statistical: number\n drag: number\n damping: number\n airDensity: number\n minHeight: number\n bandHeight: number\n stiffnessFactor: number\n beamFactor: number\n flange: number\n loadFactor: number\n chord: boolean\n meanRatio: number\n gustFactor: { A: number; B: number; C: number }\n}\n\nexport interface WindAnalysis {\n /** Height of the top above the ground and the class used. */\n height: number\n cls: 'A' | 'B' | 'C'\n /** Largest width across the wind. */\n width: number\n /** Band heights and the height of the middle of each above the ground. */\n bands: number[]\n mid: number[]\n /** Design force on each band, N, and the force of the 10-minute mean wind. */\n forces: number[]\n meanForces: number[]\n /** Design pressure at the top, N/m². */\n pressure: number\n /** Design base shear (N) and overturning moment (N m). */\n shear: number\n moment: number\n /** Top deflection under the design wind (m), over the height, and under the mean wind. */\n deflection: number\n drift: number\n lean: number\n /** Weight, N, and the overturning moment (factored) over the stabilizing moment `W e`. */\n weight: number\n overturn: number\n /** Share of the base moment the walls carry (the rest is the frame's couple). */\n wallShare: number\n /** Bending and shear stiffness of each band (cracked). */\n ei: number[]\n ga: number[]\n /** First mode (Rayleigh): frequency in Hz, angular frequency, modal mass and stiffness, shape at the nodes. */\n frequency: number\n omega: number\n modalMass: number\n modalStiffness: number\n shape: { z: number[]; phi: number[] }\n /** Modal force of the mean wind, N; turbulence intensity for the gust. */\n modalForce: number\n intensity: number\n /** Axial force the design wind adds to each input part, N (compression positive), without the load factor. */\n axial: number[]\n}\n\n/**\n * Second moment of area of a beam of web `bw` and depth `h` with a slab flange of width `bf` and thickness `tf` on top (a T section, about its own\n * centroid); the web alone when there is no flange.\n */\nexport const tBeamInertia = (bw: number, h: number, bf: number, tf: number): number => {\n const web = bw * h\n const fl = Math.max(0, bf - bw) * Math.min(tf, h)\n const t = Math.min(tf, h)\n const yc = (web * (h / 2) + fl * (h - t / 2)) / (web + fl)\n return (bw * h ** 3) / 12 + web * (h / 2 - yc) ** 2 + (Math.max(0, bf - bw) * t ** 3) / 12 + fl * (h - t / 2 - yc) ** 2\n}\n\n/** The shape of the first mode at height `z` above the ground (linear between the nodes). */\nexport const shapeAt = (a: Pick<WindAnalysis, 'shape'>, z: number): number => {\n const { z: zs, phi } = a.shape\n if (z <= zs[0]) return phi[0]\n for (let i = 1; i < zs.length; i++) if (z <= zs[i]) return phi[i - 1] + ((phi[i] - phi[i - 1]) * (z - zs[i - 1])) / (zs[i] - zs[i - 1])\n return phi[phi.length - 1]\n}\n\n/**\n * Wind on a building of `parts` standing on the ground at `ground` (the y of the top of the foundations). Null when it has no wall or column.\n * Bands of `bandHeight`; a part gives to a band the share of itself that lies inside it.\n */\nexport const analyzeWind = (parts: readonly WindPartInput[], c: WindCase, ground: number): WindAnalysis | null => {\n const [dx, dz] = c.direction\n const along = (p: WindPartInput) => {\n const cx = (p.min[0] + p.max[0]) / 2, cz = (p.min[2] + p.max[2]) / 2\n const hx = (p.max[0] - p.min[0]) / 2, hz = (p.max[2] - p.min[2]) / 2\n return {\n u: cx * dx + cz * dz, v: -cx * dz + cz * dx,\n du: 2 * (Math.abs(dx) * hx + Math.abs(dz) * hz), dv: 2 * (Math.abs(dz) * hx + Math.abs(dx) * hz),\n }\n }\n const g = parts.map(along)\n let topY = ground\n let resists = false\n for (const p of parts) {\n if (p.kind === 'foundation') continue\n topY = Math.max(topY, p.max[1])\n if ((p.kind === 'wall' || p.kind === 'column') && p.elasticPa) resists = true\n }\n const height = topY - ground\n if (!(height > 0) || !resists) return null\n const n = Math.max(1, Math.ceil(height / c.bandHeight - 1e-9))\n const bands = Array.from({ length: n }, (_, j) => Math.min(c.bandHeight, height - j * c.bandHeight))\n const z0 = Array.from({ length: n }, (_, j) => j * c.bandHeight)\n const mid = bands.map((h, j) => z0[j] + h / 2)\n const share = (p: WindPartInput, j: number): number => {\n const a = Math.max(p.min[1] - ground, z0[j]), b = Math.min(p.max[1] - ground, z0[j] + bands[j])\n return Math.max(0, b - a)\n }\n\n // the building across the wind, the weight and the section of walls and columns\n const vmin = new Array<number>(n).fill(Infinity), vmax = new Array<number>(n).fill(-Infinity)\n const mass = new Array<number>(n).fill(0)\n let weight = 0, wu = 0\n let footEnd = -Infinity\n let anyFoundation = false\n for (let i = 0; i < parts.length; i++) {\n const p = parts[i]\n weight += p.mass * GRAVITY\n wu += p.mass * g[i].u\n if (p.kind === 'foundation') {\n anyFoundation = true\n footEnd = Math.max(footEnd, g[i].u + g[i].du / 2)\n continue\n }\n const full = Math.max(1e-6, p.max[1] - p.min[1])\n for (let j = 0; j < n; j++) {\n const ov = share(p, j)\n if (ov <= 0) continue\n vmin[j] = Math.min(vmin[j], g[i].v - g[i].dv / 2)\n vmax[j] = Math.max(vmax[j], g[i].v + g[i].dv / 2)\n if (!p.damper) mass[j] += (p.mass * ov) / full\n }\n }\n if (!anyFoundation) for (let i = 0; i < parts.length; i++) if (parts[i].min[1] - ground < 0.1) footEnd = Math.max(footEnd, g[i].u + g[i].du / 2)\n const totalMass = weight / GRAVITY\n const uCg = totalMass > 0 ? wu / totalMass : 0\n const width = vmax.map((hi, j) => (hi > vmin[j] ? hi - vmin[j] : 0))\n const widest = Math.max(...width)\n const cls = c.cls === 'auto' ? windClass(Math.max(height, widest)) : c.cls\n\n // forces on the bands\n const k0 = c.speed * c.topography * c.statistical\n const pressure = mid.map((z) => windPressure(k0 * heightFactor(z, c.terrain, cls, { gustFactor: c.gustFactor, minHeight: c.minHeight }), c.airDensity))\n const meanPressure = mid.map((z) => windPressure(k0 * meanHeightFactor(z, c.terrain, cls, { meanRatio: c.meanRatio, minHeight: c.minHeight }), c.airDensity))\n const forces = bands.map((h, j) => pressure[j] * c.drag * width[j] * h)\n const meanForces = bands.map((h, j) => meanPressure[j] * c.drag * width[j] * h)\n const V = shearNodes(forces)\n const M = momentNodes(bands, V)\n\n // the lateral system: walls as one section, columns as a shear frame\n const ea = new Array<number>(n).fill(0), eau = new Array<number>(n).fill(0)\n const vertical: number[] = []\n for (let i = 0; i < parts.length; i++) {\n const p = parts[i]\n if ((p.kind !== 'wall' && !(p.kind === 'column' && c.chord)) || !p.elasticPa) continue\n vertical.push(i)\n const area = g[i].du * g[i].dv\n const e = p.elasticPa * c.stiffnessFactor\n for (let j = 0; j < n; j++) {\n const w = share(p, j) / bands[j]\n if (w <= 0) continue\n ea[j] += e * area * w\n eau[j] += e * area * g[i].u * w\n }\n }\n const centre = ea.map((v, j) => (v > 0 ? eau[j] / v : 0))\n const ei = new Array<number>(n).fill(0)\n const ga = new Array<number>(n).fill(0)\n for (const i of vertical) {\n const p = parts[i]\n const e = p.elasticPa! * c.stiffnessFactor\n for (let j = 0; j < n; j++) {\n const w = share(p, j) / bands[j]\n if (w <= 0) continue\n ei[j] += e * ((g[i].du ** 3 * g[i].dv) / 12 + g[i].du * g[i].dv * (g[i].u - centre[j]) ** 2) * w\n }\n }\n for (let i = 0; i < parts.length; i++) {\n const p = parts[i]\n if (p.kind !== 'column' || !p.elasticPa) continue\n const h = Math.max(1e-6, p.max[1] - p.min[1])\n const kc = (p.elasticPa * c.stiffnessFactor * (g[i].du ** 3 * g[i].dv) / 12) / h\n let beams = 0\n for (const b of p.beams ?? []) {\n const q = parts[b]\n if (!q?.elasticPa) continue\n const hx = q.max[0] - q.min[0], hz = q.max[2] - q.min[2]\n const long = Math.max(hx, hz), short = Math.min(hx, hz)\n const cos = hx >= hz ? Math.abs(dx) : Math.abs(dz)\n const depth = q.max[1] - q.min[1]\n const inertia = tBeamInertia(short, depth, short + 2 * c.flange * long, q.slab ?? 0)\n beams += (cos * cos * q.elasticPa * c.beamFactor * inertia) / Math.max(long, 1e-6)\n }\n const k = beams / kc\n const base = p.min[1] - ground < 0.05\n const a = base ? (0.5 + k) / (2 + k) : k / (2 + k)\n const stiffness = (a * 12 * (p.elasticPa * c.stiffnessFactor) * ((g[i].du ** 3 * g[i].dv) / 12)) / (h * h)\n for (let j = 0; j < n; j++) ga[j] += (stiffness * share(p, j)) / bands[j]\n }\n // what stands above the highest wall or column (a roof, its trusses) is carried by them and moves with their top: nothing bends there\n let last = -1\n for (let j = 0; j < n; j++) if (ei[j] > 0 || ga[j] > 0) last = j\n for (let j = last + 1; j < n && last >= 0; j++) {\n ei[j] = ei[last] * RIGID\n ga[j] = ga[last] * RIGID\n }\n const tiny = 1\n const eiS = ei.map((v) => Math.max(v, tiny))\n const gaS = ga.map((v) => Math.max(v, tiny))\n const sol = solveWallFrame(bands, eiS, gaS, V)\n const deflection = sol.w[n]\n const lean = solveWallFrame(bands, eiS, gaS, shearNodes(meanForces)).w[n]\n\n // what the walls and the frame each carry\n const kappa = bands.map((h, j) => (sol.psi[j + 1] - sol.psi[j]) / h)\n const Mmid = bands.map((h, j) => M[j + 1] + (h / 2) * (V[j + 1] + (V[j] + V[j + 1]) / 2) / 2)\n const Mwall = ei.map((v, j) => Math.min(Mmid[j], Math.max(0, v * kappa[j])))\n const axial = new Array<number>(parts.length).fill(0)\n for (const i of vertical) {\n const p = parts[i]\n let sum = 0, tot = 0\n for (let j = 0; j < n; j++) {\n const w = share(p, j)\n if (w <= 0) continue\n sum += w * p.elasticPa! * c.stiffnessFactor * kappa[j] * g[i].du * g[i].dv * (g[i].u - centre[j])\n tot += w\n }\n axial[i] = tot > 0 ? sum / tot : 0\n }\n if (!c.chord) {\n // the frame carries the rest of the moment as a couple of the columns: forces in proportion to `A d` from their centroid\n const colA = new Array<number>(n).fill(0), colAu = new Array<number>(n).fill(0)\n const cols: number[] = []\n for (let i = 0; i < parts.length; i++) {\n if (parts[i].kind !== 'column') continue\n cols.push(i)\n for (let j = 0; j < n; j++) {\n const w = share(parts[i], j) / bands[j]\n colA[j] += g[i].du * g[i].dv * w\n colAu[j] += g[i].du * g[i].dv * g[i].u * w\n }\n }\n const colC = colA.map((a, j) => (a > 0 ? colAu[j] / a : 0))\n const colI = new Array<number>(n).fill(0)\n for (const i of cols) for (let j = 0; j < n; j++) colI[j] += (g[i].du * g[i].dv * (g[i].u - colC[j]) ** 2 * share(parts[i], j)) / bands[j]\n for (const i of cols) {\n let sum = 0, tot = 0\n for (let j = 0; j < n; j++) {\n const w = share(parts[i], j)\n if (w <= 0 || colI[j] <= 0) continue\n sum += w * (Math.max(0, Mmid[j] - Mwall[j]) * g[i].du * g[i].dv * (g[i].u - colC[j])) / colI[j]\n tot += w\n }\n axial[i] = tot > 0 ? sum / tot : 0\n }\n }\n\n // stability: overturning moment against the weight over the leeward edge of the foundations\n const arm = footEnd - uCg\n const overturn = arm > 0 ? (c.loadFactor * M[0]) / (weight * arm) : Infinity\n\n // first mode, Rayleigh: the shape under a load equal to the mass of each band\n const mode = solveWallFrame(bands, eiS, gaS, shearNodes(mass))\n const top = mode.w[n]\n const um = bands.map((_, j) => (mode.w[j] + mode.w[j + 1]) / 2)\n let mu = 0, muu = 0\n mass.forEach((m, j) => {\n mu += m * um[j]\n muu += m * um[j] * um[j]\n })\n const omega = muu > 0 ? Math.sqrt(mu / muu) : 0\n const phi = um.map((u) => (top > 0 ? u / top : 0))\n const modalMass = mass.reduce((s, m, j) => s + m * phi[j] * phi[j], 0)\n const modalForce = meanForces.reduce((s, f, j) => s + f * phi[j], 0)\n const z = [0, ...bands.map((_, j) => z0[j] + bands[j])]\n const intensity = turbulenceIntensity(Math.max(0.6 * height, c.minHeight), c.terrain.z0)\n\n return {\n height, cls, width: widest, bands, mid, forces, meanForces, pressure: pressure[n - 1], shear: V[0], moment: M[0], deflection, drift: deflection / height, lean,\n weight, overturn, wallShare: M[0] > 0 ? Mwall[0] / M[0] : 0, ei, ga, frequency: omega / (2 * Math.PI), omega, modalMass, modalStiffness: omega * omega * modalMass,\n shape: { z, phi: mode.w.map((w) => (top > 0 ? w / top : 0)) }, modalForce, intensity, axial,\n }\n}\n\n// ---------------------------------------------------------------------------------------------------------------------------------------------\n// Tuned mass damper\n// ---------------------------------------------------------------------------------------------------------------------------------------------\n\n/**\n * Optimal tuning of a damper of mass ratio `mu` (damper mass over the modal mass): its frequency over the building's and its damping ratio.\n * `den-hartog` (1956): `1 / (1 + mu)` and `sqrt(3 mu / (8 (1 + mu)^3))`, for a harmonic force on an undamped structure. `warburton` (1982): for a random\n * force, `sqrt(1 - mu / 2) / (1 + mu)` and `sqrt(mu (1 - mu / 4) / (4 (1 + mu) (1 - mu / 2)))`.\n */\nexport const damperTuning = (mu: number, kind: 'den-hartog' | 'warburton' = 'den-hartog'): { frequency: number; damping: number } =>\n kind === 'warburton'\n ? { frequency: Math.sqrt(1 - mu / 2) / (1 + mu), damping: Math.sqrt((mu * (1 - mu / 4)) / (4 * (1 + mu) * (1 - mu / 2))) }\n : { frequency: 1 / (1 + mu), damping: Math.sqrt((3 * mu) / (8 * (1 + mu) ** 3)) }\n\n/**\n * Amplitude of the structure under a harmonic force over its static deflection, with a damper: `r` the forcing frequency over the structure's,\n * `mu` the mass ratio, `g` the damper's frequency over the structure's, `damper` and `structure` the damping ratios. Solves\n * `[(1 - r^2 + 2 i zs r) - mu A r^2 / (A - r^2)] X = 1` with `A = g^2 + 2 i zd g r`. `mu` 0 is the structure alone (`1 / (2 zs)` at resonance).\n */\nexport const damperAmplification = (r: number, mu: number, g: number, damper: number, structure = 0): number => {\n // complex arithmetic by hand: numbers as [re, im]\n const mul = (a: [number, number], b: [number, number]): [number, number] => [a[0] * b[0] - a[1] * b[1], a[0] * b[1] + a[1] * b[0]]\n const div = (a: [number, number], b: [number, number]): [number, number] => {\n const d = b[0] * b[0] + b[1] * b[1]\n return [(a[0] * b[0] + a[1] * b[1]) / d, (a[1] * b[0] - a[0] * b[1]) / d]\n }\n const A: [number, number] = [g * g, 2 * damper * g * r]\n const main: [number, number] = [1 - r * r, 2 * structure * r]\n const coupling = mu > 0 ? mul([mu * r * r, 0], div(A, [A[0] - r * r, A[1]])) : ([0, 0] as [number, number])\n const total: [number, number] = [main[0] - coupling[0], main[1] - coupling[1]]\n return 1 / Math.hypot(total[0], total[1])\n}\n\n// ---------------------------------------------------------------------------------------------------------------------------------------------\n// Gust and sway\n// ---------------------------------------------------------------------------------------------------------------------------------------------\n\n/** A gust series: sines of equal frequency spacing whose amplitudes follow the Davenport spectrum, normalized to unit variance. */\nexport interface Gust {\n freq: number[]\n amp: number[]\n phase: number[]\n}\n\n/**\n * The turbulence at the 10 m mean speed `v10`: `components` sines up to `maxHz`, amplitudes from the Davenport spectrum `f S(f) / u*^2 = 4 x^2 / (1 + x^2)^(4/3)`,\n * `x = scale f / v10` (NBR 6123 chapter 9, Simiu & Scanlan), phases from the seed.\n */\nexport const makeGust = (v10: number, o: { components: number; maxHz: number; scale: number; seed: number }): Gust => {\n const rng = createRng(o.seed)\n const n = Math.max(1, Math.floor(o.components))\n const df = o.maxHz / n\n const freq = Array.from({ length: n }, (_, k) => (k + 0.5) * df)\n const weight = freq.map((f) => {\n const x = (o.scale * f) / Math.max(v10, 1e-6)\n return ((4 * x * x) / (1 + x * x) ** (4 / 3) / f) * df\n })\n const sum = weight.reduce((s, w) => s + w, 0)\n return { freq, amp: weight.map((w) => Math.sqrt((2 * w) / sum)), phase: freq.map(() => rng.next() * 2 * Math.PI) }\n}\n\n/** The gust at time `t`: zero mean, unit variance. */\nexport const gustAt = (gust: Gust, t: number): number => {\n let s = 0\n for (let k = 0; k < gust.freq.length; k++) s += gust.amp[k] * Math.cos(2 * Math.PI * gust.freq[k] * t + gust.phase[k])\n return s\n}\n\n/** The first mode of a building with an optional tuned mass damper: modal mass, stiffness and damping, and the damper's mass, stiffness and dashpot. */\nexport interface SwaySystem {\n M: number\n K: number\n C: number\n damper?: { m: number; k: number; c: number }\n}\n\n/** Displacement and velocity of the top, and of the damper's mass (absolute). */\nexport interface SwayState {\n x: number\n v: number\n y: number\n w: number\n}\n\n/** Advances `s` by `dt` seconds under the force `force(t)` (N, on the modal mass), RK4 with steps no longer than `maxStep`. */\nexport const stepSway = (s: SwayState, sys: SwaySystem, t: number, dt: number, force: (t: number) => number, maxStep = Infinity): void => {\n const steps = Math.max(1, Math.ceil(dt / maxStep - 1e-9))\n const h = dt / steps\n const d = sys.damper\n const f = (x: number, v: number, y: number, w: number, tt: number): [number, number, number, number] => {\n const fd = d ? d.k * (y - x) + d.c * (w - v) : 0\n return [v, (force(tt) - sys.K * x - sys.C * v + fd) / sys.M, d ? w : 0, d ? -fd / d.m : 0]\n }\n for (let i = 0; i < steps; i++) {\n const tt = t + i * h\n const k1 = f(s.x, s.v, s.y, s.w, tt)\n const k2 = f(s.x + (h / 2) * k1[0], s.v + (h / 2) * k1[1], s.y + (h / 2) * k1[2], s.w + (h / 2) * k1[3], tt + h / 2)\n const k3 = f(s.x + (h / 2) * k2[0], s.v + (h / 2) * k2[1], s.y + (h / 2) * k2[2], s.w + (h / 2) * k2[3], tt + h / 2)\n const k4 = f(s.x + h * k3[0], s.v + h * k3[1], s.y + h * k3[2], s.w + h * k3[3], tt + h)\n s.x += (h / 6) * (k1[0] + 2 * k2[0] + 2 * k3[0] + k4[0])\n s.v += (h / 6) * (k1[1] + 2 * k2[1] + 2 * k3[1] + k4[1])\n s.y += (h / 6) * (k1[2] + 2 * k2[2] + 2 * k3[2] + k4[2])\n s.w += (h / 6) * (k1[3] + 2 * k2[3] + 2 * k3[3] + k4[3])\n }\n}\n\n// ---------------------------------------------------------------------------------------------------------------------------------------------\n// Tension of walls and columns\n// ---------------------------------------------------------------------------------------------------------------------------------------------\n\n/**\n * Force in newtons a wall or column holds in tension: its vertical rebar at yield (`reinforcement` bars, or `ratio` of the section) when it has any,\n * else the tensile strength of its material times the section, else nothing (a masonry wall does not pull).\n */\nexport const tensionCapacity = (\n dims: Vec3, o: { reinforcement?: { spacing: number; diameter: number }; ratio?: number; yieldMPa: number; tensileMPa?: number },\n): number => {\n const section = dims[0] * dims[2]\n if (o.reinforcement) {\n const bars = verticalBarCount(dims, thinAxisOf(dims), o.reinforcement.spacing)\n return bars * Math.PI * (o.reinforcement.diameter / 2) ** 2 * o.yieldMPa * 1e6\n }\n if (o.ratio) return o.ratio * section * o.yieldMPa * 1e6\n return (o.tensileMPa ?? 0) * 1e6 * section\n}\n","[\n {\n \"id\": \"steel\",\n \"density\": 7850,\n \"hpPerKg\": 400,\n \"penetration\": 110,\n \"penetrationClass\": \"steel\",\n \"penetrationScale\": 1.3,\n \"ductility\": 0.9,\n \"fracture\": \"none\",\n \"damageScale\": {\n \"slash\": 0.1,\n \"blunt\": 0.8\n },\n \"hitDebris\": \"sparks\",\n \"breakDebris\": \"sparks\",\n \"ricochetDeg\": 20,\n \"thermal\": {\n \"meltC\": 1450,\n \"meltRate\": 0.05,\n \"conductivity\": 0.5,\n \"heatCapacity\": 3\n },\n \"visual\": {\n \"glows\": true\n },\n \"tags\": [\n \"metal\",\n \"conductive\"\n ],\n \"compressive\": 2000000\n },\n {\n \"id\": \"cast_iron\",\n \"density\": 7200,\n \"hpPerKg\": 150,\n \"penetration\": 160,\n \"penetrationClass\": \"steel\",\n \"penetrationScale\": 1.0,\n \"ductility\": 0.2,\n \"fracture\": \"snap\",\n \"fragmentSize\": [\n 0.08,\n 0.3\n ],\n \"damageScale\": {\n \"slash\": 0.1,\n \"blunt\": 1.2\n },\n \"hitDebris\": \"sparks\",\n \"breakDebris\": \"chips\",\n \"ricochetDeg\": 15,\n \"thermal\": {\n \"meltC\": 1200,\n \"meltRate\": 0.05,\n \"conductivity\": 0.45,\n \"heatCapacity\": 3\n },\n \"visual\": {\n \"glows\": true\n },\n \"tags\": [\n \"metal\",\n \"conductive\"\n ],\n \"compressive\": 1500000\n },\n {\n \"id\": \"aluminium\",\n \"density\": 2700,\n \"hpPerKg\": 250,\n \"penetration\": 60,\n \"penetrationClass\": \"steel\",\n \"penetrationScale\": 3,\n \"ductility\": 0.85,\n \"fracture\": \"none\",\n \"damageScale\": {\n \"slash\": 0.2\n },\n \"hitDebris\": \"sparks\",\n \"breakDebris\": \"sparks\",\n \"ricochetDeg\": 15,\n \"thermal\": {\n \"meltC\": 660,\n \"meltRate\": 0.06,\n \"conductivity\": 0.8,\n \"heatCapacity\": 1.5\n },\n \"visual\": {\n \"glows\": true\n },\n \"tags\": [\n \"metal\",\n \"conductive\"\n ],\n \"compressive\": 800000\n },\n {\n \"id\": \"copper\",\n \"density\": 8960,\n \"hpPerKg\": 300,\n \"penetration\": 70,\n \"penetrationClass\": \"steel\",\n \"penetrationScale\": 1.5,\n \"ductility\": 0.95,\n \"fracture\": \"none\",\n \"damageScale\": {\n \"slash\": 0.2\n },\n \"hitDebris\": \"sparks\",\n \"breakDebris\": \"sparks\",\n \"ricochetDeg\": 15,\n \"thermal\": {\n \"meltC\": 1085,\n \"meltRate\": 0.05,\n \"conductivity\": 1,\n \"heatCapacity\": 2.5\n },\n \"visual\": {\n \"glows\": true\n },\n \"tags\": [\n \"metal\",\n \"conductive\"\n ],\n \"compressive\": 1000000\n },\n {\n \"id\": \"wood_soft\",\n \"splitForm\": \"slivers\",\n \"density\": 500,\n \"hpPerKg\": 90,\n \"penetration\": 9,\n \"penetrationClass\": \"wood\",\n \"penetrationScale\": 1.5,\n \"ductility\": 0.35,\n \"fracture\": \"splinter\",\n \"fragmentSize\": [\n 0.03,\n 0.15\n ],\n \"damageScale\": {\n \"blunt\": 1.2,\n \"slash\": 1.5\n },\n \"hitDebris\": \"splinters\",\n \"breakDebris\": \"splinters\",\n \"thermal\": {\n \"ignitionC\": 300,\n \"flameC\": 800,\n \"fuelFraction\": 0.9,\n \"burnRate\": 0.012,\n \"conductivity\": 0.05,\n \"heatCapacity\": 1.2,\n \"smoke\": \"grey\"\n },\n \"visual\": {\n \"charColor\": 1709072,\n \"innerColor\": 14730131\n },\n \"tags\": [\n \"wood\",\n \"organic\",\n \"flammable\"\n ],\n \"compressive\": 100000,\n \"hits\": {\n \"blunt\": {\n \"tear\": \"splinters\",\n \"tearJoules\": 60\n }\n }\n },\n {\n \"id\": \"wood_hard\",\n \"splitForm\": \"slivers\",\n \"density\": 750,\n \"hpPerKg\": 140,\n \"penetration\": 14,\n \"penetrationClass\": \"wood\",\n \"penetrationScale\": 1,\n \"ductility\": 0.3,\n \"fracture\": \"splinter\",\n \"fragmentSize\": [\n 0.03,\n 0.2\n ],\n \"damageScale\": {\n \"slash\": 1.2\n },\n \"hitDebris\": \"splinters\",\n \"breakDebris\": \"splinters\",\n \"thermal\": {\n \"ignitionC\": 330,\n \"flameC\": 800,\n \"fuelFraction\": 0.9,\n \"burnRate\": 0.01,\n \"conductivity\": 0.06,\n \"heatCapacity\": 1.4,\n \"smoke\": \"grey\"\n },\n \"visual\": {\n \"charColor\": 1709072,\n \"innerColor\": 13213802\n },\n \"tags\": [\n \"wood\",\n \"organic\",\n \"flammable\"\n ],\n \"compressive\": 150000,\n \"hits\": {\n \"blunt\": {\n \"tear\": \"splinters\",\n \"tearJoules\": 150\n }\n }\n },\n {\n \"id\": \"plywood\",\n \"splitForm\": \"plies\",\n \"density\": 600,\n \"hpPerKg\": 70,\n \"penetration\": 7,\n \"penetrationClass\": \"wood\",\n \"penetrationScale\": 2,\n \"ductility\": 0.3,\n \"fracture\": \"snap\",\n \"fragmentSize\": [\n 0.1,\n 0.4\n ],\n \"damageScale\": {\n \"slash\": 1.3\n },\n \"hitDebris\": \"splinters\",\n \"breakDebris\": \"splinters\",\n \"thermal\": {\n \"ignitionC\": 300,\n \"flameC\": 800,\n \"fuelFraction\": 0.85,\n \"burnRate\": 0.013,\n \"conductivity\": 0.05,\n \"heatCapacity\": 1.2,\n \"smoke\": \"grey\"\n },\n \"visual\": {\n \"charColor\": 1709072,\n \"innerColor\": 14862234\n },\n \"tags\": [\n \"wood\",\n \"organic\",\n \"flammable\"\n ],\n \"compressive\": 60000,\n \"hits\": {\n \"ballistic\": {\n \"tear\": \"splinters\"\n },\n \"blunt\": {\n \"tear\": \"splinters\",\n \"tearJoules\": 80\n }\n }\n },\n {\n \"id\": \"mdf\",\n \"splitForm\": \"granules\",\n \"density\": 750,\n \"hpPerKg\": 45,\n \"penetration\": 6,\n \"penetrationClass\": \"wood\",\n \"penetrationScale\": 2.5,\n \"ductility\": 0.15,\n \"fracture\": \"snap\",\n \"fragmentSize\": [\n 0.08,\n 0.35\n ],\n \"hitDebris\": \"chips\",\n \"breakDebris\": \"dust\",\n \"thermal\": {\n \"ignitionC\": 290,\n \"flameC\": 750,\n \"fuelFraction\": 0.85,\n \"burnRate\": 0.014,\n \"conductivity\": 0.05,\n \"heatCapacity\": 1.2,\n \"smoke\": \"grey\"\n },\n \"visual\": {\n \"charColor\": 1709072,\n \"innerColor\": 12096362\n },\n \"tags\": [\n \"wood\",\n \"organic\",\n \"flammable\"\n ],\n \"compressive\": 30000,\n \"hits\": {\n \"ballistic\": {\n \"tear\": \"lumps\",\n \"tearJoules\": 120\n },\n \"blunt\": {\n \"tear\": \"lumps\",\n \"tearJoules\": 20\n }\n }\n },\n {\n \"id\": \"glass\",\n \"density\": 2500,\n \"hpPerKg\": 12,\n \"penetration\": 6,\n \"ductility\": 0.02,\n \"fracture\": \"shatter\",\n \"fragmentSize\": [\n 0.05,\n 0.25\n ],\n \"damageScale\": {\n \"blunt\": 1.5,\n \"shelter\": 3\n },\n \"hitDebris\": \"shards\",\n \"breakDebris\": \"shards\",\n \"ricochetDeg\": 8,\n \"thermal\": {\n \"meltC\": 1400,\n \"meltRate\": 0.03,\n \"conductivity\": 0.1,\n \"heatCapacity\": 1.5,\n \"thermalShockC\": 150\n },\n \"visual\": {\n \"glows\": true,\n \"transparent\": true\n },\n \"tags\": [\n \"glass\",\n \"brittle\"\n ],\n \"compressive\": 100000\n },\n {\n \"id\": \"tempered_glass\",\n \"density\": 2500,\n \"hpPerKg\": 30,\n \"penetration\": 9,\n \"ductility\": 0.02,\n \"fracture\": \"crumble\",\n \"fragmentSize\": [\n 0.006,\n 0.02\n ],\n \"hitDebris\": \"shards\",\n \"breakDebris\": \"shards\",\n \"ricochetDeg\": 8,\n \"thermal\": {\n \"meltC\": 1400,\n \"meltRate\": 0.03,\n \"conductivity\": 0.1,\n \"heatCapacity\": 1.5,\n \"thermalShockC\": 250\n },\n \"visual\": {\n \"glows\": true,\n \"transparent\": true\n },\n \"tags\": [\n \"glass\",\n \"brittle\"\n ],\n \"compressive\": 200000,\n \"damageScale\": {\n \"shelter\": 3\n }\n },\n {\n \"id\": \"ceramic\",\n \"density\": 2400,\n \"hpPerKg\": 25,\n \"penetration\": 12,\n \"ductility\": 0.02,\n \"fracture\": \"shatter\",\n \"fragmentSize\": [\n 0.03,\n 0.12\n ],\n \"damageScale\": {\n \"blunt\": 1.3\n },\n \"hitDebris\": \"chips\",\n \"breakDebris\": \"shards\",\n \"thermal\": {\n \"conductivity\": 0.1,\n \"heatCapacity\": 1.5,\n \"thermalShockC\": 200\n },\n \"tags\": [\n \"ceramic\",\n \"brittle\"\n ],\n \"compressive\": 150000\n },\n {\n \"id\": \"concrete\",\n \"density\": 2300,\n \"hpPerKg\": 14,\n \"penetration\": 18,\n \"penetrationClass\": \"concrete\",\n \"penetrationScale\": 1,\n \"ductility\": 0.03,\n \"fracture\": \"crumble\",\n \"fragmentSize\": [\n 0.05,\n 0.25\n ],\n \"damageScale\": {\n \"explosive\": 1.2\n },\n \"hits\": {\n \"ballistic\": {\n \"unitJoules\": 500,\n \"floor\": 900,\n \"crater\": true\n },\n \"blunt\": {\n \"unitJoules\": 1500,\n \"floor\": 60\n }\n },\n \"ricochetDeg\": 12,\n \"hitDebris\": \"chips\",\n \"breakDebris\": \"dust\",\n \"visual\": { \"innerColor\": 10197652 },\n \"thermal\": {\n \"conductivity\": 0.15,\n \"heatCapacity\": 2.5\n },\n \"tags\": [\n \"masonry\",\n \"brittle\"\n ],\n \"compressive\": 444000,\n \"strength\": {\n \"compressiveMPa\": 25,\n \"tensileMPa\": 2.56,\n \"elasticGPa\": 28\n }\n },\n {\n \"id\": \"brick\",\n \"density\": 1900,\n \"hpPerKg\": 12,\n \"penetration\": 14,\n \"penetrationClass\": \"brick\",\n \"penetrationScale\": 1,\n \"ductility\": 0.05,\n \"fracture\": \"crumble\",\n \"fragmentSize\": [\n 0.04,\n 0.12\n ],\n \"ricochetDeg\": 10,\n \"hitDebris\": \"chips\",\n \"breakDebris\": \"dust\",\n \"visual\": { \"innerColor\": 12085567 },\n \"thermal\": {\n \"conductivity\": 0.15,\n \"heatCapacity\": 2.5\n },\n \"tags\": [\n \"masonry\",\n \"brittle\"\n ],\n \"compressive\": 40000,\n \"strength\": {\n \"compressiveMPa\": 2.35,\n \"tensileMPa\": 0.1,\n \"elasticGPa\": 2.35\n }\n },\n {\n \"id\": \"plaster\",\n \"density\": 850,\n \"hpPerKg\": 18,\n \"penetration\": 3,\n \"penetrationClass\": \"brick\",\n \"penetrationScale\": 3,\n \"ductility\": 0.05,\n \"fracture\": \"crumble\",\n \"fragmentSize\": [\n 0.05,\n 0.3\n ],\n \"hitDebris\": \"dust\",\n \"breakDebris\": \"dust\",\n \"visual\": { \"innerColor\": 14999507 },\n \"thermal\": {\n \"conductivity\": 0.1,\n \"heatCapacity\": 1.5\n },\n \"tags\": [\n \"masonry\",\n \"brittle\"\n ],\n \"compressive\": 8000\n },\n {\n \"id\": \"stone\",\n \"density\": 2700,\n \"hpPerKg\": 25,\n \"penetration\": 25,\n \"penetrationClass\": \"concrete\",\n \"penetrationScale\": 0.9,\n \"ductility\": 0.03,\n \"fracture\": \"crumble\",\n \"fragmentSize\": [\n 0.06,\n 0.3\n ],\n \"ricochetDeg\": 15,\n \"hitDebris\": \"chips\",\n \"breakDebris\": \"dust\",\n \"visual\": { \"innerColor\": 9407364 },\n \"thermal\": {\n \"conductivity\": 0.2,\n \"heatCapacity\": 2.5\n },\n \"tags\": [\n \"masonry\",\n \"brittle\"\n ],\n \"compressive\": 300000\n },\n {\n \"id\": \"plastic\",\n \"density\": 1100,\n \"hpPerKg\": 60,\n \"penetration\": 8,\n \"ductility\": 0.5,\n \"fracture\": \"snap\",\n \"fragmentSize\": [\n 0.05,\n 0.3\n ],\n \"hitDebris\": \"chips\",\n \"breakDebris\": \"chips\",\n \"thermal\": {\n \"ignitionC\": 400,\n \"flameC\": 700,\n \"fuelFraction\": 0.8,\n \"burnRate\": 0.02,\n \"meltC\": 200,\n \"meltRate\": 0.06,\n \"conductivity\": 0.05,\n \"heatCapacity\": 1,\n \"smoke\": \"black\"\n },\n \"visual\": {\n \"charColor\": 855309\n },\n \"tags\": [\n \"plastic\",\n \"flammable\"\n ],\n \"compressive\": 40000\n },\n {\n \"id\": \"rubber\",\n \"density\": 1100,\n \"hpPerKg\": 80,\n \"penetration\": 12,\n \"ductility\": 0.9,\n \"fracture\": \"tear\",\n \"fragmentSize\": [\n 0.05,\n 0.2\n ],\n \"hitDebris\": \"chips\",\n \"breakDebris\": \"fibers\",\n \"thermal\": {\n \"ignitionC\": 350,\n \"flameC\": 750,\n \"fuelFraction\": 0.6,\n \"burnRate\": 0.015,\n \"conductivity\": 0.05,\n \"heatCapacity\": 1.2,\n \"smoke\": \"black\"\n },\n \"visual\": {\n \"charColor\": 855309\n },\n \"tags\": [\n \"rubber\",\n \"flammable\"\n ],\n \"compressive\": 20000\n },\n {\n \"id\": \"fabric\",\n \"density\": 400,\n \"hpPerKg\": 20,\n \"penetration\": 0.8,\n \"ductility\": 0.8,\n \"fracture\": \"tear\",\n \"fragmentSize\": [\n 0.05,\n 0.25\n ],\n \"damageScale\": {\n \"slash\": 4,\n \"ballistic\": 0.5\n },\n \"hitDebris\": \"fibers\",\n \"breakDebris\": \"fibers\",\n \"thermal\": {\n \"ignitionC\": 230,\n \"flameC\": 600,\n \"fuelFraction\": 1,\n \"burnRate\": 0.05,\n \"conductivity\": 0.03,\n \"heatCapacity\": 0.6,\n \"smoke\": \"grey\"\n },\n \"visual\": {\n \"charColor\": 1709072\n },\n \"tags\": [\n \"fabric\",\n \"organic\",\n \"flammable\"\n ],\n \"compressive\": 500\n },\n {\n \"id\": \"foam\",\n \"density\": 30,\n \"hpPerKg\": 15,\n \"penetration\": 0.5,\n \"ductility\": 0.7,\n \"fracture\": \"tear\",\n \"fragmentSize\": [\n 0.03,\n 0.15\n ],\n \"damageScale\": {\n \"slash\": 2,\n \"ballistic\": 0.4\n },\n \"hitDebris\": \"fibers\",\n \"breakDebris\": \"fibers\",\n \"thermal\": {\n \"ignitionC\": 250,\n \"flameC\": 900,\n \"fuelFraction\": 0.95,\n \"burnRate\": 0.09,\n \"conductivity\": 0.02,\n \"heatCapacity\": 0.5,\n \"smoke\": \"black\"\n },\n \"visual\": {\n \"charColor\": 855309\n },\n \"tags\": [\n \"fabric\",\n \"flammable\"\n ],\n \"compressive\": 100\n },\n {\n \"id\": \"leather\",\n \"density\": 900,\n \"hpPerKg\": 50,\n \"penetration\": 4,\n \"ductility\": 0.8,\n \"fracture\": \"tear\",\n \"fragmentSize\": [\n 0.05,\n 0.25\n ],\n \"damageScale\": {\n \"slash\": 2\n },\n \"hitDebris\": \"fibers\",\n \"breakDebris\": \"fibers\",\n \"thermal\": {\n \"ignitionC\": 320,\n \"flameC\": 650,\n \"fuelFraction\": 0.7,\n \"burnRate\": 0.01,\n \"conductivity\": 0.05,\n \"heatCapacity\": 1,\n \"smoke\": \"grey\"\n },\n \"visual\": {\n \"charColor\": 1709072\n },\n \"tags\": [\n \"fabric\",\n \"organic\",\n \"flammable\"\n ],\n \"compressive\": 2000\n },\n {\n \"id\": \"paper\",\n \"density\": 700,\n \"hpPerKg\": 8,\n \"penetration\": 0.3,\n \"ductility\": 0.5,\n \"fracture\": \"tear\",\n \"fragmentSize\": [\n 0.03,\n 0.15\n ],\n \"sheet\": 0.001,\n \"damageScale\": {\n \"slash\": 3\n },\n \"hitDebris\": \"fibers\",\n \"breakDebris\": \"fibers\",\n \"thermal\": {\n \"ignitionC\": 230,\n \"flameC\": 600,\n \"fuelFraction\": 1,\n \"burnRate\": 0.06,\n \"conductivity\": 0.03,\n \"heatCapacity\": 0.5,\n \"smoke\": \"grey\"\n },\n \"visual\": {\n \"charColor\": 1709072,\n \"innerColor\": 15524048\n },\n \"tags\": [\n \"fabric\",\n \"organic\",\n \"flammable\"\n ],\n \"compressive\": 500\n },\n {\n \"id\": \"foliage\",\n \"density\": 150,\n \"hpPerKg\": 20,\n \"penetration\": 0.5,\n \"ductility\": 0.6,\n \"fracture\": \"tear\",\n \"fragmentSize\": [\n 0.03,\n 0.1\n ],\n \"damageScale\": {\n \"slash\": 4\n },\n \"hitDebris\": \"leaves\",\n \"breakDebris\": \"leaves\",\n \"thermal\": {\n \"ignitionC\": 300,\n \"flameC\": 700,\n \"fuelFraction\": 0.8,\n \"burnRate\": 0.08,\n \"conductivity\": 0.03,\n \"heatCapacity\": 0.8,\n \"smoke\": \"white\"\n },\n \"visual\": {\n \"charColor\": 1709072\n },\n \"tags\": [\n \"plant\",\n \"organic\",\n \"flammable\"\n ],\n \"compressive\": 500\n },\n {\n \"id\": \"green_wood\",\n \"splitForm\": \"slivers\",\n \"density\": 650,\n \"hpPerKg\": 5,\n \"penetration\": 10,\n \"penetrationClass\": \"wood\",\n \"penetrationScale\": 1.2,\n \"ductility\": 0.5,\n \"fracture\": \"splinter\",\n \"fragmentSize\": [\n 0.03,\n 0.2\n ],\n \"damageScale\": {\n \"slash\": 1.3,\n \"ballistic\": 0.1\n },\n \"hitDebris\": \"splinters\",\n \"breakDebris\": \"leaves\",\n \"thermal\": {\n \"ignitionC\": 400,\n \"flameC\": 700,\n \"fuelFraction\": 0.8,\n \"burnRate\": 0.006,\n \"conductivity\": 0.06,\n \"heatCapacity\": 2,\n \"smoke\": \"white\"\n },\n \"visual\": {\n \"charColor\": 1709072,\n \"innerColor\": 14207126\n },\n \"tags\": [\n \"plant\",\n \"wood\",\n \"organic\",\n \"flammable\"\n ],\n \"compressive\": 60000,\n \"hits\": {\n \"blunt\": {\n \"tear\": \"none\"\n }\n }\n },\n {\n \"id\": \"cactus\",\n \"density\": 900,\n \"hpPerKg\": 30,\n \"penetration\": 2,\n \"ductility\": 0.6,\n \"fracture\": \"tear\",\n \"fragmentSize\": [\n 0.04,\n 0.15\n ],\n \"damageScale\": {\n \"slash\": 3\n },\n \"hitDebris\": \"fibers\",\n \"breakDebris\": \"fibers\",\n \"thermal\": {\n \"ignitionC\": 450,\n \"flameC\": 650,\n \"fuelFraction\": 0.3,\n \"burnRate\": 0.01,\n \"conductivity\": 0.05,\n \"heatCapacity\": 3,\n \"smoke\": \"white\"\n },\n \"visual\": {\n \"charColor\": 1709072\n },\n \"tags\": [\n \"plant\",\n \"organic\",\n \"flammable\"\n ],\n \"compressive\": 5000\n },\n {\n \"id\": \"flesh_fruit\",\n \"density\": 950,\n \"hpPerKg\": 15,\n \"penetration\": 1.5,\n \"ductility\": 0.7,\n \"fracture\": \"tear\",\n \"fragmentSize\": [\n 0.02,\n 0.08\n ],\n \"damageScale\": {\n \"slash\": 2\n },\n \"hitDebris\": \"drips\",\n \"breakDebris\": \"drips\",\n \"thermal\": {\n \"conductivity\": 0.05,\n \"heatCapacity\": 3\n },\n \"tags\": [\n \"plant\",\n \"organic\"\n ],\n \"compressive\": 1000\n },\n {\n \"id\": \"wax\",\n \"density\": 900,\n \"hpPerKg\": 30,\n \"penetration\": 3,\n \"ductility\": 0.5,\n \"fracture\": \"snap\",\n \"fragmentSize\": [\n 0.05,\n 0.2\n ],\n \"hitDebris\": \"chips\",\n \"breakDebris\": \"chips\",\n \"thermal\": {\n \"ignitionC\": 230,\n \"flameC\": 700,\n \"fuelFraction\": 0.9,\n \"burnRate\": 0.02,\n \"meltC\": 60,\n \"meltRate\": 0.2,\n \"conductivity\": 0.05,\n \"heatCapacity\": 0.8,\n \"smoke\": \"grey\"\n },\n \"tags\": [\n \"wax\",\n \"flammable\"\n ],\n \"compressive\": 5000\n },\n {\n \"id\": \"soil\",\n \"density\": 1300,\n \"hpPerKg\": 3,\n \"penetration\": 5,\n \"ductility\": 0.3,\n \"fracture\": \"crumble\",\n \"fragmentSize\": [\n 0.03,\n 0.12\n ],\n \"hitDebris\": \"dust\",\n \"breakDebris\": \"dust\",\n \"thermal\": {\n \"conductivity\": 0.1,\n \"heatCapacity\": 2.5\n },\n \"tags\": [\n \"soil\",\n \"masonry\"\n ],\n \"compressive\": 20000\n },\n {\n \"id\": \"asphalt\",\n \"density\": 2350,\n \"hpPerKg\": 10,\n \"penetration\": 14,\n \"penetrationClass\": \"concrete\",\n \"penetrationScale\": 0.8,\n \"ductility\": 0.1,\n \"fracture\": \"crumble\",\n \"fragmentSize\": [\n 0.03,\n 0.15\n ],\n \"ricochetDeg\": 8,\n \"hitDebris\": \"chips\",\n \"breakDebris\": \"dust\",\n \"thermal\": {\n \"conductivity\": 0.1,\n \"heatCapacity\": 2,\n \"ignitionC\": 400,\n \"burnRate\": 0.002,\n \"smoke\": \"black\"\n },\n \"tags\": [\n \"masonry\",\n \"brittle\"\n ],\n \"compressive\": 30000\n },\n {\n \"id\": \"sand\",\n \"density\": 1600,\n \"hpPerKg\": 2,\n \"penetration\": 6,\n \"ductility\": 0.4,\n \"fracture\": \"crumble\",\n \"fragmentSize\": [\n 0.01,\n 0.04\n ],\n \"hitDebris\": \"dust\",\n \"breakDebris\": \"dust\",\n \"thermal\": {\n \"conductivity\": 0.1,\n \"heatCapacity\": 2\n },\n \"tags\": [\n \"soil\"\n ],\n \"compressive\": 10000\n },\n {\n \"id\": \"gravel\",\n \"density\": 1800,\n \"hpPerKg\": 3,\n \"penetration\": 8,\n \"ductility\": 0.3,\n \"fracture\": \"crumble\",\n \"fragmentSize\": [\n 0.02,\n 0.06\n ],\n \"hitDebris\": \"chips\",\n \"breakDebris\": \"dust\",\n \"thermal\": {\n \"conductivity\": 0.1,\n \"heatCapacity\": 2\n },\n \"tags\": [\n \"soil\",\n \"masonry\"\n ],\n \"compressive\": 20000\n },\n {\n \"id\": \"turf\",\n \"density\": 900,\n \"hpPerKg\": 3,\n \"penetration\": 4,\n \"ductility\": 0.5,\n \"fracture\": \"crumble\",\n \"fragmentSize\": [\n 0.03,\n 0.1\n ],\n \"hitDebris\": \"dust\",\n \"breakDebris\": \"dust\",\n \"thermal\": {\n \"conductivity\": 0.1,\n \"heatCapacity\": 1.5,\n \"ignitionC\": 250,\n \"burnRate\": 0.03,\n \"smoke\": \"white\"\n },\n \"tags\": [\n \"soil\",\n \"organic\"\n ],\n \"compressive\": 15000\n },\n {\n \"id\": \"mortar\",\n \"density\": 1900,\n \"hpPerKg\": 10,\n \"penetration\": 12,\n \"penetrationClass\": \"concrete\",\n \"penetrationScale\": 1.2,\n \"ductility\": 0.03,\n \"fracture\": \"crumble\",\n \"fragmentSize\": [\n 0.02,\n 0.08\n ],\n \"ricochetDeg\": 8,\n \"hitDebris\": \"chips\",\n \"breakDebris\": \"dust\",\n \"thermal\": {\n \"conductivity\": 0.15,\n \"heatCapacity\": 2.5\n },\n \"tags\": [\n \"masonry\",\n \"brittle\"\n ],\n \"compressive\": 100000\n },\n {\n \"id\": \"mud\",\n \"density\": 1700,\n \"hpPerKg\": 1,\n \"penetration\": 5,\n \"ductility\": 0.8,\n \"fracture\": \"crumble\",\n \"fragmentSize\": [\n 0.02,\n 0.08\n ],\n \"hitDebris\": \"dust\",\n \"breakDebris\": \"dust\",\n \"thermal\": {\n \"conductivity\": 0.5,\n \"heatCapacity\": 3.2\n },\n \"tags\": [\n \"soil\",\n \"wet\"\n ],\n \"compressive\": 5000\n },\n {\n \"id\": \"clay\",\n \"density\": 1800,\n \"hpPerKg\": 5,\n \"penetration\": 7,\n \"ductility\": 0.05,\n \"fracture\": \"crumble\",\n \"fragmentSize\": [\n 0.02,\n 0.1\n ],\n \"hitDebris\": \"chips\",\n \"breakDebris\": \"dust\",\n \"thermal\": {\n \"conductivity\": 0.15,\n \"heatCapacity\": 2.2\n },\n \"tags\": [\n \"soil\",\n \"brittle\"\n ],\n \"compressive\": 60000\n },\n {\n \"id\": \"snow\",\n \"density\": 300,\n \"hpPerKg\": 1,\n \"penetration\": 3,\n \"ductility\": 0.6,\n \"fracture\": \"crumble\",\n \"fragmentSize\": [\n 0.01,\n 0.05\n ],\n \"hitDebris\": \"dust\",\n \"breakDebris\": \"dust\",\n \"thermal\": {\n \"conductivity\": 0.1,\n \"heatCapacity\": 2.1\n },\n \"tags\": [\n \"soil\",\n \"frozen\"\n ],\n \"compressive\": 1000\n },\n {\n \"id\": \"cobble\",\n \"density\": 2650,\n \"hpPerKg\": 25,\n \"penetration\": 25,\n \"penetrationClass\": \"concrete\",\n \"penetrationScale\": 0.9,\n \"ductility\": 0.03,\n \"fracture\": \"crumble\",\n \"fragmentSize\": [\n 0.05,\n 0.15\n ],\n \"ricochetDeg\": 15,\n \"hitDebris\": \"chips\",\n \"breakDebris\": \"chips\",\n \"thermal\": {\n \"conductivity\": 0.2,\n \"heatCapacity\": 2.5\n },\n \"tags\": [\n \"masonry\",\n \"brittle\"\n ],\n \"compressive\": 300000\n },\n {\n \"id\": \"paver\",\n \"density\": 2300,\n \"hpPerKg\": 14,\n \"penetration\": 18,\n \"penetrationClass\": \"concrete\",\n \"penetrationScale\": 1,\n \"ductility\": 0.03,\n \"fracture\": \"crumble\",\n \"fragmentSize\": [\n 0.04,\n 0.12\n ],\n \"ricochetDeg\": 12,\n \"hitDebris\": \"chips\",\n \"breakDebris\": \"chips\",\n \"thermal\": {\n \"conductivity\": 0.15,\n \"heatCapacity\": 2.5\n },\n \"tags\": [\n \"masonry\",\n \"brittle\"\n ],\n \"compressive\": 350000\n }\n]\n","{\n \"cast iron\": \"cast_iron\",\n \"cast_iron\": \"cast_iron\",\n \"castiron\": \"cast_iron\",\n \"metal\": \"steel\",\n \"steel\": \"steel\",\n \"iron\": \"steel\",\n \"chrome\": \"steel\",\n \"alumin\": \"aluminium\",\n \"alu_\": \"aluminium\",\n \"alu-\": \"aluminium\",\n \"alu \": \"aluminium\",\n \"copper\": \"copper\",\n \"brass\": \"copper\",\n \"bronze\": \"copper\",\n \"wood\": \"wood_soft\",\n \"timber\": \"wood_soft\",\n \"plank\": \"wood_soft\",\n \"lumber\": \"wood_soft\",\n \"pine\": \"wood_soft\",\n \"hardwood\": \"wood_hard\",\n \"oak\": \"wood_hard\",\n \"plywood\": \"plywood\",\n \"mdf\": \"mdf\",\n \"chipboard\": \"mdf\",\n \"glass\": \"glass\",\n \"window\": \"glass\",\n \"mirror\": \"glass\",\n \"tempered\": \"tempered_glass\",\n \"windshield\": \"tempered_glass\",\n \"fabric\": \"fabric\",\n \"cloth\": \"fabric\",\n \"cushion\": \"fabric\",\n \"sofa\": \"fabric\",\n \"curtain\": \"fabric\",\n \"carpet\": \"fabric\",\n \"textile\": \"fabric\",\n \"canvas\": \"fabric\",\n \"foam\": \"foam\",\n \"sponge\": \"foam\",\n \"mattress\": \"foam\",\n \"leather\": \"leather\",\n \"paper\": \"paper\",\n \"cardboard\": \"paper\",\n \"leaf\": \"foliage\",\n \"leaves\": \"foliage\",\n \"foliage\": \"foliage\",\n \"bush\": \"foliage\",\n \"grass\": \"foliage\",\n \"trunk\": \"green_wood\",\n \"branch\": \"green_wood\",\n \"twig\": \"green_wood\",\n \"cactus\": \"cactus\",\n \"fruit\": \"flesh_fruit\",\n \"apple\": \"flesh_fruit\",\n \"melon\": \"flesh_fruit\",\n \"wax\": \"wax\",\n \"candle\": \"wax\",\n \"concrete\": \"concrete\",\n \"cement\": \"concrete\",\n \"brick\": \"brick\",\n \"tile\": \"ceramic\",\n \"ceramic\": \"ceramic\",\n \"porcelain\": \"ceramic\",\n \"stone\": \"stone\",\n \"rock\": \"stone\",\n \"marble\": \"stone\",\n \"plaster\": \"plaster\",\n \"drywall\": \"plaster\",\n \"gypsum\": \"plaster\",\n \"plastic\": \"plastic\",\n \"pvc\": \"plastic\",\n \"acrylic\": \"plastic\",\n \"rubber\": \"rubber\",\n \"tire\": \"rubber\",\n \"tyre\": \"rubber\",\n \"soil\": \"soil\",\n \"dirt\": \"soil\",\n \"potting\": \"soil\",\n \"mud\": \"soil\"\n}","import materialsJson from './data/materials.json'\nimport hintsJson from './data/material-hints.json'\nimport { aabbOf, quatFromEuler, shapeDims } from './math'\nimport { GRAVITY, isSlender, resolveFlexure, resolveMasonry, slendernessFactor } from './flexure'\nimport { thinAxisOf } from './layers'\nimport { rebarBars } from './rebar'\nimport type { FlexureOptions, JointKind, JointSpec, MasonryOptions, MaterialDef, MaterialId, PartShape, PartSpec, ToolKind } from './types'\n\n/** Built-in materials (data in `src/data/materials.json`). Override or extend with the `materials` option of `createDestruction`. */\nexport const MATERIALS: MaterialDef[] = materialsJson as unknown as MaterialDef[]\n\n/** Default joint strength (joint hit points), tools that undo it and seconds of tool work. */\nexport const JOINT_DEFAULTS: Record<JointKind, { strength: number; tools: ToolKind[]; seconds: number }> = {\n screw: { strength: 80, tools: ['screwdriver'], seconds: 2.5 },\n bolt: { strength: 200, tools: ['wrench'], seconds: 4 },\n nail: { strength: 60, tools: ['pry_bar', 'hammer'], seconds: 2 },\n weld: { strength: 600, tools: ['cutting_torch', 'saw'], seconds: 8 },\n glue: { strength: 50, tools: ['pry_bar', 'knife'], seconds: 3 },\n hinge: { strength: 120, tools: ['screwdriver'], seconds: 3 },\n clip: { strength: 20, tools: ['hand'], seconds: 0.6 },\n tie: { strength: 15, tools: ['knife', 'hand'], seconds: 1 },\n mortar: { strength: 400, tools: ['hammer'], seconds: 6 },\n fused: { strength: 1000, tools: [], seconds: 0 },\n stem: { strength: 40, tools: ['knife', 'saw', 'hand'], seconds: 1.5 },\n rebar: { strength: 1500, tools: ['cutting_torch', 'saw'], seconds: 20 },\n resting: { strength: 30, tools: ['hand'], seconds: 1 },\n}\n\nconst has = (m: MaterialDef, tag: string) => !!m.tags && m.tags.includes(tag)\n\n/**\n * The joint kind that fits two materials: glass is glued (clipped to plastic), soft things are tied, plants share a stem, masonry gets mortar,\n * metal is welded, wood is screwed, plastic clips. `inferJoints` refines weld to bolt for thick metal and screw to nail for thin wood.\n */\nexport const JOINT_BY_MATERIALS = (a: MaterialDef, b: MaterialDef): JointKind => {\n const any = (tag: string) => has(a, tag) || has(b, tag)\n const both = (tag: string) => has(a, tag) && has(b, tag)\n if (any('glass')) return any('plastic') ? 'clip' : 'glue'\n if (any('fabric')) return 'tie'\n if (both('plant')) return 'stem'\n if (any('plant')) return 'tie'\n if (both('masonry')) return 'mortar'\n if (any('masonry') && any('metal')) return 'bolt'\n if (both('metal')) return 'weld'\n if (any('plastic')) return 'clip'\n if (any('rubber') || any('wax')) return 'glue'\n return 'screw'\n}\n\nconst MATERIAL_MAP: ReadonlyMap<MaterialId, MaterialDef> = new Map(MATERIALS.map((m) => [m.id, m]))\n\nconst HINTS = Object.entries(hintsJson as Record<string, string>).sort((x, y) => y[0].length - x[0].length)\n\n/** Guess a material id from a mesh or node name (case-insensitive substring; the longest keyword wins). */\nexport const guessMaterial = (name: string): MaterialId | undefined => {\n const n = name.toLowerCase()\n for (const [key, id] of HINTS) if (n.includes(key)) return id\n return undefined\n}\n\n/** Volume of a shape in m³. */\nexport const partVolume = (shape: PartShape): number => {\n if (shape.kind === 'box') return shape.size[0] * shape.size[1] * shape.size[2]\n if (shape.kind === 'cylinder') return Math.PI * shape.radius * shape.radius * shape.height\n return (4 / 3) * Math.PI * shape.radius ** 3\n}\n\n/** Mass of a part in kg: its `mass`, or density × volume × fill. */\nexport const partMass = (part: PartSpec, material: MaterialDef): number => part.mass ?? material.density * partVolume(part.shape) * (part.fill ?? 1)\n\n/** Wall thickness of a part in metres (see `PartSpec.thickness`). */\nexport const partThickness = (part: PartSpec): number => {\n const dims = shapeDims(part.shape)\n const min = Math.min(dims[0], dims[1], dims[2])\n return Math.max(1e-4, Math.min(part.thickness ?? min * (part.fill ?? 1), min))\n}\n\n/**\n * Joints for touching parts. Two parts touch when their axis-aligned bounds (after rotation), grown by `tolerance` metres, overlap. The kind comes\n * from `JOINT_BY_MATERIALS`; thick metal pairs (smallest dimension of both >= 2 cm) get a `bolt` instead of a `weld`, and thin wood pairs (either\n * under 2 cm) a `nail` instead of a `screw`.\n */\nexport const inferJoints = (parts: PartSpec[], tolerance = 0.01, materials: ReadonlyMap<string, MaterialDef> = MATERIAL_MAP): JointSpec[] => {\n const boxes = parts.map((p) => aabbOf(p.shape, p.position, quatFromEuler(...(p.rotation ?? [0, 0, 0]))))\n const out: JointSpec[] = []\n for (let i = 0; i < parts.length; i++) {\n for (let j = i + 1; j < parts.length; j++) {\n const a = boxes[i], b = boxes[j]\n let touch = true\n for (let k = 0; k < 3 && touch; k++) if (a.min[k] - tolerance > b.max[k] || b.min[k] - tolerance > a.max[k]) touch = false\n if (!touch) continue\n const ma = materials.get(parts[i].material)\n const mb = materials.get(parts[j].material)\n let kind: JointKind = ma && mb ? JOINT_BY_MATERIALS(ma, mb) : 'screw'\n const thin = Math.min(partThickness(parts[i]), partThickness(parts[j]))\n if (kind === 'weld' && thin >= 0.02) kind = 'bolt'\n if (kind === 'screw' && ma && mb && has(ma, 'wood') && has(mb, 'wood') && thin < 0.02) kind = 'nail'\n out.push({ id: `${parts[i].id}~${parts[j].id}`, a: parts[i].id, b: parts[j].id, kind })\n }\n }\n return out\n}\n\n/**\n * Load in kg a structural part carries before it fails in compression: `structure.capacity`, else the section times the material's strength. The\n * section is the product of the two smallest dimensions (thickness times longest dimension for slabs; thickness times horizontal length for walls);\n * foundations get x10. With `material.strength` (real values) the strength is `compressiveMPa`: a slender masonry or plain concrete wall or pillar keeps\n * `slendernessFactor` of it (the unavoidable eccentricity and its height over thickness), a reinforced pillar carries `0.85 * fck * Ac + As * fy`\n * (NBR 6118). Without it, the game-tuned `material.compressive` (default 20 000 kg/m²).\n */\nexport const partCapacity = (part: PartSpec, material: MaterialDef, options: { masonry?: MasonryOptions; flexure?: FlexureOptions } = {}): number => {\n if (part.structure?.capacity !== undefined) return part.structure.capacity\n const d = shapeDims(part.shape).sort((a, b) => a - b)\n const role = part.structure?.role\n const sh = shapeDims(part.shape)\n const section = role === 'wall' || role === 'partition' ? Math.min(sh[0], sh[2]) * Math.max(sh[0], sh[2]) : role === 'slab' ? d[0] * d[2] : d[0] * d[1]\n const foundation = role === 'foundation' ? 10 : 1\n const strength = material.strength\n if (!strength) return Math.max(1, section * (material.compressive ?? 20000) * foundation)\n const fc = strength.compressiveMPa * 1e6\n let newtons = fc * section\n const upright = role === 'wall' || role === 'partition' || role === 'column'\n if (upright && isSlender(part, material)) newtons *= slendernessFactor(sh[1], Math.min(sh[0], sh[2]), options.masonry)\n else if (role === 'column' && part.reinforcement) {\n const m = resolveMasonry(options.masonry)\n const bars = rebarBars(sh, thinAxisOf(sh), part.reinforcement.spacing).length\n const steel = bars * Math.PI * (part.reinforcement.diameter / 2) ** 2\n newtons = m.concreteFactor * fc * section + steel * resolveFlexure(options.flexure).rebarYieldMPa * 1e6\n }\n return Math.max(1, (newtons / GRAVITY) * foundation)\n}\n\n\n/**\n * Multiplier of blunt damage on brittle parts (ductility < 0.3): up to x4.7 for fully brittle materials (glass, ceramic, stone), times a thinness\n * term that follows bending stress (1 / thickness squared, x1 at 2 cm or more, at most x25). A 3 mm glass bottle breaks from a 1.5 m drop; a\n * concrete block (thick) is only ever x4.4.\n */\nexport const fragility = (ductility: number, thickness: number): number => {\n if (ductility >= 0.3) return 1\n return (1 + (4 * (0.3 - ductility)) / 0.3) * Math.min(25, Math.max(1, (0.02 / Math.max(thickness, 1e-4)) ** 2))\n}\n","import type { Vec3 } from './destruction'\n\n/**\n * The numbers of the shove a blast gives to a body that moves (a loose item, a piece of furniture, a person): all of them a game value, with a default that reads well in a room,\n * not a physical table. A host reads them once and lends them to the modules that move their own bodies (`ModuleHost.blastShove`).\n */\nexport interface BlastShoveOptions {\n /**\n * The share of the blast energy that reaches a body as motion: the speed at the centre is `sqrt(2 * energy * coupling / mass)`, before the falloff (default 0.02).\n */\n readonly coupling?: number\n /** Fastest a body is thrown, in m/s, at the centre of the blast (default 20). */\n readonly maxSpeed?: number\n /** How much of the push goes up: the direction is `(away, lift)` normalised from the horizontal outward direction (default 0.3). */\n readonly lift?: number\n /** Below this speed (m/s) nothing moves: a heavy thing far from a small blast stays where it is (default 0.3). */\n readonly minSpeed?: number\n /** Exponent of the falloff `(1 - distance / radius) ^ power`, the same as the damage of the destruction world (default 2). */\n readonly falloffPower?: number\n}\n\n/** The defaults of `BlastShoveOptions`. */\nexport const DEFAULT_BLAST_SHOVE: Readonly<Required<BlastShoveOptions>> = { coupling: 0.02, maxSpeed: 20, lift: 0.3, minSpeed: 0.3, falloffPower: 2 }\n\n/** A blast as the shove reads it: where, how much energy (J) and how far it reaches (m). `reach` (0..1) is the share that got through what stood in the way. */\nexport interface BlastSource {\n readonly point: Vec3\n readonly energy: number\n readonly radius: number\n readonly reach?: number\n /**\n * Kilograms of TNT equivalent of the charge. With it a body is pushed by the blast wave itself (`blast-impulse`), and the shove of loose items keeps this module's rule; without it the body\n * takes the charge from `energy` by `BlastImpulseOptions.tntPerJoule`.\n */\n readonly tnt?: number\n /** Inside this radius (metres) the blast is lethal: a body there that the blast reaches (not behind cover) goes down, wounded, wherever the wave pushed it. */\n readonly lethalRadius?: number\n}\n\n/** What a blast does to one body: how fast it leaves (m/s), the unit direction it leaves in, and how far from the centre it was. */\nexport interface BlastShove {\n readonly speed: number\n readonly direction: Vec3\n readonly distance: number\n /** The falloff applied, 0..1. */\n readonly falloff: number\n}\n\nconst clampShare = (share: number): number => Math.min(1, Math.max(0, share))\n\n/**\n * The shove a blast gives to a body of `mass` kg whose centre is at `position`: away from the centre, lifted a little, with the speed\n * `sqrt(reach) * min(maxSpeed, sqrt(2 * energy * coupling / mass)) * (1 - distance / radius) ^ 2`. Undefined when the body is outside the radius or the speed is under `minSpeed`.\n * The same rule moves the loose items and furniture of the test room and the people of the characters module, so a game that tunes the options tunes all of them.\n */\nexport function blastShove(blast: BlastSource, target: { readonly position: Vec3; readonly mass: number }, options: BlastShoveOptions = {}): BlastShove | undefined {\n const o = { ...DEFAULT_BLAST_SHOVE, ...options }\n const dx = target.position[0] - blast.point[0]\n const dy = target.position[1] - blast.point[1]\n const dz = target.position[2] - blast.point[2]\n const distance = Math.hypot(dx, dy, dz)\n if (!(blast.radius > 0) || distance > blast.radius) return undefined\n const falloff = (1 - distance / blast.radius) ** o.falloffPower\n const mass = Math.max(target.mass, 0.05)\n // cover takes its share off the push itself, past the cap too: a light thing behind a cupboard is not thrown as fast as one in the open\n const reach = clampShare(blast.reach ?? 1)\n const speed = Math.sqrt(reach) * Math.min(o.maxSpeed, Math.sqrt((2 * blast.energy * o.coupling) / mass)) * falloff\n if (!(speed >= o.minSpeed)) return undefined\n // straight above or below the centre there is no \"away\": the push goes up\n const direction: Vec3 = distance > 1e-4 ? [dx / distance, dy / distance + o.lift, dz / distance] : [0, 1, 0]\n const length = Math.hypot(direction[0], direction[1], direction[2])\n return { speed, direction: [direction[0] / length, direction[1] / length, direction[2] / length], distance, falloff }\n}\n","/**\n * The push a blast gives a standing body, from the physics of the blast wave and not from a game coupling: the impulse of the wave per square metre at a distance from a charge of\n * `tnt` kg of TNT equivalent (Kinney and Graham's fit of the side-on impulse, scaled by the cube root of the charge), reflected on the body, over the area the body shows the wave,\n * divided by its mass. A hand grenade at 3 m gives a person a few tenths of a metre per second; what floors that person is the fragments, not the wave. A big charge close throws.\n */\n\n/** The numbers of the body a blast wave pushes. All have a default for a standing adult. */\nexport interface BlastImpulseOptions {\n /** Square metres of the body the wave meets: about 1.75 m tall by 0.4 m wide (default 0.7). */\n readonly bodyArea?: number\n /** How much of the push goes up: the direction is `(away, lift)` normalised (default 0.15: the wave runs along the ground). */\n readonly lift?: number\n /** Below this speed (m/s) the body does not move (default 0.3). */\n readonly minSpeed?: number\n /**\n * Kilograms of TNT per joule of the blast `energy`, for a blast that does not say its charge (`BlastSource.tnt`). Default 0.24 / 200000: the arsenal's energy scale, where the M67 (180 g\n * of Composition B, 0.24 kg of TNT) is 200 kJ. It is a game equivalence for blasts without a charge, not a physical constant.\n */\n readonly tntPerJoule?: number\n}\n\nexport const DEFAULT_BLAST_IMPULSE: Readonly<Required<BlastImpulseOptions>> = { bodyArea: 0.7, lift: 0.15, minSpeed: 0.3, tntPerJoule: 0.24 / 200000 }\n\n/** Closest distance (m) the fit is read at: inside it the charge is in contact and the body is torn apart anyway. */\nconst NEAREST = 0.3\n\n/**\n * Side-on (incident) specific impulse of the wave, in Pa·s, at `distance` metres from `tnt` kg of TNT in free air: Kinney and Graham, \"Explosive Shocks in Air\" (1985),\n * `I/W^(1/3) = 0.067 sqrt(1 + (Z/0.23)^4) / (Z^2 (1 + (Z/1.55)^3)^(1/3))` bar·ms per kg^(1/3), with the scaled distance `Z = R / W^(1/3)`.\n */\nexport function sideOnImpulse(tnt: number, distance: number): number {\n if (!(tnt > 0)) return 0\n const w3 = Math.cbrt(tnt)\n const z = Math.max(distance, NEAREST) / w3\n const scaled = (0.067 * Math.sqrt(1 + (z / 0.23) ** 4)) / (z * z * Math.cbrt(1 + (z / 1.55) ** 3))\n return scaled * w3 * 100 // bar·ms to Pa·s\n}\n\n/** Sea-level atmospheric pressure, Pa. */\nconst ATMOSPHERE = 101325\n\n/**\n * Peak side-on (incident) overpressure of the wave, in Pa, at `distance` metres from `tnt` kg of TNT in free air: Kinney and Graham, \"Explosive Shocks in Air\" (1985),\n * `Ps/Pa = 808 (1 + (Z/4.5)^2) / (sqrt(1 + (Z/0.048)^2) sqrt(1 + (Z/0.32)^2) sqrt(1 + (Z/1.35)^2))`, with the scaled distance `Z = R / W^(1/3)` (m/kg^(1/3)).\n * What a wall takes from a blast is read against it: about 7 kPa cracks plaster and breaks windows, 14 to 20 kPa knocks parts of a brick wall out, 35 kPa and over brings an\n * unreinforced brick wall down (Glasstone and Dolan, \"The Effects of Nuclear Weapons\", 1977, table 5.139; UFC 3-340-02).\n */\nexport function sideOnOverpressure(tnt: number, distance: number): number {\n if (!(tnt > 0)) return 0\n const z = Math.max(distance, NEAREST) / Math.cbrt(tnt)\n const ratio = (808 * (1 + (z / 4.5) ** 2)) / (Math.sqrt(1 + (z / 0.048) ** 2) * Math.sqrt(1 + (z / 0.32) ** 2) * Math.sqrt(1 + (z / 1.35) ** 2))\n return ratio * ATMOSPHERE\n}\n\n/**\n * The impulse per square metre a body facing the wave takes, Pa·s: the side-on impulse reflected. The reflection doubles a weak wave and grows up to about six times close to the charge,\n * where the wave is strong (the ratio of reflected to side-on impulse of the Kingery-Bulmash charts, fitted as `2 + 4 / (1 + Z^2)`).\n */\nexport function bodyImpulse(tnt: number, distance: number): number {\n if (!(tnt > 0)) return 0\n const z = Math.max(distance, NEAREST) / Math.cbrt(tnt)\n return sideOnImpulse(tnt, distance) * (2 + 4 / (1 + z * z))\n}\n\n/** The speed (m/s) a blast wave gives a free body of `mass` kg at `distance` metres from `tnt` kg of TNT, `reach` (0..1) of it getting through what stands in the way. */\nexport function blastBodySpeed(tnt: number, distance: number, mass: number, reach = 1, options: BlastImpulseOptions = {}): number {\n const area = options.bodyArea ?? DEFAULT_BLAST_IMPULSE.bodyArea\n return (bodyImpulse(tnt, distance) * area * Math.max(0, reach)) / Math.max(mass, 1)\n}\n","import { blastBodySpeed, DEFAULT_BLAST_IMPULSE } from './blast-impulse'\nimport type { BlastImpulseOptions } from './blast-impulse'\nimport type { BlastShoveOptions, BlastSource } from './blast-shove'\nimport type { Vec3 } from './destruction'\n\n/** From this speed (m/s) a blast takes a standing body off its feet. Below it the body is only pushed. */\nexport const KNOCK_DOWN_SPEED = 2.5\n/** The angle of a body lying where it fell (the same tilt a dead body takes). */\nexport const KNOCKED_DOWN_ANGLE = 1.35\n/** Seconds the body lies after it lands: this plus the landing speed times `STAND_UP_PER_SPEED`. */\nconst LIE_SECONDS = 1.6\n/** Seconds a body floored by its wounds (inside the lethal radius) lies before it gets up, when it is not dead. */\nconst WOUNDED_LIE_SECONDS = 6\n/** The share of the blast that has to get through for its fragments to reach a body: behind cover that stops half of it the fragments stop too. */\nexport const FRAGMENT_COVER = 0.5\n/** Seconds a body is stunned at the edge of the lethal radius (the ringing ears, the dizziness); it falls with the square of the way to the edge of the blast. */\nconst STUN_SECONDS = 4\nconst STAND_UP_PER_SPEED = 0.25\nconst FALL_SECONDS = 0.25\nconst RISE_SECONDS = 0.6\n/** m/s squared that slows a body sliding on the ground. */\nconst GROUND_FRICTION = 7\nconst GRAVITY = 9.81\n/** Height of the chest above the feet: where the blast takes the body. */\nexport const KNOCK_CHEST = 1.1\nconst CHEST = KNOCK_CHEST\n\n/** What a blast is doing to one body: its velocity (m/s), whether it is in the air, and how far down it is (0 on its feet, 1 lying). */\nexport interface Knock {\n velocity: [number, number, number]\n airborne: boolean\n /** 0..1 */\n lying: number\n /** Seconds left to lie on the ground after it stopped. */\n lieLeft: number\n /** Knocked off its feet by this blast. */\n down: boolean\n /** Floored by its wounds: inside the lethal radius and not behind cover. It lies longer and falls where it stood. */\n wounded?: boolean\n /** Seconds of stun the blast gave the body: dizziness and ringing ears. */\n stunSeconds?: number\n /** The horizontal unit direction away from the blast, even when the push is too weak to move the body: the way it falls. */\n away?: Vec3\n}\n\n/** The mass of a body in kg from its height (m) and its build (1 = average): 70 kg at 1.75 m. */\nexport const bodyMass = (height: number, build = 1): number => 70 * (height / 1.75) ** 2 * build\n\n/**\n * What a blast does to a body standing at `feet`, of `mass` kg. Undefined when the blast does not reach it or does nothing to it.\n *\n * The body is pushed by the blast wave (`blastBodySpeed`, from the charge `blast.tnt`, or from `energy` by `tntPerJoule`), taken at the chest and cut by `reach`, the share that got through\n * cover. It is floored when that push is `KNOCK_DOWN_SPEED` or more, or when it stands inside `lethalRadius` with the blast reaching it (the fragments and the overpressure fell it where it\n * stands). It is stunned for a while inside the radius. `options` are the shove numbers of the host's loose items; only their `minSpeed` applies to a body.\n */\nexport function knockOf(blast: BlastSource, feet: Vec3, mass: number, options?: BlastShoveOptions, impulse: BlastImpulseOptions = {}): Knock | undefined {\n const o = { ...DEFAULT_BLAST_IMPULSE, ...impulse }\n const chest: Vec3 = [feet[0], feet[1] + CHEST, feet[2]]\n const dx = chest[0] - blast.point[0]\n const dy = chest[1] - blast.point[1]\n const dz = chest[2] - blast.point[2]\n const distance = Math.hypot(dx, dy, dz)\n if (!(blast.radius > 0) || distance > blast.radius) return undefined\n const reach = Math.max(0, Math.min(1, blast.reach ?? 1))\n const tnt = blast.tnt ?? blast.energy * o.tntPerJoule\n let speed = blastBodySpeed(tnt, distance, mass, reach, o)\n const minSpeed = impulse.minSpeed ?? options?.minSpeed ?? o.minSpeed\n if (speed < minSpeed) speed = 0\n const struck = reach >= FRAGMENT_COVER\n const wounded = struck && blast.lethalRadius !== undefined && distance <= blast.lethalRadius\n const edge = 1 - distance / blast.radius\n const stunSeconds = struck ? STUN_SECONDS * edge * edge * reach : 0\n if (speed === 0 && !wounded && stunSeconds < 0.25) return undefined\n // straight above or below the centre there is no \"away\": the push goes up\n const horizontal = Math.hypot(dx, dz)\n const away: Vec3 = horizontal > 1e-4 ? [dx / horizontal, o.lift, dz / horizontal] : [0, 1, 0]\n const length = Math.hypot(away[0], away[1], away[2])\n const velocity: [number, number, number] = [(away[0] / length) * speed, (away[1] / length) * speed, (away[2] / length) * speed]\n return {\n velocity,\n airborne: velocity[1] > 0.5,\n lying: 0,\n lieLeft: wounded ? WOUNDED_LIE_SECONDS : 0,\n away: horizontal > 1e-4 ? [dx / horizontal, 0, dz / horizontal] : [0, 0, 0],\n down: speed >= KNOCK_DOWN_SPEED || wounded,\n ...(wounded ? { wounded } : {}),\n ...(stunSeconds >= 0.25 ? { stunSeconds } : {}),\n }\n}\n\n/**\n * Moves a body one step: it slides on the ground and slows, falls when it was knocked down, lies a while and gets up (a dead body stays down). Moves `position` in place; returns true when the\n * body is on its feet and still, and the knock can be dropped.\n */\nexport function stepKnock(knock: Knock, position: { x: number; y: number; z: number }, dt: number, groundAt: (x: number, z: number) => number, alive: boolean): boolean {\n const v = knock.velocity\n position.x += v[0] * dt\n position.z += v[2] * dt\n const ground = groundAt(position.x, position.z)\n if (knock.airborne || position.y > ground + 1e-4) {\n v[1] -= GRAVITY * dt\n position.y += v[1] * dt\n if (position.y <= ground) {\n position.y = ground\n v[1] = 0\n knock.airborne = false\n }\n } else position.y = ground\n const horizontal = Math.hypot(v[0], v[2])\n if (!knock.airborne && horizontal > 0) {\n const slowed = Math.max(0, horizontal - GROUND_FRICTION * dt)\n v[0] *= slowed / horizontal\n v[2] *= slowed / horizontal\n }\n const moving = horizontal > 0.05 || knock.airborne\n if (knock.down) {\n // a body floored where it stands (its wounds, not the push) still takes the time of a fall to reach the ground\n if (moving || knock.lying < 1) knock.lying = Math.min(1, knock.lying + dt / FALL_SECONDS)\n else if (alive) {\n knock.lieLeft = knock.lieLeft > 0 ? knock.lieLeft : LIE_SECONDS + Math.hypot(v[0], v[2]) * STAND_UP_PER_SPEED\n knock.lieLeft -= dt\n if (knock.lieLeft <= 0) knock.down = false\n }\n } else if (knock.lying > 0) knock.lying = Math.max(0, knock.lying - dt / RISE_SECONDS)\n return !moving && !knock.down && knock.lying === 0\n}\n\n/** Where `launchBody` leaves the throw on the body's root until the module that animates it takes it. */\nconst LAUNCHED = 'launched'\n\n/**\n * Throws a body at `velocity` (m/s, world): an occupant leaving a car through the glass, a pedestrian run over. The module that animates the body\n * takes it on its next frame (`takeLaunch`) and moves it as it moves a body a blast knocked down: flying, landing, sliding, lying, getting up.\n */\nexport function launchBody(root: { userData: Record<string, unknown> }, velocity: Vec3): void {\n root.userData[LAUNCHED] = [velocity[0], velocity[1], velocity[2]]\n}\n\n/** The throw `launchBody` left on the root, as a knock (knocked down, in the air), once; undefined when nothing threw it. */\nexport function takeLaunch(root: { userData: Record<string, unknown> }): Knock | undefined {\n const velocity = root.userData[LAUNCHED] as Vec3 | undefined\n if (!velocity) return undefined\n delete root.userData[LAUNCHED]\n return { velocity: [velocity[0], velocity[1], velocity[2]], airborne: true, lying: 0, lieLeft: 0, down: true }\n}\n","export interface CostOptions {\n /** Reads of `state()` and of `describe()` to time. Default 10 000. */\n reads?: number\n /** Ceiling, in milliseconds, for all the reads of one method. Default 50 (5 microseconds per read). */\n ceilingMs?: number\n /** Ceiling of heap growth, in bytes, over all the reads of one method (only where `process.memoryUsage` exists). Default 1 MiB. */\n allocationBytes?: number\n}\n\nconst DEFAULT_COST_READS = 10_000\nconst DEFAULT_COST_CEILING_MS = 50\nconst DEFAULT_COST_ALLOCATION_BYTES = 1024 * 1024\n\nconst heapUsedBytes = (): number | undefined => {\n const nodeProcess = (globalThis as { process?: { memoryUsage?: () => { heapUsed: number } } }).process\n return nodeProcess?.memoryUsage?.().heapUsed\n}\n\ntype CheckReadCostParams = { readonly name: string; readonly read: () => unknown; readonly options: CostOptions; readonly problems: string[] }\n\nexport const checkReadCost = ({ name, read, options, problems }: CheckReadCostParams): void => {\n const reads = options.reads ?? DEFAULT_COST_READS\n const ceilingMs = options.ceilingMs ?? DEFAULT_COST_CEILING_MS\n const allocationBytes = options.allocationBytes ?? DEFAULT_COST_ALLOCATION_BYTES\n if (read() !== read()) problems.push(`${name}() returns a new object on each read: cache it between changes (cost contract)`)\n // a first pass lets the engine compile and optimise the loop: that code and its feedback are heap too, and would read as the method allocating\n for (let i = 0; i < reads; i++) read()\n const heapBefore = heapUsedBytes()\n const started = performance.now()\n for (let i = 0; i < reads; i++) read()\n const elapsedMs = performance.now() - started\n const heapAfter = heapUsedBytes()\n if (elapsedMs > ceilingMs) problems.push(`${name}() took ${elapsedMs.toFixed(1)} ms for ${reads} reads, over the ${ceilingMs} ms ceiling (cost contract)`)\n if (heapBefore !== undefined && heapAfter !== undefined && heapAfter - heapBefore > allocationBytes)\n problems.push(`${name}() grew the heap by ${heapAfter - heapBefore} bytes over ${reads} reads, over the ${allocationBytes} byte ceiling (cost contract)`)\n}\n","import { checkReadCost } from './impact-cost'\nimport type { CostOptions } from './impact-cost'\nimport type { DamageType, DestructibleSpec, DestructionEvent, Hit, JointSpec, ObjectState, ToolKind, Vec3 } from './destruction'\n\n/**\n * What a game module implements for an object whose behaviour it owns (a vehicle with its own panel deformation, a creature, a machine). The\n * world (`DestructionWorld.register`) hosts it next to its own objects: raycast, shoot, explode, hit, disassemble, extinguish, update, state,\n * reset and `on` all route to it.\n *\n * Space: the impl receives hits in WORLD space and returns events in WORLD space (it owns its transform; the transform given to `register` or\n * `setTransform` is only used by the world for raycasts and blast range). Every event must carry `object === id` and name parts listed by\n * `describe()`.\n */\n/** World-space ray for `DestructibleImpl.surfaceRay`. */\nexport interface SurfaceRay {\n readonly origin: Vec3\n readonly direction: Vec3\n readonly maxDistance: number\n ignored?(part: string): boolean\n}\n\nexport interface SurfaceRayHit {\n readonly part: string\n readonly point: Vec3\n readonly normal: Vec3\n readonly distance: number\n /** Thickness the ray crosses in this part, metres. */\n readonly pathLen: number\n}\n\nexport interface DestructibleImpl {\n readonly id: string\n readonly name?: string\n /**\n * Parts, joints and structure in the impl's local space, for raycast, inspector and log.\n * COST CONTRACT (D8): called per frame by the renderer, so it is O(1), allocation-free and cached between changes: the same object comes\n * back until a hit, tool, fire or pose change alters it. `checkDestructible(impl, { cost: true })` measures it.\n */\n describe(): DestructibleSpec\n /** Apply one hit (see `IMPACT_CONTRACT` for the fields per type) and return the events it caused. */\n hit(hit: Hit): DestructionEvent[]\n /**\n * The real surface a ray meets, for an impl whose drawn shape is not its boxes (a car body): the boxes of `describe()` only say where to look, and a shot that crosses\n * them without touching the drawn surface goes on. `ignored` answers for the parts the round already went through. Null when the ray meets nothing.\n */\n surfaceRay?(ray: SurfaceRay): SurfaceRayHit | null\n /** Advance fire, melting, collapse and other timed behaviour. */\n update?(dt: number): DestructionEvent[]\n /**\n * COST CONTRACT (D8): the host reads it per part per frame, so it is O(1), allocation-free and cached between changes (see `describe()`).\n * The cached object is shared with every reader: treat it as read-only, copy before changing it.\n */\n state(): Readonly<ObjectState>\n reset?(): void\n /** The world took the object out (`DestructionWorld.remove`): the impl lets go of what it joined (shared queues, listeners). */\n dispose?(): void\n /** Same contract as `DestructionWorld.disassemble`: progress 0..1, or -1 when the tool cannot undo the joint. */\n disassemble?(jointId: string, tool: ToolKind, dt: number): number\n extinguish?(partId?: string): void\n /** Optional: an animation moved a part; `position` / `rotation` (Euler XYZ, radians) are object-local. Keep raycast and hit shapes in sync. */\n setPartPose?(partId: string, position: Vec3, rotation?: Vec3): void\n /** Plain JSON of the impl's own state, stored in `DestructionSnapshot.impls`. */\n serialize?(): unknown\n load?(data: unknown): void\n}\n\n/** The fields a weapon or hazard must put in a `Hit`, per damage type. THE impact contract. */\nexport interface ImpactContract {\n required: string[]\n optional: string[]\n note: string\n}\n\nexport const IMPACT_CONTRACT: Record<DamageType, ImpactContract> = {\n ballistic: { required: ['type', 'point', 'direction', 'energy', 'caliber'], optional: ['space', 'source'], note: 'bullets and pellets: joules and diameter in millimetres' },\n blunt: { required: ['type', 'point', 'energy'], optional: ['direction', 'radius', 'space', 'source'], note: 'contact radius in metres (default 3 cm)' },\n slash: { required: ['type', 'point', 'energy'], optional: ['direction', 'radius', 'space', 'source'], note: 'axes, knives, machetes' },\n explosive: { required: ['type', 'point', 'energy', 'radius'], optional: ['lethalRadius', 'space', 'source'], note: 'point is the centre of the blast, radius the range in metres' },\n fire: { required: ['type', 'point', 'temperature', 'radius'], optional: ['duration', 'space', 'source'], note: 'flame temperature in °C; duration in seconds (call every frame with `dt`)' },\n heat: { required: ['type', 'point', 'temperature', 'radius'], optional: ['duration', 'space', 'source'], note: 'heat without flame (cutting torch, hot plate)' },\n}\n\n/** Problems with a hit according to the impact contract (empty when it is valid). */\nexport const checkHit = (hit: Hit): string[] => {\n const c = IMPACT_CONTRACT[hit.type]\n if (!c) return [`unknown damage type \"${String(hit.type)}\"`]\n const out: string[] = []\n for (const f of c.required) {\n const v = (hit as unknown as Record<string, unknown>)[f]\n if (v === undefined || (Array.isArray(v) ? v.some((n) => !Number.isFinite(n)) : typeof v === 'number' && !Number.isFinite(v))) out.push(`${hit.type} hit needs \"${f}\"`)\n }\n return out\n}\n\nexport interface CheckOptions {\n /**\n * Ids of every material the impl may use (the contracts package does not know the materials of your world: pass the ids of\n * `world.materials`, or the built-in plus your own). When omitted, the material check is skipped.\n */\n materials?: Iterable<string>\n /** Opt-in cost measurement (D8): `true` for the defaults, or the limits to use. */\n cost?: boolean | CostOptions\n}\n\nconst finiteJson = (v: unknown, path: string, out: string[]) => {\n if (typeof v === 'number') {\n if (!Number.isFinite(v)) out.push(`${path} is not a finite number`)\n } else if (Array.isArray(v)) v.forEach((x, i) => finiteJson(x, `${path}[${i}]`, out))\n else if (v && typeof v === 'object') for (const [k, x] of Object.entries(v)) finiteJson(x, `${path}.${k}`, out)\n else if (typeof v === 'function' || typeof v === 'symbol' || typeof v === 'bigint') out.push(`${path} is not JSON`)\n}\n\n/**\n * Contract checker for the test room (it needs no world): `describe()` is valid, a 500 J ballistic hit at a part centre returns well-formed events of this impl, `state()`\n * matches `describe()`, hit points never go negative, `update(0.016)` returns an array and every event is JSON-serializable. It hits the impl\n * (and calls `reset()` afterwards when there is one). With `options.cost` it also times `state()` and `describe()` (the cost contract of D8).\n */\nexport const checkDestructible = (impl: DestructibleImpl, options: CheckOptions = {}): { ok: boolean; problems: string[] } => {\n const problems: string[] = []\n const known = options.materials ? new Set(options.materials) : null\n let spec: DestructibleSpec | undefined\n try {\n spec = impl.describe()\n } catch (e) {\n return { ok: false, problems: [`describe() threw: ${String(e)}`] }\n }\n if (!spec || !Array.isArray(spec.parts) || spec.parts.length === 0) return { ok: false, problems: ['describe() must return at least one part'] }\n const ids = new Set<string>()\n for (const p of spec.parts) {\n if (ids.has(p.id)) problems.push(`duplicate part id \"${p.id}\"`)\n ids.add(p.id)\n if (known && !known.has(p.material)) problems.push(`part \"${p.id}\" has unknown material \"${p.material}\"`)\n if (!p.shape || !['box', 'cylinder', 'sphere'].includes(p.shape.kind)) problems.push(`part \"${p.id}\" has no valid shape`)\n if (!Array.isArray(p.position) || p.position.length !== 3) problems.push(`part \"${p.id}\" has no position`)\n }\n const jointIds = new Set<string>()\n for (const j of (spec.joints ?? []) as JointSpec[]) {\n if (!ids.has(j.a) || !ids.has(j.b)) problems.push(`joint \"${j.id ?? `${j.a}~${j.b}`}\" references an unknown part`)\n const jid = j.id ?? `${j.a}~${j.b}`\n if (jointIds.has(jid)) problems.push(`duplicate joint id \"${jid}\"`)\n jointIds.add(jid)\n }\n const checkState = (label: string) => {\n let st: ObjectState\n try {\n st = impl.state()\n } catch (e) {\n problems.push(`state() threw ${label}: ${String(e)}`)\n return\n }\n const sids = st.parts.map((p) => p.id).sort().join(',')\n if (sids !== [...ids].sort().join(',')) problems.push(`state() part ids do not match describe() ${label}`)\n for (const p of st.parts) if (!(p.hp >= 0)) problems.push(`part \"${p.id}\" has negative or invalid hp ${label}`)\n }\n const checkEvents = (events: unknown, label: string) => {\n if (!Array.isArray(events)) {\n problems.push(`${label} must return an array`)\n return\n }\n const evs = events as DestructionEvent[]\n evs.forEach((e, i) => {\n if (e.object !== impl.id) problems.push(`${label} event ${i} (${e.type}) has object \"${String(e.object)}\", expected \"${impl.id}\"`)\n const part = (e as { part?: string }).part\n if (part !== undefined && !ids.has(part)) problems.push(`${label} event ${i} (${e.type}) names unknown part \"${part}\"`)\n })\n const bad: string[] = []\n finiteJson(evs, 'events', bad)\n problems.push(...bad.map((b) => `${label}: ${b}`))\n try {\n const s = JSON.stringify(evs)\n if (JSON.stringify(JSON.parse(s)) !== s) problems.push(`${label} events do not survive a JSON round trip`)\n } catch (e) {\n problems.push(`${label} events are not JSON-serializable: ${String(e)}`)\n }\n }\n checkState('before the hit')\n const target = spec.parts[0]\n try {\n const hit: Hit = { type: 'ballistic', point: [target.position[0], target.position[1], target.position[2]], direction: [0, 0, -1], energy: 500, caliber: 9 }\n checkEvents(impl.hit(hit), 'hit()')\n } catch (e) {\n problems.push(`hit() threw: ${String(e)}`)\n }\n checkState('after the hit')\n if (impl.update) {\n try {\n checkEvents(impl.update(0.016), 'update()')\n } catch (e) {\n problems.push(`update() threw: ${String(e)}`)\n }\n checkState('after update')\n }\n try {\n impl.reset?.()\n } catch (e) {\n problems.push(`reset() threw: ${String(e)}`)\n }\n if (options.cost) {\n const cost = options.cost === true ? {} : options.cost\n try {\n checkReadCost({ name: 'state', read: () => impl.state(), options: cost, problems })\n checkReadCost({ name: 'describe', read: () => impl.describe(), options: cost, problems })\n } catch (e) {\n problems.push(`cost measurement threw: ${String(e)}`)\n }\n }\n return { ok: problems.length === 0, problems }\n}\n","/** The slots of a body an item can cover (the item slot vocabulary: game-items imports it from here). */\nexport type BodySlot = 'head' | 'eyes' | 'torso' | 'arms' | 'hands' | 'legs' | 'feet' | 'over'\n\n/** The 11 segments of the detailed body model (the Arsenal ids). */\nexport type SegmentKind = 'head' | 'jaw' | 'neck' | 'torso' | 'pelvis' | 'upperArm' | 'forearm' | 'hand' | 'thigh' | 'shin' | 'foot'\n\n/** The 6 regions of the crowd model (the game regions 0..5). */\nexport type BodyRegion = 'head' | 'torso' | 'armL' | 'armR' | 'legL' | 'legR'\n\n/** Bits of the `missing` mask of a body. The instanced body shader reads them, so the values are part of the contract. */\nexport const MISSING_BITS = {\n head: 1,\n armL: 2,\n armR: 4,\n legL: 8,\n legR: 16,\n armLBroken: 32,\n armRBroken: 64,\n legLBroken: 128,\n legRBroken: 256,\n jaw: 512,\n} as const\n","import type { DestructibleSpec, PartSpec } from './destruction'\n\nexport interface CheckSpecOptions {\n /** Known material ids. When given, every part's material must be one of them. */\n materials?: Iterable<string>\n}\n\nexport interface SpecReport {\n /** False when there is at least one problem (warnings do not count). */\n ok: boolean\n problems: string[]\n /** Things that are legal but probably wrong, e.g. structural parts that cannot reach an anchored part. */\n warnings: string[]\n}\n\nconst STRUCTURE_ROLES = ['foundation', 'column', 'beam', 'slab', 'wall', 'partition', 'roof', 'stair', 'none']\nconst BEARS = [true, false, 'a_on_b', 'b_on_a']\n\nconst finite = (n: unknown): n is number => typeof n === 'number' && Number.isFinite(n)\nconst positive = (n: unknown): boolean => finite(n) && n > 0\nconst vec3 = (v: unknown): boolean => Array.isArray(v) && v.length === 3 && v.every(finite)\nconst nonNegative = (n: unknown): boolean => n === undefined || (finite(n) && n >= 0)\n\nconst FACES = ['both', '+', '-']\nconst BONDS = ['running', 'stack']\n\n/** Layers, reinforcement, units and breach: known materials, finite positive sizes. */\nconst checkStagedFields = (p: PartSpec | undefined, label: string, materials: Set<string> | null, problems: string[]): void => {\n const known = (m: unknown, what: string): void => {\n if (materials && !materials.has(m as string)) problems.push(`${label} ${what} has unknown material \"${String(m)}\"`)\n }\n ;(p?.layers ?? []).forEach((l, i) => {\n known(l?.material, `layer ${i}`)\n if (!positive(l?.thickness)) problems.push(`${label} layer ${i} thickness must be finite and positive`)\n if (!FACES.includes(l?.faces)) problems.push(`${label} layer ${i} has an invalid faces \"${String(l?.faces)}\"`)\n })\n const r = p?.reinforcement\n if (r) {\n known(r.material, 'reinforcement')\n if (!positive(r.spacing) || !positive(r.diameter)) problems.push(`${label} reinforcement spacing and diameter must be finite and positive`)\n if (r.residualCapacity !== undefined && !(finite(r.residualCapacity) && r.residualCapacity >= 0 && r.residualCapacity <= 1)) problems.push(`${label} reinforcement residualCapacity must be between 0 and 1`)\n }\n const u = p?.units\n if (u) {\n known(u.mortar, 'units mortar')\n if (!vec3(u.size) || !u.size.every(positive)) problems.push(`${label} units size must be three finite positive numbers`)\n if (!BONDS.includes(u.bond)) problems.push(`${label} units has an invalid bond \"${String(u.bond)}\"`)\n }\n if (p?.breach && p.breach.area !== undefined && !positive(p.breach.area)) problems.push(`${label} breach area must be finite and positive`)\n}\n\n/**\n * Static checks on a `DestructibleSpec` (no world needed), for items that give a `spec` instead of an `impl`: unique part ids, known materials\n * (when `options.materials` is given), joints that reference existing, different parts, finite positive sizes, non-negative mass / hp / capacity,\n * valid structure roles and `bears` directions. A structural part with no path of joints to an anchored part is a warning, not a problem: it\n * is allowed, it just falls.\n */\nexport const checkSpec = (spec: DestructibleSpec, options: CheckSpecOptions = {}): SpecReport => {\n const problems: string[] = []\n const warnings: string[] = []\n const materials = options.materials ? new Set(options.materials) : null\n const parts = Array.isArray(spec?.parts) ? spec.parts : []\n if (!Array.isArray(spec?.parts) || parts.length === 0) problems.push('the spec needs at least one part')\n const ids = new Set<string>()\n for (const p of parts) {\n const id = String(p?.id ?? '')\n const label = `part \"${id}\"`\n if (id === '') problems.push('a part has no id')\n else if (ids.has(id)) problems.push(`duplicate part id \"${id}\"`)\n ids.add(id)\n if (materials && !materials.has(p?.material)) problems.push(`${label} has unknown material \"${String(p?.material)}\"`)\n else if (typeof p?.material !== 'string' || p.material === '') problems.push(`${label} needs a material`)\n const s = p?.shape\n if (s?.kind === 'box') {\n if (!Array.isArray(s.size) || s.size.length !== 3 || !s.size.every(positive)) problems.push(`${label} box size must be three finite positive numbers`)\n } else if (s?.kind === 'cylinder') {\n if (!positive(s.radius) || !positive(s.height)) problems.push(`${label} cylinder radius and height must be finite and positive`)\n } else if (s?.kind === 'sphere') {\n if (!positive(s.radius)) problems.push(`${label} sphere radius must be finite and positive`)\n } else problems.push(`${label} has an unknown shape`)\n if (!vec3(p?.position)) problems.push(`${label} needs a finite position [x, y, z]`)\n if (p?.rotation !== undefined && !vec3(p.rotation)) problems.push(`${label} has an invalid rotation`)\n for (const f of ['mass', 'hp', 'thickness'] as const) if (!nonNegative(p?.[f])) problems.push(`${label} ${f} must be a finite number >= 0`)\n if (p?.fill !== undefined && !(finite(p.fill) && p.fill >= 0 && p.fill <= 1)) problems.push(`${label} fill must be between 0 and 1`)\n if (p?.structure) {\n if (!STRUCTURE_ROLES.includes(p.structure.role)) problems.push(`${label} has an invalid structure role \"${String(p.structure.role)}\"`)\n if (!nonNegative(p.structure.capacity)) problems.push(`${label} structure capacity must be a finite number >= 0`)\n }\n if (p?.contains && !nonNegative(p.contains.liters)) problems.push(`${label} contains.liters must be a finite number >= 0`)\n checkStagedFields(p, label, materials, problems)\n }\n\n const jointIds = new Set<string>()\n const edges: Array<[string, string]> = []\n for (const j of spec?.joints ?? []) {\n const id = j.id ?? `${j.a}~${j.b}`\n const label = `joint \"${id}\"`\n if (jointIds.has(id)) problems.push(`duplicate joint id \"${id}\"`)\n jointIds.add(id)\n if (!ids.has(j.a)) problems.push(`${label} references unknown part \"${String(j.a)}\"`)\n if (!ids.has(j.b)) problems.push(`${label} references unknown part \"${String(j.b)}\"`)\n if (j.a === j.b) problems.push(`${label} joins part \"${String(j.a)}\" to itself`)\n if (j.bears !== undefined && !BEARS.includes(j.bears)) problems.push(`${label} has an invalid bears \"${String(j.bears)}\"`)\n if (!nonNegative(j.strength)) problems.push(`${label} strength must be a finite number >= 0`)\n if (!nonNegative(j.seconds)) problems.push(`${label} seconds must be a finite number >= 0`)\n if (j.bears !== false && ids.has(j.a) && ids.has(j.b) && j.a !== j.b) edges.push([j.a, j.b])\n }\n\n // structural parts must reach an anchored part over the joints (only when the spec lists its joints: otherwise they are inferred later)\n const structural = parts.filter((p) => p?.structure && p.structure.role !== 'none')\n if (structural.length && spec.joints) {\n const anchored = parts.filter((p) => p.anchored || p.structure?.role === 'foundation').map((p) => p.id)\n const adj = new Map<string, string[]>()\n for (const [a, b] of edges) {\n adj.set(a, [...(adj.get(a) ?? []), b])\n adj.set(b, [...(adj.get(b) ?? []), a])\n }\n const seen = new Set(anchored)\n const queue = [...anchored]\n while (queue.length) {\n for (const n of adj.get(queue.pop()!) ?? []) {\n if (seen.has(n)) continue\n seen.add(n)\n queue.push(n)\n }\n }\n const lost = structural.filter((p) => !seen.has(p.id)).map((p) => p.id)\n if (lost.length) warnings.push(`structural part(s) ${lost.map((i) => `\"${i}\"`).join(', ')} cannot reach an anchored part, so they will fall`)\n }\n return { ok: problems.length === 0, problems, warnings }\n}\n","import type { BallisticExtras, Hit, HitIgnition, Vec3 } from './destruction'\n\n/**\n * A ballistic shot (one per pellet) as a weapon module produces it. Plain data: any damage model can consume it (`shotToHit` makes the `Hit`).\n */\nexport interface Shot {\n origin: Vec3\n /** Unit vector. */\n direction: Vec3\n /** Muzzle energy in joules. */\n energy: number\n /** Bullet diameter in millimetres. */\n caliber: number\n /** snake_case calibre id, e.g. `9x19`. */\n caliberId: string\n /** Muzzle speed in m/s. */\n speed: number\n /** Projectile mass in grams (one pellet for a shotgun load). */\n mass?: number\n /** Energy at a distance in metres, with the calibre's drag. */\n energyAt(distance: number): number\n pellet: number\n /** snake_case weapon id. */\n weapon: string\n source?: string\n /** Kind of the round that was loaded (`fmj`, `hp`, `ap`, `buck`, `slug`, `incendiary`, `tracer`...). */\n ammo?: string\n /** Millimetres of steel, concrete, brick and wood the round goes through at the muzzle (the ammo table of the weapons module). `shotToHit` scales it by the energy left. */\n penetration?: Readonly<Record<string, number>>\n incendiary?: boolean\n tracer?: boolean\n /** Chances that the round lights flammable vapour or fuel. */\n ignition?: HitIgnition\n}\n\n/**\n * The fields of the round that a damage model takes besides the geometry: the penetration by material scaled by the energy that is left at `distance`\n * (linear in the energy: half the energy goes through half as much), the incendiary and tracer flags and the ignition chances. Pass it as the sixth\n * argument of `DestructionWorld.shoot` or spread it in a `Hit`.\n */\nexport const shotExtras = (shot: Shot, distance = 0): BallisticExtras => {\n const out: { -readonly [K in keyof BallisticExtras]: BallisticExtras[K] } = {}\n if (shot.penetration) {\n const k = shot.energy > 0 ? Math.min(1, Math.max(0, shot.energyAt(distance) / shot.energy)) : 1\n const scaled: Record<string, number> = {}\n for (const key of Object.keys(shot.penetration)) scaled[key] = shot.penetration[key]! * k\n out.penetration = scaled\n }\n if (shot.incendiary) out.incendiary = true\n if (shot.tracer) out.tracer = true\n if (shot.ignition) out.ignition = { spark: shot.ignition.spark, flame: shot.ignition.flame }\n return out\n}\n\n/** One use of a non-firearm (melee swing, flame tick, heat tick, throw, tool tick, extinguisher tick). */\nexport type Use =\n | { kind: 'melee'; damage: 'blunt' | 'slash'; energy: number; radius: number; reach: number; origin: Vec3; direction: Vec3 }\n | { kind: 'flame'; temperature: number; radius: number; range: number; cone: boolean; duration: number; origin: Vec3; direction: Vec3 }\n | { kind: 'heat'; temperature: number; radius: number; range: number; duration: number; origin: Vec3; direction: Vec3 }\n | {\n kind: 'throw'\n energy: number\n radius: number\n fuse: number\n velocity: Vec3\n origin: Vec3\n fire?: { temperature: number; radius: number; seconds: number }\n /** Explosive id (`m67`, `molotov`, `pg7v`...): the host looks the numbers up in the arsenal. Absent on a plain thrown object. */\n explosive?: string\n /** What sets it off: `timer` after `fuse` seconds, `impact` on the first hit once armed. */\n trigger?: 'timer' | 'impact'\n /** Metres the projectile must fly before an impact sets it off; closer, it hits without exploding (rocket launchers). */\n armDistance?: number\n /** Radius in metres of the wounding area (`radius` is the lethal one). */\n injuryRadius?: number\n /** Seconds the blast stuns whoever is inside the injury radius (flashbang). */\n stunSeconds?: number\n /** Seconds the thrower held it after pulling the pin: `fuse` is what was left of the full fuse when it left the hand. */\n cooked?: number\n /** Went off in the thrower's hand (held past the fuse): no velocity, `fuse` is 0 and the blast is at `origin`. */\n inHand?: boolean\n }\n /** An explosive set down where the trigger is pulled (mine, C4, charge): it waits for its trigger instead of flying. */\n | {\n kind: 'place'\n explosive: string\n /** `wire`: something trips it; `remote`: the player fires it; `timer`: after `fuse` seconds. */\n triggers: readonly ('timer' | 'wire' | 'remote')[]\n energy: number\n /** Lethal radius in metres. */\n radius: number\n injuryRadius: number\n /** Cone the blast goes through, in front of `direction` (mine); absent for a blast in every direction. */\n cone?: { halfAngleDeg: number; length: number }\n /** The wire a `wire` charge stretches from where it is set down: metres out, degrees from its facing (counter-clockwise from above) and metres above it. */\n tripwire?: { length: number; angleDeg: number; height: number }\n fuse?: number\n origin: Vec3\n direction: Vec3\n }\n /** The blast behind a rocket launcher: dangerous inside `radius` metres, in the cone around `direction` (pointing away from the target). */\n | { kind: 'backblast'; radius: number; halfAngleDeg: number; origin: Vec3; direction: Vec3 }\n | { kind: 'tool'; tool: string; reach: number; duration: number; origin: Vec3; direction: Vec3 }\n | { kind: 'extinguish'; range: number; coolC: number; duration: number; origin: Vec3; direction: Vec3 }\n | { kind: 'hand'; reach: number; origin: Vec3; direction: Vec3 }\n\n/**\n * The `Hit` a ballistic shot makes at `point` (world space): the energy is what is left of the shot at that distance from its origin\n * (`shot.energyAt`), the direction and calibre come from the shot. `normal` (the surface normal at the point, when the caller knows it) does not\n * change the hit; it is accepted so that callers can pass what their raycast returned and so that a stricter implementation could use it.\n */\nexport const shotToHit = (shot: Shot, point: Vec3, normal?: Vec3): Hit => {\n void normal\n const dx = point[0] - shot.origin[0]\n const dy = point[1] - shot.origin[1]\n const dz = point[2] - shot.origin[2]\n const distance = Math.hypot(dx, dy, dz)\n return {\n type: 'ballistic',\n point: [point[0], point[1], point[2]],\n direction: [shot.direction[0], shot.direction[1], shot.direction[2]],\n energy: shot.energyAt(distance),\n caliber: shot.caliber,\n ...(shot.mass === undefined ? {} : { mass: shot.mass }),\n ...shotExtras(shot, distance),\n source: shot.source ?? shot.weapon,\n }\n}\n\n/**\n * The `Hit` a non-firearm `Use` makes at `point` (world space), or `null` for uses that do not damage by themselves.\n *\n * - `melee` -> `blunt` / `slash` with the swing's `energy`, contact `radius` and `direction`;\n * - `flame` -> `fire` and `heat` -> `heat`, with `temperature`, `duration` and a contact radius of at most 0.3 m (one ray of the cone);\n * - `throw` -> the blast (`explosive`, `energy`, `radius`, centred on `point`, the place it detonates). A thrown item with no blast energy but\n * a `fire` patch (a molotov) gives that patch as a `fire` hit (`temperature`, `radius`, `seconds` as `duration`). No energy and no fire -> `null`;\n * - `tool`, `extinguish` and `hand` -> `null` (tools work on joints, the extinguisher cools, the hand only grabs).\n *\n * `normal` does not change the hit (same as `shotToHit`).\n */\nexport const useToHit = (use: Use, point: Vec3, normal?: Vec3): Hit | null => {\n void normal\n const p: Vec3 = [point[0], point[1], point[2]]\n switch (use.kind) {\n case 'melee':\n return { type: use.damage, point: p, direction: [use.direction[0], use.direction[1], use.direction[2]], energy: use.energy, radius: use.radius }\n case 'flame':\n case 'heat':\n return {\n type: use.kind === 'flame' ? 'fire' : 'heat',\n point: p,\n direction: [use.direction[0], use.direction[1], use.direction[2]],\n temperature: use.temperature,\n radius: Math.min(use.radius, 0.3),\n duration: use.duration,\n }\n case 'throw':\n if (use.energy > 0) return { type: 'explosive', point: p, energy: use.energy, radius: use.radius }\n if (use.fire) return { type: 'fire', point: p, temperature: use.fire.temperature, radius: use.fire.radius, duration: use.fire.seconds }\n return null\n default:\n return null\n }\n}\n","import type { Hit } from './destruction'\n\n/**\n * How a container of flammable fluid (a fuel tank, a jerrycan, a gas bottle) is set alight by what hits it. A normal bullet that goes through only\n * makes a leak; the leak lights when something supplies a flame: a spark of a hard round on metal, an incendiary or tracer round, a fire nearby\n * or a blast. These are the numbers of the target side; the numbers of the round (core, jacket, incendiary, tracer) are in the weapons module\n * (`rules.ignition` of `@adatechnology/game-weapons`) and reach the target in `Hit.ignition`. Every number is a default to be changed per game.\n */\nexport interface IgnitionRules {\n /**\n * How much of the spark and of the flame of a round reaches the vapour, by how full the container is: points `[filled, factor]`, `filled` 0..1\n * (litres over capacity), `factor` 0..1, linear between points. A full container holds a mixture too rich to burn (the vapour has no air) and\n * mostly leaks; a nearly empty one holds the vapour/air mixture of a flammable range and lights the easiest; a dry one has little vapour left.\n * Default: 0.6 empty, 1 at 10 percent, 0.6 at 35, 0.3 at 65, 0.15 at 90 and 0.12 full.\n */\n fillCurve: ReadonlyArray<readonly [number, number]>\n /** 0..1: how much of the fill factor also weighs on the flame of an incendiary or tracer (1: as much as on a spark; 0: not at all). Default 0.5. */\n flameFillInfluence: number\n /** Chance of the flame of a round that is flagged `incendiary` or `tracer` but carries no `ignition` numbers (a host that passes only the flags). */\n flameDefaults: { incendiary: number; tracer: number }\n /**\n * What a spark needs to strike: a factor 0..1 by material id of the struck part. A material that is not listed but is metal takes\n * `sparkMetalDefault`; a part that is not metal never sparks. Default: steel and iron 1, aluminium 0.25.\n */\n sparkTarget: Readonly<Record<string, number>>\n sparkMetalDefault: number\n /**\n * Factor 0..1 on the spark by fluid (default 1): diesel has a flash point of 52 degrees C and more, so a spark that lights petrol vapour does\n * not light it (a flame does). Default: diesel 0.15.\n */\n sparkFluid: Readonly<Record<string, number>>\n /** A leaking container of flammable fluid within `radius` metres of a burning part or a burning fuel stain lights at `chancePerSecond`. */\n fireNear: { radius: number; chancePerSecond: number }\n}\n\n/** Defaults of `IgnitionRules`. */\nexport const DEFAULT_IGNITION_RULES: IgnitionRules = {\n fillCurve: [\n [0, 0.6],\n [0.1, 1],\n [0.35, 0.6],\n [0.65, 0.3],\n [0.9, 0.15],\n [1, 0.12],\n ],\n flameFillInfluence: 0.5,\n flameDefaults: { incendiary: 0.7, tracer: 0.2 },\n sparkTarget: { steel: 1, iron: 1, aluminium: 0.25 },\n sparkMetalDefault: 0.5,\n sparkFluid: { diesel: 0.15 },\n fireNear: { radius: 1.5, chancePerSecond: 0.5 },\n}\n\n/** Merges a partial `IgnitionRules` over the defaults (an object is merged one level deep). */\nexport const resolveIgnitionRules = (rules?: Partial<IgnitionRules>): IgnitionRules => ({\n ...DEFAULT_IGNITION_RULES,\n ...rules,\n flameDefaults: { ...DEFAULT_IGNITION_RULES.flameDefaults, ...rules?.flameDefaults },\n sparkTarget: { ...DEFAULT_IGNITION_RULES.sparkTarget, ...rules?.sparkTarget },\n sparkFluid: { ...DEFAULT_IGNITION_RULES.sparkFluid, ...rules?.sparkFluid },\n fireNear: { ...DEFAULT_IGNITION_RULES.fireNear, ...rules?.fireNear },\n})\n\n/** Linear interpolation of the fill curve at `fill` (0..1); outside the points it keeps the first or the last. */\nexport const fillFactor = (fill: number, curve: IgnitionRules['fillCurve'] = DEFAULT_IGNITION_RULES.fillCurve): number => {\n if (curve.length === 0) return 1\n const f = Math.min(1, Math.max(0, fill))\n if (f <= curve[0]![0]) return curve[0]![1]\n for (let i = 1; i < curve.length; i++) {\n const [x1, y1] = curve[i]!\n const [x0, y0] = curve[i - 1]!\n if (f <= x1) return x1 === x0 ? y1 : y0 + ((y1 - y0) * (f - x0)) / (x1 - x0)\n }\n return curve[curve.length - 1]![1]\n}\n\n/** The factor of what a spark strikes: 0 when the struck part is not metal. */\nexport const sparkTargetFactor = (materialId: string, metal: boolean, rules: IgnitionRules = DEFAULT_IGNITION_RULES): number =>\n !metal ? 0 : rules.sparkTarget[materialId] ?? rules.sparkMetalDefault\n\n/**\n * Chance that one round that went through the wall of a container lights the fluid that leaks: the spark (only on metal) and the flame (any\n * wall), each weighed by the fill of the container; the two are independent. 0 when the round carries nothing (`Hit.ignition` absent and not\n * flagged `incendiary` or `tracer`): a plain bullet on a plain wall only leaks.\n */\nexport const ignitionChance = (hit: Pick<Hit, 'incendiary' | 'tracer' | 'ignition'>, target: { sparkTarget: number; fill: number; fluid?: string }, rules: IgnitionRules = DEFAULT_IGNITION_RULES): number => {\n const k = fillFactor(target.fill, rules.fillCurve)\n const spark = (hit.ignition?.spark ?? 0) * target.sparkTarget * (target.fluid === undefined ? 1 : rules.sparkFluid[target.fluid] ?? 1) * k\n const flameBase = hit.ignition?.flame ?? Math.max(hit.incendiary ? rules.flameDefaults.incendiary : 0, hit.tracer ? rules.flameDefaults.tracer : 0)\n const flame = flameBase * (1 - rules.flameFillInfluence * (1 - k))\n return 1 - (1 - Math.min(1, Math.max(0, spark))) * (1 - Math.min(1, Math.max(0, flame)))\n}\n","/**\n * The seal of a closed container (a food tin, a drink can, a jar, a bottle with a cap): what opens it and whether a breach spoils what is inside.\n * Plain data and one pure check, shared by the item rules (`resolveUse` of game-items) and any host that lets the player open and eat (the test room).\n */\nexport interface SealSpec {\n /** Ids of the tools that open it (items or weapons: `can_opener`, `knife`); any one of them is enough. */\n readonly openWith?: readonly string[]\n /** It opens by hand (a pull tab, a ring pull, a screw cap): no tool needed. */\n readonly byHand?: boolean\n /** A hole through the container or a leak spoils what is inside: it can no longer be eaten or drunk. */\n readonly spoilsWhenBreached?: boolean\n}\n\n/** The state of one container: opened, holed through (a shot, a blade) or leaking. */\nexport interface SealState {\n readonly opened?: boolean\n readonly breached?: boolean\n readonly leaked?: boolean\n}\n\n/** Why a sealed container cannot be eaten or drunk now. */\nexport type SealBlock = 'sealed' | 'breached' | 'leaked'\n\n/** Whether it can be opened with the tools at hand, and with which one (undefined when it opens by hand). */\nexport const sealOpener = (seal: SealSpec, tools: Iterable<string>): { readonly ok: boolean; readonly tool?: string } => {\n if (seal.byHand || !seal.openWith || seal.openWith.length === 0) return { ok: true }\n const have = new Set(tools)\n const tool = seal.openWith.find((id) => have.has(id))\n return tool === undefined ? { ok: false } : { ok: true, tool }\n}\n\n/** What stops eating or drinking it now, or undefined when nothing does. A spoiled container (breached, leaked) is blocked even once open. */\nexport const sealBlock = (seal: SealSpec, state: SealState): SealBlock | undefined => {\n if (seal.spoilsWhenBreached && state.breached) return 'breached'\n if (seal.spoilsWhenBreached && state.leaked) return 'leaked'\n if (!state.opened) return 'sealed'\n return undefined\n}\n","import type { Vec3 } from './destruction'\n\n/**\n * Where a hand should be, in world space. `position` is the middle of the palm; the orientation follows one convention for every hand: the hand-local +x runs from the wrist to the\n * knuckles (the way the fingers point when open), +y is the back of the hand and +z completes the frame (for a right hand the little finger side; the thumb is at -z). A left hand is the\n * mirror image of a right one, so the same numbers describe the same grip: its thumb is at +z.\n */\nexport interface HandPose {\n position: Vec3\n /** Unit quaternion `[x, y, z, w]`, hand-local to world. */\n quaternion: [number, number, number, number]\n}\n\n/**\n * What a tool in the hands asks of the hands that hold it (a weapon asks for a grip on its grip and handguard, a carried item for a hand under it). A side left out or null is not held:\n * the hand stays in its rest stance. Nothing here knows what the tool is.\n */\nexport interface HandTargets {\n R?: HandPose | null\n L?: HandPose | null\n /** How closed the fingers are, 0 open to 1 closed on a grip. Default 1. */\n grip?: number\n /** The same for the left hand, when it differs from `grip` (a hand laid on a forend is looser than the one on the trigger). */\n gripL?: number\n /** The size of the hands against life size (a tool drawn smaller than real takes smaller hands). Default 1. */\n scale?: number\n /** Fingers of the right hand that curl by themselves, 0 extended to 1 fully curled (the index finger of a trigger hand); the others follow `grip`. */\n fingers?: { index?: number }\n /** The same for the left hand (its index on the trigger of a tool of its own, with a tool in each hand); absent, the left hand's fingers all follow `gripL`. */\n fingersL?: { index?: number }\n /**\n * Where the elbows go: `view` puts them on screen beside the hand, out to the side, as a tool held out in front (default); `body` lets them hang down and back by the body, as an item\n * carried close (a can, a bottle), where an elbow out to the side would lift it above the shoulder.\n */\n elbows?: 'view' | 'body'\n}\n\n/** Read every frame by whoever draws the arms; answers null while nothing is held. */\nexport type HandTargetSource = () => HandTargets | null\n\n/** The muzzle of the tool in the hands as it is drawn now (world space): where a shot's flash and tracer leave, and which way the barrel points. */\nexport interface MuzzlePose {\n readonly position: Vec3\n /** Unit vector along the barrel, out of the muzzle. */\n readonly direction: Vec3\n /** The module draws the muzzle flash itself: the host draws none of its own. */\n readonly drawsFlash: boolean\n}\n\n/** A hand of the body: `R` the right, `L` the left. A tool in one hand alone is in the right; the left holds one of its own only with a tool in each hand (`HostTool.offHand`). */\nexport type ToolHand = 'R' | 'L'\n\n/**\n * Read by the host at each shot; null while the tool in the hands has no muzzle (a knife, a bare hand). `hand` is the hand that fired (absent: the right one); a source that draws\n * one tool only answers the same for both.\n */\nexport type MuzzleSource = (hand?: ToolHand) => MuzzlePose | null\n\n/**\n * The layer of what the first-person view draws over the world (three.js `Object3D.layers`): the tool in the hands and the arms that hold it. A host with a first-person view draws\n * the world without this layer, then this layer alone over it with the depth cleared and its own field of view (`ModuleHost.setViewmodelFov`), as shooters draw the weapon in the hands:\n * it never goes into a wall, and the gun and the arms are framed by the lens chosen for them. Seen from outside (third person) nothing is on it.\n */\nexport const FIRST_PERSON_LAYER = 9\n","/** How a hand turns something round in strokes (a screw cap, a tap handle, a knob): what `twistStroke` answers for one moment of the turning. */\nexport interface TwistStroke {\n /** Radians the wrist is turned from the middle of its stroke, positive the way the part turns. */\n readonly angle: number\n /** Radians the part has turned in all, from 0 to `strokes * reach`. */\n readonly turned: number\n /** How closed the fingers are, 0 open to 1 closed: closed on the part while it turns, open while the wrist turns back. */\n readonly grip: number\n /** 0..1, how far the hand rises off the part while the wrist turns back (1 is `TWIST_LIFT` metres). */\n readonly lift: number\n}\n\nexport interface TwistOptions {\n /** Strokes of the wrist. Default 3. */\n readonly strokes?: number\n /** Radians the part turns in one stroke (a wrist turns about a quarter round with its hold). Default 1.6. */\n readonly reach?: number\n}\n\n/** Metres a hand rises off the part between two strokes. */\nexport const TWIST_LIFT = 0.012\n/** Share of each stroke spent turning the part; the rest turns the wrist back open. */\nconst TURNING = 0.7\n\nconst smooth = (k: number): number => k * k * (3 - 2 * k)\n\n/**\n * The hand turning a part round at `share` (0..1) of the whole turning: in each stroke the wrist turns with the part, then lets go, rises a little and turns back.\n * Pure and the same for every host, so first and third person turn the same hand the same way.\n */\nexport const twistStroke = (share: number, options: TwistOptions = {}): TwistStroke => {\n const strokes = Math.max(1, Math.round(options.strokes ?? 3))\n const reach = options.reach ?? 1.6\n const along = Math.min(1, Math.max(0, share)) * strokes\n const index = Math.min(strokes - 1, Math.floor(along))\n const phase = along - index\n if (phase <= TURNING) {\n const k = smooth(phase / TURNING)\n return { angle: reach * (k - 0.5), turned: reach * (index + k), grip: 1, lift: 0 }\n }\n const k = (phase - TURNING) / (1 - TURNING)\n return { angle: reach * (0.5 - smooth(k)), turned: reach * (index + 1), grip: 0.35, lift: Math.sin(k * Math.PI) }\n}\n","import type { Vec3 } from './destruction'\n\n/** Pose of one part (or of the whole item) at a key: position offset in metres and Euler XYZ rotation in radians, both relative to the rest pose. */\nexport interface AnimationPose {\n position?: Vec3\n rotation?: Vec3\n}\n\nexport interface AnimationKey {\n /** Seconds from the start of the clip. */\n t: number\n /** Pose of the item's root. */\n position?: Vec3\n rotation?: Vec3\n /** Poses of named parts: the key is a destruction part id (a pistol `reload` moves `mag`; a car door `open` rotates `door_l`). */\n parts?: Record<string, AnimationPose>\n}\n\nexport interface AnimationEventSpec {\n /** Seconds from the start of the clip. */\n t: number\n /** snake_case type the host maps (`sound`, `eject_casing`, `door_latch`...). */\n type: string\n data?: Record<string, unknown>\n /**\n * Seconds of real time the event fires before `t`, not stretched with the clip: a recorded sound whose hit comes that long after its start\n * (the click of a magazine seating) starts early so the hit lands on `t`. The player passes the lead it could apply as `data.lead`.\n */\n lead?: number\n}\n\n/** A use animation a module brings with its item. Poses between keys are interpolated by the player (the test room does it linearly). */\nexport interface AnimationClipSpec {\n /** snake_case: `reload`, `open`, `drink`... Unique within the item. */\n id: string\n /** Seconds. */\n duration: number\n keys: AnimationKey[]\n events?: AnimationEventSpec[]\n}\n\n/** What an item exposes when it brings its own animations. */\nexport interface ItemAnimationContract {\n animations: AnimationClipSpec[]\n}\n\nconst finite3 = (v: unknown): boolean => Array.isArray(v) && v.length === 3 && v.every((n) => typeof n === 'number' && Number.isFinite(n))\n\n/**\n * Problems with a clip (empty when it is valid): a snake_case id, a positive finite duration, at least one key, key and event times inside\n * `[0, duration]` and not going backwards, finite vectors, every named part one of `partIds`, event types that are non-empty strings and\n * JSON-serializable event data.\n */\nexport const checkAnimation = (clip: AnimationClipSpec, partIds: Iterable<string>): { ok: boolean; problems: string[] } => {\n const problems: string[] = []\n const parts = new Set(partIds)\n const id = String(clip?.id ?? '')\n if (!/^[a-z][a-z0-9_]*$/.test(id)) problems.push(`clip id \"${id}\" must be snake_case`)\n const label = `clip \"${id}\"`\n if (!(typeof clip?.duration === 'number' && Number.isFinite(clip.duration) && clip.duration > 0)) problems.push(`${label} needs a positive finite duration`)\n const dur = typeof clip?.duration === 'number' && clip.duration > 0 ? clip.duration : Infinity\n if (!Array.isArray(clip?.keys) || clip.keys.length === 0) {\n problems.push(`${label} needs at least one key`)\n return { ok: false, problems }\n }\n let prev = -Infinity\n clip.keys.forEach((k, i) => {\n if (!(typeof k.t === 'number' && Number.isFinite(k.t)) || k.t < 0 || k.t > dur + 1e-9) problems.push(`${label} key ${i} has t=${String(k.t)} outside 0..${dur}`)\n else if (k.t < prev) problems.push(`${label} key ${i} goes back in time (${k.t} < ${prev})`)\n else prev = k.t\n for (const f of ['position', 'rotation'] as const) if (k[f] !== undefined && !finite3(k[f])) problems.push(`${label} key ${i} has an invalid ${f}`)\n for (const [pid, pose] of Object.entries(k.parts ?? {})) {\n if (!parts.has(pid)) problems.push(`${label} key ${i} moves unknown part \"${pid}\"`)\n for (const f of ['position', 'rotation'] as const) if (pose?.[f] !== undefined && !finite3(pose[f])) problems.push(`${label} key ${i} part \"${pid}\" has an invalid ${f}`)\n }\n })\n let prevEv = -Infinity\n ;(clip.events ?? []).forEach((e, i) => {\n if (!(typeof e.t === 'number' && Number.isFinite(e.t)) || e.t < 0 || e.t > dur + 1e-9) problems.push(`${label} event ${i} has t=${String(e.t)} outside 0..${dur}`)\n else if (e.t < prevEv) problems.push(`${label} event ${i} goes back in time`)\n else prevEv = e.t\n if (typeof e.type !== 'string' || e.type === '') problems.push(`${label} event ${i} needs a type`)\n try {\n JSON.stringify(e.data ?? {})\n } catch {\n problems.push(`${label} event ${i} data is not JSON`)\n }\n })\n return { ok: problems.length === 0, problems }\n}\n","import type { AnimationClipSpec, AnimationEventSpec, AnimationPose } from './animation'\nimport { checkAnimation } from './animation'\nimport type { HostEvent } from './module'\n\n/** Clips a tool can bring, one per move of its cycle. A tool brings the ones it has; a missing clip is simply not played. */\nexport const TOOL_CLIP = {\n DRAW: 'draw',\n SHOT: 'shot',\n MISFIRE: 'misfire',\n EMPTY: 'empty',\n CYCLE: 'cycle',\n RELOAD: 'reload',\n FEED: 'feed',\n FAULT: 'fault',\n CLEAR: 'clear',\n SAFETY_ON: 'safety_on',\n SAFETY_OFF: 'safety_off',\n MODE: 'mode',\n /** A throwable with the pin out, held until it is thrown. */\n COOK: 'cook',\n /** The stock folds, unfolds, slides in or out (variants `fold`, `unfold`, `collapse`, `extend`). */\n STOCK: 'stock',\n /** A light or a laser is switched (variants `on`, `off`). */\n TOGGLE: 'toggle',\n} as const\nexport type ToolClipId = (typeof TOOL_CLIP)[keyof typeof TOOL_CLIP]\n\n/** What a renderer does when a rule event arrives. `variant` picks `<clip>_<variant>` when the tool has it, else `<clip>`. */\nexport type ToolAnimationStep =\n | { readonly type: 'play'; readonly clip: ToolClipId; readonly variant?: string; readonly duration?: number; readonly repeat?: number }\n /** Move the clip that is playing to the marker (a clip event `stage` with `data.stage`) the rule just reached. */\n | { readonly type: 'sync'; readonly stage: string }\n /** The rule says the phase is over: the clip jumps to its end if it is still running. */\n | { readonly type: 'finish'; readonly clip: ToolClipId }\n\nconst stockVariant = (event: Extract<HostEvent, { type: 'stock' }>): string => {\n const isFolding = event.kind === undefined ? false : event.kind.includes('fold')\n if (event.state === 'collapsed') return isFolding ? 'fold' : 'collapse'\n return isFolding ? 'unfold' : 'extend'\n}\n\n/** The move a host event asks of the tool in hand, or null when it has no motion. */\nexport const toolAnimationStep = (event: HostEvent): ToolAnimationStep | null => {\n switch (event.type) {\n case 'tool':\n return { type: 'play', clip: TOOL_CLIP.DRAW, ...(event.duration === undefined ? {} : { duration: event.duration }) }\n case 'shot':\n return { type: 'play', clip: TOOL_CLIP.SHOT, repeat: Math.max(1, event.rounds ?? 1) }\n case 'misfire':\n return { type: 'play', clip: TOOL_CLIP.MISFIRE }\n case 'empty':\n return { type: 'play', clip: TOOL_CLIP.EMPTY }\n case 'mode':\n return { type: 'play', clip: TOOL_CLIP.MODE, variant: event.mode }\n case 'fault':\n return { type: 'play', clip: TOOL_CLIP.FAULT, variant: event.fault }\n case 'clear':\n if (event.phase === 'end') return { type: 'finish', clip: TOOL_CLIP.CLEAR }\n return { type: 'play', clip: TOOL_CLIP.CLEAR, variant: event.fault, ...(event.duration === undefined ? {} : { duration: event.duration }) }\n case 'safety':\n return { type: 'play', clip: event.on ? TOOL_CLIP.SAFETY_ON : TOOL_CLIP.SAFETY_OFF }\n case 'cycle':\n if (event.phase === 'end') return { type: 'finish', clip: TOOL_CLIP.CYCLE }\n return { type: 'play', clip: TOOL_CLIP.CYCLE, ...(event.duration === undefined ? {} : { duration: event.duration }) }\n case 'reload':\n if (event.phase === 'end') return { type: 'finish', clip: TOOL_CLIP.RELOAD }\n return { type: 'play', clip: TOOL_CLIP.RELOAD, ...(event.kind === undefined ? {} : { variant: event.kind }), ...(event.duration === undefined ? {} : { duration: event.duration }) }\n case 'stage':\n return { type: 'sync', stage: event.stage }\n case 'feed':\n return { type: 'play', clip: TOOL_CLIP.FEED }\n case 'cook':\n if (event.phase === 'start') return { type: 'play', clip: TOOL_CLIP.COOK, duration: event.fuse }\n return { type: 'finish', clip: TOOL_CLIP.COOK }\n case 'stock':\n return { type: 'play', clip: TOOL_CLIP.STOCK, variant: stockVariant(event), ...(event.duration === undefined ? {} : { duration: event.duration }) }\n case 'toggle':\n return { type: 'play', clip: TOOL_CLIP.TOGGLE, variant: event.on ? 'on' : 'off' }\n default:\n return null\n }\n}\n\n/** Where a renderer puts the poses: every part of the tool by id (the ids the clips move), and the whole tool. Poses are offsets from rest. */\nexport interface ToolRig {\n setPartPose(partId: string, pose: AnimationPose): void\n setRootPose?(pose: AnimationPose): void\n}\n\n/** Clips by id, with the variants as `<clip>_<variant>`. */\nexport type ToolClipSet = Readonly<Record<string, AnimationClipSpec>>\n\n/** A renderer's tool animator: feed it the host events and the frame time. */\nexport interface ToolAnimator {\n handle(event: HostEvent): void\n update(dt: number): void\n /** Ids of the clips playing now. */\n readonly playing: readonly string[]\n dispose(): void\n}\n\nexport const STAGE_EVENT = 'stage'\n\n/** The clip with its times (keys and events) scaled so that it lasts `duration` seconds. */\nexport const scaleClip = (clip: AnimationClipSpec, duration: number): AnimationClipSpec => {\n const factor = clip.duration > 0 ? duration / clip.duration : 1\n return {\n ...clip,\n duration,\n keys: clip.keys.map((key) => ({ ...key, t: key.t * factor })),\n ...(clip.events ? { events: clip.events.map((event) => ({ ...event, t: event.t * factor })) } : {}),\n }\n}\n\nconst ZERO: [number, number, number] = [0, 0, 0]\nconst mix = (from: readonly number[], to: readonly number[], fraction: number): [number, number, number] => [\n (from[0] ?? 0) + ((to[0] ?? 0) - (from[0] ?? 0)) * fraction,\n (from[1] ?? 0) + ((to[1] ?? 0) - (from[1] ?? 0)) * fraction,\n (from[2] ?? 0) + ((to[2] ?? 0) - (from[2] ?? 0)) * fraction,\n]\n\n/** Pose of the whole tool (`partId` undefined) or of one part at `time`, linear between keys; a key that does not name it means rest. */\nexport const sampleClip = (clip: AnimationClipSpec, partId: string | undefined, time: number): { position: [number, number, number]; rotation: [number, number, number] } => {\n const points = clip.keys.map((key) => {\n const pose = partId === undefined ? key : key.parts?.[partId]\n return { t: key.t, position: pose?.position ?? ZERO, rotation: pose?.rotation ?? ZERO }\n })\n const first = points[0]\n if (!first || first.t > 0) points.unshift({ t: 0, position: ZERO, rotation: ZERO })\n const last = points[points.length - 1]\n if (!last) return { position: ZERO, rotation: ZERO }\n if (time >= last.t) return { position: mix(last.position, last.position, 0), rotation: mix(last.rotation, last.rotation, 0) }\n const index = Math.max(0, points.findIndex((point, i) => time >= point.t && time < (points[i + 1]?.t ?? Infinity)))\n const from = points[index]\n const to = points[index + 1]\n if (!from || !to) return { position: ZERO, rotation: ZERO }\n const fraction = to.t > from.t ? (time - from.t) / (to.t - from.t) : 0\n return { position: mix(from.position, to.position, fraction), rotation: mix(from.rotation, to.rotation, fraction) }\n}\n\n/** Problems with a clip set (empty when valid): each key is the clip id (or `<clip>_<variant>`), every clip passes `checkAnimation`, and a `stage` event names its stage. */\nexport const checkToolClips = (clips: ToolClipSet, partIds: Iterable<string>): { ok: boolean; problems: string[] } => {\n const parts = [...partIds]\n const problems: string[] = []\n for (const [key, clip] of Object.entries(clips)) {\n if (clip.id !== key) problems.push(`clip \"${key}\" has the id \"${clip.id}\"`)\n if (!(clip.duration > 0)) problems.push(`clip \"${key}\" has no duration`)\n problems.push(...checkAnimation(clip, parts).problems)\n for (const event of clip.events ?? []) if (event.type === STAGE_EVENT && typeof event.data?.stage !== 'string') problems.push(`clip \"${key}\" has a stage event without data.stage`)\n }\n return { ok: problems.length === 0, problems }\n}\n\ninterface Instance {\n readonly name: string\n readonly clip: AnimationClipSpec\n time: number\n delay: number\n fired: number\n}\n\nexport interface ToolClipPlayerOptions {\n clips: ToolClipSet\n rig: ToolRig\n /** Called for each clip event as its time passes (`eject_casing`, `drop_magazine`, `stage`...). */\n onEvent?(event: AnimationEventSpec, clip: string): void\n /** Seconds between the rounds of a `repeat` (a burst): default 0.1. */\n repeatInterval?(): number\n}\n\n/** The default player of a tool's clips: runs the steps of `toolAnimationStep` against a rig, scaled to the duration the rule gives. */\nexport interface ToolClipPlayer {\n apply(step: ToolAnimationStep): void\n update(dt: number): void\n readonly playing: readonly string[]\n /** The clips being played with the time each has reached and the clip itself (scaled to the duration the rule gave), for a renderer that has to follow what the clip does now (the hands working a part). */\n readonly running: ReadonlyArray<{ readonly name: string; readonly time: number; readonly clip: AnimationClipSpec }>\n}\n\n/**\n * The clip with every event that has a `lead` moved that many seconds earlier, the lead it got in `data.lead`. A led event never goes before 0\n * nor before the event written ahead of it (a fast clip keeps its order: the lead shrinks). Run after `scaleClip`: the lead is real time, the\n * clip's stretch does not touch it.\n */\nexport const leadClipEvents = (clip: AnimationClipSpec): AnimationClipSpec => {\n const events = clip.events ?? []\n if (!events.some((event) => (event.lead ?? 0) > 0)) return clip\n let floor = 0\n const led = events.map((event) => {\n const lead = Math.max(0, Math.min(event.t - floor, event.lead ?? 0))\n const t = event.t - lead\n floor = Math.max(floor, t)\n if (event.lead === undefined) return event\n const moved: AnimationEventSpec = { ...event, t, data: lead > 0 ? { ...event.data, lead } : { ...event.data } }\n delete moved.lead\n return moved\n })\n return { ...clip, events: led }\n}\n\nexport const createToolClipPlayer = (options: ToolClipPlayerOptions): ToolClipPlayer => {\n const { clips, rig, onEvent } = options\n let instances: Instance[] = []\n\n const find = (clip: string, variant?: string): { name: string; clip: AnimationClipSpec } | undefined => {\n const name = variant !== undefined && clips[`${clip}_${variant}`] ? `${clip}_${variant}` : clip\n const found = clips[name]\n return found ? { name, clip: found } : undefined\n }\n\n const render = (instance: Instance): void => {\n const time = Math.min(instance.time, instance.clip.duration)\n const root = sampleClip(instance.clip, undefined, time)\n if (instance.clip.keys.some((key) => key.position || key.rotation)) rig.setRootPose?.(root)\n const touched = new Set(instance.clip.keys.flatMap((key) => Object.keys(key.parts ?? {})))\n for (const id of touched) rig.setPartPose(id, sampleClip(instance.clip, id, time))\n }\n\n const fireEvents = (instance: Instance, upTo: number): void => {\n const events = instance.clip.events ?? []\n while (instance.fired < events.length && (events[instance.fired]?.t ?? Infinity) <= upTo + 1e-9) {\n const event = events[instance.fired]\n instance.fired += 1\n if (event) onEvent?.(event, instance.name)\n }\n }\n\n return {\n apply(step) {\n if (step.type === 'sync') {\n for (const instance of instances) {\n const marker = (instance.clip.events ?? []).find((event) => event.type === STAGE_EVENT && event.data?.stage === step.stage)\n if (marker && instance.time < marker.t) instance.time = marker.t\n }\n return\n }\n if (step.type === 'finish') {\n for (const instance of instances) {\n if (instance.name !== step.clip && !instance.name.startsWith(`${step.clip}_`)) continue\n fireEvents(instance, instance.clip.duration)\n instance.time = instance.clip.duration\n }\n return\n }\n const found = find(step.clip, step.variant)\n if (!found) return\n const clip = leadClipEvents(step.duration && step.duration > 0 ? scaleClip(found.clip, step.duration) : found.clip)\n const interval = options.repeatInterval?.() ?? 0.1\n instances = instances.filter((existing) => existing.name !== found.name || existing.delay > 0)\n for (let round = 0; round < (step.repeat ?? 1); round++) {\n instances.push({ name: found.name, clip, time: 0, delay: round * interval, fired: 0 })\n }\n },\n update(dt) {\n for (const instance of instances) {\n const carried = instance.delay > 0 ? dt - instance.delay : dt\n if (instance.delay > 0) {\n instance.delay = Math.max(0, instance.delay - dt)\n if (instance.delay > 0) continue\n }\n instance.time += carried\n fireEvents(instance, instance.time)\n render(instance)\n }\n instances = instances.filter((instance) => instance.delay > 0 || instance.time < instance.clip.duration)\n },\n get playing() {\n return instances.map((instance) => instance.name)\n },\n get running() {\n return instances.filter((instance) => instance.delay <= 0).map((instance) => ({ name: instance.name, time: instance.time, clip: instance.clip }))\n },\n }\n}\n","export const FRAME_PHASES = ['input', 'fixedSimulate', 'lateSimulate', 'present', 'render', 'idle'] as const\nexport type FramePhase = (typeof FRAME_PHASES)[number]\n\n/**\n * Presentation work a system leaves for later frames, run in small units within a shared time budget.\n * Never simulation: nothing that consumes a seeded generator or decides an outcome may wait in a queue.\n */\nexport interface DeferredQueue {\n /** Stable name for stats and logs (see `DEFERRED_QUEUE_ID`). */\n readonly id: string\n /**\n * Units waiting. 0 means idle; the budget skips the queue without calling `run`. `frame` is the budget's frame counter: a queue may\n * report 0 for the rest of a frame (the crease queue does in the frame a panel was torn). Same value for repeated calls in one frame.\n */\n pending(frame?: number): number\n /**\n * Runs units in order until `clock() >= deadline`. Contract: when `pending() > 0` it runs **at least one** unit, even with a deadline\n * already past; it never runs a unit after it saw the deadline pass. Returns how many units it ran.\n */\n run(deadline: number, clock: () => number): number\n /** Runs everything now (synchronous step, clear, dispose). */\n flush(): void\n /**\n * Called by `budget.register`: from now on the owner stops draining on its own (no MessageChannel, no drain inside `update`).\n * Never called by a getter; a queue nobody registered keeps today's internal draining.\n */\n attach?(): void\n /** Called by the unregister function and by `budget.dispose`: the owner goes back to its internal draining. */\n detach?(): void\n}\n\n/** Where a module registers a deferred queue with the host's budget. */\nexport interface DeferredQueueOptions {\n /** Higher runs first. See DEFERRED_PRIORITY. */\n readonly priority: number\n /** `present` runs before the render (the work must show this frame); `idle` runs after it. Default `idle`. */\n readonly phase?: 'present' | 'idle'\n /** Starvation guard: the queue runs at least one unit every this many frames, even with the budget spent. Default 4. */\n readonly minEveryFrames?: number\n /** Milliseconds of every frame kept for this queue before the others share the rest (when it has work). Default 0. */\n readonly reserveMs?: number\n}\n\n/** The ids of the kit's queues: what `DeferredQueue.id` says and what `DEFERRED_PRIORITY` is keyed by. */\nexport const DEFERRED_QUEUE_ID = {\n DESTRUCTION_EVENTS: 'destruction.events',\n BREACH_PAINT: 'floorplan.breach-paint',\n AUDIO_VOICES: 'audio.voices',\n VEHICLE_CREASE: 'vehicles.crease',\n} as const\n\n/** Default priorities and reserves of the kit's queues; a host may override any of them. */\nexport const DEFERRED_PRIORITY = {\n [DEFERRED_QUEUE_ID.DESTRUCTION_EVENTS]: { priority: 300, phase: 'present' },\n [DEFERRED_QUEUE_ID.BREACH_PAINT]: { priority: 250, phase: 'present' },\n [DEFERRED_QUEUE_ID.AUDIO_VOICES]: { priority: 200, phase: 'idle', reserveMs: 1 },\n [DEFERRED_QUEUE_ID.VEHICLE_CREASE]: { priority: 100, phase: 'idle' },\n} as const satisfies Readonly<Record<string, DeferredQueueOptions>>\n\nexport interface DeferredQueueReport {\n readonly ok: boolean\n readonly problems: readonly string[]\n}\n\n/**\n * Checks the `DeferredQueue` contract. `fill` leaves the queue with at least two units waiting (the same call is made on a fresh queue).\n * It cannot prove the queue only carries presentation work: that is a rule of review.\n */\nexport function checkDeferredQueue(queue: DeferredQueue, fill: () => void): DeferredQueueReport {\n const problems: string[] = []\n fill()\n const waiting = queue.pending(1)\n if (waiting < 2) problems.push(`fill() must leave at least 2 units waiting (pending is ${waiting})`)\n if (queue.pending(1) !== waiting) problems.push('pending(frame) changed between two calls in the same frame')\n const ran = queue.run(0, () => 1)\n if (ran !== 1) problems.push(`run with a deadline already past must run exactly one unit (ran ${ran})`)\n if (waiting >= 2 && queue.pending(2) !== waiting - 1) problems.push(`one unit ran but pending went from ${waiting} to ${queue.pending(2)}`)\n try {\n queue.attach?.()\n queue.attach?.()\n queue.detach?.()\n queue.detach?.()\n } catch (error) {\n problems.push(`attach/detach must be idempotent: ${error instanceof Error ? error.message : String(error)}`)\n }\n queue.flush()\n if (queue.pending(3) !== 0) problems.push(`flush must leave nothing pending (pending is ${queue.pending(3)})`)\n if (queue.run(0, () => 1) !== 0) problems.push('run on an empty queue must run no unit')\n return { ok: problems.length === 0, problems }\n}\n","const WARNED_KEY = Symbol.for('@adatechnology/game-contracts.warned')\n\ntype WarnedHolder = { [WARNED_KEY]?: Set<string> }\n\nconst warnedKeys = (): Set<string> => {\n const holder = globalThis as WarnedHolder\n return (holder[WARNED_KEY] ??= new Set<string>())\n}\n\ndeclare const process: { readonly env: { readonly NODE_ENV?: string } }\n\n// The literal `process.env.NODE_ENV` is what bundlers replace; where there is no `process` the reference throws and counts as development.\nconst isProduction = (): boolean => {\n try {\n return process.env.NODE_ENV === 'production'\n } catch {\n return false\n }\n}\n\nconst isQuiet = (): boolean => (globalThis as { __GAME_KIT_QUIET__?: unknown }).__GAME_KIT_QUIET__ === true\n\n/**\n * Warns on the console the first time `key` is seen, and only outside production and when `globalThis.__GAME_KIT_QUIET__` is not `true`: for a silent fallback that keeps working (an adapter that made its own effects\n * world or audio engine because the host lent none). The seen keys live on `globalThis`, so several bundles of the kit on one page warn once together.\n */\nexport const warnOnce = (key: string, message: string): void => {\n if (isQuiet() || isProduction()) return\n const seen = warnedKeys()\n if (seen.has(key)) return\n seen.add(key)\n console.warn(`[game-kit] ${message}`)\n}\n\n/** Forgets what `warnOnce` has seen (tests that count warnings). */\nexport const resetWarnOnce = (): void => warnedKeys().clear()\n","import { warnOnce } from './warn'\n\ntype PlainObject = Record<string, unknown>\ntype Entry = { readonly id: string }\n\n/** Keys that would reach the prototype of the result when a patch comes from parsed JSON. */\nconst UNSAFE_KEYS: ReadonlySet<string> = new Set(['__proto__', 'constructor', 'prototype'])\n\nconst isPlainObject = (value: unknown): value is PlainObject =>\n typeof value === 'object' && value !== null && !Array.isArray(value) && Object.getPrototypeOf(value) === Object.prototype\n\n/** Recursively optional; arrays and functions are replaced as a whole, objects are merged. */\nexport type DeepPartial<TValue> = TValue extends (...args: never[]) => unknown\n ? TValue\n : TValue extends readonly unknown[]\n ? TValue\n : TValue extends object\n ? { [TKey in keyof TValue]?: DeepPartial<TValue[TKey]> }\n : TValue\n\n/** Merges `patch` over `base`: plain objects merge field by field, arrays, functions and primitives replace. `undefined` in the patch is ignored. */\nexport const deepMerge = <TBase extends object>(base: TBase, patch: object | undefined): TBase => {\n if (!patch) return base\n const result: PlainObject = { ...(base as PlainObject) }\n for (const [key, value] of Object.entries(patch)) {\n if (value === undefined || UNSAFE_KEYS.has(key)) continue\n const current = result[key]\n result[key] = isPlainObject(current) && isPlainObject(value) ? deepMerge(current, value) : value\n }\n return result as TBase\n}\n\n/** The shipped entries with the ones from `extra` added or, when the id exists, replaced. */\nexport const mergeById = <TEntry extends Entry>(shipped: readonly TEntry[], extra: readonly TEntry[] | undefined): Map<string, TEntry> => {\n const entries = new Map<string, TEntry>()\n for (const entry of [...shipped, ...(extra ?? [])]) entries.set(entry.id, entry)\n return entries\n}\n\n/** Applies `patch` by id; a patch for an id that does not exist is ignored (and warned about once, in development). */\nexport const applyPatches = <TEntry extends Entry>(entries: Map<string, TEntry>, patches: Readonly<Record<string, DeepPartial<TEntry> | Partial<TEntry>>> | undefined): void => {\n for (const [id, patch] of Object.entries(patches ?? {})) {\n const entry = entries.get(id)\n if (entry) entries.set(id, deepMerge(entry, patch))\n else warnOnce(`registry.patch.${id}`, `patch for \"${id}\" ignored: no entry has that id`)\n }\n}\n\n/** Takes the ids out; an id that does not exist is ignored (and warned about once, in development). */\nexport const removeIds = (entries: Map<string, unknown>, ids: readonly string[] | undefined): void => {\n for (const id of ids ?? []) {\n if (!entries.delete(id)) warnOnce(`registry.remove.${id}`, `remove of \"${id}\" ignored: no entry has that id`)\n }\n}\n","import type { Vec3 } from './destruction'\n\n/**\n * The bench of a module: controls, layers and counters it declares as data. The host keeps the values, draws them in a generic way and hands\n * every change back through `ModuleHost.bench`. Nothing here is specific to a kind of module.\n */\nexport type ControlValue = number | boolean | string\n\nexport interface ChoiceOption {\n readonly id: string\n readonly name: string\n /** Heading the host lists the option under (`optgroup`, a grouped row of buttons). Options of a group must sit next to each other. */\n readonly group?: string\n}\n\ninterface ControlBase {\n /** snake_case, unique across the module's controls, layers and metrics. */\n readonly id: string\n /** Display name, already translated for the locale the host asked for. */\n readonly name: string\n readonly hint?: string\n readonly hidden?: boolean\n /**\n * The change (or the press, for an action) takes a noticeable time, a third of a second or more: the host shows its loading indicator while it works, with this text, or the control's name for `true`.\n * Only the host's own controls panel does it; a change made through `TestRoom.bench().set / act` runs at once.\n */\n readonly slow?: boolean | string\n}\n\nexport interface NumberControl extends ControlBase {\n readonly kind: 'number'\n readonly min: number\n readonly max: number\n readonly step?: number\n readonly unit?: string\n readonly default: number\n}\n\nexport interface BooleanControl extends ControlBase {\n readonly kind: 'boolean'\n readonly default: boolean\n}\n\nexport interface ChoiceControl extends ControlBase {\n readonly kind: 'choice'\n readonly options: readonly ChoiceOption[]\n readonly default: string\n}\n\n/** A button: no value, only the press. */\nexport interface ActionControl extends ControlBase {\n readonly kind: 'action'\n}\n\nexport type ModuleControl = NumberControl | BooleanControl | ChoiceControl | ActionControl\n\n/** Something of the module the viewer turns on or off (smoke, flash, casings). */\nexport interface ModuleLayer {\n readonly id: string\n readonly name: string\n /** On unless `false`. */\n readonly default?: boolean\n}\n\n/** Pulled: the room calls read only when it samples (~4 Hz, or on TestRoom.metrics()). */\nexport interface ModuleMetric {\n readonly id: string\n readonly name: string\n readonly unit?: string\n /** Budget: the host shows a bar and warns past it. */\n readonly max?: number\n readonly digits?: number\n read(): number | string\n}\n\nexport type BenchChange =\n | { readonly kind: 'control'; readonly id: string; readonly value: ControlValue }\n | { readonly kind: 'layer'; readonly id: string; readonly on: boolean }\n | { readonly kind: 'action'; readonly id: string }\n\nexport interface ControlPatch {\n readonly hidden?: boolean\n readonly disabled?: boolean\n readonly options?: readonly ChoiceOption[]\n readonly value?: ControlValue\n}\n\n/** What the host lends a module that declares a bench: the current values and the changes. */\nexport interface ModuleBench {\n value(id: string): ControlValue | undefined\n layer(id: string): boolean\n /** Right after attach returns, the host sends one change per control (not actions) and per layer, in declaration order. */\n onChange(listener: (change: BenchChange) => void): () => void\n /** `value` sets without emitting (no echo loops); `options` falls back to the first option if the value is no longer offered. */\n patch(id: string, patch: ControlPatch): void\n /** Move the host camera (a near / middle / far choice). */\n look(eye: Vec3, target: Vec3): void\n /** Shows a sheet on the host's panel, or takes it down with `null`. A host without a sheet area ignores it. */\n sheet?(sheet: BenchSheet | null): void\n}\n\n/**\n * A card of text the module puts on the host's panel (the sheet of an effect, of a weapon): what it is, its numbers, its steps, its colours and,\n * optionally, a strip of segments over time. Names and texts are already translated for the host's locale.\n */\nexport interface BenchSheet {\n readonly kicker?: string\n readonly title: string\n readonly body?: string\n readonly facts?: readonly { readonly label: string; readonly value: string }[]\n readonly steps?: readonly { readonly at: string; readonly text: string }[]\n readonly swatches?: readonly { readonly color: string; readonly name: string }[]\n readonly note?: string\n /** A picture of the real thing the card is about, with its author and licence: the host shows it on the card, linked to `page`. */\n readonly image?: { readonly url: string; readonly alt: string; readonly credit?: string; readonly page?: string }\n /** A strip of named segments (seconds), with tick marks and a playhead that follows the module metric `metric`. */\n readonly timeline?: {\n readonly segments: readonly { readonly name: string; readonly start: number; readonly end: number; readonly color: string }[]\n readonly ticks: readonly number[]\n readonly metric: string\n }\n}\n\nexport interface BenchReport {\n readonly ok: boolean\n readonly problems: readonly string[]\n}\n\nexport interface BenchDeclaration {\n readonly controls?: readonly ModuleControl[]\n readonly layers?: readonly ModuleLayer[]\n readonly metrics?: readonly ModuleMetric[]\n}\n\nconst SNAKE_CASE = /^[a-z][a-z0-9_]*$/\nconst finite = (n: unknown): n is number => typeof n === 'number' && Number.isFinite(n)\n\nfunction checkControl(control: ModuleControl, problems: string[]): void {\n const label = `control \"${control.id}\"`\n if (control.kind === 'number') {\n if (!finite(control.min) || !finite(control.max) || control.min >= control.max) problems.push(`${label} needs min < max`)\n if (control.step !== undefined && !(finite(control.step) && control.step > 0)) problems.push(`${label} needs a step > 0`)\n if (!finite(control.default) || control.default < control.min || control.default > control.max) problems.push(`${label} default ${String(control.default)} is outside ${control.min}..${control.max}`)\n return\n }\n if (control.kind !== 'choice') return\n if (control.options.length === 0) {\n problems.push(`${label} needs at least one option`)\n return\n }\n const seen = new Set<string>()\n const groups = new Set<string>()\n let previousGroup: string | undefined\n for (const option of control.options) {\n if (seen.has(option.id)) problems.push(`${label} repeats option \"${option.id}\"`)\n seen.add(option.id)\n if (option.group !== undefined && (typeof option.group !== 'string' || option.group === '')) problems.push(`${label} option \"${option.id}\" has an empty group`)\n else if (option.group !== undefined && option.group !== previousGroup && groups.has(option.group)) problems.push(`${label} group \"${option.group}\" is split: its options must be next to each other`)\n if (typeof option.group === 'string' && option.group !== '') groups.add(option.group)\n previousGroup = option.group\n }\n if (!seen.has(control.default)) problems.push(`${label} default \"${control.default}\" is not among its options`)\n}\n\n/** snake_case ids unique across controls, layers and metrics; min < max; step > 0; default in range; options non-empty, unique, default among them, each group in one run; metric max > 0. */\nexport function checkBench(declared: BenchDeclaration): BenchReport {\n const problems: string[] = []\n const ids = new Set<string>()\n const claim = (kind: string, id: string): void => {\n if (!SNAKE_CASE.test(id)) problems.push(`${kind} id \"${id}\" must be snake_case`)\n if (ids.has(id)) problems.push(`duplicate id \"${id}\" across controls, layers and metrics`)\n ids.add(id)\n }\n for (const control of declared.controls ?? []) {\n claim('control', control.id)\n checkControl(control, problems)\n }\n for (const layer of declared.layers ?? []) claim('layer', layer.id)\n for (const metric of declared.metrics ?? []) {\n claim('metric', metric.id)\n if (metric.max !== undefined && !(finite(metric.max) && metric.max > 0)) problems.push(`metric \"${metric.id}\" needs a max > 0`)\n }\n return { ok: problems.length === 0, problems }\n}\n","/** The weather, light and ground as the world is right now. Written by whoever drives the weather, read by whoever reacts to it. */\nexport interface EnvironmentState {\n /** Rain in mm/h; 0 is dry. */\n readonly rain: number\n /** Wind in m/s along x and z, and its strength (the length of that vector). */\n readonly windX: number\n readonly windZ: number\n readonly windSpeed: number\n /** Strongest gust in m/s. */\n readonly gust: number\n /** Render fog far distance in metres. */\n readonly fogFar: number\n /** How far one can see for gameplay, in metres (not the render fog). */\n readonly visibility: number\n /** 0 is full daylight, 1 is the darkest night. */\n readonly nightFactor: number\n readonly temperatureC: number\n /** Wet ground, 0..1: rises with rain and dries after it stops. */\n readonly wetness: number\n}\n\nexport type EnvironmentKey = keyof EnvironmentState\n\n/** A calm dry day (the normal world, before anything went wrong). */\nexport const DEFAULT_ENVIRONMENT: EnvironmentState = {\n rain: 0,\n windX: 0,\n windZ: 0,\n windSpeed: 0,\n gust: 0,\n fogFar: 220,\n visibility: 220,\n nightFactor: 0,\n temperatureC: 20,\n wetness: 0,\n}\n\n/** The host's environment (`ModuleHost.environment`): a store the weather module writes to and the others read. */\nexport interface EnvironmentBus {\n get(): EnvironmentState\n /** Merges `patch` into the state; listeners hear it only when a value really changed. */\n set(patch: Partial<EnvironmentState>): void\n /** Hears every change with the keys that changed. Returns the unsubscribe function. */\n on(listener: (state: EnvironmentState, changed: readonly EnvironmentKey[]) => void): () => void\n}\n\n/** A plain store that implements the bus; the test room and tests use it, a game may bring its own. */\nexport function createEnvironmentBus(initial: Partial<EnvironmentState> = {}): EnvironmentBus {\n let state: EnvironmentState = { ...DEFAULT_ENVIRONMENT, ...initial }\n const listeners = new Set<(state: EnvironmentState, changed: readonly EnvironmentKey[]) => void>()\n return {\n get: () => state,\n set(patch) {\n const changed = (Object.keys(patch) as EnvironmentKey[]).filter((key) => patch[key] !== undefined && patch[key] !== state[key])\n if (changed.length === 0) return\n const next = { ...state } as { -readonly [Key in EnvironmentKey]: number }\n for (const key of changed) next[key] = patch[key] as number\n state = next\n for (const listener of [...listeners]) listener(state, changed)\n },\n on(listener) {\n listeners.add(listener)\n return () => void listeners.delete(listener)\n },\n }\n}\n","import { applyPatches, deepMerge, mergeById, removeIds } from './registry'\nimport type { DeepPartial } from './registry'\n\n/** One category (kind) of items. Defaults and required contracts are inherited from the `extends` chain. */\nexport interface CategoryDef<TDefaults extends object = Record<string, unknown>> {\n readonly id: string\n /** Parent category id; the child inherits its defaults and its required contracts. */\n readonly extends?: string\n /** Field values every entry of this kind starts with; objects merge down the chain, arrays replace. */\n readonly defaults?: DeepPartial<TDefaults>\n /** Contract ids (`ContractChecker.id`) every entry of this kind, or of a descendant, must satisfy. */\n readonly requires?: readonly string[]\n /** An abstract category only groups: entries cannot declare it directly, only its descendants. */\n readonly abstract?: boolean\n}\n\n/** Where a checker is being run: the entry's kind and the chain of categories root first. */\nexport interface ContractContext {\n readonly kind: string\n readonly chain: readonly string[]\n}\n\n/** A named contract: returns the problems of an entry, each a short phrase like `missing leftover.despawnSeconds`. Empty means it holds. */\nexport interface ContractChecker<TEntry> {\n readonly id: string\n check(entry: TEntry, ctx: ContractContext): string[]\n}\n\nexport interface CategoryOptions {\n /** Categories added to the shipped ones; the same id replaces. */\n readonly extra?: readonly CategoryDef[]\n /** Partial changes by id, applied after `extra`. */\n readonly patches?: Readonly<Record<string, DeepPartial<CategoryDef> | Partial<CategoryDef>>>\n /** Ids taken out of the tree (their children are then reported by `check()`). */\n readonly remove?: readonly string[]\n}\n\nexport interface CategoryRegistry {\n get(id: string): CategoryDef | undefined\n has(id: string): boolean\n ids(): string[]\n /** Root first, ending at `id`. Throws on an unknown id, an unknown parent or a cycle. */\n chain(id: string): string[]\n /** `defaults` merged along the chain, root first, so the closest category wins. */\n defaults(id: string): Record<string, unknown>\n /** Union of `requires` along the chain, order kept, without duplicates. */\n requires(id: string): string[]\n /** True when `id` is `ancestorId` or descends from it. */\n isA(id: string, ancestorId: string): boolean\n /** Problems in the tree itself: duplicate ids, unknown `extends`, cycles. */\n check(): string[]\n}\n\nexport interface CategorizedOptions {\n /** Field of the entry that names its category. Default `kind`. */\n readonly kindField?: string\n /** Known gaps by entry id: problems starting with one of these texts go to `allowed`, so the list can shrink over time. */\n readonly allow?: Readonly<Record<string, readonly string[]>>\n}\n\nexport interface CategorizedReport {\n readonly ok: boolean\n readonly problems: string[]\n readonly allowed: string[]\n}\n\nexport const defineCategories = (defs: readonly CategoryDef[], options: CategoryOptions = {}): CategoryRegistry => {\n const problems: string[] = []\n const duplicates = (list: readonly CategoryDef[]): void => {\n const ids = new Set<string>()\n for (const def of list) {\n if (ids.has(def.id)) problems.push(`duplicate category \"${def.id}\"`)\n ids.add(def.id)\n }\n }\n duplicates(defs)\n duplicates(options.extra ?? [])\n\n const entries = mergeById(defs, options.extra)\n applyPatches(entries, options.patches)\n removeIds(entries, options.remove)\n\n const chain = (id: string): string[] => {\n const path: string[] = []\n let current: string | undefined = id\n while (current !== undefined) {\n const def = entries.get(current)\n if (!def) throw new Error(path.length === 0 ? `unknown category \"${current}\"` : `category \"${path[0]}\" has unknown parent \"${current}\"`)\n if (path.includes(current)) throw new Error(`category cycle: ${[...path, current].reverse().join(' -> ')}`)\n path.push(current)\n current = def.extends\n }\n return path.reverse()\n }\n\n const registry: CategoryRegistry = {\n get: (id) => entries.get(id),\n has: (id) => entries.has(id),\n ids: () => [...entries.keys()],\n chain,\n defaults: (id) => chain(id).reduce<Record<string, unknown>>((acc, ancestor) => deepMerge(acc, entries.get(ancestor)?.defaults), {}),\n requires: (id) => {\n const out: string[] = []\n for (const ancestor of chain(id)) for (const contract of entries.get(ancestor)?.requires ?? []) if (!out.includes(contract)) out.push(contract)\n return out\n },\n isA: (id, ancestorId) => {\n try {\n return chain(id).includes(ancestorId)\n } catch {\n return false\n }\n },\n check: () => {\n const found = [...problems]\n for (const [id, def] of entries) {\n if (def.extends !== undefined && !entries.has(def.extends)) found.push(`category \"${id}\" extends unknown \"${def.extends}\"`)\n else {\n try {\n chain(id)\n } catch (error) {\n const message = (error as Error).message\n // The same cycle is found from each of its members; the dedupe keeps one line per distinct message.\n if (message.startsWith('category cycle') && !found.includes(message)) found.push(message)\n }\n }\n }\n return found\n },\n }\n return registry\n}\n\n/** The entry with the defaults of its category underneath: the entry wins, objects merge, arrays replace. */\nexport const resolveEntry = <TEntry extends object>(registry: CategoryRegistry, entry: TEntry, kindField = 'kind'): TEntry =>\n deepMerge(registry.defaults(String((entry as Record<string, unknown>)[kindField])) as TEntry, entry)\n\n/** Checks that each entry has a known, concrete kind and satisfies every contract its chain requires. */\nexport const checkCategorized = <TEntry extends { readonly id: string }>(\n entries: readonly TEntry[],\n registry: CategoryRegistry,\n checkers: readonly ContractChecker<TEntry>[],\n options: CategorizedOptions = {},\n): CategorizedReport => {\n const kindField = options.kindField ?? 'kind'\n const byId = new Map(checkers.map((checker) => [checker.id, checker]))\n const problems: string[] = [...registry.check()]\n const allowed: string[] = []\n\n for (const entry of entries) {\n const kind = String((entry as Record<string, unknown>)[kindField])\n if (!registry.has(kind)) {\n problems.push(`\"${entry.id}\" has unknown kind \"${kind}\"`)\n continue\n }\n if (registry.get(kind)?.abstract) {\n problems.push(`\"${entry.id}\" has abstract kind \"${kind}\"`)\n continue\n }\n let path: string[]\n try {\n path = registry.chain(kind)\n } catch (error) {\n problems.push(`\"${entry.id}\" (${kind}): ${(error as Error).message}`)\n continue\n }\n const resolved = resolveEntry(registry, entry, kindField)\n for (const contract of registry.requires(kind)) {\n const owner = path.find((ancestor) => registry.get(ancestor)?.requires?.includes(contract)) ?? kind\n const checker = byId.get(contract)\n if (!checker) {\n problems.push(`kind \"${kind}\" requires contract \"${contract}\" but no checker is registered`)\n continue\n }\n const prefix = `\"${entry.id}\" (${kind}): `\n for (const problem of checker.check(resolved, { kind, chain: path })) {\n const text = `${prefix}${problem}, required by ${owner}`\n if ((options.allow?.[entry.id] ?? []).some((start) => problem.startsWith(start))) allowed.push(text)\n else problems.push(text)\n }\n }\n }\n return { ok: problems.length === 0, problems: [...new Set(problems)], allowed }\n}\n","/**\n * Where a drawn object comes from. Every builder of the kit that draws a piece (a car of the fleet, a house or a wall, a piece of furniture, a person, an\n * animal, a plant, an item, a weapon) marks the root it returns, and every renderer that draws for the room (effects, debris, liquids, the room itself)\n * marks its own roots, so a host can tell a piece of the kit from something drawn on the spot. Duck-typed on three.js objects (`userData`, `parent`,\n * `children`), so the contracts stay free of three.js.\n */\nexport const KIT_ORIGIN_KEY = 'kitOrigin'\n\n/** What drew an object: the package and the kind of piece (`vehicle`, `structure`, `furniture`, `person`... or `effect`, `room` for what is not a piece). */\nexport interface KitOrigin {\n readonly owner: string\n readonly kind: string\n /** The catalogue id of the piece, when it has one. */\n readonly id?: string\n /** Drawn as a simple stand-in shape because the kit has no model of the piece yet (an item with no team model): a model still to make. */\n readonly standIn?: boolean\n}\n\ninterface Node {\n userData?: Record<string, unknown>\n parent?: Node | null\n children?: readonly Node[]\n name?: string\n visible?: boolean\n isMesh?: boolean\n isPoints?: boolean\n isLine?: boolean\n isSprite?: boolean\n}\n\n/** Marks `object` as drawn by `origin.owner` and returns it. */\nexport function markKitOrigin<T>(object: T, origin: KitOrigin): T {\n const node = object as unknown as Node\n node.userData = node.userData ?? {}\n node.userData[KIT_ORIGIN_KEY] = { ...origin }\n return object\n}\n\n/** The origin of the object or of its nearest marked ancestor; null when nothing up the tree is marked. */\nexport function kitOriginOf(object: unknown): KitOrigin | null {\n for (let node = object as Node | null | undefined; node; node = node.parent) {\n const origin = node.userData?.[KIT_ORIGIN_KEY] as KitOrigin | undefined\n if (origin && typeof origin.owner === 'string') return origin\n }\n return null\n}\n\n/** A drawn thing that no builder of the kit marked: what was drawn on the spot. */\nexport interface UnmarkedDrawing {\n /** The names of the object and its named ancestors, outermost first. */\n readonly path: string\n readonly object: unknown\n}\n\n/** Every visible mesh, line, point cloud or sprite under `root` with no marked ancestor (`root` itself not counted as one). */\nexport function unmarkedDrawings(root: unknown): UnmarkedDrawing[] {\n const out: UnmarkedDrawing[] = []\n const pathOf = (node: Node): string => {\n const names: string[] = []\n for (let n: Node | null | undefined = node; n && n !== root; n = n.parent) if (n.name) names.push(n.name)\n return names.reverse().join(' > ') || '(no name)'\n }\n const walk = (node: Node, marked: boolean): void => {\n if (node.visible === false) return\n const here = marked || (node !== root && Boolean((node.userData?.[KIT_ORIGIN_KEY] as KitOrigin | undefined)?.owner))\n if (!here && (node.isMesh || node.isPoints || node.isLine || node.isSprite)) out.push({ path: pathOf(node), object: node })\n for (const child of node.children ?? []) walk(child, here)\n }\n walk(root as Node, false)\n return out\n}\n","/** A floor rectangle in an object's own space, metres (x across, z along). */\nexport interface Footprint {\n readonly minX: number\n readonly maxX: number\n readonly minZ: number\n readonly maxZ: number\n}\n\n/** What `footprintBlocker` reads of an object: its world matrix (three.js `Object3D`, duck-typed so the contracts stay free of three.js). */\nexport interface FootprintObject {\n readonly matrixWorld: { readonly elements: ArrayLike<number> }\n readonly parent?: unknown\n updateWorldMatrix?(updateParents: boolean, updateChildren: boolean): void\n}\n\n/**\n * The `ModuleHost.addBlocker` function of a solid object standing on the floor: the walking player stays out of `footprint`, a rectangle in the object's own space,\n * so the object blocks turned with it and follows it when it moves. An object out of the scene (no parent) blocks nothing.\n */\nexport function footprintBlocker(object: FootprintObject | (() => FootprintObject | null | undefined), footprint: Footprint | (() => Footprint | null | undefined)): (x: number, z: number, radius: number) => boolean {\n return (x, z, radius) => {\n const o = typeof object === 'function' ? object() : object\n const fp = typeof footprint === 'function' ? footprint() : footprint\n if (!o || !fp || !o.parent) return false\n o.updateWorldMatrix?.(true, false)\n const e = o.matrixWorld.elements\n // the world point in the object's own floor axes: its x and z columns are at right angles, so a projection on each (over its squared length, for a scale) inverts the matrix\n const dx = x - (e[12] as number)\n const dz = z - (e[14] as number)\n const ax = (e[0] as number) ** 2 + (e[1] as number) ** 2 + (e[2] as number) ** 2\n const az = (e[8] as number) ** 2 + (e[9] as number) ** 2 + (e[10] as number) ** 2\n const lx = (dx * (e[0] as number) + dz * (e[2] as number)) / (ax || 1)\n const lz = (dx * (e[8] as number) + dz * (e[10] as number)) / (az || 1)\n return lx > fp.minX - radius && lx < fp.maxX + radius && lz > fp.minZ - radius && lz < fp.maxZ + radius\n }\n}\n","/**\n * The sounds of a body (footsteps, jumps, landings, blows, hurt), as ids every package agrees on: the rule that knows what the body did\n * (`game-player`, a host's own player) names the sound, and the bank that knows how it sounds (`game-audio`'s `BODY_FOLEY_BANK`) answers it.\n * A game swaps the sound of an id (a sample instead of the synthesis) without touching the rule.\n */\n\n/** What the feet touch, by how it sounds (not by what it is made of: a wooden floor and a plywood board both sound `wood`). */\nexport const SURFACE_IDS = ['concrete', 'asphalt', 'wood', 'tile', 'dirt', 'grass', 'gravel', 'sand', 'metal', 'water', 'glass', 'carpet'] as const\nexport type SurfaceId = (typeof SURFACE_IDS)[number]\n\n/** The surface a body stands on when nobody says (the test room's floor is a concrete slab). */\nexport const DEFAULT_SURFACE: SurfaceId = 'concrete'\n\n/** How the feet move: a run hits harder and shorter; a crouched step is the walk, quieter. */\nexport const GAIT_IDS = ['walk', 'run'] as const\nexport type GaitId = (typeof GAIT_IDS)[number]\n\n/** How hard a landing is: `light` for a jump on the spot or a step down (up to about 5 m/s), `heavy` for a drop of more than a metre and a half. */\nexport const LANDING_IDS = ['light', 'heavy'] as const\nexport type LandingId = (typeof LANDING_IDS)[number]\n\n/** The fall speed (m/s) from which a landing is `heavy`. */\nexport const HEAVY_LANDING_SPEED = 5.5\n\nexport type FootstepSoundId = `footstep_${SurfaceId}_${GaitId}`\nexport type LandSoundId = `land_${SurfaceId}_${LandingId}`\n\n/**\n * How a blow is struck, by the body part or the tool that does it. `blade` stabs or slashes, `blunt` is a club, a bat, a pipe or a hammer, `chop` an\n * axe or a machete driven down.\n */\nexport const BLOW_IDS = ['punch', 'kick', 'shove', 'blade', 'blunt', 'chop'] as const\nexport type BlowId = (typeof BLOW_IDS)[number]\n\n/** What the blow meets: a body (flesh and bone, the head apart), something else (the material answers with its own impact), or nothing. */\nexport type BlowTarget = 'body' | 'head' | 'object' | 'air'\n\n/** The sounds of the body that are not a footstep or a landing. */\nexport const BODY_SOUND_IDS = [\n 'jump',\n 'cloth_rustle',\n 'body_fall',\n 'fall_damage',\n 'player_hurt',\n 'player_breath_run',\n 'player_death',\n 'bite',\n 'grab',\n 'punch_swing',\n 'punch_hit_body',\n 'punch_hit_face',\n 'punch_hit_object',\n 'kick_swing',\n 'kick_hit',\n 'kick_hit_object',\n 'shove_two_hands',\n 'knife_swing',\n 'knife_stab',\n 'knife_slash',\n 'knife_hit_object',\n 'blunt_swing',\n 'blunt_hit',\n 'blunt_hit_object',\n 'axe_swing',\n 'axe_chop',\n 'axe_hit_object',\n] as const\nexport type BodySoundId = (typeof BODY_SOUND_IDS)[number]\n\n/** Every sound of a body: what a host plays for the player, a survivor or a zombie. */\nexport type BodyFoleyId = FootstepSoundId | LandSoundId | BodySoundId\n\nexport const footstepSoundId = (surface: SurfaceId, gait: GaitId): FootstepSoundId => `footstep_${surface}_${gait}`\nexport const landSoundId = (surface: SurfaceId, fallSpeed: number): LandSoundId => `land_${surface}_${fallSpeed >= HEAVY_LANDING_SPEED ? 'heavy' : 'light'}`\n\n/** Every footstep and landing id, in the order of the surfaces. */\nexport const FOOTSTEP_SOUND_IDS: readonly FootstepSoundId[] = SURFACE_IDS.flatMap((surface) => GAIT_IDS.map((gait) => footstepSoundId(surface, gait)))\nexport const LAND_SOUND_IDS: readonly LandSoundId[] = SURFACE_IDS.flatMap((surface) => LANDING_IDS.map((landing): LandSoundId => `land_${surface}_${landing}`))\nexport const BODY_FOLEY_IDS: readonly BodyFoleyId[] = [...FOOTSTEP_SOUND_IDS, ...LAND_SOUND_IDS, ...BODY_SOUND_IDS]\n\nconst SWING: Readonly<Record<BlowId, BodySoundId | null>> = {\n punch: 'punch_swing',\n kick: 'kick_swing',\n // two hands pushed out do not whistle: the shove is one sound, at the contact\n shove: null,\n blade: 'knife_swing',\n blunt: 'blunt_swing',\n chop: 'axe_swing',\n}\n\n/**\n * Seconds from the start of a swing's sound to its loudest point (the limb or the tool at full speed, just before the contact). A host that knows when the\n * blow lands starts the swing this long before; one that does not plays the swing now and the hit this long after.\n */\nexport const SWING_LEAD_SECONDS: Readonly<Record<BlowId, number>> = { punch: 0.07, kick: 0.09, shove: 0, blade: 0.05, blunt: 0.1, chop: 0.11 }\n\n/** The swing through the air, played as the blow starts (`null`: the blow has none). */\nexport const swingSoundId = (blow: BlowId): BodySoundId | null => SWING[blow]\n\nconst HIT: Readonly<Record<BlowId, Readonly<Record<Exclude<BlowTarget, 'air'>, BodySoundId>>>> = {\n punch: { body: 'punch_hit_body', head: 'punch_hit_face', object: 'punch_hit_object' },\n kick: { body: 'kick_hit', head: 'kick_hit', object: 'kick_hit_object' },\n shove: { body: 'shove_two_hands', head: 'shove_two_hands', object: 'shove_two_hands' },\n blade: { body: 'knife_stab', head: 'knife_stab', object: 'knife_hit_object' },\n blunt: { body: 'blunt_hit', head: 'blunt_hit', object: 'blunt_hit_object' },\n chop: { body: 'axe_chop', head: 'axe_chop', object: 'axe_hit_object' },\n}\n\n/**\n * The body's side of a blow that lands: the knuckles, the shoe, the blade or the club meeting what it hit. On an object the material's own impact\n * plays too (the wood, the metal); this is the part that says it was a punch and not a shot.\n */\nexport const hitSoundId = (blow: BlowId, target: Exclude<BlowTarget, 'air'>): BodySoundId => HIT[blow][target]\n\n/**\n * The surface a material sounds like underfoot, by the material ids of `game-destruction` and `game-terrain` (unknown ids: `fallback`). Data, so\n * a game with its own materials passes its own table to `surfaceOfMaterial`.\n */\nexport const MATERIAL_SURFACES: Readonly<Record<string, SurfaceId>> = {\n concrete: 'concrete',\n mortar: 'concrete',\n stone: 'concrete',\n brick: 'concrete',\n cobble: 'concrete',\n paver: 'concrete',\n plaster: 'concrete',\n asphalt: 'asphalt',\n wood_soft: 'wood',\n wood_hard: 'wood',\n green_wood: 'wood',\n plywood: 'wood',\n mdf: 'wood',\n ceramic: 'tile',\n plastic: 'tile',\n soil: 'dirt',\n mud: 'dirt',\n clay: 'dirt',\n wax: 'dirt',\n flesh_fruit: 'dirt',\n turf: 'grass',\n foliage: 'grass',\n cactus: 'grass',\n gravel: 'gravel',\n sand: 'sand',\n // no snow surface yet: packed snow crunches closest to sand underfoot\n snow: 'sand',\n steel: 'metal',\n cast_iron: 'metal',\n aluminium: 'metal',\n copper: 'metal',\n water: 'water',\n glass: 'glass',\n tempered_glass: 'glass',\n fabric: 'carpet',\n foam: 'carpet',\n leather: 'carpet',\n rubber: 'carpet',\n paper: 'carpet',\n}\n\nexport const isSurfaceId = (value: unknown): value is SurfaceId => typeof value === 'string' && (SURFACE_IDS as readonly string[]).includes(value)\n\n/** The surface of a material id; a surface id passes through. */\nexport function surfaceOfMaterial(material: string | undefined, table: Readonly<Record<string, SurfaceId>> = MATERIAL_SURFACES, fallback: SurfaceId = DEFAULT_SURFACE): SurfaceId {\n if (material === undefined) return fallback\n if (isSurfaceId(material)) return material\n return table[material] ?? fallback\n}\n","/**\n * @adatechnology/game-contracts: the contracts every game module (vehicles, furniture, plants, houses, weapons) depends on, and nothing else.\n * Types plus tiny pure checkers, no runtime dependencies. The default destruction world, the renderers and the test room are optional.\n */\nexport type {\n ChainDelay,\n Crack,\n DamageStage,\n DamageType,\n DebrisKind,\n Dent,\n DestructibleSpec,\n BlastOptions,\n BlastReport,\n ConfinementOptions,\n ExplosionChain,\n FragmentHitOptions,\n ShelterOptions,\n DestructionEvent,\n DestructionEventType,\n FluidKind,\n Fragment,\n FragmentMark,\n FractureStyle,\n BallisticExtras,\n Hit,\n HitIgnition,\n HitResult,\n Hole,\n JointKind,\n JointSpec,\n JointState,\n MaterialId,\n ObjectState,\n PartShape,\n PartSpec,\n PartBreach,\n PartState,\n PartStatus,\n PartUnits,\n Quat,\n RayHit,\n Reinforcement,\n TensionRebar,\n TunedMassDamper,\n WindExposure,\n WindState,\n PileSpec,\n SoilLayer,\n SoilProfile,\n SoilState,\n StructureRole,\n SurfaceLayer,\n ToolKind,\n Vec3,\n} from './destruction'\nexport type { BusyOptions, BusySink, BusyTask } from './busy'\nexport { blastShove, DEFAULT_BLAST_SHOVE } from './blast-shove'\nexport { bodyMass, FRAGMENT_COVER, KNOCK_CHEST, KNOCK_DOWN_SPEED, KNOCKED_DOWN_ANGLE, knockOf, launchBody, stepKnock, takeLaunch } from './blast-knock'\nexport { blastBodySpeed, bodyImpulse, DEFAULT_BLAST_IMPULSE, sideOnImpulse, sideOnOverpressure } from './blast-impulse'\nexport type { BlastImpulseOptions } from './blast-impulse'\nexport type { Knock } from './blast-knock'\nexport type { BlastShove, BlastShoveOptions, BlastSource } from './blast-shove'\nexport { IMPACT_CONTRACT, checkDestructible, checkHit } from './impact'\nexport type { CheckOptions, DestructibleImpl, ImpactContract, SurfaceRay, SurfaceRayHit } from './impact'\nexport type { CostOptions } from './impact-cost'\nexport { MISSING_BITS } from './body'\nexport type { BodyRegion, BodySlot, SegmentKind } from './body'\nexport { checkSpec } from './spec'\nexport type { CheckSpecOptions, SpecReport } from './spec'\nexport { shotToHit, shotExtras, useToHit } from './weapons'\nexport { DEFAULT_IGNITION_RULES, fillFactor, ignitionChance, resolveIgnitionRules, sparkTargetFactor } from './ignition'\nexport type { IgnitionRules } from './ignition'\nexport type { Shot, Use } from './weapons'\nexport type { ContainerSpec, ItemUseDef, LiquidId } from './fluids'\nexport { sealBlock, sealOpener } from './seal'\nexport type { SealBlock, SealSpec, SealState } from './seal'\nexport type { HandPose, HandTargetSource, HandTargets, MuzzlePose, MuzzleSource, ToolHand } from './hands'\nexport { FIRST_PERSON_LAYER } from './hands'\nexport { TWIST_LIFT, twistStroke } from './twist'\nexport type { TwistOptions, TwistStroke } from './twist'\nexport type { EffectHandle, EffectRequest, EffectSink, Enclosure, EnclosureBox } from './effects'\nexport type { WarmUpProbes } from './warm-up'\nexport { checkAnimation } from './animation'\nexport type { AnimationClipSpec, AnimationEventSpec, AnimationKey, AnimationPose, ItemAnimationContract } from './animation'\nexport { STAGE_EVENT, TOOL_CLIP, checkToolClips, createToolClipPlayer, leadClipEvents, sampleClip, scaleClip, toolAnimationStep } from './tool-animation'\nexport type { ToolAnimationStep, ToolAnimator, ToolClipId, ToolClipPlayer, ToolClipPlayerOptions, ToolClipSet, ToolRig } from './tool-animation'\nexport { DEFERRED_PRIORITY, DEFERRED_QUEUE_ID, FRAME_PHASES, checkDeferredQueue } from './frame'\nexport type { DeferredQueue, DeferredQueueOptions, DeferredQueueReport, FramePhase } from './frame'\nexport type { FrameOptions, AreaPlacement, GroundLayout, GroundZone, HostEvent, HostGraphics, HostTool, HostToolAttachment, CornerImage, ModuleArea, ModuleHost, ModuleView, ModuleItemFluid, ModuleItemSeal, ModuleScenario, PlayerState, ItemSeat, ItemSounds, TestableItem, TestableModule, Thumbnail, ToolCommand, ToolCommandResult, HostReach } from './module'\nexport { applyPatches, deepMerge, mergeById, removeIds } from './registry'\nexport type { DeepPartial } from './registry'\nimport { resetWarnOnce as resetWarnOnceForTests } from './warn'\n\nexport { warnOnce } from './warn'\n/** @deprecated Import it from `@adatechnology/game-contracts/testing`. */\nexport const resetWarnOnce = resetWarnOnceForTests\nexport { checkBench } from './bench'\nexport type {\n ActionControl,\n BenchChange,\n BenchDeclaration,\n BenchReport,\n BenchSheet,\n BooleanControl,\n ChoiceControl,\n ChoiceOption,\n ControlPatch,\n ControlValue,\n ModuleBench,\n ModuleControl,\n ModuleLayer,\n ModuleMetric,\n NumberControl,\n} from './bench'\nexport type { AudioListener, AudioSink, LoopHandle, SoundHandle, SoundRequest } from './audio'\nexport { DEFAULT_ENVIRONMENT, createEnvironmentBus } from './environment'\nexport type { EnvironmentBus, EnvironmentKey, EnvironmentState } from './environment'\nexport { checkCategorized, defineCategories, resolveEntry } from './categories'\nexport type { CategorizedOptions, CategorizedReport, CategoryDef, CategoryOptions, CategoryRegistry, ContractChecker, ContractContext } from './categories'\nexport { KIT_ORIGIN_KEY, kitOriginOf, markKitOrigin, unmarkedDrawings } from './origin'\nexport type { KitOrigin, UnmarkedDrawing } from './origin'\nexport { footprintBlocker } from './footprint'\nexport type { Footprint, FootprintObject } from './footprint'\nexport {\n BLOW_IDS,\n BODY_FOLEY_IDS,\n BODY_SOUND_IDS,\n DEFAULT_SURFACE,\n FOOTSTEP_SOUND_IDS,\n GAIT_IDS,\n HEAVY_LANDING_SPEED,\n LANDING_IDS,\n LAND_SOUND_IDS,\n MATERIAL_SURFACES,\n SURFACE_IDS,\n SWING_LEAD_SECONDS,\n footstepSoundId,\n hitSoundId,\n isSurfaceId,\n landSoundId,\n surfaceOfMaterial,\n swingSoundId,\n} from './foley'\nexport type { BlowId, BlowTarget, BodyFoleyId, BodySoundId, FootstepSoundId, GaitId, LandSoundId, LandingId, SurfaceId } from './foley'\n","import { chainDelayOf, drawChainDelay, FIRE_PRIME_C, shotDamageFractionOf } from './chain'\nimport type { ChainTrigger } from './chain'\nimport { planFragments } from './fracture'\nimport type { PlannedFragment } from './fracture'\nimport { cellsOutside, cellsWithin, clumpCells, marksInBox, planeAxes, unitGrid, unsupportedCells } from './breach'\nimport type { LocalHole, UnitCell } from './breach'\nimport { layersEnergy, layersThickness, MAX_SPALLS, outerLayer, resolveLayer, thinAxisOf } from './layers'\nimport type { LayerRT } from './layers'\nimport { bendBar, clipBarsToBox, clipBarsToDisc, rebarBars, rebarMass } from './rebar'\nimport {\n GRAVITY, bendGeometry, blastImpulse, isReinforced, elasticEnergy, impulseEnergy, isFlexural, lineLoad, momentOfEnergy, resolveFlexure, resolveMasonry, sectionMoments, sectionWidth,\n spanMoment, spanOf, tensionSteel,\n} from './flexure'\nimport type { BendGeometry } from './flexure'\nimport { footingSoil, pileCapacity, pileStiffness, profileOf, resolveSoil, soilAt, solveFoundation, stiffnessCentre, subgradeModulus, yieldSprings } from './soil'\nimport type { SoilSpring } from './soil'\nimport { analyzeWind, damperTuning, exposureOf, gustAt, makeGust, meanHeightFactor, resolveWind, shapeAt, stepSway, tensionCapacity } from './wind'\nimport type { Gust, ResolvedWind, SwayState, SwaySystem, WindAnalysis, WindCase, WindPartInput } from './wind'\nimport { JOINT_DEFAULTS, inferJoints, MATERIALS, partCapacity, partMass, partThickness, partVolume, fragility } from './materials'\nimport { aabbOf, createRng, distanceToShape, quat, quatFromEuler, rayShape, rotateVec, shapeArea, shapeBound, shapeDims, surfacePoint, toLocal, toWorld, vec } from './math'\nimport type { DestructibleImpl } from './contracts'\nimport type {\n AddOptions, Crack, DamageType, DebrisKind, DestructibleSpec, Dent, DestructionEvent, DestructionEventType, DestructionOptions, DestructionSnapshot,\n DamageStage, DestructionWorld, Fragment, FractureStyle, Hit, HitResult, Hole, JointSpec, JointState, MaterialDef, MaterialId, ObjectRuntime, ObjectState, PartRuntime, PartSpec,\n PartState, Quat, RayHit, ToolKind, Vec3, SoilProfile, SoilState, WindOptions, WindState,\n BlastOptions, BlastReport, ConfinementOptions, FragmentHitOptions, ShelterOptions,\n BallisticExtras,\n} from './types'\nimport { bodyImpulse, DEFAULT_BLAST_IMPULSE, ignitionChance, resolveIgnitionRules, sideOnOverpressure, sparkTargetFactor } from '@adatechnology/game-contracts'\n\n/** Hit points removed per joule (before the material's `damageScale`). */\n/** Metres: a ductile part this thin or thinner dishes around a bullet hole. */\nconst THIN_SHEET_DISHING = 0.005\n/** Rays of a box sweep start this far inside its face, so that a box touching a wall still sees it. */\nconst SWEEP_BACK = 0.01\n\n/** Where the rays of a box sweep leave from: a grid on each face the box moves toward. */\nfunction sweepOrigins(box: { readonly min: Vec3; readonly max: Vec3 }, d: Vec3, spacing: number): Vec3[] {\n const origins: Vec3[] = []\n const line = (from: number, to: number): number[] => {\n const n = Math.max(1, Math.ceil((to - from) / spacing))\n return Array.from({ length: n + 1 }, (_, i) => from + ((to - from) * i) / n)\n }\n for (const axis of [0, 1, 2] as const) {\n if (Math.abs(d[axis]) < 1e-3) continue\n const lead = d[axis] > 0 ? box.max[axis] - SWEEP_BACK : box.min[axis] + SWEEP_BACK\n const u = ((axis + 1) % 3) as 0 | 1 | 2\n const v = ((axis + 2) % 3) as 0 | 1 | 2\n for (const a of line(box.min[u], box.max[u])) {\n for (const b of line(box.min[v], box.max[v])) {\n const point: Vec3 = [0, 0, 0]\n point[axis] = lead\n point[u] = a\n point[v] = b\n origins.push(point)\n }\n }\n }\n return origins\n}\n/** Metres: a ductile part this thin or thinner is a foil-like sheet (a drink can, a food tin): a blow folds it where it lands, a blade cuts through it. */\nconst THIN_SHEET_CRUSH = 0.0005\n/** Metres: the widest dent a blow leaves on such a sheet; the sheet folds under the fist, the shoe or the corner it lands on, not under the whole reach of the blow. */\nconst THIN_SHEET_CONTACT = 0.025\nconst DMG_PER_J = 0.02\n/** Fraction of a blast's energy that reaches a part at distance 0. */\nconst BLAST_COUPLING = 0.1\n/**\n * Blast options (all off until asked for). Shelter: a part the line from the blast to the target crosses lets through `exp(-r / k)`, `r` being the\n * hit points of the slab it crosses per square metre (`hpPerKg * density * path * damageScale.shelter`). Fragment hits: up to 24 fragments, half their\n * kinetic energy lands as a blunt hit, thrown at most 6 m (and `speed * 0.4 s`) within 10 degrees of their aim. Confinement: 26 rays reaching\n * `1.5 * radius`, multiplier `1 + 1.5 * closedShare^2 * clamp(radius / meanDistance, 0, 2)` up to 3.\n */\nexport const SHELTER_DEFAULTS: Required<ShelterOptions> = { k: 2800, brokenTransmission: 0.5, minPath: 0.005 }\nexport const FRAGMENT_HIT_DEFAULTS: Required<FragmentHitOptions> = { max: 24, energyFactor: 0.5, hitType: 'blunt', range: 6, flightTime: 0.4, spread: 10, aim: 40 }\nexport const CONFINEMENT_DEFAULTS: Required<ConfinementOptions> = { rays: 26, reach: 1.5, gain: 1.5, power: 2, max: 3 }\nconst FLAMMABLE_FLUIDS = ['gas', 'fuel']\n/** Diameter in metres of the opening `vent` makes when none is given: a cylinder valve (about 8 mm). */\nconst VENT_DIAMETER = 0.008\n/** A flame lights a flammable leak when it reaches this temperature (the auto-ignition of propane in air is about 470 °C; a lighter flame is above 1000 °C). */\nconst FLAME_LIGHTS_LEAK_C = 470\n/** Cosine of the tilt past which a `resting` joint lets go: what only lies on a part (a book on a shelf) slides off once it leans past about 30°. */\nconst RESTING_HOLD_COS = Math.cos(Math.PI / 6)\n/** Staged parts: default breach radius (m), blast multiplier on the breach area, area a part must lose to open (m²), and the share of capacity the bare cage keeps. */\nconst BREACH_RADIUS = 0.55\nconst BREACH_BLAST_FACTOR = 6\nconst BREACH_AREA = 0.25\n/** Metres of reach per cube root of kilojoule for a blast to open a breach. */\nconst BREACH_BLAST_REACH = 0.12\n/** Share of the breach reach within which a blast cuts a reinforced member through (a charge at or near contact strips it to its cage); further off it blows its concrete out block by block. */\nconst MEMBER_CUT_REACH = 0.5\n/** Share of its hit points a blast further off than the cut reach leaves a reinforced member with: the wave loads it whole, so it weakens it only where it knocks the concrete out (`blastUnits`). */\nconst FAR_MEMBER_HP_FLOOR = 0.25\n/**\n * What a wall resists a blast with, J/m² (joules per kg that knock a unit out, times its density and thickness), for which `BREACH_BLAST_REACH` holds:\n * the houses' 13 cm brick wall (200 J/kg, 1900 kg/m³). A stronger wall breaks over less, by the cube root (the scaled distance of a blast).\n */\nconst BLAST_REFERENCE_RESISTANCE = 200 * 1900 * 0.13\n/** The edge of what a blast knocks out of a wall of units is ragged: its radius varies by this share around the hole and from unit to unit. */\nconst BLAST_EDGE_RAGGED = 0.3\n/** Out to this many times the radius of the hole, the units are loosened: they take `BLAST_EDGE_WEAR` of what knocks them out, so the next blow finishes them. */\nconst BLAST_EDGE_LOOSE = 1.35\n/**\n * Pressure-impulse curve at which an unreinforced infill panel (the masonry between two pillars and under the bond beam) fails as a whole:\n * `(P - PANEL_PRESSURE) * (I - PANEL_IMPULSE) >= PANEL_PI` with the reflected peak pressure P (Pa) and the reflected impulse I (Pa·s) the face takes at the middle\n * of the panel. Read from the iso-damage curves of brick walls (UFC 3-340-02, Glasstone and Dolan table 5.139: heavy damage from about 70 kPa when the\n * load lasts): 4.8 kg of TNT 4 m off brings the panel down, a grenade 2 m off or the same 4.8 kg 6 m off only cracks it.\n */\nconst PANEL_PRESSURE = 70_000\nconst PANEL_IMPULSE = 150\nconst PANEL_PI = 6e6\n/** Where the panel is read, as shares of its span and height from its middle, and how many of them must pass `PANEL_PI` for the panel to fail. */\nconst PANEL_POINTS: readonly (readonly [number, number])[] = [[0, 0], [-0.3, 0], [0.3, 0], [0, -0.3], [0, 0.3]]\nconst PANEL_POINTS_LOADED = 4\nconst BLAST_EDGE_WEAR = 0.6\nconst RESIDUAL_CAPACITY = 0.15\n/** Long wooden parts break where they are hit: band length along the part (m) and how much longer than wide a part must be. */\nconst SEVER_BAND = 0.1\nconst SEVER_ASPECT = 3\n/** A round that goes through wood tears its exit out in splinters: its damage counts this many times over in the band it crosses. */\nconst SEVER_BALLISTIC = 2\n/** Joules per piece a blow tears out of a material that tears (`MaterialHit.tearJoules` default): a round leaving wood tears 2 to 7 splinters. */\nconst TEAR_JOULES = 150\n/** Running number of the torn pieces (their ids). */\nlet tears = 0\n/** Metres two parts may be apart and still rest on each other, for the span of a beam or a slab. */\nconst SUPPORT_TOLERANCE = 0.05\n/** Unit-sized fragments of a whole wall: at most this many times `maxFragments`. A breach picks its units from a grid of up to `BREACH_GRID_CAP`. */\nconst UNIT_FRAGMENT_FACTOR = 4\nconst BREACH_GRID_CAP = 4096\n/** Joules per kilogram of a masonry unit that knock it out of its wall (a 4 kg brick: two 9 mm rounds, one rifle round). */\nconst CHIP_ENERGY = 200\n/** Share of a hit's energy the units next to the one hit take, at the edge of the unit hit (falls to 0 at the hit's radius). */\nconst CHIP_SPLASH = 0.5\n/** Share of a unit's face the craters of shots take before the rest of the unit comes out. */\nconst CRATER_SPENT = 0.6\n/** Crater widths from a free edge of a wall (its ends, its top) within which a shot tears the corner off out to the edge. */\nconst EDGE_REACH = 1.5\n/** Metres a bar of an exposed cage bows out of the part's plane at full overload (stress 1.5 and up), per metre of bar. */\nconst BAR_BOW = 0.08\n/** Metres of a joint one bullet shakes loose: a joint longer than this takes only its share of the wear. */\nconst BULLET_JOINT_SPAN = 0.3\n\n/** A cut only goes through a slice of the part, so a part longer than `CUT_SLICE` costs no more to cut than a 1 m piece of the same section. */\nconst CUT_SLICE = 1\nconst cutFactorOf = (shape: PartSpec['shape']): number => clamp(Math.max(...shapeDims(shape)) / CUT_SLICE, 1, 50)\n\ninterface PartRT {\n spec: PartSpec\n mat: MaterialDef\n st: PartState\n q: Quat\n /** Current object-local position (the spec's, unless moved by `setPartPose`). */\n pos: Vec3\n mass0: number\n fuel0: number\n area: number\n thickness: number\n /** Slash damage multiplier: longest dimension / 1 m (1..50). */\n cutFactor: number\n dims: Vec3\n bound: number\n rt: PartRuntime\n /** Structural role other than `none`. */\n structural: boolean\n anchored: boolean\n cap: number\n /** Structural part that never had a support path (the spec itself leaves it floating): it is held by its joints like a non-structural part and does not collapse by itself. */\n orphan: boolean\n /** The part has layers, units, reinforcement or a breach: it goes through damage stages. */\n staged: boolean\n /** Axis the part is thinnest along (the wall's depth). */\n thin: number\n layers: LayerRT[]\n /** Bending geometry, for parts in the bending model (`structure.flexure`). */\n bend?: BendGeometry\n /** Span in metres between the supports it rests on now (0: it rests along its whole length, or on nothing). */\n span: number\n /** Supports the span was measured for (indices joined), to measure it again only when they change. */\n spanKey: string\n /** Moment at rest in N m of the section that bends under its weight. */\n restMoment: number\n /** Load in kg that bends it: its own mass and what rests on it away from its supports. */\n bendLoad: number\n /** Overloaded in bending without steel that holds: when it fails it snaps in two instead of crumbling. */\n snap: boolean\n}\n\n/** A crater in the unit `cell` of `p`, along its axis `a` (`b` is the other axis of the plane), from the hit at `at` (part-local). */\ninterface TornToEdgeOptions {\n readonly p: PartRT\n readonly cell: UnitCell\n readonly a: number\n readonly b: number\n readonly at: number\n readonly crater: [number, number]\n readonly reach: number\n /** The unit at this index of the part's grid was knocked out. */\n readonly gone: (index: number) => boolean\n}\n\ninterface JointRT {\n spec: Required<JointSpec>\n st: JointState\n ia: number\n ib: number\n bears: boolean | 'a_on_b' | 'b_on_a'\n /** Object-local position. */\n pos: Vec3\n step: number\n}\n\ninterface ObjRT {\n id: string\n spec: DestructibleSpec\n st: ObjectState\n parts: PartRT[]\n byId: Map<string, PartRT>\n idx: Map<string, number>\n joints: JointRT[]\n jointMap: Map<string, JointRT>\n byPart: Map<string, JointRT[]>\n /** Local bounding sphere. */\n bc: Vec3\n br: number\n active: boolean\n tmp: number[]\n hasStructure: boolean\n /** Set only while `build` solves the structure for the first time. */\n seeding?: boolean\n dirty: boolean\n maxStress: number\n collapsed: Set<string>\n /** Structural parts with no support path to an anchored part (they fall). */\n unsup: boolean[]\n anyAnchor: boolean\n /** Creation order of the object in this world: breaks ties between parts that go off at the same time. */\n order: number\n /** The pose the host gave (`add`, `setTransform`); `st.position`/`st.rotation` are this with the soil's settlement and tilt on top. */\n base: { pos: Vec3; rot: Quat }\n /** The ground under the object (`DestructibleSpec.soil`), when it has foundations on it. */\n soil?: SoilRT\n /** The wind on the object (`DestructionOptions.wind`), when the world has wind and the object is a structure. */\n wind?: WindRT\n}\n\ninterface WindRT {\n /** The wind of the world with this object's `DestructibleSpec.wind` over it, as of the last analysis. */\n cfg: ResolvedWind\n gust: Gust\n /** What the gust was made for (speed, terrain), to make it again when the wind changes. */\n gustKey: string\n analysis: WindAnalysis | null\n /** Parts of the object that went into the analysis, by input index. */\n parts: number[]\n sys: SwaySystem | null\n /** Mass ratio of the damper and its modal weight in the system (0 without one). */\n mu: number\n dyn: SwayState & { peak: number }\n /** Tension capacity of each wall and column, by part index. */\n tension: Map<number, number>\n /** Time and values of the last `sway` event. */\n emitted: { t: number; peak: number; status: WindState['status'] }\n}\n\ninterface SoilRT {\n profile: SoilProfile\n s: number\n a: number\n b: number\n /** Out-of-plumb of the building, as slopes along x and z. */\n imp: [number, number]\n /** Pivot of the tilt: the centre of stiffness at the level of the base, object-local. */\n pivot: Vec3\n /** The structure changed since the soil was last solved. */\n dirty: boolean\n /** Permanent settlement of the soil under each spring (by `SoilSpring` key) from yielding. */\n sets: Map<string, number>\n /** Time and values of the last `settle` event. */\n emitted: { t: number; s: number; tilt: number; status: SoilState['status'] }\n}\n\ninterface Carry {\n parts: Map<string, { st: PartState; rt: PartRuntime }>\n joints: Map<string, { st: JointState; step: number }>\n collapsed?: string[]\n soil?: SoilState\n soilSets?: Record<string, number>\n wind?: [number, number, number, number, number]\n}\n\n\ninterface Loc {\n p: PartRT\n point: Vec3\n normal: Vec3\n dir: Vec3\n pathLen: number\n}\n\ninterface ImplRT {\n impl: DestructibleImpl\n position: Vec3\n rotation: Quat\n /** Part pose overrides set by `setPartPose` (object-local). */\n poses: Map<string, { pos: Vec3; q: Quat }>\n}\n\ninterface Blast {\n point: Vec3\n energy: number\n radius: number\n lethalRadius?: number\n source?: string\n}\n\nconst clamp = (v: number, a: number, b: number) => Math.max(a, Math.min(b, v))\n/** Millimetres of this material a round goes through: the entry of `Hit.penetration` for its `penetrationClass` (else its id) times the material's `penetrationScale`; undefined when the round has none. */\nconst penetrationOf = (mat: MaterialDef, table: Readonly<Record<string, number>> | undefined): number | undefined => {\n if (!table) return undefined\n const v = table[mat.penetrationClass ?? mat.id] ?? table[mat.id]\n return v === undefined ? undefined : v * (mat.penetrationScale ?? 1)\n}\n/** Share of its capacity a structural part still has: a bare rebar cage keeps the reinforcement's residual, a breached part loses what left it. */\n/** Metres from a buried part of the foundation (a footing, a ground beam) within which a blast still reaches it: a charge laid against it. */\nconst BURIED_BLAST_REACH = 0.5\n/** Share of its hit points a part that gave at its cut keeps: it stands, as damaged as the shots left it. */\nconst GIVE_AT_CUT_HP = 0.5\nconst capacityScale = (p: PartRT, borne?: BorneAt, through?: ThroughAt): number => {\n const residual = p.spec.reinforcement?.residualCapacity ?? RESIDUAL_CAPACITY\n if (p.st.stripped) return residual\n const kept = Math.min(p.rt.removed ? 1 - p.rt.removed / p.mass0 : 1, sectionKept(p, residual, borne, through))\n // the cage keeps its share where the concrete is gone\n return Math.max(p.spec.reinforcement ? residual : 0.05, kept)\n}\n/**\n * Largest share of the cross-section the units knocked out of a part took at one place along its length (`PartState.chipped`): a column with half its\n * width shot away at one height carries half. A wall, a partition or a column carries its load down, so its section is across at one height (a wall\n * with a slot shot along its base stands on what is left of it); any other part's length runs along the longer of the two axes of its face. Where `borne`\n * says a lying part rests on what is under it (a bond beam on its wall), its load goes straight down there and a section shot away at that place takes\n * nothing from what it carries.\n */\ntype BorneAt = (local: Vec3, along: number) => boolean\n/** Share of a standing part's load that goes through the place `local` along `along` (part space): what rests on it, and its own weight above that place. */\ntype ThroughAt = (local: Vec3, along: number) => number\n/**\n * The section a part still has for what it carries: at each place a shot took units out, what is left of the section over the share of the load that\n * goes through there (`through`; a column cut just under its top carries the little that is above the cut), the cage's `residual` at least where the\n * concrete is gone. The smallest of them; 1 when nothing was taken out.\n */\nconst sectionKept = (p: PartRT, residual: number, borne?: BorneAt, through?: ThroughAt): number => {\n let kept = 1\n forEachSection(p, borne, (c, along, gone) => {\n const share = through?.(c.center, along) ?? 1\n if (share <= 0) return\n kept = Math.min(kept, Math.max(p.spec.reinforcement ? residual : 0, 1 - gone) / share)\n })\n return kept\n}\nconst sectionLoss = (p: PartRT, borne?: BorneAt): number => {\n let worst = 0\n forEachSection(p, borne, (_c, _along, gone) => {\n worst = Math.max(worst, gone)\n })\n return Math.min(1, worst)\n}\n/** Calls `visit` with each place along a part's length where units were taken out, the axis of its length and the share of the section gone there. */\nconst forEachSection = (p: PartRT, borne: BorneAt | undefined, visit: (c: { readonly center: Vec3 }, along: number, gone: number) => void): void => {\n const cells = p.st.chipped\n if (!cells?.length) return\n const [u, v] = planeAxes(p.thin)\n const role = p.spec.structure?.role\n const up = rotateVec(p.q, [0, 0, 0].map((_, k) => (k === v ? 1 : 0)) as Vec3)\n const upright = Math.abs(up[1]) > 0.7 ? v : Math.abs(rotateVec(p.q, [0, 0, 0].map((_, k) => (k === u ? 1 : 0)) as Vec3)[1]) > 0.7 ? u : -1\n const along = (role === 'wall' || role === 'partition' || role === 'column') && upright >= 0 ? upright : p.dims[u] >= p.dims[v] ? u : v\n const across = along === u ? v : u\n const lying = along !== upright || upright < 0\n for (const c of cells) {\n if (lying && borne?.(c.center, along)) continue\n // the pieces whose span along the length overlaps this one's centre: what is gone across the section there (overlapping pieces count once)\n const spans: Array<[number, number]> = []\n for (const d of cells) if (Math.abs(d.center[along] - c.center[along]) < d.size[along] / 2 + 1e-6) spans.push([d.center[across] - d.size[across] / 2, d.center[across] + d.size[across] / 2])\n spans.sort((a, b) => a[0] - b[0])\n let gone = 0, end = -Infinity\n for (const [a, b] of spans) {\n if (b <= end) continue\n gone += b - Math.max(a, end)\n end = b\n }\n visit(c, along, Math.min(1, gone / Math.max(p.dims[across], 1e-6)))\n }\n}\nconst isLost = (p: PartRT) => p.st.status === 'broken' || p.st.status === 'melted' || p.st.status === 'ashes'\nconst clone = <T>(v: T): T => structuredClone(v)\n/**\n * Fraction of a structural part's hit points lost per second while its stress is above 1. A floor of 0.12 makes even a barely overloaded part\n * give way in about 8 s (a rate proportional to the excess alone never finishes: stress 1.02 would take two minutes), then it grows with the\n * excess and tops out at 0.6: stress 1.1 fails in ~4.5 s, 1.5 in ~1.9 s and anything above 1.7 in ~1.7 s. Deterministic: depends only on stress.\n */\nconst overloadRate = (stress: number) => Math.min(0.6, 0.12 + 0.8 * (stress - 1))\nconst updateBound = (o: ObjRT) => {\n if (!o.parts.length) return\n const c: Vec3 = [0, 0, 0]\n for (const p of o.parts) for (let k = 0; k < 3; k++) c[k] += p.pos[k] / o.parts.length\n let r = 0\n for (const p of o.parts) r = Math.max(r, vec.distance(c, p.pos) + p.bound)\n o.bc = c\n o.br = r\n}\nconst AXIS = { x: 0, y: 1, z: 2 } as const\n\nexport const createDestruction = (options: DestructionOptions = {}): DestructionWorld => {\n const materials = new Map<MaterialId, MaterialDef>()\n for (const m of MATERIALS) materials.set(m.id, m)\n for (const m of options.materials ?? []) materials.set(m.id, m)\n const ambient = options.ambientC ?? 20\n const maxFragments = options.maxFragments ?? 24\n const maxDents = options.maxDents ?? 24\n const maxHoles = options.maxHoles ?? 32\n const fireSpread = options.fireSpread ?? 0.6\n const breachRadius = options.breach?.radius ?? BREACH_RADIUS\n const structureSafety = options.structure?.safetyFactor ?? 1\n const flexure = resolveFlexure(options.structure?.flexure)\n const masonry = resolveMasonry(options.structure?.masonry)\n const soilCfg = resolveSoil(options.soil)\n let windOpts: WindOptions | undefined = options.wind\n let windCfg: ResolvedWind | null = windOpts ? resolveWind(windOpts) : null\n const ignitionRules = resolveIgnitionRules(options.ignition)\n const breachBlastFactor = options.breach?.blastFactor ?? BREACH_BLAST_FACTOR\n const chipEnergy = options.breach?.chipEnergy ?? CHIP_ENERGY\n const chainLinkCap = options.chainLinksPerUpdate !== undefined && options.chainLinksPerUpdate >= 1 ? Math.floor(options.chainLinksPerUpdate) : Infinity\n const rng = createRng(options.seed ?? 1)\n const rnd = () => rng.next()\n\n let time = 0\n let counter = 0\n const objects = new Map<string, ObjRT>()\n const listeners = new Map<string, Set<(e: DestructionEvent) => void>>()\n let cur: DestructionEvent[] = []\n const blasts: Blast[] = []\n /** Glass the blast front has not reached yet: the damage lands when it does (`blastFrontSpeed`). */\n const frontQueue: Array<{ o: ObjRT; p: PartRT; due: number; amount: number; fragEnergy: number; point: Vec3; src?: string }> = []\n const blastFrontSpeed = options.blastFrontSpeed ?? 0\n /** Explosive parts that were primed and wait for their delay. */\n const primed = new Map<PartRT, ObjRT>()\n let orderCounter = 0\n const impls = new Map<string, ImplRT>()\n const taken = (id: string) => objects.has(id) || impls.has(id)\n\n // -------------------------------------------------------------------------------------------------------------------------------------------\n // Events\n // -------------------------------------------------------------------------------------------------------------------------------------------\n\n const emit = (e: DestructionEvent) => {\n cur.push(e)\n options.onEvent?.(e)\n const all = listeners.get('*')\n if (all) for (const fn of [...all]) fn(e)\n const typed = listeners.get(e.type)\n if (typed) for (const fn of [...typed]) fn(e)\n }\n // the kind of the hit being resolved now (`doHit`): every event it emits carries it as `blow`\n let blow: DamageType | undefined\n const base = (o: ObjRT, source?: string): { object: string; time: number; source?: string; blow?: DamageType } => ({\n object: o.id,\n time,\n ...(source === undefined ? {} : { source }),\n ...(blow === undefined ? {} : { blow }),\n })\n\n const pendingCollapse = new Map<ObjRT, string | undefined>()\n let runDepth = 0\n\n /** Blasts queued by parts that exploded; each can prime or set off more parts. It ends: a part goes off once and is primed once, so the queue only grows by parts not yet lost. */\n const drainBlasts = () => {\n for (let blast = blasts.shift(); blast; blast = blasts.shift()) blastWorld(blast.point, blast.energy, blast.radius, blast.source, undefined, undefined, blast.lethalRadius)\n }\n\n const run = <T>(fn: () => T): { value: T; events: DestructionEvent[] } => {\n const prev = cur\n const mine: DestructionEvent[] = []\n cur = mine\n runDepth++\n try {\n const value = fn()\n drainBlasts()\n if (runDepth === 1) flushCollapse()\n return { value, events: mine }\n } finally {\n runDepth--\n cur = prev\n }\n }\n\n // -------------------------------------------------------------------------------------------------------------------------------------------\n // Building objects\n // -------------------------------------------------------------------------------------------------------------------------------------------\n\n const nextId = () => {\n let id: string\n do id = `obj_${++counter}`\n while (taken(id))\n return id\n }\n\n const freshRuntime = (): PartRuntime => ({ meltEmitted: 0, dripT: 0, prevTemp: ambient, shockT: 0, jet: false })\n\n const resolveSpec = (spec: DestructibleSpec): DestructibleSpec => {\n const out = clone(spec)\n const joints = out.joints ?? inferJoints(out.parts, 0.01, materials)\n const structural = (id: string) => {\n const role = out.parts.find((p) => p.id === id)?.structure?.role\n return role !== undefined && role !== 'none'\n }\n out.joints = joints.map((j) => {\n const def = JOINT_DEFAULTS[j.kind]\n return {\n id: j.id ?? `${j.a}~${j.b}`, a: j.a, b: j.b, kind: j.kind, strength: j.strength ?? def.strength, tools: j.tools ?? [...def.tools], seconds: j.seconds ?? def.seconds,\n bears: j.bears ?? (structural(j.a) && structural(j.b)),\n }\n })\n return out\n }\n\n const build = (spec: DestructibleSpec, id: string, pos: Vec3, rot: Quat, carry?: Carry): ObjRT => {\n const st: ObjectState = { id, position: [pos[0], pos[1], pos[2]], rotation: [rot[0], rot[1], rot[2], rot[3]], parts: [], joints: [], groups: [], destroyed: false }\n if (spec.name !== undefined) st.name = spec.name\n const o: ObjRT = {\n id, spec, st, parts: [], byId: new Map(), idx: new Map(), joints: [], jointMap: new Map(), byPart: new Map(), bc: [0, 0, 0], br: 0, active: false, tmp: [], hasStructure: false, dirty: false, maxStress: 0, collapsed: new Set(carry?.collapsed ?? []), unsup: [], anyAnchor: false, order: ++orderCounter,\n base: { pos: [pos[0], pos[1], pos[2]], rot: [rot[0], rot[1], rot[2], rot[3]] },\n }\n for (const ps of spec.parts) {\n if (o.byId.has(ps.id)) throw new Error(`duplicate part id \"${ps.id}\"`)\n const mat = materials.get(ps.material)\n if (!mat) throw new Error(`unknown material \"${ps.material}\" on part \"${ps.id}\"`)\n const mass0 = partMass(ps, mat)\n const maxHp = Math.max(1, ps.hp ?? mass0 * mat.hpPerKg)\n const fuel0 = mat.thermal.ignitionC !== undefined ? mass0 * (mat.thermal.fuelFraction ?? 0) : 0\n const c = carry?.parts.get(ps.id)\n const staged = !!(ps.layers?.length || ps.reinforcement || ps.units || ps.breach)\n const layers = (ps.layers ?? []).map((l, i) => {\n const lm = materials.get(l.material)\n if (!lm) throw new Error(`unknown material \"${l.material}\" on layer ${i} of part \"${ps.id}\"`)\n return resolveLayer(l, i, lm)\n })\n if (ps.reinforcement && !materials.has(ps.reinforcement.material)) throw new Error(`unknown material \"${ps.reinforcement.material}\" on the reinforcement of part \"${ps.id}\"`)\n const pst: PartState = c?.st ?? {\n id: ps.id, material: ps.material, status: 'intact', hp: maxHp, maxHp, mass: mass0, temperature: ambient, burning: false, fuel: fuel0, char: 0, melt: 0,\n dents: [], holes: [], cracks: [], group: 0, ...(staged ? { stage: 0 as DamageStage } : {}),\n }\n if (!c && ps.contains) pst.liters = ps.contains.liters\n const p: PartRT = {\n spec: ps, mat, st: pst, q: quatFromEuler(...(ps.rotation ?? [0, 0, 0])), pos: [ps.position[0], ps.position[1], ps.position[2]], mass0, fuel0, area: shapeArea(ps.shape), thickness: partThickness(ps), cutFactor: cutFactorOf(ps.shape),\n dims: shapeDims(ps.shape), bound: shapeBound(ps.shape), rt: c?.rt ?? { ...freshRuntime(), prevTemp: pst.temperature },\n structural: !!ps.structure && ps.structure.role !== 'none', anchored: !!ps.anchored || ps.structure?.role === 'foundation', cap: ps.structure ? partCapacity(ps, mat, { masonry, flexure }) : 0, orphan: false,\n staged, thin: thinAxisOf(shapeDims(ps.shape)), layers, span: 0, spanKey: '', restMoment: 0, bendLoad: 0, snap: false,\n ...(ps.shape.kind === 'box' && isFlexural(ps, mat, flexure) ? { bend: bendGeometry(ps) } : {}),\n }\n if (p.structural) o.hasStructure = true\n if (p.rt.chainDue !== undefined && !isLost(p)) primed.set(p, o)\n o.idx.set(ps.id, o.parts.length)\n o.parts.push(p)\n o.byId.set(ps.id, p)\n o.st.parts.push(pst)\n o.byPart.set(ps.id, [])\n }\n for (const js of spec.joints ?? []) {\n const r = js as Required<JointSpec>\n const ia = o.idx.get(r.a), ib = o.idx.get(r.b)\n if (ia === undefined || ib === undefined) throw new Error(`joint \"${r.id}\" references an unknown part`)\n if (o.jointMap.has(r.id)) throw new Error(`duplicate joint id \"${r.id}\"`)\n const pa = o.parts[ia], pb = o.parts[ib]\n const A = aabbOf(pa.spec.shape, pa.spec.position, pa.q)\n const B = aabbOf(pb.spec.shape, pb.spec.position, pb.q)\n const pos: Vec3 = [0, 0, 0]\n for (let k = 0; k < 3; k++) pos[k] = (Math.max(A.min[k], B.min[k]) + Math.min(A.max[k], B.max[k])) / 2\n const bears: JointRT['bears'] = r.bears ?? (pa.structural && pb.structural)\n const c = carry?.joints.get(r.id)\n const jst: JointState = c?.st ?? { id: r.id, a: r.a, b: r.b, kind: r.kind, hp: r.strength, maxHp: r.strength, progress: 0, open: false }\n const j: JointRT = { spec: r, st: jst, ia, ib, bears, pos, step: c?.step ?? 0 }\n o.joints.push(j)\n o.jointMap.set(r.id, j)\n o.byPart.get(r.a)!.push(j)\n o.byPart.get(r.b)!.push(j)\n o.st.joints.push(jst)\n }\n // open joints whose parts are no longer both here (left behind by `splitGroup`) stay listed, inert, so callers still see them open\n for (const [jid, c] of carry?.joints ?? []) if (c.st.open && !o.jointMap.has(jid)) o.st.joints.push(c.st)\n updateBound(o)\n o.anyAnchor = o.parts.some((p) => p.anchored)\n o.unsup = o.parts.map(() => false)\n if (windCfg && o.hasStructure && spec.wind !== false) o.wind = newWind(o, carry?.wind)\n const ground = spec.soil ?? soilCfg.site\n if (ground !== undefined && o.parts.some((p) => p.spec.structure?.role === 'foundation')) initSoil(o, profileOf(ground), carry?.soil, carry?.soilSets)\n o.seeding = true\n solveStructure(o)\n o.seeding = false\n if (o.soil && !carry?.soil) settleSoil(o, 0)\n if (o.soil) o.soil.dirty = false\n recomputeGroups(o)\n o.st.destroyed = o.parts.length > 0 && o.parts.every(isLost)\n o.active = o.maxStress > 0.8 || o.parts.some((p) => p.st.burning || p.st.temperature > ambient + 0.5 || (p.st.liters ?? 0) > 0)\n return o\n }\n\n const recomputeGroups = (o: ObjRT) => {\n const n = o.parts.length\n const parent = Array.from({ length: n }, (_, i) => i)\n const find = (i: number): number => {\n while (parent[i] !== i) {\n parent[i] = parent[parent[i]]\n i = parent[i]\n }\n return i\n }\n const union = (a: number, b: number) => {\n parent[find(a)] = find(b)\n }\n const live = (j: JointRT) => !j.st.open && !isLost(o.parts[j.ia]) && !isLost(o.parts[j.ib])\n if (o.unsup.some(Boolean)) {\n // parts that lost every support fall: cut them from the supported pieces; loose non-structural parts follow the part they hang on\n for (const j of o.joints) if (live(j) && !o.unsup[j.ia] && !o.unsup[j.ib]) union(j.ia, j.ib)\n const supported = new Set<number>()\n for (let i = 0; i < n; i++) if (!isLost(o.parts[i]) && !o.unsup[i] && (o.parts[i].structural || o.parts[i].anchored)) supported.add(find(i))\n for (const j of o.joints) {\n if (!live(j) || !(o.unsup[j.ia] || o.unsup[j.ib])) continue\n if (o.unsup[j.ia] && o.unsup[j.ib]) union(j.ia, j.ib)\n else {\n const u = o.unsup[j.ia] ? j.ia : j.ib\n const other = u === j.ia ? j.ib : j.ia\n if (!o.parts[other].structural && !supported.has(find(other))) union(u, other)\n }\n }\n } else for (const j of o.joints) if (live(j)) union(j.ia, j.ib)\n const comps = new Map<number, number[]>()\n for (let i = 0; i < n; i++) {\n if (isLost(o.parts[i])) continue\n const r = find(i)\n const l = comps.get(r)\n if (l) l.push(i)\n else comps.set(r, [i])\n }\n const list = [...comps.values()].map((ix) => ({\n ix,\n anchored: ix.some((i) => o.parts[i].anchored),\n mass: ix.reduce((s, i) => s + o.parts[i].st.mass, 0),\n }))\n list.sort((a, b) => (a.anchored === b.anchored ? (b.mass - a.mass) || (a.ix[0] - b.ix[0]) : a.anchored ? -1 : 1))\n o.st.groups = list.map((g) => g.ix.map((i) => o.parts[i].spec.id))\n for (const p of o.parts) if (isLost(p)) p.st.group = -1\n list.forEach((g, gi) => g.ix.forEach((i) => (o.parts[i].st.group = gi)))\n }\n\n /**\n * Which part `r` rests on over joint `j` (index), or -1 when the joint does not let `r` rest on its other end. A `tie` is a rope: it only pulls,\n * so it holds `r` up only when `r` hangs below the part it is tied to (a lamp from a ceiling), never when that part is beside or under it\n * (a guy rope to a stake in the ground).\n */\n const restsOn = (o: ObjRT, j: JointRT, r: number): number => {\n const b = j.bears\n if (!b) return -1\n const k = b === true ? (j.ia === r ? j.ib : j.ia) : b === 'a_on_b' ? (j.ia === r ? j.ib : -1) : j.ib === r ? j.ia : -1\n if (k < 0 || j.spec.kind !== 'tie') return k\n return partXf(o, o.parts[k]).c[1] > partXf(o, o.parts[r]).c[1] + 1e-6 ? k : -1\n }\n\n // -------------------------------------------------------------------------------------------------------------------------------------------\n // Bending (`structure.flexure`): span from the supports, moment at rest, blast impulse on the span\n // -------------------------------------------------------------------------------------------------------------------------------------------\n\n /** Bumped when a part is posed again, which is what makes a remembered contact box stale. */\n let poseVersion = 0\n const contactMemo = new WeakMap<PartRT, Map<PartRT, { version: number; box: [Vec3, Vec3] }>>()\n\n /** Where `p` touches `support`, as a box in `p`'s own axes (remembered per pair: the solver asks for the same pairs again at every joint that breaks). */\n const contactBox = (p: PartRT, support: PartRT): [Vec3, Vec3] => {\n let byTouching = contactMemo.get(p)\n if (!byTouching) contactMemo.set(p, (byTouching = new Map()))\n const known = byTouching.get(support)\n if (known && known.version === poseVersion) return known.box\n const box = measureContact(p, support)\n byTouching.set(support, { version: poseVersion, box })\n return box\n }\n\n /**\n * The share of a standing part's load that goes through a place along its height: what rests on it plus its own weight above that place, over all it\n * carries. Undefined for a lying part (its length is across the load).\n */\n const throughOf = (p: PartRT): ThroughAt | undefined => {\n const load = p.st.load ?? 0\n if (load <= 0) return undefined\n const above = Math.max(0, load - p.st.mass)\n const up = rotateVec(p.q, [0, 1, 0])\n return (local, along) => {\n const axis: Vec3 = [0, 0, 0]\n axis[along] = 1\n const sign = Math.sign(rotateVec(p.q, axis)[1])\n // only an upright length carries its load down through a section\n if (Math.abs(up[1]) < 0.7 && Math.abs(rotateVec(p.q, axis)[1]) < 0.7) return 1\n const half = p.dims[along] / 2\n const share = clamp((half - sign * local[along]) / Math.max(p.dims[along], 1e-6), 0, 1)\n return (above + p.st.mass * share) / load\n }\n }\n\n /** Where a part rests on its supports: a place along its length (part space) over the contact of one of them. */\n const borneOn = (p: PartRT, supports: readonly PartRT[]): BorneAt | undefined => {\n if (supports.length === 0) return undefined\n const boxes = supports.map((support) => contactBox(p, support))\n return (local, along) => boxes.some(([lo, hi]) => local[along] >= lo[along] - SUPPORT_TOLERANCE && local[along] <= hi[along] + SUPPORT_TOLERANCE)\n }\n\n const measureContact = (p: PartRT, support: PartRT): [Vec3, Vec3] => {\n const A = aabbOf(p.spec.shape, p.pos, p.q), B = aabbOf(support.spec.shape, support.pos, support.q)\n const lo: Vec3 = [0, 0, 0], hi: Vec3 = [0, 0, 0]\n for (let k = 0; k < 3; k++) {\n const a = Math.max(A.min[k], B.min[k]) - SUPPORT_TOLERANCE, b = Math.min(A.max[k], B.max[k]) + SUPPORT_TOLERANCE\n lo[k] = Math.min(a, b)\n hi[k] = Math.max(a, b)\n }\n const out: [Vec3, Vec3] = [[Infinity, Infinity, Infinity], [-Infinity, -Infinity, -Infinity]]\n for (let c = 0; c < 8; c++) {\n const l = toLocal(p.pos, p.q, [c & 1 ? hi[0] : lo[0], c & 2 ? hi[1] : lo[1], c & 4 ? hi[2] : lo[2]])\n for (let k = 0; k < 3; k++) {\n out[0][k] = Math.min(out[0][k], l[k])\n out[1][k] = Math.max(out[1][k], l[k])\n }\n }\n return out\n }\n\n /** The centre of where `above` touches `p`, in object space. */\n const contactCentre = (p: PartRT, above: PartRT): Vec3 => {\n const [lo, hi] = contactBox(p, above)\n return toWorld(p.pos, p.q, [(lo[0] + hi[0]) / 2, (lo[1] + hi[1]) / 2, (lo[2] + hi[2]) / 2])\n }\n\n /**\n * The support of `p` (index into the object's parts, among `lower`) that a load standing at `at` (object space) is over: within one depth of `p` of\n * where `p` rests on it, so the load goes straight down by a strut instead of bending `p` (a load that near a support is not carried in bending,\n * EN 1992-1-1 6.2.2(6)). -1 when it is over none.\n */\n const overSupportAt = (o: ObjRT, p: PartRT, at: Vec3, lower: readonly number[]): number => {\n const g = p.bend!\n const local = toLocal(p.pos, p.q, at)\n const depth = g.gravity >= 0 ? g.dims[g.gravity] : Math.min(...g.depthAxes.map((a) => g.dims[a]))\n let best = -1\n let bestGap = depth\n for (const k of lower) {\n const [a, b] = contactBox(p, o.parts[k])\n let gap = 0\n for (const ax of g.spanAxes) gap = Math.max(gap, a[ax] - local[ax], local[ax] - b[ax])\n if (gap <= bestGap) {\n best = k\n bestGap = gap - 1e-9\n }\n }\n return best\n }\n\n /** The section of `p` that bends along `axis`, with its tension steel and moments (a bare cage keeps only the steel's residual). */\n const sectionOf = (p: PartRT, axis: number) => {\n const g = p.bend!\n const section = { b: sectionWidth(g, axis), h: g.dims[axis] }\n const rebar = tensionSteel(p.spec, g.dims, section, flexure)\n return { section, rebar, ...sectionMoments(p.mat, section, rebar, flexure) }\n }\n\n /** Moment at rest over the moment the section holds, for the supports `lower` (indices) `p` rests on now. Sets `p.span` and `p.restMoment`. */\n const restFlexure = (o: ObjRT, p: PartRT, lower: readonly number[]): number => {\n const g = p.bend!\n const key = lower.join(',')\n if (key !== p.spanKey) {\n p.spanKey = key\n p.span = spanOf(g, lower.map((k) => contactBox(p, o.parts[k])))\n }\n p.restMoment = 0\n if (g.gravity < 0 || p.span <= 0) return 0\n const sec = sectionOf(p, g.gravity)\n p.restMoment = spanMoment(lineLoad(g, p.bendLoad) * Math.abs(g.up[g.gravity]), p.span)\n // once the tension face has cracked only the steel holds; a bare cage keeps its residual share\n const holds = (p.st.cracked ? sec.steel : sec.ultimate) * capacityScale(p)\n return (p.restMoment * structureSafety) / Math.max(holds, 1)\n }\n\n /**\n * A blast bends a beam or a slab: the reflected impulse over the span (`blastImpulse`, averaged over points of the face that takes it) gives the\n * span kinetic energy (`impulseEnergy`), which it takes as strain energy up to a peak moment (`momentOfEnergy`), added to or taken from the moment at\n * rest when the blast pushes along the weight. Past the cracking moment the tension face cracks; a section whose steel does not hold more than that\n * snaps; a reinforced one yields and fails when its plastic rotation (`(U(M) - U(Mu)) / (2 Mu)` per blast, added up) reaches `failRotationDeg`.\n */\n const bendByBlast = (o: ObjRT, p: PartRT, point: Vec3, energy: number, radius: number, reach: number, src?: string) => {\n const g = p.bend\n if (!g || p.span <= 0 || isLost(p) || p.st.stripped || reach <= 0) return\n const s = p.mat.strength!\n if (!s.elasticGPa) return\n const { c, q } = partXf(o, p)\n const near = surfacePoint(p.spec.shape, toLocal(c, q, point))\n const local = toLocal(c, q, point)\n const away = vec.normalize(vec.sub(near.point, local), vec.scale(near.normal, -1))\n let axis = g.depthAxes[0]!\n for (const a of g.depthAxes) if (Math.abs(away[a]) > Math.abs(away[axis])) axis = a\n const cos = Math.abs(away[axis])\n if (cos < 1e-3) return\n const tnt = energy / flexure.tntJoules\n const L = p.span\n const offsets = g.member ? [[-0.5], [-0.25], [0], [0.25], [0.5]] : [[0, 0], [-0.25, 0], [0.25, 0], [0, -0.25], [0, 0.25]]\n const face = -Math.sign(away[axis]) * g.dims[axis] / 2\n let sum = 0\n for (const off of offsets) {\n const sp: Vec3 = [near.point[0], near.point[1], near.point[2]]\n g.spanAxes.forEach((a, k) => (sp[a] = Math.max(-g.dims[a] / 2, Math.min(g.dims[a] / 2, sp[a] + off[k]! * L))))\n sp[axis] = face\n const r = vec.distance(toWorld(c, q, sp), point)\n if (r < radius) sum += blastImpulse(tnt, r, flexure)\n }\n const width = sectionWidth(g, axis)\n const impulse = (sum / offsets.length) * cos * reach * width * L\n const weight = axis === g.gravity ? p.bendLoad : p.st.mass\n const kinetic = impulseEnergy(impulse, (lineLoad(g, weight) / GRAVITY) * L, flexure)\n const sec = sectionOf(p, axis)\n const EI = (s.elasticGPa * 1e9 * sec.section.b * sec.section.h ** 3) / 12\n const along = axis === g.gravity ? -Math.sign(away[axis] * g.up[axis]) : 0\n const dynamic = momentOfEnergy(kinetic, L, EI, flexure.loadFactor)\n const peak = Math.abs(dynamic + along * p.restMoment)\n if (peak <= sec.cracking) return\n if (!p.st.cracked) {\n p.st.cracked = true\n const tension: Vec3 = [near.point[0], near.point[1], near.point[2]]\n tension[axis] = dynamic + along * p.restMoment >= 0 ? -face : face\n const n: Vec3 = [0, 0, 0]\n n[axis] = Math.sign(tension[axis]) || 1\n addCrack(o, p, toWorld(c, q, tension), rotateVec(q, n), sec.section.b, src)\n }\n if (!sec.reinforced) {\n p.snap = true\n failPart(o, p, point, away, kinetic, 12, src, 'snap')\n return\n }\n // a lightly reinforced section (its steel holds less than the concrete did) now carries only what the steel gives\n solveStructure(o)\n if (peak <= sec.steel) return\n const rotation = (elasticEnergy(peak, L, EI, flexure.loadFactor) - elasticEnergy(sec.steel, L, EI, flexure.loadFactor)) / (2 * sec.steel)\n p.rt.hinge = (p.rt.hinge ?? 0) + rotation\n markDamaged(p)\n if (p.rt.hinge >= (flexure.failRotationDeg * Math.PI) / 180) hingeDrop(o, p, src)\n }\n\n /** Span a part is left with on `supports` along its longest axis: twice the farthest any point of it is from a support (a cantilever's is twice its overhang). */\n const freeSpan = (p: PartRT, supports: readonly PartRT[]): number => {\n if (supports.length === 0) return Infinity\n const d = p.dims\n const L = [0, 1, 2].sort((a, b) => d[b] - d[a])[0]\n const spans = supports.map((k) => contactBox(p, k)).map(([lo, hi]) => [lo[L], hi[L]] as const)\n let far = 0\n for (let i = 0; i <= 16; i++) {\n const x = (i / 16 - 0.5) * d[L]\n let near = Infinity\n for (const [lo, hi] of spans) near = Math.min(near, Math.max(lo - x, x - hi, 0))\n far = Math.max(far, near)\n }\n return 2 * far\n }\n\n /** Distribute own mass plus carried load down the bearing graph to the anchored parts; mark parts without any support path. */\n const solveStructure = (o: ObjRT) => {\n o.maxStress = 0\n if (!o.hasStructure) return\n const parts = o.parts\n const n = parts.length\n const dist = new Array<number>(n).fill(-1)\n const ok = (i: number) => parts[i].structural && !isLost(parts[i])\n const isPartition = (i: number) => parts[i].spec.structure?.role === 'partition'\n // a part whose supports leave it a longer span than it holds (`structure.maxSpan`) is out, and so is what stood on it only through it\n const out = new Set<number>()\n let queue: number[] = []\n let lowerOf = new Map<number, number[]>()\n for (;;) {\n dist.fill(-1)\n queue = []\n for (let i = 0; i < n; i++) if (ok(i) && !out.has(i) && parts[i].anchored) {\n dist[i] = 0\n queue.push(i)\n }\n for (let h = 0; h < queue.length; h++) {\n const s = queue[h]\n if (isPartition(s)) continue\n for (const j of o.byPart.get(parts[s].spec.id)!) {\n if (j.st.open || !j.bears) continue\n const r = j.ia === s ? j.ib : j.ia\n if (dist[r] >= 0 || !ok(r) || out.has(r) || restsOn(o, j, r) !== s) continue\n dist[r] = dist[s] + 1\n queue.push(r)\n }\n }\n lowerOf = new Map<number, number[]>()\n let dropped = false\n for (const i of queue) {\n const lower: number[] = []\n for (const j of o.byPart.get(parts[i].spec.id)!) {\n if (j.st.open || !j.bears) continue\n const k = restsOn(o, j, i)\n if (k >= 0 && dist[k] >= 0 && dist[k] < dist[i] && !isPartition(k)) lower.push(k)\n }\n lowerOf.set(i, lower)\n const max = parts[i].spec.structure?.maxSpan\n if (max !== undefined && !parts[i].anchored && freeSpan(parts[i], lower.map((k) => parts[k])) > max) {\n out.add(i)\n dropped = true\n }\n }\n if (!dropped) break\n }\n const incoming = new Array<number>(n).fill(0)\n // the part of the load that bends a beam or a slab: what rests on it away from its supports. A load that stands over a support (a column\n // standing on a slab right over the beam below, a wall right over the wall below) goes straight down to that support with where it stands,\n // and bends that one only if it is away from its own supports\n const bending = new Array<number>(n).fill(0)\n const through: Array<Array<{ at: Vec3; mass: number; over: number }>> = parts.map(() => [])\n const pass = (k: number, at: Vec3, mass: number) => {\n const over = overSupportAt(o, parts[k], at, lowerOf.get(k) ?? [])\n if (over < 0) bending[k] += mass\n else through[k].push({ at, mass, over })\n }\n for (let h = queue.length - 1; h >= 0; h--) {\n const i = queue[h]\n const total = parts[i].st.mass + incoming[i]\n parts[i].st.load = total\n const lower = lowerOf.get(i)!\n for (const k of lower) incoming[k] += total / lower.length\n if (lower.length === 0) continue\n const bulk = parts[i].bend ? parts[i].st.mass + bending[i] : total\n for (const k of lower) if (parts[k].bend) pass(k, contactCentre(parts[k], parts[i]), bulk / lower.length)\n if (parts[i].bend) for (const item of through[i]) if (parts[item.over]?.bend) pass(item.over, item.at, item.mass)\n }\n for (let i = 0; i < n; i++) {\n const p = parts[i]\n o.unsup[i] = false\n if (!p.structural) continue\n if (dist[i] < 0 || isLost(p)) {\n p.st.load = p.st.mass\n p.st.stress = 0\n if (o.seeding && !p.anchored && !isLost(p) && p.st.status !== 'collapsed' && !o.collapsed.has(p.spec.id)) p.orphan = true\n o.unsup[i] = o.anyAnchor && !isLost(p) && !p.orphan\n continue\n }\n p.st.stress = (p.st.load! * structureSafety) / (p.cap * capacityScale(p, borneOn(p, (lowerOf.get(i) ?? []).map((k) => parts[k])), throughOf(p)))\n if (p.bend) {\n p.bendLoad = p.st.mass + bending[i]\n const bent = restFlexure(o, p, lowerOf.get(i) ?? [])\n p.st.flexure = bent\n p.snap = bent > 1 && !p.st.stripped && !sectionOf(p, p.bend.gravity).reinforced\n // a beam or slab carries its load in bending: the load the solver routes through it is not a compression it takes, unless a designer gave\n // it a capacity (`structure.capacity`, `sizeStructure`), which then holds as well\n if (p.spec.structure?.capacity === undefined || bent > p.st.stress) p.st.stress = bent\n }\n if (p.st.stress > o.maxStress) o.maxStress = p.st.stress\n }\n if (o.wind) applyWind(o)\n if (o.maxStress > 0.8) o.active = true\n if (o.soil) o.soil.dirty = true\n }\n\n // -------------------------------------------------------------------------------------------------------------------------------------------\n // Wind (`DestructionOptions.wind`): lateral load that grows with height, the walls and frame that resist it, the sway of the top\n // -------------------------------------------------------------------------------------------------------------------------------------------\n\n const newWind = (o: ObjRT, carried?: [number, number, number, number, number]): WindRT => {\n const cfg = exposureOf(windCfg!, o.spec.wind)\n const [x = 0, v = 0, y = 0, w = 0, peak = 0] = carried ?? []\n return {\n cfg, gust: { freq: [], amp: [], phase: [] }, gustKey: '', analysis: null, parts: [], sys: null, mu: 0, dyn: { x, v, y, w, peak }, tension: new Map(),\n emitted: { t: -Infinity, peak: 0, status: 'ok' },\n }\n }\n\n /** The wind direction in the object's own axes: the horizontal unit vector `[x, z]`. */\n const windDirection = (o: ObjRT, cfg: ResolvedWind): [number, number] => {\n const d = rotateVec(quat.conjugate(o.base.rot), cfg.direction)\n const h = Math.hypot(d[0], d[2])\n return h > 1e-9 ? [d[0] / h, d[2] / h] : [1, 0]\n }\n\n /** Axial force the wind adds to the walls and columns, the design drift and the first mode of the object as it stands now. */\n const applyWind = (o: ObjRT) => {\n const w = o.wind!\n const cfg = (w.cfg = exposureOf(windCfg!, o.spec.wind))\n const terrain = cfg.terrains.get(cfg.terrain)\n if (!terrain) throw new Error(`unknown wind terrain \"${cfg.terrain}\"`)\n const inputs: WindPartInput[] = []\n const at = new Map<number, number>()\n const keep: number[] = []\n let ground = Infinity, foundationTop = -Infinity\n o.parts.forEach((p, i) => {\n if (isLost(p) || isTerrain(p) || o.collapsed.has(p.spec.id) || o.unsup[i]) return\n const box = aabbOf(p.spec.shape, p.pos, p.q)\n const role = p.spec.structure?.role\n const e = p.mat.strength?.elasticGPa\n const kind: WindPartInput['kind'] = role === 'wall' ? 'wall' : role === 'column' ? 'column' : role === 'beam' ? 'beam' : role === 'foundation' ? 'foundation' : 'other'\n at.set(i, inputs.length)\n keep.push(i)\n ground = Math.min(ground, box.min[1])\n if (kind === 'foundation') foundationTop = Math.max(foundationTop, box.max[1])\n inputs.push({ min: box.min, max: box.max, kind, ...(e ? { elasticPa: e * 1e9 } : {}), mass: p.st.mass, ...(p.spec.damper ? { damper: true } : {}) })\n })\n keep.forEach((i, k) => {\n if (inputs[k].kind !== 'column') return\n const beams: number[] = []\n for (const j of o.byPart.get(o.parts[i].spec.id)!) {\n if (j.st.open) continue\n const b = at.get(j.ia === i ? j.ib : j.ia)\n if (b !== undefined && inputs[b].kind === 'beam') beams.push(b)\n }\n inputs[k].beams = beams\n })\n // a slab that rests on a beam works with it as a flange\n keep.forEach((i, k) => {\n if (inputs[k].kind !== 'beam') return\n for (const j of o.byPart.get(o.parts[i].spec.id)!) {\n if (j.st.open) continue\n const q = o.parts[j.ia === i ? j.ib : j.ia]\n const role = q.spec.structure?.role\n if ((role === 'slab' || role === 'roof') && !isLost(q) && q.spec.shape.kind === 'box') {\n inputs[k].slab = q.dims[1]\n break\n }\n }\n })\n const c: WindCase = {\n speed: cfg.speed, direction: windDirection(o, cfg), terrain, cls: cfg.class, topography: cfg.topography, statistical: cfg.statistical, drag: cfg.drag, damping: cfg.damping,\n airDensity: cfg.airDensity, minHeight: cfg.minHeight, bandHeight: cfg.bandHeight, stiffnessFactor: cfg.stiffnessFactor, beamFactor: cfg.beamFactor, loadFactor: cfg.loadFactor,\n chord: cfg.chord, meanRatio: cfg.meanRatio, gustFactor: cfg.gustFactor, flange: cfg.flange,\n }\n const a = inputs.length && cfg.speed > 0 ? analyzeWind(inputs, c, foundationTop > -Infinity ? foundationTop : ground) : null\n w.analysis = a\n w.parts = keep\n for (const p of o.parts) delete p.st.wind\n if (!a) {\n w.sys = null\n delete o.st.wind\n return\n }\n // the load on the walls and columns: compression adds to their load, tension takes from it (and pulls on the part when it passes the dead load)\n keep.forEach((i, k) => {\n const N = a.axial[k]\n const p = o.parts[i]\n if (!N || !p.structural || o.unsup[i]) return\n p.st.wind = N\n const dead = p.st.load ?? p.st.mass\n const force = N * cfg.loadFactor\n let stress = 0\n if (force >= 0) stress = (dead * structureSafety + force / GRAVITY) / (p.cap * capacityScale(p))\n else if (dead + force / GRAVITY < 0) {\n let cap = w.tension.get(i)\n if (cap === undefined) {\n const r = p.spec.reinforcement\n const ratio = p.spec.structure?.rebar?.ratio\n cap = tensionCapacity(p.dims, {\n ...(r ? { reinforcement: r } : {}), ...(ratio ? { ratio } : {}), yieldMPa: flexure.rebarYieldMPa,\n ...(p.mat.strength?.tensileMPa !== undefined ? { tensileMPa: p.mat.strength.tensileMPa } : {}),\n })\n w.tension.set(i, cap)\n }\n stress = Math.min(10, (-(dead + force / GRAVITY) * GRAVITY) / Math.max(cap * capacityScale(p), 1))\n }\n if (stress > (p.st.stress ?? 0)) p.st.stress = stress\n if ((p.st.stress ?? 0) > o.maxStress) o.maxStress = p.st.stress ?? 0\n })\n // the first mode, with the tuned mass damper if there is one\n const key = `${cfg.speed}|${cfg.terrain}|${cfg.topography}|${cfg.statistical}|${cfg.meanRatio}|${cfg.gust.components}|${cfg.gust.maxHz}|${cfg.gust.scale}|${cfg.gust.seed}`\n if (key !== w.gustKey) {\n w.gustKey = key\n const v10 = cfg.speed * cfg.topography * cfg.statistical * meanHeightFactor(10, terrain, a.cls, { meanRatio: cfg.meanRatio, minHeight: cfg.minHeight })\n w.gust = makeGust(v10, cfg.gust)\n }\n let md = 0, spec: PartSpec['damper'] | undefined\n for (const i of keep) {\n const p = o.parts[i]\n if (!p.spec.damper) continue\n const phi = shapeAt(a, p.pos[1] - (foundationTop > -Infinity ? foundationTop : ground))\n md += p.st.mass * phi * phi\n spec ??= p.spec.damper\n }\n const sys: SwaySystem = { M: a.modalMass, K: a.modalStiffness, C: 2 * cfg.damping * a.omega * a.modalMass }\n w.mu = 0\n if (md > 0 && a.modalMass > 0) {\n w.mu = md / a.modalMass\n const tuned = damperTuning(w.mu, cfg.tuning)\n const f = spec?.frequency ?? tuned.frequency * a.frequency\n const zeta = spec?.damping ?? tuned.damping\n sys.damper = { m: md, k: md * (2 * Math.PI * f) ** 2, c: 2 * zeta * md * 2 * Math.PI * f }\n }\n w.sys = a.modalMass > 0 && a.omega > 0 ? sys : null\n const st: WindState = {\n speed: cfg.speed, pressure: a.pressure, shear: a.shear, moment: a.moment, deflection: a.deflection, drift: a.drift, limit: cfg.driftLimit, overturn: Math.min(a.overturn, 1000),\n frequency: a.frequency, lean: a.lean, sway: w.dyn.x, peak: w.dyn.peak, status: a.overturn > 1 ? 'overturn' : a.drift > cfg.driftLimit ? 'drift' : 'ok',\n }\n if (sys.damper) st.damper = { ratio: w.mu, travel: w.dyn.y - w.dyn.x }\n o.st.wind = st\n }\n\n /** Moves the top of the building with the gust (the first mode and the damper, integrated together) and reports `sway` when it changes. */\n const stepWind = (o: ObjRT, dt: number) => {\n const w = o.wind!\n const a = w.analysis\n const st = o.st.wind\n if (!a || !st || !w.sys) return\n const gust = w.gust\n const I = a.intensity\n const force = (t: number) => {\n const n = gustAt(gust, t)\n return a.modalForce * (2 * I * n + I * I * (n * n - 1))\n }\n const wn = Math.max(a.omega, w.sys.damper ? Math.sqrt(w.sys.damper.k / w.sys.damper.m) : 0)\n stepSway(w.dyn, w.sys, time - dt, dt, force, (2 * Math.PI) / wn / 20)\n const d = w.dyn\n d.peak = Math.max(Math.abs(d.x), d.peak * Math.exp(-dt / w.cfg.peakDecay))\n st.sway = d.x\n st.peak = d.peak\n if (st.damper) st.damper.travel = d.y - d.x\n const e = w.emitted\n if (d.peak < e.peak * 0.8) e.peak = d.peak\n if (st.status !== e.status || (time - e.t >= 0.5 && d.peak > e.peak * 1.05 + 1e-3)) {\n w.emitted = { t: time, peak: d.peak, status: st.status }\n const dir = windDirection(o, w.cfg)\n const world = rotateVec(o.base.rot, [dir[0], 0, dir[1]])\n emit({ ...base(o), type: 'sway', sway: d.x, peak: d.peak, drift: st.drift, overturn: st.overturn, frequency: st.frequency, direction: world, status: st.status })\n }\n }\n\n // -------------------------------------------------------------------------------------------------------------------------------------------\n // Soil (`DestructibleSpec.soil`): footings and piles on the ground, settlement, tilt and tipping over\n // -------------------------------------------------------------------------------------------------------------------------------------------\n\n const isTerrain = (p: PartRT) => !!p.spec.tags?.includes('terrain')\n const isFoundation = (p: PartRT) => p.spec.structure?.role === 'foundation' && !isLost(p)\n const slopeTilt = (a: number, b: number) => Math.atan(Math.hypot(a, b))\n\n /** The springs the object stands on: a grid of cells under each footing, one per pile, and a footing under each part that rests on the terrain. */\n const soilSprings = (o: ObjRT, profile: SoilProfile): { springs: Array<SoilSpring & { key: string }>; baseY: number } => {\n const found = o.parts.filter(isFoundation)\n const box = (p: PartRT) => aabbOf(p.spec.shape, p.pos, p.q)\n const surface = profile.surface ?? Math.max(...found.map((p) => box(p).max[1]))\n const prints: Array<{ x0: number; x1: number; z0: number; z1: number; bottom: number; part: PartRT }> = []\n for (const f of found) {\n const b = box(f)\n if (!isTerrain(f)) {\n prints.push({ x0: b.min[0], x1: b.max[0], z0: b.min[2], z1: b.max[2], bottom: b.min[1], part: f })\n continue\n }\n // the ground itself: each structural part that rests on it gets a footing at least `footingWidth` wide (a strip under a wall, a pad under a pillar)\n const fi = o.idx.get(f.spec.id)!\n const width = profile.footingWidth ?? soilCfg.footingWidth\n for (const j of o.byPart.get(f.spec.id)!) {\n if (j.st.open || !j.bears) continue\n const r = j.ia === fi ? j.ib : j.ia\n const q = o.parts[r]\n if (!q.structural || isLost(q) || restsOn(o, j, r) !== fi) continue\n const c = box(q)\n const x0 = Math.max(c.min[0], b.min[0]), x1 = Math.min(c.max[0], b.max[0]), z0 = Math.max(c.min[2], b.min[2]), z1 = Math.min(c.max[2], b.max[2])\n const cx = (x0 + x1) / 2, cz = (z0 + z1) / 2\n const wx = Math.max(width, x1 - x0), wz = Math.max(width, z1 - z0)\n prints.push({ x0: cx - wx / 2, x1: cx + wx / 2, z0: cz - wz / 2, z1: cz + wz / 2, bottom: c.min[1], part: q })\n }\n }\n const springs: Array<SoilSpring & { key: string }> = []\n for (const fp of prints) {\n const wx = Math.max(0.01, fp.x1 - fp.x0), wz = Math.max(0.01, fp.z1 - fp.z0)\n const depth = Math.max(0, surface - fp.bottom)\n const pile = fp.part.spec.structure?.role === 'foundation' ? fp.part.spec.structure.pile : undefined\n if (pile) {\n const count = Math.max(1, Math.round(pile.count ?? 1))\n const nx = Math.ceil(Math.sqrt(count)), nz = Math.ceil(count / nx)\n const cap = pileCapacity(profile, pile, depth, soilCfg.byId).ultimate\n const tip = soilAt(profile, depth + pile.length, soilCfg.byId)\n const k = pileStiffness(pile, fp.part.mat.strength?.elasticGPa ?? soilCfg.pileElasticGPa, tip.elasticMPa, tip.poisson)\n for (let i = 0; i < count; i++) {\n const col = i % nx, row = Math.floor(i / nx)\n springs.push({ key: `${fp.part.spec.id}#${i}`, x: fp.x0 + ((col + 0.5) * wx) / nx, z: fp.z0 + ((row + 0.5) * wz) / nz, hx: wx / (2 * nx), hz: wz / (2 * nz), k, cap })\n }\n continue\n }\n const B = Math.min(wx, wz)\n const g = footingSoil(profile, depth, B, soilCfg.byId, soilCfg.influence)\n const ks = subgradeModulus(g.elasticMPa, g.poisson, B, soilCfg.rigidity)\n const size = Math.max(wx, wz) / Math.max(1, soilCfg.cells)\n const nx = Math.max(1, Math.round(wx / size)), nz = Math.max(1, Math.round(wz / size))\n const area = (wx * wz) / (nx * nz)\n for (let i = 0; i < nx; i++) {\n for (let k = 0; k < nz; k++) {\n springs.push({ key: `${fp.part.spec.id}#${i}.${k}`, x: fp.x0 + ((i + 0.5) * wx) / nx, z: fp.z0 + ((k + 0.5) * wz) / nz, hx: wx / (2 * nx), hz: wz / (2 * nz), k: ks * area, cap: soilCfg.safety * g.allowableKPa * 1000 * area })\n }\n }\n }\n return { springs, baseY: prints.length ? Math.min(...prints.map((fp) => fp.bottom)) : 0 }\n }\n\n /** Weight (N) and centre of mass of what stands on the ground: every part left that is not the terrain and has not fallen. */\n const soilWeight = (o: ObjRT): { w: number; c: Vec3 } => {\n let m = 0\n const c: Vec3 = [0, 0, 0]\n for (const p of o.parts) {\n if (isLost(p) || isTerrain(p) || o.collapsed.has(p.spec.id) || o.unsup[o.idx.get(p.spec.id)!]) continue\n m += p.st.mass\n for (let k = 0; k < 3; k++) c[k] += p.st.mass * p.pos[k]\n }\n return { w: m * GRAVITY, c: m > 0 ? [c[0] / m, c[1] / m, c[2] / m] : c }\n }\n\n const initSoil = (o: ObjRT, profile: SoilProfile, carried?: SoilState, carrySets?: Record<string, number>) => {\n const so: SoilRT = { profile, s: 0, a: 0, b: 0, imp: [0, 0], pivot: [0, 0, 0], dirty: true, sets: new Map(), emitted: { t: -Infinity, s: 0, tilt: 0, status: 'stable' } }\n const { springs, baseY } = soilSprings(o, profile)\n if (!springs.length) return\n const [x0, z0] = stiffnessCentre(springs)\n so.pivot = [x0, baseY, z0]\n // the out-of-plumb is taken the unfavourable way: about the axis the foundations are weakest in, toward the side the weight already leans to\n let ix = 0, iz = 0\n for (const sp of springs) {\n ix += sp.k * (sp.x - x0) ** 2\n iz += sp.k * (sp.z - z0) ** 2\n }\n const { c } = soilWeight(o)\n const along = ix <= iz ? 0 : 1\n const off = along === 0 ? c[0] - x0 : c[2] - z0\n const sign = Math.abs(off) > 1e-6 ? Math.sign(off) : 1\n so.imp = along === 0 ? [sign * soilCfg.imperfection, 0] : [0, sign * soilCfg.imperfection]\n if (carried) {\n const t = Math.tan((carried.tilt * Math.PI) / 180)\n so.s = carried.settlement\n so.a = t * carried.direction[0]\n so.b = t * carried.direction[2]\n so.emitted = { t: -Infinity, s: carried.settlement, tilt: carried.tilt, status: carried.status }\n o.st.soil = clone(carried)\n for (const [k, v] of Object.entries(carrySets ?? {})) so.sets.set(k, v)\n if (carried.status === 'toppled') for (const p of o.parts) p.anchored = false\n }\n o.soil = so\n applySoilPose(o)\n }\n\n /** The settled pose: tilted about the pivot by the slopes of the base, then down by the settlement; `st.position`/`rotation` follow. */\n const applySoilPose = (o: ObjRT) => {\n const so = o.soil\n if (!so) {\n o.st.position = [o.base.pos[0], o.base.pos[1], o.base.pos[2]]\n o.st.rotation = [o.base.rot[0], o.base.rot[1], o.base.rot[2], o.base.rot[3]]\n return\n }\n const angle = slopeTilt(so.a, so.b)\n // the side that goes down `a` per metre of x turns +x toward -y: a rotation about (b, 0, -a)\n const R = angle > 1e-12 ? quat.fromAxisAngle(vec.normalize([so.b, 0, -so.a]), angle) : quat.identity()\n const t = vec.sub(vec.sub(so.pivot, rotateVec(R, so.pivot)), [0, so.s, 0])\n o.st.rotation = quat.normalize(quat.mul(o.base.rot, R))\n o.st.position = vec.add(o.base.pos, rotateVec(o.base.rot, t))\n const lean = Math.hypot(so.a, so.b)\n const st: SoilState = o.st.soil ?? { settlement: 0, tilt: 0, direction: [0, 0, 0], bearing: 0, edge: 0, status: 'stable', offset: { position: [0, 0, 0], rotation: [0, 0, 0, 1] } }\n st.settlement = so.s\n st.tilt = (angle * 180) / Math.PI\n st.direction = lean > 1e-12 ? [so.a / lean, 0, so.b / lean] : [0, 0, 0]\n st.offset = { position: t, rotation: R }\n o.st.soil = st\n }\n\n /** The object tipped over: nothing holds it to the ground any more, everything falls. */\n const topple = (o: ObjRT, src?: string) => {\n for (const p of o.parts) p.anchored = false\n solveStructure(o)\n recomputeGroups(o)\n if (!pendingCollapse.has(o)) pendingCollapse.set(o, src)\n }\n\n /**\n * Solve the ground under the object and move it toward the equilibrium. `dt` 0 (the object is placed): it takes the equilibrium at once, as a\n * building that has stood there. In `update` an elastic change is taken at once and a yielding soil moves the object at `sinkRate`/`tiltRate`;\n * with no stable equilibrium it keeps sinking and leaning until its centre of mass passes the edge of its foundations and it tips over.\n */\n const settleSoil = (o: ObjRT, dt: number) => {\n const so = o.soil!\n const st = o.st.soil\n if (st?.status === 'toppled') return\n const { springs } = soilSprings(o, so.profile)\n for (const sp of springs) sp.set = so.sets.get(sp.key) ?? 0\n const { w, c } = soilWeight(o)\n if (!springs.length || w <= 0) {\n if (springs.length === 0 && w > 0) {\n so.s += soilCfg.sinkRate * dt\n applySoilPose(o)\n o.st.soil!.status = 'yielding'\n }\n return\n }\n const height = Math.max(0, c[1] - so.pivot[1])\n // the wind overturns the building as if its centre of mass stood `M / W` further downwind\n const wa = o.wind?.analysis\n const push = wa ? windDirection(o, o.wind!.cfg) : [0, 0]\n const shift = wa ? wa.moment / w : 0\n const r = solveFoundation(springs, w, c[0] + shift * push[0], c[2] + shift * push[1], height, so.imp, { s: so.s, a: so.a, b: so.b })\n let status: SoilState['status'] = 'stable'\n const sinkStep = soilCfg.sinkRate * dt\n const tiltStep = Math.tan((soilCfg.tiltRate * Math.PI) / 180) * dt\n if (r.stable && (!r.yielded || dt === 0)) {\n so.s = r.s\n so.a = r.a\n so.b = r.b\n } else if (r.stable) {\n const ds = r.s - so.s, da = r.a - so.a, db = r.b - so.b\n const fs = Math.abs(ds) > sinkStep ? sinkStep / Math.abs(ds) : 1\n const lean = Math.hypot(da, db)\n const ft = lean > tiltStep ? tiltStep / lean : 1\n so.s += ds * fs\n so.a += da * ft\n so.b += db * ft\n if (fs < 1 || ft < 1) status = 'yielding'\n } else {\n status = 'yielding'\n if (dt === 0) {\n // placed where the ground cannot hold it: it starts from the elastic settlement and moves from there in `update`\n so.s = w / springs.reduce((sum, sp) => sum + sp.k, 0)\n } else {\n so.s += sinkStep * (r.bearing >= 1 ? 1 : 0.25)\n const lean = Math.hypot(so.a, so.b)\n const ux = lean > 1e-9 ? so.a / lean : Math.sign(so.imp[0]), uz = lean > 1e-9 ? so.b / lean : Math.sign(so.imp[1])\n so.a += ux * tiltStep\n so.b += uz * tiltStep\n }\n }\n if (so.s !== 0 || so.a !== 0 || so.b !== 0) {\n const sets = yieldSprings(springs, so.s, so.a, so.b)\n springs.forEach((sp, i) => {\n if (sets[i] > 0) so.sets.set(sp.key, sets[i])\n })\n }\n applySoilPose(o)\n const out = o.st.soil!\n out.bearing = r.bearing\n out.edge = r.edge\n out.status = status\n // tipped over: the centre of mass, moved over by the lean, passed the edge of the foundations in the direction it leans\n const lean = Math.hypot(so.a, so.b)\n if (lean > 1e-9) {\n const [x0, z0] = [so.pivot[0], so.pivot[2]]\n const ux = so.a / lean, uz = so.b / lean\n const e = (c[0] - x0 + height * (so.a + so.imp[0])) * ux + (c[2] - z0 + height * (so.b + so.imp[1])) * uz\n let edge = 0\n for (const sp of springs) edge = Math.max(edge, (sp.x - x0) * ux + (sp.z - z0) * uz + sp.hx * Math.abs(ux) + sp.hz * Math.abs(uz))\n if (e > edge || slopeTilt(so.a, so.b) > Math.PI / 3) out.status = 'toppled'\n }\n }\n\n const stepSoil = (o: ObjRT, dt: number) => {\n const so = o.soil!\n if (o.st.soil?.status === 'toppled') return\n if (!so.dirty && o.st.soil?.status !== 'yielding') return\n so.dirty = false\n settleSoil(o, dt)\n const st = o.st.soil!\n const e = so.emitted\n const changed = st.status !== e.status || ((time - e.t >= 0.5 || e.t === -Infinity) && (Math.abs(st.tilt - e.tilt) > 0.01 || Math.abs(st.settlement - e.s) > 0.002))\n if (changed) {\n so.emitted = { t: time, s: st.settlement, tilt: st.tilt, status: st.status }\n emit({ ...base(o), type: 'settle', settlement: st.settlement, tilt: st.tilt, direction: rotateVec(o.base.rot, st.direction), bearing: st.bearing, status: st.status })\n }\n if (st.status === 'toppled') topple(o)\n }\n\n /**\n * Ask for a collapse report. It is not computed right away: a blow can break several parts in one go (a column and the roof's supports, or a\n * column whose joint opens just before the column itself fractures), so the groups are examined once, after every loss of the operation.\n */\n const collapseCheck = (o: ObjRT, src?: string) => {\n if (!o.hasStructure || !o.parts.some((p) => p.anchored)) return\n if (!pendingCollapse.has(o)) pendingCollapse.set(o, src)\n }\n\n /** Report the groups of remaining structural parts that lost every anchor (each part is reported once). */\n const flushCollapse = () => {\n for (const [o, src] of [...pendingCollapse]) {\n pendingCollapse.delete(o)\n if (!objects.has(o.id) || objects.get(o.id) !== o) continue\n for (const g of o.st.groups) {\n const ps = g.map((id) => o.byId.get(id)!).filter((p) => !isLost(p) && !o.collapsed.has(p.spec.id))\n if (ps.length === 0 || g.some((id) => o.byId.get(id)!.anchored) || !ps.some((p) => p.structural)) continue\n for (const p of ps) {\n o.collapsed.add(p.spec.id)\n p.st.status = 'collapsed'\n setStage(o, p, 3, {}, src)\n }\n emit({ ...base(o, src), type: 'collapse', parts: ps.map((p) => p.spec.id), mass: ps.reduce((sum, p) => sum + p.st.mass, 0) })\n }\n }\n }\n\n const getObj = (id: string): ObjRT => {\n const o = objects.get(id)\n if (!o) throw new Error(`unknown object \"${id}\"`)\n return o\n }\n const getPart = (o: ObjRT, id: string): PartRT => {\n const p = o.byId.get(id)\n if (!p) throw new Error(`unknown part \"${id}\" in object \"${o.id}\"`)\n return p\n }\n\n // -------------------------------------------------------------------------------------------------------------------------------------------\n // Geometry in world space\n // -------------------------------------------------------------------------------------------------------------------------------------------\n\n const partXf = (o: ObjRT, p: PartRT): { c: Vec3; q: Quat } => ({ c: toWorld(o.st.position, o.st.rotation, p.pos), q: quat.mul(o.st.rotation, p.q) })\n const objLocal = (o: ObjRT, w: Vec3) => toLocal(o.st.position, o.st.rotation, w)\n const objLocalDir = (o: ObjRT, w: Vec3) => rotateVec(quat.conjugate(o.st.rotation), w)\n const jointWorld = (o: ObjRT, j: JointRT) => toWorld(o.st.position, o.st.rotation, j.pos)\n const distToPart = (o: ObjRT, p: PartRT, w: Vec3) => {\n const { c, q } = partXf(o, p)\n return distanceToShape(p.spec.shape, toLocal(c, q, w))\n }\n const partWorldAabb = (o: ObjRT, p: PartRT) => {\n const { c, q } = partXf(o, p)\n return aabbOf(p.spec.shape, c, q)\n }\n\n interface PartRay { t0: number; t1: number; n: Vec3 }\n const rayPartRaw = (pos: Vec3, rot: Quat, spec: PartSpec, pq: Quat, origin: Vec3, d: Vec3, lp: Vec3 = spec.position): PartRay | null => {\n const c = toWorld(pos, rot, lp)\n const q = quat.mul(rot, pq)\n const qi = quat.conjugate(q)\n const r = rayShape(spec.shape, rotateVec(qi, vec.sub(origin, c)), rotateVec(qi, d))\n return r ? { t0: r.t0, t1: r.t1, n: rotateVec(q, r.n0) } : null\n }\n const rayPart = (o: ObjRT, p: PartRT, origin: Vec3, d: Vec3): PartRay | null => rayPartRaw(o.st.position, o.st.rotation, p.spec, p.q, origin, d, p.pos)\n\n const raySphereMiss = (origin: Vec3, d: Vec3, c: Vec3, r: number, maxDist: number): boolean => {\n const oc = vec.sub(origin, c)\n const b = vec.dot(oc, d)\n const cc = vec.dot(oc, oc) - r * r\n if (cc > 0 && b > 0) return true\n const disc = b * b - cc\n if (disc < 0) return true\n return -b - Math.sqrt(disc) > maxDist\n }\n\n const raycastInternal = (origin: Vec3, dir: Vec3, maxDist: number, ignore?: Set<string>, worldOnly = false, precise = false): (RayHit & { pathLen: number }) | null => {\n const d = vec.normalize(dir)\n let best: (RayHit & { pathLen: number }) | null = null\n for (const o of objects.values()) {\n if (raySphereMiss(origin, d, toWorld(o.st.position, o.st.rotation, o.bc), o.br, best ? Math.min(maxDist, best.distance) : maxDist)) continue\n for (const p of o.parts) {\n if (isLost(p) || ignore?.has(`${o.id}\\0${p.spec.id}`)) continue\n const r = rayPart(o, p, origin, d)\n if (!r || r.t0 < 0 || r.t0 > maxDist) continue\n if (p.st.opening && insideOpening(o, p, vec.madd(origin, d, r.t0))) continue\n if (p.st.chipped && insideChip(p, objLocal(o, vec.madd(origin, d, r.t0)))) continue\n if (!best || r.t0 < best.distance) best = { object: o.id, part: p.spec.id, point: vec.madd(origin, d, r.t0), normal: r.n, distance: r.t0, pathLen: r.t1 - r.t0 }\n }\n }\n for (const im of worldOnly ? [] : impls.values()) {\n let boxHit: (RayHit & { pathLen: number }) | null = null\n for (const ps of im.impl.describe().parts) {\n if (ignore?.has(`${im.impl.id}\\0${ps.id}`)) continue\n const ov = im.poses.get(ps.id)\n const r = rayPartRaw(im.position, im.rotation, ps, ov?.q ?? quatFromEuler(...(ps.rotation ?? [0, 0, 0])), origin, d, ov?.pos)\n if (!r || r.t1 < 0 || r.t0 > maxDist) continue\n if (r.t0 < 0) {\n // from inside a box (a round in the cabin): only the impl's own surface says what it meets\n if (precise && im.impl.surfaceRay) boxHit = boxHit ?? { object: im.impl.id, part: ps.id, point: origin, normal: r.n, distance: 0, pathLen: r.t1 }\n continue\n }\n if (!boxHit || r.t0 < boxHit.distance) boxHit = { object: im.impl.id, part: ps.id, point: vec.madd(origin, d, r.t0), normal: r.n, distance: r.t0, pathLen: r.t1 - r.t0 }\n }\n if (!boxHit) continue\n if (precise && im.impl.surfaceRay) {\n const far = best ? Math.min(maxDist, best.distance) : maxDist\n const implId = im.impl.id\n const s = im.impl.surfaceRay({ origin, direction: d, maxDistance: far, ...(ignore ? { ignored: (part: string) => ignore.has(`${implId}\\0${part}`) } : {}) })\n if (s && (!best || s.distance < best.distance)) best = { object: implId, part: s.part, point: s.point, normal: s.normal, distance: s.distance, pathLen: s.pathLen }\n } else if (!best || boxHit.distance < best.distance) best = boxHit\n }\n return best\n }\n\n // impl hosting\n const implHit = (im: ImplRT, hit: Hit): HitResult => {\n let h = hit\n if (hit.space === 'local') {\n h = { ...hit, space: 'world', point: toWorld(im.position, im.rotation, hit.point) }\n if (hit.direction) h.direction = rotateVec(im.rotation, hit.direction)\n }\n const start = cur.length\n for (const e of im.impl.hit(h) ?? []) emit(e.time === undefined ? { ...e, time } : e)\n const mine = cur.slice(start)\n const res: HitResult = { object: im.impl.id, damage: 0, penetrated: false, exitEnergy: 0, events: mine, point: hit.point }\n for (const e of mine) {\n if (e.type === 'damage') res.damage += e.amount\n if (e.type === 'hole' && e.hole.through) res.penetrated = true\n if (res.part === undefined && 'part' in e) res.part = (e as { part: string }).part\n }\n return res\n }\n\n const implJointPos = (im: ImplRT, a: string, b: string): Vec3 | null => {\n const parts = im.impl.describe().parts\n const pa = parts.find((p) => p.id === a), pb = parts.find((p) => p.id === b)\n if (!pa || !pb) return null\n const A = aabbOf(pa.shape, pa.position, quatFromEuler(...(pa.rotation ?? [0, 0, 0])))\n const B = aabbOf(pb.shape, pb.position, quatFromEuler(...(pb.rotation ?? [0, 0, 0])))\n const pos: Vec3 = [0, 0, 0]\n for (let k = 0; k < 3; k++) pos[k] = (Math.max(A.min[k], B.min[k]) + Math.min(A.max[k], B.max[k])) / 2\n return toWorld(im.position, im.rotation, pos)\n }\n\n /** Find the part a hit lands on: a short ray along `dir`, else the nearest part within `tol`. */\n const locate = (o: ObjRT, point: Vec3, dir: Vec3 | undefined, tol: number, only?: PartRT): Loc | null => {\n const cands = only ? [only] : o.parts\n if (dir && vec.length(dir) > 1e-9) {\n const d = vec.normalize(dir)\n const origin = vec.madd(point, d, -0.05)\n let best: Loc | null = null\n let bestT = Infinity\n let inside: Loc | null = null\n for (const p of cands) {\n if (isLost(p)) continue\n const r = rayPart(o, p, origin, d)\n if (!r) continue\n if (r.t0 >= 0 && r.t0 <= 0.15) {\n if (r.t0 < bestT) {\n bestT = r.t0\n best = { p, point: vec.madd(origin, d, r.t0), normal: r.n, dir: d, pathLen: Math.max(r.t1 - r.t0, 1e-4) }\n }\n } else if (r.t0 < 0 && r.t1 > 0 && !inside) {\n inside = { p, point, normal: vec.scale(d, -1), dir: d, pathLen: Math.max(r.t1 - 0.05, p.thickness) }\n }\n }\n if (best) return best\n if (inside) return inside\n }\n let np: PartRT | null = null\n let nd = Infinity\n for (const p of cands) {\n if (isLost(p)) continue\n const dd = distToPart(o, p, point)\n if (dd < nd) {\n nd = dd\n np = p\n }\n }\n if (!np || nd > tol) return null\n const { c, q } = partXf(o, np)\n const sp = surfacePoint(np.spec.shape, toLocal(c, q, point))\n const normal = rotateVec(q, sp.normal)\n return { p: np, point: toWorld(c, q, sp.point), normal, dir: dir && vec.length(dir) > 1e-9 ? vec.normalize(dir) : vec.scale(normal, -1), pathLen: np.thickness }\n }\n\n // -------------------------------------------------------------------------------------------------------------------------------------------\n // Marks on parts\n // -------------------------------------------------------------------------------------------------------------------------------------------\n\n const markDamaged = (p: PartRT) => {\n if (p.st.status === 'intact') p.st.status = 'damaged'\n }\n\n const addDent = (o: ObjRT, p: PartRT, wp: Vec3, wn: Vec3, radius: number, depth: number, src?: string) => {\n const dent: Dent = { point: objLocal(o, wp), normal: objLocalDir(o, wn), radius, depth }\n const arr = p.st.dents\n let ni = -1, nd = Infinity\n for (let i = 0; i < arr.length; i++) {\n const dd = vec.distance(arr[i].point, dent.point)\n if (dd < nd) {\n nd = dd\n ni = i\n }\n }\n if (ni >= 0 && (arr.length >= maxDents || nd < arr[ni].radius * 0.6)) {\n arr[ni].depth = Math.min(0.1, Math.max(arr[ni].depth, depth) + depth * 0.3)\n arr[ni].radius = Math.max(arr[ni].radius, radius)\n } else arr.push(dent)\n markDamaged(p)\n emit({ ...base(o, src), type: 'dent', part: p.spec.id, dent, worldPoint: wp })\n }\n\n const addHole = (o: ObjRT, p: PartRT, wp: Vec3, wn: Vec3, diameter: number, through: boolean, exit?: Vec3, src?: string) => {\n const hole: Hole = { point: objLocal(o, wp), normal: objLocalDir(o, wn), diameter, through }\n p.st.holes.push(hole)\n if (p.st.holes.length > maxHoles) p.st.holes.shift()\n markDamaged(p)\n emit({ ...base(o, src), type: 'hole', part: p.spec.id, hole, worldPoint: wp, ...(exit ? { exitPoint: exit } : {}), ...(p.spec.powder ? { powder: { ...p.spec.powder } } : {}) })\n setStage(o, p, 1, {}, src)\n return hole\n }\n\n const addCrack = (o: ObjRT, p: PartRT, wp: Vec3, wn: Vec3, length: number, src?: string) => {\n const crack: Crack = { point: objLocal(o, wp), normal: objLocalDir(o, wn), length: Math.min(length, Math.max(p.bound, 0.05)), rays: 5 + Math.floor(rnd() * 5) }\n p.st.cracks.push(crack)\n if (p.st.cracks.length > 16) p.st.cracks.shift()\n markDamaged(p)\n emit({ ...base(o, src), type: 'crack', part: p.spec.id, crack, worldPoint: wp })\n setStage(o, p, 1, {}, src)\n }\n\n const debris = (o: ObjRT, p: PartRT, kind: DebrisKind, point: Vec3, normal: Vec3, count: number, speed: number, src?: string, material?: MaterialId) =>\n emit({ ...base(o, src), type: 'debris', part: p.spec.id, kind, point, normal, count, speed, ...(material && material !== p.spec.material ? { material } : {}) })\n\n const holeRate = (hole: Hole, pressurized: boolean) => (pressurized ? 0.5 : 0.1) * (hole.diameter / 0.009)\n\n // -------------------------------------------------------------------------------------------------------------------------------------------\n // Failure, joints\n // -------------------------------------------------------------------------------------------------------------------------------------------\n\n const detachEvents = (o: ObjRT, opened: JointRT[], by: 'break' | 'tool' | 'part_lost', src?: string) => {\n for (const j of opened) emit({ ...base(o, src), type: 'detach', joint: j.spec.id, parts: [j.spec.a, j.spec.b], by, groups: o.st.groups.map((g) => [...g]) })\n }\n\n /** Gravity is all that holds a `resting` joint: tipped past `RESTING_HOLD_COS` (the object's up axis leaning away from the world's), what lay on a part falls off. */\n const slideOffResting = (o: ObjRT, rotation: Quat) => {\n const upY = 1 - 2 * (rotation[0] * rotation[0] + rotation[2] * rotation[2])\n if (upY >= RESTING_HOLD_COS) return\n const opened = o.joints.filter((j) => j.spec.kind === 'resting' && !j.st.open)\n if (opened.length === 0) return\n run(() => {\n for (const j of opened) {\n j.st.open = true\n j.st.openedBy = 'break'\n }\n solveStructure(o)\n recomputeGroups(o)\n detachEvents(o, opened, 'break')\n collapseCheck(o)\n })\n }\n\n const checkDestroyed = (o: ObjRT, src?: string) => {\n if (!o.st.destroyed && o.parts.length > 0 && o.parts.every(isLost)) {\n o.st.destroyed = true\n emit({ ...base(o, src), type: 'destroyed' })\n }\n }\n\n const partLost = (o: ObjRT, p: PartRT, src?: string) => {\n const opened: JointRT[] = []\n for (const j of o.byPart.get(p.spec.id) ?? []) {\n if (j.st.open) continue\n j.st.open = true\n j.st.openedBy = 'part_lost'\n opened.push(j)\n }\n solveStructure(o)\n recomputeGroups(o)\n detachEvents(o, opened, 'part_lost', src)\n collapseCheck(o, src)\n checkDestroyed(o, src)\n }\n\n /**\n * Distance from a world point to the joint's contact region: the overlap box of the two parts' bounds (or, when they only nearly touch, the box\n * of the gap between them). Measuring to the joint centre would make a thick part untouchable: a blow on a trunk's surface is half the trunk's\n * width away from a joint that sits on its axis.\n */\n const jointReach = (o: ObjRT, j: JointRT, point: Vec3): number => {\n const A = partWorldAabb(o, o.parts[j.ia]), B = partWorldAabb(o, o.parts[j.ib])\n let d2 = 0\n for (let k = 0; k < 3; k++) {\n const lo = Math.min(Math.max(A.min[k], B.min[k]), Math.min(A.max[k], B.max[k]))\n const hi = Math.max(Math.max(A.min[k], B.min[k]), Math.min(A.max[k], B.max[k]))\n const d = point[k] < lo ? lo - point[k] : point[k] > hi ? point[k] - hi : 0\n d2 += d * d\n }\n return Math.sqrt(d2)\n }\n /** How far from the contact region a blow still counts: half the smallest dimension of the smaller part, at least 6 cm. */\n const jointReachLimit = (o: ObjRT, j: JointRT): number => {\n const pa = o.parts[j.ia], pb = o.parts[j.ib]\n const small = pa.dims[0] * pa.dims[1] * pa.dims[2] <= pb.dims[0] * pb.dims[1] * pb.dims[2] ? pa : pb\n return Math.max(0.06, 0.5 * Math.min(small.dims[0], small.dims[1], small.dims[2]))\n }\n\n /** Length of the joint's contact region: the longest side of the overlap box of the two parts' bounds (a wall's bed runs the whole wall). */\n const jointLength = (o: ObjRT, j: JointRT): number => {\n const A = partWorldAabb(o, o.parts[j.ia]), B = partWorldAabb(o, o.parts[j.ib])\n let len = 0\n for (let k = 0; k < 3; k++) len = Math.max(len, Math.min(A.max[k], B.max[k]) - Math.max(A.min[k], B.min[k]))\n return len\n }\n\n /**\n * Wears the joints of `p` by `amount`. `span` (metres) is how much of a joint's length the blow reaches: a joint longer than that takes only its share\n * (a bullet loosens the mortar bed under it, not the whole bed of a ten-metre wall), so a row of shots does not bring a wall down. A blow breaks at\n * most that stretch: however hard, it takes no more than its share of the joint's strength, so the bed of a wall gives way once blows broke it all along.\n */\n const wearJoints = (o: ObjRT, p: PartRT, amount: number, near?: Vec3, radius = 0.06, src?: string, split = false, span?: number) => {\n if (amount <= 0) return\n const mine = (o.byPart.get(p.spec.id) ?? []).filter((j) => !j.st.open)\n if (split && mine.length) amount /= mine.length\n for (const j of mine) {\n if (j.st.open) continue\n // the rebar of a reinforced part (a cage, or the tension steel of `structure.rebar`) ties it to the next one: blows do not wear it, only a torch\n // or a saw cuts it (or the part itself giving way)\n if (j.spec.kind === 'rebar' && (isReinforced(o.parts[j.ia].spec) || isReinforced(o.parts[j.ib].spec))) continue\n if (near && jointReach(o, j, near) > Math.max(radius, jointReachLimit(o, j))) continue\n j.st.hp -= span === undefined ? amount : Math.min(amount, j.st.maxHp) * Math.min(1, span / Math.max(jointLength(o, j), 1e-6))\n if (j.st.hp <= 0) {\n j.st.hp = 0\n j.st.open = true\n j.st.openedBy = 'break'\n solveStructure(o)\n recomputeGroups(o)\n detachEvents(o, [j], 'break', src)\n collapseCheck(o, src)\n }\n }\n }\n\n // -------------------------------------------------------------------------------------------------------------------------------------------\n // Damage stages: spall, breach, reinforcement cage\n // -------------------------------------------------------------------------------------------------------------------------------------------\n\n const setStage = (o: ObjRT, p: PartRT, stage: DamageStage, extra: { opening?: { center: Vec3; radius: number }; fragments?: Fragment[] } = {}, src?: string) => {\n if (!p.staged || (p.st.stage ?? 0) >= stage) return\n p.st.stage = stage\n emit({ ...base(o, src), type: 'stage', part: p.spec.id, stage, ...extra })\n }\n\n /** `1` when the outward normal points along the part's local +thin axis, else `-1`. */\n const faceOf = (o: ObjRT, p: PartRT, worldNormal: Vec3): number => (rotateVec(quat.conjugate(partXf(o, p).q), worldNormal)[p.thin] >= 0 ? 1 : -1)\n\n const spallOuter = (o: ObjRT, p: PartRT, wp: Vec3, face: number, normal: Vec3, radius: number, src?: string) => {\n if (p.layers.length === 0) return\n const lp = objLocal(o, wp)\n const layer = outerLayer(p.layers, p.rt.spalls, face, lp)\n if (!layer) return\n const spalls = (p.rt.spalls ??= [])\n spalls.push([layer.index, face, lp[0], lp[1], lp[2], radius])\n if (spalls.length > MAX_SPALLS) spalls.shift()\n markDamaged(p)\n emit({ ...base(o, src), type: 'spall', part: p.spec.id, layer: layer.index, point: wp, area: Math.PI * radius * radius })\n debris(o, p, layer.mat.hitDebris, wp, normal, 5, 2, src, layer.mat.id)\n setStage(o, p, 1, {}, src)\n }\n\n /** A crater in the bare surface of a part (concrete): the surface around the hit flakes off with its dust, drawn as a spall of the core (`layer` -1). */\n const crater = (o: ObjRT, p: PartRT, wp: Vec3, normal: Vec3, radius: number, src?: string) => {\n markDamaged(p)\n emit({ ...base(o, src), type: 'spall', part: p.spec.id, layer: -1, point: wp, area: Math.PI * radius * radius })\n debris(o, p, p.mat.breakDebris, wp, normal, 6, 1.5, src)\n setStage(o, p, 1, {}, src)\n }\n\n const insideOpening = (o: ObjRT, p: PartRT, objectPoint: Vec3): boolean => {\n const op = p.st.opening\n if (!op) return false\n const [u, v] = planeAxes(p.thin)\n const lp = toLocal(p.pos, p.q, objectPoint)\n const lc = toLocal(p.pos, p.q, op.center)\n return Math.hypot(lp[u] - lc[u], lp[v] - lc[v]) <= op.radius\n }\n\n /** Square metres of wall a blow removes: the volume its damage takes out, over the thickness it crosses. */\n const breachAreaOf = (p: PartRT, damage: number, blast: boolean): number =>\n (damage / (p.mat.hpPerKg * p.mat.density) / Math.max(p.thickness, 0.005)) * (blast ? breachBlastFactor : 1)\n\n const localHolesOf = (p: PartRT): LocalHole[] =>\n p.st.holes.map((h) => ({ point: toLocal(p.pos, p.q, h.point), normal: rotateVec(quat.conjugate(p.q), h.normal), diameter: h.diameter }))\n\n const unitsOf = (p: PartRT) => p.spec.units ?? { size: [p.mat.fragmentSize?.[1] ?? 0.2, p.mat.fragmentSize?.[1] ?? 0.2, p.thickness] as Vec3, bond: 'stack' as const }\n\n const FRAGMENT_SHAPE = { shatter: 'shard', splinter: 'splinter', tear: 'scrap' } as const\n\n /**\n * Unit-sized fragments of `cells` (part-local), thrown from `hitW`; the holes that fell on a unit stay on it as `marks`. `inner`: drawn in the colour of\n * the inside of the material (a brick knocked out of its plaster), not the part's paint.\n */\n const cellFragments = (o: ObjRT, p: PartRT, cells: readonly UnitCell[], hitW: Vec3, dir: Vec3 | null, speed: number, mass: number, tag: string, inner = false): Fragment[] => {\n const { c, q } = partXf(o, p)\n const holes = p.st.holes.length > 0 ? localHolesOf(p) : []\n const [u, v] = planeAxes(p.thin)\n const faceArea = (cell: UnitCell) => cell.size[u] * cell.size[v]\n const total = cells.reduce((sum, cell) => sum + faceArea(cell), 0) || 1\n const shape = p.spec.units ? 'chunk' : FRAGMENT_SHAPE[p.mat.fracture as keyof typeof FRAGMENT_SHAPE] ?? 'chunk'\n return cells.map((cell, i) => {\n const cw = toWorld(c, q, cell.center)\n const out = vec.normalize(vec.sub(cw, hitW), [0, 1, 0])\n const dv = dir ? vec.normalize(vec.madd(out, dir, 0.6)) : out\n const k = speed * (0.6 + 0.8 * rnd())\n const marks = marksInBox(cell.center, cell.size, undefined, holes)\n return {\n id: `${p.spec.id}#${tag}${i}`, part: p.spec.id, material: p.spec.material, shape, center: cw, size: [cell.size[0], cell.size[1], cell.size[2]], rotation: q,\n velocity: [dv[0] * k, dv[1] * k + 0.5 * rnd(), dv[2] * k], angularVelocity: [(rnd() - 0.5) * 8, (rnd() - 0.5) * 8, (rnd() - 0.5) * 8],\n mass: (mass * faceArea(cell)) / total, ...(marks.length > 0 ? { marks } : {}), ...(inner ? { inner } : {}),\n }\n })\n }\n\n const worldBars = (o: ObjRT, p: PartRT, bars: ReadonlyArray<readonly [Vec3, Vec3]>): Array<[Vec3, Vec3]> => {\n const { c, q } = partXf(o, p)\n return bars.map(([a, b]) => [toWorld(c, q, a), toWorld(c, q, b)])\n }\n\n /** A blow that made through damage of `area` m² at `wp` (world): adds up with the earlier ones within the breach radius, and opens the part past its threshold. */\n const addBreach = (o: ObjRT, p: PartRT, wp: Vec3, area: number, energy: number, dir: Vec3 | null, src?: string) => {\n if (!p.staged || area <= 0 || (p.st.stage ?? 0) >= 2 || p.st.stripped || isLost(p)) return\n const lp = objLocal(o, wp)\n const list = (p.rt.breach ??= [])\n list.push([lp[0], lp[1], lp[2], area])\n if (list.length > MAX_SPALLS) list.shift()\n let total = 0\n const sum: Vec3 = [0, 0, 0]\n for (const [x, y, z, a] of list) {\n if (vec.distance([x, y, z], lp) > breachRadius) continue\n total += a\n sum[0] += x * a\n sum[1] += y * a\n sum[2] += z * a\n }\n if (total < (p.spec.breach?.area ?? BREACH_AREA)) return\n openBreach(o, p, [sum[0] / total, sum[1] / total, sum[2] / total], total, energy, dir, src)\n }\n\n /** The unit grid of a part with `units`, at the cap a breach uses (the same cells every time, so a unit keeps its index). Not saved: it is rebuilt from the spec. */\n const unitGrids = new WeakMap<PartRT, UnitCell[]>()\n const gridOf = (p: PartRT): UnitCell[] => {\n let grid = unitGrids.get(p)\n if (!grid) unitGrids.set(p, (grid = unitGrid(p.dims, p.thin, unitsOf(p), BREACH_GRID_CAP)))\n return grid\n }\n\n /** The object-local point falls in a unit that was knocked out of the part (`PartState.chipped`). */\n const insideChip = (p: PartRT, objectPoint: Vec3): boolean => {\n const cells = p.st.chipped\n if (!cells?.length) return false\n const [u, v] = planeAxes(p.thin)\n const lp = toLocal(p.pos, p.q, objectPoint)\n return cells.some((c) => Math.abs(lp[u] - c.center[u]) <= c.size[u] / 2 && Math.abs(lp[v] - c.center[v]) <= c.size[v] / 2)\n }\n\n /**\n * A shot or a blow on a wall of units (`PartSpec.units`) wears the unit it lands on, and a little the ones around it within `radius`, until it gives\n * way at `chipEnergy` joules per kilogram of its mass. A blow knocks the whole unit out; a shot breaks it where it lands: a crater a few centimetres across\n * (`craterAcross`) goes through the unit, the rest of it stays in the wall, and its bits fly out of both faces (most out of the far one, along the shot). A unit whose\n * craters took most of its face (`CRATER_SPENT`) lets its rest go. Each gives a `chip` event with the piece that came out and its fragments\n * (`PartState.chipped`), and what goes through it passes. The face area that came out adds up like through damage (`addBreach`), so enough of it\n * close together opens the part. A reinforced part keeps its units (the cage holds them: it crumbles in a breach).\n */\n const chipUnits = (o: ObjRT, p: PartRT, kind: 'ballistic' | 'blunt', wp: Vec3, hitEnergy: number, dir: Vec3 | null, radius: number, src?: string) => {\n if (!p.spec.units || !p.staged || chipEnergy <= 0 || p.st.stripped || isLost(p) || (p.st.stage ?? 0) >= 2) return\n // the material says what a blow of this kind takes out of it: joules per kg of a unit, and the part of each blow that only scars the surface\n const rule = p.mat.hits?.[kind]\n const perKg = rule?.unitJoules ?? chipEnergy\n const energy = hitEnergy - (rule?.floor ?? 0)\n if (perKg <= 0 || energy <= 0) return\n const [u, v] = planeAxes(p.thin)\n const lp = toLocal(p.pos, p.q, objLocal(o, wp))\n const grid = gridOf(p)\n const worn = (p.rt.chips ??= {})\n const cut = (p.rt.craters ??= {})\n const out: UnitCell[] = []\n const wholeBefore = Object.values(worn).filter((w) => w === -1).length\n const shot = kind === 'ballistic'\n for (let i = 0; i < grid.length; i++) {\n const cell = grid[i]!\n if (worn[i] === -1) continue\n const gap = Math.hypot(Math.max(0, Math.abs(lp[u] - cell.center[u]) - cell.size[u] / 2), Math.max(0, Math.abs(lp[v] - cell.center[v]) - cell.size[v] / 2))\n if (gap > radius) continue\n const share = gap === 0 ? 1 : CHIP_SPLASH * (1 - gap / radius)\n const total = (worn[i] ?? 0) + energy * share\n const mass = p.mat.density * cell.size[0] * cell.size[1] * cell.size[2]\n if (total < perKg * mass) {\n worn[i] = total\n continue\n }\n if (!shot) {\n // a blow knocks the unit out\n worn[i] = -1\n out.push(cell)\n continue\n }\n // the shot breaks the unit where it lands (the point nearest to it on the unit): a crater through it, the rest stays\n const size: Vec3 = [cell.size[0], cell.size[1], cell.size[2]]\n const center: Vec3 = [cell.center[0], cell.center[1], cell.center[2]]\n for (const a of [u, v]) {\n const w = Math.min(cell.size[a], craterAcross(hitEnergy) * (0.85 + 0.3 * rnd()))\n const lo = cell.center[a] - cell.size[a] / 2 + w / 2, hi = cell.center[a] + cell.size[a] / 2 - w / 2\n size[a] = w\n center[a] = clamp(lp[a], lo, hi)\n // at a free edge of the part (its ends, its top) nothing holds the corner: the crater tears off the piece out to the edge\n const [from, to] = tornToEdge({ p, cell, a, b: a === u ? v : u, at: lp[a], crater: [center[a] - w / 2, center[a] + w / 2], reach: w * EDGE_REACH, gone: (k) => worn[k] === -1 })\n size[a] = to - from\n center[a] = (from + to) / 2\n }\n const taken = (cut[i] ?? 0) + size[u] * size[v]\n if (taken >= cell.size[u] * cell.size[v] * CRATER_SPENT) {\n // a shot that would leave little of it takes the rest too, broken in pieces\n worn[i] = -1\n out.push({ ...cell, crater: true } as UnitCell)\n continue\n }\n worn[i] = 0\n cut[i] = taken\n out.push({ center, size, crater: true } as UnitCell)\n }\n if (out.length === 0) return\n const { c, q } = partXf(o, p)\n const chipped = (p.st.chipped ??= [])\n const holes = localHolesOf(p)\n for (const cell of out) {\n const mass = Math.min(p.st.mass, p.mat.density * cell.size[0] * cell.size[1] * cell.size[2])\n const center = toWorld(c, q, cell.center)\n const speed = clamp(Math.sqrt((2 * energy * 0.05) / Math.max(mass, 0.05)), 0.5, 6)\n const tag = `c${chipped.length}_`\n const fragments = (cell as { crater?: boolean }).crater ? craterFragments(o, p, cell, dir, speed, mass, tag) : cellFragments(o, p, [cell], wp, dir, speed, mass, tag, true)\n p.st.holes = p.st.holes.filter((_, k) => marksInBox(cell.center, cell.size, undefined, [holes[k]!]).length === 0)\n chipped.push({ center: [cell.center[0], cell.center[1], cell.center[2]], size: [cell.size[0], cell.size[1], cell.size[2]] })\n p.st.mass = Math.max(0, p.st.mass - mass)\n p.rt.removed = (p.rt.removed ?? 0) + mass\n markDamaged(p)\n setStage(o, p, 1, {}, src)\n emit({ ...base(o, src), type: 'chip', part: p.spec.id, center, size: [cell.size[0], cell.size[1], cell.size[2]], rotation: q, fragments })\n debris(o, p, p.mat.breakDebris, center, vec.scale(dir ?? [0, 1, 0], -1), 6, 2, src)\n }\n // what the units that came out held up and nothing else holds comes down\n if (Object.values(worn).filter((w) => w === -1).length > wholeBefore) dropUnsupported(o, p, src)\n if (p.spec.reinforcement) exposeRebar(o, p, src)\n for (const cell of out) addBreach(o, p, toWorld(c, q, cell.center), cell.size[u] * cell.size[v], energy, dir, src)\n if (p.structural && !isLost(p)) {\n solveStructure(o)\n collapseCheck(o, src)\n }\n }\n\n /**\n * The span of a crater along axis `a` of the part (`crater`, inside the unit `cell`), carried out to the side of the unit when that side is free and the\n * hit lands within `reach` of it: nothing holds that corner, so the shot tears the piece off. A side is free at the ends of the wall, at its top (not at\n * its bottom, which stands on what holds it) and where the unit next to it was knocked out, so the edge a torn corner leaves tears off in turn.\n */\n const tornToEdge = (o: TornToEdgeOptions): [number, number] => {\n const { p, cell, a, b, at, crater, reach, gone } = o\n const half = p.dims[a] / 2\n const lo = cell.center[a] - cell.size[a] / 2, hi = cell.center[a] + cell.size[a] / 2\n const free = (side: number, sign: number): boolean => {\n if (sign > 0 ? side >= half - 1e-6 : side <= -half + 1e-6) return sign > 0 || a !== planeAxes(p.thin)[1]\n const probe = side + sign * 1e-3\n return gridOf(p).some((c, k) => gone(k) && Math.abs(probe - c.center[a]) <= c.size[a] / 2 && Math.abs(cell.center[b] - c.center[b]) <= c.size[b] / 2)\n }\n if (at - lo <= reach && free(lo, -1)) return [lo, Math.max(crater[1], lo)]\n if (hi - at <= reach && free(hi, 1)) return [Math.min(crater[0], hi), hi]\n return crater\n }\n\n /** Metres across the crater a round of `energy` joules breaks through a unit: 6 cm for a pistol round, 10 for a rifle round. */\n const craterAcross = (energy: number): number => clamp(0.03 + 0.0012 * Math.sqrt(Math.max(0, energy)), 0.03, 0.14)\n\n /**\n * The bits of a unit a shot broke through (`cell`, part-local: the crater, or the rest of a unit the craters spent): small irregular pieces of the\n * inside of the material, two in three thrown out of the far face along the shot, the rest back out of the face it hit.\n */\n const craterFragments = (o: ObjRT, p: PartRT, cell: UnitCell, dir: Vec3 | null, speed: number, mass: number, tag: string): Fragment[] => {\n const { c, q } = partXf(o, p)\n const [u, v] = planeAxes(p.thin)\n const d = dir ?? rotateVec(q, [p.thin === 0 ? 1 : 0, p.thin === 1 ? 1 : 0, p.thin === 2 ? 1 : 0])\n // which face of the part the shot leaves by, in part axes\n const exitSign = Math.sign(rotateVec(quat.conjugate(q), d)[p.thin]) || 1\n const bit = Math.max(0.01, Math.min(cell.size[u], cell.size[v]) / 3)\n const n = clamp(Math.round((cell.size[u] * cell.size[v]) / (bit * bit * 3)), 4, 10) + Math.floor(rnd() * 3)\n const out: Fragment[] = []\n for (let i = 0; i < n; i++) {\n const back = i % 3 === 2\n const lc: Vec3 = [cell.center[0], cell.center[1], cell.center[2]]\n lc[u] += (rnd() - 0.5) * cell.size[u] * 0.7\n lc[v] += (rnd() - 0.5) * cell.size[v] * 0.7\n lc[p.thin] += (back ? -exitSign : exitSign) * (p.thickness / 2 + 0.01)\n const size: Vec3 = [0, 0, 0]\n size[u] = bit * (0.6 + 0.8 * rnd())\n size[v] = bit * (0.5 + 0.7 * rnd())\n size[p.thin] = bit * (0.4 + 0.6 * rnd())\n const spread: Vec3 = [(rnd() - 0.5) * 0.9, (rnd() - 0.3) * 0.9, (rnd() - 0.5) * 0.9]\n const k = speed * (back ? 0.4 + 0.4 * rnd() : 0.7 + 0.8 * rnd())\n const vdir = vec.normalize(vec.add(back ? vec.scale(d, -1) : d, spread))\n out.push({\n id: `${p.spec.id}#${tag}${i}`, part: p.spec.id, material: p.spec.material, shape: 'chunk', center: toWorld(c, q, lc), size, rotation: q,\n velocity: [vdir[0] * k, vdir[1] * k + 0.5 * rnd(), vdir[2] * k], angularVelocity: [(rnd() - 0.5) * 20, (rnd() - 0.5) * 20, (rnd() - 0.5) * 20],\n mass: mass / n, inner: true,\n })\n }\n return out\n }\n\n /**\n * The bars of a reinforced part that show (all of them once it is stripped, else those inside its opening and its knocked-out units), bowed out of the\n * part's plane by its overload (`stress` past 1) so the cage bends under the load it carries until the part gives way. Emitted as one `expose` with\n * every bar that shows, so a renderer can replace the part's cage with it.\n */\n const exposeRebar = (o: ObjRT, p: PartRT, src?: string) => {\n const r = p.spec.reinforcement\n if (!r) return\n const [u, v] = planeAxes(p.thin)\n const all = rebarBars(p.dims, p.thin, r.spacing)\n let bars: Array<[Vec3, Vec3]>\n if (p.st.stripped) bars = all\n else {\n bars = []\n for (const cell of p.st.chipped ?? []) bars.push(...clipBarsToBox(all, u, v, cell.center, cell.size))\n const op = p.st.opening\n if (op) {\n const lc = toLocal(p.pos, p.q, op.center)\n bars.push(...clipBarsToDisc(all, u, v, [lc[u], lc[v]], op.radius + 0.05))\n }\n }\n const bow = clamp(((p.st.stress ?? 0) - 1) / 0.5, 0, 1)\n if (bow > 0) bars = bars.flatMap((bar, i) => bendBar(bar, p.thin, bow * BAR_BOW, i))\n emit({ ...base(o, src), type: 'expose', part: p.spec.id, bars: worldBars(o, p, bars) })\n }\n\n /**\n * Stage 2: the units around `center` (object-local) come out as fragments the size of one unit, the part keeps an opening and its mass drops. An\n * opening as wide as the part cuts it in two (a column, a lintel): that is a fracture instead.\n */\n const openBreach = (o: ObjRT, p: PartRT, center: Vec3, total: number, energy: number, dir: Vec3 | null, src?: string) => {\n const [u, v] = planeAxes(p.thin)\n const radius = clamp(Math.sqrt(total / Math.PI), Math.sqrt((p.spec.breach?.area ?? BREACH_AREA) / Math.PI), breachRadius)\n const lc = toLocal(p.pos, p.q, center)\n lc[p.thin] = 0\n const { c, q } = partXf(o, p)\n const worldCenter = toWorld(c, q, lc)\n if (2 * radius >= Math.min(p.dims[u], p.dims[v])) {\n failPart(o, p, worldCenter, dir, energy, 12, src)\n return\n }\n const worn = p.rt.chips\n const cells = cellsWithin(gridOf(p).filter((_, i) => worn?.[i] !== -1), p.thin, lc, radius)\n const removed = (p.st.mass * cells.reduce((sum, cell) => sum + cell.size[u] * cell.size[v], 0)) / (p.dims[u] * p.dims[v])\n const speed = clamp(Math.sqrt((2 * energy * 0.1) / Math.max(removed, 0.05)), 0.5, 8)\n const fragments = cellFragments(o, p, cells, worldCenter, dir, speed, removed, 'b')\n const holes = localHolesOf(p)\n p.st.holes = p.st.holes.filter((_, i) => !cells.some((cell) => marksInBox(cell.center, cell.size, undefined, [holes[i]!]).length > 0))\n p.st.mass = Math.max(0, p.st.mass - removed)\n p.rt.removed = (p.rt.removed ?? 0) + removed\n p.st.opening = { center: objLocal(o, worldCenter), radius }\n markDamaged(p)\n setStage(o, p, 1, {}, src)\n setStage(o, p, 2, { opening: { center: worldCenter, radius }, fragments }, src)\n debris(o, p, p.mat.breakDebris, worldCenter, vec.scale(dir ?? [0, 1, 0], -1), 14, 3, src)\n dropUnsupported(o, p, src)\n const reinforcement = p.spec.reinforcement\n if (reinforcement) exposeRebar(o, p, src)\n if (p.structural) solveStructure(o)\n }\n\n /**\n * Metres from a blast of `energy` joules within which it breaks a wall of units through: `BREACH_BLAST_REACH` by the cube root of the kilojoules, for\n * the reference wall, and by the cube root of how much less or more that wall resists (`BLAST_REFERENCE_RESISTANCE`).\n */\n const blastReachOf = (p: PartRT, energy: number): number => {\n const perKg = p.mat.hits?.blunt?.unitJoules ?? chipEnergy\n const resistance = Math.max(1, perKg * p.mat.density * p.thickness)\n return BREACH_BLAST_REACH * Math.cbrt(Math.max(0, energy) / 1000) * clamp(Math.cbrt(BLAST_REFERENCE_RESISTANCE / resistance), 0.3, 2)\n }\n\n /**\n * A blast on a wall of units (`PartSpec.units`): the units where the wall is within its reach (`blastReachOf`) come out, the circle the sphere of\n * that reach cuts on the wall, its edge ragged as masonry breaks along its joints; the units just past it are loosened for the next blow, and the\n * units the hole leaves with nothing under them (`unsupportedCells`: the corner over a hole at the free end of a wall) come down with them. The rest\n * of the wall stands. Everything that came out is one `chip` with `units`, and it adds up in `PartState.chipped`, so later shots and blasts go on\n * cutting the same wall. Returns whether any unit came out.\n */\n const blastUnits = (o: ObjRT, p: PartRT, wp: Vec3, energy: number, dist: number, src?: string): boolean => {\n if (!p.staged || p.st.stripped || isLost(p) || chipEnergy <= 0) return false\n const reach = blastReachOf(p, energy)\n if (dist >= reach) return false\n const radius = Math.sqrt(reach * reach - dist * dist)\n const [u, v] = planeAxes(p.thin)\n const lp = toLocal(p.pos, p.q, objLocal(o, wp))\n const op = p.st.opening ? toLocal(p.pos, p.q, p.st.opening.center) : null\n const grid = gridOf(p)\n const worn = (p.rt.chips ??= {})\n const perKg = p.mat.hits?.blunt?.unitJoules ?? chipEnergy\n const lobes = [rnd() * 2 * Math.PI, rnd() * 2 * Math.PI]\n const out: number[] = []\n for (let i = 0; i < grid.length; i++) {\n const cell = grid[i]!\n if (worn[i] === -1) continue\n if (op && p.st.opening && Math.hypot(cell.center[u] - op[u], cell.center[v] - op[v]) <= p.st.opening.radius) continue\n const du = cell.center[u] - lp[u], dv = cell.center[v] - lp[v]\n const angle = Math.atan2(dv, du)\n const edge = radius * (1 + BLAST_EDGE_RAGGED * (0.5 * Math.sin(3 * angle + lobes[0]!) + 0.3 * Math.sin(5 * angle + lobes[1]!) + 0.4 * (rnd() - 0.5)))\n const d = Math.hypot(du, dv)\n if (d <= edge) {\n worn[i] = -1\n out.push(i)\n } else if (d <= edge * BLAST_EDGE_LOOSE) {\n const mass = p.mat.density * cell.size[0] * cell.size[1] * cell.size[2]\n worn[i] = Math.max(worn[i] ?? 0, perKg * mass * BLAST_EDGE_WEAR)\n }\n }\n if (out.length === 0) return false\n return knockOutUnits(o, p, wp, energy, out, src)\n }\n\n /**\n * A blast on the infill of a confined wall (`PANEL_PI`): the reflected pressure and impulse at the middle of the bay the charge faces (between the two\n * pillars around it, or the ends of the wall) decide whether that panel fails. A failed panel comes out whole into the side away from the charge; the\n * pillars and the bond beam around it are parts of their own and stay. Returns whether the panel came out.\n */\n const blastPanel = (o: ObjRT, p: PartRT, point: Vec3, energy: number, src?: string): boolean => {\n if (!p.staged || p.st.stripped || isLost(p) || !p.spec.units || p.spec.units.mortar === p.spec.material || p.spec.reinforcement) return false\n const [u, v] = planeAxes(p.thin)\n const lp = toLocal(p.pos, p.q, objLocal(o, point))\n const half = p.dims[u] / 2\n // the pillars standing in this wall, as positions along it\n const posts: number[] = []\n for (const m of o.parts) {\n if (m === p || !m.spec.reinforcement || isLost(m) || m.spec.shape.kind !== 'box') continue\n const mp = toLocal(p.pos, p.q, m.pos)\n if (Math.abs(mp[p.thin]) > p.dims[p.thin] + 0.15 || Math.abs(mp[u]) > half + 0.15 || m.dims[v] < p.dims[v] * 0.5) continue\n posts.push(mp[u])\n }\n let from = -half, to = half\n for (const x of posts) {\n if (x <= lp[u] && x > from) from = x\n if (x >= lp[u] && x < to) to = x\n }\n if (to - from < 0.2) return false\n // a panel fails in bending across its span: the wave has to load most of it, not one place (a grenade close to it breaks a hole there instead)\n const tnt = energy * DEFAULT_BLAST_IMPULSE.tntPerJoule\n const centre = objLocal(o, point)\n const span = to - from, height = p.dims[v]\n let loaded = 0\n for (const [fu, fv] of PANEL_POINTS) {\n const at: Vec3 = [0, 0, 0]\n at[u] = (from + to) / 2 + fu * span\n at[v] = fv * height\n at[p.thin] = Math.sign(lp[p.thin]) * p.dims[p.thin] / 2\n const r = vec.distance(toWorld(p.pos, p.q, at), centre)\n const side = sideOnOverpressure(tnt, r)\n // reflected peak pressure of a shock meeting a wall head on (Rankine-Hugoniot, air as an ideal gas)\n const reflected = 2 * side + (6 * side * side) / (side + 7 * 101325)\n const impulse = bodyImpulse(tnt, r)\n if (reflected > PANEL_PRESSURE && impulse > PANEL_IMPULSE && (reflected - PANEL_PRESSURE) * (impulse - PANEL_IMPULSE) >= PANEL_PI) loaded++\n }\n if (loaded < PANEL_POINTS_LOADED) return false\n const grid = gridOf(p)\n const worn = (p.rt.chips ??= {})\n const out: number[] = []\n for (let i = 0; i < grid.length; i++) {\n const cell = grid[i]!\n if (worn[i] === -1) continue\n if (cell.center[u] - cell.size[u] / 2 >= from - 1e-6 && cell.center[u] + cell.size[u] / 2 <= to + 1e-6) out.push(i)\n }\n if (out.length === 0) return false\n for (const i of out) worn[i] = -1\n return knockOutUnits(o, p, point, energy, out, src)\n }\n\n /** Takes the units `out` (indices of the part's grid) out of a wall of units: they fly from `wp` as clumps, what they leave with nothing under it comes down, and one `chip` says so. */\n const knockOutUnits = (o: ObjRT, p: PartRT, wp: Vec3, energy: number, out: readonly number[], src?: string): boolean => {\n const [u, v] = planeAxes(p.thin)\n const op = p.st.opening ? toLocal(p.pos, p.q, p.st.opening.center) : null\n const grid = gridOf(p)\n const worn = (p.rt.chips ??= {})\n for (const i of out) worn[i] = -1\n const loose = unsupportedCells(grid, p.thin, p.dims, (i) => worn[i] !== -1 && !(op && p.st.opening && Math.hypot(grid[i]!.center[u] - op[u], grid[i]!.center[v] - op[v]) <= p.st.opening.radius))\n for (const i of loose) worn[i] = -1\n const blown = out.map((i) => grid[i]!), fallen = loose.map((i) => grid[i]!)\n const volume = (cells: readonly UnitCell[]) => cells.reduce((sum, cell) => sum + cell.size[0] * cell.size[1] * cell.size[2], 0)\n const blownMass = Math.min(p.st.mass, p.mat.density * volume(blown))\n const fallenMass = Math.min(p.st.mass - blownMass, p.mat.density * volume(fallen))\n const speed = clamp(Math.sqrt((2 * energy * 0.02) / Math.max(blownMass, 0.05)), 1, 12)\n // what flies is clumps of units still held by their mortar, at most `maxFragments` of them (and a quarter of that for what comes down), so a blast\n // costs a renderer about as many pieces as a fracture does\n const { c, q } = partXf(o, p)\n const chipped = (p.st.chipped ??= [])\n const tag = `x${chipped.length}_`\n const fragments = [\n ...cellFragments(o, p, clumpCells(blown, p.thin, maxFragments), wp, null, speed, blownMass, tag, true),\n ...(fallen.length > 0 ? cellFragments(o, p, clumpCells(fallen, p.thin, Math.max(2, Math.round(maxFragments / 4))), wp, null, 0.3, fallenMass, `${tag}f`, true) : []),\n ]\n const cells = [...blown, ...fallen]\n const holes = localHolesOf(p)\n p.st.holes = p.st.holes.filter((_, k) => !cells.some((cell) => marksInBox(cell.center, cell.size, undefined, [holes[k]!]).length > 0))\n const lo: Vec3 = [Infinity, Infinity, Infinity], hi: Vec3 = [-Infinity, -Infinity, -Infinity]\n for (const cell of cells) {\n chipped.push({ center: [cell.center[0], cell.center[1], cell.center[2]], size: [cell.size[0], cell.size[1], cell.size[2]] })\n for (let k = 0; k < 3; k++) {\n lo[k] = Math.min(lo[k]!, cell.center[k]! - cell.size[k]! / 2)\n hi[k] = Math.max(hi[k]!, cell.center[k]! + cell.size[k]! / 2)\n }\n }\n p.st.mass = Math.max(0, p.st.mass - blownMass - fallenMass)\n p.rt.removed = (p.rt.removed ?? 0) + blownMass + fallenMass\n markDamaged(p)\n setStage(o, p, 1, {}, src)\n const center = toWorld(c, q, [(lo[0] + hi[0]) / 2, (lo[1] + hi[1]) / 2, (lo[2] + hi[2]) / 2])\n const units = cells.map((cell) => ({ center: toWorld(c, q, cell.center), size: [cell.size[0], cell.size[1], cell.size[2]] as Vec3 }))\n emit({ ...base(o, src), type: 'chip', part: p.spec.id, center, size: [hi[0] - lo[0], hi[1] - lo[1], hi[2] - lo[2]], rotation: q, fragments, units })\n debris(o, p, p.mat.breakDebris, center, vec.normalize(vec.sub(center, wp), [0, 1, 0]), 14, 3, src)\n if (p.spec.reinforcement) exposeRebar(o, p, src)\n if (p.structural && !isLost(p)) {\n solveStructure(o)\n collapseCheck(o, src)\n }\n return true\n }\n\n /**\n * The units of a wall of laid units (brick or block in its mortar) that a removal left with no bearing down to the bottom of the wall (`unsupportedCells`):\n * an island of bricks over the edge of a hole, a unit held by a corner. They come down as debris (one `chip` with `units`, the pieces clumped as they\n * fall), leave the part (`PartState.chipped`, so shots and rays pass where they were) and their marks go with them. Returns how many units fell.\n */\n const dropUnsupported = (o: ObjRT, p: PartRT, src?: string): number => {\n if (!p.spec.units || p.spec.units.mortar === p.spec.material || p.st.stripped || isLost(p)) return 0\n const [u, v] = planeAxes(p.thin)\n const grid = gridOf(p)\n const worn = (p.rt.chips ??= {})\n const op = p.st.opening ? toLocal(p.pos, p.q, p.st.opening.center) : null\n const opened = (cell: UnitCell): boolean => !!op && !!p.st.opening && Math.hypot(cell.center[u] - op[u], cell.center[v] - op[v]) <= p.st.opening.radius\n const loose = unsupportedCells(grid, p.thin, p.dims, (i) => worn[i] !== -1 && !opened(grid[i]!))\n if (loose.length === 0) return 0\n for (const i of loose) worn[i] = -1\n const fallen = loose.map((i) => grid[i]!)\n const mass = Math.min(p.st.mass, p.mat.density * fallen.reduce((sum, cell) => sum + cell.size[0] * cell.size[1] * cell.size[2], 0))\n const { c, q } = partXf(o, p)\n const chipped = (p.st.chipped ??= [])\n const lo: Vec3 = [Infinity, Infinity, Infinity], hi: Vec3 = [-Infinity, -Infinity, -Infinity]\n for (const cell of fallen) {\n for (let k = 0; k < 3; k++) {\n lo[k] = Math.min(lo[k]!, cell.center[k]! - cell.size[k]! / 2)\n hi[k] = Math.max(hi[k]!, cell.center[k]! + cell.size[k]! / 2)\n }\n }\n const center = toWorld(c, q, [(lo[0] + hi[0]) / 2, (lo[1] + hi[1]) / 2, (lo[2] + hi[2]) / 2])\n const fragments = cellFragments(o, p, clumpCells(fallen, p.thin, Math.max(2, Math.round(maxFragments / 4))), vec.add(center, [0, 1, 0]), null, 0.3, mass, `u${chipped.length}_`, true)\n const holes = localHolesOf(p)\n p.st.holes = p.st.holes.filter((_, k) => !fallen.some((cell) => marksInBox(cell.center, cell.size, undefined, [holes[k]!]).length > 0))\n for (const cell of fallen) chipped.push({ center: [cell.center[0], cell.center[1], cell.center[2]], size: [cell.size[0], cell.size[1], cell.size[2]] })\n p.st.mass = Math.max(0, p.st.mass - mass)\n p.rt.removed = (p.rt.removed ?? 0) + mass\n markDamaged(p)\n const units = fallen.map((cell) => ({ center: toWorld(c, q, cell.center), size: [cell.size[0], cell.size[1], cell.size[2]] as Vec3 }))\n emit({ ...base(o, src), type: 'chip', part: p.spec.id, center, size: [hi[0] - lo[0], hi[1] - lo[1], hi[2] - lo[2]], rotation: q, fragments, units })\n debris(o, p, p.mat.breakDebris, center, [0, -1, 0], 6, 1, src)\n return loose.length\n }\n\n /**\n * A reinforced concrete part with a place shot away gives there, not as a whole: what rests on it no longer bears on it (the bond beam on a pillar cut\n * under its top goes on resting on its wall and the other pillars), and the part stays as it is, the concrete above the cut held by the cage. Returns\n * false when nothing rested on it, for the whole part to break as before.\n */\n const giveAtCut = (o: ObjRT, p: PartRT, src?: string): boolean => {\n if (!p.spec.reinforcement || !p.spec.units || !p.st.chipped?.length || sectionLoss(p) <= 0) return false\n const opened: JointRT[] = []\n for (const j of o.byPart.get(p.spec.id) ?? []) {\n if (j.st.open) continue\n const onIt = (j.bears === 'a_on_b' && j.spec.b === p.spec.id) || (j.bears === 'b_on_a' && j.spec.a === p.spec.id)\n if (!onIt) continue\n j.st.open = true\n j.st.openedBy = 'break'\n opened.push(j)\n }\n if (opened.length === 0) return false\n p.st.hp = Math.max(p.st.hp, p.st.maxHp * GIVE_AT_CUT_HP)\n markDamaged(p)\n solveStructure(o)\n recomputeGroups(o)\n detachEvents(o, opened, 'break', src)\n exposeRebar(o, p, src)\n collapseCheck(o, src)\n return true\n }\n\n /** The concrete of a reinforced part is gone: the part stays as its rebar cage, with the capacity the reinforcement leaves it. */\n const stripPart = (o: ObjRT, p: PartRT, reinforcement: NonNullable<PartSpec['reinforcement']>, src?: string) => {\n const bars = rebarBars(p.dims, p.thin, reinforcement.spacing)\n p.st.stripped = true\n p.st.hp = p.st.maxHp\n p.st.mass = rebarMass(bars, reinforcement.diameter, materials.get(reinforcement.material)?.density)\n p.st.holes = []\n p.st.burning = false\n p.rt.jet = false\n markDamaged(p)\n solveStructure(o)\n exposeRebar(o, p, src)\n collapseCheck(o, src)\n }\n\n /** The units of the part that are still there (the opening of a breach is already gone), as a fragment plan. */\n const unitFragmentPlan = (p: PartRT, cap: number): PlannedFragment[] => {\n const grid = unitGrid(p.dims, p.thin, unitsOf(p), cap)\n const op = p.st.opening\n const cells = op ? cellsOutside(grid, p.thin, toLocal(p.pos, p.q, op.center), op.radius) : grid\n const [u, v] = planeAxes(p.thin)\n return cells.map((cell) => ({ center: cell.center, size: cell.size, q: quat.identity(), shape: 'chunk' as const, weight: cell.size[u] * cell.size[v] }))\n }\n\n /** The bare cage gives way (overload, a blast, a cut that finishes): the part is lost for good. */\n const loseCage = (o: ObjRT, p: PartRT, src?: string) => {\n p.st.status = 'broken'\n p.st.hp = 0\n p.st.mass = 0\n emit({ ...base(o, src), type: 'expose', part: p.spec.id, bars: [] })\n debris(o, p, 'sparks', partXf(o, p).c, [0, 1, 0], 6, 3, src)\n partLost(o, p, src)\n }\n\n /**\n * A reinforced beam or slab that fails in bending folds at the hinge and comes down in one piece, held together by its bars: the joints it rests on\n * open, it keeps what rests on it, and it falls (a `collapse` follows) instead of turning to rubble.\n */\n const hingeDrop = (o: ObjRT, p: PartRT, src?: string) => {\n const i = o.idx.get(p.spec.id)!\n const opened: JointRT[] = []\n for (const j of o.byPart.get(p.spec.id) ?? []) {\n if (j.st.open || restsOn(o, j, i) < 0) continue\n j.st.open = true\n j.st.hp = 0\n j.st.openedBy = 'break'\n opened.push(j)\n }\n p.st.hp = Math.max(1, p.st.maxHp * 0.1)\n p.st.cracked = true\n markDamaged(p)\n debris(o, p, p.mat.breakDebris, partXf(o, p).c, [0, -1, 0], 12, 2, src)\n solveStructure(o)\n recomputeGroups(o)\n detachEvents(o, opened, 'break', src)\n collapseCheck(o, src)\n }\n\n /** Part hit points reached 0 (or it was forced to explode): fragments, debris, joints open. */\n const failPart = (o: ObjRT, p: PartRT, origin: Vec3 | null, dir: Vec3 | null, fragEnergy: number, cap: number, src?: string, force?: FractureStyle) => {\n if (isLost(p)) return\n if (p.st.stripped) {\n loseCage(o, p, src)\n return\n }\n if (!force && p.bend && (p.st.flexure ?? 0) > 1 && sectionOf(p, p.bend.gravity).reinforced) {\n hingeDrop(o, p, src)\n return\n }\n if (!force && giveAtCut(o, p, src)) return\n const ex = p.spec.explodes\n const style = force ?? (p.snap ? 'snap' : p.mat.fracture === 'none' ? 'snap' : p.mat.fracture)\n const { c, q } = partXf(o, p)\n const hitW = origin ?? c\n const grain = p.spec.grain ? AXIS[p.spec.grain] : undefined\n const hitLocal = toLocal(c, q, hitW)\n const unitPlan = p.spec.units ? unitFragmentPlan(p, maxFragments * UNIT_FRAGMENT_FACTOR) : []\n const axis = style === 'splinter' || style === 'snap' ? severAxis(p) : -1\n const cutAt = axis < 0 ? undefined : p.rt.cutAt ?? (origin ? hitLocal[axis] : undefined)\n // wood plans its splinters, sheets and lumps on a stream of its own: how a board comes apart never moves the cracks and spalls the world draws after it\n const planRnd = p.mat.splitForm ? splitStream(o.id, p.spec.id, hitLocal) : rnd\n const plan = unitPlan.length > 0 ? unitPlan : planFragments({\n style, dims: p.dims, thickness: p.thickness, grain, hit: hitLocal, fragmentSize: p.mat.fragmentSize ?? [0.04, 0.2], maxFragments, rnd: planRnd, sheet: p.mat.sheet,\n ...(p.mat.splitForm ? { form: p.mat.splitForm } : {}),\n ...(cutAt !== undefined ? { cut: { at: cutAt, gap: SEVER_BAND } } : {}),\n })\n const holes = p.st.holes.length > 0 ? localHolesOf(p) : []\n const mass = p.st.mass\n const totW = plan.reduce((s, f) => s + f.weight, 0) || 1\n const energy = ex ? ex.energy * 0.2 : fragEnergy\n const speed = clamp(Math.sqrt((2 * energy) / Math.max(mass, 0.05)), 0.3, ex ? 40 : cap)\n const fragments: Fragment[] = plan.map((f, i) => {\n const cw = toWorld(c, q, f.center)\n const out = vec.normalize(vec.sub(cw, hitW), [0, 1, 0])\n const dv = dir ? vec.normalize(vec.madd(out, dir, 0.6)) : out\n const k = speed * (0.6 + 0.8 * rnd())\n const marks = marksInBox(f.center, f.size, f.q, holes)\n return {\n id: `${p.spec.id}#${i}`, part: p.spec.id, material: p.spec.material, shape: f.shape, center: cw, size: f.size, rotation: quat.mul(q, f.q),\n velocity: [dv[0] * k, dv[1] * k + 0.5 * rnd(), dv[2] * k],\n angularVelocity: [(rnd() - 0.5) * 12, (rnd() - 0.5) * 12, (rnd() - 0.5) * 12],\n mass: (mass * f.weight) / totW, ...(marks.length > 0 ? { marks } : {}), ...(f.inner ? { inner: true } : {}),\n }\n })\n const reinforcement = p.spec.reinforcement\n if (!reinforcement) {\n p.st.status = 'broken'\n p.st.hp = 0\n p.st.mass = 0\n p.st.burning = false\n p.rt.jet = false\n }\n emit({ ...base(o, src), type: 'fracture', part: p.spec.id, style, fragments, point: hitW })\n debris(o, p, p.mat.breakDebris, c, [0, 1, 0], clamp(Math.round(Math.cbrt(partVolume(p.spec.shape)) * 30), 3, 20), 2, src)\n setStage(o, p, 3, {}, src)\n if (reinforcement) {\n stripPart(o, p, reinforcement, src)\n return\n }\n if (ex) {\n emit({ ...base(o, src), type: 'explode', part: p.spec.id, point: c, energy: ex.energy, radius: ex.radius, ...(ex.lethalRadius !== undefined ? { lethalRadius: ex.lethalRadius } : {}), ...(ex.tnt !== undefined ? { tnt: ex.tnt } : {}), ...(ex.effect !== undefined ? { effect: ex.effect } : {}) })\n blasts.push({ point: c, energy: ex.energy, radius: ex.radius, ...(ex.lethalRadius !== undefined ? { lethalRadius: ex.lethalRadius } : {}), source: src })\n }\n partLost(o, p, src)\n }\n\n /**\n * Sets an explosive part off from outside (`explodes.chain`): it will explode after the delay of `trigger`, once. The delay is one draw\n * from the world seed, so the same inputs give the same order of blasts.\n */\n const prime = (o: ObjRT, p: PartRT, trigger: ChainTrigger, src?: string) => {\n const spec = chainDelayOf(p.spec, trigger)\n if (spec === undefined || isLost(p) || p.rt.chainDue !== undefined) return\n const delay = drawChainDelay(spec, rnd)\n p.rt.chainDue = time + delay\n primed.set(p, o)\n o.active = true\n emit({ ...base(o, src), type: 'primed', part: p.spec.id, point: partXf(o, p).c, trigger, delay })\n }\n\n const CHAIN_TRIGGER_OF: Partial<Record<DamageType, ChainTrigger>> = { ballistic: 'shot', explosive: 'explosion' }\n\n /** Remove hit points. Returns the amount actually removed. */\n /**\n * A long wooden part (a board, a batten, a beam: `splinter`, box, at least `SEVER_ASPECT` times longer than it is wide) breaks where it is hit: its\n * length is cut in bands `SEVER_BAND` long, each with its share of the hit points, and the band whose share runs out breaks it across there. A thin\n * board has little in each band and goes in a few shots; a beam or a log carries its whole section in each band and takes many.\n */\n const severAxis = (p: PartRT): number => {\n // boards and beams break where they are hit: wood along the grain, a snapping board (MDF, plastic) across\n if ((p.mat.fracture !== 'splinter' && p.mat.fracture !== 'snap') || p.spec.shape.kind !== 'box') return -1\n const d = p.dims\n const order = [0, 1, 2].sort((a, b) => d[b] - d[a])\n return d[order[0]] >= SEVER_ASPECT * d[order[1]] && d[order[0]] >= 3 * SEVER_BAND ? order[0] : -1\n }\n const bandOf = (o: ObjRT, p: PartRT, axis: number, origin: Vec3): number => {\n const { c, q } = partXf(o, p)\n const along = toLocal(c, q, origin)[axis]\n const L = p.dims[axis]\n return clamp(Math.floor((along + L / 2) / SEVER_BAND), 0, Math.ceil(L / SEVER_BAND) - 1)\n }\n\n const applyDamage = (o: ObjRT, p: PartRT, amount: number, type: DamageType, origin: Vec3 | null, dir: Vec3 | null, fragEnergy: number, cap: number, src?: string): number => {\n if (isLost(p) || amount <= 0) return 0\n const prev = p.st.hp\n p.st.hp -= amount\n const axis = origin && type !== 'fire' && type !== 'heat' ? severAxis(p) : -1\n if (axis >= 0 && p.st.hp > 0) {\n const band = bandOf(o, p, axis, origin!)\n const cuts = (p.rt.cuts ??= {})\n cuts[band] = (cuts[band] ?? 0) + amount * (type === 'ballistic' ? SEVER_BALLISTIC : 1)\n if (cuts[band] >= (p.st.maxHp * SEVER_BAND) / p.dims[axis]) {\n p.rt.cutAt = -p.dims[axis] / 2 + (band + 0.5) * SEVER_BAND\n p.st.hp = 0\n }\n }\n markDamaged(p)\n const trigger = CHAIN_TRIGGER_OF[type]\n const chained = trigger !== undefined && chainDelayOf(p.spec, trigger) !== undefined\n // a bullet or a blast sets a chained part off after its delay instead of tearing it apart on the spot\n if (chained && p.st.hp <= 0 && p.rt.chainDue === undefined) p.st.hp = Math.min(prev, 1)\n if (p.st.hp <= 0 && p.mat.fracture === 'none' && !p.spec.explodes) p.st.hp = Math.min(prev, 1)\n const done = prev - p.st.hp\n if (done > 0) emit({ ...base(o, src), type: 'damage', part: p.spec.id, amount: done, hp: Math.max(0, p.st.hp), damageType: type })\n if (p.st.hp <= 0) failPart(o, p, origin, dir, fragEnergy, cap, src)\n else if (chained && (trigger === 'explosion' || 1 - p.st.hp / p.st.maxHp >= shotDamageFractionOf(p.spec))) prime(o, p, trigger, src)\n return done\n }\n\n // -------------------------------------------------------------------------------------------------------------------------------------------\n // Hits\n // -------------------------------------------------------------------------------------------------------------------------------------------\n\n /** A container of flammable fluid with a hole that goes through: it leaks. */\n const leaksFlammable = (p: PartRT): boolean => {\n const c = p.spec.contains\n return !!c && FLAMMABLE_FLUIDS.includes(c.fluid) && (p.st.liters ?? 0) > 0 && p.st.holes.some((h) => h.through)\n }\n\n /**\n * A round that went through the wall of a container of flammable fluid lights the leak or does not: the spark of a hard round on metal and the\n * flame of an incendiary or tracer (`Hit.ignition`, `Hit.incendiary`, `Hit.tracer`), weighed by how full the container is (`options.ignition`).\n * A plain bullet carries neither and only leaks. The part burns or goes off at the next `update` (`rt.lit`).\n */\n const rollIgnition = (o: ObjRT, p: PartRT, round: BallisticExtras) => {\n const c = p.spec.contains\n if (!c || !FLAMMABLE_FLUIDS.includes(c.fluid) || p.rt.jet || p.rt.lit) return\n const fill = c.liters > 0 ? (p.st.liters ?? 0) / c.liters : 0\n const chance = ignitionChance(round, { sparkTarget: sparkTargetFactor(p.mat.id, !!p.mat.tags?.includes('metal'), ignitionRules), fill, fluid: c.fluid }, ignitionRules)\n if (chance > 0 && rnd() < chance) {\n p.rt.lit = true\n o.active = true\n }\n }\n\n /** What is lit by a fire or a blast near: the leaks of flammable fluid within `radius` of `centre` (object parts only). */\n const lightLeaksNear = (centre: Vec3, radius: number) => {\n for (const o of objects.values()) {\n for (const q of o.parts) {\n if (isLost(q) || q.rt.lit || q.rt.jet || !leaksFlammable(q)) continue\n if (vec.distance(partXf(o, q).c, centre) - q.bound > radius) continue\n q.rt.lit = true\n o.active = true\n }\n }\n }\n\n /** What a blow of `kind` tears out of the material (`MaterialDef.hits`): a round into wood tears splinters by default. */\n const tearOf = (mat: MaterialDef, kind: DamageType): { tear: 'splinters' | 'lumps' | 'none'; joules: number } => {\n const h = mat.hits?.[kind]\n const tear = h?.tear ?? (kind === 'ballistic' && mat.penetrationClass === 'wood' ? 'splinters' : 'none')\n return { tear, joules: h?.tearJoules ?? TEAR_JOULES }\n }\n\n /**\n * Pieces torn out where a blow lands, as the material answers that kind of blow (`MaterialDef.hits`): splinters of fresh wood, lumps of MDF.\n * A round (`exit` when it went through) throws most out of the exit along the shot and one in three back out of the entry, two out of the entry\n * when it stayed; a blow knocks them out of the face it hits, one per `tearJoules`, none below. `scale` is the calibre or the contact size (m).\n * Reported as a `chip` where they came off. The part stays: its hit points take the blow apart.\n */\n const tearAt = (o: ObjRT, p: PartRT, kind: DamageType, entry: Vec3, exit: Vec3 | undefined, d: Vec3, E: number, scale: number, src?: string) => {\n const { tear, joules } = tearOf(p.mat, kind)\n if (tear === 'none') return\n const shot = kind === 'ballistic'\n const n = shot ? (exit ? clamp(Math.round(E / joules), 1, 7) : 1) : clamp(Math.floor(E / joules), 0, 5)\n if (n === 0) return\n const fibre = tear === 'lumps'\n const { q } = partXf(o, p)\n const along = (p.spec.grain ? AXIS[p.spec.grain] : undefined) ?? [0, 1, 2].sort((a, b) => p.dims[b] - p.dims[a])[0]\n const fragments: Fragment[] = []\n for (let i = 0; i < n; i++) {\n // out of the entry (back towards the shooter or the fist), or out of the exit along the shot\n const back = !exit || i % 3 === 2\n // plywood tears thin flat splinters off its face veneer; solid wood thicker ones; MDF short lumps\n const plies = p.mat.splitForm === 'plies'\n const len = scale * (fibre ? 1.2 + 1.2 * rnd() : 3 + 4 * rnd()), w = scale * (0.8 + 0.8 * rnd()), t = scale * (fibre ? 0.7 + 0.6 * rnd() : plies ? 0.15 + 0.15 * rnd() : 0.4 + 0.4 * rnd())\n const size: Vec3 = [w, w, w]\n size[along] = len\n size[(along + 1) % 3] = w\n size[(along + 2) % 3] = t\n const spread: Vec3 = [(rnd() - 0.5) * 0.8, (rnd() - 0.2) * 0.8, (rnd() - 0.5) * 0.8]\n const speed = shot ? (back ? 1.5 + 2 * rnd() : 2 + 4 * rnd()) : 0.8 + 1.2 * rnd()\n const v = vec.scale(vec.normalize(vec.add(back ? vec.scale(d, -1) : d, spread)), speed)\n const mass = size[0] * size[1] * size[2] * p.mat.density\n fragments.push({\n id: `${p.spec.id}#t${tears++}-${i}`, part: p.spec.id, material: p.spec.material, shape: fibre ? 'chunk' : 'splinter',\n center: back || !exit ? vec.madd(entry, d, -0.01) : vec.madd(exit, d, 0.01), size, rotation: q, velocity: v, inner: true,\n angularVelocity: [(rnd() - 0.5) * 30, (rnd() - 0.5) * 30, (rnd() - 0.5) * 30], mass,\n })\n }\n const patch: Vec3 = [scale * 4, scale * 4, scale * 4]\n emit({ ...base(o, src), type: 'chip', part: p.spec.id, center: exit ?? entry, size: patch, rotation: q, fragments, torn: true })\n }\n\n interface BallisticOut { penetrated: boolean; exitEnergy: number; exitPoint?: Vec3; damage: number }\n\n const ballistic = (o: ObjRT, p: PartRT, entry: Vec3, n: Vec3, d: Vec3, E: number, caliber: number, pathLen: number, src?: string, round: BallisticExtras = {}): BallisticOut => {\n const mat = p.mat\n const piercing = round.piercing ?? 1\n // a bare cage and an opening do not stop a bullet\n if (p.st.stripped || (p.st.opening && insideOpening(o, p, objLocal(o, entry))) || insideChip(p, objLocal(o, entry))) {\n return { penetrated: true, exitEnergy: E, exitPoint: vec.madd(entry, d, Math.min(pathLen, p.thickness)), damage: 0 }\n }\n const sin = Math.min(1, Math.abs(vec.dot(d, n)))\n const angle = (Math.asin(sin) * 180) / Math.PI\n const slant = Math.max(sin, 0.3)\n const effM = p.thickness / slant\n const face = p.layers.length > 0 ? faceOf(o, p, n) : 1\n const exitLocal = objLocal(o, vec.madd(entry, d, Math.min(pathLen, effM)))\n const coats = p.layers.length > 0 ? layersEnergy(p.layers, p.rt.spalls, face, objLocal(o, entry)) + layersEnergy(p.layers, p.rt.spalls, -face, exitLocal) : 0\n // each coat adds penetration x thickness to the core's; a part without layers keeps the plain formula\n const thr = coats > 0 ? (mat.penetration * p.thickness * 1000 + coats) / slant : mat.penetration * effM * 1000\n // the bullet's kind matters against hard targets (steel, masonry); wood, flesh and the like take every bullet for its energy\n const hard = mat.tags?.includes('metal') || mat.tags?.includes('masonry')\n // a round that carries its penetration (mm by material class) goes through a part as thick as that, whatever the energy says; else the energy rule with `piercing`\n const penMm = penetrationOf(mat, round.penetration)\n const Ep = penMm !== undefined ? penMm * mat.penetration : piercing === 1 || !hard ? E : E * piercing\n const penetrated = Ep > thr\n // a thin brittle shell that shatters (a pane, a bottle) is lost to one bullet that a thick block of the same glass shrugs off: the same\n // fragility factor that melee uses for blunt hits (1 for ductile materials and for shells 2 cm or thicker, up to x118 for 3 mm glass)\n const scale = (mat.damageScale?.ballistic ?? 1) * (mat.fracture === 'shatter' ? fragility(mat.ductility, p.thickness) : 1)\n const id = p.spec.id\n if (!penetrated && mat.ricochetDeg && angle < mat.ricochetDeg) {\n const r = vec.sub(d, vec.scale(n, 2 * vec.dot(d, n)))\n emit({ ...base(o, src), type: 'ricochet', part: id, point: entry, direction: vec.normalize(r), energy: E * 0.4 })\n debris(o, p, mat.hitDebris, entry, n, 3, 3, src)\n const dmg = applyDamage(o, p, E * DMG_PER_J * scale * 0.2, 'ballistic', entry, d, E * 0.1, 12, src)\n return { penetrated: false, exitEnergy: 0, damage: dmg }\n }\n if (p.layers.length > 0) spallOuter(o, p, entry, face, n, Math.max(0.03, (caliber / 1000) * 4), src)\n else if (mat.hits?.ballistic?.crater) crater(o, p, entry, n, clamp(0.02 + Math.sqrt(E) * 0.0015, 0.02, 0.15), src)\n const brittle = mat.ductility < 0.3\n const ratio = Ep / Math.max(thr, 1e-6)\n const crackLen = clamp(0.03 + ratio * 0.2, 0.03, 0.8)\n let exitPoint: Vec3 | undefined\n if (penetrated) {\n const exitDist = (p.spec.contains || (p.spec.fill !== undefined && p.spec.fill < 0.5) || p.thickness < pathLen * 0.5)\n ? pathLen\n : Math.min(pathLen, effM + layersThickness(p.layers, face) / slant + layersThickness(p.layers, -face) / slant)\n exitPoint = vec.madd(entry, d, exitDist)\n const hole = addHole(o, p, entry, n, (caliber / 1000) * (mat.ductility >= 0.3 ? 1 : 1.5), true, exitPoint, src)\n if (p.layers.length > 0) spallOuter(o, p, exitPoint, -face, vec.scale(n, -1), Math.max(0.03, (caliber / 1000) * 4), src)\n addBreach(o, p, entry, Math.PI * (hole.diameter / 2) * (hole.diameter / 2), E, d, src)\n // a thin ductile sheet is dished around the hole it is punched through: deeper the more energy the shot carries\n if (mat.ductility >= 0.5 && p.thickness <= THIN_SHEET_DISHING) addDent(o, p, entry, n, Math.max((caliber * 3) / 1000, 0.012), clamp(E * 0.00002, 0.001, 0.03), src)\n if (brittle && mat.fracture === 'shatter') addCrack(o, p, entry, n, crackLen, src)\n if (p.spec.contains && (p.st.liters ?? 0) > 1e-4) {\n emit({\n ...base(o, src), type: 'leak', part: id, fluid: p.spec.contains.fluid, point: entry,\n direction: p.spec.contains.outflow ? vec.normalize(rotateVec(o.st.rotation, rotateVec(p.q, p.spec.contains.outflow))) : n, rate: holeRate(hole, !!p.spec.contains.pressurized),\n pressurized: !!p.spec.contains.pressurized,\n })\n rollIgnition(o, p, round)\n }\n } else if (mat.ductility >= 0.5) {\n addDent(o, p, entry, n, Math.max((caliber * 3) / 1000, 0.012), clamp(Math.min(Math.max(p.thickness * 3, 0.003), ratio * 0.01), 0.001, 0.05), src)\n } else if (brittle) {\n // a wall of units (brick, block) takes a round in a crater, not a star of cracks: those are glass's and a slab's\n if (!p.spec.units) addCrack(o, p, entry, n, crackLen, src)\n if (mat.fracture !== 'shatter') addHole(o, p, entry, n, caliber / 1000, false, undefined, src)\n } else addHole(o, p, entry, n, caliber / 1000, false, undefined, src)\n debris(o, p, mat.hitDebris, entry, n, clamp(Math.round(E / 60) + 2, 2, 14), clamp(Math.sqrt(E) / 6, 1, 8), src)\n // a bullet only wears the joints of the part it hits, by the energy the part absorbed (a through-and-through shot transfers little), and only along\n // the stretch of each joint it shakes\n wearJoints(o, p, (penetrated ? thr : E) * 0.02, undefined, 0, src, true, BULLET_JOINT_SPAN)\n // a round that goes through a ductile shell (sheet metal, a plastic wall) punches a clean hole and leaves in it only the energy it took to cross it: a 9 mm through a\n // 3 mm plastic bin leaves 24 of its 500 J. So does a hollow shell of a material that tears (a cardboard box, a carton): the round punches through its thin wall and\n // leaves a hole, it does not shred the box. Brittle, fibrous and layered materials (glass, wood, a solid stack of paper, masonry) take the whole shock, as before.\n const hollowTear = mat.fracture === 'tear' && p.spec.fill !== undefined && p.spec.fill < 0.5\n const absorbed = penetrated && ((mat.ductility >= 0.5 && mat.fracture !== 'tear') || hollowTear) ? Math.min(E, thr) : E\n const dmg = applyDamage(o, p, absorbed * DMG_PER_J * scale, 'ballistic', entry, d, absorbed * 0.1, 12, src)\n if (!isLost(p)) tearAt(o, p, 'ballistic', entry, penetrated ? exitPoint : undefined, d, E, caliber / 1000, src)\n // a wall of units: the unit hit takes what the bullet left in it (all of it when the bullet stopped), and comes out when it took enough\n chipUnits(o, p, 'ballistic', entry, penetrated ? Math.min(E, Math.max(thr, E * 0.5)) : E, d, Math.max(0.05, (caliber / 1000) * 8), src)\n return { penetrated, exitEnergy: penetrated ? (penMm !== undefined ? E * (1 - thr / Ep) : E - thr / (hard ? piercing : 1)) : 0, exitPoint, damage: dmg }\n }\n\n const melee = (o: ObjRT, p: PartRT, kind: 'blunt' | 'slash', E: number, point: Vec3, n: Vec3, d: Vec3, contactR: number, src?: string): number => {\n const mat = p.mat\n const thrMm = mat.penetration * p.thickness * 1000\n // brittle thin shells (a bottle, a mug, a pane) break from a knock that a thick block shrugs off\n const fragile = kind === 'blunt' ? fragility(mat.ductility, p.thickness) : 1\n const Ec = E * fragile\n // a foil-like sheet folds deeper than a plate for the same blow (up to 4 times for a tenth of a millimetre), on the patch the blow touches\n const sheet = mat.ductility >= 0.5 && p.thickness <= THIN_SHEET_CRUSH\n const fold = sheet ? Math.min(4, Math.sqrt(0.001 / p.thickness)) : 1\n const patch = sheet ? Math.min(contactR, THIN_SHEET_CONTACT) : contactR\n if (E > 0) {\n if (kind === 'blunt') {\n // a sheet folds in at most to near its middle, never through its far wall\n if (mat.ductility >= 0.5) addDent(o, p, point, n, Math.max(patch, 0.015), clamp(E * 0.0001 * fold, 0.001, sheet ? Math.min(0.06, Math.min(...p.dims) * 0.45) : 0.06), src)\n else if (mat.ductility < 0.3) {\n if (Ec >= 5) addCrack(o, p, point, n, clamp(0.04 + Math.min(Ec, E * 6) * 0.0008, 0.04, 0.6), src)\n } else if (E >= thrMm * 0.2) addDent(o, p, point, n, Math.max(contactR, 0.015), clamp(E * 0.00006, 0.001, 0.04), src)\n } else if (mat.fracture === 'tear') {\n addHole(o, p, point, n, clamp(0.02 + E * 0.0005, 0.02, 0.3), true, undefined, src)\n } else if (mat.ductility >= 0.3 && E >= thrMm) {\n // a blade with more energy than the wall takes to cross goes through it and leaves a slit the width of the blade (a knife into a 3 mm plastic bin or a\n // drink can, an axe through a thin board); brittle walls (glass, ceramic, masonry, MDF) are only scratched\n addHole(o, p, point, n, clamp(contactR, 0.01, 0.08), true, undefined, src)\n // a foil-thin sheet (a can) is pushed in around the slit\n if (sheet) addDent(o, p, point, n, Math.max(patch * 0.6, 0.01), clamp(E * 0.00004 * fold, 0.0005, 0.02), src)\n } else if (mat.ductility >= 0.5) {\n addDent(o, p, point, n, Math.max(contactR, 0.01), clamp(E * 0.00004, 0.0005, 0.02), src)\n }\n debris(o, p, mat.hitDebris, point, n, clamp(Math.round(E / 25) + 1, 1, 10), clamp(Math.sqrt(E) / 8, 1, 6), src)\n }\n // a blow shakes the joints of the part it lands on, except on the terrain a structure stands on (an anchored part tagged `terrain`): a piece that lands on the\n // ground does not loosen every wall that stands on it\n if (kind === 'blunt') {\n if (!(p.anchored && p.spec.tags?.includes('terrain'))) wearJoints(o, p, E * 0.3, undefined, 0, src)\n } else wearJoints(o, p, E * 0.3, point, 0.06, src)\n if (kind === 'blunt' && E > 0 && p.layers.length > 0) spallOuter(o, p, point, faceOf(o, p, n), n, Math.max(contactR, 0.05), src)\n const scale = mat.damageScale?.[kind] ?? 1\n const done = applyDamage(o, p, Ec * DMG_PER_J * scale * (kind === 'slash' ? p.cutFactor : 1), kind, point, d, E * 0.1, 12, src)\n addBreach(o, p, point, breachAreaOf(p, done, false), E, d, src)\n // a blow that did not open the wall wears the units it lands on\n if (kind === 'blunt') chipUnits(o, p, 'blunt', point, E, d, Math.max(contactR, 0.03), src)\n if (E > 0 && !isLost(p)) tearAt(o, p, kind, point, undefined, d, E, clamp(contactR * 0.2, 0.006, 0.02), src)\n return done\n }\n\n /**\n * What one part takes of a blast: dents, cracks, debris, heat, joint wear and the hit points. `reach` is the share of the blast that gets to the\n * part (`blast.shelter`; 1 without it) and it comes back, so a caller can report it. It is computed from the point of the part nearest to the centre.\n */\n const blastPart = (o: ObjRT, p: PartRT, point: Vec3, energy: number, radius: number, src: string | undefined, res: HitResult, reachAt?: (wp: Vec3, p: PartRT) => number): number | null => {\n if (isLost(p)) return null\n const { c, q } = partXf(o, p)\n const lp = toLocal(c, q, point)\n const dist = distanceToShape(p.spec.shape, lp)\n if (dist >= radius) return null\n const sp = surfacePoint(p.spec.shape, lp)\n const wp = toWorld(c, q, sp.point)\n const reach = reachAt ? reachAt(wp, p) : 1\n const f = (1 - dist / radius) ** 2 * reach\n const Ein = energy * f * BLAST_COUPLING\n const wn = rotateVec(q, sp.normal)\n if (!res.part) {\n res.part = p.spec.id\n res.point = wp\n }\n const mat = p.mat\n if (Ein > 20) {\n if (mat.ductility >= 0.5) addDent(o, p, wp, wn, clamp(0.05 + Math.sqrt(Ein) * 0.002, 0.05, 0.4), clamp(0.004 + Ein * 0.00002, 0.004, 0.08), src)\n else if (mat.ductility < 0.3 && Ein > 60) addCrack(o, p, wp, wn, clamp(0.05 + Ein * 0.0005, 0.05, 1), src)\n debris(o, p, mat.hitDebris, wp, wn, clamp(Math.round(Ein / 80) + 1, 1, 12), clamp(Math.sqrt(Ein) / 4, 2, 15), src)\n }\n const th = mat.thermal\n if (th.ignitionC !== undefined && p.st.fuel > 0) {\n p.st.temperature += 300 * f\n o.active = true\n if (f >= 0.25 && !p.st.burning) {\n p.st.temperature = Math.max(p.st.temperature, th.ignitionC + 1)\n checkIgnite(o, p, src)\n }\n }\n // a blast loosens a long joint (the mortar bed of a wall) over the stretch it breaks, not all along it\n wearJoints(o, p, Ein * 0.5, undefined, 0, src, false, 2 * BREACH_BLAST_REACH * Math.cbrt(Math.max(0, energy) / 1000))\n const amount = Ein * DMG_PER_J * (mat.damageScale?.explosive ?? 1)\n if (blastFrontSpeed > 0 && dist > 0 && mat.tags?.includes('glass')) {\n frontQueue.push({ o, p, due: time + dist / blastFrontSpeed, amount, fragEnergy: Ein * 0.3, point, ...(src !== undefined ? { src } : {}) })\n return reach\n }\n if (Ein > 20 && p.layers.length > 0) spallOuter(o, p, wp, faceOf(o, p, wn), wn, clamp(0.05 + Math.sqrt(Ein) * 0.002, 0.05, 0.4), src)\n const breachReach = BREACH_BLAST_REACH * Math.cbrt(Math.max(0, energy) / 1000)\n const farMember = Boolean(p.spec.reinforcement && p.spec.units) && dist > MEMBER_CUT_REACH * breachReach\n // a member out of the cut reach keeps its floor of hit points and is not severed at one band: the wave loads the whole of it\n const dealt = farMember\n ? applyDamage(o, p, Math.min(amount, Math.max(0, p.st.hp - p.st.maxHp * FAR_MEMBER_HP_FLOOR)), 'explosive', null, null, Ein * 0.3, 40, src)\n : applyDamage(o, p, amount, 'explosive', point, null, Ein * 0.3, 40, src)\n res.damage += dealt\n if (p.bend && flexure.enabled) bendByBlast(o, p, point, energy, radius, reach, src)\n // laid units (brick, block in their mortar) come out by the unit; a cast part (its units are of its own material) opens as one breach\n if (p.spec.units && p.spec.units.mortar !== p.spec.material) {\n blastPanel(o, p, point, energy, src)\n if (!isLost(p)) blastUnits(o, p, wp, energy, dist, src)\n }\n // a reinforced member (a pillar, a beam) is cut through only by a charge at or near contact; further off the blast takes the concrete it reaches\n // out of it, block by block, the bars show there and the cage holds the member to what it rests on\n else if (farMember) blastUnits(o, p, wp, energy, dist, src)\n else if (dist <= breachReach) addBreach(o, p, wp, breachAreaOf(p, dealt, true), Ein, null, src)\n return reach\n }\n\n const blastProbe = { partsTested: 0, partsNear: 0 }\n\n /** Broad phase: the blast centre in object space against each part's bounding sphere, so a part out of reach costs three subtractions and no allocation. */\n const blastCandidates = (o: ObjRT, point: Vec3, radius: number): PartRT[] => {\n const local = toLocal(o.st.position, o.st.rotation, point)\n const near: PartRT[] = []\n for (const p of o.parts) {\n const reach = radius + p.bound\n const dx = local[0] - p.pos[0]\n const dy = local[1] - p.pos[1]\n const dz = local[2] - p.pos[2]\n if (dx * dx + dy * dy + dz * dz >= reach * reach) continue\n // a footing or a ground beam is in the soil: the air blast reaches it only from a charge against it\n if (p.spec.anchored && p.spec.structure?.role === 'foundation' && distToPart(o, p, point) > BURIED_BLAST_REACH) continue\n near.push(p)\n }\n blastProbe.partsTested += o.parts.length\n blastProbe.partsNear += near.length\n return near\n }\n\n const blastObject = (o: ObjRT, point: Vec3, energy: number, radius: number, src?: string): HitResult => {\n const start = cur.length\n const res: HitResult = { object: o.id, damage: 0, penetrated: false, exitEnergy: 0, events: [] }\n for (const p of blastCandidates(o, point, radius)) blastPart(o, p, point, energy, radius, src, res)\n res.events = cur.slice(start)\n return res\n }\n\n // -------------------------------------------------------------------------------------------------------------------------------------------\n // Blast options: shelter, fragment hits, confinement (all off by default)\n // -------------------------------------------------------------------------------------------------------------------------------------------\n\n interface BlastCfg {\n shelter: Required<ShelterOptions> | null\n frag: Required<FragmentHitOptions> | null\n /** A number is the multiplier itself. */\n conf: Required<ConfinementOptions> | number | null\n }\n\n const blastCfg = (call?: BlastOptions): BlastCfg => {\n const pick = <K extends keyof BlastOptions>(key: K): BlastOptions[K] => (call && call[key] !== undefined ? call[key] : options.blast?.[key])\n const merge = <T extends object>(v: boolean | T | undefined, defaults: Required<T>): Required<T> | null => {\n if (!v) return null\n const out = { ...defaults }\n if (v !== true) for (const [key, value] of Object.entries(v)) if (value !== undefined) (out as Record<string, unknown>)[key] = value\n return out\n }\n const conf = pick('confinement')\n return {\n shelter: merge(pick('shelter'), SHELTER_DEFAULTS),\n frag: merge(pick('fragmentHits'), FRAGMENT_HIT_DEFAULTS),\n conf: typeof conf === 'number' ? (Number.isFinite(conf) ? Math.max(0, conf) : 1) : merge(conf, CONFINEMENT_DEFAULTS),\n }\n }\n\n /** Same directions in every blast of this world: a Fibonacci lattice turned by the world seed. */\n const confinementRays = new Map<number, Vec3[]>()\n const raysOf = (n: number): Vec3[] => {\n let rays = confinementRays.get(n)\n if (rays) return rays\n const r = createRng((options.seed ?? 1) ^ 0x5bd1e995)\n const off = r.next()\n const phi0 = r.next() * Math.PI * 2\n rays = []\n for (let i = 0; i < n; i++) {\n const y = 1 - (2 * (i + off)) / n\n const s = Math.sqrt(Math.max(0, 1 - y * y))\n const phi = phi0 + i * 2.399963229728653\n rays.push([Math.cos(phi) * s, y, Math.sin(phi) * s])\n }\n confinementRays.set(n, rays)\n return rays\n }\n\n /** Pressure multiplier of a blast at `point`: the host's number, or an estimate from rays that hit parts (never the ones that are lost or open). */\n const confinementOf = (conf: BlastCfg['conf'], point: Vec3, radius: number): number => {\n if (conf === null) return 1\n if (typeof conf === 'number') return conf\n let hits = 0\n let sum = 0\n for (const d of raysOf(Math.max(1, Math.round(conf.rays)))) {\n const h = raycastInternal(point, d, radius * conf.reach, undefined, true)\n if (h) {\n hits++\n sum += h.distance\n }\n }\n if (hits === 0) return 1\n const closed = hits / Math.max(1, Math.round(conf.rays))\n const ratio = clamp(radius / Math.max(sum / hits, 1e-3), 0, 2)\n return Math.min(Math.max(1, conf.max), 1 + conf.gain * closed ** conf.power * ratio)\n }\n\n const FLAG_LOST = 1\n const FLAG_OPEN = 2\n\n /** The legacy blast: every part of every object, then every impl, each at full strength. */\n const blastPlain = (point: Vec3, energy: number, radius: number, src?: string, lethal?: number): HitResult[] => {\n const out: HitResult[] = []\n for (const o of [...objects.values()]) {\n if (vec.distance(toWorld(o.st.position, o.st.rotation, o.bc), point) - o.br >= radius) continue\n const r = blastObject(o, point, energy, radius, src)\n if (r.part) out.push(r)\n }\n for (const im of [...impls.values()]) {\n if (implInRange(im, point, radius)) out.push(implHit(im, { type: 'explosive', point, energy, radius, ...(lethal !== undefined ? { lethalRadius: lethal } : {}), ...(src !== undefined ? { source: src } : {}) }))\n }\n return out\n }\n\n const implParts = (im: ImplRT) =>\n im.impl.describe().parts.map((ps) => {\n const ov = im.poses.get(ps.id)\n return { ps, c: toWorld(im.position, im.rotation, ov?.pos ?? ps.position), q: quat.mul(im.rotation, ov?.q ?? quatFromEuler(...(ps.rotation ?? [0, 0, 0]))) }\n })\n\n const implInRange = (im: ImplRT, point: Vec3, radius: number): boolean => implParts(im).some(({ ps, c, q }) => distanceToShape(ps.shape, toLocal(c, q, point)) < radius)\n\n /** A blast with shelter, fragment hits or confinement. Parts are served from the nearest to the farthest, so a wall takes the blast (and may break) before what is behind it. */\n const blastScene = (point: Vec3, energy: number, radius: number, src: string | undefined, cfg: BlastCfg, only?: ObjRT | ImplRT, lethal?: number): HitResult[] => {\n const mult = confinementOf(cfg.conf, point, radius)\n const E = energy * mult\n const shelter = cfg.shelter\n const flags = new Map<PartRT, number>()\n const inRange: ObjRT[] = []\n for (const o of objects.values()) {\n if (vec.distance(toWorld(o.st.position, o.st.rotation, o.bc), point) - o.br >= radius) continue\n inRange.push(o)\n if (shelter) for (const p of o.parts) flags.set(p, (isLost(p) ? FLAG_LOST : 0) | (p.st.opening || p.st.stripped ? FLAG_OPEN : 0))\n }\n // what each blocker stands in front of, to aim its fragments\n const shields = new Map<PartRT, Vec3[]>()\n /** Share of the blast that gets to `tp` (world) through everything between it and the centre; `self` never blocks. */\n const reachAt = (tp: Vec3, self: PartRT | null): number => {\n if (!shelter) return 1\n const L = vec.distance(point, tp)\n if (L < 1e-4) return 1\n const d = vec.scale(vec.sub(tp, point), 1 / L)\n let t = 1\n for (const o of inRange) {\n if (raySphereMiss(point, d, toWorld(o.st.position, o.st.rotation, o.bc), o.br, L)) continue\n for (const p of o.parts) {\n if (p === self) continue\n const was = flags.get(p) ?? 0\n if (was & FLAG_LOST) continue\n const r = rayPart(o, p, point, d)\n if (!r) continue\n const t0 = Math.max(r.t0, 0)\n const path = Math.min(r.t1, L) - t0\n if (path < shelter.minPath) continue\n const mid = vec.madd(point, d, t0 + path / 2)\n const opening = p.st.opening && insideOpening(o, p, mid)\n if (opening && was & FLAG_OPEN) continue\n if (p.st.stripped && was & FLAG_OPEN) continue\n const resistance = p.mat.hpPerKg * p.mat.density * path * (p.mat.damageScale?.shelter ?? 1)\n let ti = Math.exp(-resistance / shelter.k)\n // destroyed or breached by this same blast: part of what it held back goes through\n if (isLost(p) || opening || (p.st.stripped && !(was & FLAG_OPEN))) ti += (1 - ti) * shelter.brokenTransmission\n t *= ti\n if (cfg.frag) {\n let list = shields.get(p)\n if (!list) shields.set(p, (list = []))\n list.push(tp)\n }\n }\n }\n return t\n }\n\n interface Item { dist: number; order: number; o?: ObjRT; p?: PartRT; im?: ImplRT }\n const items: Item[] = []\n let order = 0\n for (const o of inRange) {\n if (only && only !== o) continue\n for (const p of blastCandidates(o, point, radius)) {\n if (isLost(p)) continue\n const dist = distToPart(o, p, point)\n if (dist < radius) items.push({ dist, order: order++, o, p })\n }\n }\n for (const im of impls.values()) {\n if (only && only !== im) continue\n let dist = Infinity\n for (const { ps, c, q } of implParts(im)) dist = Math.min(dist, distanceToShape(ps.shape, toLocal(c, q, point)))\n if (dist < radius) items.push({ dist, order: order++, im })\n }\n items.sort((a, b) => a.dist - b.dist || a.order - b.order)\n\n const results = new Map<ObjRT | ImplRT, HitResult>()\n const reports = new Map<ObjRT | ImplRT, BlastReport>()\n const report = (key: ObjRT | ImplRT): BlastReport => {\n let r = reports.get(key)\n if (!r) reports.set(key, (r = { shelter: 0, confinement: mult, fragmentHits: 0 }))\n return r\n }\n const thrown: Array<{ frag: Fragment; object: string; part: PartRT | null }> = []\n const sweep = (from: number) => {\n if (!cfg.frag) return\n for (let i = from; i < cur.length; i++) {\n const e = cur[i]!\n if (e.type !== 'fracture' && e.type !== 'stage') continue\n for (const frag of e.fragments ?? []) thrown.push({ frag, object: e.object, part: objects.get(e.object)?.byId.get(e.part) ?? null })\n }\n }\n\n for (const it of items) {\n if (it.o && it.p) {\n const o = it.o\n let res = results.get(o)\n if (!res) results.set(o, (res = { object: o.id, damage: 0, penetrated: false, exitEnergy: 0, events: [] }))\n const start = cur.length\n const k = blastPart(o, it.p, point, E, radius, src, res, shelter ? reachAt : undefined)\n res.events.push(...cur.slice(start))\n sweep(start)\n if (k !== null) {\n const rep = report(o)\n rep.shelter = Math.max(rep.shelter, k)\n if (shelter) (rep.parts ??= {})[it.p.spec.id] = k\n }\n } else if (it.im) {\n const im = it.im\n // the impl takes one hit: the share of the blast that gets to its parts, weighted by how hard the blast hits each\n let num = 0\n let den = 0\n for (const { ps, c, q } of implParts(im)) {\n const lp = toLocal(c, q, point)\n const dist = distanceToShape(ps.shape, lp)\n if (dist >= radius) continue\n const f = (1 - dist / radius) ** 2\n const sp = surfacePoint(ps.shape, lp)\n num += f * reachAt(toWorld(c, q, sp.point), null)\n den += f\n }\n const k = den > 0 ? num / den : 1\n const res = implHit(im, { type: 'explosive', point, energy: E * k, radius, ...(lethal !== undefined ? { lethalRadius: lethal } : {}), ...(shelter ? { shelter: k } : {}), ...(src !== undefined ? { source: src } : {}) })\n results.set(im, res)\n report(im).shelter = k\n }\n }\n\n if (cfg.frag && thrown.length > 0) {\n const g = cfg.frag\n const energyOf = (f: Fragment) => 0.5 * f.mass * (f.velocity[0] ** 2 + f.velocity[1] ** 2 + f.velocity[2] ** 2)\n const list = thrown\n .map((t, i) => ({ ...t, i, e: energyOf(t.frag) }))\n .sort((a, b) => b.e - a.e || a.i - b.i)\n .slice(0, Math.max(0, Math.floor(g.max)))\n list.forEach((t, i) => throwFragment(t.frag, t.object, t.part, g, point, i, src, shields, results, reports, mult))\n }\n\n const out: HitResult[] = []\n const reportShelter = (key: ObjRT | ImplRT, res: HitResult) => {\n res.blast = reports.get(key) ?? { shelter: 1, confinement: mult, fragmentHits: 0 }\n }\n const summary: Array<{ object: string; part?: string; factor: number }> = []\n let fragmentHits = 0\n for (const o of objects.values()) {\n const r = results.get(o)\n if (!r?.part) continue\n reportShelter(o, r)\n out.push(r)\n for (const [part, factor] of Object.entries(r.blast?.parts ?? {})) summary.push({ object: o.id, part, factor })\n fragmentHits += r.blast?.fragmentHits ?? 0\n }\n for (const im of impls.values()) {\n const r = results.get(im)\n if (!r) continue\n reportShelter(im, r)\n out.push(r)\n if (shelter) summary.push({ object: im.impl.id, factor: r.blast?.shelter ?? 1 })\n fragmentHits += r.blast?.fragmentHits ?? 0\n }\n emit({ type: 'blast', object: '', time, ...(src !== undefined ? { source: src } : {}), point, energy: E, radius, confinement: mult, shelter: summary, fragmentHits })\n return out\n }\n\n /** Integer seed from numbers: a fragment's flight depends only on the blast and on the fragment, not on what the world did before. */\n const seedOf = (...nums: number[]): number => {\n let h = 2166136261\n for (const n of nums) {\n h = Math.imul(h ^ (Math.round(n * 1000) | 0), 16777619)\n h ^= h >>> 15\n }\n return h | 0\n }\n\n /**\n * The stream a wood part plans its break on: read off the world's stream without drawing from it (so a save carries it), and mixed with the object,\n * the part and where it was hit.\n */\n const splitStream = (objectId: string, partId: string, hit: Vec3): (() => number) => {\n const codes = Array.from(`${objectId}|${partId}`, (char) => char.charCodeAt(0) / 1000)\n const stream = createRng(seedOf(rng.state() / 1000, ...codes, hit[0], hit[1], hit[2]))\n return () => stream.next()\n }\n\n /** One fragment of a part the blast broke flies on: a low-energy hit on the first part or impl it reaches within its throw. */\n const throwFragment = (\n frag: Fragment, objectId: string, from: PartRT | null, g: Required<FragmentHitOptions>, centre: Vec3, index: number, src: string | undefined,\n shields: Map<PartRT, Vec3[]>, results: Map<ObjRT | ImplRT, HitResult>, reports: Map<ObjRT | ImplRT, BlastReport>, mult: number,\n ) => {\n const v = frag.velocity\n const speed = Math.hypot(v[0], v[1], v[2])\n const energy = g.energyFactor * 0.5 * frag.mass * speed * speed\n if (speed < 0.5 || energy < 1) return\n const r = createRng(seedOf(options.seed ?? 1, centre[0], centre[1], centre[2], index, frag.center[0], frag.center[1], frag.center[2]))\n let dir = vec.scale(v, 1 / speed)\n // a fragment of a blocker whose flight points at a target behind it goes for that target\n const behind = from ? shields.get(from) : undefined\n if (behind) {\n let best = Math.cos((g.aim * Math.PI) / 180)\n for (const tp of behind) {\n const to = vec.sub(tp, frag.center)\n const len = vec.length(to)\n if (len < 1e-4) continue\n const cos = vec.dot(dir, to) / len\n if (cos >= best) {\n best = cos\n dir = vec.scale(to, 1 / len)\n }\n }\n }\n const spread = Math.tan((g.spread * Math.PI) / 180)\n dir = vec.normalize([dir[0] + (r.next() - 0.5) * 2 * spread, dir[1] + (r.next() - 0.5) * 2 * spread, dir[2] + (r.next() - 0.5) * 2 * spread], dir)\n const range = Math.min(g.range, speed * g.flightTime)\n const origin = vec.madd(frag.center, dir, 0.02)\n const rh = raycastInternal(origin, dir, range, from ? new Set([`${objectId}\\0${from.spec.id}`]) : undefined)\n if (!rh) return\n const hit: Hit = {\n type: g.hitType, point: rh.point, direction: dir, energy, radius: 0.05, part: rh.part,\n ...(g.hitType === 'ballistic' ? { caliber: clamp(Math.max(...frag.size) * 1000, 3, 30), mass: frag.mass * 1000 } : {}),\n ...(src !== undefined ? { source: src } : {}),\n }\n emit({ type: 'fragment_hit', object: objectId, time, ...(src !== undefined ? { source: src } : {}), from: { object: objectId, part: frag.part }, target: { object: rh.object, part: rh.part }, point: rh.point, direction: dir, energy, mass: frag.mass, speed })\n const im = impls.get(rh.object)\n const o = im ? undefined : objects.get(rh.object)\n const key = im ?? o\n if (!key) return\n const res = im ? implHit(im, hit) : doHit(o!, hit, o!.byId.get(rh.part))\n const have = results.get(key)\n if (have) {\n have.damage += res.damage\n have.events.push(...res.events)\n if (!have.part) have.part = res.part\n if (res.penetrated) have.penetrated = true\n } else results.set(key, { ...res, events: [...res.events] })\n let rep = reports.get(key)\n if (!rep) reports.set(key, (rep = { shelter: 1, confinement: mult, fragmentHits: 0 }))\n rep.fragmentHits++\n }\n\n const blastWorld = (point: Vec3, energy: number, radius: number, src?: string, call?: BlastOptions, only?: ObjRT | ImplRT, lethal?: number): HitResult[] => {\n const cfg = blastCfg(call)\n const res = !cfg.shelter && !cfg.frag && cfg.conf === null ? blastPlain(point, energy, radius, src, lethal) : blastScene(point, energy, radius, src, cfg, only, lethal)\n // a blast is a flame: a container that leaks flammable fluid inside it catches\n lightLeaksNear(point, radius)\n return res\n }\n\n const heatObject = (o: ObjRT, point: Vec3, T: number, radius: number, duration: number, src?: string): HitResult => {\n const start = cur.length\n const res: HitResult = { object: o.id, damage: 0, penetrated: false, exitEnergy: 0, events: [] }\n for (const p of o.parts) {\n if (isLost(p)) continue\n const dist = distToPart(o, p, point)\n if (dist >= radius) continue\n const f = clamp(1 - dist / radius, 0.25, 1)\n if (!res.part) {\n res.part = p.spec.id\n res.point = point\n }\n if (T > p.st.temperature) {\n const k = (0.8 * f) / (p.mat.thermal.heatCapacity ?? 1)\n p.st.temperature += (T - p.st.temperature) * (1 - Math.exp(-k * duration))\n }\n o.active = true\n // a flame held against a flammable leak lights it: it burns, or goes off by its chain, at the next update\n if (T >= FLAME_LIGHTS_LEAK_C && !p.rt.jet && !p.rt.lit && leaksFlammable(p)) p.rt.lit = true\n checkIgnite(o, p, src)\n }\n res.events = cur.slice(start)\n return res\n }\n\n /** `fn` with every event it emits tagged with the blow `type` (a shot, a hit). */\n const withBlow =\n <T>(type: DamageType, fn: () => T) =>\n (): T => {\n const outer = blow\n blow = type\n try {\n return fn()\n } finally {\n blow = outer\n }\n }\n\n const doHit = (o: ObjRT, hit: Hit, only?: PartRT): HitResult => withBlow(hit.type, () => resolveHit(o, hit, only))()\n\n const resolveHit = (o: ObjRT, hit: Hit, only?: PartRT): HitResult => {\n let point = hit.point\n let dir = hit.direction\n if (hit.space === 'local') {\n point = toWorld(o.st.position, o.st.rotation, point)\n if (dir) dir = rotateVec(o.st.rotation, dir)\n }\n const src = hit.source\n const start = cur.length\n let res: HitResult = { object: o.id, damage: 0, penetrated: false, exitEnergy: 0, events: [] }\n const E = hit.energy ?? 0\n if (hit.type === 'ballistic') {\n const loc = locate(o, point, dir, 0.05, only)\n if (loc) {\n const out = ballistic(o, loc.p, loc.point, loc.normal, loc.dir, E, hit.caliber ?? 9, loc.pathLen, src, hit)\n res = { ...res, part: loc.p.spec.id, point: loc.point, damage: out.damage, penetrated: out.penetrated, exitEnergy: out.exitEnergy }\n }\n } else if (hit.type === 'blunt' || hit.type === 'slash') {\n const radius = hit.radius ?? 0\n const loc = locate(o, point, dir, Math.max(0.05, radius), only)\n if (loc) {\n res.part = loc.p.spec.id\n res.point = loc.point\n res.damage += melee(o, loc.p, hit.type, E, loc.point, loc.normal, loc.dir, radius || 0.03, src)\n if (radius > 0.1 && !only) {\n for (const p of o.parts) {\n if (p === loc.p || isLost(p)) continue\n const dd = distToPart(o, p, point)\n if (dd >= radius) continue\n const { c, q } = partXf(o, p)\n const sp = surfacePoint(p.spec.shape, toLocal(c, q, point))\n res.damage += melee(o, p, hit.type, E * (1 - dd / radius) ** 2, toWorld(c, q, sp.point), rotateVec(q, sp.normal), loc.dir, radius, src)\n }\n }\n }\n } else if (hit.type === 'explosive') {\n const call = hit.blast || hit.confinement !== undefined ? { ...hit.blast, ...(hit.confinement !== undefined ? { confinement: hit.confinement } : {}) } : undefined\n const cfg = blastCfg(call)\n if (!cfg.shelter && !cfg.frag && cfg.conf === null) res = blastObject(o, point, E, hit.radius ?? 2, src)\n else {\n res = blastWorld(point, E, hit.radius ?? 2, src, call, o)[0] ?? res\n res.events = cur.slice(start)\n }\n } else {\n res = heatObject(o, point, hit.temperature ?? 800, hit.radius ?? 0.25, hit.duration ?? 1, src)\n }\n res.events = cur.slice(start)\n return res\n }\n\n // -------------------------------------------------------------------------------------------------------------------------------------------\n // Fire, heat, melting, leaks\n // -------------------------------------------------------------------------------------------------------------------------------------------\n\n const checkIgnite = (o: ObjRT, p: PartRT, src?: string) => {\n const th = p.mat.thermal\n if (isLost(p) || p.st.burning || th.ignitionC === undefined || p.st.fuel <= 0 || p.st.temperature < th.ignitionC) return\n p.st.burning = true\n p.st.temperature = Math.max(p.st.temperature, th.flameC ?? 800)\n o.active = true\n markDamaged(p)\n emit({ ...base(o, src), type: 'ignite', part: p.spec.id, point: partXf(o, p).c })\n }\n\n const syncMass = (p: PartRT) => {\n p.st.mass = Math.max(0, p.mass0 * (1 - p.st.melt) - (p.fuel0 - p.st.fuel))\n }\n\n const burnStep = (o: ObjRT, p: PartRT, dt: number) => {\n const th = p.mat.thermal\n const use = Math.min((th.burnRate ?? 0.01) * p.area * dt, p.st.fuel)\n p.st.fuel -= use\n syncMass(p)\n if (p.structural) o.dirty = true\n p.st.temperature = th.flameC ?? 800\n markDamaged(p)\n if (p.fuel0 > 0) {\n p.st.char = clamp(1 - p.st.fuel / p.fuel0, 0, 1)\n p.st.hp = Math.min(p.st.hp, Math.max(1, p.st.maxHp * (p.st.fuel / p.fuel0)))\n }\n if (p.st.fuel <= 1e-9) {\n p.st.fuel = 0\n p.st.burning = false\n p.st.char = 1\n const c = partXf(o, p).c\n if ((th.fuelFraction ?? 0) >= 0.8) {\n p.st.status = 'ashes'\n p.st.hp = 0\n p.st.mass = p.mass0 * (1 - (th.fuelFraction ?? 0))\n emit({ ...base(o), type: 'burnout', part: p.spec.id, point: c })\n debris(o, p, 'ash', c, [0, 1, 0], clamp(Math.round(Math.cbrt(partVolume(p.spec.shape)) * 30), 3, 20), 1)\n partLost(o, p)\n } else {\n emit({ ...base(o), type: 'burnout', part: p.spec.id, point: c })\n }\n }\n }\n\n const meltStep = (o: ObjRT, p: PartRT, dt: number) => {\n const th = p.mat.thermal\n if (th.meltC === undefined || p.st.temperature <= th.meltC) return\n const rate = (th.meltRate ?? 0.05) * ((p.st.temperature - th.meltC) / 100)\n p.st.melt = Math.min(1, p.st.melt + rate * dt)\n syncMass(p)\n if (p.structural) o.dirty = true\n markDamaged(p)\n p.rt.dripT += dt\n if (p.rt.dripT >= 0.25) {\n p.rt.dripT -= 0.25\n const b = partWorldAabb(o, p)\n const pt: Vec3 = [b.min[0] + (b.max[0] - b.min[0]) * (0.2 + 0.6 * rnd()), b.min[1], b.min[2] + (b.max[2] - b.min[2]) * (0.2 + 0.6 * rnd())]\n emit({ ...base(o), type: 'drip', part: p.spec.id, point: pt, material: p.mat.id })\n }\n if (p.st.melt - p.rt.meltEmitted >= 0.05 || p.st.melt >= 1) {\n p.rt.meltEmitted = p.st.melt\n emit({ ...base(o), type: 'melt', part: p.spec.id, melt: p.st.melt })\n }\n if (p.st.melt >= 1) {\n p.st.status = 'melted'\n p.st.hp = 0\n p.st.mass = 0\n p.st.burning = false\n p.rt.jet = false\n partLost(o, p)\n }\n }\n\n const stepObject = (o: ObjRT, dt: number, sources: Array<{ o: ObjRT; p: PartRT; flame: number }>) => {\n const parts = o.parts\n const T0 = o.tmp\n T0.length = parts.length\n for (let i = 0; i < parts.length; i++) T0[i] = parts[i].st.temperature\n let hot = false\n for (let i = 0; i < parts.length; i++) {\n const p = parts[i]\n if (isLost(p)) continue\n const th = p.mat.thermal\n const hc = th.heatCapacity ?? 1\n const s = p.st\n if (p.rt.jet) {\n s.temperature = Math.max(s.temperature, 900)\n } else if (s.burning) {\n burnStep(o, p, dt)\n if (isLost(p)) continue\n }\n if (!s.burning && !p.rt.jet) {\n // conduction from hotter neighbours through closed joints, then cooling\n let dT = 0\n let maxN = s.temperature\n for (const j of o.byPart.get(p.spec.id)!) {\n if (j.st.open) continue\n const k = j.ia === i ? j.ib : j.ia\n if (isLost(parts[k]) || T0[k] <= T0[i]) continue\n const c = (th.conductivity + parts[k].mat.thermal.conductivity) / 2\n dT += (T0[k] - T0[i]) * (1 - Math.exp((-1.2 * c * dt) / hc))\n if (T0[k] > maxN) maxN = T0[k]\n }\n if (dT > 0) s.temperature = Math.min(s.temperature + dT, maxN)\n s.temperature += (ambient - s.temperature) * (1 - Math.exp(-dt / (20 * hc)))\n if (Math.abs(s.temperature - ambient) < 0.05) s.temperature = ambient\n }\n meltStep(o, p, dt)\n if (isLost(p)) continue\n checkIgnite(o, p)\n const ex = p.spec.explodes\n if (ex && chainDelayOf(p.spec, 'fire') !== undefined) {\n if (s.temperature >= (ex.atC ?? FIRE_PRIME_C)) prime(o, p, 'fire')\n } else if (ex && ex.atC !== undefined && s.temperature >= ex.atC) {\n failPart(o, p, null, null, 0, 40)\n continue\n }\n // leaks\n const cont = p.spec.contains\n if (cont && (s.liters ?? 0) > 0) {\n let rate = 0\n for (const h of s.holes) if (h.through) rate += holeRate(h, !!cont.pressurized)\n if (rate > 0) {\n s.liters = Math.max(0, (s.liters ?? 0) - rate * dt)\n hot = true\n if (FLAMMABLE_FLUIDS.includes(cont.fluid) && (s.temperature >= 350 || p.rt.lit) && !p.rt.jet) {\n p.rt.lit = false\n if (ex && chainDelayOf(p.spec, 'fire') !== undefined) {\n prime(o, p, 'fire')\n continue\n }\n if (ex) {\n failPart(o, p, null, null, 0, 40)\n continue\n }\n p.rt.jet = true\n s.burning = true\n emit({ ...base(o), type: 'ignite', part: p.spec.id, point: partXf(o, p).c })\n }\n }\n }\n if ((s.liters ?? 0) <= 0) p.rt.lit = false\n if (p.rt.jet && (s.liters ?? 0) <= 0) {\n p.rt.jet = false\n s.burning = false\n emit({ ...base(o), type: 'extinguish', part: p.spec.id })\n }\n // thermal shock\n const sc = th.thermalShockC\n if (sc !== undefined) {\n p.rt.shockT = Math.max(0, p.rt.shockT - dt)\n const rate = Math.abs(s.temperature - p.rt.prevTemp) / dt\n p.rt.prevTemp = s.temperature\n if (rate > sc && p.rt.shockT <= 0) {\n p.rt.shockT = 1\n const { c, q } = partXf(o, p)\n const lp: Vec3 = [(rnd() - 0.5) * p.dims[0], (rnd() - 0.5) * p.dims[1], (rnd() - 0.5) * p.dims[2]]\n const sp = surfacePoint(p.spec.shape, lp)\n addCrack(o, p, toWorld(c, q, sp.point), rotateVec(q, sp.normal), 0.1 + (rate / sc) * 0.1)\n applyDamage(o, p, p.st.maxHp * 0.25, 'heat', null, null, 5, 3)\n if (isLost(p)) continue\n }\n }\n if (s.burning || p.rt.jet) sources.push({ o, p, flame: p.rt.jet ? 900 : th.flameC ?? 800 })\n if (s.burning || p.rt.jet || s.temperature > ambient + 0.5) hot = true\n }\n if (o.hasStructure) {\n if (o.dirty) {\n o.dirty = false\n solveStructure(o)\n }\n for (const p of parts) {\n if (!p.structural || isLost(p)) continue\n const stress = p.st.stress ?? 0\n p.rt.stressT = Math.max(0, (p.rt.stressT ?? 0) - dt)\n if (stress > 1) {\n if (p.rt.stressT <= 0) {\n p.rt.stressT = 0.5\n emit({ ...base(o), type: 'stress', part: p.spec.id, stress, load: p.st.load ?? 0 })\n // the bare steel of an overloaded part bends further each time\n if (p.spec.reinforcement && (p.st.stripped || p.st.chipped?.length || p.st.opening)) exposeRebar(o, p)\n }\n applyDamage(o, p, overloadRate(stress) * p.st.maxHp * dt, 'blunt', null, null, 5, 3)\n } else if (stress > 0.8 && p.mat.ductility < 0.3 && p.rt.stressT <= 0 && p.st.cracks.length < 6) {\n p.rt.stressT = 0.5\n const { c, q } = partXf(o, p)\n const sp = surfacePoint(p.spec.shape, [(rnd() - 0.5) * p.dims[0], (rnd() - 0.5) * p.dims[1], (rnd() - 0.5) * p.dims[2]])\n addCrack(o, p, toWorld(c, q, sp.point), rotateVec(q, sp.normal), 0.1 + (stress - 0.8) * 0.5)\n }\n }\n if (o.maxStress > 0.8) hot = true\n }\n o.active = hot\n }\n\n /** A leak of flammable fluid within `ignition.fireNear.radius` of a burning part (or of a jet) lights at `chancePerSecond`. */\n const igniteLeaksNearFire = (sources: Array<{ o: ObjRT; p: PartRT; flame: number }>, dt: number) => {\n const { radius, chancePerSecond } = ignitionRules.fireNear\n if (chancePerSecond <= 0) return\n const chance = 1 - Math.exp(-chancePerSecond * dt)\n for (const src of sources) {\n if (!src.p.st.burning && !src.p.rt.jet) continue\n const sc = partXf(src.o, src.p).c\n for (const o of objects.values()) {\n for (const q of o.parts) {\n if (q === src.p || isLost(q) || q.rt.lit || q.rt.jet || !leaksFlammable(q)) continue\n if (vec.distance(partXf(o, q).c, sc) - q.bound - src.p.bound > radius) continue\n if (rnd() < chance) {\n q.rt.lit = true\n o.active = true\n }\n }\n }\n }\n }\n\n const spread = (sources: Array<{ o: ObjRT; p: PartRT; flame: number }>, dt: number) => {\n for (const src of sources) {\n if (!src.p.st.burning && !src.p.rt.jet) continue\n const sc = toWorld(src.o.st.position, src.o.st.rotation, src.p.pos)\n const A = partWorldAabb(src.o, src.p)\n for (const o of objects.values()) {\n if (o === src.o) continue\n if (vec.distance(toWorld(o.st.position, o.st.rotation, o.bc), sc) > o.br + src.p.bound + fireSpread) continue\n for (const q of o.parts) {\n if (isLost(q) || q.st.burning) continue\n const B = partWorldAabb(o, q)\n const gap = Math.hypot(\n Math.max(0, A.min[0] - B.max[0], B.min[0] - A.max[0]),\n Math.max(0, A.min[1] - B.max[1], B.min[1] - A.max[1]),\n Math.max(0, A.min[2] - B.max[2], B.min[2] - A.max[2]),\n )\n if (gap >= fireSpread || src.flame <= q.st.temperature) continue\n const f = 1 - gap / fireSpread\n q.st.temperature += (src.flame - q.st.temperature) * (1 - Math.exp((-0.6 * f * dt) / (q.mat.thermal.heatCapacity ?? 1)))\n o.active = true\n }\n }\n }\n }\n\n // -------------------------------------------------------------------------------------------------------------------------------------------\n // World API\n // -------------------------------------------------------------------------------------------------------------------------------------------\n\n /** The primed part that goes off first: earliest due time, then the older object, then the part listed first. */\n const nextPrimed = (until: number): { o: ObjRT; p: PartRT } | null => {\n let best: { o: ObjRT; p: PartRT } | null = null\n for (const [p, o] of primed) {\n if (objects.get(o.id) !== o || isLost(p)) {\n primed.delete(p)\n continue\n }\n const due = p.rt.chainDue as number\n if (due > until) continue\n if (!best) best = { o, p }\n else {\n const bestDue = best.p.rt.chainDue as number\n if (due < bestDue || (due === bestDue && (o.order < best.o.order || (o.order === best.o.order && (o.idx.get(p.spec.id) ?? 0) < (best.o.idx.get(best.p.spec.id) ?? 0))))) best = { o, p }\n }\n }\n return best\n }\n\n /**\n * Explodes the primed parts whose delay ran out by `until`, one at a time in order of time; each blast is resolved before the next part goes off,\n * so a part it primes counts its delay from that moment, not from the end of the frame.\n */\n const detonatePrimed = (until: number) => {\n const end = time\n let fired = 0\n for (let next = nextPrimed(until); next && fired < chainLinkCap; next = nextPrimed(until)) {\n fired++\n primed.delete(next.p)\n time = Math.max(0, Math.min(end, next.p.rt.chainDue as number))\n next.p.rt.chainDue = undefined\n failPart(next.o, next.p, null, null, 0, 40)\n drainBlasts()\n }\n time = end\n }\n\n /** Lands the damage of the glass the blast front has reached by `time`, the nearest first. */\n const releaseFront = () => {\n if (frontQueue.length === 0) return\n frontQueue.sort((a, b) => a.due - b.due)\n while (frontQueue.length > 0 && frontQueue[0]!.due <= time) {\n const hit = frontQueue.shift()!\n if (objects.get(hit.o.id) !== hit.o) continue\n applyDamage(hit.o, hit.p, hit.amount, 'explosive', hit.point, null, hit.fragEnergy, 40, hit.src)\n }\n }\n\n /** Collapse events are produced after the whole operation: make sure the result of the operation carries them. */\n const withCollapses = (r: { value: HitResult[]; events: DestructionEvent[] }): HitResult[] => {\n const last = r.value[r.value.length - 1]\n if (!last) return r.value\n for (const e of r.events) if (e.type === 'collapse' && !r.value.some((h) => h.events.includes(e))) last.events.push(e)\n return r.value\n }\n\n /** An explosive hit on an impl: a blast of its own when blast options are on, else the plain hit. */\n const blastImpl = (im: ImplRT, h: Hit): HitResult => {\n const call = h.blast || h.confinement !== undefined ? { ...h.blast, ...(h.confinement !== undefined ? { confinement: h.confinement } : {}) } : undefined\n const cfg = blastCfg(call)\n if (!cfg.shelter && !cfg.frag && cfg.conf === null) return implHit(im, h)\n const world = h.space === 'local' ? toWorld(im.position, im.rotation, h.point) : h.point\n const r = blastWorld(world, h.energy ?? 0, h.radius ?? 2, h.source, call, im)\n return r.find((x) => x.object === im.impl.id) ?? implHit(im, h)\n }\n\n const whole = (fn: () => HitResult): HitResult => {\n const r = run(fn)\n r.value.events = r.events\n return r.value\n }\n\n const world: DestructionWorld = {\n materials,\n get time() {\n return time\n },\n add(spec, opts: AddOptions = {}) {\n const id = opts.id ?? nextId()\n if (taken(id)) throw new Error(`object \"${id}\" already exists`)\n objects.set(id, build(resolveSpec(spec), id, opts.position ?? [0, 0, 0], opts.rotation ?? [0, 0, 0, 1]))\n return id\n },\n register(impl, opts: AddOptions = {}) {\n const id = opts.id ?? impl.id\n if (taken(id)) throw new Error(`object \"${id}\" already exists`)\n impls.set(id, { impl, position: opts.position ?? [0, 0, 0], rotation: opts.rotation ?? [0, 0, 0, 1], poses: new Map() })\n return id\n },\n setPartPose(objectId, partId, position, rotation) {\n const q = quatFromEuler(...(rotation ?? [0, 0, 0]))\n const im = impls.get(objectId)\n if (im) {\n im.impl.setPartPose?.(partId, position, rotation)\n im.poses.set(partId, { pos: [position[0], position[1], position[2]], q })\n return\n }\n const o = getObj(objectId)\n const p = getPart(o, partId)\n p.pos = [position[0], position[1], position[2]]\n p.q = q\n poseVersion++\n updateBound(o)\n },\n remove(id) {\n impls.get(id)?.impl.dispose?.()\n objects.delete(id)\n impls.delete(id)\n },\n has: (id) => taken(id),\n ids: () => [...objects.keys(), ...impls.keys()],\n setTransform(id, position, rotation) {\n const im = impls.get(id)\n if (im) {\n im.position = [position[0], position[1], position[2]]\n im.rotation = [rotation[0], rotation[1], rotation[2], rotation[3]]\n return\n }\n const o = getObj(id)\n o.base = { pos: [position[0], position[1], position[2]], rot: [rotation[0], rotation[1], rotation[2], rotation[3]] }\n applySoilPose(o)\n slideOffResting(o, rotation)\n },\n splitGroup(id, group, newId) {\n if (impls.has(id)) throw new Error(`object \"${id}\" is a registered DestructibleImpl and cannot be split; its module owns its pieces`)\n const o = getObj(id)\n if (o.st.groups.length < 2) return id\n const names = o.st.groups[group]\n if (!names) throw new Error(`object \"${id}\" has no group ${group}`)\n const moved = new Set(names)\n const nid = newId ?? nextId()\n if (objects.has(nid)) throw new Error(`object \"${nid}\" already exists`)\n // an open joint between the two objects stays with the original\n const carryFor = (keep: (pid: string) => boolean, keepOpen: (a: string, b: string) => boolean = () => false): Carry => ({\n parts: new Map(o.parts.filter((p) => keep(p.spec.id)).map((p) => [p.spec.id, { st: p.st, rt: p.rt }])),\n joints: new Map([\n ...o.joints.filter((j) => (keep(j.spec.a) && keep(j.spec.b)) || (j.st.open && keepOpen(j.spec.a, j.spec.b))).map((j): [string, { st: JointState; step: number }] => [j.spec.id, { st: j.st, step: j.step }]),\n ...o.st.joints.filter((st) => st.open && !o.jointMap.has(st.id) && keepOpen(st.a, st.b)).map((st): [string, { st: JointState; step: number }] => [st.id, { st, step: 0 }]),\n ]),\n collapsed: [...o.collapsed].filter(keep),\n })\n const sub = (keep: (pid: string) => boolean): DestructibleSpec => {\n const s: DestructibleSpec = { parts: o.spec.parts.filter((p) => keep(p.id)), joints: (o.spec.joints ?? []).filter((j) => keep(j.a) && keep(j.b)) }\n if (o.spec.name !== undefined) s.name = o.spec.name\n if (o.spec.tags) s.tags = [...o.spec.tags]\n if (o.spec.soil !== undefined) s.soil = o.spec.soil\n // the part and joint specs are never written after `add`, so the halves share them instead of deep-copying a whole house twice\n return s\n }\n const inNew = (pid: string) => moved.has(pid)\n const inOld = (pid: string) => !moved.has(pid)\n const pos = o.st.position, rot = o.st.rotation\n const fresh = build(sub(inNew), nid, pos, rot, carryFor(inNew, (a, b) => inNew(a) && inNew(b)))\n const restCarry = carryFor(inOld, (a, b) => !(inNew(a) && inNew(b)))\n if (o.st.soil) restCarry.soil = o.st.soil\n if (o.soil?.sets.size) restCarry.soilSets = Object.fromEntries(o.soil.sets)\n const rest = build(sub(inOld), id, o.soil ? o.base.pos : pos, o.soil ? o.base.rot : rot, restCarry)\n objects.set(id, rest)\n objects.set(nid, fresh)\n return nid\n },\n hit(objectId, h) {\n const im = impls.get(objectId)\n if (im) return whole(() => (h.type === 'explosive' ? blastImpl(im, h) : implHit(im, h)))\n const o = getObj(objectId)\n return whole(() => doHit(o, h))\n },\n hitPart(objectId, partId, h) {\n const im = impls.get(objectId)\n if (im) return whole(() => implHit(im, h))\n const o = getObj(objectId)\n const p = getPart(o, partId)\n return whole(() => doHit(o, h, p))\n },\n blastProbe() {\n return { ...blastProbe }\n },\n blastReach(point, target, options = {}) {\n const L = vec.distance(point, target)\n if (L < 1e-4) return 1\n const shelter: Required<ShelterOptions> = { ...SHELTER_DEFAULTS, ...options.shelter }\n const ignore = new Set(options.ignore ?? [])\n const d = vec.scale(vec.sub(target, point), 1 / L)\n let t = 1\n for (const o of objects.values()) {\n if (ignore.has(o.id) || raySphereMiss(point, d, toWorld(o.st.position, o.st.rotation, o.bc), o.br, L)) continue\n for (const p of o.parts) {\n if (isLost(p) || p.st.stripped) continue\n const r = rayPart(o, p, point, d)\n if (!r) continue\n const t0 = Math.max(r.t0, 0)\n const path = Math.min(r.t1, L) - t0\n if (path < shelter.minPath) continue\n // a hole the line goes through (a breached wall, an open window) lets the blast by\n if (p.st.opening && insideOpening(o, p, toLocal(o.st.position, o.st.rotation, vec.madd(point, d, t0 + path / 2)))) continue\n t *= Math.exp(-(p.mat.hpPerKg * p.mat.density * path * (p.mat.damageScale?.shelter ?? 1)) / shelter.k)\n if (t < 1e-4) return 0\n }\n }\n // hosted bodies (a vehicle): a part with a thickness is a shell, crossed through its two walls, not through the air inside it\n for (const im of impls.values()) {\n if (ignore.has(im.impl.id)) continue\n for (const ps of im.impl.describe().parts) {\n const mat = materials.get(ps.material)\n if (!mat) continue\n const ov = im.poses.get(ps.id)\n const r = rayPartRaw(im.position, im.rotation, ps, ov?.q ?? quatFromEuler(...(ps.rotation ?? [0, 0, 0])), point, d, ov?.pos)\n if (!r || r.t1 < 0 || r.t0 > L) continue\n let path = Math.min(r.t1, L) - Math.max(r.t0, 0)\n if (ps.thickness !== undefined && ps.thickness > 0) path = Math.min(path, 2 * ps.thickness)\n else if (path < shelter.minPath) continue\n t *= Math.exp(-(mat.hpPerKg * mat.density * path * (mat.damageScale?.shelter ?? 1)) / shelter.k)\n if (t < 1e-4) return 0\n }\n }\n return t\n },\n explode(point, energy, radius, source, blast) {\n blastProbe.partsTested = 0\n blastProbe.partsNear = 0\n return withCollapses(run(() => blastWorld(point, energy, radius, source, blast)))\n },\n raycast(origin, direction, maxDistance = Infinity) {\n const r = raycastInternal(origin, direction, maxDistance, undefined, false, true)\n return r ? { object: r.object, part: r.part, point: r.point, normal: r.normal, distance: r.distance } : null\n },\n sweepBox(box, direction, distance, options = {}) {\n const d = vec.normalize(direction)\n const ignored = options.ignore === undefined ? undefined : objects.get(options.ignore)\n // an object hosted by an impl (a vehicle) is ignored by its own parts too\n const hosted = options.ignore === undefined || ignored ? undefined : impls.get(options.ignore)\n const ignore = ignored\n ? new Set(ignored.parts.map((p) => `${ignored.id}\\0${p.spec.id}`))\n : hosted\n ? new Set(hosted.impl.describe().parts.map((p) => `${hosted.impl.id}\\0${p.id}`))\n : undefined\n let best: RayHit | null = null\n for (const origin of sweepOrigins(box, d, options.spacing ?? 0.2)) {\n const r = raycastInternal(origin, d, distance + SWEEP_BACK, ignore)\n if (!r || (best && r.distance >= best.distance)) continue\n best = { object: r.object, part: r.part, point: r.point, normal: r.normal, distance: Math.max(0, r.distance - SWEEP_BACK) }\n }\n return best\n },\n shoot(origin, direction, energy, caliber, source, round) {\n const extras: BallisticExtras = typeof round === 'number' ? { piercing: round } : round ?? {}\n return withCollapses(run(withBlow('ballistic', () => {\n const results: HitResult[] = []\n const d = vec.normalize(direction)\n const ignore = new Set<string>()\n let org = origin\n let E = energy\n for (let i = 0; i < 4 && E > 0; i++) {\n const rh = raycastInternal(org, d, Infinity, ignore, false, true)\n if (!rh) break\n const im = impls.get(rh.object)\n if (im) {\n // the penetration a weapon gives is for the muzzle energy: past each part the round goes through less\n const scaled = extras.penetration && E < energy ? { ...extras, penetration: Object.fromEntries(Object.entries(extras.penetration).map(([k, mm]) => [k, mm * (E / energy)])) } : extras\n const r = implHit(im, { type: 'ballistic', point: rh.point, part: rh.part, normal: rh.normal, direction: d, energy: E, caliber, ...scaled, ...(source !== undefined ? { source } : {}) })\n r.part = rh.part\n r.point = rh.point\n // the part says what the round keeps (a sheet takes little, a block all of it); else half, as before\n const left = r.events.find((e) => e.type === 'hole' && (e as { energyLeft?: number }).energyLeft !== undefined) as { energyLeft?: number } | undefined\n r.exitEnergy = r.penetrated ? (left?.energyLeft ?? E * 0.5) : 0\n results.push(r)\n ignore.add(`${im.impl.id}\\0${rh.part}`)\n if (!r.penetrated) break\n org = vec.madd(rh.point, d, Math.min(rh.pathLen, 0.05) + 0.001)\n E = r.exitEnergy\n continue\n }\n const o = getObj(rh.object)\n const p = getPart(o, rh.part)\n const start = cur.length\n const out = ballistic(o, p, rh.point, rh.normal, d, E, caliber, rh.pathLen, source, extras)\n results.push({ object: o.id, part: p.spec.id, point: rh.point, damage: out.damage, penetrated: out.penetrated, exitEnergy: out.exitEnergy, events: cur.slice(start) })\n ignore.add(`${o.id}\\0${p.spec.id}`)\n if (!out.penetrated || !out.exitPoint) break\n org = vec.madd(out.exitPoint, d, 0.001)\n E = out.exitEnergy\n }\n return results\n })))\n },\n disassemble(objectId, jointId, tool: ToolKind, dt) {\n const im = impls.get(objectId)\n if (im) return im.impl.disassemble ? im.impl.disassemble(jointId, tool, dt) : -1\n const o = getObj(objectId)\n const j = o.jointMap.get(jointId)\n if (!j || !j.spec.tools.includes(tool)) return -1\n if (j.st.open) return 1\n return run(() => {\n j.st.progress = Math.min(1, j.st.progress + (j.spec.seconds > 0 ? dt / j.spec.seconds : 1))\n if (j.st.progress >= 1 - 1e-9) j.st.progress = 1\n const step = Math.floor(j.st.progress * 10 + 1e-9)\n if (step > j.step || j.st.progress >= 1) {\n j.step = step\n emit({ ...base(o), type: 'disassemble_progress', joint: j.spec.id, tool, progress: j.st.progress })\n }\n if (j.st.progress >= 1) {\n j.st.open = true\n j.st.openedBy = 'tool'\n solveStructure(o)\n recomputeGroups(o)\n detachEvents(o, [j], 'tool')\n collapseCheck(o)\n }\n return j.st.progress\n }).value\n },\n workableJoints(objectId, tool) {\n const im = impls.get(objectId)\n if (im) {\n const spec = im.impl.describe()\n return im.impl.state().joints.filter((js) => {\n const j = (spec.joints ?? []).find((x) => (x.id ?? `${x.a}~${x.b}`) === js.id)\n return !js.open && !!j && (j.tools ?? JOINT_DEFAULTS[j.kind].tools).includes(tool)\n })\n }\n return getObj(objectId).joints.filter((j) => !j.st.open && j.spec.tools.includes(tool)).map((j) => j.st)\n },\n nearestJoint(objectId, point, maxDistance = 0.3, tool) {\n const im = impls.get(objectId)\n // Candidates: closed joints with their world position and whether `tool` can undo them.\n const cands: { st: JointState; d: number; ok: boolean }[] = []\n if (im) {\n const spec = im.impl.describe()\n for (const js of im.impl.state().joints) {\n if (js.open) continue\n const pos = implJointPos(im, js.a, js.b)\n const j = (spec.joints ?? []).find((x) => (x.id ?? `${x.a}~${x.b}`) === js.id)\n cands.push({ st: js, d: pos ? vec.distance(pos, point) : Infinity, ok: !!j && (j.tools ?? JOINT_DEFAULTS[j.kind].tools).includes(tool as ToolKind) })\n }\n } else {\n const o = getObj(objectId)\n for (const j of o.joints) {\n if (j.st.open) continue\n cands.push({ st: j.st, d: vec.distance(jointWorld(o, j), point), ok: tool ? j.spec.tools.includes(tool) : true })\n }\n }\n const pick = (only: boolean): JointState | null => {\n let best: JointState | null = null\n let bd = maxDistance\n for (const c of cands) {\n if (only && !c.ok) continue\n if (c.d <= bd) {\n bd = c.d\n best = c.st\n }\n }\n return best\n }\n return (tool ? pick(true) : null) ?? pick(false)\n },\n extinguish(objectId, partId, coolC = 200) {\n const im = impls.get(objectId)\n if (im) {\n run(() => im.impl.extinguish?.(partId))\n return\n }\n const o = getObj(objectId)\n run(() => {\n for (const p of partId ? [getPart(o, partId)] : o.parts) {\n if (isLost(p)) continue\n if (p.st.burning) {\n p.st.burning = false\n p.rt.jet = false\n emit({ ...base(o), type: 'extinguish', part: p.spec.id })\n }\n p.st.temperature = Math.max(ambient, p.st.temperature - coolC)\n }\n o.active = true\n })\n },\n setWind(next) {\n windOpts = { ...windOpts, ...Object.fromEntries(Object.entries(next).filter(([, v]) => v !== undefined)) }\n windCfg = resolveWind(windOpts)\n for (const o of objects.values()) {\n if (!o.hasStructure || o.spec.wind === false) continue\n o.wind ??= newWind(o)\n o.dirty = true\n o.active = true\n }\n },\n vent(objectId, partId, opening = {}) {\n if (impls.has(objectId)) return false\n const o = getObj(objectId)\n const p = getPart(o, partId)\n const c = p.spec.contains\n if (!c || isLost(p) || (p.st.liters ?? 0) <= 0) return false\n if (p.st.holes.some((h) => h.vent)) return true\n return run(() => {\n const wp = opening.point ?? partXf(o, p).c\n const wn = vec.normalize(opening.normal ?? [0, 1, 0])\n const hole: Hole = { point: objLocal(o, wp), normal: objLocalDir(o, wn), diameter: opening.diameter ?? VENT_DIAMETER, through: true, vent: true }\n p.st.holes.push(hole)\n if (p.st.holes.length > maxHoles) p.st.holes.shift()\n o.active = true\n emit({\n ...base(o), type: 'leak', part: partId, fluid: c.fluid, point: wp,\n direction: c.outflow ? vec.normalize(rotateVec(o.st.rotation, rotateVec(p.q, c.outflow))) : wn, rate: holeRate(hole, !!c.pressurized), pressurized: !!c.pressurized,\n })\n return true\n }).value\n },\n seal(objectId, partId) {\n if (impls.has(objectId)) return 0\n const o = getObj(objectId)\n const p = getPart(o, partId)\n const before = p.st.holes.length\n p.st.holes = p.st.holes.filter((h) => !h.vent)\n o.active = true\n return before - p.st.holes.length\n },\n setLiters(objectId, partId, liters) {\n if (impls.has(objectId)) return\n const p = getPart(getObj(objectId), partId)\n if (!p.spec.contains) return\n p.st.liters = clamp(liters, 0, p.spec.contains.liters)\n getObj(objectId).active = true\n },\n update(dt) {\n if (!(dt > 0)) return []\n return run(() => {\n time += dt\n const sources: Array<{ o: ObjRT; p: PartRT; flame: number }> = []\n for (const o of [...objects.values()]) if (o.active) stepObject(o, dt, sources)\n for (const o of [...objects.values()]) if (o.soil && objects.get(o.id) === o) stepSoil(o, dt)\n for (const o of [...objects.values()]) if (o.wind && objects.get(o.id) === o) stepWind(o, dt)\n if (sources.length) {\n spread(sources, dt)\n igniteLeaksNearFire(sources, dt)\n }\n detonatePrimed(time)\n releaseFront()\n for (const im of [...impls.values()]) {\n if (!im.impl.update) continue\n for (const e of im.impl.update(dt) ?? []) emit(e.time === undefined ? { ...e, time } : e)\n }\n }).events\n },\n state: (id) => objects.get(id)?.st ?? impls.get(id)?.impl.state() ?? null,\n snapshot: (id) => {\n const st = objects.get(id)?.st ?? impls.get(id)?.impl.state()\n return st ? clone(st) : null\n },\n part: (id, partId) => objects.get(id)?.byId.get(partId)?.st ?? impls.get(id)?.impl.state().parts.find((p) => p.id === partId) ?? null,\n reset(id) {\n const im = impls.get(id)\n if (im) {\n im.impl.reset?.()\n return\n }\n const o = getObj(id)\n objects.set(id, build(o.spec, id, o.base.pos, o.base.rot))\n },\n on(type: DestructionEventType | '*', fn) {\n let set = listeners.get(type)\n if (!set) listeners.set(type, (set = new Set()))\n set.add(fn)\n return () => {\n set!.delete(fn)\n }\n },\n serialize(): DestructionSnapshot {\n return {\n version: 1,\n time,\n rng: rng.state(),\n counter,\n objects: [...objects.values()].map((o) => {\n const runtime: ObjectRuntime = { parts: {}, joints: {}, collapsed: [...o.collapsed], ...(o.soil?.sets.size ? { soil: Object.fromEntries(o.soil.sets) } : {}), ...(o.wind ? { wind: [o.wind.dyn.x, o.wind.dyn.v, o.wind.dyn.y, o.wind.dyn.w, o.wind.dyn.peak] as [number, number, number, number, number] } : {}) }\n for (const p of o.parts) runtime.parts[p.spec.id] = clone(p.rt)\n for (const j of o.joints) runtime.joints[j.spec.id] = j.step\n return { id: o.id, spec: clone(o.spec), state: clone(o.st), runtime }\n }),\n ...(impls.size\n ? { impls: [...impls.values()].map((im) => ({ id: im.impl.id, position: [...im.position] as Vec3, rotation: [...im.rotation] as Quat, data: im.impl.serialize?.() })) }\n : {}),\n }\n },\n load(snap) {\n if (snap.version !== 1) throw new Error(`unsupported snapshot version ${String(snap.version)}`)\n objects.clear()\n time = snap.time\n rng.set(snap.rng)\n counter = snap.counter ?? 0\n for (const e of snap.objects) {\n const state = clone(e.state)\n const carry: Carry = {\n parts: new Map(\n state.parts.map((st) => [st.id, { st, rt: e.runtime?.parts[st.id] ? clone(e.runtime.parts[st.id]) : { ...freshRuntime(), prevTemp: st.temperature } }]),\n ),\n joints: new Map(state.joints.map((st) => [st.id, { st, step: e.runtime?.joints[st.id] ?? 0 }])),\n collapsed: e.runtime?.collapsed,\n ...(e.runtime?.wind ? { wind: e.runtime.wind } : {}),\n }\n let pos = state.position, rot = state.rotation\n if (state.soil) {\n // the saved pose has the settlement on top of the host's: take it off to get the host's back\n carry.soil = state.soil\n if (e.runtime?.soil) carry.soilSets = e.runtime.soil\n rot = quat.normalize(quat.mul(state.rotation, quat.conjugate(state.soil.offset.rotation)))\n pos = vec.sub(state.position, rotateVec(rot, state.soil.offset.position))\n }\n objects.set(e.id, build(clone(e.spec), e.id, pos, rot, carry))\n }\n for (const e of snap.impls ?? []) {\n const im = impls.get(e.id)\n if (!im) continue\n im.position = [e.position[0], e.position[1], e.position[2]]\n im.rotation = [e.rotation[0], e.rotation[1], e.rotation[2], e.rotation[3]]\n if (e.data !== undefined) im.impl.load?.(e.data)\n }\n },\n }\n return world\n}\n","[\n {\n \"id\": \"brick_wall_plastered\",\n \"name\": \"Plastered brick wall\",\n \"core\": { \"material\": \"brick\", \"thickness\": 0.09 },\n \"layers\": [{ \"material\": \"plaster\", \"thickness\": 0.02, \"faces\": \"both\" }],\n \"units\": { \"size\": [0.23, 0.075, 0.11], \"bond\": \"running\", \"mortar\": \"plaster\" },\n \"breach\": { \"area\": 0.25 }\n },\n {\n \"id\": \"concrete_block_wall\",\n \"name\": \"Concrete block wall\",\n \"core\": { \"material\": \"concrete\", \"thickness\": 0.14 },\n \"fill\": 0.55,\n \"units\": { \"size\": [0.39, 0.19, 0.14], \"bond\": \"running\", \"mortar\": \"plaster\" },\n \"breach\": { \"area\": 0.25 }\n },\n {\n \"id\": \"reinforced_concrete\",\n \"name\": \"Reinforced concrete wall\",\n \"core\": { \"material\": \"concrete\", \"thickness\": 0.2 },\n \"reinforcement\": { \"material\": \"steel\", \"spacing\": 0.18, \"diameter\": 0.008, \"residualCapacity\": 0.15 },\n \"units\": { \"size\": [0.6, 0.42, 0.2], \"bond\": \"stack\", \"mortar\": \"concrete\" },\n \"breach\": { \"area\": 0.25 }\n },\n {\n \"id\": \"drywall\",\n \"name\": \"Drywall partition on steel studs\",\n \"core\": { \"material\": \"plaster\", \"thickness\": 0.0125 },\n \"layers\": [{ \"material\": \"plaster\", \"thickness\": 0.0125, \"faces\": \"+\" }],\n \"depth\": 0.095,\n \"breach\": { \"area\": 0.25 }\n },\n {\n \"id\": \"wood_frame_wall\",\n \"name\": \"Wood frame wall\",\n \"core\": { \"material\": \"plywood\", \"thickness\": 0.012 },\n \"layers\": [{ \"material\": \"plaster\", \"thickness\": 0.0125, \"faces\": \"-\" }],\n \"depth\": 0.1135,\n \"breach\": { \"area\": 0.25 }\n },\n {\n \"id\": \"log_wall\",\n \"name\": \"Log wall\",\n \"core\": { \"material\": \"wood_soft\", \"thickness\": 0.2 },\n \"fill\": 0.785,\n \"breach\": { \"area\": 0.25 }\n },\n {\n \"id\": \"sheet_metal_shack\",\n \"name\": \"Corrugated sheet metal wall\",\n \"core\": { \"material\": \"steel\", \"thickness\": 0.0006 },\n \"depth\": 0.02,\n \"breach\": { \"area\": 0.25 }\n },\n {\n \"id\": \"glass_pane\",\n \"name\": \"Glass pane\",\n \"core\": { \"material\": \"glass\", \"thickness\": 0.006 },\n \"breach\": { \"area\": 0.1 }\n }\n]\n","import { applyPatches, mergeById, removeIds } from '@adatechnology/game-contracts'\nimport type { DeepPartial } from '@adatechnology/game-contracts'\n\nimport assembliesJson from './data/assemblies.json'\nimport { MATERIALS } from './materials'\nimport type { MaterialDef, MaterialId, PartBreach, PartSpec, PartUnits, Reinforcement, SurfaceLayer, Vec3 } from './types'\n\n/**\n * A wall as a builder builds it: a core with coats, the masonry unit it is laid in, its rebar and when it breaches. Dimensions are metres (data in\n * `src/data/assemblies.json`); `assemblyPart` turns one into a `PartSpec`. Extend or override with `registerAssembly`.\n */\nexport interface AssemblyDef {\n id: string\n name: string\n /** `thickness` is the core's, in metres: what a bullet has to get through besides the coats. */\n core: { material: MaterialId; thickness: number }\n /** Coats, outermost first. */\n layers?: readonly SurfaceLayer[]\n /** Physical depth of the wall when it is not core plus coats (a drywall partition is mostly air between the boards). */\n depth?: number\n /** Solid fraction of the core (hollow blocks, round logs): scales its mass and the thickness a bullet crosses. Default 1. */\n fill?: number\n units?: PartUnits\n reinforcement?: Reinforcement\n breach?: PartBreach\n}\n\nexport interface AssemblyPartOptions {\n id: string\n /** Along the part's x axis. */\n width: number\n /** Along the part's y axis. */\n height: number\n position: Vec3\n rotation?: Vec3\n structure?: PartSpec['structure']\n /** Other `PartSpec` fields (tags, anchored, hp...). */\n extra?: Partial<PartSpec>\n /** Materials to read densities from (default the built-in `MATERIALS`). */\n materials?: ReadonlyMap<MaterialId, MaterialDef>\n}\n\n// What the JSON held at load, before any `registerAssembly` changed the shared list.\nconst SHIPPED: readonly AssemblyDef[] = structuredClone(assembliesJson as unknown as AssemblyDef[])\n\n/**\n * Built-in assemblies; `registerAssembly` adds to this list.\n * @deprecated the list every page shares. Use `createAssemblies({ packs, patch, remove })`, or `defaultAssemblies()` for this one.\n */\nexport const ASSEMBLIES: AssemblyDef[] = assembliesJson as unknown as AssemblyDef[]\n\nexport interface AssembliesOptions {\n /** Assemblies added to the built-in ones; one with the id of a built-in replaces it. */\n readonly packs?: readonly (readonly AssemblyDef[])[]\n /** Changes by id, merged field by field over what is there. */\n readonly patch?: Readonly<Record<string, DeepPartial<AssemblyDef>>>\n /** Ids taken out. */\n readonly remove?: readonly string[]\n}\n\nexport interface Assemblies {\n list(): readonly AssemblyDef[]\n get(id: string): AssemblyDef | undefined\n /** Adds an assembly, or replaces the one with the same id. */\n register(def: AssemblyDef): void\n /** The wall as a `PartSpec`; throws for an id this set does not have. */\n part(assemblyId: string, options: AssemblyPartOptions): PartSpec\n}\n\nconst assembliesOver = (defs: AssemblyDef[]): Assemblies => {\n const get = (id: string): AssemblyDef | undefined => defs.find((a) => a.id === id)\n return {\n list: () => defs,\n get,\n register(def) {\n const at = defs.findIndex((a) => a.id === def.id)\n if (at >= 0) defs[at] = def\n else defs.push(def)\n },\n part: (assemblyId, options) => buildAssemblyPart(get(assemblyId), assemblyId, options),\n }\n}\n\n/** A set of assemblies of its own: the built-in ones (copied) plus `packs`, `patch` and `remove`. Nothing is shared with any other set on the page. */\nexport const createAssemblies = (options: AssembliesOptions = {}): Assemblies => {\n const entries = mergeById(SHIPPED.map((def) => structuredClone(def)), (options.packs ?? []).flat())\n applyPatches(entries, options.patch)\n removeIds(entries, options.remove)\n return assembliesOver([...entries.values()])\n}\n\nlet defaultSet: Assemblies | undefined\n\n/** The set behind `ASSEMBLIES`, `registerAssembly`, `getAssembly` and `assemblyPart`, created on first use. */\nexport const defaultAssemblies = (): Assemblies => (defaultSet ??= assembliesOver(ASSEMBLIES))\n\n/** @deprecated use `createAssemblies(...).register`. */\nexport const registerAssembly = (def: AssemblyDef): void => defaultAssemblies().register(def)\n\n/** @deprecated use `createAssemblies(...).get`. */\nexport const getAssembly = (id: string): AssemblyDef | undefined => defaultAssemblies().get(id)\n\nconst faceCount = (layer: SurfaceLayer): number => (layer.faces === 'both' ? 2 : 1)\n\n/** Physical depth of the wall in metres. */\nexport const assemblyDepth = (def: AssemblyDef): number => def.depth ?? def.core.thickness + (def.layers ?? []).reduce((sum, l) => sum + l.thickness * faceCount(l), 0)\n\n/**\n * The wall as a box `[width, height, depth]` (thin along local z) with the assembly's layers, units, rebar and breach. Mass is the core (times `fill`)\n * plus the coats; `thickness` is the core's, so each coat adds its own `penetration x thickness` to what a bullet must cross.\n */\nconst buildAssemblyPart = (def: AssemblyDef | undefined, assemblyId: string, options: AssemblyPartOptions): PartSpec => {\n if (!def) throw new Error(`unknown assembly \"${assemblyId}\"`)\n const densityOf = (id: MaterialId): number => {\n const m = options.materials?.get(id) ?? MATERIALS.find((x) => x.id === id)\n if (!m) throw new Error(`unknown material \"${id}\" in assembly \"${assemblyId}\"`)\n return m.density\n }\n const fill = def.fill ?? 1\n const area = options.width * options.height\n const coreMass = area * def.core.thickness * fill * densityOf(def.core.material)\n const layerMass = (def.layers ?? []).reduce((sum, l) => sum + area * l.thickness * faceCount(l) * densityOf(l.material), 0)\n return {\n id: options.id,\n material: def.core.material,\n shape: { kind: 'box', size: [options.width, options.height, assemblyDepth(def)] },\n position: options.position,\n ...(options.rotation ? { rotation: options.rotation } : {}),\n mass: coreMass + layerMass,\n thickness: def.core.thickness * fill,\n ...(def.layers ? { layers: def.layers.map((l) => ({ ...l })) } : {}),\n ...(def.units ? { units: { ...def.units, size: [...def.units.size] as Vec3 } } : {}),\n ...(def.reinforcement ? { reinforcement: { ...def.reinforcement } } : {}),\n ...(def.breach ? { breach: { ...def.breach } } : {}),\n ...(options.structure ? { structure: options.structure } : {}),\n ...options.extra,\n }\n}\n\n/** @deprecated use `createAssemblies(...).part`. */\nexport const assemblyPart = (assemblyId: string, options: AssemblyPartOptions): PartSpec => defaultAssemblies().part(assemblyId, options)\n","import type { DestructibleSpec, JointSpec, MaterialId, PartSpec, PileSpec, Reinforcement, SoilProfile } from './types'\n\nexport interface FrameOptions {\n /** Total length along x between the outer column centres, metres (default 8). */\n spanX?: number\n /** Total length along z (default 8). */\n spanZ?: number\n /** Columns along x (at least 2, default 3). */\n columnsX?: number\n /** Columns along z (at least 2, default 3). */\n columnsZ?: number\n /** Height of one floor from slab top to the underside of the next slab, metres (default 3). */\n height?: number\n /** Number of floors (default 1). */\n floors?: number\n /** Brick walls on every perimeter bay of every floor; the first bay of the ground floor on the -z side gets a door opening (default false). */\n walls?: boolean\n /** A thin roof slab resting on the top beams (default true); without it the top floor is open. */\n roof?: boolean\n columnSize?: number\n beamHeight?: number\n slabThickness?: number\n wallThickness?: number\n doorWidth?: number\n doorHeight?: number\n /** Material of foundations, columns, beams, slabs and roof (default `concrete`). */\n material?: MaterialId\n wallMaterial?: MaterialId\n /** Override the load capacity of every column, kg (see `PartState.load`). */\n columnCapacity?: number\n /**\n * Tension steel ratio of the beams and slabs (`structure.rebar.ratio`; default beams 1%, slabs and roof 0.5%, inside the ranges of NBR 6118);\n * `false` makes them plain concrete (they snap when they bend past cracking).\n */\n rebar?: { beam?: number; slab?: number } | false\n /** Side of the square pad under each column in metres (default 2.2 x `columnSize`), 0.3 m thick. */\n footing?: number\n /** One raft under the whole frame instead of a pad per column (`raft`, the footprint plus `footing` / 2 each side, 0.4 m thick). */\n raft?: boolean\n /** Piles under each pad (or under the raft): the pad becomes a pile cap. */\n piles?: PileSpec\n /**\n * Columns run from storey to storey: each one rests on the column below (through the slab, as a cast-in-place column does) instead of on the slab,\n * so the slab carries only its own floor. Default false (the column of each storey stands on the slab below, as before).\n */\n continuousColumns?: boolean\n /** Rebar cage of the columns (`PartSpec.reinforcement`; default none). A caged column carries `0.85 fck Ac + As fy` and its `rebar` joints are monolithic. */\n columnCage?: Reinforcement\n /** Thickness of the roof slab (default 0.75 x `slabThickness`; a flat roof that carries a screed and equipment is as thick as a floor). */\n roofThickness?: number\n /** The ground the frame stands on (`DestructibleSpec.soil`). */\n soil?: string | SoilProfile\n}\n\n/**\n * A parametric test structure: a grid of columns on foundations, beams between the column tops, one slab per floor (the last one a roof), and\n * optional brick walls with a door. Joints are explicit and directional: columns rest on foundations (or on the slab below) with `rebar`, beams on\n * columns, slabs on beams, the roof rests on the top beams, walls hang on their columns with `mortar`. Part ids: `foundation_i_j`, `column_f_i_j`,\n * `beam_x_f_i_j`, `beam_z_f_i_j`, `slab_f`, `roof`, `wall_*`, `door`. Ground is y = 0 (the top of the foundations).\n */\nexport const buildFrame = (o: FrameOptions = {}): DestructibleSpec => {\n const spanX = o.spanX ?? 8, spanZ = o.spanZ ?? 8\n const nx = Math.max(2, o.columnsX ?? 3), nz = Math.max(2, o.columnsZ ?? 3)\n const H = o.height ?? 3, floors = Math.max(1, o.floors ?? 1)\n const cs = o.columnSize ?? 0.3, bh = o.beamHeight ?? 0.3, bw = 0.2, T = o.slabThickness ?? 0.2, wt = o.wallThickness ?? 0.2\n const dw = o.doorWidth ?? 1, dh = o.doorHeight ?? 2.1\n const mat = o.material ?? 'concrete', wmat = o.wallMaterial ?? 'brick'\n const roof = o.roof ?? true\n const rebarOf = (kind: 'beam' | 'slab') => (o.rebar === false ? {} : { rebar: { ratio: o.rebar?.[kind] ?? (kind === 'beam' ? 0.01 : 0.005) } })\n const xs = Array.from({ length: nx }, (_, i) => -spanX / 2 + (i * spanX) / (nx - 1))\n const zs = Array.from({ length: nz }, (_, j) => -spanZ / 2 + (j * spanZ) / (nz - 1))\n const parts: PartSpec[] = []\n const joints: JointSpec[] = []\n const on = (a: string, b: string, kind: JointSpec['kind']) => joints.push({ id: `${a}~${b}`, a, b, kind, bears: 'a_on_b' })\n\n const pad = o.footing ?? cs * 2.2\n const pile = o.piles ? { pile: { ...o.piles } } : {}\n if (o.raft) {\n parts.push({\n id: 'raft', material: mat, shape: { kind: 'box', size: [spanX + pad, 0.4, spanZ + pad] }, position: [0, -0.2, 0],\n structure: { role: 'foundation', ...pile }, anchored: true,\n })\n } else {\n for (let i = 0; i < nx; i++) {\n for (let j = 0; j < nz; j++) {\n parts.push({\n id: `foundation_${i}_${j}`, material: mat, shape: { kind: 'box', size: [pad, 0.3, pad] }, position: [xs[i], -0.15, zs[j]],\n structure: { role: 'foundation', ...pile }, anchored: true,\n })\n }\n }\n }\n for (let f = 0; f < floors; f++) {\n const yb = f * (H + T)\n const top = yb + H\n const last = f === floors - 1\n const slabId = last && roof ? 'roof' : `slab_${f}`\n for (let i = 0; i < nx; i++) {\n for (let j = 0; j < nz; j++) {\n const id = `column_${f}_${i}_${j}`\n parts.push({\n id, material: mat, shape: { kind: 'box', size: [cs, H, cs] }, position: [xs[i], yb + H / 2, zs[j]],\n structure: o.columnCapacity === undefined ? { role: 'column' } : { role: 'column', capacity: o.columnCapacity },\n ...(o.columnCage ? { reinforcement: { ...o.columnCage } } : {}),\n })\n on(id, f === 0 ? (o.raft ? 'raft' : `foundation_${i}_${j}`) : o.continuousColumns ? `column_${f - 1}_${i}_${j}` : `slab_${f - 1}`, 'rebar')\n }\n }\n const beams: string[] = []\n const beam = (id: string, size: [number, number, number], pos: [number, number, number], c1: string, c2: string) => {\n parts.push({ id, material: mat, shape: { kind: 'box', size }, position: pos, structure: { role: 'beam', ...rebarOf('beam') } })\n on(id, c1, 'rebar')\n on(id, c2, 'rebar')\n beams.push(id)\n }\n for (let j = 0; j < nz; j++) {\n for (let i = 0; i < nx - 1; i++) {\n beam(`beam_x_${f}_${i}_${j}`, [xs[i + 1] - xs[i] - cs, bh, bw], [(xs[i] + xs[i + 1]) / 2, top - bh / 2, zs[j]], `column_${f}_${i}_${j}`, `column_${f}_${i + 1}_${j}`)\n }\n }\n for (let i = 0; i < nx; i++) {\n for (let j = 0; j < nz - 1; j++) {\n beam(`beam_z_${f}_${i}_${j}`, [bw, bh, zs[j + 1] - zs[j] - cs], [xs[i], top - bh / 2, (zs[j] + zs[j + 1]) / 2], `column_${f}_${i}_${j}`, `column_${f}_${i}_${j + 1}`)\n }\n }\n const thick = last && roof ? o.roofThickness ?? T * 0.75 : T\n parts.push({\n id: slabId, material: mat, shape: { kind: 'box', size: [spanX + cs + 0.2, thick, spanZ + cs + 0.2] }, position: [0, top + thick / 2, 0],\n structure: { role: last && roof ? 'roof' : 'slab', ...rebarOf('slab') },\n })\n for (const b of beams) on(slabId, b, last && roof ? 'resting' : 'rebar')\n\n if (o.walls) {\n const wh = H - bh\n const wy = yb + wh / 2\n const wall = (id: string, size: [number, number, number], pos: [number, number, number], supports: string[]) => {\n parts.push({ id, material: wmat, shape: { kind: 'box', size }, position: pos, structure: { role: 'wall' } })\n for (const s of supports) on(id, s, 'mortar')\n }\n for (const j of [0, nz - 1]) {\n for (let i = 0; i < nx - 1; i++) {\n const c1 = `column_${f}_${i}_${j}`, c2 = `column_${f}_${i + 1}_${j}`\n const avail = xs[i + 1] - xs[i] - cs\n if (f === 0 && j === 0 && i === 0 && avail > dw + 0.4) {\n const side = (avail - dw) / 2\n const lx = xs[i] + cs / 2 + side / 2, rx = xs[i + 1] - cs / 2 - side / 2\n wall(`wall_door_left`, [side, wh, wt], [lx, wy, zs[j]], [c1])\n wall(`wall_door_right`, [side, wh, wt], [rx, wy, zs[j]], [c2])\n const lh = wh - dh\n wall(`wall_door_lintel`, [dw, lh, wt], [xs[i] + cs / 2 + side + dw / 2, yb + dh + lh / 2, zs[j]], ['wall_door_left', 'wall_door_right'])\n parts.push({ id: 'door', material: 'wood_hard', shape: { kind: 'box', size: [dw - 0.04, dh, 0.05] }, position: [xs[i] + cs / 2 + side + dw / 2, yb + dh / 2, zs[j]], tags: ['door'] })\n joints.push({ id: 'door~wall_door_left', a: 'door', b: 'wall_door_left', kind: 'hinge', bears: false })\n } else wall(`wall_x_${f}_${i}_${j}`, [avail, wh, wt], [(xs[i] + xs[i + 1]) / 2, wy, zs[j]], [c1, c2])\n }\n }\n for (const i of [0, nx - 1]) {\n for (let j = 0; j < nz - 1; j++) {\n wall(`wall_z_${f}_${i}_${j}`, [wt, wh, zs[j + 1] - zs[j] - cs], [xs[i], wy, (zs[j] + zs[j + 1]) / 2], [`column_${f}_${i}_${j}`, `column_${f}_${i}_${j + 1}`])\n }\n }\n }\n }\n return { name: 'frame', parts, joints, tags: ['structure'], ...(o.soil !== undefined ? { soil: o.soil } : {}) }\n}\n","import { createDestruction } from './world'\nimport { GRAVITY, bendGeometry, isFlexural, isReinforced, resolveFlexure, sectionMoments, sectionWidth, steelMoment, tensionSteel } from './flexure'\nimport { MATERIALS } from './materials'\nimport { shapeDims } from './math'\nimport { resolveWind, tensionCapacity } from './wind'\nimport type { DestructibleSpec, MaterialDef, SizeStructureOptions, StructureRole } from './types'\n\n/** Highest tension steel ratio a designer puts in a beam or slab (NBR 6118 17.3.5.2.4: 4% of the section). */\nconst MAX_REBAR_RATIO = 0.04\n\n/** The spec as the sizing worlds see it: the ground does not change the loads, so the soil is left out. */\nconst onRock = (spec: DestructibleSpec): DestructibleSpec => {\n if (spec.soil === undefined) return spec\n const { soil: _soil, ...rest } = spec\n return rest\n}\n\n/** The spec without one part (and its joints; inferred joints are inferred again without it). */\nconst without = (spec: DestructibleSpec, id: string): DestructibleSpec => {\n const reduced: DestructibleSpec = { ...spec, parts: spec.parts.filter((p) => p.id !== id), joints: (spec.joints ?? []).filter((j) => j.a !== id && j.b !== id) }\n if (!spec.joints) delete reduced.joints\n return reduced\n}\n\n/**\n * Sizes the tension steel of the reinforced beams, slabs, roofs and stairs of a structure (a `reinforcement` cage or a `structure.rebar`), the way\n * `sizeStructure` sizes the capacities: each one gets the `structure.rebar.ratio` that keeps its bending at rest (`PartState.flexure`) at `safety`\n * (`safetyByRole`) and, with `redundancy`, at most `redundancy` after the loss of any part of `redundancyRoles`. Steel is only added (up to 4% of the\n * section) and plain concrete stays plain: a beam the spec makes without steel is a beam without steel. Returns a copy.\n */\nexport const sizeRebar = (spec: DestructibleSpec, options: SizeStructureOptions = {}): DestructibleSpec => {\n const flexure = resolveFlexure(options.flexure)\n const materials = new Map<string, MaterialDef>(MATERIALS.map((m) => [m.id, m]))\n for (const m of options.materials ?? []) materials.set(m.id, m)\n const out = structuredClone(spec)\n const targets = out.parts.filter((p) => {\n const m = materials.get(p.material)\n return p.shape.kind === 'box' && !!m && isReinforced(p) && isFlexural(p, m, flexure)\n })\n if (targets.length === 0) return out\n const safety = options.safety ?? 0.65\n const safetyOf = (role: StructureRole): number => options.safetyByRole?.[role] ?? safety\n const bending = (s: DestructibleSpec): Map<string, number> => {\n const w = createDestruction({ ...(options.materials ? { materials: options.materials } : {}), structure: { flexure: options.flexure } })\n const id = w.add(onRock(s))\n return new Map(w.state(id)!.parts.map((p) => [p.id, p.flexure ?? 0]))\n }\n const base = bending(out)\n const factor = new Map(targets.map((p) => [p.id, (base.get(p.id) ?? 0) / safetyOf(p.structure!.role)]))\n if (options.redundancy !== undefined) {\n const roles: readonly StructureRole[] = options.redundancyRoles ?? ['column']\n for (const lost of out.parts) {\n if (!lost.structure || !roles.includes(lost.structure.role)) continue\n const l = bending(without(out, lost.id))\n for (const p of targets) if (p.id !== lost.id) factor.set(p.id, Math.max(factor.get(p.id)!, (l.get(p.id) ?? 0) / options.redundancy))\n }\n }\n for (const p of targets) {\n const f = factor.get(p.id)!\n const g = bendGeometry(p)\n if (f <= 1 || g.gravity < 0) continue\n const section = { b: sectionWidth(g, g.gravity), h: g.dims[g.gravity] }\n const steel = tensionSteel(p, g.dims, section, flexure)\n const m = materials.get(p.material)!\n const need = f * sectionMoments(m, section, steel, flexure).ultimate\n const momentOf = (area: number) => steelMoment(area, steel.yieldMPa, steel.d, section.b, m.strength!.compressiveMPa, flexure)\n // the smallest steel area whose moment reaches the need (the moment grows with the area), found by bisection, at most the 4% cap\n const cap = MAX_REBAR_RATIO * section.b * steel.d\n if (steel.area >= cap) continue\n let lo = steel.area, hi = cap\n if (momentOf(hi) > need) {\n for (let k = 0; k < 60; k++) {\n const mid = (lo + hi) / 2\n if (momentOf(mid) < need) lo = mid\n else hi = mid\n }\n }\n const ratio = hi / (section.b * steel.d)\n p.structure = { ...p.structure!, rebar: { ...p.structure!.rebar, ratio } }\n }\n return out\n}\n\n/**\n * Sizes the load capacity of a structure the way an engineer would, from the loads the world itself computes. The intact spec goes through the\n * same load solver `createDestruction` uses, and each structural part (`structure.role` other than `none`) gets `structure.capacity = load / safety`,\n * so its at-rest stress is exactly `safety` (`safetyByRole` overrides it per role). With `redundancy` set, every part whose role is in\n * `redundancyRoles` (default `column`) is also removed in turn and the capacity of the parts that would carry more is raised so they stay at or below\n * `redundancy`. Parts without `structure`, with role `none`, or with no support path to an\n * anchored part are left as they are. The spec is not modified; a copy is returned.\n */\nexport const sizeStructure = (spec: DestructibleSpec, options: SizeStructureOptions = {}): DestructibleSpec => {\n const safety = options.safety ?? 0.65\n const redundancy = options.redundancy\n const redundancyRoles: readonly StructureRole[] = options.redundancyRoles ?? ['column']\n const safetyOf = (role: StructureRole): number => options.safetyByRole?.[role] ?? safety\n const loads = (s: DestructibleSpec, wind?: SizeStructureOptions['wind']): Map<string, { load: number; stress: number; wind: number }> => {\n const w = createDestruction({ ...(options.materials ? { materials: options.materials } : {}), ...(wind ? { wind } : {}) })\n const id = w.add(onRock(s))\n return new Map(w.state(id)!.parts.map((p) => [p.id, { load: p.load ?? 0, stress: p.stress ?? 0, wind: p.wind ?? 0 }]))\n }\n const out = structuredClone(spec)\n const base = loads(out, options.wind)\n const gamma = options.wind ? resolveWind(options.wind).loadFactor : 0\n const need = new Map<string, number>()\n for (const p of out.parts) {\n if (!p.structure || p.structure.role === 'none') continue\n const b = base.get(p.id)\n if (!b || b.stress <= 0) continue\n // the wind adds its factored axial force to the dead load (compression side); on the tension side the bars are sized below\n need.set(p.id, (b.load + (b.wind > 0 ? (gamma * b.wind) / GRAVITY : 0)) / safetyOf(p.structure.role))\n }\n if (redundancy !== undefined) {\n for (const col of out.parts) {\n if (!col.structure || !redundancyRoles.includes(col.structure.role)) continue\n const reduced: DestructibleSpec = {\n ...out,\n parts: out.parts.filter((p) => p.id !== col.id),\n joints: (out.joints ?? []).filter((j) => j.a !== col.id && j.b !== col.id),\n }\n // joints are inferred when the spec has none; removing a part then removes its joints with it\n if (!out.joints) delete reduced.joints\n const l = loads(reduced)\n for (const [id, n] of need) {\n const r = l.get(id)\n if (r && r.stress > 0) need.set(id, Math.max(n, r.load / redundancy))\n }\n }\n }\n for (const p of out.parts) {\n const n = need.get(p.id)\n if (n !== undefined) p.structure = { ...p.structure!, capacity: n }\n }\n if (options.wind) {\n // a wall or column that the wind pulls past its dead load needs bars for the pull: thicker bars, to the 40 mm of NBR 7480\n const yieldMPa = resolveFlexure(options.flexure).rebarYieldMPa\n for (const p of out.parts) {\n const b = base.get(p.id)\n if (!b || b.wind >= 0 || !p.reinforcement || p.shape.kind !== 'box') continue\n const pull = (-(b.load + (gamma * b.wind) / GRAVITY) * GRAVITY)\n if (pull <= 0) continue\n const dims = shapeDims(p.shape)\n const have = tensionCapacity(dims, { reinforcement: p.reinforcement, yieldMPa })\n const want = pull / safetyOf(p.structure?.role ?? 'wall')\n if (have > 0 && want > have) p.reinforcement = { ...p.reinforcement, diameter: Math.min(0.04, p.reinforcement.diameter * Math.sqrt(want / have)) }\n }\n }\n return sizeRebar(out, options)\n}\n","import type { DamageType, DestructionEventType, FractureStyle, JointKind, PartStatus, StructureRole, ToolKind } from './types'\n\n/** Locales shipped with the package. Unknown locales fall back to `en`. */\nexport type DestructionLocale = 'en' | 'pt-BR'\n\nexport interface DestructionStrings {\n /** Display name per material id (see `MATERIALS`). Unknown ids are not listed. */\n materialNames: Record<string, string>\n partStatus: Record<PartStatus, string>\n jointKinds: Record<JointKind, string>\n toolKinds: Record<ToolKind, string>\n damageTypes: Record<DamageType, string>\n /** Short label per event type, for logs and kill-feed style text. */\n eventLabels: Record<DestructionEventType, string>\n fractureStyles: Record<FractureStyle, string>\n structureRoles: Record<StructureRole, string>\n}\n\nexport const locales: Record<DestructionLocale, DestructionStrings> = {\n en: {\n materialNames: {\n steel: 'steel', cast_iron: 'cast iron', aluminium: 'aluminium', copper: 'copper', wood_soft: 'softwood', wood_hard: 'hardwood', plywood: 'plywood',\n mdf: 'MDF', glass: 'glass', tempered_glass: 'tempered glass', ceramic: 'ceramic', concrete: 'concrete', brick: 'brick', plaster: 'plaster',\n stone: 'stone', plastic: 'plastic', rubber: 'rubber', fabric: 'fabric', foam: 'foam', leather: 'leather', paper: 'paper', foliage: 'foliage',\n green_wood: 'green wood', cactus: 'cactus', flesh_fruit: 'fruit', wax: 'wax', soil: 'soil', asphalt: 'asphalt', sand: 'sand', gravel: 'gravel', turf: 'turf', mortar: 'mortar', mud: 'mud', clay: 'dry clay', snow: 'snow', cobble: 'cobblestone', paver: 'concrete paver',\n },\n partStatus: { intact: 'intact', damaged: 'damaged', collapsed: 'collapsed', broken: 'broken', melted: 'melted', ashes: 'ashes' },\n jointKinds: {\n screw: 'screw', bolt: 'nut and bolt', nail: 'nail', weld: 'weld', glue: 'glue', hinge: 'hinge', clip: 'clip', tie: 'tie', mortar: 'mortar',\n fused: 'fused', stem: 'stem', rebar: 'rebar', resting: 'resting',\n },\n toolKinds: {\n hand: 'hand', screwdriver: 'screwdriver', wrench: 'wrench', pry_bar: 'pry bar', saw: 'saw', cutting_torch: 'cutting torch', knife: 'knife', hammer: 'hammer',\n },\n damageTypes: { ballistic: 'ballistic', blunt: 'blunt', slash: 'slash', explosive: 'explosive', fire: 'fire', heat: 'heat' },\n eventLabels: {\n damage: 'damage', dent: 'dent', hole: 'hole', crack: 'crack', ricochet: 'ricochet', debris: 'debris', fracture: 'broke', detach: 'came loose',\n disassemble_progress: 'taking apart', ignite: 'caught fire', extinguish: 'put out', burnout: 'burned to ash', melt: 'melting', drip: 'dripping',\n leak: 'leak', explode: 'exploded', primed: 'about to explode', stress: 'overload', collapse: 'collapsed', settle: 'ground gave way', sway: 'sway', spall: 'plaster came off', stage: 'damage stage', chip: 'brick knocked out', expose: 'rebar bare', body: 'body', blast: 'blast', fragment_hit: 'fragment hit', destroyed: 'destroyed',\n },\n fractureStyles: { shatter: 'shatter', crumble: 'crumble', splinter: 'splinter', tear: 'tear', snap: 'snap', none: 'none' },\n structureRoles: { foundation: 'foundation', column: 'column', beam: 'beam', slab: 'slab', wall: 'wall', partition: 'partition', roof: 'roof', stair: 'stairs', none: 'none' },\n },\n 'pt-BR': {\n materialNames: {\n steel: 'aço', cast_iron: 'ferro fundido', aluminium: 'alumínio', copper: 'cobre', wood_soft: 'madeira macia', wood_hard: 'madeira de lei',\n plywood: 'compensado', mdf: 'MDF', glass: 'vidro', tempered_glass: 'vidro temperado', ceramic: 'cerâmica', concrete: 'concreto', brick: 'tijolo',\n plaster: 'gesso', stone: 'pedra', plastic: 'plástico', rubber: 'borracha', fabric: 'tecido', foam: 'espuma', leather: 'couro', paper: 'papel',\n foliage: 'folhagem', green_wood: 'madeira verde', cactus: 'cacto', flesh_fruit: 'fruta', wax: 'cera', soil: 'terra', asphalt: 'asfalto', sand: 'areia', gravel: 'brita', turf: 'grama', mortar: 'argamassa', mud: 'lama', clay: 'barro seco', snow: 'neve', cobble: 'paralelepípedo', paver: 'bloquete',\n },\n partStatus: { intact: 'intacto', damaged: 'danificado', collapsed: 'desabado', broken: 'quebrado', melted: 'derretido', ashes: 'cinzas' },\n jointKinds: {\n screw: 'parafuso', bolt: 'porca e parafuso', nail: 'prego', weld: 'solda', glue: 'cola', hinge: 'dobradiça', clip: 'encaixe', tie: 'amarração',\n mortar: 'argamassa', fused: 'fundido', stem: 'caule', rebar: 'vergalhão', resting: 'apoiado',\n },\n toolKinds: {\n hand: 'mão', screwdriver: 'chave de fenda', wrench: 'chave inglesa', pry_bar: 'pé de cabra', saw: 'serra', cutting_torch: 'maçarico', knife: 'faca', hammer: 'martelo',\n },\n damageTypes: { ballistic: 'tiro', blunt: 'impacto', slash: 'corte', explosive: 'explosão', fire: 'fogo', heat: 'calor' },\n eventLabels: {\n damage: 'dano', dent: 'amassado', hole: 'furo', crack: 'trinca', ricochet: 'ricochete', debris: 'estilhaços', fracture: 'quebrou', detach: 'soltou',\n disassemble_progress: 'desmontando', ignite: 'pegou fogo', extinguish: 'apagou', burnout: 'virou cinza', melt: 'derretendo', drip: 'pingando',\n leak: 'vazamento', explode: 'explodiu', primed: 'prestes a explodir', stress: 'sobrecarga', collapse: 'desabou', settle: 'recalque do solo', sway: 'balanço', spall: 'reboco soltou', stage: 'estágio de dano', chip: 'tijolo arrancado', expose: 'vergalhão à mostra', body: 'corpo', blast: 'explosão', fragment_hit: 'estilhaço atingiu', destroyed: 'destruído',\n },\n fractureStyles: { shatter: 'estilhaçar', crumble: 'esfarelar', splinter: 'lascar', tear: 'rasgar', snap: 'partir', none: 'nenhuma' },\n structureRoles: { foundation: 'fundação', column: 'pilar', beam: 'viga', slab: 'laje', wall: 'parede', partition: 'divisória', roof: 'telhado', stair: 'escada', none: 'nenhum' },\n },\n}\n\nexport const resolveStrings = (locale: string | undefined): DestructionStrings => locales[(locale as DestructionLocale) ?? 'en'] ?? locales.en\n","import { checkDestructible as check } from '@adatechnology/game-contracts'\nimport type { CheckOptions as ContractCheckOptions, CostOptions, DestructibleImpl } from '@adatechnology/game-contracts'\nimport { MATERIALS } from './materials'\n\n// The contract itself lives in @adatechnology/game-contracts (a module depends only on that); re-exported here so that no import breaks.\nexport { IMPACT_CONTRACT, checkHit } from '@adatechnology/game-contracts'\nexport type { DestructibleImpl, ImpactContract } from '@adatechnology/game-contracts'\n\nexport interface CheckOptions {\n /** Ids of custom materials the impl uses besides the built-in `MATERIALS`. */\n materials?: string[]\n /** Opt-in cost measurement of `state()` and `describe()` (D8). */\n cost?: boolean | CostOptions\n}\n\n/**\n * `checkDestructible` of `@adatechnology/game-contracts`, with the built-in `MATERIALS` (plus `options.materials`) as the known material ids.\n * It hits the impl (and calls `reset()` afterwards when there is one).\n */\nexport const checkDestructible = (impl: DestructibleImpl, options: CheckOptions = {}): { ok: boolean; problems: string[] } => {\n const contractOptions: ContractCheckOptions = { materials: [...MATERIALS.map((m) => m.id), ...(options.materials ?? [])], ...(options.cost === undefined ? {} : { cost: options.cost }) }\n return check(impl, contractOptions)\n}\n"],"mappings":"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","names":["checkDestructible","n0","n1","a","c","t0","t1","dy","inside","sign","a","b","n","th","u","v","bar","s","definedOf","z","clamp","pos","world","nx","nz","lean","taken","crater","spread","bar","cells","dmg","options","checkDestructible"]}