@adatechnology/game-vehicles-three 0.3.7 → 0.4.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 +23 -2
- package/dist/index.global.js +122 -0
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +41 -0
- package/dist/index.js.map +1 -1
- package/package.json +8 -8
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Damageable, VehicleContext, VehicleKit } from '@adatechnology/game-vehicles';
|
|
1
|
+
import { Damageable, VehicleContext, VehicleKit, CabinSource } from '@adatechnology/game-vehicles';
|
|
2
2
|
import { FleetDims } from '@adatechnology/game-vehicles-fleet';
|
|
3
3
|
import { EffectSink, Vec3, TestableModule } from '@adatechnology/game-contracts';
|
|
4
4
|
|
|
@@ -53,6 +53,27 @@ interface VehiclesThreeOptions {
|
|
|
53
53
|
*/
|
|
54
54
|
declare function createVehiclesThree(THREE: any, options: VehiclesThreeOptions): VehiclesThree;
|
|
55
55
|
|
|
56
|
+
/**
|
|
57
|
+
* 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
|
|
58
|
+
* do not pass through a shut car: they go round it and get in only through an open door, a broken window or a bullet hole. `sync` every frame;
|
|
59
|
+
* a vehicle whose object left the scene is forgotten and its cabin ended.
|
|
60
|
+
*/
|
|
61
|
+
interface CabinSmoke {
|
|
62
|
+
/** Follows the cabin of a vehicle by its object id; `frame` is the object the host placed it in (the destructible's `frame`). */
|
|
63
|
+
track(id: string, source: CabinSource, frame: {
|
|
64
|
+
readonly parent: unknown | null;
|
|
65
|
+
}): void;
|
|
66
|
+
/** Ends the cabin of one vehicle now. */
|
|
67
|
+
untrack(id: string, effects: EffectSink | undefined): void;
|
|
68
|
+
/** Tells `effects` where every cabin is now. A host without `enclose` lets the smoke through, as before. */
|
|
69
|
+
sync(effects: EffectSink | undefined): void;
|
|
70
|
+
/** Ends every cabin (the module leaves). */
|
|
71
|
+
clear(effects: EffectSink | undefined): void;
|
|
72
|
+
/** The ids followed now. */
|
|
73
|
+
ids(): string[];
|
|
74
|
+
}
|
|
75
|
+
declare function createCabinSmoke(): CabinSmoke;
|
|
76
|
+
|
|
56
77
|
/**
|
|
57
78
|
* 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,
|
|
58
79
|
* 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,
|
|
@@ -223,4 +244,4 @@ declare const VEHICLE_SCENARIO_IDS: readonly string[];
|
|
|
223
244
|
declare const PAGE_SCENARIO_ALIASES: Readonly<Record<string, string>>;
|
|
224
245
|
declare const PAGE_ITEM_ALIASES: Readonly<Record<string, string>>;
|
|
225
246
|
|
|
226
|
-
export { type BuildVehicleOptions, type BuiltVehicle, 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, createVehiclesTestModule, createVehiclesThree, defaultEffectIds, defaultSoundIds, fuse, liteMaterials, liteMeshes, loadVehiclesTestModule };
|
|
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 };
|
package/dist/index.global.js
CHANGED
|
@@ -31,6 +31,7 @@ var GameVehiclesThree = (() => {
|
|
|
31
31
|
VEHICLE_SCENARIO_IDS: () => VEHICLE_SCENARIO_IDS,
|
|
32
32
|
classColor: () => classColor,
|
|
33
33
|
classify: () => classify,
|
|
34
|
+
createCabinSmoke: () => createCabinSmoke,
|
|
34
35
|
createVehiclesTestModule: () => createVehiclesTestModule,
|
|
35
36
|
createVehiclesThree: () => createVehiclesThree,
|
|
36
37
|
defaultEffectIds: () => defaultEffectIds,
|
|
@@ -42395,6 +42396,123 @@ var GameVehiclesThree = (() => {
|
|
|
42395
42396
|
root.userData.vehicle = vehicle;
|
|
42396
42397
|
return { root, vehicle };
|
|
42397
42398
|
}
|
|
42399
|
+
var CABIN_LEAK = 0.02;
|
|
42400
|
+
var HOLE_RATE_PER_AREA = 3e3;
|
|
42401
|
+
var CRACK_GAP_PER_METRE = 0.5;
|
|
42402
|
+
var THROUGH = 0.18;
|
|
42403
|
+
var HOLE_PATCH = 0.12;
|
|
42404
|
+
var FULL_SWING = 1.15;
|
|
42405
|
+
var SHELL_ROLES = /* @__PURE__ */ new Set(["door", "glass", "roof", "lid", "panel", "pillar"]);
|
|
42406
|
+
var GONE = /* @__PURE__ */ new Set(["broken", "melted", "ashes"]);
|
|
42407
|
+
function cabinBoxOf(vehicle) {
|
|
42408
|
+
const cabin = vehicle.meta.cabin;
|
|
42409
|
+
if (!cabin || !(cabin.x1 > cabin.x0) || !(cabin.y1 > cabin.y0) || !(cabin.z > 0)) return null;
|
|
42410
|
+
return cabin;
|
|
42411
|
+
}
|
|
42412
|
+
function swingOf(vehicle, partId) {
|
|
42413
|
+
const pivot = vehicle.vehicle?.getObjectByName?.(partId);
|
|
42414
|
+
const q = pivot?.quaternion;
|
|
42415
|
+
if (!q) return 0;
|
|
42416
|
+
const angle = 2 * Math.acos(Math.min(1, Math.abs(q.w)));
|
|
42417
|
+
return Math.min(1, angle / FULL_SWING);
|
|
42418
|
+
}
|
|
42419
|
+
var overlaps = (b, c, margin) => Math.abs(b.center[0] - (c.x0 + c.x1) / 2) <= b.size[0] / 2 + (c.x1 - c.x0) / 2 + margin && Math.abs(b.center[1] - (c.y0 + c.y1) / 2) <= b.size[1] / 2 + (c.y1 - c.y0) / 2 + margin && Math.abs(b.center[2]) <= b.size[2] / 2 + c.z + margin;
|
|
42420
|
+
function cabinEnclosure(source, options = {}) {
|
|
42421
|
+
const c = source.vehicle;
|
|
42422
|
+
const cabin = cabinBoxOf(c);
|
|
42423
|
+
const node = c.vehicle;
|
|
42424
|
+
if (!cabin || !node?.localToWorld) return null;
|
|
42425
|
+
const state = source.state();
|
|
42426
|
+
if (state.destroyed) return null;
|
|
42427
|
+
const V3 = node.position.constructor;
|
|
42428
|
+
const Quat = node.quaternion.constructor;
|
|
42429
|
+
const mid = [(cabin.x0 + cabin.x1) / 2, (cabin.y0 + cabin.y1) / 2, 0];
|
|
42430
|
+
const half = [(cabin.x1 - cabin.x0) / 2, (cabin.y1 - cabin.y0) / 2, cabin.z];
|
|
42431
|
+
const ajar = options.ajar ?? 0.06;
|
|
42432
|
+
const byId = new Map(state.parts.map((p) => [p.id, p]));
|
|
42433
|
+
const mainGroup = state.groups[0] ? new Set(state.groups[0]) : null;
|
|
42434
|
+
const openings = [];
|
|
42435
|
+
let crackLength = 0;
|
|
42436
|
+
const toCabin = (b) => ({
|
|
42437
|
+
center: [b.center[0] - mid[0], b.center[1] - mid[1], b.center[2] - mid[2]],
|
|
42438
|
+
halfSize: [b.size[0] / 2 + THROUGH, b.size[1] / 2 + THROUGH, b.size[2] / 2 + THROUGH]
|
|
42439
|
+
});
|
|
42440
|
+
node.updateWorldMatrix?.(true, false);
|
|
42441
|
+
const frame = options.frame ?? c.root;
|
|
42442
|
+
frame?.updateWorldMatrix?.(true, false);
|
|
42443
|
+
const inverse = node.matrixWorld.clone().invert();
|
|
42444
|
+
for (const def of source.model.parts) {
|
|
42445
|
+
if (!SHELL_ROLES.has(def.role) || !overlaps(def.box, cabin, 0.12)) continue;
|
|
42446
|
+
const part = byId.get(def.id);
|
|
42447
|
+
if (!part) continue;
|
|
42448
|
+
const gone = GONE.has(part.status) || mainGroup !== null && !mainGroup.has(def.id);
|
|
42449
|
+
const swung = (def.role === "door" || def.role === "lid") && swingOf(c, def.id) > ajar;
|
|
42450
|
+
if (gone || swung) {
|
|
42451
|
+
openings.push(toCabin(def.box));
|
|
42452
|
+
continue;
|
|
42453
|
+
}
|
|
42454
|
+
for (const hole of part.holes) {
|
|
42455
|
+
if (!hole.through && def.material !== "glass") continue;
|
|
42456
|
+
const area3 = Math.PI * (hole.diameter / 2) ** 2;
|
|
42457
|
+
const p = new V3(hole.point[0], hole.point[1], hole.point[2]);
|
|
42458
|
+
if (frame?.localToWorld) frame.localToWorld(p);
|
|
42459
|
+
p.applyMatrix4(inverse);
|
|
42460
|
+
openings.push({
|
|
42461
|
+
center: [p.x - mid[0], p.y - mid[1], p.z - mid[2]],
|
|
42462
|
+
halfSize: [HOLE_PATCH, HOLE_PATCH, HOLE_PATCH],
|
|
42463
|
+
// the patch is far bigger than the hole: only a share of what crosses it passes, more for a bigger hole
|
|
42464
|
+
rate: Math.min(4, area3 * HOLE_RATE_PER_AREA)
|
|
42465
|
+
});
|
|
42466
|
+
}
|
|
42467
|
+
for (const crack of part.cracks) crackLength += crack.length;
|
|
42468
|
+
}
|
|
42469
|
+
const center = node.localToWorld(new V3(mid[0], mid[1], mid[2]));
|
|
42470
|
+
const q = node.getWorldQuaternion(new Quat());
|
|
42471
|
+
const scale = node.getWorldScale(new V3());
|
|
42472
|
+
const leak = (options.leak ?? CABIN_LEAK) * (1 + crackLength * CRACK_GAP_PER_METRE);
|
|
42473
|
+
return {
|
|
42474
|
+
center: [center.x, center.y, center.z],
|
|
42475
|
+
halfSize: [half[0] * Math.abs(scale.x), half[1] * Math.abs(scale.y), half[2] * Math.abs(scale.z)],
|
|
42476
|
+
orientation: [q.x, q.y, q.z, q.w],
|
|
42477
|
+
openings: openings.map((o) => ({ ...o, center: [o.center[0] * scale.x, o.center[1] * scale.y, o.center[2] * scale.z], halfSize: [o.halfSize[0] * Math.abs(scale.x), o.halfSize[1] * Math.abs(scale.y), o.halfSize[2] * Math.abs(scale.z)] })),
|
|
42478
|
+
leak
|
|
42479
|
+
};
|
|
42480
|
+
}
|
|
42481
|
+
|
|
42482
|
+
// src/cabin-smoke.ts
|
|
42483
|
+
function createCabinSmoke() {
|
|
42484
|
+
const tracked = /* @__PURE__ */ new Map();
|
|
42485
|
+
const end = (id, entry, effects) => {
|
|
42486
|
+
if (entry.declared) effects?.enclose?.(id, null);
|
|
42487
|
+
tracked.delete(id);
|
|
42488
|
+
};
|
|
42489
|
+
return {
|
|
42490
|
+
track(id, source, frame) {
|
|
42491
|
+
tracked.set(id, { source, frame, declared: false, placed: false });
|
|
42492
|
+
},
|
|
42493
|
+
untrack(id, effects) {
|
|
42494
|
+
const entry = tracked.get(id);
|
|
42495
|
+
if (entry) end(id, entry, effects);
|
|
42496
|
+
},
|
|
42497
|
+
sync(effects) {
|
|
42498
|
+
if (!effects?.enclose) return;
|
|
42499
|
+
for (const [id, entry] of tracked) {
|
|
42500
|
+
if (!entry.frame.parent) {
|
|
42501
|
+
if (entry.placed) end(id, entry, effects);
|
|
42502
|
+
continue;
|
|
42503
|
+
}
|
|
42504
|
+
entry.placed = true;
|
|
42505
|
+
const enclosure = cabinEnclosure(entry.source, { frame: entry.frame });
|
|
42506
|
+
if (enclosure || entry.declared) effects.enclose(id, enclosure);
|
|
42507
|
+
entry.declared = enclosure !== null;
|
|
42508
|
+
}
|
|
42509
|
+
},
|
|
42510
|
+
clear(effects) {
|
|
42511
|
+
for (const [id, entry] of [...tracked]) end(id, entry, effects);
|
|
42512
|
+
},
|
|
42513
|
+
ids: () => [...tracked.keys()]
|
|
42514
|
+
};
|
|
42515
|
+
}
|
|
42398
42516
|
|
|
42399
42517
|
// ../game-vehicles-driving/dist/index.js
|
|
42400
42518
|
var defaultArcadeSpec = {
|
|
@@ -43456,6 +43574,7 @@ var GameVehiclesThree = (() => {
|
|
|
43456
43574
|
const settings = { quality: "high", paint: false, seed: 1, palette: "auto", driving: "arcade", surface: "dry_asphalt" };
|
|
43457
43575
|
const kits = /* @__PURE__ */ new WeakMap();
|
|
43458
43576
|
const placed = /* @__PURE__ */ new Map();
|
|
43577
|
+
const cabins = createCabinSmoke();
|
|
43459
43578
|
let host = null;
|
|
43460
43579
|
let three = null;
|
|
43461
43580
|
let counter = 0;
|
|
@@ -43520,6 +43639,7 @@ var GameVehiclesThree = (() => {
|
|
|
43520
43639
|
const kit = r.userData.kit;
|
|
43521
43640
|
const d = createVehicleDestructible(kit, r.userData.vehicle, { id, frame: root, name: text.items[itemKey] ?? key });
|
|
43522
43641
|
tapEffects(d);
|
|
43642
|
+
cabins.track(id, d, root);
|
|
43523
43643
|
r.userData.destructible = d;
|
|
43524
43644
|
return d;
|
|
43525
43645
|
},
|
|
@@ -43775,6 +43895,7 @@ var GameVehiclesThree = (() => {
|
|
|
43775
43895
|
}
|
|
43776
43896
|
if (host?.bench && boxKey() !== helpersShown && (host.bench.layer("damageables") || host.bench.layer("zones") || helpersShown !== "")) refreshLayers();
|
|
43777
43897
|
lane?.step(dt);
|
|
43898
|
+
cabins.sync(effects());
|
|
43778
43899
|
};
|
|
43779
43900
|
const count2 = () => {
|
|
43780
43901
|
let drawCalls = 0;
|
|
@@ -43875,6 +43996,7 @@ var GameVehiclesThree = (() => {
|
|
|
43875
43996
|
stopChange?.();
|
|
43876
43997
|
stopFrame();
|
|
43877
43998
|
stopBlocker?.();
|
|
43999
|
+
cabins.clear(effects());
|
|
43878
44000
|
clearHelpers();
|
|
43879
44001
|
clearLane();
|
|
43880
44002
|
host = null;
|