@adatechnology/game-weapons-three 0.11.2 → 0.12.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.
package/dist/index.d.ts CHANGED
@@ -1,681 +1,10 @@
1
- import { HostTool, HandPose, EffectSink, HostEvent, HandTargets, TestableModule, AreaPlacement, DestructionEvent, Hit, Vec3 as Vec3$1, ModuleControl, ModuleLayer, ModuleMetric, ModuleHost, TestableItem, DestructibleSpec, ToolClipSet } from '@adatechnology/game-contracts';
2
- import { CaliberDef, ReloadStageId, WeaponEvent, MountKind, AttachmentDef, FittedAttachment, Arsenal, ExplosiveDef, WeaponDef, CartridgeDims, CaseType, ReloadFamily } from '@adatechnology/game-weapons';
3
- import { AudioEngine } from '@adatechnology/game-audio';
1
+ import { I as ItemModels, W as WeaponProps, a as WeaponItemModel, M as ModelKit, b as WeaponModel, c as ModelParts, d as ModelFamily, A as AttachmentModelRegistry, L as LaserRaycast } from './testing-BlaMwqMW.js';
2
+ export { e as ARCHETYPE_MODELS, f as AttachmentBuildContext, g as AttachmentModel, h as AttachmentModelBuilder, C as CLASS_REFERENCE_ENERGY, i as COUNTER_ITEM_ID, D as DEFAULT_ENERGY_CURVE, j as DEFAULT_EXPLOSIVES_SCENE, k as DistanceCurve, E as EXPLOSIVES_AREA_ID, l as EXPLOSIVES_TEXT, m as EnergyCurve, n as ExplosivesRoom, o as ExplosivesScene, p as ExplosivesTestModuleOptions, q as ExplosivesText, F as FxLayers, G as GAME_DISTANCE_CURVE, r as GAME_SOUND_CLASSES, s as ItemModelRequest, t as MECHANICAL_SOUNDS, u as MODEL_ENTRIES, v as MOUNTED_M134_ITEM_ID, w as MechanicalSoundId, x as ModelEntry, y as ModelMaterials, z as ModelOptions, B as MountFrame, S as ShotExtras, H as ShotSound, J as ShotSoundClass, K as ShotSoundInput, N as ShotSoundOptions, O as SoundClassDef, P as SoundStep, Q as WEAPON_ITEM_PREFIX, R as WeaponAudio, T as WeaponAudioOptions, U as WeaponFx, V as WeaponFxOptions, X as WeaponsTestModuleOptions, Y as buildItemWeaponModel, Z as buildWeaponModel, _ as buildWeaponModelById, $ as computeShotSound, a0 as createExplosivesTestModule, a1 as createWeaponAudio, a2 as createWeaponFx, a3 as createWeaponsTestModule, a4 as defaultWeaponProps, a5 as deriveFrames, a6 as explosivesTextOf, a7 as hasWeaponModel, a8 as itemModelOfWeapon, a9 as mechanicalSoundOf, aa as modelKit, ab as mountFrame, ac as registerWeaponItemModel, ad as weaponsLayout } from './testing-BlaMwqMW.js';
4
3
  import * as THREE_NS from 'three';
5
-
6
- /** One sound of the game: [lowpass cutoff Hz, gain, seconds]. Literal from the `P` table of `sfx` in the game (jogo.js L62101-L62104). */
7
- type SoundClassDef = readonly [cutoff: number, gain: number, seconds: number];
8
- /** The game names are pistola, escopeta, fuzil, rifle, impacto, carne, passo, vidro, madeira, recarga, vazio and explosao. */
9
- declare const GAME_SOUND_CLASSES: {
10
- readonly pistol: readonly [1800, 0.9, 0.18];
11
- readonly shotgun: readonly [900, 1.2, 0.35];
12
- readonly rifle: readonly [1400, 1.1, 0.28];
13
- readonly long_rifle: readonly [1100, 1.3, 0.45];
14
- readonly impact: readonly [2500, 0.25, 0.05];
15
- readonly flesh: readonly [600, 0.35, 0.08];
16
- readonly step: readonly [400, 0.08, 0.05];
17
- readonly glass: readonly [5000, 0.5, 0.3];
18
- readonly wood: readonly [700, 0.5, 0.2];
19
- readonly reload: readonly [3000, 0.15, 0.06];
20
- readonly empty: readonly [4000, 0.12, 0.03];
21
- readonly explosion: readonly [200, 1.6, 1.4];
22
- };
23
- /** The four classes a shot can have: the game picks one by calibre (jogo.js L68697). */
24
- type ShotSoundClass = 'pistol' | 'shotgun' | 'rifle' | 'long_rifle';
25
- /** Distance muffling of the game (jogo.js L62092, L62105): `gain / (1 + d² × gainFalloff)`, `cutoff / (1 + d × cutoffFalloff)`, silent under `minGain`. */
26
- type DistanceCurve = {
27
- readonly gainFalloff: number;
28
- readonly cutoffFalloff: number;
29
- readonly minGain: number;
30
- };
31
- declare const GAME_DISTANCE_CURVE: DistanceCurve;
32
- /**
33
- * The calibre energy (joules) scales loudness, length and brightness around the class: each factor is `base + span × k`, where k goes from 0 (50 J)
34
- * to 1 (50 J × 10^spanDecades) on a log scale, divided by the same factor at the class reference energy. So the game calibres sound exactly as in
35
- * the game, and a lighter or heavier calibre of the same class is quieter and brighter, or louder and duller.
36
- */
37
- type EnergyCurve = {
38
- readonly floorJ: number;
39
- readonly spanDecades: number;
40
- readonly gain: readonly [base: number, span: number];
41
- readonly duration: readonly [base: number, span: number];
42
- readonly cutoff: readonly [base: number, span: number];
43
- /** The muzzle crack (high noise) and the body (low thump) follow the energy alone. */
44
- readonly crackGain: readonly [base: number, span: number];
45
- readonly bodyGain: readonly [base: number, span: number];
46
- readonly bodyDuration: readonly [base: number, span: number];
47
- readonly bodyFrequency: readonly [base: number, span: number];
48
- };
49
- declare const DEFAULT_ENERGY_CURVE: EnergyCurve;
50
- /** Muzzle energy of the game calibres in the SDK (9x19, 12ga_00buck × pellets, 7_62x39, 7_62x51): where a class sounds exactly as in the game. */
51
- declare const CLASS_REFERENCE_ENERGY: Readonly<Record<ShotSoundClass, number>>;
52
- type ShotSoundOptions = {
53
- /** Replaces or adds sound classes (the game table is the default). */
54
- readonly classes?: Readonly<Record<string, SoundClassDef>>;
55
- readonly distance?: Partial<DistanceCurve>;
56
- readonly energy?: Partial<EnergyCurve>;
57
- readonly referenceEnergy?: Partial<Record<ShotSoundClass, number>>;
58
- /** Picks the class of a shot; the default follows the game (shotgun by shell, handguns by category, then by energy). */
59
- readonly classOf?: (input: ShotSoundInput, energyJ: number) => ShotSoundClass;
60
- /** Class bands by energy (J): below `handgunBelowJ` a pistol, below `rifleBelowJ` a rifle, above that a long rifle. */
61
- readonly bands?: {
62
- readonly handgunBelowJ: number;
63
- readonly rifleBelowJ: number;
64
- };
65
- readonly suppressor?: {
66
- readonly gain: number;
67
- readonly cutoff: number;
68
- readonly crack: number;
69
- readonly body: number;
70
- };
71
- readonly indoors?: {
72
- readonly duration: number;
73
- readonly cutoff: number;
74
- };
75
- };
76
- type ShotSoundInput = {
77
- /** The calibre; its energy (× pellets) is used unless `energyJ` is given. */
78
- readonly caliber?: CaliberDef;
79
- readonly energyJ?: number;
80
- readonly category?: string;
81
- /** Metres from the listener, default 0. */
82
- readonly distance?: number;
83
- /** Master gain of the game `sfx` (its `vol`), default 1. */
84
- readonly volume?: number;
85
- readonly suppressed?: boolean;
86
- readonly indoors?: boolean;
87
- };
88
- type ShotSound = {
89
- readonly soundClass: ShotSoundClass;
90
- readonly energyJ: number;
91
- /** False when the shot is under the game's `minGain` at this distance: nothing is played. */
92
- readonly audible: boolean;
93
- /** The main noise burst: lowpass cutoff Hz, starting gain and the seconds of the exponential tail (to 0.001). */
94
- readonly cutoff: number;
95
- readonly gain: number;
96
- readonly duration: number;
97
- /** High noise burst of the muzzle. */
98
- readonly crack: {
99
- readonly gain: number;
100
- readonly cutoff: number;
101
- readonly duration: number;
102
- };
103
- /** Low thump that sweeps from `frequency` to `to`. */
104
- readonly body: {
105
- readonly gain: number;
106
- readonly frequency: number;
107
- readonly to: number;
108
- readonly duration: number;
109
- };
110
- };
111
- /**
112
- * The parameters of a gunshot, without WebAudio: the sound class and the distance muffling of the game (S2) with the calibre energy of the SDK.
113
- * Pure and deterministic; the playback layer only turns it into nodes.
114
- */
115
- declare const computeShotSound: (input: ShotSoundInput, options?: ShotSoundOptions) => ShotSound;
116
-
117
- /** One layer of a mechanical sound; `at` is seconds after the start. */
118
- type SoundStep =
119
- /** Metal click: a short high noise plus a square tone at 0.6 × the frequency (the SDK synth, as before). */
120
- {
121
- readonly layer: 'metal';
122
- readonly at: number;
123
- readonly frequency: number;
124
- readonly gain: number;
125
- }
126
- /** A sound class of the game (`recarga`, `vazio`...) played at a volume. */
127
- | {
128
- readonly layer: 'class';
129
- readonly at: number;
130
- readonly soundClass: keyof typeof GAME_SOUND_CLASSES;
131
- readonly volume: number;
132
- }
133
- /** Dull landing: lowpass noise. */
134
- | {
135
- readonly layer: 'thud';
136
- readonly at: number;
137
- readonly gain: number;
138
- readonly frequency: number;
139
- }
140
- /** The art scene's `sTone` (cena L1324): a tone sliding from `f` to `f2` (default `f`) in `d` seconds, at `vol`, `at` seconds after the start. */
141
- | {
142
- readonly layer: 'scene_tone';
143
- readonly at: number;
144
- readonly wave: 'sine' | 'square';
145
- readonly f: number;
146
- readonly f2?: number;
147
- readonly d: number;
148
- readonly vol: number;
149
- }
150
- /** The art scene's `sNoise` (cena L1323): filtered noise, the filter sliding to `f2` when given, `d` seconds, at `vol`. */
151
- | {
152
- readonly layer: 'scene_noise';
153
- readonly at: number;
154
- readonly type: 'lowpass' | 'highpass' | 'bandpass';
155
- readonly f: number;
156
- readonly f2?: number;
157
- readonly q: number;
158
- readonly d: number;
159
- readonly vol: number;
160
- };
161
- type MechanicalSoundId = ReloadStageId | 'dry_fire' | 'misfire' | 'feed' | 'cycle' | 'mode' | 'safety_on' | 'safety_off' | 'jam' | 'clear_start' | 'clear_end' | 'stock_fold' | 'light_click' | 'attach';
162
- /**
163
- * Sounds keyed by the rule: the `reload_stage` ids of `RELOAD_STAGES`, plus the other weapon events. The click of an empty weapon and the generic
164
- * reload tick are the game's `vazio` and `recarga` classes (jogo.js L62101-L62104; played at L68644-L68662). The Cena de Arte delivered the reload sounds
165
- * (`empty` -> dry_fire, `magOut` -> magazine_out, `magIn` -> magazine_in, `bolt` -> charge, `shell` -> round_in; cena L1339-L1343), so those use them; the gallery
166
- * (sources/armas-itens__galeria-3d-arsenal.js) has no sound, and the other metal layers are the SDK synth (the same `metal` used since the first version).
167
- */
168
- declare const MECHANICAL_SOUNDS: Readonly<Record<MechanicalSoundId, readonly SoundStep[]>>;
169
- /** Which mechanical sound a weapon event asks for, if any (`shot`, `draw` and `reload` start/end have their own handling). */
170
- declare const mechanicalSoundOf: (event: WeaponEvent) => MechanicalSoundId | undefined;
171
-
172
- var profiles = {
173
- weight: {
174
- light: {
175
- pitch: 1.3,
176
- gain: 0.85
177
- },
178
- medium: {
179
- pitch: 1,
180
- gain: 1
181
- },
182
- heavy: {
183
- pitch: 0.78,
184
- gain: 1.2
185
- }
186
- },
187
- material: {
188
- steel: {
189
- pitch: 1,
190
- gain: 1
191
- },
192
- polymer: {
193
- pitch: 0.82,
194
- gain: 0.8
195
- }
196
- }
197
- };
198
- var data = {
199
- profiles: profiles};
200
-
201
- /** How a weapon sounds: the weight of its metal (pitch and level) and what it is made of. */
202
- interface SoundProfile {
203
- readonly weight: keyof typeof data.profiles.weight;
204
- readonly material: keyof typeof data.profiles.material;
205
- }
206
-
207
- /** What a shot adds to the energy and the category: where the listener is and how the weapon is set. */
208
- type ShotExtras = Pick<ShotSoundInput, 'caliber' | 'distance' | 'volume' | 'suppressed' | 'indoors'>;
209
- interface WeaponAudioOptions extends ShotSoundOptions {
210
- /** Seed of the noise buffer, of the start point in it and of the casing pitch: same seed, same sound. Default 1. */
211
- readonly seed?: number;
212
- /** Replaces or adds mechanical sounds by id. */
213
- readonly mechanical?: Readonly<Partial<Record<MechanicalSoundId, readonly SoundStep[]>>>;
214
- /** Replaces or adds the sounds of the reload clip cues by id (`reload-sounds.json` has the ones the kit ships). */
215
- readonly reloadCues?: Readonly<Record<string, readonly SoundStep[]>>;
216
- /** Where the AudioContext comes from (default: the global one); lets a host or a test lend its own. Not used with `engine`. */
217
- readonly createContext?: () => AudioContext;
218
- /**
219
- * A sound engine the host already has (one shared engine mixes, limits and pans every module the same way). The weapon sounds are registered in it
220
- * and play on its `weapons` bus; `seed` gives them their own random stream, the master volume and the context stay the engine's. Without it the
221
- * weapon audio makes its own engine with the game mix, no voice limit, and the master at `volume`.
222
- */
223
- readonly engine?: AudioEngine;
224
- }
225
- /** Sounds the weapon presentation plays. */
226
- interface WeaponAudio {
227
- /** A shot: class and distance muffling of the game, loudness and body from the muzzle energy (joules). */
228
- shot(energyJ: number, category: string, extras?: ShotExtras): void;
229
- /** The parameters `shot` would play (pure). */
230
- shotSound(input: ShotSoundInput): ShotSound;
231
- /** Dry click of an empty weapon. */
232
- click(): void;
233
- /** A mechanical sound by id: a reload stage, `dry_fire`, `jam`, `safety_on`... */
234
- mechanical(id: MechanicalSoundId): void;
235
- /** A cue of a reload clip (`mag_seat`, `charging_handle_pull`, `pump_back`...) for a weapon's profile (the weight of its metal and what it is made of): played now, where the clip says. */
236
- cue(id: string, profile?: SoundProfile): void;
237
- /** The mechanical sound of a weapon event, if it has one (reload stages, empty, misfire, fault, clear, safety, mode, feed). */
238
- event(event: WeaponEvent): void;
239
- /** A sound class of the game by name (`impact`, `flesh`, `glass`...), with the game's distance muffling. */
240
- play(soundClass: string, volume?: number, distance?: number): void;
241
- /** Magazine out, or the first shell in. */
242
- reloadStart(category: string): void;
243
- /** Magazine seated and the action racked. */
244
- reloadEnd(category: string): void;
245
- /** The pump or lever cycling after a shot. */
246
- cycle(): void;
247
- /** A casing bouncing on the floor. */
248
- clink(): void;
249
- /** A magazine landing on the floor. */
250
- thud(): void;
251
- /** Master volume, 0 to 1. */
252
- setVolume(volume: number): void;
253
- dispose(): void;
254
- }
255
- declare function createWeaponAudio(volume?: number, options?: WeaponAudioOptions): WeaponAudio;
256
-
257
- /** What the bench turns on or off in the presentation of the weapon: the ejected casings, the dropped magazines, the muzzle flash, the accessory models and the light and laser beams. */
258
- interface FxLayers {
259
- casings: boolean;
260
- magazines: boolean;
261
- muzzleFlash: boolean;
262
- attachments: boolean;
263
- beams: boolean;
264
- }
265
-
266
- /** How the gallery builders describe a weapon: the short keys of `data/models.json` (the page's own option names), all optional. */
267
- interface ModelOptions {
268
- /** Total length and barrel length in mm, and the calibre text, as the weapons table gives them. */
269
- L?: number;
270
- B?: number;
271
- cal?: string;
272
- /** Pistol style (`glock`, `taurus`, `g2c`, `beretta`, `pt100`, `sig`, `cz`, `m1911`, `makarov`, `fiveseven`, `deagle`), slide height, grip length. */
273
- st?: string;
274
- h?: number;
275
- gl?: number;
276
- deagle?: number;
277
- /** Metal and furniture finish. */
278
- steel?: number;
279
- stain?: number;
280
- wood?: number;
281
- olive?: number;
282
- tan?: number;
283
- /** Selector or safety mark, cyclic rate (rpm), rounds in a burst, how unreliable (`rel`). */
284
- sel?: number;
285
- rpm?: number;
286
- burst?: number;
287
- rel?: number;
288
- /** Rifle layout. */
289
- stock?: string;
290
- stockLen?: number;
291
- hg?: string;
292
- hgFrac?: number;
293
- hR?: number;
294
- wR?: number;
295
- br?: number;
296
- grip?: string;
297
- gripAt?: number;
298
- mag?: string;
299
- magLen?: number;
300
- magAt?: number;
301
- magMat?: string;
302
- curve?: number;
303
- fore?: number;
304
- tubeLen?: number;
305
- scope?: number;
306
- brake?: number;
307
- ejectBack?: number;
308
- round?: number;
309
- ar?: number;
310
- ak?: number;
311
- g3?: number;
312
- charge?: number;
313
- rail?: number;
314
- jacket?: number;
315
- gas?: number;
316
- noFH?: number;
317
- carry?: number;
318
- bipod?: number;
319
- bolt?: number;
320
- lever?: number;
321
- tube?: number;
322
- pump?: number;
323
- heat?: number;
324
- /** Chambers of the revolver cylinder (default 6): the capacity of the weapon. */
325
- chambers?: number;
326
- bayo?: number;
327
- rod?: number;
328
- bands?: number;
329
- shot?: number;
330
- /** Launcher type: `rpg`, `m72`, `at4`, `carl`, `flame`, `flameDIY`. */
331
- lt?: string;
332
- }
333
- /**
334
- * Numbers the builders write down while they draw, in the space of `inner` (metres along the barrel, before `fitLength` stretches it): where the accessories go.
335
- * Written by the rifle and the M134 builders; the others get theirs measured from the model (`deriveFrames`).
336
- */
337
- interface ModelFrames {
338
- length: number;
339
- barrelY: number;
340
- barrelRadius: number;
341
- receiverStart: number;
342
- receiverEnd: number;
343
- receiverHeight: number;
344
- receiverWidth: number;
345
- handguardEnd: number;
346
- magazineX: number;
347
- gripX: number;
348
- /** The top rail is drawn (an optic sits on it without an adapter). */
349
- hasRail: boolean;
350
- /** Where the gun joins what is under the barrel (x, y), when the model has a place for it that the rule does not derive from the handguard. */
351
- underbarrel?: readonly [number, number];
352
- }
353
- /** The moving mechanism of a model, which picks its fire, reload and clear motion. */
354
- type ModelFamily = 'pistol' | 'revolver' | 'rifle' | 'semiint' | 'semi12' | 'p90' | 'belt' | 'pump' | 'lever' | 'bolt' | 'boltmag' | 'break' | 'rocket' | 'flame';
355
- /** The named parts a model exposes to the animation: pivots and marks inside the model, never copies. */
356
- interface ModelParts {
357
- family: ModelFamily;
358
- /** Recoil strength of the model (the page's `kick`). */
359
- kick?: number;
360
- /** How far the slide or bolt travels back, in metres. */
361
- stroke?: number;
362
- slide?: THREE_NS.Object3D;
363
- bolt?: THREE_NS.Object3D;
364
- boltHandle?: THREE_NS.Object3D;
365
- boltHandleRest?: number;
366
- mag?: THREE_NS.Object3D | null;
367
- /** How far a magazine drops, and `1` for one that goes up. */
368
- magDrop?: number;
369
- magDir?: number;
370
- trigger?: THREE_NS.Object3D;
371
- hammer?: THREE_NS.Object3D;
372
- lever?: THREE_NS.Object3D;
373
- pump?: THREE_NS.Object3D;
374
- belt?: THREE_NS.Object3D;
375
- cover?: THREE_NS.Object3D;
376
- crane?: THREE_NS.Object3D;
377
- cylinder?: THREE_NS.Object3D;
378
- chambers?: THREE_NS.Object3D[];
379
- barrels?: THREE_NS.Object3D;
380
- breech?: THREE_NS.Object3D[];
381
- /** The pivot of the pistol grip (its y runs along the grip, tilted as the grip is): the right hand holds here. Models without a drawn grip leave it out and the hand is placed from `frames`. */
382
- grip?: THREE_NS.Object3D;
383
- /** The existing selector or safety mesh; the gallery draws it but does not move it. */
384
- safety?: THREE_NS.Object3D;
385
- muzzle?: THREE_NS.Object3D;
386
- eject?: THREE_NS.Object3D;
387
- loadPort?: THREE_NS.Object3D;
388
- topLoad?: THREE_NS.Object3D;
389
- /** Parts that glow with barrel heat; each owns a clone of its material. */
390
- glow: THREE_NS.Mesh[];
391
- /** Launchers. */
392
- launcherType?: string;
393
- disposable?: boolean;
394
- rear?: THREE_NS.Object3D;
395
- round?: THREE_NS.Object3D;
396
- roundRest?: number;
397
- makeRound?: () => THREE_NS.Object3D;
398
- gauge?: THREE_NS.Object3D;
399
- /** Where the accessories go (see `ModelFrames`). */
400
- frames?: ModelFrames;
401
- /** The meshes of the stock the builder drew, in the order it drew them: `rigStock` moves them into one pivot. */
402
- stockMeshes?: THREE_NS.Object3D[];
403
- /** The stock pivot `rigStock` made, and how it moves. */
404
- stock?: THREE_NS.Object3D;
405
- stockMove?: StockMove;
406
- /** The meshes of each part that ships on the weapon, by accessory id (`red_dot`, `bipod`, `muzzle_brake`): taking the accessory off hides them. */
407
- fittings?: Record<string, THREE_NS.Object3D[]>;
408
- /** The pivot a launcher under the barrel sits in (made by `rigUnderbarrel`), and its muzzle mark once one is fitted. */
409
- ugl?: THREE_NS.Object3D;
410
- uglMuzzle?: THREE_NS.Object3D;
411
- }
412
- /** How the stock moves when it collapses: a slide of `travel` metres along the weapon (in `inner` units), or a half turn about `axis` (`foldAxis` of the rule). */
413
- interface StockMove {
414
- kind: 'fold' | 'retract';
415
- axis: 'x' | 'y' | 'z';
416
- travel: number;
417
- }
418
-
419
- /** One weapon of the gallery as `data/models.json` keeps it: the builder, the measures in mm and the builder's options. */
420
- interface ModelEntry {
421
- readonly builder: 'pistol' | 'revolver' | 'rifle' | 'bullpup' | 'p90' | 'break' | 'm2' | 'm134' | 'launcher';
422
- readonly caliber: string;
423
- readonly length: number;
424
- readonly barrel: number;
425
- readonly options: ModelOptions;
426
- readonly variantOf?: string;
427
- }
428
- declare const MODEL_ENTRIES: Readonly<Record<string, ModelEntry>>;
429
- /**
430
- * The model each generic archetype wears: the one of the first brand weapon (lowest id) that points to it with `archetype` and fires the same way (a rocket launcher that points to
431
- * `shotgun_pump_12` does not lend its tube to the shotgun). An archetype nothing points to, the melee weapons and the bow keep their simple prop.
432
- */
433
- declare const ARCHETYPE_MODELS: Readonly<Record<string, string>>;
434
- /** A weapon model: `root` (the page's `wr`) holds `inner` (what the builder made, fitted to the real length); `parts` are pivots and marks inside `inner`. */
435
- interface WeaponModel {
436
- readonly id: string;
437
- readonly root: THREE_NS.Group;
438
- readonly inner: THREE_NS.Group;
439
- readonly parts: ModelParts;
440
- }
441
- declare const hasWeaponModel: (id: string) => boolean;
442
- /** The gallery model of a weapon (or of the brand weapon an archetype wears, see `ARCHETYPE_MODELS`), long axis along +x, rear at the origin; undefined for melee, throwables and what nothing drew. */
443
- declare function buildWeaponModelById(THREE: typeof THREE_NS, id: string): WeaponModel | undefined;
444
-
445
- type Three = typeof THREE_NS;
446
- type Material = THREE_NS.Material;
447
- type Parent = THREE_NS.Object3D;
448
- declare const createMaterials: (THREE: Three) => {
449
- metal: THREE_NS.MeshStandardMaterial;
450
- steel: THREE_NS.MeshStandardMaterial;
451
- steelL: THREE_NS.MeshStandardMaterial;
452
- dark: THREE_NS.MeshStandardMaterial;
453
- poly: THREE_NS.MeshStandardMaterial;
454
- olive: THREE_NS.MeshStandardMaterial;
455
- tan: THREE_NS.MeshStandardMaterial;
456
- wood: THREE_NS.MeshStandardMaterial;
457
- woodL: THREE_NS.MeshStandardMaterial;
458
- brass: THREE_NS.MeshStandardMaterial;
459
- copper: THREE_NS.MeshStandardMaterial;
460
- lead: THREE_NS.MeshStandardMaterial;
461
- shell: THREE_NS.MeshStandardMaterial;
462
- glass: THREE_NS.MeshStandardMaterial;
463
- lens: THREE_NS.MeshStandardMaterial;
464
- rubber: THREE_NS.MeshStandardMaterial;
465
- white: THREE_NS.MeshStandardMaterial;
466
- hole: THREE_NS.MeshStandardMaterial;
467
- bake: THREE_NS.MeshStandardMaterial;
468
- rust: THREE_NS.MeshStandardMaterial;
469
- rustD: THREE_NS.MeshStandardMaterial;
470
- worn: THREE_NS.MeshStandardMaterial;
471
- fire: THREE_NS.MeshBasicMaterial;
472
- fire2: THREE_NS.MeshBasicMaterial;
473
- flashA: THREE_NS.MeshBasicMaterial;
474
- flashB: THREE_NS.MeshBasicMaterial;
475
- smokeP: THREE_NS.MeshStandardMaterial;
476
- /** Launcher paints. */
477
- yellow: THREE_NS.MeshStandardMaterial;
478
- red: THREE_NS.MeshStandardMaterial;
479
- redPaint: THREE_NS.MeshStandardMaterial;
480
- tape: THREE_NS.MeshStandardMaterial;
481
- pipe: THREE_NS.MeshStandardMaterial;
482
- green: THREE_NS.MeshStandardMaterial;
483
- /** Magazine finishes named by the options. */
484
- bakelite: THREE_NS.MeshStandardMaterial;
485
- polyMag: THREE_NS.MeshStandardMaterial;
486
- };
487
- type ModelMaterials = ReturnType<typeof createMaterials>;
488
- /**
489
- * The gallery's primitives on the host's three.js. Each takes the parent first and the position last as the page does (`box(parent, w, h, d, material, x, y, z, rz, ry, rx)`),
490
- * so that the builders read like the originals. `roundness` is the page's `RF`: how round the next boxes are, `null` for the default.
491
- */
492
- interface ModelKit {
493
- readonly THREE: Three;
494
- readonly M: ModelMaterials;
495
- roundness: number | null;
496
- group(): THREE_NS.Group;
497
- box(parent: Parent, w: number, h: number, d: number, material: Material, x: number, y: number, z: number, rz?: number, ry?: number, rx?: number): THREE_NS.Mesh;
498
- /** Cylinders along x, y and z. `radiusEnd` makes a cone. */
499
- cylinderX(parent: Parent, radius: number, length: number, material: Material, x: number, y: number, z: number, segments?: number, radiusEnd?: number): THREE_NS.Mesh;
500
- cylinderY(parent: Parent, radius: number, height: number, material: Material, x: number, y: number, z: number, segments?: number, radiusEnd?: number): THREE_NS.Mesh;
501
- cylinderZ(parent: Parent, radius: number, length: number, material: Material, x: number, y: number, z: number, segments?: number): THREE_NS.Mesh;
502
- sphere(parent: Parent, radius: number, material: Material, x: number, y: number, z: number, detail?: number): THREE_NS.Mesh;
503
- torus(parent: Parent, geometry: THREE_NS.TorusGeometry, material: Material, x: number, y: number, z: number): THREE_NS.Mesh;
504
- mark(parent: Parent, x: number, y: number, z: number): THREE_NS.Object3D;
505
- pivot(parent: Parent, x?: number, y?: number, z?: number): THREE_NS.Group;
506
- }
507
- /**
508
- * One kit per three.js namespace: the materials and the geometry cache are shared by every model built with it. The kit's `THREE` is
509
- * `shapeGeometries(host)`: box, cylinder, cone, sphere and torus come from game-shapes (the same bytes, the same classes); the rest is the host's.
510
- */
511
- declare function modelKit(host: Three): ModelKit;
512
-
513
- type Vec3 = [number, number, number];
514
- /** The shape of a model that carries its `inner` and `root` as `buildWeaponModelById` makes them. */
515
- interface FramedModel {
516
- readonly root: THREE_NS.Group;
517
- readonly inner: THREE_NS.Group;
518
- readonly parts: ModelParts;
519
- }
520
- /** Where an accessory of one kind of mount goes, in the space of the wrapper (`root`): the origin of its own frame and the sizes it needs from the weapon. */
521
- interface MountFrame {
522
- readonly mount: MountKind;
523
- readonly position: Vec3;
524
- /** The other end, for what stretches between two points (a sling between its swivels). */
525
- readonly secondary?: Vec3;
526
- readonly barrelRadius: number;
527
- readonly receiverWidth: number;
528
- readonly receiverHeight: number;
529
- /** The top rail is drawn: an optic needs no adapter. */
530
- readonly hasRail: boolean;
531
- /** The sign of z for a side rail: left is negative, right is positive (z is to the right of the weapon). */
532
- readonly side: -1 | 0 | 1;
533
- }
534
- /**
535
- * Frames for a model whose builder wrote none (pistols, revolvers, bullpups, launchers...): measured from the model as it is built, with `root` still at the origin.
536
- * The numbers are in the space of `inner`, like the ones the rifle builder writes.
537
- */
538
- declare function deriveFrames(THREE: typeof THREE_NS, model: FramedModel): ModelFrames;
539
- /** The frame of a mount of the model, or undefined for the mounts nothing is drawn on (`stock`, `barrel`). */
540
- declare function mountFrame(model: FramedModel, mount: MountKind): MountFrame | undefined;
541
-
542
- /** Distance in metres to what the ray hits, or null when it hits nothing within `maxDistance`: the host's raycast, which the laser asks every frame. */
543
- type LaserRaycast = (origin: THREE_NS.Vector3, direction: THREE_NS.Vector3, maxDistance: number) => number | null;
544
- /** What a builder is given: the accessory, where it sits on the weapon (`frame`, in the space of the wrapper) and the pieces of the model it may hang from or hide. */
545
- interface AttachmentBuildContext {
546
- readonly kit: ModelKit;
547
- readonly model: WeaponModel;
548
- readonly attachment: AttachmentDef;
549
- readonly fitted: FittedAttachment;
550
- readonly frame: MountFrame;
551
- readonly raycast: LaserRaycast | undefined;
552
- /** The meshes the magazine pivot had before any accessory (a drum or an extension replaces or extends them). */
553
- readonly factoryMagazine: readonly THREE_NS.Object3D[];
554
- /** The pivot of the launcher under the barrel, which the reload clip slides (only on a weapon with a place for one). */
555
- readonly slide: THREE_NS.Object3D | undefined;
556
- }
557
- /** What a builder makes: the object (its origin on the frame), and what the rig needs to know about it. */
558
- interface AttachmentModel {
559
- readonly object: THREE_NS.Object3D;
560
- /** Where the object hangs: the wrapper (default), the magazine pivot (it moves with the magazine) or the sliding pivot of the launcher. */
561
- readonly hangsFrom?: 'root' | 'magazine';
562
- /** Parts of the weapon that are not drawn while this one is on (a drum hides the magazine it replaces). */
563
- readonly hides?: readonly THREE_NS.Object3D[];
564
- /** How far forward the muzzle moves (a suppressor): the flash and the smoke come out of its end. */
565
- readonly muzzleOffset?: number;
566
- /** A launcher's muzzle mark, which the shot clip flashes. */
567
- readonly muzzle?: THREE_NS.Object3D;
568
- /** A light or laser turned on or off. */
569
- setOn?(on: boolean): void;
570
- /** Every frame, while the weapon is in the hands (the laser measures how far its beam goes). */
571
- update?(): void;
572
- dispose?(): void;
573
- }
574
- type AttachmentModelBuilder = (context: AttachmentBuildContext) => AttachmentModel | THREE_NS.Object3D | null;
575
- /** Builders by the `model` id of the accessory (`AttachmentDef.model`). A game replaces or adds one with `attachmentModels` of the weapons module. */
576
- type AttachmentModelRegistry = Readonly<Record<string, AttachmentModelBuilder>>;
577
-
578
- interface WeaponFxOptions {
579
- THREE: typeof THREE_NS;
580
- scene: THREE_NS.Scene;
581
- camera: THREE_NS.Camera;
582
- arsenal: Arsenal;
583
- /** Height things rest on at (x, z): casings and magazines land there. */
584
- groundAt: (x: number, z: number) => number;
585
- /** Sounds (`createWeaponAudio`); null or absent: silent. */
586
- audio?: WeaponAudio | null;
587
- /** Seed of the scatter of the effects of the gallery models. */
588
- seed?: number;
589
- /** The rocket of a launcher flies out of the viewmodel along the barrel (default true). A host that draws the projectile itself (the test room does) sets it to false, so one round flies, not two. */
590
- flyRocket?: boolean;
591
- /** The tool as it is now (barrel heat, fuel burning). */
592
- tool?: () => HostTool;
593
- /** Wear of the weapon: `new`, `used`, `worn` or `rusty`. */
594
- condition?: string;
595
- /** What is drawn: read at the moment of each event, so the bench can change it live. */
596
- layers?: FxLayers;
597
- /** Metres between the shooter and the listener, for the distance muffling of the shot sound (default 0). */
598
- soundDistance?: () => number;
599
- /** Told at every sound cue of a reload clip, at the moment the clip says it (also with no audio): the weapon, the cue id and the profile it sounds with. */
600
- onSound?: (cue: {
601
- weapon: string;
602
- cue: string;
603
- profile: SoundProfile;
604
- }) => void;
605
- /** Builders of accessory models that replace or add to the ones the kit ships (by the `model` of the accessory). */
606
- attachmentModels?: AttachmentModelRegistry;
607
- /** How far a laser beam goes from a point along a direction (metres), or null when it hits nothing: the dot lands where it ends. */
608
- raycast?: LaserRaycast;
609
- /** Where the world is (distance from a point along a direction to the first surface, or null): the weapon in the hands comes back from a wall it would go through. */
610
- contact?: LaserRaycast;
611
- /** Where the body holds the tool (`ModuleHost.holdFrame`): third person draws it there at its real size. */
612
- bodyHold?: () => HandPose | null;
613
- /** The host's effects: the muzzle flash, smoke, backblast and flame jet of the gallery models are recipes it plays; without it the viewmodel makes a world of its own for them. */
614
- effects?: EffectSink;
615
- }
616
-
617
- /** The weapon in the hands, its fire and reload motion, ejected casings and dropped magazines, and their sounds. */
618
- interface WeaponFx {
619
- /** Feed every tool event of the host, with the tool as it is after the event. */
620
- handle(event: HostEvent, tool: HostTool): void;
621
- update(dt: number): void;
622
- /** Dresses the weapon for its wear (`new`, `used`, `worn`, `rusty`); the gallery models show it in their metal. */
623
- setCondition(condition: string): void;
624
- /** Where the hands take the weapon (world space, read every frame after `update`): the grip and the forend of the model, or the handle of the generic prop; null with nothing in the hands. */
625
- handTargets(): HandTargets | null;
626
- /** What is drawn (casings, magazines, muzzle flash): change a field and the next event follows it. */
627
- readonly layers: FxLayers;
628
- /** Weapon shown in the hands, or null. */
629
- readonly inHand: string | null;
630
- /** The clips of the model playing now with the seconds each lasts (scaled to the rule's duration): which reload variant went (`reload` or `reload_empty`...). */
631
- readonly clips: ReadonlyArray<{
632
- name: string;
633
- seconds: number;
634
- }>;
635
- /** Casings and magazines currently on the floor or in the air. */
636
- readonly casings: number;
637
- readonly magazines: number;
638
- dispose(): void;
639
- }
640
- /**
641
- * The presentation of the tool in the hands. The weapons the gallery drew (`MODEL_ENTRIES`) get their model and the clips the rule's events call for
642
- * (fire, cycle, jam, clear, safety, the seven reloads); the generic archetypes keep their low-poly prop.
643
- */
644
- declare function createWeaponFx(options: WeaponFxOptions): WeaponFx;
645
-
646
- interface WeaponsTestModuleOptions {
647
- /** `en` or `pt-BR` (default). */
648
- locale?: string;
649
- /** The arsenal to lay out (default `createArsenal` with the locale). */
650
- arsenal?: Arsenal;
651
- /** Play sounds (default true; silent anyway where there is no AudioContext). */
652
- sound?: boolean;
653
- /** Wear of the weapon in the hands, which the gallery models show in their metal: `new` (default), `used`, `worn` or `rusty`. */
654
- condition?: string;
655
- /** Seed of the scatter of casings and smoke (default 1). */
656
- seed?: number;
657
- /** Builders of accessory models that replace or add to the ones the kit ships (by the `model` of the accessory). */
658
- attachmentModels?: AttachmentModelRegistry;
659
- /** Folder (ending with a slash) the weapon thumbnails are served from, relative to the page (default `weapon-svg/`); `false` leaves the items without a thumbnail. */
660
- thumbnailBase?: string | false;
661
- /** The rocket of a launcher flies out of the weapon in the hands (default true). A host that draws the projectile (the test room's `projectileModel`) passes false: one round flies. */
662
- flyRocket?: boolean;
663
- }
664
- /** Prefix of the item ids of the weapon props (`weapon_pistol_9mm`). */
665
- declare const WEAPON_ITEM_PREFIX = "weapon_";
666
- declare const COUNTER_ITEM_ID = "counter_weapons";
667
- declare const MOUNTED_M134_ITEM_ID = "m134_tripod";
668
- /** Where the counters go and where each weapon lies on them: weapons side by side across the counters in order, each taking its strip, until the counter is full. */
669
- declare function weaponsLayout(weaponItemIds: string[], pitchOf?: (itemId: string) => number): AreaPlacement[];
670
- /**
671
- * The weapons test area as a `TestableModule` of @adatechnology/game-contracts: every weapon of the arsenal on counters, the real model of each one the gallery drew (aim at one and
672
- * press H to equip it), targets at shooting distance, and, through `attach`, the weapon in the hands with its fire and reload motion,
673
- * ejected casings, dropped magazines and sounds, driven by the host's tool events.
674
- */
675
- declare function createWeaponsTestModule(options?: WeaponsTestModuleOptions): TestableModule & {
676
- readonly audio: WeaponAudio | null;
677
- readonly fx: WeaponFx | null;
678
- };
4
+ import { TestableItem, Vec3, HostEvent, EffectSink, DestructibleSpec, DeepPartial, ToolClipSet } from '@adatechnology/game-contracts';
5
+ import { ExplosiveDef, Arsenal, WeaponDef, CartridgeDims, CaliberDef, CaseType, ReloadFamily, FittedAttachment, AttachmentDef } from '@adatechnology/game-weapons';
6
+ import { LightBudget } from '@adatechnology/game-render-three';
7
+ import '@adatechnology/game-audio';
679
8
 
680
9
  /** Where a thumbnail came from: the model of the kit (`generated`) or a freely licensed drawing of the real weapon (`commons`, with its author and licence). */
681
10
  interface WeaponThumbnailEntry {
@@ -696,296 +25,6 @@ declare const DEFAULT_THUMBNAIL_BASE = "weapon-svg/";
696
25
  /** The URL of a weapon's thumbnail under `base` (which ends with a slash), or undefined when it has none. */
697
26
  declare function weaponThumbnailUrl(id: string, base?: string): string | undefined;
698
27
 
699
- /** The words of the explosives area (the P13 cylinder bench and its narration), by locale (`en` and `pt-BR`). `{name}` marks a value the module fills in. */
700
- interface ExplosivesText {
701
- group: string;
702
- name: string;
703
- cylinder: string;
704
- actions: Record<'shoot' | 'valve' | 'light' | 'fire' | 'reset', {
705
- name: string;
706
- hint: string;
707
- }>;
708
- blastScale: {
709
- name: string;
710
- hint: string;
711
- };
712
- layers: Record<'rings', string>;
713
- metrics: Record<'gas' | 'clock' | 'phase', string>;
714
- phases: Record<'rest' | 'leaking' | 'torch' | 'primed' | 'exploded', string>;
715
- rings: {
716
- lethal: string;
717
- injury: string;
718
- };
719
- triggers: Record<'shot' | 'fire' | 'explosion', string>;
720
- things: Record<string, string>;
721
- verdicts: {
722
- wall_pieces: string;
723
- lost_parts: string;
724
- dead: string;
725
- hurt: string;
726
- unhurt: string;
727
- wall_broken: string;
728
- wall_cracked: string;
729
- wall_intact: string;
730
- burning: string;
731
- standing: string;
732
- };
733
- log: {
734
- leak_shot: string;
735
- leak_valve: string;
736
- valve_closed: string;
737
- valve_closed_late: string;
738
- primed: string;
739
- jet_lit: string;
740
- jet_lit_by: string;
741
- lighter_none: string;
742
- lighter_lit: string;
743
- fire_set: string;
744
- heating: string;
745
- explode: string;
746
- shell: string;
747
- shell_landed: string;
748
- residual: string;
749
- aftermath_person: string;
750
- aftermath_wall: string;
751
- aftermath_object: string;
752
- reset: string;
753
- scale: string;
754
- no_room: string;
755
- shoot: string;
756
- no_vessel: string;
757
- };
758
- sheet: {
759
- kicker: string;
760
- title: string;
761
- body: string;
762
- facts: Record<'energy' | 'lethal' | 'injury' | 'gas' | 'mass' | 'torch' | 'shot_chain' | 'fire_chain', string>;
763
- steps: Array<{
764
- at: string;
765
- text: string;
766
- }>;
767
- segments: Record<'jet' | 'torch' | 'blast', string>;
768
- note: string;
769
- };
770
- scenarios: {
771
- shot: string;
772
- shot_leak: string;
773
- shot_ignite: string;
774
- shot_explode: string;
775
- shot_zombie: string;
776
- shot_survivor: string;
777
- shot_wall: string;
778
- valve: string;
779
- valve_leak: string;
780
- valve_quiet: string;
781
- valve_lit: string;
782
- valve_explode: string;
783
- fire: string;
784
- fire_explode: string;
785
- chain: string;
786
- chain_explode: string;
787
- push_p13: string;
788
- push_grenade: string;
789
- push_found: string;
790
- push_told: string;
791
- push_outward: string;
792
- push_falloff: string;
793
- push_person: string;
794
- push_heavy: string;
795
- };
796
- }
797
- declare const EXPLOSIVES_TEXT: Record<string, ExplosivesText>;
798
- declare const explosivesTextOf: (locale: string) => ExplosivesText;
799
-
800
- /** Id of the explosives module (`?area=explosives_area` opens it). */
801
- declare const EXPLOSIVES_AREA_ID = "explosives_area";
802
- /** The parts of a part state the bench reads (structural: `PartState` of the destruction world fits). */
803
- interface PartView {
804
- readonly liters?: number;
805
- readonly temperature: number;
806
- readonly status: string;
807
- readonly holes: ReadonlyArray<{
808
- readonly diameter: number;
809
- readonly through: boolean;
810
- }>;
811
- readonly cracks: readonly unknown[];
812
- readonly burning: boolean;
813
- }
814
- /** What the explosives module needs from the room it drives (structural: the `TestRoom` of game-test-room fits). */
815
- interface ExplosivesRoom {
816
- readonly world: {
817
- readonly time: number;
818
- ids(): string[];
819
- on(type: '*', fn: (event: DestructionEvent) => void): () => void;
820
- hit(objectId: string, hit: Hit): unknown;
821
- vent(objectId: string, partId: string, opening?: {
822
- point?: Vec3$1;
823
- normal?: Vec3$1;
824
- diameter?: number;
825
- }): boolean;
826
- seal(objectId: string, partId: string): number;
827
- part(objectId: string, partId: string): PartView | null;
828
- state(objectId: string): {
829
- readonly parts: readonly (PartView & {
830
- readonly id: string;
831
- readonly hp: number;
832
- readonly maxHp: number;
833
- })[];
834
- } | null;
835
- };
836
- readonly renderer: {
837
- impulse(objectId: string, impulse: Vec3$1, point?: Vec3$1): void;
838
- };
839
- readonly vfx: {
840
- spawn(kind: string, point: Vec3$1, velocity: Vec3$1, options?: {
841
- color?: number;
842
- size?: number;
843
- life?: number;
844
- alpha?: number;
845
- }): void;
846
- burst(kind: string, point: Vec3$1, normal: Vec3$1, count: number, speed?: number): void;
847
- fire(options: {
848
- point: Vec3$1;
849
- radius: number;
850
- life: number;
851
- }): number;
852
- stop(handle: number): void;
853
- };
854
- spawned(): ReadonlyArray<{
855
- readonly objectId: string;
856
- readonly itemId: string;
857
- readonly root: unknown;
858
- }>;
859
- openArea(group: string): unknown;
860
- clear(): void;
861
- spawn(itemId: string, position?: Vec3$1, rotationY?: number): {
862
- readonly objectId: string;
863
- readonly itemId: string;
864
- readonly root: unknown;
865
- };
866
- setTool(weaponId: string): void;
867
- waitUntilReady(maxSeconds?: number): number;
868
- look(position: Vec3$1, target: Vec3$1): void;
869
- use(hold?: number): void;
870
- on(type: 'spawn', fn: (data: unknown) => void): () => void;
871
- }
872
- /** The bench of the explosives area as the module and its scenarios see it. */
873
- interface ExplosivesBench {
874
- readonly room: ExplosivesRoom | undefined;
875
- readonly def: ExplosiveDef;
876
- /** The strength multiplier now (the next cylinder laid takes it). */
877
- blastScale(): number;
878
- /** Called by the module's `area`: the cylinders spawned from now on belong to the area (they get their rings). */
879
- areaOpened(): void;
880
- controls(): ModuleControl[];
881
- layers(): ModuleLayer[];
882
- metrics(): ModuleMetric[];
883
- attach(host: ModuleHost): () => void;
884
- /** The actions of the bench, by the id of their button. Each answers whether it did something. */
885
- readonly actions: Readonly<Record<'shoot' | 'valve' | 'light' | 'fire' | 'reset', () => boolean>>;
886
- /** The cylinder of the scene (the first one alive), with what the bench knows about it. */
887
- vessel(): VesselView | undefined;
888
- /** The wall of the scene, the zombie and the survivor, as the aftermath reads them. */
889
- /** The last explosion the host told (a part of the world or a thrown explosive): where, how strong and how far; undefined before the first, and after the area is cleared. */
890
- lastBlast(): {
891
- readonly point: Vec3$1;
892
- readonly energy: number;
893
- readonly radius: number;
894
- readonly cause: string;
895
- readonly explosive?: string;
896
- } | undefined;
897
- witnesses(): Array<{
898
- kind: 'person' | 'wall' | 'object';
899
- id: string;
900
- itemId: string;
901
- distance: number;
902
- alive?: boolean;
903
- vitality?: number;
904
- broken?: number;
905
- marks?: number;
906
- pieces?: number;
907
- }>;
908
- }
909
- interface VesselView {
910
- readonly objectId: string;
911
- /** World time of the first leak, of the jet catching fire and of the blast (seconds); undefined until they happen. */
912
- readonly leakAt: number | undefined;
913
- readonly litAt: number | undefined;
914
- readonly explodedAt: number | undefined;
915
- readonly cause: 'shot' | 'valve' | undefined;
916
- readonly valveOpen: boolean;
917
- readonly lit: boolean;
918
- readonly exploded: boolean;
919
- readonly point: Vec3$1 | undefined;
920
- }
921
- interface ExplosivesBenchOptions {
922
- readonly locale: string;
923
- readonly text: ExplosivesText;
924
- readonly def: ExplosiveDef;
925
- readonly scene: {
926
- readonly cylinder: Vec3$1;
927
- };
928
- readonly room: ExplosivesRoom | undefined;
929
- readonly blastScale: number;
930
- readonly profile: {
931
- readonly visualRadius?: number;
932
- readonly residualFires?: ReadonlyArray<{
933
- readonly radius: number;
934
- readonly life: number;
935
- }>;
936
- } | undefined;
937
- }
938
- /**
939
- * The state and the actions of the explosives area: it follows the world's events of the cylinder (leak, primed, explode), tells each phase in the room's log, plays the torch and the flight
940
- * of the shell (the Laboratório de Explosões, `SC.p13`) and drives the destruction world for the bench actions. The module wraps it in a `TestableModule`.
941
- */
942
- declare function createExplosivesBench(options: ExplosivesBenchOptions): ExplosivesBench;
943
-
944
- /** Where the things of the scene stand (metres, in the room's world; the brick wall is the room's own at z = -11). The kitchen corner is against the wall; the player looks at it from about 6 m. */
945
- interface ExplosivesScene {
946
- /** Item ids and positions of the kitchen furniture (items of the household module); one that the room does not know is left out. */
947
- readonly furniture: ReadonlyArray<{
948
- readonly item: string;
949
- readonly at: Vec3$1;
950
- readonly rotationY?: number;
951
- }>;
952
- /** The cylinder. */
953
- readonly cylinder: Vec3$1;
954
- /** The zombie (about 3 m from the cylinder) and the survivor (about 8 m): item ids of the characters module. */
955
- readonly zombie: {
956
- readonly item: string;
957
- readonly at: Vec3$1;
958
- };
959
- readonly survivor: {
960
- readonly item: string;
961
- readonly at: Vec3$1;
962
- };
963
- /** The player's eye (about 6 m from the cylinder: outside the 5 m lethal ring, the lamp rig of the weather module is behind it). */
964
- readonly eye: Vec3$1;
965
- }
966
- /** The kitchen corner of the default scene: fridge, cabinet, the cylinder and the stove side by side against the wall, a table 2 m away. */
967
- declare const DEFAULT_EXPLOSIVES_SCENE: ExplosivesScene;
968
- interface ExplosivesTestModuleOptions {
969
- /** `en` or `pt-BR` (default). */
970
- locale?: string;
971
- /** The arsenal to read the P13 from (default `createArsenal` with the locale). */
972
- arsenal?: Arsenal;
973
- /** The room the module drives: its destruction world, effects and tools. Without it the module still lays the area and the bench shows, but the actions only say they need the room. */
974
- room?: ExplosivesRoom;
975
- /** Overrides of the default scene (see `ExplosivesScene`). */
976
- scene?: Partial<ExplosivesScene>;
977
- /** Strength multiplier the bench starts at (default 1: the arsenal's numbers; a game value, see the README). */
978
- blastScale?: number;
979
- }
980
- /**
981
- * The explosives test area as a `TestableModule`: the P13 cooking gas cylinder in a kitchen corner against a brick wall, with furniture, a zombie at 3 m, a survivor at 8 m and rings on the floor at the
982
- * lethal and injury radii. The bench shoots it, opens its valve, lights it with a lighter, throws it in a fire or restarts the scene; every phase is told in the room's log in the locale of the room.
983
- * The module reads the sequence (the torch delay, the gas, the flight of the shell) from the arsenal def of `propane_p13` and the blast from its `chain`, so a game changes them with `ArsenalOptions.patch.explosives`.
984
- */
985
- declare function createExplosivesTestModule(options?: ExplosivesTestModuleOptions): TestableModule & {
986
- readonly bench: ReturnType<typeof createExplosivesBench>;
987
- };
988
-
989
28
  /** Prefix of the item ids of the explosives that sit in the world (`world_fuel_barrel`). */
990
29
  declare const WORLD_EXPLOSIVE_PREFIX = "world_";
991
30
  /** Name of the mesh of the brass valve on the P13 model (the team's `botijao`: the 0xb8913a cylinder on the neck). */
@@ -996,14 +35,16 @@ declare const WORLD_EXPLOSIVE_IDS: readonly string[];
996
35
  interface WorldExplosiveOptions {
997
36
  /** Multiplies `energy`, `lethalRadius` and `injuryRadius` of the explosive (default 1: the arsenal's numbers). It is a game value, not a physical table; the arsenal's own place for it is `ArsenalOptions.patch.explosives`. */
998
37
  readonly scale?: () => number;
38
+ /** The item models of game-items-three (`itemModels` there): the P13 is drawn with the team's model; default `itemModels` there (deprecated: pass it). */
39
+ readonly items?: ItemModels;
999
40
  }
1000
41
  /** Where the valve is on a spawned cylinder, in the world (the centre of the brass mesh), or undefined when the object has none. */
1001
- declare const worldExplosiveValve: (THREE: typeof THREE_NS, root: THREE_NS.Object3D) => Vec3$1 | undefined;
42
+ declare const worldExplosiveValve: (THREE: typeof THREE_NS, root: THREE_NS.Object3D) => Vec3 | undefined;
1002
43
  /**
1003
44
  * What is left of a world explosive after the blast, as an object to fly: the same model, worn and darkened (the torn shell of the P13 in the Laboratório de Explosões, `SC.p13`),
1004
45
  * with no part mapped. Undefined for the explosives that have no model of the team.
1005
46
  */
1006
- declare const worldExplosiveShell: (THREE: typeof THREE_NS, defId: string) => THREE_NS.Group | undefined;
47
+ declare const worldExplosiveShell: (THREE: typeof THREE_NS, defId: string, items?: ItemModels) => THREE_NS.Group | undefined;
1007
48
  /** An explosive of the arsenal standing in the world: it goes off by a bullet, fire or another blast, after the delay its `chain` gives. */
1008
49
  declare const worldExplosiveItem: (def: ExplosiveDef, name: string, options?: WorldExplosiveOptions) => TestableItem | undefined;
1009
50
 
@@ -1057,27 +98,28 @@ declare const BODY_ACTIONS: ReadonlySet<string>;
1057
98
  declare function weaponProp(def: Pick<WeaponDef, 'id' | 'category' | 'mass'>, name?: string): WeaponProp;
1058
99
  /** One mesh per box part, named after the part (what destruction renderers bind to), in a group with its origin on the floor. */
1059
100
  declare function buildProp(THREE: typeof THREE_NS, prop: WeaponProp): THREE_NS.Group;
1060
- /** How a weapon is drawn from an item model of game-items-three: the item (default the weapon id), and the turns the laying-down rule gets wrong. */
1061
- interface WeaponItemModel {
1062
- /** Catalog id of the item model; the weapon id when absent. */
1063
- readonly item?: string;
1064
- /** Quarter turns about y after the long axis is laid along x (a crossbow's stock is shorter than its limbs). */
1065
- readonly turn?: number;
1066
- /** Turn it end for end after the head is found (the head is the narrow end: a knife's blade, a screwdriver's tip, an extinguisher's nozzle). */
1067
- readonly flip?: boolean;
1068
- }
1069
- /** Draws a weapon the gallery did not model with an item model of game-items-three (a game adds its own or corrects one; `null` keeps the low-poly prop). */
1070
- declare function registerWeaponItemModel(weaponId: string, model: WeaponItemModel | null): void;
1071
- /** The item model of game-items-three that draws a weapon (`baseball_bat`, `axe`, `fire_extinguisher`...), or undefined when there is none. */
1072
- declare function itemModelOfWeapon(weaponId: string): string | undefined;
101
+
1073
102
  /**
1074
- * A weapon the gallery did not draw, with the team's item model (Itens do Vale Cinzento: the bat, the axe, the machete, the extinguisher...): its long axis turned
1075
- * along +x and laid flat, the wider end (the head) at +x unless `registerWeaponItemModel` says otherwise, the origin at the bottom centre, an empty `handle` at the narrow end where the hand closes. Undefined
1076
- * when game-items-three has no model of it.
103
+ * The prop of a weapon the gallery drew (or that an item model draws, `buildItemWeaponModel`), for a counter or the floor: its model lying on the side, centred on the footprint with its underside on the floor, joined into one mesh per
104
+ * material (the hands keep the model with its pivots, `buildWeaponModelById`), every mesh naming the one rigid part (`body`) that moves it. The size of that part is left in
105
+ * `userData.footprint` for `modeledPropSpec`.
1077
106
  */
1078
- declare function buildItemWeaponModel(THREE: typeof THREE_NS, def: Pick<WeaponDef, 'id'>): THREE_NS.Group | undefined;
1079
- /** The model of a weapon for the hands or a shelf: the team's item model when the kit has one (`buildItemWeaponModel`), the low-poly prop the counters show otherwise. */
1080
- declare function buildWeaponModel(THREE: typeof THREE_NS, def: Pick<WeaponDef, 'id' | 'category' | 'mass'>): THREE_NS.Group;
107
+ declare function buildModeledProp(THREE: typeof THREE_NS, def: Pick<WeaponDef, 'id'>, name: string, decorate?: (root: THREE_NS.Object3D) => void, items?: ItemModels, props?: WeaponProps): THREE_NS.Group | undefined;
108
+ /** A modeled weapon on a tripod of three steel legs under its middle (the same legs the `tripod` accessory draws in the hands). */
109
+ declare function buildTripodMountedProp(THREE: typeof THREE_NS, def: Pick<WeaponDef, 'id'>, name: string, items?: ItemModels, props?: WeaponProps): THREE_NS.Group | undefined;
110
+ /** The destruction spec of a modeled prop: one steel box of its measures, with the real mass of the weapon. */
111
+ declare function modeledPropSpec(root: unknown, def: Pick<WeaponDef, 'mass'>, name: string): DestructibleSpec;
112
+
113
+ interface WeaponPropsOptions {
114
+ /** Item model overrides by weapon id, added to the shipped ones (`null` keeps the low-poly prop); later packs replace earlier ones. */
115
+ readonly packs?: readonly Readonly<Record<string, WeaponItemModel | null>>[];
116
+ /** Changes to an override by weapon id, merged field by field. */
117
+ readonly patch?: Readonly<Record<string, DeepPartial<WeaponItemModel>>>;
118
+ /** Weapon ids whose override is taken out (the weapon id itself is then the item model id). */
119
+ readonly remove?: readonly string[];
120
+ }
121
+ /** A set of weapon prop overrides of its own: the shipped ones plus `packs`, `patch` and `remove`. Nothing is shared with any other set on the page. */
122
+ declare function createWeaponProps(options?: WeaponPropsOptions): WeaponProps;
1081
123
 
1082
124
  /** The shapes the gallery draws: rimfire, straight rimless (`p`), straight rimmed (`rimp`), bottleneck rimless (`r`), bottleneck rimmed (`rr`) and shotgun shell. */
1083
125
  type CartridgeShape = 'shell' | 'rim' | 'p' | 'rimp' | 'r' | 'rr';
@@ -1125,6 +167,8 @@ interface FitAttachmentOptions {
1125
167
  readonly isDrawn?: () => boolean;
1126
168
  /** Asked every frame: false puts the light and laser out whatever they are set to (the bench layer for the beams). */
1127
169
  readonly areBeamsOn?: () => boolean;
170
+ /** The host's light budget: the weapon light is a source of it. Without it the light is a `SpotLight` of its own (deprecated, removed in the next major). */
171
+ readonly lights?: LightBudget;
1128
172
  }
1129
173
  /** The accessories drawn on one model: it follows the list of fitted parts. */
1130
174
  interface AttachmentRig {
@@ -1160,4 +204,4 @@ declare function rigUnderbarrel(THREE: typeof THREE_NS, model: WeaponModel, def:
1160
204
  */
1161
205
  declare function rigStock(THREE: typeof THREE_NS, model: WeaponModel, def: Pick<WeaponDef, 'stock' | 'dimensions'>): void;
1162
206
 
1163
- export { ARCHETYPE_MODELS, ATTACHMENT_MODELS, type AttachmentBuildContext, type AttachmentModel, type AttachmentModelBuilder, type AttachmentModelRegistry, type AttachmentRig, BODY_ACTIONS, CLASS_REFERENCE_ENERGY, COUNTER_ITEM_ID, type CartridgeShape, type ClipContext, DEFAULT_ENERGY_CURVE, DEFAULT_EXPLOSIVES_SCENE, DEFAULT_THUMBNAIL_BASE, type DistanceCurve, EXPLOSIVES_AREA_ID, EXPLOSIVES_TEXT, type EnergyCurve, type ExplosivesRoom, type ExplosivesScene, type ExplosivesTestModuleOptions, type ExplosivesText, type FitAttachmentOptions, type FxLayers, GAME_DISTANCE_CURVE, GAME_SOUND_CLASSES, type LaserRaycast, MECHANICAL_SOUNDS, MODEL_ENTRIES, MOUNTED_M134_ITEM_ID, type MechanicalSoundId, type ModelEntry, type ModelFamily, type ModelKit, type ModelMaterials, type ModelOptions, type ModelParts, type MountFrame, P13_VALVE_MESH, type ProjectileModel, type ProjectileQuery, type ShotExtras, type ShotSound, type ShotSoundClass, type ShotSoundInput, type ShotSoundOptions, type SoundClassDef, type SoundStep, WEAPON_ITEM_PREFIX, WEAPON_THUMBNAILS, WORLD_EFFECTS, WORLD_EXPLOSIVE_IDS, WORLD_EXPLOSIVE_PREFIX, type WeaponAudio, type WeaponAudioOptions, type WeaponFx, type WeaponFxOptions, type WeaponItemModel, type WeaponModel, type WeaponProp, type WeaponThumbnailEntry, type WeaponsTestModuleOptions, type WorldEffectIds, type WorldEffectsOptions, type WorldExplosiveOptions, applyCondition, buildCartridge, buildCasing, buildItemWeaponModel, buildProp, buildRound, buildToolClips, buildWeaponModel, buildWeaponModelById, cartridgeShape, computeShotSound, createExplosivesTestModule, createWeaponAudio, createWeaponFx, createWeaponsTestModule, createWorldEffects, deriveFrames, explosivesTextOf, fitAttachmentModels, hasWeaponModel, itemModelOfWeapon, mechanicalSoundOf, modelKit, mountFrame, partRegistry, projectileModel, registerWeaponItemModel, rigStock, rigUnderbarrel, weaponProp, weaponThumbnailCredit, weaponThumbnailUrl, weaponsLayout, worldExplosiveItem, worldExplosiveShell, worldExplosiveValve };
207
+ export { ATTACHMENT_MODELS, AttachmentModelRegistry, type AttachmentRig, BODY_ACTIONS, type CartridgeShape, type ClipContext, DEFAULT_THUMBNAIL_BASE, type FitAttachmentOptions, ItemModels, LaserRaycast, ModelFamily, ModelKit, ModelParts, P13_VALVE_MESH, type ProjectileModel, type ProjectileQuery, WEAPON_THUMBNAILS, WORLD_EFFECTS, WORLD_EXPLOSIVE_IDS, WORLD_EXPLOSIVE_PREFIX, WeaponItemModel, WeaponModel, type WeaponProp, WeaponProps, type WeaponPropsOptions, type WeaponThumbnailEntry, type WorldEffectIds, type WorldEffectsOptions, type WorldExplosiveOptions, applyCondition, buildCartridge, buildCasing, buildModeledProp, buildProp, buildRound, buildToolClips, buildTripodMountedProp, cartridgeShape, createWeaponProps, createWorldEffects, fitAttachmentModels, modeledPropSpec, partRegistry, projectileModel, rigStock, rigUnderbarrel, weaponProp, weaponThumbnailCredit, weaponThumbnailUrl, worldExplosiveItem, worldExplosiveShell, worldExplosiveValve };