@adatechnology/game-weapons-three 0.1.0 → 0.2.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 +447 -9
- package/dist/index.global.js +10633 -1011
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +4218 -80
- package/dist/index.js.map +1 -1
- package/package.json +7 -6
package/dist/index.d.ts
CHANGED
|
@@ -1,13 +1,175 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { Arsenal, WeaponDef } from '@adatechnology/game-weapons';
|
|
1
|
+
import { HostTool, HostEvent, TestableModule, AreaPlacement, TestableItem, DestructibleSpec, ToolClipSet } from '@adatechnology/game-contracts';
|
|
2
|
+
import { CaliberDef, ReloadStageId, WeaponEvent, Arsenal, ExplosiveDef, WeaponDef, CartridgeDims, CaseType, ReloadFamily } from '@adatechnology/game-weapons';
|
|
3
3
|
import * as THREE_NS from 'three';
|
|
4
4
|
|
|
5
|
+
/** One sound of the game: [lowpass cutoff Hz, gain, seconds]. Literal from the `P` table of `sfx` in the game (jogo.js L62101-L62104). */
|
|
6
|
+
type SoundClassDef = readonly [cutoff: number, gain: number, seconds: number];
|
|
7
|
+
/** The game names are pistola, escopeta, fuzil, rifle, impacto, carne, passo, vidro, madeira, recarga, vazio and explosao. */
|
|
8
|
+
declare const GAME_SOUND_CLASSES: {
|
|
9
|
+
readonly pistol: readonly [1800, 0.9, 0.18];
|
|
10
|
+
readonly shotgun: readonly [900, 1.2, 0.35];
|
|
11
|
+
readonly rifle: readonly [1400, 1.1, 0.28];
|
|
12
|
+
readonly long_rifle: readonly [1100, 1.3, 0.45];
|
|
13
|
+
readonly impact: readonly [2500, 0.25, 0.05];
|
|
14
|
+
readonly flesh: readonly [600, 0.35, 0.08];
|
|
15
|
+
readonly step: readonly [400, 0.08, 0.05];
|
|
16
|
+
readonly glass: readonly [5000, 0.5, 0.3];
|
|
17
|
+
readonly wood: readonly [700, 0.5, 0.2];
|
|
18
|
+
readonly reload: readonly [3000, 0.15, 0.06];
|
|
19
|
+
readonly empty: readonly [4000, 0.12, 0.03];
|
|
20
|
+
readonly explosion: readonly [200, 1.6, 1.4];
|
|
21
|
+
};
|
|
22
|
+
/** The four classes a shot can have: the game picks one by calibre (jogo.js L68697). */
|
|
23
|
+
type ShotSoundClass = 'pistol' | 'shotgun' | 'rifle' | 'long_rifle';
|
|
24
|
+
/** Distance muffling of the game (jogo.js L62092, L62105): `gain / (1 + d² × gainFalloff)`, `cutoff / (1 + d × cutoffFalloff)`, silent under `minGain`. */
|
|
25
|
+
type DistanceCurve = {
|
|
26
|
+
readonly gainFalloff: number;
|
|
27
|
+
readonly cutoffFalloff: number;
|
|
28
|
+
readonly minGain: number;
|
|
29
|
+
};
|
|
30
|
+
declare const GAME_DISTANCE_CURVE: DistanceCurve;
|
|
31
|
+
/**
|
|
32
|
+
* 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)
|
|
33
|
+
* 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
|
|
34
|
+
* the game, and a lighter or heavier calibre of the same class is quieter and brighter, or louder and duller.
|
|
35
|
+
*/
|
|
36
|
+
type EnergyCurve = {
|
|
37
|
+
readonly floorJ: number;
|
|
38
|
+
readonly spanDecades: number;
|
|
39
|
+
readonly gain: readonly [base: number, span: number];
|
|
40
|
+
readonly duration: readonly [base: number, span: number];
|
|
41
|
+
readonly cutoff: readonly [base: number, span: number];
|
|
42
|
+
/** The muzzle crack (high noise) and the body (low thump) follow the energy alone. */
|
|
43
|
+
readonly crackGain: readonly [base: number, span: number];
|
|
44
|
+
readonly bodyGain: readonly [base: number, span: number];
|
|
45
|
+
readonly bodyDuration: readonly [base: number, span: number];
|
|
46
|
+
readonly bodyFrequency: readonly [base: number, span: number];
|
|
47
|
+
};
|
|
48
|
+
declare const DEFAULT_ENERGY_CURVE: EnergyCurve;
|
|
49
|
+
/** 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. */
|
|
50
|
+
declare const CLASS_REFERENCE_ENERGY: Readonly<Record<ShotSoundClass, number>>;
|
|
51
|
+
type ShotSoundOptions = {
|
|
52
|
+
/** Replaces or adds sound classes (the game table is the default). */
|
|
53
|
+
readonly classes?: Readonly<Record<string, SoundClassDef>>;
|
|
54
|
+
readonly distance?: Partial<DistanceCurve>;
|
|
55
|
+
readonly energy?: Partial<EnergyCurve>;
|
|
56
|
+
readonly referenceEnergy?: Partial<Record<ShotSoundClass, number>>;
|
|
57
|
+
/** Picks the class of a shot; the default follows the game (shotgun by shell, handguns by category, then by energy). */
|
|
58
|
+
readonly classOf?: (input: ShotSoundInput, energyJ: number) => ShotSoundClass;
|
|
59
|
+
/** Class bands by energy (J): below `handgunBelowJ` a pistol, below `rifleBelowJ` a rifle, above that a long rifle. */
|
|
60
|
+
readonly bands?: {
|
|
61
|
+
readonly handgunBelowJ: number;
|
|
62
|
+
readonly rifleBelowJ: number;
|
|
63
|
+
};
|
|
64
|
+
readonly suppressor?: {
|
|
65
|
+
readonly gain: number;
|
|
66
|
+
readonly cutoff: number;
|
|
67
|
+
readonly crack: number;
|
|
68
|
+
readonly body: number;
|
|
69
|
+
};
|
|
70
|
+
readonly indoors?: {
|
|
71
|
+
readonly duration: number;
|
|
72
|
+
readonly cutoff: number;
|
|
73
|
+
};
|
|
74
|
+
};
|
|
75
|
+
type ShotSoundInput = {
|
|
76
|
+
/** The calibre; its energy (× pellets) is used unless `energyJ` is given. */
|
|
77
|
+
readonly caliber?: CaliberDef;
|
|
78
|
+
readonly energyJ?: number;
|
|
79
|
+
readonly category?: string;
|
|
80
|
+
/** Metres from the listener, default 0. */
|
|
81
|
+
readonly distance?: number;
|
|
82
|
+
/** Master gain of the game `sfx` (its `vol`), default 1. */
|
|
83
|
+
readonly volume?: number;
|
|
84
|
+
readonly suppressed?: boolean;
|
|
85
|
+
readonly indoors?: boolean;
|
|
86
|
+
};
|
|
87
|
+
type ShotSound = {
|
|
88
|
+
readonly soundClass: ShotSoundClass;
|
|
89
|
+
readonly energyJ: number;
|
|
90
|
+
/** False when the shot is under the game's `minGain` at this distance: nothing is played. */
|
|
91
|
+
readonly audible: boolean;
|
|
92
|
+
/** The main noise burst: lowpass cutoff Hz, starting gain and the seconds of the exponential tail (to 0.001). */
|
|
93
|
+
readonly cutoff: number;
|
|
94
|
+
readonly gain: number;
|
|
95
|
+
readonly duration: number;
|
|
96
|
+
/** High noise burst of the muzzle. */
|
|
97
|
+
readonly crack: {
|
|
98
|
+
readonly gain: number;
|
|
99
|
+
readonly cutoff: number;
|
|
100
|
+
readonly duration: number;
|
|
101
|
+
};
|
|
102
|
+
/** Low thump that sweeps from `frequency` to `to`. */
|
|
103
|
+
readonly body: {
|
|
104
|
+
readonly gain: number;
|
|
105
|
+
readonly frequency: number;
|
|
106
|
+
readonly to: number;
|
|
107
|
+
readonly duration: number;
|
|
108
|
+
};
|
|
109
|
+
};
|
|
110
|
+
/**
|
|
111
|
+
* 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.
|
|
112
|
+
* Pure and deterministic; the playback layer only turns it into nodes.
|
|
113
|
+
*/
|
|
114
|
+
declare const computeShotSound: (input: ShotSoundInput, options?: ShotSoundOptions) => ShotSound;
|
|
115
|
+
|
|
116
|
+
/** One layer of a mechanical sound; `at` is seconds after the start. */
|
|
117
|
+
type SoundStep =
|
|
118
|
+
/** Metal click: a short high noise plus a square tone at 0.6 × the frequency (the SDK synth, as before). */
|
|
119
|
+
{
|
|
120
|
+
readonly layer: 'metal';
|
|
121
|
+
readonly at: number;
|
|
122
|
+
readonly frequency: number;
|
|
123
|
+
readonly gain: number;
|
|
124
|
+
}
|
|
125
|
+
/** A sound class of the game (`recarga`, `vazio`...) played at a volume. */
|
|
126
|
+
| {
|
|
127
|
+
readonly layer: 'class';
|
|
128
|
+
readonly at: number;
|
|
129
|
+
readonly soundClass: keyof typeof GAME_SOUND_CLASSES;
|
|
130
|
+
readonly volume: number;
|
|
131
|
+
}
|
|
132
|
+
/** Dull landing: lowpass noise. */
|
|
133
|
+
| {
|
|
134
|
+
readonly layer: 'thud';
|
|
135
|
+
readonly at: number;
|
|
136
|
+
readonly gain: number;
|
|
137
|
+
readonly frequency: number;
|
|
138
|
+
};
|
|
139
|
+
type MechanicalSoundId = ReloadStageId | 'dry_fire' | 'misfire' | 'feed' | 'cycle' | 'mode' | 'safety_on' | 'safety_off' | 'jam' | 'clear_start' | 'clear_end';
|
|
140
|
+
/**
|
|
141
|
+
* 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
|
|
142
|
+
* reload tick are the game's `vazio` and `recarga` classes (jogo.js L62101-L62104; played at L68644-L68662); the gallery (sources/armas-itens__galeria-3d-arsenal.js)
|
|
143
|
+
* has no sound, so the metal layers are the SDK synth (the same `metal` used since the first version).
|
|
144
|
+
*/
|
|
145
|
+
declare const MECHANICAL_SOUNDS: Readonly<Record<MechanicalSoundId, readonly SoundStep[]>>;
|
|
146
|
+
/** Which mechanical sound a weapon event asks for, if any (`shot`, `draw` and `reload` start/end have their own handling). */
|
|
147
|
+
declare const mechanicalSoundOf: (event: WeaponEvent) => MechanicalSoundId | undefined;
|
|
148
|
+
|
|
149
|
+
/** What a shot adds to the energy and the category: where the listener is and how the weapon is set. */
|
|
150
|
+
type ShotExtras = Pick<ShotSoundInput, 'caliber' | 'distance' | 'volume' | 'suppressed' | 'indoors'>;
|
|
151
|
+
interface WeaponAudioOptions extends ShotSoundOptions {
|
|
152
|
+
/** Seed of the noise buffer, of the start point in it and of the casing pitch: same seed, same sound. Default 1. */
|
|
153
|
+
readonly seed?: number;
|
|
154
|
+
/** Replaces or adds mechanical sounds by id. */
|
|
155
|
+
readonly mechanical?: Readonly<Partial<Record<MechanicalSoundId, readonly SoundStep[]>>>;
|
|
156
|
+
/** Where the AudioContext comes from (default: the global one); lets a host or a test lend its own. */
|
|
157
|
+
readonly createContext?: () => AudioContext;
|
|
158
|
+
}
|
|
5
159
|
/** Sounds the weapon presentation plays. */
|
|
6
160
|
interface WeaponAudio {
|
|
7
|
-
/** A shot:
|
|
8
|
-
shot(energyJ: number, category: string): void;
|
|
161
|
+
/** A shot: class and distance muffling of the game, loudness and body from the muzzle energy (joules). */
|
|
162
|
+
shot(energyJ: number, category: string, extras?: ShotExtras): void;
|
|
163
|
+
/** The parameters `shot` would play (pure). */
|
|
164
|
+
shotSound(input: ShotSoundInput): ShotSound;
|
|
9
165
|
/** Dry click of an empty weapon. */
|
|
10
166
|
click(): void;
|
|
167
|
+
/** A mechanical sound by id: a reload stage, `dry_fire`, `jam`, `safety_on`... */
|
|
168
|
+
mechanical(id: MechanicalSoundId): void;
|
|
169
|
+
/** The mechanical sound of a weapon event, if it has one (reload stages, empty, misfire, fault, clear, safety, mode, feed). */
|
|
170
|
+
event(event: WeaponEvent): void;
|
|
171
|
+
/** A sound class of the game by name (`impact`, `flesh`, `glass`...), with the game's distance muffling. */
|
|
172
|
+
play(soundClass: string, volume?: number, distance?: number): void;
|
|
11
173
|
/** Magazine out, or the first shell in. */
|
|
12
174
|
reloadStart(category: string): void;
|
|
13
175
|
/** Magazine seated and the action racked. */
|
|
@@ -22,7 +184,14 @@ interface WeaponAudio {
|
|
|
22
184
|
setVolume(volume: number): void;
|
|
23
185
|
dispose(): void;
|
|
24
186
|
}
|
|
25
|
-
declare function createWeaponAudio(volume?: number): WeaponAudio;
|
|
187
|
+
declare function createWeaponAudio(volume?: number, options?: WeaponAudioOptions): WeaponAudio;
|
|
188
|
+
|
|
189
|
+
/** What the bench turns on or off in the presentation of the weapon: the ejected casings, the dropped magazines and the muzzle flash. */
|
|
190
|
+
interface FxLayers {
|
|
191
|
+
casings: boolean;
|
|
192
|
+
magazines: boolean;
|
|
193
|
+
muzzleFlash: boolean;
|
|
194
|
+
}
|
|
26
195
|
|
|
27
196
|
interface WeaponFxOptions {
|
|
28
197
|
THREE: typeof THREE_NS;
|
|
@@ -33,12 +202,27 @@ interface WeaponFxOptions {
|
|
|
33
202
|
groundAt: (x: number, z: number) => number;
|
|
34
203
|
/** Sounds (`createWeaponAudio`); null or absent: silent. */
|
|
35
204
|
audio?: WeaponAudio | null;
|
|
205
|
+
/** Seed of the scatter of the effects of the gallery models. */
|
|
206
|
+
seed?: number;
|
|
207
|
+
/** The tool as it is now (barrel heat, fuel burning). */
|
|
208
|
+
tool?: () => HostTool;
|
|
209
|
+
/** Wear of the weapon: `new`, `used`, `worn` or `rusty`. */
|
|
210
|
+
condition?: string;
|
|
211
|
+
/** What is drawn: read at the moment of each event, so the bench can change it live. */
|
|
212
|
+
layers?: FxLayers;
|
|
213
|
+
/** Metres between the shooter and the listener, for the distance muffling of the shot sound (default 0). */
|
|
214
|
+
soundDistance?: () => number;
|
|
36
215
|
}
|
|
216
|
+
|
|
37
217
|
/** The weapon in the hands, its fire and reload motion, ejected casings and dropped magazines, and their sounds. */
|
|
38
218
|
interface WeaponFx {
|
|
39
219
|
/** Feed every tool event of the host, with the tool as it is after the event. */
|
|
40
220
|
handle(event: HostEvent, tool: HostTool): void;
|
|
41
221
|
update(dt: number): void;
|
|
222
|
+
/** Dresses the weapon for its wear (`new`, `used`, `worn`, `rusty`); the gallery models show it in their metal. */
|
|
223
|
+
setCondition(condition: string): void;
|
|
224
|
+
/** What is drawn (casings, magazines, muzzle flash): change a field and the next event follows it. */
|
|
225
|
+
readonly layers: FxLayers;
|
|
42
226
|
/** Weapon shown in the hands, or null. */
|
|
43
227
|
readonly inHand: string | null;
|
|
44
228
|
/** Casings and magazines currently on the floor or in the air. */
|
|
@@ -46,6 +230,10 @@ interface WeaponFx {
|
|
|
46
230
|
readonly magazines: number;
|
|
47
231
|
dispose(): void;
|
|
48
232
|
}
|
|
233
|
+
/**
|
|
234
|
+
* 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
|
|
235
|
+
* (fire, cycle, jam, clear, safety, the seven reloads); the generic archetypes keep their low-poly prop.
|
|
236
|
+
*/
|
|
49
237
|
declare function createWeaponFx(options: WeaponFxOptions): WeaponFx;
|
|
50
238
|
|
|
51
239
|
interface WeaponsTestModuleOptions {
|
|
@@ -55,14 +243,18 @@ interface WeaponsTestModuleOptions {
|
|
|
55
243
|
arsenal?: Arsenal;
|
|
56
244
|
/** Play sounds (default true; silent anyway where there is no AudioContext). */
|
|
57
245
|
sound?: boolean;
|
|
246
|
+
/** Wear of the weapon in the hands, which the gallery models show in their metal: `new` (default), `used`, `worn` or `rusty`. */
|
|
247
|
+
condition?: string;
|
|
248
|
+
/** Seed of the scatter of casings and smoke (default 1). */
|
|
249
|
+
seed?: number;
|
|
58
250
|
}
|
|
59
251
|
/** Prefix of the item ids of the weapon props (`weapon_pistol_9mm`). */
|
|
60
252
|
declare const WEAPON_ITEM_PREFIX = "weapon_";
|
|
61
253
|
declare const COUNTER_ITEM_ID = "counter_weapons";
|
|
62
|
-
/** Where the counters go and where each weapon lies on them:
|
|
63
|
-
declare function weaponsLayout(weaponItemIds: string[]): AreaPlacement[];
|
|
254
|
+
/** 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. */
|
|
255
|
+
declare function weaponsLayout(weaponItemIds: string[], pitchOf?: (itemId: string) => number): AreaPlacement[];
|
|
64
256
|
/**
|
|
65
|
-
* The weapons test area as a `TestableModule` of @adatechnology/game-contracts:
|
|
257
|
+
* 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
|
|
66
258
|
* press H to equip it), targets at shooting distance, and, through `attach`, the weapon in the hands with its fire and reload motion,
|
|
67
259
|
* ejected casings, dropped magazines and sounds, driven by the host's tool events.
|
|
68
260
|
*/
|
|
@@ -71,6 +263,13 @@ declare function createWeaponsTestModule(options?: WeaponsTestModuleOptions): Te
|
|
|
71
263
|
readonly fx: WeaponFx | null;
|
|
72
264
|
};
|
|
73
265
|
|
|
266
|
+
/** Prefix of the item ids of the explosives that sit in the world (`world_fuel_barrel`). */
|
|
267
|
+
declare const WORLD_EXPLOSIVE_PREFIX = "world_";
|
|
268
|
+
/** The ids of the explosives of the arsenal that the area puts in the world. */
|
|
269
|
+
declare const WORLD_EXPLOSIVE_IDS: readonly string[];
|
|
270
|
+
/** 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. */
|
|
271
|
+
declare const worldExplosiveItem: (def: ExplosiveDef, name: string) => TestableItem | undefined;
|
|
272
|
+
|
|
74
273
|
/** A low-poly prop: its destruction spec (box parts only) and one colour per part. */
|
|
75
274
|
interface WeaponProp {
|
|
76
275
|
spec: DestructibleSpec;
|
|
@@ -85,4 +284,243 @@ declare function buildProp(THREE: typeof THREE_NS, prop: WeaponProp): THREE_NS.G
|
|
|
85
284
|
/** The model of a weapon for the hands or a shelf: the same prop the counters show. */
|
|
86
285
|
declare function buildWeaponModel(THREE: typeof THREE_NS, def: Pick<WeaponDef, 'id' | 'category' | 'mass'>): THREE_NS.Group;
|
|
87
286
|
|
|
88
|
-
|
|
287
|
+
/** How the gallery builders describe a weapon: the short keys of `data/models.json` (the page's own option names), all optional. */
|
|
288
|
+
interface ModelOptions {
|
|
289
|
+
/** Total length and barrel length in mm, and the calibre text, as the weapons table gives them. */
|
|
290
|
+
L?: number;
|
|
291
|
+
B?: number;
|
|
292
|
+
cal?: string;
|
|
293
|
+
/** Pistol style (`glock`, `taurus`, `g2c`, `beretta`, `pt100`, `sig`, `cz`, `m1911`, `makarov`, `fiveseven`, `deagle`), slide height, grip length. */
|
|
294
|
+
st?: string;
|
|
295
|
+
h?: number;
|
|
296
|
+
gl?: number;
|
|
297
|
+
deagle?: number;
|
|
298
|
+
/** Metal and furniture finish. */
|
|
299
|
+
steel?: number;
|
|
300
|
+
stain?: number;
|
|
301
|
+
wood?: number;
|
|
302
|
+
olive?: number;
|
|
303
|
+
tan?: number;
|
|
304
|
+
/** Selector or safety mark, cyclic rate (rpm), rounds in a burst, how unreliable (`rel`). */
|
|
305
|
+
sel?: number;
|
|
306
|
+
rpm?: number;
|
|
307
|
+
burst?: number;
|
|
308
|
+
rel?: number;
|
|
309
|
+
/** Rifle layout. */
|
|
310
|
+
stock?: string;
|
|
311
|
+
stockLen?: number;
|
|
312
|
+
hg?: string;
|
|
313
|
+
hgFrac?: number;
|
|
314
|
+
hR?: number;
|
|
315
|
+
wR?: number;
|
|
316
|
+
br?: number;
|
|
317
|
+
grip?: string;
|
|
318
|
+
gripAt?: number;
|
|
319
|
+
mag?: string;
|
|
320
|
+
magLen?: number;
|
|
321
|
+
magAt?: number;
|
|
322
|
+
magMat?: string;
|
|
323
|
+
curve?: number;
|
|
324
|
+
fore?: number;
|
|
325
|
+
tubeLen?: number;
|
|
326
|
+
scope?: number;
|
|
327
|
+
brake?: number;
|
|
328
|
+
ejectBack?: number;
|
|
329
|
+
round?: number;
|
|
330
|
+
ar?: number;
|
|
331
|
+
ak?: number;
|
|
332
|
+
g3?: number;
|
|
333
|
+
charge?: number;
|
|
334
|
+
rail?: number;
|
|
335
|
+
jacket?: number;
|
|
336
|
+
gas?: number;
|
|
337
|
+
noFH?: number;
|
|
338
|
+
carry?: number;
|
|
339
|
+
bipod?: number;
|
|
340
|
+
bolt?: number;
|
|
341
|
+
lever?: number;
|
|
342
|
+
tube?: number;
|
|
343
|
+
pump?: number;
|
|
344
|
+
heat?: number;
|
|
345
|
+
/** Chambers of the revolver cylinder (default 6): the capacity of the weapon. */
|
|
346
|
+
chambers?: number;
|
|
347
|
+
bayo?: number;
|
|
348
|
+
rod?: number;
|
|
349
|
+
bands?: number;
|
|
350
|
+
shot?: number;
|
|
351
|
+
/** Launcher type: `rpg`, `m72`, `at4`, `carl`, `flame`, `flameDIY`. */
|
|
352
|
+
lt?: string;
|
|
353
|
+
}
|
|
354
|
+
/** The moving mechanism of a model, which picks its fire, reload and clear motion. */
|
|
355
|
+
type ModelFamily = 'pistol' | 'revolver' | 'rifle' | 'semiint' | 'semi12' | 'p90' | 'belt' | 'pump' | 'lever' | 'bolt' | 'boltmag' | 'break' | 'rocket' | 'flame';
|
|
356
|
+
/** The named parts a model exposes to the animation: pivots and marks inside the model, never copies. */
|
|
357
|
+
interface ModelParts {
|
|
358
|
+
family: ModelFamily;
|
|
359
|
+
/** Recoil strength of the model (the page's `kick`). */
|
|
360
|
+
kick?: number;
|
|
361
|
+
/** How far the slide or bolt travels back, in metres. */
|
|
362
|
+
stroke?: number;
|
|
363
|
+
slide?: THREE_NS.Object3D;
|
|
364
|
+
bolt?: THREE_NS.Object3D;
|
|
365
|
+
boltHandle?: THREE_NS.Object3D;
|
|
366
|
+
boltHandleRest?: number;
|
|
367
|
+
mag?: THREE_NS.Object3D | null;
|
|
368
|
+
/** How far a magazine drops, and `1` for one that goes up. */
|
|
369
|
+
magDrop?: number;
|
|
370
|
+
magDir?: number;
|
|
371
|
+
trigger?: THREE_NS.Object3D;
|
|
372
|
+
hammer?: THREE_NS.Object3D;
|
|
373
|
+
lever?: THREE_NS.Object3D;
|
|
374
|
+
pump?: THREE_NS.Object3D;
|
|
375
|
+
belt?: THREE_NS.Object3D;
|
|
376
|
+
cover?: THREE_NS.Object3D;
|
|
377
|
+
crane?: THREE_NS.Object3D;
|
|
378
|
+
cylinder?: THREE_NS.Object3D;
|
|
379
|
+
chambers?: THREE_NS.Object3D[];
|
|
380
|
+
barrels?: THREE_NS.Object3D;
|
|
381
|
+
breech?: THREE_NS.Object3D[];
|
|
382
|
+
/** The existing selector or safety mesh; the gallery draws it but does not move it. */
|
|
383
|
+
safety?: THREE_NS.Object3D;
|
|
384
|
+
muzzle?: THREE_NS.Object3D;
|
|
385
|
+
eject?: THREE_NS.Object3D;
|
|
386
|
+
loadPort?: THREE_NS.Object3D;
|
|
387
|
+
topLoad?: THREE_NS.Object3D;
|
|
388
|
+
/** Parts that glow with barrel heat; each owns a clone of its material. */
|
|
389
|
+
glow: THREE_NS.Mesh[];
|
|
390
|
+
/** Launchers. */
|
|
391
|
+
launcherType?: string;
|
|
392
|
+
disposable?: boolean;
|
|
393
|
+
rear?: THREE_NS.Object3D;
|
|
394
|
+
round?: THREE_NS.Object3D;
|
|
395
|
+
roundRest?: number;
|
|
396
|
+
makeRound?: () => THREE_NS.Object3D;
|
|
397
|
+
gauge?: THREE_NS.Object3D;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
/** One weapon of the gallery as `data/models.json` keeps it: the builder, the measures in mm and the builder's options. */
|
|
401
|
+
interface ModelEntry {
|
|
402
|
+
readonly builder: 'pistol' | 'revolver' | 'rifle' | 'bullpup' | 'p90' | 'break' | 'm2' | 'launcher';
|
|
403
|
+
readonly caliber: string;
|
|
404
|
+
readonly length: number;
|
|
405
|
+
readonly barrel: number;
|
|
406
|
+
readonly options: ModelOptions;
|
|
407
|
+
readonly variantOf?: string;
|
|
408
|
+
}
|
|
409
|
+
declare const MODEL_ENTRIES: Readonly<Record<string, ModelEntry>>;
|
|
410
|
+
/**
|
|
411
|
+
* 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
|
|
412
|
+
* `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.
|
|
413
|
+
*/
|
|
414
|
+
declare const ARCHETYPE_MODELS: Readonly<Record<string, string>>;
|
|
415
|
+
/** 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`. */
|
|
416
|
+
interface WeaponModel {
|
|
417
|
+
readonly id: string;
|
|
418
|
+
readonly root: THREE_NS.Group;
|
|
419
|
+
readonly inner: THREE_NS.Group;
|
|
420
|
+
readonly parts: ModelParts;
|
|
421
|
+
}
|
|
422
|
+
declare const hasWeaponModel: (id: string) => boolean;
|
|
423
|
+
/** 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. */
|
|
424
|
+
declare function buildWeaponModelById(THREE: typeof THREE_NS, id: string): WeaponModel | undefined;
|
|
425
|
+
|
|
426
|
+
type Three = typeof THREE_NS;
|
|
427
|
+
type Material = THREE_NS.Material;
|
|
428
|
+
type Parent = THREE_NS.Object3D;
|
|
429
|
+
declare const createMaterials: (THREE: Three) => {
|
|
430
|
+
metal: THREE_NS.MeshStandardMaterial;
|
|
431
|
+
steel: THREE_NS.MeshStandardMaterial;
|
|
432
|
+
steelL: THREE_NS.MeshStandardMaterial;
|
|
433
|
+
dark: THREE_NS.MeshStandardMaterial;
|
|
434
|
+
poly: THREE_NS.MeshStandardMaterial;
|
|
435
|
+
olive: THREE_NS.MeshStandardMaterial;
|
|
436
|
+
tan: THREE_NS.MeshStandardMaterial;
|
|
437
|
+
wood: THREE_NS.MeshStandardMaterial;
|
|
438
|
+
woodL: THREE_NS.MeshStandardMaterial;
|
|
439
|
+
brass: THREE_NS.MeshStandardMaterial;
|
|
440
|
+
copper: THREE_NS.MeshStandardMaterial;
|
|
441
|
+
lead: THREE_NS.MeshStandardMaterial;
|
|
442
|
+
shell: THREE_NS.MeshStandardMaterial;
|
|
443
|
+
glass: THREE_NS.MeshStandardMaterial;
|
|
444
|
+
lens: THREE_NS.MeshStandardMaterial;
|
|
445
|
+
rubber: THREE_NS.MeshStandardMaterial;
|
|
446
|
+
white: THREE_NS.MeshStandardMaterial;
|
|
447
|
+
hole: THREE_NS.MeshStandardMaterial;
|
|
448
|
+
bake: THREE_NS.MeshStandardMaterial;
|
|
449
|
+
rust: THREE_NS.MeshStandardMaterial;
|
|
450
|
+
rustD: THREE_NS.MeshStandardMaterial;
|
|
451
|
+
worn: THREE_NS.MeshStandardMaterial;
|
|
452
|
+
fire: THREE_NS.MeshBasicMaterial;
|
|
453
|
+
fire2: THREE_NS.MeshBasicMaterial;
|
|
454
|
+
flashA: THREE_NS.MeshBasicMaterial;
|
|
455
|
+
flashB: THREE_NS.MeshBasicMaterial;
|
|
456
|
+
smokeP: THREE_NS.MeshStandardMaterial;
|
|
457
|
+
/** Launcher paints. */
|
|
458
|
+
yellow: THREE_NS.MeshStandardMaterial;
|
|
459
|
+
red: THREE_NS.MeshStandardMaterial;
|
|
460
|
+
redPaint: THREE_NS.MeshStandardMaterial;
|
|
461
|
+
tape: THREE_NS.MeshStandardMaterial;
|
|
462
|
+
pipe: THREE_NS.MeshStandardMaterial;
|
|
463
|
+
green: THREE_NS.MeshStandardMaterial;
|
|
464
|
+
/** Magazine finishes named by the options. */
|
|
465
|
+
bakelite: THREE_NS.MeshStandardMaterial;
|
|
466
|
+
polyMag: THREE_NS.MeshStandardMaterial;
|
|
467
|
+
};
|
|
468
|
+
type ModelMaterials = ReturnType<typeof createMaterials>;
|
|
469
|
+
/**
|
|
470
|
+
* 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)`),
|
|
471
|
+
* so that the builders read like the originals. `roundness` is the page's `RF`: how round the next boxes are, `null` for the default.
|
|
472
|
+
*/
|
|
473
|
+
interface ModelKit {
|
|
474
|
+
readonly THREE: Three;
|
|
475
|
+
readonly M: ModelMaterials;
|
|
476
|
+
roundness: number | null;
|
|
477
|
+
group(): THREE_NS.Group;
|
|
478
|
+
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;
|
|
479
|
+
/** Cylinders along x, y and z. `radiusEnd` makes a cone. */
|
|
480
|
+
cylinderX(parent: Parent, radius: number, length: number, material: Material, x: number, y: number, z: number, segments?: number, radiusEnd?: number): THREE_NS.Mesh;
|
|
481
|
+
cylinderY(parent: Parent, radius: number, height: number, material: Material, x: number, y: number, z: number, segments?: number, radiusEnd?: number): THREE_NS.Mesh;
|
|
482
|
+
cylinderZ(parent: Parent, radius: number, length: number, material: Material, x: number, y: number, z: number, segments?: number): THREE_NS.Mesh;
|
|
483
|
+
sphere(parent: Parent, radius: number, material: Material, x: number, y: number, z: number, detail?: number): THREE_NS.Mesh;
|
|
484
|
+
torus(parent: Parent, geometry: THREE_NS.TorusGeometry, material: Material, x: number, y: number, z: number): THREE_NS.Mesh;
|
|
485
|
+
mark(parent: Parent, x: number, y: number, z: number): THREE_NS.Object3D;
|
|
486
|
+
pivot(parent: Parent, x?: number, y?: number, z?: number): THREE_NS.Group;
|
|
487
|
+
}
|
|
488
|
+
/** One kit per three.js namespace: the materials and the geometry cache are shared by every model built with it. */
|
|
489
|
+
declare function modelKit(THREE: Three): ModelKit;
|
|
490
|
+
|
|
491
|
+
/** The shapes the gallery draws: rimfire, straight rimless (`p`), straight rimmed (`rimp`), bottleneck rimless (`r`), bottleneck rimmed (`rr`) and shotgun shell. */
|
|
492
|
+
type CartridgeShape = 'shell' | 'rim' | 'p' | 'rimp' | 'r' | 'rr';
|
|
493
|
+
/** The gallery's cartridge type of a calibre, from its case type, rim and dimensions. */
|
|
494
|
+
declare function cartridgeShape(caliber: Pick<CaliberDef, 'caseType' | 'rim'>, dims: CartridgeDims): CartridgeShape;
|
|
495
|
+
/** Port of the gallery's `cartridge`: the round standing on its base, in millimetres (the gallery shows it enlarged), brass case and copper or lead bullet. */
|
|
496
|
+
declare function buildCartridge(kit: ModelKit, dims: CartridgeDims, shape: CartridgeShape): THREE_NS.Group;
|
|
497
|
+
/** An empty case in metres, lying along x with the base at the origin: the brass the weapon throws out. */
|
|
498
|
+
declare function buildCasing(kit: ModelKit, dims: CartridgeDims, shape: CartridgeShape): {
|
|
499
|
+
group: THREE_NS.Group;
|
|
500
|
+
radius: number;
|
|
501
|
+
length: number;
|
|
502
|
+
};
|
|
503
|
+
/** A live round in metres, lying along x with the base at the origin: what is loaded into a weapon and what a clear throws out. */
|
|
504
|
+
declare function buildRound(kit: ModelKit, dims: CartridgeDims, shape: CartridgeShape): {
|
|
505
|
+
group: THREE_NS.Group;
|
|
506
|
+
radius: number;
|
|
507
|
+
};
|
|
508
|
+
|
|
509
|
+
/** Dresses the model for how worn the weapon is. The first call keeps the finish each mesh came with, so any condition can be put back. */
|
|
510
|
+
declare function applyCondition(kit: ModelKit, model: WeaponModel, condition: string): void;
|
|
511
|
+
|
|
512
|
+
/** The parts of a model by the id the clips use: `slide`, `mag`, `trigger`..., `breech_0`, `chamber_3`. */
|
|
513
|
+
declare function partRegistry(parts: ModelParts): Map<string, THREE_NS.Object3D>;
|
|
514
|
+
|
|
515
|
+
/** What the clips of a weapon are written from: its model (parts and mechanism), its calibre's case and how its rule reloads it. */
|
|
516
|
+
interface ClipContext {
|
|
517
|
+
readonly parts: ModelParts;
|
|
518
|
+
readonly family: ModelFamily;
|
|
519
|
+
readonly caseType: CaseType;
|
|
520
|
+
readonly reloadFamily: ReloadFamily | undefined;
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
/** Every clip a weapon model brings, by the ids `toolAnimationStep` asks for (`shot`, `cycle`, `reload`, `reload_empty`, `fault_<id>`, `clear_<id>`...). */
|
|
524
|
+
declare function buildToolClips(context: ClipContext): ToolClipSet;
|
|
525
|
+
|
|
526
|
+
export { ARCHETYPE_MODELS, BODY_ACTIONS, CLASS_REFERENCE_ENERGY, COUNTER_ITEM_ID, type CartridgeShape, type ClipContext, DEFAULT_ENERGY_CURVE, type DistanceCurve, type EnergyCurve, type FxLayers, GAME_DISTANCE_CURVE, GAME_SOUND_CLASSES, MECHANICAL_SOUNDS, MODEL_ENTRIES, type MechanicalSoundId, type ModelEntry, type ModelFamily, type ModelKit, type ModelMaterials, type ModelOptions, type ModelParts, type ShotExtras, type ShotSound, type ShotSoundClass, type ShotSoundInput, type ShotSoundOptions, type SoundClassDef, type SoundStep, WEAPON_ITEM_PREFIX, WORLD_EXPLOSIVE_IDS, WORLD_EXPLOSIVE_PREFIX, type WeaponAudio, type WeaponAudioOptions, type WeaponFx, type WeaponFxOptions, type WeaponModel, type WeaponProp, type WeaponsTestModuleOptions, applyCondition, buildCartridge, buildCasing, buildProp, buildRound, buildToolClips, buildWeaponModel, buildWeaponModelById, cartridgeShape, computeShotSound, createWeaponAudio, createWeaponFx, createWeaponsTestModule, hasWeaponModel, mechanicalSoundOf, modelKit, partRegistry, weaponProp, weaponsLayout, worldExplosiveItem };
|