@adatechnology/game-destruction 0.7.2 → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { Vec3, Quat, MaterialId, FractureStyle, DamageType, DebrisKind, DestructionEvent, BlastOptions, DestructibleSpec, ObjectState, DestructibleImpl, Hit, HitResult, RayHit, ToolKind, JointState, PartState, DestructionEventType, StructureRole, ConfinementOptions, FragmentHitOptions, ShelterOptions, ExplosionChain, PartSpec, JointKind, JointSpec, PartShape, SurfaceLayer, PartUnits, Reinforcement, PartBreach, PartStatus } from '@adatechnology/game-contracts';
2
- export { BlastOptions, BlastReport, ChainDelay, ConfinementOptions, Crack, DamageStage, DamageType, DebrisKind, Dent, DestructibleImpl, DestructibleSpec, DestructionEvent, DestructionEventType, ExplosionChain, FluidKind, FractureStyle, Fragment, FragmentHitOptions, FragmentMark, Hit, HitResult, Hole, IMPACT_CONTRACT, ImpactContract, JointKind, JointSpec, JointState, MaterialId, ObjectState, PartBreach, PartShape, PartSpec, PartState, PartStatus, PartUnits, Quat, RayHit, Reinforcement, ShelterOptions, StructureRole, SurfaceLayer, ToolKind, Vec3, checkHit } from '@adatechnology/game-contracts';
1
+ import { Vec3, Quat, MaterialId, FractureStyle, DamageType, DebrisKind, DestructionEvent, StructureRole, SoilProfile, WindExposure, IgnitionRules, BlastOptions, DestructibleSpec, ObjectState, DestructibleImpl, Hit, HitResult, RayHit, BallisticExtras, ToolKind, JointState, PartState, DestructionEventType, ConfinementOptions, FragmentHitOptions, ShelterOptions, ExplosionChain, PartSpec, JointKind, JointSpec, PartShape, SurfaceLayer, PartUnits, Reinforcement, PartBreach, PileSpec, PartStatus } from '@adatechnology/game-contracts';
2
+ export { BallisticExtras, BlastOptions, BlastReport, ChainDelay, ConfinementOptions, Crack, DamageStage, DamageType, DebrisKind, Dent, DestructibleImpl, DestructibleSpec, DestructionEvent, DestructionEventType, ExplosionChain, FluidKind, FractureStyle, Fragment, FragmentHitOptions, FragmentMark, Hit, HitIgnition, HitResult, Hole, IMPACT_CONTRACT, ImpactContract, JointKind, JointSpec, JointState, MaterialId, ObjectState, PartBreach, PartShape, PartSpec, PartState, PartStatus, PartUnits, PileSpec, Quat, RayHit, Reinforcement, ShelterOptions, SoilLayer, SoilProfile, SoilState, StructureRole, SurfaceLayer, TensionRebar, ToolKind, TunedMassDamper, Vec3, WindExposure, WindState, checkHit } from '@adatechnology/game-contracts';
3
3
 
4
4
  /**
5
5
  * Public types of @adatechnology/game-destruction.
@@ -46,6 +46,16 @@ interface MaterialDef {
46
46
  * through and keeps the rest; one that carries less stops (dent, crack or lodge).
47
47
  */
48
48
  penetration: number;
49
+ /**
50
+ * Which entry of `Hit.penetration` this material is measured by (`steel`, `concrete`, `brick`, `wood`; default its own id). A structural steel beam is
51
+ * `steel`, an aluminium sheet is `steel` too, softwood is `wood`.
52
+ */
53
+ penetrationClass?: string;
54
+ /**
55
+ * Millimetres of this material a round goes through for every millimetre of its `penetrationClass` reference in the table (default 1). Structural
56
+ * steel (S235) is softer than the RHA the tables use, so 1.3; softwood against hardwood 1.5; aluminium against steel 3.
57
+ */
58
+ penetrationScale?: number;
49
59
  /** 0 = brittle (glass), 1 = very ductile (soft steel). Ductile parts dent and bend before they break; brittle parts crack and shatter. */
50
60
  ductility: number;
51
61
  /** How the part fails when its hp reaches 0. */
@@ -77,6 +87,193 @@ interface MaterialDef {
77
87
  * softwood 100 000, steel 2 000 000). Default 20 000. See `PartSpec.structure`.
78
88
  */
79
89
  compressive?: number;
90
+ /**
91
+ * Engineering strengths of the material, in real units. When present they replace the game-tuned `compressive` for the capacity of the part and
92
+ * turn on the bending model of beams and slabs (`tensileMPa`). See `MaterialStrength`.
93
+ */
94
+ strength?: MaterialStrength;
95
+ }
96
+ /**
97
+ * Real strengths of a structural material (characteristic values). Concrete C25 (NBR 6118 / Eurocode 2): compressive 25, tensile 0.3 * fck^(2/3) = 2.56,
98
+ * elastic 5600 * sqrt(fck) = 28 GPa. Clay brick masonry (Eurocode 6, fk = 0.55 * fb^0.7 * fm^0.3 with fb 4 MPa, mortar M5): compressive 2.35.
99
+ */
100
+ interface MaterialStrength {
101
+ /** Characteristic compressive strength in MPa (fck of concrete, fk of a masonry wall). */
102
+ compressiveMPa: number;
103
+ /** Mean axial tensile strength in MPa (fctm of concrete). Without it the material does not take part in the bending model. */
104
+ tensileMPa?: number;
105
+ /** Modulus of elasticity in GPa (tangent at the origin, Eci, for the dynamic stiffness). */
106
+ elasticGPa?: number;
107
+ /**
108
+ * Masonry and plain concrete walls and pillars lose capacity with their slenderness and the unavoidable eccentricity of the load (`structure.masonry`).
109
+ * Default true for materials tagged `masonry` that are not reinforced.
110
+ */
111
+ slender?: boolean;
112
+ }
113
+ /** Bending of beams, slabs, roofs and stairs (`DestructionOptions.structure.flexure`). Every number is configurable; the defaults are real values. */
114
+ interface FlexureOptions {
115
+ /** Off: beams and slabs are checked in compression only, as before (default true). */
116
+ enabled?: boolean;
117
+ /** Roles the bending model applies to (default beam, slab, roof, stair). Only parts whose material has `strength.tensileMPa`. */
118
+ roles?: readonly StructureRole[];
119
+ /**
120
+ * Which beams and slabs the bending model takes. `rebar` (default): those that declare their tension steel in `structure.rebar` (a ratio of 0 is
121
+ * plain concrete). `reinforced`: also those with only a `reinforcement` cage, their steel taken from the cage. `all`: every one, and those with no
122
+ * steel at all are plain concrete. The default leaves structures made before this model as they were.
123
+ */
124
+ scope?: 'rebar' | 'reinforced' | 'all';
125
+ /** Factor alpha on the tensile strength for the cracking moment of a rectangular section, `Mr = alpha * fct * b * h^2 / 6` (NBR 6118 17.3.1: 1.5). */
126
+ crackFactor?: number;
127
+ /** Yield strength of the tension steel in MPa when the part does not say it (500: CA-50, NBR 7480). */
128
+ rebarYieldMPa?: number;
129
+ /** Cover from the tension face to the bar in metres when the part does not say it (0.03: NBR 6118 table 7.2, class II, beams). */
130
+ cover?: number;
131
+ /**
132
+ * Largest neutral axis depth over d of a ductile section (0.45: NBR 6118 14.6.4.3). Steel beyond it is taken as double reinforcement (it adds its
133
+ * pull times `d - d'`).
134
+ */
135
+ neutralAxisLimit?: number;
136
+ /** Support rotation in degrees at which a reinforced member fails under a blast (10: PDC-TR 06-08, hazardous damage of RC beams and slabs). */
137
+ failRotationDeg?: number;
138
+ /** Load factor of the equivalent one-degree-of-freedom system (0.64: Biggs 1964, simply supported, uniform load, elastic). */
139
+ loadFactor?: number;
140
+ /** Mass factor of the equivalent system (0.50: Biggs 1964, same case). */
141
+ massFactor?: number;
142
+ /** Joules per kilogram of TNT to turn a blast energy into a charge mass (4.184e6, the definition of the TNT equivalent). */
143
+ tntJoules?: number;
144
+ /** Incident impulse coefficient in Pa s m / kg^(2/3): `i = impulse * W^(2/3) / R` (200: Sadovsky). */
145
+ impulse?: number;
146
+ /** Reflected over incident impulse far from the charge (2: normal reflection of a weak shock). */
147
+ reflection?: number;
148
+ /** Rise of the reflection near the charge, in m/kg^(1/3): the factor is `reflection + reflectionNear / Z` (4: about 4 at Z = 2, 6 at Z = 1). */
149
+ reflectionNear?: number;
150
+ /** Smallest scaled distance in m/kg^(1/3) the impulse formula is used at; nearer, the breach model of the hit points takes over (0.5). */
151
+ nearScaled?: number;
152
+ }
153
+ /** Crushing of bearing walls and pillars of masonry or plain concrete (`DestructionOptions.structure.masonry`). */
154
+ interface MasonryOptions {
155
+ /** Unavoidable eccentricity of the load over the thickness (0.05: NBR 16868-1 and Eurocode 6 6.1.2.2): the capacity is times `1 - 2 * e`. */
156
+ minEccentricity?: number;
157
+ /** Slenderness `h / t` at which the capacity reaches zero in `1 - (lambda / limit)^3` (40: NBR 16868-1 reduction factor R). */
158
+ slendernessLimit?: number;
159
+ /** Share of the cross-section of concrete counted in the axial capacity of a reinforced pillar, `0.85 * fck` (0.85: NBR 6118 17.2.2). */
160
+ concreteFactor?: number;
161
+ }
162
+ /** What a soil is made of: decides the pile factors (Décourt-Quaresma) and the modulus correlation. */
163
+ type SoilKind = 'clay' | 'silt' | 'sand' | 'gravel' | 'rock';
164
+ /** A soil class of the registry (`SOILS`, `soils.json`): real allowable pressures and stiffness. Add or override them with `soil.soils`. */
165
+ interface SoilDef {
166
+ id: string;
167
+ kind: SoilKind;
168
+ /** Allowable pressure of a shallow footing in kPa (NBR 6122 basic pressures); the soil gives way at `allowableKPa * soil.safety`. */
169
+ allowableKPa: number;
170
+ /** SPT blow count N (NBR 6484), used for the pile resistance (Décourt-Quaresma). */
171
+ spt: number;
172
+ /** Young's modulus in MPa (Teixeira & Godoy: `alpha * K * N`). */
173
+ elasticMPa: number;
174
+ /** Poisson's ratio. */
175
+ poisson: number;
176
+ /** Ultimate pile resistances in kPa when they do not come from `spt` (rock): end bearing at the tip and skin friction on the shaft. */
177
+ pile?: {
178
+ tipKPa?: number;
179
+ skinKPa?: number;
180
+ };
181
+ }
182
+ /** The soil model. Every number has a real default; see `SOIL_DEFAULTS`. */
183
+ interface SoilOptions {
184
+ /** Extra or overriding soil classes (merged over `SOILS` by id). */
185
+ soils?: SoilDef[];
186
+ /** Profile for objects with foundations whose spec has no `soil` (default none: only objects with `soil` bear on the ground). */
187
+ site?: string | SoilProfile;
188
+ /** Global safety factor of a shallow footing: the soil gives way at this times the allowable pressure (3: NBR 6122). */
189
+ safety?: number;
190
+ /** Global safety factor of a pile (2: NBR 6122); `pileLength` sizes with it. */
191
+ pileSafety?: number;
192
+ /** Influence factor of a rigid footing in the elastic settlement `q B (1 - nu^2) Iw / E` (0.82: rigid square, Bowles). */
193
+ rigidity?: number;
194
+ /** Depth under a footing, in footing widths, whose soil it bears on (2: the stress bulb of a square footing). */
195
+ influence?: number;
196
+ /** Out-of-plumb of a building, radians (1/200: Eurocode 2 5.2 basic imperfection); it leans this way before any load. */
197
+ imperfection?: number;
198
+ /** Footing cells per side for the contact pressure (default 4). */
199
+ cells?: number;
200
+ /** Speed at which a yielding foundation sinks, in m/s of game time (0.05; the real thing takes hours to days). */
201
+ sinkRate?: number;
202
+ /** Speed at which a yielding object leans further, in degrees per second of game time (1.5). */
203
+ tiltRate?: number;
204
+ /** Width a footing has at least under a part that rests on a `terrain` foundation, metres (0.6: NBR 6122 minimum), unless the profile says. */
205
+ footingWidth?: number;
206
+ /** Young's modulus of the piles in GPa when the material has no `strength.elasticGPa` (25). */
207
+ pileElasticGPa?: number;
208
+ }
209
+ /** A terrain roughness category of the wind profile (`wind.terrains`, `WIND_TERRAIN`): NBR 6123 table 1 and the roughness length. */
210
+ interface WindTerrainDef {
211
+ id: string;
212
+ /** Gradient height in metres: the profile stops growing above it. */
213
+ zg: number;
214
+ /** Parameter `b` of the profile `S2 = b * Fr * (z / 10)^p`, by class of the building. */
215
+ b: {
216
+ A: number;
217
+ B: number;
218
+ C: number;
219
+ };
220
+ /** Exponent `p` of the profile, by class. */
221
+ p: {
222
+ A: number;
223
+ B: number;
224
+ C: number;
225
+ };
226
+ /** Roughness length in metres, for the turbulence intensity `1 / ln(z / z0)` (EN 1991-1-4 4.4). */
227
+ z0: number;
228
+ }
229
+ /**
230
+ * The wind. Every number has a real default; see `WIND_DEFAULTS`. The fields of `WindExposure` are the defaults for every object; an object's
231
+ * `DestructibleSpec.wind` replaces them for itself.
232
+ */
233
+ interface WindOptions extends WindExposure {
234
+ /** Basic wind speed V0 in m/s: the 3 s gust at 10 m over flat open ground, 50-year return (NBR 6123 isopleths; 40). */
235
+ speed?: number;
236
+ /** Direction the wind blows towards, in world space (the horizontal part is used; default `[1, 0, 0]`). */
237
+ direction?: Vec3;
238
+ /** Air density in kg/m³ (1.226: `q = 0.613 V^2`). */
239
+ airDensity?: number;
240
+ /** Lowest height the profile is evaluated at, metres (5: NBR 6123). */
241
+ minHeight?: number;
242
+ /** Height of one slice of the building, metres (3). */
243
+ bandHeight?: number;
244
+ /** Share of the gross stiffness the cracked structure keeps (0.8: NBR 6118 15.7.3). */
245
+ stiffnessFactor?: number;
246
+ /** Share of the gross stiffness the cracked beams keep (0.4: NBR 6118 15.7.3); they set how much the columns of a frame resist. */
247
+ beamFactor?: number;
248
+ /** Share of the span each side of the web that the slab adds to a beam as a flange (0.1: NBR 6118 14.6.2.2); 0 leaves the slab out of the frame. */
249
+ flange?: number;
250
+ /** Drift limit, top deflection over height (1/500). */
251
+ driftLimit?: number;
252
+ /** Factor on the wind in the strength checks of the parts and the overturning (1.4: NBR 8681 variable action). */
253
+ loadFactor?: number;
254
+ /** Count the axial stiffness of the columns in the bending of the whole building (false: a frame of shallow beams does not act as a tube). */
255
+ chord?: boolean;
256
+ /** Fraction of the design gust the 10-minute mean wind is (0.69: NBR 6123 chapter 9). */
257
+ meanRatio?: number;
258
+ /** Gust factor Fr of each class (NBR 6123 table 1: 1, 0.98, 0.95). */
259
+ gustFactor?: {
260
+ A: number;
261
+ B: number;
262
+ C: number;
263
+ };
264
+ /** Extra or overriding terrain categories (merged over `WIND_TERRAIN` by id). */
265
+ terrains?: WindTerrainDef[];
266
+ /** The gust in time: sines drawn from the Davenport spectrum (`components` of them up to `maxHz`, `scale` metres in `x = scale f / V10`, `seed` for the phases). */
267
+ gust?: {
268
+ components?: number;
269
+ maxHz?: number;
270
+ scale?: number;
271
+ seed?: number;
272
+ };
273
+ /** Seconds in which the recorded peak of the sway decays by a factor e (60). */
274
+ peakDecay?: number;
275
+ /** Tuning of a tuned mass damper that gives no frequency: `den-hartog` (harmonic force) or `warburton` (random force). */
276
+ tuning?: 'den-hartog' | 'warburton';
80
277
  }
81
278
  interface DestructionOptions {
82
279
  /** Extra or overriding materials (merged over `MATERIALS` by id). */
@@ -95,18 +292,43 @@ interface DestructionOptions {
95
292
  maxHoles?: number;
96
293
  /** Distance at which a burning part heats parts of other objects, in metres (default 0.6). */
97
294
  fireSpread?: number;
295
+ /**
296
+ * The structure solver. A slab or beam is held by the sum of the capacities of what it rests on: its load is shared among the supports that are
297
+ * left, so losing columns moves the load to the rest and the structure falls when the capacity left (the sum) is less than the load.
298
+ * The capacity of each part is `structure.capacity`, else the material's `compressive` (kg/m², in `MaterialDef`) times its section.
299
+ */
300
+ structure?: {
301
+ /**
302
+ * Multiplies every load before it is compared with the capacities: stress = `load * safetyFactor / capacity` (default 1). Above 1 the whole
303
+ * structure is loaded harder than its capacities were sized for (a worn building, a weaker material); below 1 it has extra margin. It does not
304
+ * change the capacities; to size them use `sizeStructure({ safety })`.
305
+ */
306
+ safetyFactor?: number;
307
+ /** Bending of beams and slabs: the tension face cracks, the steel carries the pull, a member without steel snaps. See `FlexureOptions`. */
308
+ flexure?: FlexureOptions;
309
+ /** Crushing of bearing walls and pillars with slenderness. See `MasonryOptions`. */
310
+ masonry?: MasonryOptions;
311
+ };
312
+ /** The ground under objects that have `DestructibleSpec.soil` (or `soil.site`): settlement, tilt, bearing failure and piles. See `SoilOptions`. */
313
+ soil?: SoilOptions;
314
+ /**
315
+ * The wind of the world on every structure (default none: no wind). A lateral load that grows with height, the core and the frame that resist it, the
316
+ * sway of the top and tuned mass dampers. See `WindOptions`.
317
+ */
318
+ wind?: WindOptions;
319
+ /**
320
+ * What lights the flammable fluid that leaks from a container (a fuel tank, a jerrycan, a gas bottle). A round that goes through only makes a
321
+ * leak; it lights it only when `Hit.ignition` (a spark on metal), `Hit.incendiary` or `Hit.tracer` say so, by the chance of the round weighed by
322
+ * how full the container is; a burning part within `fireNear.radius` or a blast also lights it. See `IgnitionRules` of the contracts for every
323
+ * number and its default.
324
+ */
325
+ ignition?: Partial<IgnitionRules>;
98
326
  /** Breach of staged parts (see `PartSpec.breach`). */
99
327
  breach?: {
100
328
  /** Metres around a hit within which through damage adds up (default 0.55). */
101
329
  radius?: number;
102
330
  /** Multiplier of the breach area a blast makes over a blow of the same damage: a blast loads the whole crater (default 6). */
103
331
  blastFactor?: number;
104
- /**
105
- * Metres of reach per cube root of kilojoule: a blast only opens a breach in a part within `blastReach * cbrt(energy / 1000)` of the centre
106
- * (a hand grenade of 200 kJ: 0.7 m; 2 MJ: 1.5 m). Farther away it still damages, dents and cracks. Without it a falloff that is gentle over a
107
- * large radius let a grenade at 1 m cut a reinforced column in two. Default `Infinity` (off, so the goldens stay as they were); 0.12 is the value that matches real charges.
108
- */
109
- blastReach?: number;
110
332
  };
111
333
  /**
112
334
  * Speed of the blast front in m/s. A glass part at distance `d` from an explosion breaks `d / blastFrontSpeed` seconds later, in `update`
@@ -134,6 +356,18 @@ interface SizeStructureOptions {
134
356
  redundancy?: number;
135
357
  /** Extra or overriding materials, the same list given to `createDestruction`. */
136
358
  materials?: MaterialDef[];
359
+ /**
360
+ * Bending options of the world the spec will go into (`DestructionOptions.structure.flexure`). Reinforced beams and slabs (a `reinforcement` cage
361
+ * or `structure.rebar`) get the tension steel ratio they need: at rest at `safety` (per role) of their moment, and, with `redundancy`, after the loss
362
+ * of any part of `redundancyRoles`. Steel is only added, never removed, and plain concrete stays plain.
363
+ */
364
+ flexure?: FlexureOptions;
365
+ /**
366
+ * The wind the structure is designed for (the same `WindOptions` the world will have): each wall and column gets the capacity for its dead load
367
+ * plus the factored axial force the wind adds to it, at `safety`, and a reinforced one that the wind pulls past its dead load gets bars thick enough
368
+ * (to 40 mm) to hold the pull at `safety`. Beams and slabs do not change (the wind moment in the frame is not modelled).
369
+ */
370
+ wind?: WindOptions;
137
371
  }
138
372
  interface AddOptions {
139
373
  /** Object id (default a generated `obj_1`, `obj_2`...). */
@@ -181,7 +415,7 @@ interface DestructionWorld {
181
415
  /** Raycast against every part shape (world space). */
182
416
  raycast(origin: Vec3, direction: Vec3, maxDistance?: number): RayHit | null;
183
417
  /** Ballistic shot: raycast, hit, and continue through with the exit energy (up to 4 objects/parts). */
184
- shoot(origin: Vec3, direction: Vec3, energy: number, caliber: number, source?: string, piercing?: number): HitResult[];
418
+ shoot(origin: Vec3, direction: Vec3, energy: number, caliber: number, source?: string, round?: number | BallisticExtras): HitResult[];
185
419
  /**
186
420
  * Work on a joint with a tool for `dt` seconds (call every frame while the player holds the button). Returns the progress 0..1, or -1 when the
187
421
  * tool cannot undo this joint. At 1 the joint opens (`detach` with `by: 'tool'`).
@@ -218,6 +452,26 @@ interface DestructionWorld {
218
452
  * that drain or refill the part. Does nothing when the part has no `contains`.
219
453
  */
220
454
  setLiters(objectId: string, partId: string, liters: number): void;
455
+ /**
456
+ * Opens a through opening of `diameter` metres (default 8 mm) in a container part (`PartSpec.contains`) at a world point, as a valve or a tap does: the part leaks like it does from a bullet hole
457
+ * (a `leak` event, the level drops in `update`, gas lights from a flame and then burns or goes off by its `explodes.chain`) but nothing is damaged and no `hole` event is sent. `point` defaults to the part's
458
+ * centre and `normal` (the way the fluid leaves) to up. Returns false when the part holds nothing, is lost or the object is a registered impl; true when it is open (also when it already was).
459
+ */
460
+ vent(objectId: string, partId: string, opening?: {
461
+ point?: Vec3;
462
+ normal?: Vec3;
463
+ diameter?: number;
464
+ }): boolean;
465
+ /** Closes the openings `vent` made in a part; returns how many it closed. The leak stops (a gas jet that is burning goes out when the level reaches zero or the fluid no longer flows). */
466
+ seal(objectId: string, partId: string): number;
467
+ /**
468
+ * Change the wind of the world (`DestructionOptions.wind`) while playing: its speed and the direction it blows towards. Turns the wind on when the
469
+ * world was made without it.
470
+ */
471
+ setWind(wind: {
472
+ speed?: number;
473
+ direction?: Vec3;
474
+ }): void;
221
475
  /** Seconds since creation. */
222
476
  readonly time: number;
223
477
  }
@@ -233,6 +487,8 @@ interface PartRuntime {
233
487
  shockT: number;
234
488
  /** A leaking flammable fluid is burning on this part. */
235
489
  jet: boolean;
490
+ /** A spark, a flame or a blast reached the flammable fluid that leaks from this part: it burns (or goes off) at the next update. */
491
+ lit?: boolean;
236
492
  /** Seconds left before the next `stress` event. */
237
493
  stressT?: number;
238
494
  /** World time at which a primed explosive part goes off (`explodes.chain`). */
@@ -243,6 +499,8 @@ interface PartRuntime {
243
499
  breach?: Array<[number, number, number, number]>;
244
500
  /** Mass in kg that left the part in a breach. */
245
501
  removed?: number;
502
+ /** Plastic rotation in radians a reinforced beam or slab took in bending (blasts add it up; `flexure.failRotationDeg` breaks it). */
503
+ hinge?: number;
246
504
  }
247
505
  /** Opaque bookkeeping of an object (see `PartRuntime`). `joints` holds the last disassembly step reported per joint id. */
248
506
  interface ObjectRuntime {
@@ -250,6 +508,10 @@ interface ObjectRuntime {
250
508
  joints: Record<string, number>;
251
509
  /** Parts of groups that already reported a `collapse`. */
252
510
  collapsed?: string[];
511
+ /** Permanent settlement of the soil under each footing cell or pile that yielded (`DestructibleSpec.soil`), metres. */
512
+ soil?: Record<string, number>;
513
+ /** Sway of the top and of the tuned mass damper: `[x, v, y, w, peak]` (displacement and velocity of the building, of the damper, recorded peak). */
514
+ wind?: [number, number, number, number, number];
253
515
  }
254
516
  interface DestructionSnapshot {
255
517
  version: 1;
@@ -304,18 +566,6 @@ interface ExplosivePartOptions {
304
566
  */
305
567
  declare const explosivePart: (explosive: WorldExplosive, part: Omit<PartSpec, "explodes">, options?: ExplosivePartOptions) => PartSpec;
306
568
 
307
- /**
308
- * How well a bullet cuts through for its energy (`Hit.piercing`, the 6th argument of `shoot`). The material's `penetration` is joules per
309
- * millimetre for a hard bullet; soft lead deforms on steel and concrete and a core of hardened steel does better. A host that knows the kind
310
- * of the bullet (`CaliberDef.kind` of `@adatechnology/game-weapons`) takes the number from here, or replaces the tables with its own.
311
- *
312
- * Reference: a 12 ga slug (3000 J) does not go through 8 mm of mild steel, a .50 BMG (18000 J) goes through 20 mm and more.
313
- */
314
- declare const PIERCING_BY_KIND: Readonly<Record<string, number>>;
315
- /** Caliber ids whose bullet is lighter on the target than its kind says (a soft-core 5.56 ball does not go through a steel flange). */
316
- declare const PIERCING_BY_CALIBER: Readonly<Record<string, number>>;
317
- declare const piercingOf: (caliber: string, kind?: string) => number;
318
-
319
569
  /** Built-in materials (data in `src/data/materials.json`). Override or extend with the `materials` option of `createDestruction`. */
320
570
  declare const MATERIALS: MaterialDef[];
321
571
  /** Default joint strength (joint hit points), tools that undo it and seconds of tool work. */
@@ -344,10 +594,16 @@ declare const partThickness: (part: PartSpec) => number;
344
594
  */
345
595
  declare const inferJoints: (parts: PartSpec[], tolerance?: number, materials?: ReadonlyMap<string, MaterialDef>) => JointSpec[];
346
596
  /**
347
- * Load in kg a structural part carries before it fails: `structure.capacity`, else `material.compressive` (default 20 000 kg/m²) times the
348
- * section. The section is the product of the two smallest dimensions (thickness times longest dimension for slabs; thickness times horizontal length for walls); foundations get x10.
597
+ * Load in kg a structural part carries before it fails in compression: `structure.capacity`, else the section times the material's strength. The
598
+ * section is the product of the two smallest dimensions (thickness times longest dimension for slabs; thickness times horizontal length for walls);
599
+ * foundations get x10. With `material.strength` (real values) the strength is `compressiveMPa`: a slender masonry or plain concrete wall or pillar keeps
600
+ * `slendernessFactor` of it (the unavoidable eccentricity and its height over thickness), a reinforced pillar carries `0.85 * fck * Ac + As * fy`
601
+ * (NBR 6118). Without it, the game-tuned `material.compressive` (default 20 000 kg/m²).
349
602
  */
350
- declare const partCapacity: (part: PartSpec, material: MaterialDef) => number;
603
+ declare const partCapacity: (part: PartSpec, material: MaterialDef, options?: {
604
+ masonry?: MasonryOptions;
605
+ flexure?: FlexureOptions;
606
+ }) => number;
351
607
  /**
352
608
  * Multiplier of blunt damage on brittle parts (ductility < 0.3): up to x4.7 for fully brittle materials (glass, ceramic, stone), times a thinness
353
609
  * 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
@@ -431,6 +687,31 @@ interface FrameOptions {
431
687
  wallMaterial?: MaterialId;
432
688
  /** Override the load capacity of every column, kg (see `PartState.load`). */
433
689
  columnCapacity?: number;
690
+ /**
691
+ * 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);
692
+ * `false` makes them plain concrete (they snap when they bend past cracking).
693
+ */
694
+ rebar?: {
695
+ beam?: number;
696
+ slab?: number;
697
+ } | false;
698
+ /** Side of the square pad under each column in metres (default 2.2 x `columnSize`), 0.3 m thick. */
699
+ footing?: number;
700
+ /** One raft under the whole frame instead of a pad per column (`raft`, the footprint plus `footing` / 2 each side, 0.4 m thick). */
701
+ raft?: boolean;
702
+ /** Piles under each pad (or under the raft): the pad becomes a pile cap. */
703
+ piles?: PileSpec;
704
+ /**
705
+ * 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,
706
+ * so the slab carries only its own floor. Default false (the column of each storey stands on the slab below, as before).
707
+ */
708
+ continuousColumns?: boolean;
709
+ /** 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. */
710
+ columnCage?: Reinforcement;
711
+ /** 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). */
712
+ roofThickness?: number;
713
+ /** The ground the frame stands on (`DestructibleSpec.soil`). */
714
+ soil?: string | SoilProfile;
434
715
  }
435
716
  /**
436
717
  * 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
@@ -440,6 +721,13 @@ interface FrameOptions {
440
721
  */
441
722
  declare const buildFrame: (o?: FrameOptions) => DestructibleSpec;
442
723
 
724
+ /**
725
+ * Sizes the tension steel of the reinforced beams, slabs, roofs and stairs of a structure (a `reinforcement` cage or a `structure.rebar`), the way
726
+ * `sizeStructure` sizes the capacities: each one gets the `structure.rebar.ratio` that keeps its bending at rest (`PartState.flexure`) at `safety`
727
+ * (`safetyByRole`) and, with `redundancy`, at most `redundancy` after the loss of any part of `redundancyRoles`. Steel is only added (up to 4% of the
728
+ * section) and plain concrete stays plain: a beam the spec makes without steel is a beam without steel. Returns a copy.
729
+ */
730
+ declare const sizeRebar: (spec: DestructibleSpec, options?: SizeStructureOptions) => DestructibleSpec;
443
731
  /**
444
732
  * 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
445
733
  * same load solver `createDestruction` uses, and each structural part (`structure.role` other than `none`) gets `structure.capacity = load / safety`,
@@ -450,6 +738,233 @@ declare const buildFrame: (o?: FrameOptions) => DestructibleSpec;
450
738
  */
451
739
  declare const sizeStructure: (spec: DestructibleSpec, options?: SizeStructureOptions) => DestructibleSpec;
452
740
 
741
+ /**
742
+ * Real structural engineering of beams, slabs, walls and pillars: bending (the tension face cracks, the steel carries the pull, a member without
743
+ * 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.
744
+ */
745
+ /** Standard gravity, m/s². A physical constant. */
746
+ declare const GRAVITY = 9.81;
747
+ declare const FLEXURE_DEFAULTS: Required<FlexureOptions>;
748
+ declare const MASONRY_DEFAULTS: Required<MasonryOptions>;
749
+ /** Cracking moment of a rectangular section in N m: `alpha * fct * b * h^2 / 6` (NBR 6118 17.3.1). */
750
+ declare const crackingMoment: (tensileMPa: number, b: number, h: number, alpha?: number) => number;
751
+ /**
752
+ * 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
753
+ * `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
754
+ * concrete would crush first, so the steel beyond what balances the block is taken as paired with compression steel (double reinforcement, NBR 6118
755
+ * 17.2.4): it adds `T2 * (d - d')`, `d'` being the cover to the compression bars.
756
+ */
757
+ declare const steelMoment: (area: number, yieldMPa: number, d: number, b: number, compressiveMPa: number, options?: Pick<FlexureOptions, "neutralAxisLimit" | "cover">) => number;
758
+ /**
759
+ * 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)`.
760
+ */
761
+ declare const elasticEnergy: (moment: number, span: number, EI: number, loadFactor?: number) => number;
762
+ /** Inverse of `elasticEnergy`: the peak moment in N m a span reaches when it takes `energy` J elastically. */
763
+ declare const momentOfEnergy: (energy: number, span: number, EI: number, loadFactor?: number) => number;
764
+ /** 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). */
765
+ declare const impulseEnergy: (impulse: number, mass: number, options?: Pick<FlexureOptions, "loadFactor" | "massFactor">) => number;
766
+ /**
767
+ * 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
768
+ * `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
769
+ * 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`
770
+ * the distance is held at that scaled distance.
771
+ */
772
+ declare const blastImpulse: (tnt: number, distance: number, options?: Pick<FlexureOptions, "impulse" | "reflection" | "reflectionNear" | "nearScaled">) => number;
773
+ /**
774
+ * Share of the compressive strength a wall or pillar of height `h` and thickness `t` keeps: the unavoidable eccentricity `(1 - 2 e)` times the
775
+ * slenderness reduction `1 - (h / t / limit)^3` (NBR 16868-1), never below 0.
776
+ */
777
+ declare const slendernessFactor: (h: number, t: number, options?: MasonryOptions) => number;
778
+ /** A bending section: width `b`, depth `h` (along the bending), in metres. */
779
+ interface BendSection {
780
+ b: number;
781
+ h: number;
782
+ }
783
+ /** Tension steel of a section: area in m², effective depth in m, yield in MPa. */
784
+ interface TensionSteel {
785
+ area: number;
786
+ d: number;
787
+ yieldMPa: number;
788
+ }
789
+ /**
790
+ * 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
791
+ * (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.
792
+ */
793
+ declare const tensionSteel: (part: PartSpec, dims: Vec3, section: BendSection, options: Required<FlexureOptions>) => TensionSteel;
794
+ /**
795
+ * 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
796
+ * 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
797
+ * keep it in one piece; without steel it snaps).
798
+ */
799
+ interface SectionMoments {
800
+ cracking: number;
801
+ steel: number;
802
+ ultimate: number;
803
+ reinforced: boolean;
804
+ }
805
+ declare const sectionMoments: (material: MaterialDef, section: BendSection, steel: TensionSteel, options: Required<FlexureOptions>) => SectionMoments;
806
+ /** Static moment in N m at mid-span of a span `L` under a uniform load `w` (N/m): `w L^2 / 8`. */
807
+ declare const spanMoment: (w: number, span: number) => number;
808
+ /**
809
+ * 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
810
+ * 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
811
+ * 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.
812
+ */
813
+ interface BendGeometry {
814
+ dims: Vec3;
815
+ member: boolean;
816
+ /** Axes the span is measured along: `[long]` for a member, the two plane axes for a plate. */
817
+ spanAxes: number[];
818
+ /** Axes the part can bend along (its depth): the two cross axes of a member, the thickness of a plate. */
819
+ depthAxes: number[];
820
+ gravity: number;
821
+ up: Vec3;
822
+ }
823
+ declare const bendGeometry: (part: PartSpec) => BendGeometry;
824
+ /**
825
+ * 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
826
+ * 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
827
+ * 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.
828
+ */
829
+ declare const spanOf: (g: BendGeometry, contacts: ReadonlyArray<readonly [Vec3, Vec3]>, samples?: number) => number;
830
+ interface BearingWallOptions {
831
+ /** Storeys the wall carries, the ground floor included. */
832
+ storeys: number;
833
+ /** Height of one storey in metres. */
834
+ storeyHeight: number;
835
+ /** Load each floor puts on one metre of wall, in N/m (dead and live load of the floor's share). */
836
+ floorLoad: number;
837
+ /** Material of the wall (default the built-in `brick`): `strength.compressiveMPa` and `density`. */
838
+ material: Pick<MaterialDef, 'density' | 'strength'>;
839
+ /** Load factor (1.4: NBR 8681, permanent and variable loads). */
840
+ loadFactor?: number;
841
+ /** Material factor (2.0: NBR 16868-1, masonry). */
842
+ materialFactor?: number;
843
+ /** Thinnest bearing wall in metres (0.14: NBR 16868-1). */
844
+ minThickness?: number;
845
+ /** Thicknesses are rounded up to this many metres (0.01). */
846
+ step?: number;
847
+ masonry?: MasonryOptions;
848
+ }
849
+ /**
850
+ * 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
851
+ * walls above, times `loadFactor`) within `fk / materialFactor` times the slenderness factor of each storey's wall. `Infinity` when a storey cannot be
852
+ * carried at any thickness (the wall's own weight per storey already uses up the strength).
853
+ */
854
+ declare const bearingWallThickness: (options: BearingWallOptions) => number[];
855
+
856
+ /**
857
+ * 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)
858
+ * 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
859
+ * 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
860
+ * 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
861
+ * the edge of its foundations and it tips over.
862
+ */
863
+ /** Built-in soil classes (data in `src/data/soils.json`): NBR 6122 basic pressures, SPT N, moduli from Teixeira & Godoy. */
864
+ declare const SOILS: readonly SoilDef[];
865
+ declare const SOIL_DEFAULTS: {
866
+ readonly safety: 3;
867
+ readonly pileSafety: 2;
868
+ readonly rigidity: 0.82;
869
+ readonly influence: 2;
870
+ readonly imperfection: number;
871
+ readonly cells: 4;
872
+ readonly sinkRate: 0.05;
873
+ readonly tiltRate: 1.5;
874
+ readonly pileElasticGPa: 25;
875
+ readonly footingWidth: 0.6;
876
+ };
877
+ /** A profile from a soil class id or a profile. */
878
+ declare const profileOf: (soil: string | SoilProfile) => SoilProfile;
879
+ /** The layers of a profile that lie between two depths (metres below the surface), with the thickness of each inside that range. */
880
+ declare const layersBetween: (profile: SoilProfile, top: number, bottom: number, soils: ReadonlyMap<string, SoilDef>) => Array<{
881
+ soil: SoilDef;
882
+ thickness: number;
883
+ top: number;
884
+ }>;
885
+ /** The soil class at a depth (metres below the surface). */
886
+ declare const soilAt: (profile: SoilProfile, depth: number, soils: ReadonlyMap<string, SoilDef>) => SoilDef;
887
+ /** The soil a footing of width `width` at `depth` bears on: the weakest allowable pressure and the mean modulus over `influence` widths below it. */
888
+ declare const footingSoil: (profile: SoilProfile, depth: number, width: number, soils: ReadonlyMap<string, SoilDef>, influence?: number) => {
889
+ allowableKPa: number;
890
+ elasticMPa: number;
891
+ poisson: number;
892
+ };
893
+ /**
894
+ * 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
895
+ * 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.
896
+ */
897
+ declare const pileCapacity: (profile: SoilProfile, pile: PileSpec, top: number, soils: ReadonlyMap<string, SoilDef>) => {
898
+ tip: number;
899
+ skin: number;
900
+ ultimate: number;
901
+ tipSoil: SoilDef;
902
+ };
903
+ /**
904
+ * The shortest pile (to `step` metres) whose ultimate resistance over `safety` carries `load` newtons, going down from `top`; `maxLength` if none.
905
+ * This is how a designer takes a pile down to firm ground.
906
+ */
907
+ declare const pileLength: (profile: SoilProfile, o: {
908
+ load: number;
909
+ diameter: number;
910
+ top?: number;
911
+ method?: PileSpec["method"];
912
+ safety?: number;
913
+ step?: number;
914
+ maxLength?: number;
915
+ soils?: ReadonlyMap<string, SoilDef>;
916
+ }) => number;
917
+ /** 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)`). */
918
+ declare const pileStiffness: (pile: PileSpec, pileElasticGPa: number, tipElasticMPa: number, tipPoisson: number) => number;
919
+ /** 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. */
920
+ declare const subgradeModulus: (elasticMPa: number, poisson: number, width: number, rigidity?: number) => number;
921
+ /**
922
+ * 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.
923
+ */
924
+ declare const footingArea: (load: number, allowableKPa: number) => number;
925
+ /** One support of the object on the ground: a footing cell or a pile, at object-local `x, z`, `hx`/`hz` half its size. */
926
+ interface SoilSpring {
927
+ x: number;
928
+ z: number;
929
+ hx: number;
930
+ hz: number;
931
+ /** N/m. */
932
+ k: number;
933
+ /** Newtons it carries before it gives way. */
934
+ cap: number;
935
+ /** Permanent settlement of the soil under it from yielding, metres: it pushes back only past this (default 0). */
936
+ set?: number;
937
+ }
938
+ interface FoundationSolve {
939
+ /** Settlement at the centre of stiffness, metres. */
940
+ s: number;
941
+ /** Slopes of the base: the foundations go down `a` per metre of x and `b` per metre of z. */
942
+ a: number;
943
+ b: number;
944
+ /** An equilibrium was found and it is stable. */
945
+ stable: boolean;
946
+ /** Some spring is at its capacity in that equilibrium. */
947
+ yielded: boolean;
948
+ /** Weight over the sum of the capacities. */
949
+ bearing: number;
950
+ /** Largest force over capacity of a spring, 0..1. */
951
+ edge: number;
952
+ /** Residual of the vertical force and moments at the end, to tell which way an unstable object moves. */
953
+ residual: [number, number, number];
954
+ }
955
+ /** Centre of stiffness of the springs. */
956
+ declare const stiffnessCentre: (springs: readonly SoilSpring[]) => [number, number];
957
+ /**
958
+ * Equilibrium of a rigid object of weight `weight` (N) on elastic-perfectly-plastic springs that carry no tension, with its centre of mass at
959
+ * `(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).
960
+ * Newton iterations from `start`; where the tangent is not positive definite the elastic stiffness of the springs in contact is used instead.
961
+ */
962
+ declare const solveFoundation: (springs: readonly SoilSpring[], weight: number, xg: number, zg: number, height: number, imperfection: readonly [number, number], start?: {
963
+ s: number;
964
+ a: number;
965
+ b: number;
966
+ }) => FoundationSolve;
967
+
453
968
  /** Small vector helpers (arrays of three numbers). Pure functions; they allocate a new array. */
454
969
  declare const vec: {
455
970
  add: (a: Vec3, b: Vec3) => Vec3;
@@ -517,4 +1032,269 @@ declare const checkDestructible: (impl: DestructibleImpl, options?: CheckOptions
517
1032
  problems: string[];
518
1033
  };
519
1034
 
520
- export { ASSEMBLIES, type AddOptions, type AssemblyDef, type AssemblyPartOptions, CONFINEMENT_DEFAULTS, type ChainTrigger, type CheckOptions, type DestructionLocale, type DestructionOptions, type DestructionSnapshot, type DestructionStrings, type DestructionWorld, type ExplosivePartOptions, FIRE_PRIME_C, FRAGMENT_HIT_DEFAULTS, type FrameOptions, JOINT_BY_MATERIALS, JOINT_DEFAULTS, MATERIALS, type MaterialDef, type MaterialThermal, type ObjectRuntime, PIERCING_BY_CALIBER, PIERCING_BY_KIND, type PartRuntime, SHELTER_DEFAULTS, type SizeStructureOptions, type WorldExplosive, assemblyDepth, assemblyPart, buildFrame, checkDestructible, createDestruction, explosivePart, fragility, getAssembly, guessMaterial, inferJoints, locales, partCapacity, partMass, partThickness, partVolume, piercingOf, quat, quatFromEuler, registerAssembly, resolveStrings, rotateVec, sizeStructure, toLocal, toWorld, vec };
1035
+ /**
1036
+ * 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
1037
+ * its area, and the structure that resists it is the walls (a cantilever of composite section) working with the frame (storey shear stiffness) as
1038
+ * the wall-frame interaction of Heidebrecht & Stafford Smith. The same stiffness gives the first mode (Rayleigh), and a gust series moves the top
1039
+ * 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.
1040
+ */
1041
+ /** Built-in terrain categories (data in `src/data/wind-terrain.json`): NBR 6123 table 1 and the roughness lengths. */
1042
+ declare const WIND_TERRAIN: readonly WindTerrainDef[];
1043
+ declare const WIND_DEFAULTS: {
1044
+ readonly speed: 40;
1045
+ readonly direction: Vec3;
1046
+ readonly terrain: NonNullable<WindExposure["terrain"]>;
1047
+ readonly class: NonNullable<WindExposure["class"]>;
1048
+ readonly topography: 1;
1049
+ readonly statistical: 1;
1050
+ readonly drag: 1.3;
1051
+ readonly damping: 0.016;
1052
+ readonly airDensity: 1.226;
1053
+ readonly minHeight: 5;
1054
+ readonly bandHeight: 3;
1055
+ readonly stiffnessFactor: 0.8;
1056
+ readonly beamFactor: 0.4;
1057
+ readonly flange: 0.1;
1058
+ readonly driftLimit: number;
1059
+ readonly loadFactor: 1.4;
1060
+ readonly chord: false;
1061
+ readonly meanRatio: 0.69;
1062
+ readonly gustFactor: {
1063
+ readonly A: 1;
1064
+ readonly B: 0.98;
1065
+ readonly C: 0.95;
1066
+ };
1067
+ readonly gust: {
1068
+ readonly components: 400;
1069
+ readonly maxHz: 2;
1070
+ readonly scale: 1200;
1071
+ readonly seed: 1;
1072
+ };
1073
+ readonly peakDecay: 60;
1074
+ readonly tuning: NonNullable<WindOptions["tuning"]>;
1075
+ };
1076
+ type ResolvedWind = Required<Omit<WindOptions, 'terrains' | 'gustFactor' | 'gust' | 'direction'>> & {
1077
+ direction: Vec3;
1078
+ gustFactor: {
1079
+ A: number;
1080
+ B: number;
1081
+ C: number;
1082
+ };
1083
+ gust: {
1084
+ components: number;
1085
+ maxHz: number;
1086
+ scale: number;
1087
+ seed: number;
1088
+ };
1089
+ terrains: Map<string, WindTerrainDef>;
1090
+ };
1091
+ declare const resolveWind: (o?: WindOptions) => ResolvedWind;
1092
+ /** The world's wind with one object's `DestructibleSpec.wind` over it. */
1093
+ declare const exposureOf: (w: ResolvedWind, spec?: WindExposure | false) => ResolvedWind;
1094
+ /** 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). */
1095
+ declare const windPressure: (speed: number, density?: number) => number;
1096
+ /** Class of a building by its largest dimension (NBR 6123 table 1): `A` up to 20 m, `B` up to 50 m, `C` above. */
1097
+ declare const windClass: (largest: number) => "A" | "B" | "C";
1098
+ /**
1099
+ * 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
1100
+ * height of the category.
1101
+ */
1102
+ declare const heightFactor: (z: number, terrain: WindTerrainDef, cls: "A" | "B" | "C", o?: {
1103
+ gustFactor?: {
1104
+ A: number;
1105
+ B: number;
1106
+ C: number;
1107
+ };
1108
+ minHeight?: number;
1109
+ }) => number;
1110
+ /** The same profile for the 10-minute mean wind: no gust factor, times `meanRatio` (the share of the gust the mean is). */
1111
+ declare const meanHeightFactor: (z: number, terrain: WindTerrainDef, cls: "A" | "B" | "C", o?: {
1112
+ meanRatio?: number;
1113
+ minHeight?: number;
1114
+ }) => number;
1115
+ /** 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. */
1116
+ declare const turbulenceIntensity: (z: number, z0: number) => number;
1117
+ interface WallFrameSolution {
1118
+ /** Rotation `w'` at the n + 1 nodes. */
1119
+ psi: number[];
1120
+ /** Deflection at the nodes (0 at the base). */
1121
+ w: number[];
1122
+ }
1123
+ /**
1124
+ * 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
1125
+ * 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
1126
+ * `-(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
1127
+ * (`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`).
1128
+ */
1129
+ declare const solveWallFrame: (hb: readonly number[], ei: readonly number[], ga: readonly number[], V: readonly number[]) => WallFrameSolution;
1130
+ /** Shear at the n + 1 nodes of loads `f[j]` spread over each band (the load of the bands above, from the top). */
1131
+ declare const shearNodes: (f: readonly number[]) => number[];
1132
+ /** Moment at the n + 1 nodes from the shear at the nodes (linear inside each band, so the trapezoid is exact). */
1133
+ declare const momentNodes: (hb: readonly number[], V: readonly number[]) => number[];
1134
+ interface WindPartInput {
1135
+ /** Object-local box of the part (`aabbOf`). */
1136
+ min: Vec3;
1137
+ max: Vec3;
1138
+ /** `wall` and `column` resist, `beam` frames into the columns, `foundation` is the footprint, `other` only weighs and shows area. */
1139
+ kind: 'wall' | 'column' | 'beam' | 'foundation' | 'other';
1140
+ /** Young's modulus in Pa (walls, columns, beams). */
1141
+ elasticPa?: number;
1142
+ /** Mass in kg (what rests on it is counted by the parts that rest). */
1143
+ mass: number;
1144
+ /** A tuned mass damper: weighs, but is not part of the modal mass of the building. */
1145
+ damper?: boolean;
1146
+ /** Indices of the beams that frame into this column (closed joints). */
1147
+ beams?: readonly number[];
1148
+ /** Thickness of the slab that rests on this beam and works with it as a T section (0: none). */
1149
+ slab?: number;
1150
+ }
1151
+ /** Everything `analyzeWind` needs once it is resolved for one building (`ResolvedWind` with its terrain and direction). */
1152
+ interface WindCase {
1153
+ speed: number;
1154
+ /** Horizontal unit vector the wind blows towards, object-local `[x, z]`. */
1155
+ direction: readonly [number, number];
1156
+ terrain: WindTerrainDef;
1157
+ cls: 'auto' | 'A' | 'B' | 'C';
1158
+ topography: number;
1159
+ statistical: number;
1160
+ drag: number;
1161
+ damping: number;
1162
+ airDensity: number;
1163
+ minHeight: number;
1164
+ bandHeight: number;
1165
+ stiffnessFactor: number;
1166
+ beamFactor: number;
1167
+ flange: number;
1168
+ loadFactor: number;
1169
+ chord: boolean;
1170
+ meanRatio: number;
1171
+ gustFactor: {
1172
+ A: number;
1173
+ B: number;
1174
+ C: number;
1175
+ };
1176
+ }
1177
+ interface WindAnalysis {
1178
+ /** Height of the top above the ground and the class used. */
1179
+ height: number;
1180
+ cls: 'A' | 'B' | 'C';
1181
+ /** Largest width across the wind. */
1182
+ width: number;
1183
+ /** Band heights and the height of the middle of each above the ground. */
1184
+ bands: number[];
1185
+ mid: number[];
1186
+ /** Design force on each band, N, and the force of the 10-minute mean wind. */
1187
+ forces: number[];
1188
+ meanForces: number[];
1189
+ /** Design pressure at the top, N/m². */
1190
+ pressure: number;
1191
+ /** Design base shear (N) and overturning moment (N m). */
1192
+ shear: number;
1193
+ moment: number;
1194
+ /** Top deflection under the design wind (m), over the height, and under the mean wind. */
1195
+ deflection: number;
1196
+ drift: number;
1197
+ lean: number;
1198
+ /** Weight, N, and the overturning moment (factored) over the stabilizing moment `W e`. */
1199
+ weight: number;
1200
+ overturn: number;
1201
+ /** Share of the base moment the walls carry (the rest is the frame's couple). */
1202
+ wallShare: number;
1203
+ /** Bending and shear stiffness of each band (cracked). */
1204
+ ei: number[];
1205
+ ga: number[];
1206
+ /** First mode (Rayleigh): frequency in Hz, angular frequency, modal mass and stiffness, shape at the nodes. */
1207
+ frequency: number;
1208
+ omega: number;
1209
+ modalMass: number;
1210
+ modalStiffness: number;
1211
+ shape: {
1212
+ z: number[];
1213
+ phi: number[];
1214
+ };
1215
+ /** Modal force of the mean wind, N; turbulence intensity for the gust. */
1216
+ modalForce: number;
1217
+ intensity: number;
1218
+ /** Axial force the design wind adds to each input part, N (compression positive), without the load factor. */
1219
+ axial: number[];
1220
+ }
1221
+ /**
1222
+ * 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
1223
+ * centroid); the web alone when there is no flange.
1224
+ */
1225
+ declare const tBeamInertia: (bw: number, h: number, bf: number, tf: number) => number;
1226
+ /** The shape of the first mode at height `z` above the ground (linear between the nodes). */
1227
+ declare const shapeAt: (a: Pick<WindAnalysis, "shape">, z: number) => number;
1228
+ /**
1229
+ * 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.
1230
+ * Bands of `bandHeight`; a part gives to a band the share of itself that lies inside it.
1231
+ */
1232
+ declare const analyzeWind: (parts: readonly WindPartInput[], c: WindCase, ground: number) => WindAnalysis | null;
1233
+ /**
1234
+ * 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.
1235
+ * `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
1236
+ * force, `sqrt(1 - mu / 2) / (1 + mu)` and `sqrt(mu (1 - mu / 4) / (4 (1 + mu) (1 - mu / 2)))`.
1237
+ */
1238
+ declare const damperTuning: (mu: number, kind?: "den-hartog" | "warburton") => {
1239
+ frequency: number;
1240
+ damping: number;
1241
+ };
1242
+ /**
1243
+ * Amplitude of the structure under a harmonic force over its static deflection, with a damper: `r` the forcing frequency over the structure's,
1244
+ * `mu` the mass ratio, `g` the damper's frequency over the structure's, `damper` and `structure` the damping ratios. Solves
1245
+ * `[(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).
1246
+ */
1247
+ declare const damperAmplification: (r: number, mu: number, g: number, damper: number, structure?: number) => number;
1248
+ /** A gust series: sines of equal frequency spacing whose amplitudes follow the Davenport spectrum, normalized to unit variance. */
1249
+ interface Gust {
1250
+ freq: number[];
1251
+ amp: number[];
1252
+ phase: number[];
1253
+ }
1254
+ /**
1255
+ * 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)`,
1256
+ * `x = scale f / v10` (NBR 6123 chapter 9, Simiu & Scanlan), phases from the seed.
1257
+ */
1258
+ declare const makeGust: (v10: number, o: {
1259
+ components: number;
1260
+ maxHz: number;
1261
+ scale: number;
1262
+ seed: number;
1263
+ }) => Gust;
1264
+ /** The gust at time `t`: zero mean, unit variance. */
1265
+ declare const gustAt: (gust: Gust, t: number) => number;
1266
+ /** 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. */
1267
+ interface SwaySystem {
1268
+ M: number;
1269
+ K: number;
1270
+ C: number;
1271
+ damper?: {
1272
+ m: number;
1273
+ k: number;
1274
+ c: number;
1275
+ };
1276
+ }
1277
+ /** Displacement and velocity of the top, and of the damper's mass (absolute). */
1278
+ interface SwayState {
1279
+ x: number;
1280
+ v: number;
1281
+ y: number;
1282
+ w: number;
1283
+ }
1284
+ /** Advances `s` by `dt` seconds under the force `force(t)` (N, on the modal mass), RK4 with steps no longer than `maxStep`. */
1285
+ declare const stepSway: (s: SwayState, sys: SwaySystem, t: number, dt: number, force: (t: number) => number, maxStep?: number) => void;
1286
+ /**
1287
+ * 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,
1288
+ * else the tensile strength of its material times the section, else nothing (a masonry wall does not pull).
1289
+ */
1290
+ declare const tensionCapacity: (dims: Vec3, o: {
1291
+ reinforcement?: {
1292
+ spacing: number;
1293
+ diameter: number;
1294
+ };
1295
+ ratio?: number;
1296
+ yieldMPa: number;
1297
+ tensileMPa?: number;
1298
+ }) => number;
1299
+
1300
+ export { ASSEMBLIES, type AddOptions, type AssemblyDef, type AssemblyPartOptions, type BearingWallOptions, type BendGeometry, type BendSection, CONFINEMENT_DEFAULTS, type ChainTrigger, type CheckOptions, type DestructionLocale, type DestructionOptions, type DestructionSnapshot, type DestructionStrings, type DestructionWorld, type ExplosivePartOptions, FIRE_PRIME_C, FLEXURE_DEFAULTS, FRAGMENT_HIT_DEFAULTS, type FlexureOptions, type FoundationSolve, type FrameOptions, GRAVITY, type Gust, JOINT_BY_MATERIALS, JOINT_DEFAULTS, MASONRY_DEFAULTS, MATERIALS, type MasonryOptions, type MaterialDef, type MaterialStrength, type MaterialThermal, type ObjectRuntime, type PartRuntime, type ResolvedWind, SHELTER_DEFAULTS, SOILS, SOIL_DEFAULTS, type SectionMoments, type SizeStructureOptions, type SoilDef, type SoilKind, type SoilOptions, type SoilSpring, type SwayState, type SwaySystem, type TensionSteel, WIND_DEFAULTS, WIND_TERRAIN, type WallFrameSolution, type WindAnalysis, type WindCase, type WindOptions, type WindPartInput, type WindTerrainDef, type WorldExplosive, analyzeWind, assemblyDepth, assemblyPart, bearingWallThickness, bendGeometry, blastImpulse, buildFrame, checkDestructible, crackingMoment, createDestruction, damperAmplification, damperTuning, elasticEnergy, explosivePart, exposureOf, footingArea, footingSoil, fragility, getAssembly, guessMaterial, gustAt, heightFactor, impulseEnergy, inferJoints, layersBetween, locales, makeGust, meanHeightFactor, momentNodes, momentOfEnergy, partCapacity, partMass, partThickness, partVolume, pileCapacity, pileLength, pileStiffness, profileOf, quat, quatFromEuler, registerAssembly, resolveStrings, resolveWind, rotateVec, sectionMoments, shapeAt, shearNodes, sizeRebar, sizeStructure, slendernessFactor, soilAt, solveFoundation, solveWallFrame, spanMoment, spanOf, steelMoment, stepSway, stiffnessCentre, subgradeModulus, tBeamInertia, tensionCapacity, tensionSteel, toLocal, toWorld, turbulenceIntensity, vec, windClass, windPressure };