@adatechnology/game-vehicles-three 0.4.0 → 0.6.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,57 +1,9 @@
1
- import { Damageable, VehicleContext, VehicleKit, CabinSource } from '@adatechnology/game-vehicles';
2
- import { FleetDims } from '@adatechnology/game-vehicles-fleet';
3
- import { EffectSink, Vec3, TestableModule } from '@adatechnology/game-contracts';
4
-
5
- type VehicleQuality = 'high' | 'lite';
6
- interface BuildVehicleOptions {
7
- /** `high`: the kit's vehicle at full detail. `lite`: fused into six meshes. Default `high`. */
8
- quality?: VehicleQuality;
9
- /** Body colour as a CSS colour. Wins over `seed`. */
10
- color?: string;
11
- /** Picks the body colour from the palette of the vehicle's group. */
12
- seed?: number | string;
13
- /** State of the vehicle. Default `intact`. */
14
- state?: 'intact' | 'damaged' | 'modified';
15
- }
16
- interface BuiltVehicle {
17
- key: string;
18
- quality: VehicleQuality;
19
- /** The colour the body ended up with, or null when the vehicle keeps its own paint. */
20
- color: string | null;
21
- seed: number | string | null;
22
- /** Group in the game frame: front on +z, right on -x, centred on x and z, wheels on y = 0. */
23
- group: any;
24
- /** Damageable boxes in the game frame. */
25
- damageables: Damageable[];
26
- triangles: number;
27
- drawCalls: number;
28
- /** Measured size of the group in metres: length along z, width along x, height along y. */
29
- length: number;
30
- width: number;
31
- height: number;
32
- /** Pieces dropped for being smaller than 3 cm (lite only). */
33
- pruned: number;
34
- /** The measured size the team recorded for this vehicle, when the fleet knows it. */
35
- expected: FleetDims | undefined;
36
- /** The kit's context, for damage and animation (full detail only). */
37
- context: VehicleContext | null;
38
- dispose(): void;
39
- }
40
- interface VehiclesThree {
41
- readonly THREE: any;
42
- readonly kit: VehicleKit;
43
- build(key: string, options?: BuildVehicleOptions): BuiltVehicle;
44
- }
45
- interface VehiclesThreeOptions {
46
- kit: VehicleKit;
47
- /** Vehicle id to the group id whose palette paints it. Defaults to the fleet group of the vehicle (`military` for the military ones). */
48
- groupOf?: (key: string) => string;
49
- }
50
- /**
51
- * Builds vehicles in a game frame. Port of `FrotaLeve.criar(...).construir` (frota-leve.js 14311-14442): the kit builds with +x to the front
52
- * and +z to the right; the game wants +z to the front and -x to the right, the vehicle centred on x and z and standing on y = 0.
53
- */
54
- declare function createVehiclesThree(THREE: any, options: VehiclesThreeOptions): VehiclesThree;
1
+ import { E as EngineProfile, V as VehicleSoundKeys } from './testing-gEnSqEF6.js';
2
+ export { B as BIKE_ENGINE, a as BuildVehicleOptions, b as BuiltVehicle, C as CAR_ENGINE, c as CRASH_SPEEDS, D as DEFAULT_TEST_VEHICLES, d as DEFAULT_TEST_WRECKS, e as DEFAULT_VEHICLE_SOUND_KEYS, f as DocumentLike, g as ENGINE_PROFILES, h as EffectsLike, i as EngineLayer, j as EngineLoadLayer, F as FleetDims, M as ModuleRoomLike, P as PAGE_ITEM_ALIASES, k as PAGE_SCENARIO_ALIASES, l as PROVING_AREA_ID, m as PROVING_TEXT, n as ProvingModuleOptions, o as ProvingRoomLike, p as ProvingText, T as TRUCK_ENGINE, q as VEHICLES_AREA_ID, r as VEHICLE_SCENARIO_IDS, s as VehicleEffectIds, t as VehicleFleetContent, u as VehicleQuality, v as VehicleSoundIds, w as VehicleWreck, x as VehiclesContext, y as VehiclesRoom, z as VehiclesTestFleet, A as VehiclesTestOptions, G as VehiclesThree, H as VehiclesThreeOptions, I as createProvingModule, J as createVehiclesTestModule, K as createVehiclesThree, L as defaultEffectIds, N as defaultSoundIds, O as loadProvingModule, Q as loadVehiclesTestModule } from './testing-gEnSqEF6.js';
3
+ import { EffectSink, Vec3, AudioSink } from '@adatechnology/game-contracts';
4
+ import { CabinSource } from '@adatechnology/game-vehicles';
5
+ import { LoopRecipe, Falloff, SoundRecipe, SoundBank } from '@adatechnology/game-audio';
6
+ import '@adatechnology/game-vehicles-proving';
55
7
 
56
8
  /**
57
9
  * Keeps the host's effects told where the cabins of the vehicles are and how open they are (`EffectSink.enclose`), so the smoke, dust and steam
@@ -74,6 +26,92 @@ interface CabinSmoke {
74
26
  }
75
27
  declare function createCabinSmoke(): CabinSmoke;
76
28
 
29
+ /** How a vehicle loop falls off: `1 / (1 + d² × 0.004)`, the game's one-shot curve, with the cutoff muffled by `1 + d × 0.01` (a car far away is dull). */
30
+ declare const VEHICLE_LOOP_FALLOFF: Falloff;
31
+ /** The engines (car, truck, bike) and the tyres, as loops. */
32
+ declare const VEHICLE_LOOPS: readonly LoopRecipe[];
33
+ /** The one-shots: the starter, the engine stopping, crashes by speed, and the doors, trunk and hood of a car. */
34
+ declare const VEHICLE_SOUNDS: readonly SoundRecipe[];
35
+ declare const VEHICLE_SOUND_BANK: SoundBank;
36
+
37
+ /** What one engine loop is set to this frame. `frequency` is absent for the load layer (noise has no pitch). */
38
+ type EngineLayerSetting = {
39
+ readonly sound: string;
40
+ readonly volume: number;
41
+ readonly frequency?: number;
42
+ readonly cutoff: number;
43
+ };
44
+ type EngineMixInput = {
45
+ readonly rpm: number;
46
+ /** 0..1, how open the throttle is (the engine's load). */
47
+ readonly throttle: number;
48
+ };
49
+ /** The firing frequency of a four-stroke engine, Hz: every cylinder fires once every two turns. */
50
+ declare const firingHz: (profile: EngineProfile, rpm: number) => number;
51
+ /** RPM as a share of the range: 0 at idle, 1 at the redline. */
52
+ declare const rpmShare: (profile: EngineProfile, rpm: number) => number;
53
+ /** Equal-power weight of a layer centred at `centre` with `width` at the normalised RPM `n`. */
54
+ declare const layerWeight: (centre: number, width: number, n: number) => number;
55
+ /**
56
+ * The engine's loops for an RPM and a throttle: every tone layer at the firing frequency times its harmonic, faded in and out across the RPM range so
57
+ * the sum stays even, louder and brighter under load; the load layer opens with the throttle. A stopped engine (`rpm` 0) is silent.
58
+ */
59
+ declare function engineMix(profile: EngineProfile, input: EngineMixInput): EngineLayerSetting[];
60
+ /**
61
+ * A guess of the RPM from the speed for a driver without an engine model: the gear is kept between calls (up above 85% of the redline, down below
62
+ * 40%), so the RPM climbs and drops at each shift as it does in a real car.
63
+ */
64
+ declare function createGearGuess(profile: EngineProfile): {
65
+ rpm(speed: number, throttle: number): number;
66
+ readonly gear: number;
67
+ };
68
+
69
+ /** What the vehicle is doing this frame. Without `rpm` (a driver with no engine model) the RPM is guessed from the speed through the profile's gears. */
70
+ type VehicleSoundFrame = {
71
+ readonly dt: number;
72
+ readonly position: Vec3;
73
+ /** m/s, signed or not. */
74
+ readonly speed: number;
75
+ /** 0..1. */
76
+ readonly throttle: number;
77
+ readonly rpm?: number;
78
+ /** 0..1: how much the tyres slide (the largest wheel slip; 1 = locked or spinning). */
79
+ readonly slip?: number;
80
+ /** What the tyres are on: `dirt` for earth, gravel, sand or grass; anything else squeals as asphalt. */
81
+ readonly surface?: 'asphalt' | 'dirt';
82
+ };
83
+ type VehicleSoundOptions = {
84
+ readonly profile?: EngineProfile;
85
+ /** Any of the one-shot and tyre ids, pointed at other sounds. */
86
+ readonly sounds?: Partial<VehicleSoundKeys>;
87
+ /** Seconds the starter turns before the engine catches (the `engine_start` recipe catches at 0.75 s). */
88
+ readonly crankSeconds?: number;
89
+ };
90
+ /** What was asked of the sink, for the checks and the bench: the RPM in use and the level of each loop. */
91
+ type VehicleSoundReading = {
92
+ readonly running: boolean;
93
+ readonly rpm: number;
94
+ readonly levels: Readonly<Record<string, number>>;
95
+ };
96
+ type VehicleSound = {
97
+ /** Turns the key: the starter, then the engine catches with a flare of RPM. `fail` cranks without catching (no fuel, a dead engine). */
98
+ start(position: Vec3, options?: {
99
+ readonly fail?: boolean;
100
+ }): void;
101
+ /** Ignition off: the engine runs down. */
102
+ stop(position: Vec3): void;
103
+ /** A hit at `speed` m/s: light, medium or heavy by speed, louder with it. */
104
+ crash(speed: number, position: Vec3): 'light' | 'medium' | 'heavy';
105
+ update(frame: VehicleSoundFrame): void;
106
+ readonly reading: VehicleSoundReading;
107
+ dispose(): void;
108
+ };
109
+ /**
110
+ * The sounds of one vehicle on a host's sink (`ModuleHost.audio`): the engine loops by RPM and load, the starter, the tyres skidding and rolling,
111
+ * and crashes by speed. The loops are placed at the vehicle every frame (distance and side come from the sink). Works without a sink (silent).
112
+ */
113
+ declare function createVehicleSound(audio: AudioSink | undefined, options?: VehicleSoundOptions): VehicleSound;
114
+
77
115
  /**
78
116
  * The light mode of the team's Frota Leve (frota-leve.js 14202-14310): a built vehicle fused into six meshes, one per class of material,
79
117
  * with the meshes nobody sees from outside left out. A literal port: the classes, the thresholds (3 cm prune, 0.99 opacity, 0.5 metalness,
@@ -113,135 +151,19 @@ declare function fuse(THREE: any, c: any, pivot: any, paintColor: any, primary:
113
151
  /** One mesh per class that has triangles. */
114
152
  declare function liteMeshes(THREE: any, fusion: LiteFusion, materials: Record<LiteClass, any>): any[];
115
153
 
116
- /** What the module needs of a document (canvas textures of the kit): a real `document`, or a stub in Node. */
117
- type DocumentLike = {
118
- createElement(tag: string): unknown;
119
- };
120
- /** The host's effects (`host.effects`, an `EffectSink` of the contracts: `game-vfx-three` is one): the module asks by id and writes no particle code. */
121
- type EffectsLike = EffectSink;
122
- /** The events the module turns into effect requests, and the effect id each one asks for. A game maps its own ids over these. */
123
- type VehicleEffectIds = {
124
- readonly ignite: string;
125
- readonly explode: string;
126
- readonly glass: string;
127
- readonly sparks: string;
128
- readonly leak: string;
129
- /** The leak of a pierced tank caught fire: the whole sequence (fire along the pool, then the blast). `leak` is only the pool and the drips. */
130
- readonly leakIgnited: string;
131
- readonly exhaust: string;
132
- };
133
- declare const defaultEffectIds: VehicleEffectIds;
134
- /** The sounds the module asks of `host.audio`, by id of the host's banks. `engine` is a loop (the game's saw through a 400 Hz low-pass), `horn` and `crash` one-shots. */
135
- type VehicleSoundIds = {
136
- readonly engine: string;
137
- readonly horn: string;
138
- readonly crash: string;
139
- };
140
- declare const defaultSoundIds: VehicleSoundIds;
141
- /** A damaged vehicle of the area: the item id, the fleet vehicle it is built from and the scenario of the kit applied while building. */
142
- type VehicleWreck = {
143
- readonly key: string;
144
- readonly vehicle: string;
145
- readonly scenario: string;
146
- };
147
- declare const DEFAULT_TEST_WRECKS: readonly VehicleWreck[];
148
- type VehiclesTestOptions = {
149
- /** `en` or `pt-BR` (default). */
150
- readonly locale?: string;
151
- /** The kit the vehicles are built with, per three.js namespace. Default: `createVehicleKit` with the fleet installed (`installFleet`). */
152
- readonly createKit?: (THREE: unknown) => VehicleKit;
153
- readonly document?: DocumentLike;
154
- /** The three.js namespace the door, hood and trunk clips are computed with (they are plain numbers, so any copy works). Default: the global `THREE`; without either the items bring no clips. */
155
- readonly three?: unknown;
156
- /** The vehicles to lay out, as fleet ids (default the 8 of the Frota test: hatch, sedan, pickup, sport bike, box truck, city bus, battle tank, attack helicopter). */
157
- readonly vehicles?: readonly string[];
158
- /** Wrecks laid out after the vehicles: item `key` is the fleet vehicle `vehicle` built with the registered damage `scenario` (default `sedan_burnt` and `hatch_burnt`, the fleet's `burnt`; an empty list lays none). */
159
- readonly wrecks?: readonly VehicleWreck[];
160
- /** Effect ids requested through `host.effects` (the defaults are ids of `game-vfx`: the Garagem's `car_fuel_tank` blast, the `vehicle_fire`, `vehicle_leak` (pool and drips only), `vehicle_leak_ignited` (the whole sequence) and `vehicle_exhaust` recipes written around a car from `engine_smoke` and `fuel_leak`, and the point-based `glass_burst` and `impact_metal`). */
161
- readonly effects?: Partial<VehicleEffectIds>;
162
- /** Sound ids requested through `host.audio` (the defaults are the `game-audio` ones: `engine_saw`, `horn`, `sfx_impact`). */
163
- readonly sounds?: Partial<VehicleSoundIds>;
164
- };
165
- /** The part of the test room the scenarios use (the room's `ScenarioContext.room` has all of it). */
166
- type PartView = {
167
- holes: {
168
- through?: boolean;
169
- }[];
170
- cracks: unknown[];
171
- dents: unknown[];
172
- status: string;
173
- hp: number;
174
- maxHp: number;
175
- temperature: number;
176
- burning: boolean;
177
- liters: number;
178
- melt: number;
179
- };
180
- type SpawnedVehicle = {
181
- objectId: string;
182
- root: {
183
- userData: Record<string, unknown>;
184
- };
154
+ /** Past this distance (m) an untouched vehicle draws fused: nobody sees a door seam from here, and the full model costs hundreds of draw calls. */
155
+ declare const VEHICLE_LOD_DISTANCE = 14;
156
+ type VehicleLodOptions = {
157
+ /** The clock (ms) the quiet time is read from (default `performance.now`). */
158
+ readonly now?: () => number;
185
159
  };
186
- type VehiclesRoom = {
187
- spawn(item: string, position?: Vec3, rotationY?: number): SpawnedVehicle;
188
- setTool(weaponId: string): void;
189
- /** Lets the tool in hand finish its draw time (the room's rule: a weapon cannot fire the moment it is taken). */
190
- waitUntilReady(): void;
191
- look(position: Vec3, target: Vec3): void;
192
- use(hold?: number): void;
193
- playAnimation(clipId: string, objectId?: string): boolean;
194
- world: {
195
- part(object: string, part: string): PartView;
196
- hit(object: string, hit: Record<string, unknown>): unknown;
197
- disassemble(object: string, joint: string, tool: string, dt: number): number;
198
- state(object: string): {
199
- joints: {
200
- id: string;
201
- open: boolean;
202
- }[];
203
- groups: unknown[][];
204
- };
205
- };
206
- log: {
207
- entries(filter: {
208
- type?: string;
209
- objectId?: string;
210
- }): readonly unknown[];
211
- };
212
- };
213
- /** What a scenario needs of the room: the pass/fail line, time, and the room for the ones that shoot and hit. */
214
- type VehiclesContext = {
215
- room: VehiclesRoom;
216
- expect(condition: boolean, label: string, data?: Record<string, unknown>): void;
217
- step(seconds: number): void;
218
- };
219
-
220
- declare const VEHICLES_AREA_ID = "vehicles_area";
221
- /** The eight vehicles of the Frota test page, in its order, and the item id each one has in the area. */
222
- declare const DEFAULT_TEST_VEHICLES: readonly string[];
223
- /**
224
- * The vehicles test area as a `TestableModule`: the vehicles of the Frota test (hatch, sedan, pickup, sport bike, box truck, city bus, battle tank, attack helicopter), each with its own
225
- * `DestructibleImpl` and its door, hood and trunk clips, the eleven scenarios of that page (literal) and two for the drivers. The bench sets the quality (full or light mode), the paint
226
- * by seed and palette, the driving mode and the surface, and shows the damageable boxes by material, the zones by type and the axes of the output frame. Effects (fire, glass, sparks,
227
- * exhaust) are requested by id through `host.effects` when the host has it; this module draws none.
228
- */
229
- declare function createVehiclesTestModule(options?: VehiclesTestOptions): TestableModule<VehiclesContext> & {
230
- readonly placed: ReadonlyMap<string, unknown>;
231
- };
232
- /** What `loadVehiclesTestModule` needs of a room: `TestRoom.loadModule` has it. */
233
- type ModuleRoomLike = {
234
- loadModule(module: never): unknown;
160
+ type VehicleLod = {
161
+ /** `touched`: hit or driven, from now on it always draws in full (its damage only exists there); `posed`: a door, hood or lid is open now (fused only while all are shut). */
162
+ update(distance: number, touched: boolean, posed?: boolean): void;
163
+ readonly fused: boolean;
164
+ dispose(): void;
235
165
  };
236
- /**
237
- * Loads the vehicles module into a room. The door, hood and trunk clips of the items are computed when the room reads the items, before the module is lent the room's three.js
238
- * (`attach`), so this first lends an empty module to learn the namespace and then loads the real one with it. Pass `three` to skip that.
239
- */
240
- declare function loadVehiclesTestModule<Room extends ModuleRoomLike>(room: Room, options?: VehiclesTestOptions): ReturnType<Room['loadModule']>;
241
-
242
- declare const VEHICLE_SCENARIO_IDS: readonly string[];
243
- /** The ids of the Frota test page, for whoever keeps a report or a link made against it. */
244
- declare const PAGE_SCENARIO_ALIASES: Readonly<Record<string, string>>;
245
- declare const PAGE_ITEM_ALIASES: Readonly<Record<string, string>>;
166
+ /** Shows `full` near and the kit's fused light mode (one mesh per class of material) far, in `root`'s own space. Hit tests read the full model, visible or not. */
167
+ declare function createVehicleLod(kit: any, context: any, root: any, full: any, options?: VehicleLodOptions): VehicleLod;
246
168
 
247
- export { type BuildVehicleOptions, type BuiltVehicle, type CabinSmoke, DEFAULT_TEST_VEHICLES, DEFAULT_TEST_WRECKS, type DocumentLike, type EffectsLike, LITE_CLASSES, type LiteClass, type LiteFusion, type ModuleRoomLike, PAGE_ITEM_ALIASES, PAGE_SCENARIO_ALIASES, PRUNE_BELOW, VEHICLES_AREA_ID, VEHICLE_SCENARIO_IDS, type VehicleEffectIds, type VehicleQuality, type VehicleSoundIds, type VehicleWreck, type VehiclesContext, type VehiclesRoom, type VehiclesTestOptions, type VehiclesThree, type VehiclesThreeOptions, classColor, classify, createCabinSmoke, createVehiclesTestModule, createVehiclesThree, defaultEffectIds, defaultSoundIds, fuse, liteMaterials, liteMeshes, loadVehiclesTestModule };
169
+ export { type CabinSmoke, type EngineLayerSetting, type EngineMixInput, EngineProfile, LITE_CLASSES, type LiteClass, type LiteFusion, PRUNE_BELOW, VEHICLE_LOD_DISTANCE, VEHICLE_LOOPS, VEHICLE_LOOP_FALLOFF, VEHICLE_SOUNDS, VEHICLE_SOUND_BANK, type VehicleLod, type VehicleSound, type VehicleSoundFrame, VehicleSoundKeys, type VehicleSoundOptions, type VehicleSoundReading, classColor, classify, createCabinSmoke, createGearGuess, createVehicleLod, createVehicleSound, engineMix, firingHz, fuse, layerWeight, liteMaterials, liteMeshes, rpmShare };