@adatechnology/game-vehicles-three 0.3.6 → 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 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 };
@@ -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,
@@ -3745,11 +3746,11 @@ var GameVehiclesThree = (() => {
3745
3746
  function installBoatsExtra(fx) {
3746
3747
  const kit = fx.kit;
3747
3748
  const THREE = kit.THREE;
3748
- const shared = fx.shared;
3749
+ const shared2 = fx.shared;
3749
3750
  const trl = fx.t;
3750
3751
  const lbl = fx.label;
3751
- if (!kit || !shared.EA) return;
3752
- const V3 = kit.V3, PI = Math.PI, MT = kit.materials, CM = kit.makeMaterial, _G = kit.geo, DS = THREE.DoubleSide, EA = shared.EA, tb = EA.tab;
3752
+ if (!kit || !shared2.EA) return;
3753
+ const V3 = kit.V3, PI = Math.PI, MT = kit.materials, CM = kit.makeMaterial, _G = kit.geo, DS = THREE.DoubleSide, EA = shared2.EA, tb = EA.tab;
3753
3754
  function sailGeo(T, Hd, C, cam, o) {
3754
3755
  o = o || {};
3755
3756
  const nu = o.nu || 10, nv = o.nv || 16, pos = [], idx = [], roach = o.roach || 0;
@@ -9617,11 +9618,11 @@ var GameVehiclesThree = (() => {
9617
9618
  function installHelicoptersExtra(fx) {
9618
9619
  const kit = fx.kit;
9619
9620
  const THREE = kit.THREE;
9620
- const shared = fx.shared;
9621
+ const shared2 = fx.shared;
9621
9622
  const trl = fx.t;
9622
9623
  const lbl = fx.label;
9623
9624
  const V3 = kit.V3, PI = Math.PI, MT = kit.materials, CM = kit.makeMaterial, G2 = kit.geo;
9624
- const GH = shared.GH;
9625
+ const GH = shared2.GH;
9625
9626
  function skids(c, o) {
9626
9627
  const mat = o.mat || MT.steel, z = o.z, y = o.y || 0.07, out = [];
9627
9628
  [1, -1].forEach(function(s) {
@@ -9768,7 +9769,7 @@ var GameVehiclesThree = (() => {
9768
9769
  hood: false
9769
9770
  },
9770
9771
  function(c) {
9771
- const EA = shared.EA, col = "#1f4f8a", blue = c.paint(col), white = c.paint("#e9e7e0"), blk = CM("#1c1d1f", { roughness: 0.6 });
9772
+ const EA = shared2.EA, col = "#1f4f8a", blue = c.paint(col), white = c.paint("#e9e7e0"), blk = CM("#1c1d1f", { roughness: 0.6 });
9772
9773
  const ST = [
9773
9774
  [1.6, 0.84, 0.92, 0.06, 2],
9774
9775
  [1.5, 0.64, 1.22, 0.66, 2.2],
@@ -10103,7 +10104,7 @@ var GameVehiclesThree = (() => {
10103
10104
  hood: false
10104
10105
  },
10105
10106
  function(c) {
10106
- const EA = shared.EA, wcol = "#eeece6", white = c.paint(wcol), mar = c.paint("#7a1e22"), gold = c.paint("#c49a3a"), blk = CM("#1c1d1f", { roughness: 0.6 });
10107
+ const EA = shared2.EA, wcol = "#eeece6", white = c.paint(wcol), mar = c.paint("#7a1e22"), gold = c.paint("#c49a3a"), blk = CM("#1c1d1f", { roughness: 0.6 });
10107
10108
  const ST = [
10108
10109
  [2.62, 0.95, 1.06, 0.08, 2],
10109
10110
  [2.48, 0.7, 1.45, 0.86, 2.2],
@@ -10488,7 +10489,7 @@ var GameVehiclesThree = (() => {
10488
10489
  hood: false
10489
10490
  },
10490
10491
  function(c) {
10491
- const EA = shared.EA, navyC = "#1b2c52", navy = c.paint(navyC), white = c.paint("#ecebe6"), yel = c.paint("#d7b23a"), blk = CM("#1c1d1f", { roughness: 0.6 });
10492
+ const EA = shared2.EA, navyC = "#1b2c52", navy = c.paint(navyC), white = c.paint("#ecebe6"), yel = c.paint("#d7b23a"), blk = CM("#1c1d1f", { roughness: 0.6 });
10492
10493
  const ST = [
10493
10494
  [3.36, 1, 1.12, 0.08, 2],
10494
10495
  [3.22, 0.76, 1.56, 0.96, 2.4],
@@ -10932,7 +10933,7 @@ var GameVehiclesThree = (() => {
10932
10933
  hood: false
10933
10934
  },
10934
10935
  function(c) {
10935
- const EA = shared.EA, blk = CM("#1a1b1d", { roughness: 0.6 });
10936
+ const EA = shared2.EA, blk = CM("#1a1b1d", { roughness: 0.6 });
10936
10937
  c.meta.matte = true;
10937
10938
  const cA = new THREE.Color("#3a4430"), cB = new THREE.Color("#66603f"), cC = new THREE.Color("#55613f"), cL = new THREE.Color("#8d958c");
10938
10939
  function camo(x, y, z, under) {
@@ -19988,7 +19989,7 @@ var GameVehiclesThree = (() => {
19988
19989
  function installPlanesExtra(fx) {
19989
19990
  const kit = fx.kit;
19990
19991
  const THREE = kit.THREE;
19991
- const shared = fx.shared;
19992
+ const shared2 = fx.shared;
19992
19993
  const trl = fx.t;
19993
19994
  const lbl = fx.label;
19994
19995
  const V3 = kit.V3, PI = Math.PI, MT = kit.materials, CM = kit.makeMaterial, _G = kit.geo, _DS = THREE.DoubleSide;
@@ -20140,7 +20141,7 @@ var GameVehiclesThree = (() => {
20140
20141
  m.rotation.y += -s * Math.atan2(a - b, w);
20141
20142
  return m;
20142
20143
  }
20143
- shared.GH = {
20144
+ shared2.GH = {
20144
20145
  pose3,
20145
20146
  starDecal,
20146
20147
  rrect,
@@ -20174,7 +20175,7 @@ var GameVehiclesThree = (() => {
20174
20175
  hood: false
20175
20176
  },
20176
20177
  function(c) {
20177
- const EA = shared.EA, yel = "#f0bd22";
20178
+ const EA = shared2.EA, yel = "#f0bd22";
20178
20179
  const Q = pose3([1.62, -0.78], 0.25, [-3.24, -0.27], 0.075), P = Q.P, TH = Q.TH;
20179
20180
  const grp = new THREE.Group();
20180
20181
  grp.position.set(0, Q.Y0, 0);
@@ -20486,7 +20487,7 @@ var GameVehiclesThree = (() => {
20486
20487
  });
20487
20488
  const pd = pod(
20488
20489
  c2,
20489
- shared.EA,
20490
+ shared2.EA,
20490
20491
  P(1.4, -0.6).x,
20491
20492
  P(-1.2, -0.45).x,
20492
20493
  P(0.1, -0.66).y,
@@ -20523,7 +20524,7 @@ var GameVehiclesThree = (() => {
20523
20524
  hood: false
20524
20525
  },
20525
20526
  function(c) {
20526
- const EA = shared.EA, wcol = "#ecebe6", white = c.paint(wcol), blue = c.paint("#1d4f8c"), grey = c.paint("#8e959a"), blk = CM("#1c1d1f", { roughness: 0.6 });
20527
+ const EA = shared2.EA, wcol = "#ecebe6", white = c.paint(wcol), blue = c.paint("#1d4f8c"), grey = c.paint("#8e959a"), blk = CM("#1c1d1f", { roughness: 0.6 });
20527
20528
  const ST = [
20528
20529
  [7.58, 1.5, 1.62, 0.08, 2],
20529
20530
  [7.35, 1.3, 1.82, 0.56, 2.2],
@@ -20911,7 +20912,7 @@ var GameVehiclesThree = (() => {
20911
20912
  hood: false
20912
20913
  },
20913
20914
  function(c) {
20914
- const EA = shared.EA, wcol = "#eceae3", white = c.paint(wcol), navy = c.paint("#1e2f55"), gold = c.paint("#c99a2e"), blk = CM("#1c1d1f", { roughness: 0.6 });
20915
+ const EA = shared2.EA, wcol = "#eceae3", white = c.paint(wcol), navy = c.paint("#1e2f55"), gold = c.paint("#c99a2e"), blk = CM("#1c1d1f", { roughness: 0.6 });
20915
20916
  const ST = [
20916
20917
  [5, 2.26, 2.86, 0.62, 2.2],
20917
20918
  [4.75, 2.08, 3, 0.98, 2.6],
@@ -21326,7 +21327,7 @@ var GameVehiclesThree = (() => {
21326
21327
  hood: false
21327
21328
  },
21328
21329
  function(c) {
21329
- const EA = shared.EA, wcol = "#efeeea", white = c.paint(wcol), silver = c.paint("#7d868e", { metalness: 0.45, roughness: 0.35 }), navy = c.paint("#23324f"), blk = CM("#15161a", { roughness: 0.5 });
21330
+ const EA = shared2.EA, wcol = "#efeeea", white = c.paint(wcol), silver = c.paint("#7d868e", { metalness: 0.45, roughness: 0.35 }), navy = c.paint("#23324f"), blk = CM("#15161a", { roughness: 0.5 });
21330
21331
  const ST = [
21331
21332
  [6.3, 1.13, 1.2, 0.06, 2],
21332
21333
  [6, 0.92, 1.44, 0.6, 2.1],
@@ -21707,7 +21708,7 @@ var GameVehiclesThree = (() => {
21707
21708
  hood: false
21708
21709
  },
21709
21710
  function(c) {
21710
- const EA = shared.EA, blk = CM("#1a1b1d", { roughness: 0.6 });
21711
+ const EA = shared2.EA, blk = CM("#1a1b1d", { roughness: 0.6 });
21711
21712
  c.meta.matte = true;
21712
21713
  const cA = new THREE.Color("#323f2b"), cB = new THREE.Color("#5f6d45"), cC = new THREE.Color("#7f8466"), cL = new THREE.Color("#a3abad");
21713
21714
  function camo(x, z, y, under) {
@@ -24365,7 +24366,7 @@ var GameVehiclesThree = (() => {
24365
24366
  function installWaterAir(fx) {
24366
24367
  const kit = fx.kit;
24367
24368
  const THREE = kit.THREE;
24368
- const shared = fx.shared;
24369
+ const shared2 = fx.shared;
24369
24370
  const trl = fx.t;
24370
24371
  const lbl = fx.label;
24371
24372
  const V3 = kit.V3, PI = Math.PI, MT = kit.materials, CM = kit.makeMaterial, _paintCol = kit.paintColor, G2 = kit.geo, DS = THREE.DoubleSide, clamp3 = kit.clamp;
@@ -25040,7 +25041,7 @@ var GameVehiclesThree = (() => {
25040
25041
  t.rotation.y += s > 0 ? -Math.atan(m) : Math.atan(m);
25041
25042
  return t;
25042
25043
  }
25043
- shared.EA = {
25044
+ shared2.EA = {
25044
25045
  colorize,
25045
25046
  tab,
25046
25047
  tabL,
@@ -25099,7 +25100,7 @@ var GameVehiclesThree = (() => {
25099
25100
  hood: false
25100
25101
  },
25101
25102
  function(c) {
25102
- const EA = shared.EA, tb = EA.tab, alu = CM("#9aa1a6", { metalness: 0.65, roughness: 0.38, side: DS }), aluD = CM("#7d8489", { metalness: 0.6, roughness: 0.45, side: DS });
25103
+ const EA = shared2.EA, tb = EA.tab, alu = CM("#9aa1a6", { metalness: 0.65, roughness: 0.38, side: DS }), aluD = CM("#7d8489", { metalness: 0.6, roughness: 0.45, side: DS });
25103
25104
  const L = 5, x0 = -2.5;
25104
25105
  const H = EA.boatHull({
25105
25106
  x0,
@@ -25251,7 +25252,7 @@ var GameVehiclesThree = (() => {
25251
25252
  hood: false
25252
25253
  },
25253
25254
  function(c) {
25254
- const EA = shared.EA, tb = EA.tab, L = 7.26, x0 = -3.63;
25255
+ const EA = shared2.EA, tb = EA.tab, L = 7.26, x0 = -3.63;
25255
25256
  const white = c.paint("#ecebe5", { roughness: 0.3, metalness: 0.1 }), navy = c.paint("#1f2f4a", { roughness: 0.3, metalness: 0.1 }), vinyl = CM("#e3ddd0", { roughness: 0.65 }), _vinylD = CM("#3c4a5c", { roughness: 0.65 }), teak = CM("#8a6a45", { roughness: 0.8 });
25256
25257
  const H = EA.boatHull({
25257
25258
  x0,
@@ -25498,7 +25499,7 @@ var GameVehiclesThree = (() => {
25498
25499
  hood: false
25499
25500
  },
25500
25501
  function(c) {
25501
- const EA = shared.EA, tb = EA.tab, L = 11, x0 = -5.5;
25502
+ const EA = shared2.EA, tb = EA.tab, L = 11, x0 = -5.5;
25502
25503
  const blue = c.paint("#2f5e86", { roughness: 0.7, metalness: 0.05 }), wht = c.paint("#e6e3da", { roughness: 0.7, metalness: 0.05 }), redP = c.paint("#7a2219", { roughness: 0.8, metalness: 0.05 }), wood = CM("#6b4a2e", { roughness: 0.85 }), deckW = CM("#8a6e4c", { roughness: 0.9, side: DS });
25503
25504
  const H = EA.boatHull({
25504
25505
  x0,
@@ -25802,7 +25803,7 @@ var GameVehiclesThree = (() => {
25802
25803
  hood: false
25803
25804
  },
25804
25805
  function(c) {
25805
- const EA = shared.EA, white = "#ecebe6";
25806
+ const EA = shared2.EA, white = "#ecebe6";
25806
25807
  const paintW = c.paint(white);
25807
25808
  const ST = [
25808
25809
  [2.3, 0.98, 1.46, 0.7, 2.4],
@@ -26131,7 +26132,7 @@ var GameVehiclesThree = (() => {
26131
26132
  hood: false
26132
26133
  },
26133
26134
  function(c) {
26134
- const EA = shared.EA, TH = 0.19, X0 = 0.3, Y0 = 1, cs = Math.cos(TH), sn = Math.sin(TH);
26135
+ const EA = shared2.EA, TH = 0.19, X0 = 0.3, Y0 = 1, cs = Math.cos(TH), sn = Math.sin(TH);
26135
26136
  function P(x, y, z) {
26136
26137
  return new V3(x * cs - y * sn + X0, x * sn + y * cs + Y0, z || 0);
26137
26138
  }
@@ -26488,7 +26489,7 @@ var GameVehiclesThree = (() => {
26488
26489
  hood: false
26489
26490
  },
26490
26491
  function(c) {
26491
- const EA = shared.EA, red = c.paint("#a9241e"), white = c.paint("#e9e7e0"), blk = CM("#1c1d1f", { roughness: 0.6 });
26492
+ const EA = shared2.EA, red = c.paint("#a9241e"), white = c.paint("#e9e7e0"), blk = CM("#1c1d1f", { roughness: 0.6 });
26492
26493
  const ST = [
26493
26494
  [1.96, 0.96, 1.06, 0.06, 2],
26494
26495
  [1.85, 0.76, 1.4, 0.76, 2.2],
@@ -26814,7 +26815,7 @@ var GameVehiclesThree = (() => {
26814
26815
  hood: false
26815
26816
  },
26816
26817
  function(c) {
26817
- const EA = shared.EA, org = c.paint("#d0531e"), white = c.paint("#e8e6df"), blk = CM("#1c1d1f", { roughness: 0.6 });
26818
+ const EA = shared2.EA, org = c.paint("#d0531e"), white = c.paint("#e8e6df"), blk = CM("#1c1d1f", { roughness: 0.6 });
26818
26819
  const ST = [
26819
26820
  [3.34, 1, 1.12, 0.1, 2],
26820
26821
  [3.2, 0.82, 1.48, 0.95, 2.2],
@@ -27176,11 +27177,11 @@ var GameVehiclesThree = (() => {
27176
27177
  const groups = new Set(options.groups || fleetGroupIds);
27177
27178
  const only = options.vehicles ? new Set(options.vehicles) : null;
27178
27179
  const skip = new Set(options.exclude || []);
27179
- const shared = {};
27180
+ const shared2 = {};
27180
27181
  const t = (key, vars) => kit.t("fleet." + key, vars);
27181
27182
  return {
27182
27183
  kit,
27183
- shared,
27184
+ shared: shared2,
27184
27185
  t,
27185
27186
  label: (key) => ({ key, label: t("labels." + key) }),
27186
27187
  register(spec, build) {
@@ -29507,6 +29508,90 @@ var GameVehiclesThree = (() => {
29507
29508
  shims.add(result);
29508
29509
  return result;
29509
29510
  }
29511
+ var isTexture = (v) => !!v && typeof v === "object" && v.isTexture === true;
29512
+ function texturesOf(material, out) {
29513
+ for (const value of Object.values(material)) if (isTexture(value)) out.add(value);
29514
+ const uniforms = material.uniforms;
29515
+ if (uniforms) {
29516
+ for (const u of Object.values(uniforms)) if (isTexture(u?.value)) out.add(u.value);
29517
+ }
29518
+ }
29519
+ function collect(roots) {
29520
+ const geometries = /* @__PURE__ */ new Set();
29521
+ const materials = /* @__PURE__ */ new Set();
29522
+ const textures = /* @__PURE__ */ new Set();
29523
+ const skeletons = /* @__PURE__ */ new Set();
29524
+ for (const root of roots) {
29525
+ root.traverse((object2) => {
29526
+ const o = object2;
29527
+ if (o.geometry && typeof o.geometry.dispose === "function") geometries.add(o.geometry);
29528
+ if (o.skeleton && typeof o.skeleton.dispose === "function") skeletons.add(o.skeleton);
29529
+ const list2 = Array.isArray(o.material) ? o.material : o.material ? [o.material] : [];
29530
+ for (const m of list2) {
29531
+ if (!m || typeof m.dispose !== "function") continue;
29532
+ materials.add(m);
29533
+ texturesOf(m, textures);
29534
+ }
29535
+ });
29536
+ }
29537
+ return { geometries, materials, textures, skeletons };
29538
+ }
29539
+ var marked = /* @__PURE__ */ new WeakSet();
29540
+ var shared = (r) => r.userData?.shared === true || marked.has(r);
29541
+ function releaseObject3D(roots, options = {}) {
29542
+ const list2 = Array.isArray(roots) ? roots : [roots];
29543
+ const report = { geometries: 0, materials: 0, textures: 0 };
29544
+ if (list2.length === 0) return report;
29545
+ const found = collect(list2);
29546
+ const keepRoots = options.keep === void 0 ? [] : Array.isArray(options.keep) ? options.keep : [options.keep];
29547
+ const releasing = new Set(list2);
29548
+ for (const keep of keepRoots) {
29549
+ const walk = (o) => {
29550
+ if (releasing.has(o)) return;
29551
+ const owner = o;
29552
+ if (owner.geometry) found.geometries.delete(owner.geometry);
29553
+ if (owner.skeleton) found.skeletons.delete(owner.skeleton);
29554
+ const mats = Array.isArray(owner.material) ? owner.material : owner.material ? [owner.material] : [];
29555
+ for (const m of mats) {
29556
+ if (!m) continue;
29557
+ found.materials.delete(m);
29558
+ const t = /* @__PURE__ */ new Set();
29559
+ texturesOf(m, t);
29560
+ for (const x of t) found.textures.delete(x);
29561
+ }
29562
+ for (const c of o.children) walk(c);
29563
+ };
29564
+ walk(keep);
29565
+ }
29566
+ for (const g of found.geometries) {
29567
+ if (shared(g)) continue;
29568
+ g.dispose();
29569
+ report.geometries++;
29570
+ }
29571
+ for (const m of found.materials) {
29572
+ if (shared(m)) continue;
29573
+ m.dispose();
29574
+ report.materials++;
29575
+ }
29576
+ for (const t of found.textures) {
29577
+ if (shared(t)) continue;
29578
+ t.dispose();
29579
+ report.textures++;
29580
+ }
29581
+ for (const s of found.skeletons) s.dispose();
29582
+ return report;
29583
+ }
29584
+ function discardObject3D(objects, options = {}) {
29585
+ const list2 = Array.isArray(objects) ? objects : [objects];
29586
+ const keep = options.keep === void 0 ? [] : Array.isArray(options.keep) ? [...options.keep] : [options.keep];
29587
+ for (const object2 of list2) {
29588
+ let top = object2;
29589
+ while (top.parent) top = top.parent;
29590
+ object2.removeFromParent();
29591
+ if (top !== object2 && !keep.includes(top)) keep.push(top);
29592
+ }
29593
+ return releaseObject3D(list2, { keep });
29594
+ }
29510
29595
 
29511
29596
  // ../game-vehicles/dist/index.js
29512
29597
  var __defProp2 = Object.defineProperty;
@@ -34509,8 +34594,15 @@ var GameVehiclesThree = (() => {
34509
34594
  x.arc(cx, cy, 26 * s, 0, PI * 2);
34510
34595
  x.fill();
34511
34596
  }
34597
+ const NO_CANVAS = new Proxy(function() {
34598
+ }, { get: () => NO_CANVAS, apply: () => NO_CANVAS, set: () => true });
34512
34599
  function crackGlass(c, msh, p, force, sc) {
34513
34600
  const G2 = msh.userData.glass;
34601
+ if (G2.cracksFreed) {
34602
+ drawWeb(NO_CANVAS, 0, 0, sc != null ? sc : 0.6 + force * 0.5, Math.max(0.4, G2.aspect || 1), c.rand);
34603
+ G2.hits++;
34604
+ return;
34605
+ }
34514
34606
  if (!G2.cv) {
34515
34607
  G2.cv = document2.createElement("canvas");
34516
34608
  G2.cv.width = G2.cv.height = 256;
@@ -34593,6 +34685,14 @@ var GameVehiclesThree = (() => {
34593
34685
  const G2 = msh.userData.glass;
34594
34686
  if (G2.broken) return;
34595
34687
  G2.broken = true;
34688
+ const freeCracks = function() {
34689
+ if (!G2.tex) return;
34690
+ if (msh.material !== MATERIALS.glassEdge && msh.material?.map === G2.tex) msh.material.dispose();
34691
+ G2.tex.dispose();
34692
+ G2.tex = null;
34693
+ G2.cv = null;
34694
+ G2.cracksFreed = true;
34695
+ };
34596
34696
  const cubesAt = [];
34597
34697
  if (G2.outline && G2.T !== void 0) {
34598
34698
  const out = G2.outline;
@@ -34626,6 +34726,7 @@ var GameVehiclesThree = (() => {
34626
34726
  geo.computeVertexNormals();
34627
34727
  msh.geometry.dispose();
34628
34728
  msh.geometry = geo;
34729
+ freeCracks();
34629
34730
  msh.material = MATERIALS.glassEdge;
34630
34731
  let minx = 1e9;
34631
34732
  let maxx = -1e9;
@@ -34649,8 +34750,12 @@ var GameVehiclesThree = (() => {
34649
34750
  if (rim) {
34650
34751
  msh.geometry.dispose();
34651
34752
  msh.geometry = rim;
34753
+ freeCracks();
34652
34754
  msh.material = MATERIALS.glassEdge;
34653
- } else msh.visible = false;
34755
+ } else {
34756
+ freeCracks();
34757
+ msh.visible = false;
34758
+ }
34654
34759
  for (let j = 0; j < 36; j++)
34655
34760
  cubesAt.push(
34656
34761
  new V3(
@@ -40153,13 +40258,13 @@ var GameVehiclesThree = (() => {
40153
40258
  return c;
40154
40259
  }
40155
40260
  kit.dispose = function(c) {
40156
- const shared = Object.values(I.PARTICLE_GEOMETRIES);
40261
+ const shared2 = Object.values(I.PARTICLE_GEOMETRIES);
40157
40262
  c.root.traverse(function(o) {
40158
40263
  if (o.isSprite) {
40159
40264
  if (o.material && o.material.userData.dis) o.material.dispose();
40160
40265
  return;
40161
40266
  }
40162
- if (o.geometry && !shared.includes(o.geometry)) o.geometry.dispose();
40267
+ if (o.geometry && !shared2.includes(o.geometry)) o.geometry.dispose();
40163
40268
  });
40164
40269
  };
40165
40270
  kit.registerLegacySeeds = registerLegacySeeds;
@@ -42090,8 +42195,8 @@ var GameVehiclesThree = (() => {
42090
42195
  const buildState = () => {
42091
42196
  const parts = model.parts.map((d) => {
42092
42197
  const p = ps.get(d.id);
42093
- const marked = p.dents.length > 0 || p.holes.length > 0 || p.cracks.length > 0;
42094
- const status = p.lost ? p.status : p.hp < p.def.hp || marked ? "damaged" : "intact";
42198
+ const marked2 = p.dents.length > 0 || p.holes.length > 0 || p.cracks.length > 0;
42199
+ const status = p.lost ? p.status : p.hp < p.def.hp || marked2 ? "damaged" : "intact";
42095
42200
  return {
42096
42201
  id: d.id,
42097
42202
  material: d.material,
@@ -42291,6 +42396,123 @@ var GameVehiclesThree = (() => {
42291
42396
  root.userData.vehicle = vehicle;
42292
42397
  return { root, vehicle };
42293
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
+ }
42294
42516
 
42295
42517
  // ../game-vehicles-driving/dist/index.js
42296
42518
  var defaultArcadeSpec = {
@@ -43352,6 +43574,7 @@ var GameVehiclesThree = (() => {
43352
43574
  const settings = { quality: "high", paint: false, seed: 1, palette: "auto", driving: "arcade", surface: "dry_asphalt" };
43353
43575
  const kits = /* @__PURE__ */ new WeakMap();
43354
43576
  const placed = /* @__PURE__ */ new Map();
43577
+ const cabins = createCabinSmoke();
43355
43578
  let host = null;
43356
43579
  let three = null;
43357
43580
  let counter = 0;
@@ -43416,6 +43639,7 @@ var GameVehiclesThree = (() => {
43416
43639
  const kit = r.userData.kit;
43417
43640
  const d = createVehicleDestructible(kit, r.userData.vehicle, { id, frame: root, name: text.items[itemKey] ?? key });
43418
43641
  tapEffects(d);
43642
+ cabins.track(id, d, root);
43419
43643
  r.userData.destructible = d;
43420
43644
  return d;
43421
43645
  },
@@ -43491,10 +43715,10 @@ var GameVehiclesThree = (() => {
43491
43715
  };
43492
43716
  const clearHelpers = () => {
43493
43717
  for (const entry of placed.values()) {
43494
- for (const helper of entry.helpers) helper.parent?.remove(helper);
43718
+ discardObject3D(entry.helpers);
43495
43719
  entry.helpers = [];
43496
43720
  }
43497
- for (const axis of axes) axis.parent?.remove(axis);
43721
+ discardObject3D(axes);
43498
43722
  axes = [];
43499
43723
  helpersShown = "";
43500
43724
  };
@@ -43671,6 +43895,7 @@ var GameVehiclesThree = (() => {
43671
43895
  }
43672
43896
  if (host?.bench && boxKey() !== helpersShown && (host.bench.layer("damageables") || host.bench.layer("zones") || helpersShown !== "")) refreshLayers();
43673
43897
  lane?.step(dt);
43898
+ cabins.sync(effects());
43674
43899
  };
43675
43900
  const count2 = () => {
43676
43901
  let drawCalls = 0;
@@ -43771,6 +43996,7 @@ var GameVehiclesThree = (() => {
43771
43996
  stopChange?.();
43772
43997
  stopFrame();
43773
43998
  stopBlocker?.();
43999
+ cabins.clear(effects());
43774
44000
  clearHelpers();
43775
44001
  clearLane();
43776
44002
  host = null;