@adatechnology/game-vehicles-three 0.1.0 → 0.3.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.
@@ -22,6 +22,7 @@ var GameVehiclesThree = (() => {
22
22
  var index_exports = {};
23
23
  __export(index_exports, {
24
24
  DEFAULT_TEST_VEHICLES: () => DEFAULT_TEST_VEHICLES,
25
+ DEFAULT_TEST_WRECKS: () => DEFAULT_TEST_WRECKS,
25
26
  LITE_CLASSES: () => LITE_CLASSES,
26
27
  PAGE_ITEM_ALIASES: () => PAGE_ITEM_ALIASES,
27
28
  PAGE_SCENARIO_ALIASES: () => PAGE_SCENARIO_ALIASES,
@@ -5128,8 +5129,8 @@ var GameVehiclesThree = (() => {
5128
5129
  });
5129
5130
  return GRM[kind];
5130
5131
  }
5131
- function mkSurf(mesh, W) {
5132
- const geo = mesh.geometry, pos = geo.attributes.position, ix = geo.index, n = ix ? ix.count : pos.count;
5132
+ function mkSurf(mesh2, W) {
5133
+ const geo = mesh2.geometry, pos = geo.attributes.position, ix = geo.index, n = ix ? ix.count : pos.count;
5133
5134
  geo.computeBoundingBox();
5134
5135
  const bb = geo.boundingBox.clone();
5135
5136
  const T = [], BY = {}, BX = {}, Q = 0.02;
@@ -5146,11 +5147,11 @@ var GameVehiclesThree = (() => {
5146
5147
  S.hit = function(o, dd) {
5147
5148
  const d = dd.clone().normalize();
5148
5149
  ray.set(o, d);
5149
- const list = Math.abs(d.y) < 0.5 ? BY[Math.floor(o.y / Q)] : BX[Math.floor(o.x / Q)];
5150
- if (!list) return null;
5150
+ const list2 = Math.abs(d.y) < 0.5 ? BY[Math.floor(o.y / Q)] : BX[Math.floor(o.x / Q)];
5151
+ if (!list2) return null;
5151
5152
  let best = 1e9, bt = null;
5152
- for (let k = 0; k < list.length; k++) {
5153
- const t = T[list[k]];
5153
+ for (let k = 0; k < list2.length; k++) {
5154
+ const t = T[list2[k]];
5154
5155
  if (!ray.intersectTriangle(t[0], t[1], t[2], false, tmp)) continue;
5155
5156
  const dist = tmp.distanceTo(o);
5156
5157
  if (dist < best) {
@@ -5325,8 +5326,8 @@ var GameVehiclesThree = (() => {
5325
5326
  t.castShadow = false;
5326
5327
  return t;
5327
5328
  }
5328
- function lineOn(c, Gd, list, r, mat, off) {
5329
- const pts = list.map(function(q) {
5329
+ function lineOn(c, Gd, list2, r, mat, off) {
5330
+ const pts = list2.map(function(q) {
5330
5331
  const s = Gd.at(q[0], q[1]);
5331
5332
  return s.p.addScaledVector(s.n, off || 3e-3);
5332
5333
  });
@@ -5397,8 +5398,8 @@ var GameVehiclesThree = (() => {
5397
5398
  const r = sh(q[0]), y = (r[0] + r[1]) / 2 + (q[1] || 0), s = Gd.at(q[0], y), rad = q[2] || Math.min(0.034, (r[1] - r[0]) * 0.4);
5398
5399
  const cup = onSurf(c.cylinder(rad * 1.35, rad * 1.2, 0.012, LH, 0, 0, 0), s, 8e-3);
5399
5400
  cup.castShadow = false;
5400
- const ring = onSurf(c.add(new THREE.TorusGeometry(rad * 1.05, 4e-3, 6, 22), MT.chrome), s, 0.012, new V3(0, 0, 1));
5401
- ring.castShadow = false;
5401
+ const ring2 = onSurf(c.add(new THREE.TorusGeometry(rad * 1.05, 4e-3, 6, 22), MT.chrome), s, 0.012, new V3(0, 0, 1));
5402
+ ring2.castShadow = false;
5402
5403
  const b = onSurf(c.sphere(rad, MT.head, 0, 0, 0, 1, 0.55, 1), s, 0.01);
5403
5404
  b.castShadow = false;
5404
5405
  inner.push(b);
@@ -6015,9 +6016,9 @@ var GameVehiclesThree = (() => {
6015
6016
  });
6016
6017
  })();
6017
6018
  const REFLB = CM("#d3d7da", { metalness: 0.35, roughness: 0.28 });
6018
- function dlo(list) {
6019
+ function dlo(list2) {
6019
6020
  return function(def) {
6020
- return list.concat([def[def.length - 1]]);
6021
+ return list2.concat([def[def.length - 1]]);
6021
6022
  };
6022
6023
  }
6023
6024
  function cabTaper(belt, top, x0, L, a) {
@@ -8375,7 +8376,7 @@ var GameVehiclesThree = (() => {
8375
8376
  guards: [-1.1, 2],
8376
8377
  lightsY: 0.62
8377
8378
  });
8378
- const box = boxBody(c, { x0: f - len - 0.1, x1: -3.72, y0: 0.98, y1: 3.38, W: 2.42, col: "#f1f1ec" });
8379
+ const box2 = boxBody(c, { x0: f - len - 0.1, x1: -3.72, y0: 0.98, y1: 3.38, W: 2.42, col: "#f1f1ec" });
8379
8380
  [1, -1].forEach(function(s) {
8380
8381
  c.roundBox(4.6, 0.32, 0.01, 0.01, CM("#1f4fa3", { roughness: 0.5 }), -1, 1.35, s * 1.217);
8381
8382
  c.roundBox(4.6, 0.06, 0.01, 0.01, CM("#e0a21c", { roughness: 0.5 }), -1, 1.56, s * 1.217);
@@ -8406,7 +8407,7 @@ var GameVehiclesThree = (() => {
8406
8407
  c2.rod(new V3(-3.86, 0.6, z), new V3(-3.86, 3.5, z), 0.022, kit.steelMaterial);
8407
8408
  });
8408
8409
  });
8409
- void box;
8410
+ void box2;
8410
8411
  }
8411
8412
  );
8412
8413
  fx.register(
@@ -9583,9 +9584,9 @@ var GameVehiclesThree = (() => {
9583
9584
  return m;
9584
9585
  }
9585
9586
  function fenestron(c, x, y, R, w, n, mat, bladeMat) {
9586
- const ring = c.add(new THREE.TorusGeometry(R + 0.06, 0.07, 10, 36), mat, x, y, 0);
9587
- ring.scale.z = w / 0.14;
9588
- c.deform.push(ring);
9587
+ const ring2 = c.add(new THREE.TorusGeometry(R + 0.06, 0.07, 10, 36), mat, x, y, 0);
9588
+ ring2.scale.z = w / 0.14;
9589
+ c.deform.push(ring2);
9589
9590
  const duct = c.cylinder(R + 0.01, R + 0.01, w, MT.dark, x, y, 0, "z", { seg: 36, open: true });
9590
9591
  duct.material = CM("#141516", { roughness: 0.8, side: THREE.DoubleSide });
9591
9592
  const g = new THREE.Group();
@@ -9613,7 +9614,7 @@ var GameVehiclesThree = (() => {
9613
9614
  );
9614
9615
  }
9615
9616
  c.spin.push({ o: g, axis: "z", v: 22 });
9616
- return { ring, fan: g, duct };
9617
+ return { ring: ring2, fan: g, duct };
9617
9618
  }
9618
9619
  function xRotor(c, x, y, z, R, ch, mat, tip) {
9619
9620
  const g = new THREE.Group();
@@ -11330,16 +11331,16 @@ var GameVehiclesThree = (() => {
11330
11331
  function settle(c, tilt, riseOnly) {
11331
11332
  if (tilt) c.vehicle.rotation.z += tilt;
11332
11333
  c.root.updateMatrixWorld(true);
11333
- const inv = new THREE.Matrix4().copy(c.root.matrixWorld).invert(), box = new THREE.Box3(), tmp = new THREE.Box3();
11334
+ const inv = new THREE.Matrix4().copy(c.root.matrixWorld).invert(), box2 = new THREE.Box3(), tmp = new THREE.Box3();
11334
11335
  c.vehicle.traverse(function(ob) {
11335
11336
  if (!ob.isMesh) return;
11336
11337
  for (let q = ob; q && q !== c.vehicle; q = q.parent)
11337
11338
  if (!q.visible || q.userData.decal || q.userData.ghost || q.userData.antena) return;
11338
11339
  if (!ob.geometry.boundingBox) ob.geometry.computeBoundingBox();
11339
11340
  tmp.copy(ob.geometry.boundingBox).applyMatrix4(ob.matrixWorld).applyMatrix4(inv);
11340
- box.union(tmp);
11341
+ box2.union(tmp);
11341
11342
  });
11342
- if (!box.isEmpty() && (!riseOnly || box.min.y < -5e-3)) c.vehicle.position.y -= box.min.y;
11343
+ if (!box2.isEmpty() && (!riseOnly || box2.min.y < -5e-3)) c.vehicle.position.y -= box2.min.y;
11343
11344
  }
11344
11345
  function rollover(c, o) {
11345
11346
  o = o || {};
@@ -11616,10 +11617,10 @@ var GameVehiclesThree = (() => {
11616
11617
  function periscope(c, x, y, z, w, label, o) {
11617
11618
  o = o || {};
11618
11619
  const rot = o.rot || 0;
11619
- const box = c.roundBox(0.14, 0.12, w + 0.06, 0.02, o.mat || OLIVE_STEEL, x, y, z, { rot: [0, rot, 0] });
11620
+ const box2 = c.roundBox(0.14, 0.12, w + 0.06, 0.02, o.mat || OLIVE_STEEL, x, y, z, { rot: [0, rot, 0] });
11620
11621
  const gl = c.roundBox(0.02, 0.07, w, 0.01, MT.armorGlass, x + Math.cos(rot) * 0.07, y, z - Math.sin(rot) * 0.07, { rot: [0, rot, 0] });
11621
11622
  if (label) kit.asGlass(c, gl, label, "laminated");
11622
- return box;
11623
+ return box2;
11623
11624
  }
11624
11625
  function sideSeat(c, x0, x1, fl, z, dir, o) {
11625
11626
  o = o || {};
@@ -13947,7 +13948,7 @@ var GameVehiclesThree = (() => {
13947
13948
  o = o || {};
13948
13949
  if (kit.lod.on) o = Object.assign({}, o, { seg: Math.max(kit.lod.minLoftSegments, Math.round((o.seg || 24) * kit.lod.loftSegmentFraction)) });
13949
13950
  if (o.smooth) st = resample(st, o.smooth);
13950
- const seg = o.seg || 24, pos = [], idx = [], ring = seg + 1, axisY = o.axis === "y";
13951
+ const seg = o.seg || 24, pos = [], idx = [], ring2 = seg + 1, axisY = o.axis === "y";
13951
13952
  st.forEach(function(s) {
13952
13953
  const a0 = s[1], b0 = s[2], cc = (a0 + b0) / 2, hh = Math.abs(a0 - b0) / 2, w = s[3] / 2, e = 2 / (s[4] || o.p || 2.4), zc = s[5] || 0;
13953
13954
  for (let j = 0; j <= seg; j++) {
@@ -13959,7 +13960,7 @@ var GameVehiclesThree = (() => {
13959
13960
  });
13960
13961
  for (let i = 0; i < st.length - 1; i++)
13961
13962
  for (let k = 0; k < seg; k++) {
13962
- const A = i * ring + k, B = A + ring;
13963
+ const A = i * ring2 + k, B = A + ring2;
13963
13964
  if (axisY) idx.push(A, B, A + 1, A + 1, B, B + 1);
13964
13965
  else idx.push(A, A + 1, B, A + 1, B + 1, B);
13965
13966
  }
@@ -13971,7 +13972,7 @@ var GameVehiclesThree = (() => {
13971
13972
  if (axisY) pos.push(cc, s[0], s[5] || 0);
13972
13973
  else pos.push(s[0], cc, s[5] || 0);
13973
13974
  for (let k = 0; k < seg; k++) {
13974
- const a = si * ring + k, flip = e === 0 !== axisY;
13975
+ const a = si * ring2 + k, flip = e === 0 !== axisY;
13975
13976
  if (flip) idx.push(ci, a + 1, a);
13976
13977
  else idx.push(ci, a, a + 1);
13977
13978
  }
@@ -14158,8 +14159,8 @@ var GameVehiclesThree = (() => {
14158
14159
  });
14159
14160
  return GRM[kind];
14160
14161
  }
14161
- function mkSurf(mesh, W) {
14162
- const geo = mesh.geometry, pos = geo.attributes.position, ix = geo.index, n = ix ? ix.count : pos.count;
14162
+ function mkSurf(mesh2, W) {
14163
+ const geo = mesh2.geometry, pos = geo.attributes.position, ix = geo.index, n = ix ? ix.count : pos.count;
14163
14164
  geo.computeBoundingBox();
14164
14165
  const bb = geo.boundingBox.clone();
14165
14166
  const T = [], BY = {}, BX = {}, Q = 0.02;
@@ -14176,11 +14177,11 @@ var GameVehiclesThree = (() => {
14176
14177
  S.hit = function(o, dd) {
14177
14178
  const d = dd.clone().normalize();
14178
14179
  ray.set(o, d);
14179
- const list = Math.abs(d.y) < 0.5 ? BY[Math.floor(o.y / Q)] : BX[Math.floor(o.x / Q)];
14180
- if (!list) return null;
14180
+ const list2 = Math.abs(d.y) < 0.5 ? BY[Math.floor(o.y / Q)] : BX[Math.floor(o.x / Q)];
14181
+ if (!list2) return null;
14181
14182
  let best = 1e9, bt = null;
14182
- for (let k = 0; k < list.length; k++) {
14183
- const t = T[list[k]];
14183
+ for (let k = 0; k < list2.length; k++) {
14184
+ const t = T[list2[k]];
14184
14185
  if (!ray.intersectTriangle(t[0], t[1], t[2], false, tmp)) continue;
14185
14186
  const dist = tmp.distanceTo(o);
14186
14187
  if (dist < best) {
@@ -14355,8 +14356,8 @@ var GameVehiclesThree = (() => {
14355
14356
  t.castShadow = false;
14356
14357
  return t;
14357
14358
  }
14358
- function lineOn(c, Gd, list, r, mat, off) {
14359
- const pts = list.map(function(q) {
14359
+ function lineOn(c, Gd, list2, r, mat, off) {
14360
+ const pts = list2.map(function(q) {
14360
14361
  const s = Gd.at(q[0], q[1]);
14361
14362
  return s.p.addScaledVector(s.n, off || 3e-3);
14362
14363
  });
@@ -14427,8 +14428,8 @@ var GameVehiclesThree = (() => {
14427
14428
  const r = sh(q[0]), y = (r[0] + r[1]) / 2 + (q[1] || 0), s = Gd.at(q[0], y), rad = q[2] || Math.min(0.034, (r[1] - r[0]) * 0.4);
14428
14429
  const cup = onSurf(c.cylinder(rad * 1.35, rad * 1.2, 0.012, LH, 0, 0, 0), s, 8e-3);
14429
14430
  cup.castShadow = false;
14430
- const ring = onSurf(c.add(new THREE.TorusGeometry(rad * 1.05, 4e-3, 6, 22), MT.chrome), s, 0.012, new V3(0, 0, 1));
14431
- ring.castShadow = false;
14431
+ const ring2 = onSurf(c.add(new THREE.TorusGeometry(rad * 1.05, 4e-3, 6, 22), MT.chrome), s, 0.012, new V3(0, 0, 1));
14432
+ ring2.castShadow = false;
14432
14433
  const b = onSurf(c.sphere(rad, MT.head, 0, 0, 0, 1, 0.55, 1), s, 0.01);
14433
14434
  b.castShadow = false;
14434
14435
  inner.push(b);
@@ -16505,9 +16506,9 @@ var GameVehiclesThree = (() => {
16505
16506
  L.inner.push(m);
16506
16507
  return m;
16507
16508
  }
16508
- function bendSet(list, piv, axis, ang) {
16509
+ function bendSet(list2, piv, axis, ang) {
16509
16510
  const q = new THREE.Quaternion().setFromAxisAngle(axis.clone().normalize(), ang);
16510
- list.forEach(function(m) {
16511
+ list2.forEach(function(m) {
16511
16512
  if (!m.parent) return;
16512
16513
  m.position.sub(piv).applyQuaternion(q).add(piv);
16513
16514
  m.quaternion.premultiply(q);
@@ -17554,7 +17555,7 @@ var GameVehiclesThree = (() => {
17554
17555
  );
17555
17556
  [1, -1].forEach(function(s) {
17556
17557
  const z = s * (s > 0 ? 0.44 : 0.4);
17557
- const box = c.roundBox(0.5, 0.38, 0.2, 0.03, aluBox, -0.7, 0.8, z, { def: true }), luggageCase = [box, c.roundBox(0.52, 0.04, 0.21, 0.015, blk, -0.7, 0.98, z)];
17558
+ const box2 = c.roundBox(0.5, 0.38, 0.2, 0.03, aluBox, -0.7, 0.8, z, { def: true }), luggageCase = [box2, c.roundBox(0.52, 0.04, 0.21, 0.015, blk, -0.7, 0.98, z)];
17558
17559
  [-0.88, -0.52].forEach(function(x) {
17559
17560
  luggageCase.push(c.roundBox(0.04, 0.06, 0.03, 0.01, blk, x, 0.95, z + s * 0.1));
17560
17561
  });
@@ -17568,7 +17569,7 @@ var GameVehiclesThree = (() => {
17568
17569
  blk,
17569
17570
  { seg: 12 }
17570
17571
  );
17571
- c.part("cargo", s > 0 ? trl("labels.right_pannier") : trl("labels.left_pannier"), box, new V3(-0.7, 0.8, z), 0.6);
17572
+ c.part("cargo", s > 0 ? trl("labels.right_pannier") : trl("labels.left_pannier"), box2, new V3(-0.7, 0.8, z), 0.6);
17572
17573
  c.zone(
17573
17574
  s > 0 ? "case_right" : "case_left",
17574
17575
  s > 0 ? trl("labels.right_pannier") : trl("labels.left_pannier"),
@@ -18216,7 +18217,7 @@ var GameVehiclesThree = (() => {
18216
18217
  function sloft(st, o) {
18217
18218
  o = o || {};
18218
18219
  if (kit.lod.on) o = Object.assign({}, o, { seg: Math.max(kit.lod.minLoftSegments, Math.round((o.seg || 24) * kit.lod.loftSegmentFraction)) });
18219
- const seg = o.seg || 24, pos = [], idx = [], ring = seg + 1, axisY = o.axis === "y";
18220
+ const seg = o.seg || 24, pos = [], idx = [], ring2 = seg + 1, axisY = o.axis === "y";
18220
18221
  st.forEach(function(s) {
18221
18222
  const a0 = s[1], b0 = s[2], cc = (a0 + b0) / 2, hh = Math.abs(a0 - b0) / 2, w = s[3] / 2, e = 2 / (s[4] || o.p || 2.4), zc = s[5] || 0;
18222
18223
  for (let j = 0; j <= seg; j++) {
@@ -18228,7 +18229,7 @@ var GameVehiclesThree = (() => {
18228
18229
  });
18229
18230
  for (let i = 0; i < st.length - 1; i++)
18230
18231
  for (let k = 0; k < seg; k++) {
18231
- const A = i * ring + k, B = A + ring;
18232
+ const A = i * ring2 + k, B = A + ring2;
18232
18233
  if (axisY) idx.push(A, B, A + 1, A + 1, B, B + 1);
18233
18234
  else idx.push(A, A + 1, B, A + 1, B + 1, B);
18234
18235
  }
@@ -18240,7 +18241,7 @@ var GameVehiclesThree = (() => {
18240
18241
  if (axisY) pos.push(cc, s[0], s[5] || 0);
18241
18242
  else pos.push(s[0], cc, s[5] || 0);
18242
18243
  for (let k = 0; k < seg; k++) {
18243
- const a = si * ring + k, flip = e === 0 !== axisY;
18244
+ const a = si * ring2 + k, flip = e === 0 !== axisY;
18244
18245
  if (flip) idx.push(ci, a + 1, a);
18245
18246
  else idx.push(ci, a, a + 1);
18246
18247
  }
@@ -19471,12 +19472,12 @@ var GameVehiclesThree = (() => {
19471
19472
  });
19472
19473
  Z.fairing = grab(c, n0).concat([fendF]);
19473
19474
  const HL = lamp(c, { style: "round", x: 0.72, y: 0.84, z: 0, w: 0.19, h: 0.19, d: 0.1, side: 1, label: trl("labels.headlight") });
19474
- const ring = new THREE.Mesh(new THREE.TorusGeometry(0.075, 7e-3, 6, 32), DRL);
19475
- ring.rotation.y = PI / 2;
19476
- ring.position.set(0.052, 0, 0);
19477
- ring.castShadow = false;
19478
- HL.group.add(ring);
19479
- HL.inner.push(ring);
19475
+ const ring2 = new THREE.Mesh(new THREE.TorusGeometry(0.075, 7e-3, 6, 32), DRL);
19476
+ ring2.rotation.y = PI / 2;
19477
+ ring2.position.set(0.052, 0, 0);
19478
+ ring2.castShadow = false;
19479
+ HL.group.add(ring2);
19480
+ HL.inner.push(ring2);
19480
19481
  n0 = c.vehicle.children.length;
19481
19482
  const TK = [
19482
19483
  [0.46, 0.89, 0.76, 0.18, 2.2],
@@ -22525,7 +22526,7 @@ var GameVehiclesThree = (() => {
22525
22526
  });
22526
22527
  }
22527
22528
  function roofLining(c, extra) {
22528
- const m = c.meta, yb = (m.glasshouse ? m.glasshouse.belt : m.belt) + 0.25, bb = new THREE.Box3(), sz = new V3(), ce = new V3(), gl = new Set(c.glass), list = [];
22529
+ const m = c.meta, yb = (m.glasshouse ? m.glasshouse.belt : m.belt) + 0.25, bb = new THREE.Box3(), sz = new V3(), ce = new V3(), gl = new Set(c.glass), list2 = [];
22529
22530
  const cols = [m.color, m.roofCol].filter(Boolean).map(function(h) {
22530
22531
  return new THREE.Color(h).getHex();
22531
22532
  });
@@ -22537,14 +22538,14 @@ var GameVehiclesThree = (() => {
22537
22538
  bb.copy(o.geometry.boundingBox).applyMatrix4(o.matrix);
22538
22539
  bb.getSize(sz);
22539
22540
  bb.getCenter(ce);
22540
- if (sz.x > 0.5 && sz.z > 0.6 && sz.y < 0.08 && ce.y > yb) list.push(o);
22541
+ if (sz.x > 0.5 && sz.z > 0.6 && sz.y < 0.08 && ce.y > yb) list2.push(o);
22541
22542
  });
22542
22543
  extra = extra || [];
22543
- if (list.length || extra.length)
22544
+ if (list2.length || extra.length)
22544
22545
  c.zone("roof", null, null, null, {
22545
22546
  onBand: function(c2, b) {
22546
22547
  if (b >= 4)
22547
- list.concat(extra).forEach(function(o) {
22548
+ list2.concat(extra).forEach(function(o) {
22548
22549
  o.visible = false;
22549
22550
  });
22550
22551
  }
@@ -24329,7 +24330,7 @@ var GameVehiclesThree = (() => {
24329
24330
  }
24330
24331
  return pts;
24331
24332
  }
24332
- const ring = 2 * (m1 + m2) + 1;
24333
+ const ring2 = 2 * (m1 + m2) + 1;
24333
24334
  for (let i = 0; i <= n; i++) {
24334
24335
  const t = i / n, x = o.x0 + t * o.L, P = sec(t), row = [];
24335
24336
  for (let k = P.length - 1; k >= 1; k--) row.push([-P[k][0], P[k][1]]);
@@ -24345,8 +24346,8 @@ var GameVehiclesThree = (() => {
24345
24346
  });
24346
24347
  }
24347
24348
  for (let a = 0; a < n; a++)
24348
- for (let k2 = 0; k2 < ring - 1; k2++) {
24349
- const p0 = a * ring + k2, p1 = p0 + ring;
24349
+ for (let k2 = 0; k2 < ring2 - 1; k2++) {
24350
+ const p0 = a * ring2 + k2, p1 = p0 + ring2;
24350
24351
  idx.push(p0, p0 + 1, p1, p0 + 1, p1 + 1, p1);
24351
24352
  }
24352
24353
  const ci = pos.length / 3, sh0 = o.sheer(0), ky0 = o.keel(0);
@@ -24355,7 +24356,7 @@ var GameVehiclesThree = (() => {
24355
24356
  const c0 = o.col(o.x0, (sh0[1] + ky0) / 2, 0);
24356
24357
  col.push(c0.r, c0.g, c0.b);
24357
24358
  }
24358
- for (let r = 0; r < ring - 1; r++) idx.push(ci, r + 1, r);
24359
+ for (let r = 0; r < ring2 - 1; r++) idx.push(ci, r + 1, r);
24359
24360
  let g = new THREE.BufferGeometry();
24360
24361
  g.setAttribute("position", new THREE.Float32BufferAttribute(pos, 3));
24361
24362
  if (o.col) g.setAttribute("color", new THREE.Float32BufferAttribute(col, 3));
@@ -24428,7 +24429,7 @@ var GameVehiclesThree = (() => {
24428
24429
  function foilGeo(sts, o) {
24429
24430
  o = o || {};
24430
24431
  const n = o.n || 12, up = o.up || "y", pos = [], idx = [];
24431
- let ring;
24432
+ let ring2;
24432
24433
  const cnt = 0;
24433
24434
  function prof(st) {
24434
24435
  const out = [], cam = st.cam || 0;
@@ -24448,14 +24449,14 @@ var GameVehiclesThree = (() => {
24448
24449
  }
24449
24450
  sts.forEach(function(st) {
24450
24451
  const P = prof(st);
24451
- ring = P.length;
24452
+ ring2 = P.length;
24452
24453
  P.forEach(function(p) {
24453
24454
  pos.push(p[0], p[1], p[2]);
24454
24455
  });
24455
24456
  });
24456
24457
  for (let a = 0; a < sts.length - 1; a++)
24457
- for (let k = 0; k < ring; k++) {
24458
- const k1 = (k + 1) % ring, p0 = a * ring + k, p1 = (a + 1) * ring + k, q0 = a * ring + k1, q1 = (a + 1) * ring + k1;
24458
+ for (let k = 0; k < ring2; k++) {
24459
+ const k1 = (k + 1) % ring2, p0 = a * ring2 + k, p1 = (a + 1) * ring2 + k, q0 = a * ring2 + k1, q1 = (a + 1) * ring2 + k1;
24459
24460
  idx.push(p0, q0, p1, q0, q1, p1);
24460
24461
  }
24461
24462
  ;
@@ -24463,8 +24464,8 @@ var GameVehiclesThree = (() => {
24463
24464
  if (sts[si].noCap) return;
24464
24465
  const ci = pos.length / 3, st = sts[si];
24465
24466
  pos.push(st.p[0] - st.c * 0.35, st.p[1], st.p[2]);
24466
- for (let k = 0; k < ring; k++) {
24467
- const a0 = si * ring + k, a1 = si * ring + (k + 1) % ring;
24467
+ for (let k = 0; k < ring2; k++) {
24468
+ const a0 = si * ring2 + k, a1 = si * ring2 + (k + 1) % ring2;
24468
24469
  if (e === 0) idx.push(ci, a1, a0);
24469
24470
  else idx.push(ci, a0, a1);
24470
24471
  }
@@ -24692,7 +24693,7 @@ var GameVehiclesThree = (() => {
24692
24693
  blue: CM("#1d4f9a", { emissive: new THREE.Color("#3a7cff"), emissiveIntensity: 1.4, roughness: 0.3 })
24693
24694
  };
24694
24695
  const HALO = { red: "#ff3a2a", green: "#3aff7a", white: "#fff1d0", amber: "#ffb040", blue: "#4a8cff" };
24695
- function navLight(c, x, y, z, color, label, o) {
24696
+ function navLight(c, x, y, z, color2, label, o) {
24696
24697
  o = o || {};
24697
24698
  const r = o.r || 0.045, g = new THREE.Group();
24698
24699
  g.position.set(x, y, z);
@@ -24702,11 +24703,11 @@ var GameVehiclesThree = (() => {
24702
24703
  base.position.y = -r * 0.4;
24703
24704
  if (o.rot) base.rotation.set(o.rot[0], o.rot[1], o.rot[2]);
24704
24705
  g.add(base);
24705
- const bulb = new THREE.Mesh(new THREE.SphereGeometry(r * 0.55, 10, 8), NAV[color] || NAV.white);
24706
+ const bulb = new THREE.Mesh(new THREE.SphereGeometry(r * 0.55, 10, 8), NAV[color2] || NAV.white);
24706
24707
  g.add(bulb);
24707
24708
  const lens = new THREE.Mesh(
24708
24709
  new THREE.SphereGeometry(r, 12, 8),
24709
- color === "red" ? MT.lensRed : color === "amber" ? MT.lensAmber : MT.lens
24710
+ color2 === "red" ? MT.lensRed : color2 === "amber" ? MT.lensAmber : MT.lens
24710
24711
  );
24711
24712
  lens.renderOrder = 3;
24712
24713
  g.add(lens);
@@ -24715,10 +24716,10 @@ var GameVehiclesThree = (() => {
24715
24716
  inner: [bulb],
24716
24717
  lens: [lens],
24717
24718
  kind: o.front ? "headlight" : "taillight",
24718
- tint: color === "red" ? "red" : "clear",
24719
+ tint: color2 === "red" ? "red" : "clear",
24719
24720
  broken: false
24720
24721
  };
24721
- if (o.halo !== false) L.halo = [kit.halo(g, 0, 0, 0, o.hs || 0.35, HALO[color] || "#ffffff", 0.5)];
24722
+ if (o.halo !== false) L.halo = [kit.halo(g, 0, 0, 0, o.hs || 0.35, HALO[color2] || "#ffffff", 0.5)];
24722
24723
  c.lights.push(L);
24723
24724
  const pt = c.part(o.front ? "headlight" : "taillight", label, g, new V3(x, y, z), o.reach || 0.5);
24724
24725
  pt.light = L;
@@ -24840,15 +24841,15 @@ var GameVehiclesThree = (() => {
24840
24841
  c.roundBox(0.16 * r, 0.03, 0.04, 0.012, MT.chrome, x, y + 0.04, z);
24841
24842
  c.roundBox(0.04, 0.04, 0.03, 0.01, MT.chrome, x, y + 0.02, z);
24842
24843
  }
24843
- function skinOf2(c, mesh, keep, mat, o) {
24844
+ function skinOf2(c, mesh2, keep, mat, o) {
24844
24845
  o = o || {};
24845
- const g = mesh.geometry.clone(), p = g.attributes.position, sz = o.sz || 1.006, dy = o.dy || 0;
24846
+ const g = mesh2.geometry.clone(), p = g.attributes.position, sz = o.sz || 1.006, dy = o.dy || 0;
24846
24847
  for (let i = 0; i < p.count; i++) {
24847
24848
  p.setZ(i, p.getZ(i) * sz);
24848
24849
  p.setY(i, p.getY(i) + dy * Math.sign(p.getY(i)));
24849
24850
  }
24850
24851
  if (g.attributes.color) g.deleteAttribute("color");
24851
- const m = c.add(g, mat, mesh.position.x, mesh.position.y, mesh.position.z);
24852
+ const m = c.add(g, mat, mesh2.position.x, mesh2.position.y, mesh2.position.z);
24852
24853
  m.castShadow = false;
24853
24854
  kit.cutMesh(m, [keep], 40, o.sub ? { sub: o.sub } : void 0);
24854
24855
  c.deform.push(m);
@@ -27604,9 +27605,9 @@ var GameVehiclesThree = (() => {
27604
27605
  for (const name of LITE_CLASSES) acc[name] = { P: [], N: [], C: [], U: [], I: [], nv: 0, alpha: name === "glass", uv: name === "plate", map: null };
27605
27606
  return acc;
27606
27607
  };
27607
- function classify(mat, mesh, c) {
27608
+ function classify(mat, mesh2, c) {
27608
27609
  if (mat.map) {
27609
- if (mesh.userData.plate) return "plate";
27610
+ if (mesh2.userData.plate) return "plate";
27610
27611
  if (mat.userData && mat.userData.grille || mat.name === "grille" || mat.metalness != null && mat.roughness != null && !mat.transparent) return "trim";
27611
27612
  return null;
27612
27613
  }
@@ -27752,11 +27753,11 @@ var GameVehiclesThree = (() => {
27752
27753
  mt.map = A.map;
27753
27754
  if (mt.map) mt.map.needsUpdate = true;
27754
27755
  }
27755
- const mesh = new THREE.Mesh(g, mt);
27756
- mesh.name = name;
27757
- mesh.castShadow = name !== "glass" && name !== "light";
27758
- mesh.receiveShadow = name !== "light";
27759
- meshes.push(mesh);
27756
+ const mesh2 = new THREE.Mesh(g, mt);
27757
+ mesh2.name = name;
27758
+ mesh2.castShadow = name !== "glass" && name !== "light";
27759
+ mesh2.receiveShadow = name !== "light";
27760
+ meshes.push(mesh2);
27760
27761
  }
27761
27762
  return meshes;
27762
27763
  }
@@ -27805,7 +27806,7 @@ var GameVehiclesThree = (() => {
27805
27806
  const spec = kit.find(key);
27806
27807
  if (!spec) throw new Error(`createVehiclesThree: unknown vehicle "${key}"`);
27807
27808
  const seed = o.seed == null ? null : o.seed;
27808
- const color = o.color || (seed != null ? colorFromSeed(seed, isMilitary(key) ? paintPalettes.military : paintPalettes.civil) : null);
27809
+ const color2 = o.color || (seed != null ? colorFromSeed(seed, isMilitary(key) ? paintPalettes.military : paintPalettes.civil) : null);
27809
27810
  const c = kit.build(key, o.state || "intact", void 0, { lod: quality === "lite" });
27810
27811
  c.root.updateMatrixWorld(true);
27811
27812
  const primary = primaryPaint(c);
@@ -27836,9 +27837,9 @@ var GameVehiclesThree = (() => {
27836
27837
  c.vehicle.matrixAutoUpdate = true;
27837
27838
  pivot.add(c.vehicle);
27838
27839
  group.add(pivot);
27839
- if (color && primary) {
27840
+ if (color2 && primary) {
27840
27841
  const repainted = primary.clone();
27841
- repainted.color.set(color);
27842
+ repainted.color.set(color2);
27842
27843
  c.vehicle.traverse((m) => {
27843
27844
  if (!m.isMesh) return;
27844
27845
  if (Array.isArray(m.material)) m.material = m.material.map((x) => x === primary ? repainted : x);
@@ -27848,8 +27849,8 @@ var GameVehiclesThree = (() => {
27848
27849
  markDamageables(c, damageables);
27849
27850
  group.updateMatrixWorld(true);
27850
27851
  } else {
27851
- const fusion = fuse(THREE, c, pivotMatrix, color ? new THREE.Color(color) : null, primary, kit.lodHiddenMaterials());
27852
- for (const mesh of liteMeshes(THREE, fusion, liteMaterials(THREE, kit.studioEnvironment()))) group.add(mesh);
27852
+ const fusion = fuse(THREE, c, pivotMatrix, color2 ? new THREE.Color(color2) : null, primary, kit.lodHiddenMaterials());
27853
+ for (const mesh2 of liteMeshes(THREE, fusion, liteMaterials(THREE, kit.studioEnvironment()))) group.add(mesh2);
27853
27854
  pruned = fusion.pruned;
27854
27855
  }
27855
27856
  const size = new THREE.Box3().setFromObject(group).getSize(new THREE.Vector3());
@@ -27860,7 +27861,7 @@ var GameVehiclesThree = (() => {
27860
27861
  return {
27861
27862
  key,
27862
27863
  quality,
27863
- color,
27864
+ color: color2,
27864
27865
  seed,
27865
27866
  group,
27866
27867
  damageables,
@@ -27895,6 +27896,1594 @@ var GameVehiclesThree = (() => {
27895
27896
  }
27896
27897
  }
27897
27898
 
27899
+ // ../game-shapes/dist/chunk-R4RY23RH.js
27900
+ function canonicalJson(value) {
27901
+ if (value === null) return "null";
27902
+ if (typeof value === "number") return Object.is(value, -0) ? "-0" : Number.isFinite(value) ? String(value) : JSON.stringify(String(value));
27903
+ if (typeof value === "string") return JSON.stringify(value);
27904
+ if (typeof value === "boolean") return value ? "true" : "false";
27905
+ if (typeof value === "function") throw new Error("game-shapes: a function cannot be part of a shape (register it as a generator)");
27906
+ if (ArrayBuffer.isView(value)) return canonicalJson(Array.from(value));
27907
+ if (Array.isArray(value)) return `[${value.map((item) => item === void 0 ? "null" : canonicalJson(item)).join(",")}]`;
27908
+ if (typeof value === "object") {
27909
+ const record = value;
27910
+ const keys = Object.keys(record).filter((key) => record[key] !== void 0).sort();
27911
+ return `{${keys.map((key) => `${JSON.stringify(key)}:${canonicalJson(record[key])}`).join(",")}}`;
27912
+ }
27913
+ return "null";
27914
+ }
27915
+ function needsUint32(array) {
27916
+ for (let i = array.length - 1; i >= 0; --i) if (array[i] >= 65535) return true;
27917
+ return false;
27918
+ }
27919
+ var indexArray = (indices) => needsUint32(indices) ? new Uint32Array(indices) : new Uint16Array(indices);
27920
+ function pack(type, parameters, a) {
27921
+ return {
27922
+ type,
27923
+ parameters,
27924
+ positions: new Float32Array(a.vertices),
27925
+ normals: new Float32Array(a.normals),
27926
+ uvs: new Float32Array(a.uvs),
27927
+ ...a.indices ? { indices: indexArray(a.indices) } : {},
27928
+ groups: a.groups
27929
+ };
27930
+ }
27931
+ var normalize3 = (x, y, z) => {
27932
+ const length = Math.sqrt(x * x + y * y + z * z);
27933
+ const s = 1 / (length || 1);
27934
+ return [x * s, y * s, z * s];
27935
+ };
27936
+ function box(width = 1, height = 1, depth = 1, widthSegments = 1, heightSegments = 1, depthSegments = 1) {
27937
+ const parameters = { width, height, depth, widthSegments, heightSegments, depthSegments };
27938
+ widthSegments = Math.floor(widthSegments);
27939
+ heightSegments = Math.floor(heightSegments);
27940
+ depthSegments = Math.floor(depthSegments);
27941
+ const indices = [];
27942
+ const vertices = [];
27943
+ const normals = [];
27944
+ const uvs = [];
27945
+ const groups = [];
27946
+ let numberOfVertices = 0;
27947
+ let groupStart = 0;
27948
+ const buildPlane = (u, v, w, udir, vdir, width2, height2, depth2, gridX, gridY, materialIndex) => {
27949
+ const segmentWidth = width2 / gridX;
27950
+ const segmentHeight = height2 / gridY;
27951
+ const widthHalf = width2 / 2;
27952
+ const heightHalf = height2 / 2;
27953
+ const depthHalf = depth2 / 2;
27954
+ const gridX1 = gridX + 1;
27955
+ const gridY1 = gridY + 1;
27956
+ let vertexCounter = 0;
27957
+ let groupCount = 0;
27958
+ const vector = { x: 0, y: 0, z: 0 };
27959
+ for (let iy = 0; iy < gridY1; iy++) {
27960
+ const y = iy * segmentHeight - heightHalf;
27961
+ for (let ix = 0; ix < gridX1; ix++) {
27962
+ const x = ix * segmentWidth - widthHalf;
27963
+ vector[u] = x * udir;
27964
+ vector[v] = y * vdir;
27965
+ vector[w] = depthHalf;
27966
+ vertices.push(vector.x, vector.y, vector.z);
27967
+ vector[u] = 0;
27968
+ vector[v] = 0;
27969
+ vector[w] = depth2 > 0 ? 1 : -1;
27970
+ normals.push(vector.x, vector.y, vector.z);
27971
+ uvs.push(ix / gridX);
27972
+ uvs.push(1 - iy / gridY);
27973
+ vertexCounter += 1;
27974
+ }
27975
+ }
27976
+ for (let iy = 0; iy < gridY; iy++) {
27977
+ for (let ix = 0; ix < gridX; ix++) {
27978
+ const a = numberOfVertices + ix + gridX1 * iy;
27979
+ const b = numberOfVertices + ix + gridX1 * (iy + 1);
27980
+ const c = numberOfVertices + (ix + 1) + gridX1 * (iy + 1);
27981
+ const d = numberOfVertices + (ix + 1) + gridX1 * iy;
27982
+ indices.push(a, b, d);
27983
+ indices.push(b, c, d);
27984
+ groupCount += 6;
27985
+ }
27986
+ }
27987
+ groups.push({ start: groupStart, count: groupCount, materialIndex });
27988
+ groupStart += groupCount;
27989
+ numberOfVertices += vertexCounter;
27990
+ };
27991
+ buildPlane("z", "y", "x", -1, -1, depth, height, width, depthSegments, heightSegments, 0);
27992
+ buildPlane("z", "y", "x", 1, -1, depth, height, -width, depthSegments, heightSegments, 1);
27993
+ buildPlane("x", "z", "y", 1, 1, width, depth, height, widthSegments, depthSegments, 2);
27994
+ buildPlane("x", "z", "y", 1, -1, width, depth, -height, widthSegments, depthSegments, 3);
27995
+ buildPlane("x", "y", "z", 1, -1, width, height, depth, widthSegments, heightSegments, 4);
27996
+ buildPlane("x", "y", "z", -1, -1, width, height, -depth, widthSegments, heightSegments, 5);
27997
+ return pack("BoxGeometry", parameters, { vertices, normals, uvs, indices, groups });
27998
+ }
27999
+ function cylinderArrays(radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength) {
28000
+ radialSegments = Math.floor(radialSegments);
28001
+ heightSegments = Math.floor(heightSegments);
28002
+ const indices = [];
28003
+ const vertices = [];
28004
+ const normals = [];
28005
+ const uvs = [];
28006
+ const groups = [];
28007
+ let index = 0;
28008
+ const indexArray2 = [];
28009
+ const halfHeight = height / 2;
28010
+ let groupStart = 0;
28011
+ const generateTorso = () => {
28012
+ let groupCount = 0;
28013
+ const slope = (radiusBottom - radiusTop) / height;
28014
+ for (let y = 0; y <= heightSegments; y++) {
28015
+ const indexRow = [];
28016
+ const v = y / heightSegments;
28017
+ const radius = v * (radiusBottom - radiusTop) + radiusTop;
28018
+ for (let x = 0; x <= radialSegments; x++) {
28019
+ const u = x / radialSegments;
28020
+ const theta = u * thetaLength + thetaStart;
28021
+ const sinTheta = Math.sin(theta);
28022
+ const cosTheta = Math.cos(theta);
28023
+ vertices.push(radius * sinTheta, -v * height + halfHeight, radius * cosTheta);
28024
+ const n = normalize3(sinTheta, slope, cosTheta);
28025
+ normals.push(n[0], n[1], n[2]);
28026
+ uvs.push(u, 1 - v);
28027
+ indexRow.push(index++);
28028
+ }
28029
+ indexArray2.push(indexRow);
28030
+ }
28031
+ for (let x = 0; x < radialSegments; x++) {
28032
+ for (let y = 0; y < heightSegments; y++) {
28033
+ const a = indexArray2[y][x];
28034
+ const b = indexArray2[y + 1][x];
28035
+ const c = indexArray2[y + 1][x + 1];
28036
+ const d = indexArray2[y][x + 1];
28037
+ indices.push(a, b, d);
28038
+ indices.push(b, c, d);
28039
+ groupCount += 6;
28040
+ }
28041
+ }
28042
+ groups.push({ start: groupStart, count: groupCount, materialIndex: 0 });
28043
+ groupStart += groupCount;
28044
+ };
28045
+ const generateCap = (top) => {
28046
+ const centerIndexStart = index;
28047
+ let groupCount = 0;
28048
+ const radius = top === true ? radiusTop : radiusBottom;
28049
+ const sign2 = top === true ? 1 : -1;
28050
+ for (let x = 1; x <= radialSegments; x++) {
28051
+ vertices.push(0, halfHeight * sign2, 0);
28052
+ normals.push(0, sign2, 0);
28053
+ uvs.push(0.5, 0.5);
28054
+ index++;
28055
+ }
28056
+ const centerIndexEnd = index;
28057
+ for (let x = 0; x <= radialSegments; x++) {
28058
+ const u = x / radialSegments;
28059
+ const theta = u * thetaLength + thetaStart;
28060
+ const cosTheta = Math.cos(theta);
28061
+ const sinTheta = Math.sin(theta);
28062
+ vertices.push(radius * sinTheta, halfHeight * sign2, radius * cosTheta);
28063
+ normals.push(0, sign2, 0);
28064
+ uvs.push(cosTheta * 0.5 + 0.5, sinTheta * 0.5 * sign2 + 0.5);
28065
+ index++;
28066
+ }
28067
+ for (let x = 0; x < radialSegments; x++) {
28068
+ const c = centerIndexStart + x;
28069
+ const i = centerIndexEnd + x;
28070
+ if (top === true) indices.push(i, i + 1, c);
28071
+ else indices.push(i + 1, i, c);
28072
+ groupCount += 3;
28073
+ }
28074
+ groups.push({ start: groupStart, count: groupCount, materialIndex: top === true ? 1 : 2 });
28075
+ groupStart += groupCount;
28076
+ };
28077
+ generateTorso();
28078
+ if (openEnded === false) {
28079
+ if (radiusTop > 0) generateCap(true);
28080
+ if (radiusBottom > 0) generateCap(false);
28081
+ }
28082
+ return { vertices, normals, uvs, indices, groups };
28083
+ }
28084
+ function cylinder(radiusTop = 1, radiusBottom = 1, height = 1, radialSegments = 32, heightSegments = 1, openEnded = false, thetaStart = 0, thetaLength = Math.PI * 2) {
28085
+ const parameters = { radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength };
28086
+ return pack("CylinderGeometry", parameters, cylinderArrays(radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength));
28087
+ }
28088
+ function cone(radius = 1, height = 1, radialSegments = 32, heightSegments = 1, openEnded = false, thetaStart = 0, thetaLength = Math.PI * 2) {
28089
+ const parameters = { radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength };
28090
+ return pack("ConeGeometry", parameters, cylinderArrays(0, radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength));
28091
+ }
28092
+ function sphere(radius = 1, widthSegments = 32, heightSegments = 16, phiStart = 0, phiLength = Math.PI * 2, thetaStart = 0, thetaLength = Math.PI) {
28093
+ const parameters = { radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength };
28094
+ widthSegments = Math.max(3, Math.floor(widthSegments));
28095
+ heightSegments = Math.max(2, Math.floor(heightSegments));
28096
+ const thetaEnd = Math.min(thetaStart + thetaLength, Math.PI);
28097
+ let index = 0;
28098
+ const grid = [];
28099
+ const indices = [];
28100
+ const vertices = [];
28101
+ const normals = [];
28102
+ const uvs = [];
28103
+ for (let iy = 0; iy <= heightSegments; iy++) {
28104
+ const verticesRow = [];
28105
+ const v = iy / heightSegments;
28106
+ let uOffset = 0;
28107
+ if (iy === 0 && thetaStart === 0) uOffset = 0.5 / widthSegments;
28108
+ else if (iy === heightSegments && thetaEnd === Math.PI) uOffset = -0.5 / widthSegments;
28109
+ for (let ix = 0; ix <= widthSegments; ix++) {
28110
+ const u = ix / widthSegments;
28111
+ const x = -radius * Math.cos(phiStart + u * phiLength) * Math.sin(thetaStart + v * thetaLength);
28112
+ const y = radius * Math.cos(thetaStart + v * thetaLength);
28113
+ const z = radius * Math.sin(phiStart + u * phiLength) * Math.sin(thetaStart + v * thetaLength);
28114
+ vertices.push(x, y, z);
28115
+ const n = normalize3(x, y, z);
28116
+ normals.push(n[0], n[1], n[2]);
28117
+ uvs.push(u + uOffset, 1 - v);
28118
+ verticesRow.push(index++);
28119
+ }
28120
+ grid.push(verticesRow);
28121
+ }
28122
+ for (let iy = 0; iy < heightSegments; iy++) {
28123
+ for (let ix = 0; ix < widthSegments; ix++) {
28124
+ const a = grid[iy][ix + 1];
28125
+ const b = grid[iy][ix];
28126
+ const c = grid[iy + 1][ix];
28127
+ const d = grid[iy + 1][ix + 1];
28128
+ if (iy !== 0 || thetaStart > 0) indices.push(a, b, d);
28129
+ if (iy !== heightSegments - 1 || thetaEnd < Math.PI) indices.push(b, c, d);
28130
+ }
28131
+ }
28132
+ return pack("SphereGeometry", parameters, { vertices, normals, uvs, indices, groups: [] });
28133
+ }
28134
+ function plane(width = 1, height = 1, widthSegments = 1, heightSegments = 1) {
28135
+ const parameters = { width, height, widthSegments, heightSegments };
28136
+ const widthHalf = width / 2;
28137
+ const heightHalf = height / 2;
28138
+ const gridX = Math.floor(widthSegments);
28139
+ const gridY = Math.floor(heightSegments);
28140
+ const gridX1 = gridX + 1;
28141
+ const gridY1 = gridY + 1;
28142
+ const segmentWidth = width / gridX;
28143
+ const segmentHeight = height / gridY;
28144
+ const indices = [];
28145
+ const vertices = [];
28146
+ const normals = [];
28147
+ const uvs = [];
28148
+ for (let iy = 0; iy < gridY1; iy++) {
28149
+ const y = iy * segmentHeight - heightHalf;
28150
+ for (let ix = 0; ix < gridX1; ix++) {
28151
+ const x = ix * segmentWidth - widthHalf;
28152
+ vertices.push(x, -y, 0);
28153
+ normals.push(0, 0, 1);
28154
+ uvs.push(ix / gridX);
28155
+ uvs.push(1 - iy / gridY);
28156
+ }
28157
+ }
28158
+ for (let iy = 0; iy < gridY; iy++) {
28159
+ for (let ix = 0; ix < gridX; ix++) {
28160
+ const a = ix + gridX1 * iy;
28161
+ const b = ix + gridX1 * (iy + 1);
28162
+ const c = ix + 1 + gridX1 * (iy + 1);
28163
+ const d = ix + 1 + gridX1 * iy;
28164
+ indices.push(a, b, d);
28165
+ indices.push(b, c, d);
28166
+ }
28167
+ }
28168
+ return pack("PlaneGeometry", parameters, { vertices, normals, uvs, indices, groups: [] });
28169
+ }
28170
+ function circle(radius = 1, segments = 32, thetaStart = 0, thetaLength = Math.PI * 2) {
28171
+ const parameters = { radius, segments, thetaStart, thetaLength };
28172
+ segments = Math.max(3, segments);
28173
+ const indices = [];
28174
+ const vertices = [];
28175
+ const normals = [];
28176
+ const uvs = [];
28177
+ vertices.push(0, 0, 0);
28178
+ normals.push(0, 0, 1);
28179
+ uvs.push(0.5, 0.5);
28180
+ for (let s = 0, i = 3; s <= segments; s++, i += 3) {
28181
+ const segment = thetaStart + s / segments * thetaLength;
28182
+ vertices.push(radius * Math.cos(segment), radius * Math.sin(segment), 0);
28183
+ normals.push(0, 0, 1);
28184
+ uvs.push((vertices[i] / radius + 1) / 2, (vertices[i + 1] / radius + 1) / 2);
28185
+ }
28186
+ for (let i = 1; i <= segments; i++) indices.push(i, i + 1, 0);
28187
+ return pack("CircleGeometry", parameters, { vertices, normals, uvs, indices, groups: [] });
28188
+ }
28189
+ function ring(innerRadius = 0.5, outerRadius = 1, thetaSegments = 32, phiSegments = 1, thetaStart = 0, thetaLength = Math.PI * 2) {
28190
+ const parameters = { innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength };
28191
+ thetaSegments = Math.max(3, thetaSegments);
28192
+ phiSegments = Math.max(1, phiSegments);
28193
+ const indices = [];
28194
+ const vertices = [];
28195
+ const normals = [];
28196
+ const uvs = [];
28197
+ let radius = innerRadius;
28198
+ const radiusStep = (outerRadius - innerRadius) / phiSegments;
28199
+ for (let j = 0; j <= phiSegments; j++) {
28200
+ for (let i = 0; i <= thetaSegments; i++) {
28201
+ const segment = thetaStart + i / thetaSegments * thetaLength;
28202
+ const x = radius * Math.cos(segment);
28203
+ const y = radius * Math.sin(segment);
28204
+ vertices.push(x, y, 0);
28205
+ normals.push(0, 0, 1);
28206
+ uvs.push((x / outerRadius + 1) / 2, (y / outerRadius + 1) / 2);
28207
+ }
28208
+ radius += radiusStep;
28209
+ }
28210
+ for (let j = 0; j < phiSegments; j++) {
28211
+ const thetaSegmentLevel = j * (thetaSegments + 1);
28212
+ for (let i = 0; i < thetaSegments; i++) {
28213
+ const segment = i + thetaSegmentLevel;
28214
+ const a = segment;
28215
+ const b = segment + thetaSegments + 1;
28216
+ const c = segment + thetaSegments + 2;
28217
+ const d = segment + 1;
28218
+ indices.push(a, b, d);
28219
+ indices.push(b, c, d);
28220
+ }
28221
+ }
28222
+ return pack("RingGeometry", parameters, { vertices, normals, uvs, indices, groups: [] });
28223
+ }
28224
+ function lathe(points, segments = 12, phiStart = 0, phiLength = Math.PI * 2) {
28225
+ const parameters = { points: points.map(([x, y]) => ({ x, y })), segments, phiStart, phiLength };
28226
+ segments = Math.floor(segments);
28227
+ phiLength = Math.max(0, Math.min(Math.PI * 2, phiLength));
28228
+ const indices = [];
28229
+ const vertices = [];
28230
+ const uvs = [];
28231
+ const initNormals = [];
28232
+ const normals = [];
28233
+ const inverseSegments = 1 / segments;
28234
+ const normal = { x: 0, y: 0, z: 0 };
28235
+ const curNormal = { x: 0, y: 0, z: 0 };
28236
+ const prevNormal = { x: 0, y: 0, z: 0 };
28237
+ let dx = 0;
28238
+ let dy = 0;
28239
+ const last = points.length - 1;
28240
+ const px = (j) => points[j][0];
28241
+ const py = (j) => points[j][1];
28242
+ const setNormalized = () => {
28243
+ const n = normalize3(normal.x, normal.y, normal.z);
28244
+ normal.x = n[0];
28245
+ normal.y = n[1];
28246
+ normal.z = n[2];
28247
+ };
28248
+ for (let j = 0; j <= last; j++) {
28249
+ if (j === 0) {
28250
+ dx = px(j + 1) - px(j);
28251
+ dy = py(j + 1) - py(j);
28252
+ normal.x = dy * 1;
28253
+ normal.y = -dx;
28254
+ normal.z = dy * 0;
28255
+ prevNormal.x = normal.x;
28256
+ prevNormal.y = normal.y;
28257
+ prevNormal.z = normal.z;
28258
+ setNormalized();
28259
+ initNormals.push(normal.x, normal.y, normal.z);
28260
+ } else if (j === last) {
28261
+ initNormals.push(prevNormal.x, prevNormal.y, prevNormal.z);
28262
+ } else {
28263
+ dx = px(j + 1) - px(j);
28264
+ dy = py(j + 1) - py(j);
28265
+ normal.x = dy * 1;
28266
+ normal.y = -dx;
28267
+ normal.z = dy * 0;
28268
+ curNormal.x = normal.x;
28269
+ curNormal.y = normal.y;
28270
+ curNormal.z = normal.z;
28271
+ normal.x += prevNormal.x;
28272
+ normal.y += prevNormal.y;
28273
+ normal.z += prevNormal.z;
28274
+ setNormalized();
28275
+ initNormals.push(normal.x, normal.y, normal.z);
28276
+ prevNormal.x = curNormal.x;
28277
+ prevNormal.y = curNormal.y;
28278
+ prevNormal.z = curNormal.z;
28279
+ }
28280
+ }
28281
+ for (let i = 0; i <= segments; i++) {
28282
+ const phi = phiStart + i * inverseSegments * phiLength;
28283
+ const sin = Math.sin(phi);
28284
+ const cos = Math.cos(phi);
28285
+ for (let j = 0; j <= last; j++) {
28286
+ vertices.push(px(j) * sin, py(j), px(j) * cos);
28287
+ uvs.push(i / segments, j / (points.length - 1));
28288
+ const x = initNormals[3 * j + 0] * sin;
28289
+ const y = initNormals[3 * j + 1];
28290
+ const z = initNormals[3 * j + 0] * cos;
28291
+ normals.push(x, y, z);
28292
+ }
28293
+ }
28294
+ for (let i = 0; i < segments; i++) {
28295
+ for (let j = 0; j < points.length - 1; j++) {
28296
+ const base = j + i * points.length;
28297
+ const a = base;
28298
+ const b = base + points.length;
28299
+ const c = base + points.length + 1;
28300
+ const d = base + 1;
28301
+ indices.push(a, b, d);
28302
+ indices.push(c, d, b);
28303
+ }
28304
+ }
28305
+ return pack("LatheGeometry", parameters, { vertices, normals, uvs, indices, groups: [] });
28306
+ }
28307
+ function torus(radius = 1, tube = 0.4, radialSegments = 12, tubularSegments = 48, arc = Math.PI * 2) {
28308
+ const parameters = { radius, tube, radialSegments, tubularSegments, arc };
28309
+ radialSegments = Math.floor(radialSegments);
28310
+ tubularSegments = Math.floor(tubularSegments);
28311
+ const indices = [];
28312
+ const vertices = [];
28313
+ const normals = [];
28314
+ const uvs = [];
28315
+ for (let j = 0; j <= radialSegments; j++) {
28316
+ for (let i = 0; i <= tubularSegments; i++) {
28317
+ const u = i / tubularSegments * arc;
28318
+ const v = j / radialSegments * Math.PI * 2;
28319
+ const x = (radius + tube * Math.cos(v)) * Math.cos(u);
28320
+ const y = (radius + tube * Math.cos(v)) * Math.sin(u);
28321
+ const z = tube * Math.sin(v);
28322
+ vertices.push(x, y, z);
28323
+ const cx = radius * Math.cos(u);
28324
+ const cy = radius * Math.sin(u);
28325
+ const n = normalize3(x - cx, y - cy, z - 0);
28326
+ normals.push(n[0], n[1], n[2]);
28327
+ uvs.push(i / tubularSegments);
28328
+ uvs.push(j / radialSegments);
28329
+ }
28330
+ }
28331
+ for (let j = 1; j <= radialSegments; j++) {
28332
+ for (let i = 1; i <= tubularSegments; i++) {
28333
+ const a = (tubularSegments + 1) * j + i - 1;
28334
+ const b = (tubularSegments + 1) * (j - 1) + i - 1;
28335
+ const c = (tubularSegments + 1) * (j - 1) + i;
28336
+ const d = (tubularSegments + 1) * j + i;
28337
+ indices.push(a, b, d);
28338
+ indices.push(b, c, d);
28339
+ }
28340
+ }
28341
+ return pack("TorusGeometry", parameters, { vertices, normals, uvs, indices, groups: [] });
28342
+ }
28343
+ function difference(size, subtract) {
28344
+ const [w, h, d] = size;
28345
+ const hw = w / 2;
28346
+ const hh = h / 2;
28347
+ const hd = d / 2;
28348
+ const holes = subtract.map((hole) => ({ x0: Math.max(-hw, Math.min(hole.min[0], hole.max[0])), x1: Math.min(hw, Math.max(hole.min[0], hole.max[0])), y0: Math.max(-hh, Math.min(hole.min[1], hole.max[1])), y1: Math.min(hh, Math.max(hole.min[1], hole.max[1])) })).filter((hole) => hole.x1 > hole.x0 && hole.y1 > hole.y0);
28349
+ const cuts = (lo, hi, values) => [.../* @__PURE__ */ new Set([lo, hi, ...values.filter((v) => v > lo && v < hi)])].sort((a, b) => a - b);
28350
+ const xs = cuts(-hw, hw, holes.flatMap((hole) => [hole.x0, hole.x1]));
28351
+ const ys = cuts(-hh, hh, holes.flatMap((hole) => [hole.y0, hole.y1]));
28352
+ const nx = xs.length - 1;
28353
+ const ny = ys.length - 1;
28354
+ const solid = (i, j) => {
28355
+ if (i < 0 || j < 0 || i >= nx || j >= ny) return false;
28356
+ const cx = (xs[i] + xs[i + 1]) / 2;
28357
+ const cy = (ys[j] + ys[j + 1]) / 2;
28358
+ return !holes.some((hole) => cx > hole.x0 && cx < hole.x1 && cy > hole.y0 && cy < hole.y1);
28359
+ };
28360
+ const positions = [];
28361
+ const normals = [];
28362
+ const uvs = [];
28363
+ const indices = [];
28364
+ const quad = (corners, normal, uv) => {
28365
+ const base = positions.length / 3;
28366
+ for (let k = 0; k < 4; k++) {
28367
+ positions.push(...corners[k]);
28368
+ normals.push(...normal);
28369
+ uvs.push(...uv[k]);
28370
+ }
28371
+ indices.push(base, base + 1, base + 2, base, base + 2, base + 3);
28372
+ };
28373
+ const fu = (x) => (x + hw) / w;
28374
+ const fv = (y) => (y + hh) / h;
28375
+ for (let j = 0; j < ny; j++) {
28376
+ for (let i = 0; i < nx; i++) {
28377
+ if (!solid(i, j)) continue;
28378
+ const x0 = xs[i];
28379
+ const x1 = xs[i + 1];
28380
+ const y0 = ys[j];
28381
+ const y1 = ys[j + 1];
28382
+ quad([[x0, y0, hd], [x1, y0, hd], [x1, y1, hd], [x0, y1, hd]], [0, 0, 1], [[fu(x0), fv(y0)], [fu(x1), fv(y0)], [fu(x1), fv(y1)], [fu(x0), fv(y1)]]);
28383
+ quad([[x1, y0, -hd], [x0, y0, -hd], [x0, y1, -hd], [x1, y1, -hd]], [0, 0, -1], [[1 - fu(x1), fv(y0)], [1 - fu(x0), fv(y0)], [1 - fu(x0), fv(y1)], [1 - fu(x1), fv(y1)]]);
28384
+ const zu = (z) => (z + hd) / d;
28385
+ if (!solid(i - 1, j)) quad([[x0, y0, -hd], [x0, y0, hd], [x0, y1, hd], [x0, y1, -hd]], [-1, 0, 0], [[zu(-hd), fv(y0)], [zu(hd), fv(y0)], [zu(hd), fv(y1)], [zu(-hd), fv(y1)]]);
28386
+ if (!solid(i + 1, j)) quad([[x1, y0, hd], [x1, y0, -hd], [x1, y1, -hd], [x1, y1, hd]], [1, 0, 0], [[zu(hd), fv(y0)], [zu(-hd), fv(y0)], [zu(-hd), fv(y1)], [zu(hd), fv(y1)]]);
28387
+ if (!solid(i, j - 1)) quad([[x0, y0, -hd], [x1, y0, -hd], [x1, y0, hd], [x0, y0, hd]], [0, -1, 0], [[fu(x0), zu(-hd)], [fu(x1), zu(-hd)], [fu(x1), zu(hd)], [fu(x0), zu(hd)]]);
28388
+ if (!solid(i, j + 1)) quad([[x0, y1, hd], [x1, y1, hd], [x1, y1, -hd], [x0, y1, -hd]], [0, 1, 0], [[fu(x0), zu(hd)], [fu(x1), zu(hd)], [fu(x1), zu(-hd)], [fu(x0), zu(-hd)]]);
28389
+ }
28390
+ }
28391
+ return {
28392
+ type: "BufferGeometry",
28393
+ parameters: { size: [w, h, d], subtract: holes.map((hole) => ({ min: [hole.x0, hole.y0], max: [hole.x1, hole.y1] })) },
28394
+ positions: new Float32Array(positions),
28395
+ normals: new Float32Array(normals),
28396
+ uvs: new Float32Array(uvs),
28397
+ indices: indexArray(indices),
28398
+ groups: []
28399
+ };
28400
+ }
28401
+ var Earcut = {
28402
+ triangulate: function(data, holeIndices, dim = 2) {
28403
+ const hasHoles = holeIndices && holeIndices.length;
28404
+ const outerLen = hasHoles ? holeIndices[0] * dim : data.length;
28405
+ let outerNode = linkedList(data, 0, outerLen, dim, true);
28406
+ const triangles = [];
28407
+ if (!outerNode || outerNode.next === outerNode.prev) return triangles;
28408
+ let minX, minY, maxX, maxY, x, y, invSize;
28409
+ if (hasHoles) outerNode = eliminateHoles(data, holeIndices, outerNode, dim);
28410
+ if (data.length > 80 * dim) {
28411
+ minX = maxX = data[0];
28412
+ minY = maxY = data[1];
28413
+ for (let i = dim; i < outerLen; i += dim) {
28414
+ x = data[i];
28415
+ y = data[i + 1];
28416
+ if (x < minX) minX = x;
28417
+ if (y < minY) minY = y;
28418
+ if (x > maxX) maxX = x;
28419
+ if (y > maxY) maxY = y;
28420
+ }
28421
+ invSize = Math.max(maxX - minX, maxY - minY);
28422
+ invSize = invSize !== 0 ? 32767 / invSize : 0;
28423
+ }
28424
+ earcutLinked(outerNode, triangles, dim, minX, minY, invSize, 0);
28425
+ return triangles;
28426
+ }
28427
+ };
28428
+ function linkedList(data, start, end, dim, clockwise) {
28429
+ let i, last;
28430
+ if (clockwise === signedArea(data, start, end, dim) > 0) {
28431
+ for (i = start; i < end; i += dim) last = insertNode(i, data[i], data[i + 1], last);
28432
+ } else {
28433
+ for (i = end - dim; i >= start; i -= dim) last = insertNode(i, data[i], data[i + 1], last);
28434
+ }
28435
+ if (last && equals(last, last.next)) {
28436
+ removeNode(last);
28437
+ last = last.next;
28438
+ }
28439
+ return last;
28440
+ }
28441
+ function filterPoints(start, end) {
28442
+ if (!start) return start;
28443
+ if (!end) end = start;
28444
+ let p = start, again;
28445
+ do {
28446
+ again = false;
28447
+ if (!p.steiner && (equals(p, p.next) || area(p.prev, p, p.next) === 0)) {
28448
+ removeNode(p);
28449
+ p = end = p.prev;
28450
+ if (p === p.next) break;
28451
+ again = true;
28452
+ } else {
28453
+ p = p.next;
28454
+ }
28455
+ } while (again || p !== end);
28456
+ return end;
28457
+ }
28458
+ function earcutLinked(ear, triangles, dim, minX, minY, invSize, pass) {
28459
+ if (!ear) return;
28460
+ if (!pass && invSize) indexCurve(ear, minX, minY, invSize);
28461
+ let stop = ear, prev, next;
28462
+ while (ear.prev !== ear.next) {
28463
+ prev = ear.prev;
28464
+ next = ear.next;
28465
+ if (invSize ? isEarHashed(ear, minX, minY, invSize) : isEar(ear)) {
28466
+ triangles.push(prev.i / dim | 0);
28467
+ triangles.push(ear.i / dim | 0);
28468
+ triangles.push(next.i / dim | 0);
28469
+ removeNode(ear);
28470
+ ear = next.next;
28471
+ stop = next.next;
28472
+ continue;
28473
+ }
28474
+ ear = next;
28475
+ if (ear === stop) {
28476
+ if (!pass) {
28477
+ earcutLinked(filterPoints(ear), triangles, dim, minX, minY, invSize, 1);
28478
+ } else if (pass === 1) {
28479
+ ear = cureLocalIntersections(filterPoints(ear), triangles, dim);
28480
+ earcutLinked(ear, triangles, dim, minX, minY, invSize, 2);
28481
+ } else if (pass === 2) {
28482
+ splitEarcut(ear, triangles, dim, minX, minY, invSize);
28483
+ }
28484
+ break;
28485
+ }
28486
+ }
28487
+ }
28488
+ function isEar(ear) {
28489
+ const a = ear.prev, b = ear, c = ear.next;
28490
+ if (area(a, b, c) >= 0) return false;
28491
+ const ax = a.x, bx = b.x, cx = c.x, ay = a.y, by = b.y, cy = c.y;
28492
+ const x0 = ax < bx ? ax < cx ? ax : cx : bx < cx ? bx : cx, y0 = ay < by ? ay < cy ? ay : cy : by < cy ? by : cy, x1 = ax > bx ? ax > cx ? ax : cx : bx > cx ? bx : cx, y1 = ay > by ? ay > cy ? ay : cy : by > cy ? by : cy;
28493
+ let p = c.next;
28494
+ while (p !== a) {
28495
+ if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && pointInTriangle(ax, ay, bx, by, cx, cy, p.x, p.y) && area(p.prev, p, p.next) >= 0) return false;
28496
+ p = p.next;
28497
+ }
28498
+ return true;
28499
+ }
28500
+ function isEarHashed(ear, minX, minY, invSize) {
28501
+ const a = ear.prev, b = ear, c = ear.next;
28502
+ if (area(a, b, c) >= 0) return false;
28503
+ const ax = a.x, bx = b.x, cx = c.x, ay = a.y, by = b.y, cy = c.y;
28504
+ const x0 = ax < bx ? ax < cx ? ax : cx : bx < cx ? bx : cx, y0 = ay < by ? ay < cy ? ay : cy : by < cy ? by : cy, x1 = ax > bx ? ax > cx ? ax : cx : bx > cx ? bx : cx, y1 = ay > by ? ay > cy ? ay : cy : by > cy ? by : cy;
28505
+ const minZ = zOrder(x0, y0, minX, minY, invSize), maxZ = zOrder(x1, y1, minX, minY, invSize);
28506
+ let p = ear.prevZ, n = ear.nextZ;
28507
+ while (p && p.z >= minZ && n && n.z <= maxZ) {
28508
+ if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && p !== a && p !== c && pointInTriangle(ax, ay, bx, by, cx, cy, p.x, p.y) && area(p.prev, p, p.next) >= 0) return false;
28509
+ p = p.prevZ;
28510
+ if (n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== a && n !== c && pointInTriangle(ax, ay, bx, by, cx, cy, n.x, n.y) && area(n.prev, n, n.next) >= 0) return false;
28511
+ n = n.nextZ;
28512
+ }
28513
+ while (p && p.z >= minZ) {
28514
+ if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && p !== a && p !== c && pointInTriangle(ax, ay, bx, by, cx, cy, p.x, p.y) && area(p.prev, p, p.next) >= 0) return false;
28515
+ p = p.prevZ;
28516
+ }
28517
+ while (n && n.z <= maxZ) {
28518
+ if (n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== a && n !== c && pointInTriangle(ax, ay, bx, by, cx, cy, n.x, n.y) && area(n.prev, n, n.next) >= 0) return false;
28519
+ n = n.nextZ;
28520
+ }
28521
+ return true;
28522
+ }
28523
+ function cureLocalIntersections(start, triangles, dim) {
28524
+ let p = start;
28525
+ do {
28526
+ const a = p.prev, b = p.next.next;
28527
+ if (!equals(a, b) && intersects(a, p, p.next, b) && locallyInside(a, b) && locallyInside(b, a)) {
28528
+ triangles.push(a.i / dim | 0);
28529
+ triangles.push(p.i / dim | 0);
28530
+ triangles.push(b.i / dim | 0);
28531
+ removeNode(p);
28532
+ removeNode(p.next);
28533
+ p = start = b;
28534
+ }
28535
+ p = p.next;
28536
+ } while (p !== start);
28537
+ return filterPoints(p);
28538
+ }
28539
+ function splitEarcut(start, triangles, dim, minX, minY, invSize) {
28540
+ let a = start;
28541
+ do {
28542
+ let b = a.next.next;
28543
+ while (b !== a.prev) {
28544
+ if (a.i !== b.i && isValidDiagonal(a, b)) {
28545
+ let c = splitPolygon(a, b);
28546
+ a = filterPoints(a, a.next);
28547
+ c = filterPoints(c, c.next);
28548
+ earcutLinked(a, triangles, dim, minX, minY, invSize, 0);
28549
+ earcutLinked(c, triangles, dim, minX, minY, invSize, 0);
28550
+ return;
28551
+ }
28552
+ b = b.next;
28553
+ }
28554
+ a = a.next;
28555
+ } while (a !== start);
28556
+ }
28557
+ function eliminateHoles(data, holeIndices, outerNode, dim) {
28558
+ const queue = [];
28559
+ let i, len, start, end, list2;
28560
+ for (i = 0, len = holeIndices.length; i < len; i++) {
28561
+ start = holeIndices[i] * dim;
28562
+ end = i < len - 1 ? holeIndices[i + 1] * dim : data.length;
28563
+ list2 = linkedList(data, start, end, dim, false);
28564
+ if (list2 === list2.next) list2.steiner = true;
28565
+ queue.push(getLeftmost(list2));
28566
+ }
28567
+ queue.sort(compareX);
28568
+ for (i = 0; i < queue.length; i++) {
28569
+ outerNode = eliminateHole(queue[i], outerNode);
28570
+ }
28571
+ return outerNode;
28572
+ }
28573
+ function compareX(a, b) {
28574
+ return a.x - b.x;
28575
+ }
28576
+ function eliminateHole(hole, outerNode) {
28577
+ const bridge = findHoleBridge(hole, outerNode);
28578
+ if (!bridge) {
28579
+ return outerNode;
28580
+ }
28581
+ const bridgeReverse = splitPolygon(bridge, hole);
28582
+ filterPoints(bridgeReverse, bridgeReverse.next);
28583
+ return filterPoints(bridge, bridge.next);
28584
+ }
28585
+ function findHoleBridge(hole, outerNode) {
28586
+ let p = outerNode, qx = -Infinity, m;
28587
+ const hx = hole.x, hy = hole.y;
28588
+ do {
28589
+ if (hy <= p.y && hy >= p.next.y && p.next.y !== p.y) {
28590
+ const x = p.x + (hy - p.y) * (p.next.x - p.x) / (p.next.y - p.y);
28591
+ if (x <= hx && x > qx) {
28592
+ qx = x;
28593
+ m = p.x < p.next.x ? p : p.next;
28594
+ if (x === hx) return m;
28595
+ }
28596
+ }
28597
+ p = p.next;
28598
+ } while (p !== outerNode);
28599
+ if (!m) return null;
28600
+ const stop = m, mx = m.x, my = m.y;
28601
+ let tanMin = Infinity, tan;
28602
+ p = m;
28603
+ do {
28604
+ if (hx >= p.x && p.x >= mx && hx !== p.x && pointInTriangle(hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p.x, p.y)) {
28605
+ tan = Math.abs(hy - p.y) / (hx - p.x);
28606
+ if (locallyInside(p, hole) && (tan < tanMin || tan === tanMin && (p.x > m.x || p.x === m.x && sectorContainsSector(m, p)))) {
28607
+ m = p;
28608
+ tanMin = tan;
28609
+ }
28610
+ }
28611
+ p = p.next;
28612
+ } while (p !== stop);
28613
+ return m;
28614
+ }
28615
+ function sectorContainsSector(m, p) {
28616
+ return area(m.prev, m, p.prev) < 0 && area(p.next, m, m.next) < 0;
28617
+ }
28618
+ function indexCurve(start, minX, minY, invSize) {
28619
+ let p = start;
28620
+ do {
28621
+ if (p.z === 0) p.z = zOrder(p.x, p.y, minX, minY, invSize);
28622
+ p.prevZ = p.prev;
28623
+ p.nextZ = p.next;
28624
+ p = p.next;
28625
+ } while (p !== start);
28626
+ p.prevZ.nextZ = null;
28627
+ p.prevZ = null;
28628
+ sortLinked(p);
28629
+ }
28630
+ function sortLinked(list2) {
28631
+ let i, p, q, e, tail, numMerges, pSize, qSize, inSize = 1;
28632
+ do {
28633
+ p = list2;
28634
+ list2 = null;
28635
+ tail = null;
28636
+ numMerges = 0;
28637
+ while (p) {
28638
+ numMerges++;
28639
+ q = p;
28640
+ pSize = 0;
28641
+ for (i = 0; i < inSize; i++) {
28642
+ pSize++;
28643
+ q = q.nextZ;
28644
+ if (!q) break;
28645
+ }
28646
+ qSize = inSize;
28647
+ while (pSize > 0 || qSize > 0 && q) {
28648
+ if (pSize !== 0 && (qSize === 0 || !q || p.z <= q.z)) {
28649
+ e = p;
28650
+ p = p.nextZ;
28651
+ pSize--;
28652
+ } else {
28653
+ e = q;
28654
+ q = q.nextZ;
28655
+ qSize--;
28656
+ }
28657
+ if (tail) tail.nextZ = e;
28658
+ else list2 = e;
28659
+ e.prevZ = tail;
28660
+ tail = e;
28661
+ }
28662
+ p = q;
28663
+ }
28664
+ tail.nextZ = null;
28665
+ inSize *= 2;
28666
+ } while (numMerges > 1);
28667
+ return list2;
28668
+ }
28669
+ function zOrder(x, y, minX, minY, invSize) {
28670
+ x = (x - minX) * invSize | 0;
28671
+ y = (y - minY) * invSize | 0;
28672
+ x = (x | x << 8) & 16711935;
28673
+ x = (x | x << 4) & 252645135;
28674
+ x = (x | x << 2) & 858993459;
28675
+ x = (x | x << 1) & 1431655765;
28676
+ y = (y | y << 8) & 16711935;
28677
+ y = (y | y << 4) & 252645135;
28678
+ y = (y | y << 2) & 858993459;
28679
+ y = (y | y << 1) & 1431655765;
28680
+ return x | y << 1;
28681
+ }
28682
+ function getLeftmost(start) {
28683
+ let p = start, leftmost = start;
28684
+ do {
28685
+ if (p.x < leftmost.x || p.x === leftmost.x && p.y < leftmost.y) leftmost = p;
28686
+ p = p.next;
28687
+ } while (p !== start);
28688
+ return leftmost;
28689
+ }
28690
+ function pointInTriangle(ax, ay, bx, by, cx, cy, px, py) {
28691
+ return (cx - px) * (ay - py) >= (ax - px) * (cy - py) && (ax - px) * (by - py) >= (bx - px) * (ay - py) && (bx - px) * (cy - py) >= (cx - px) * (by - py);
28692
+ }
28693
+ function isValidDiagonal(a, b) {
28694
+ return a.next.i !== b.i && a.prev.i !== b.i && !intersectsPolygon(a, b) && // dones't intersect other edges
28695
+ (locallyInside(a, b) && locallyInside(b, a) && middleInside(a, b) && // locally visible
28696
+ (area(a.prev, a, b.prev) || area(a, b.prev, b)) || // does not create opposite-facing sectors
28697
+ equals(a, b) && area(a.prev, a, a.next) > 0 && area(b.prev, b, b.next) > 0);
28698
+ }
28699
+ function area(p, q, r) {
28700
+ return (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y);
28701
+ }
28702
+ function equals(p1, p2) {
28703
+ return p1.x === p2.x && p1.y === p2.y;
28704
+ }
28705
+ function intersects(p1, q1, p2, q2) {
28706
+ const o1 = sign(area(p1, q1, p2));
28707
+ const o2 = sign(area(p1, q1, q2));
28708
+ const o3 = sign(area(p2, q2, p1));
28709
+ const o4 = sign(area(p2, q2, q1));
28710
+ if (o1 !== o2 && o3 !== o4) return true;
28711
+ if (o1 === 0 && onSegment(p1, p2, q1)) return true;
28712
+ if (o2 === 0 && onSegment(p1, q2, q1)) return true;
28713
+ if (o3 === 0 && onSegment(p2, p1, q2)) return true;
28714
+ if (o4 === 0 && onSegment(p2, q1, q2)) return true;
28715
+ return false;
28716
+ }
28717
+ function onSegment(p, q, r) {
28718
+ return q.x <= Math.max(p.x, r.x) && q.x >= Math.min(p.x, r.x) && q.y <= Math.max(p.y, r.y) && q.y >= Math.min(p.y, r.y);
28719
+ }
28720
+ function sign(num2) {
28721
+ return num2 > 0 ? 1 : num2 < 0 ? -1 : 0;
28722
+ }
28723
+ function intersectsPolygon(a, b) {
28724
+ let p = a;
28725
+ do {
28726
+ if (p.i !== a.i && p.next.i !== a.i && p.i !== b.i && p.next.i !== b.i && intersects(p, p.next, a, b)) return true;
28727
+ p = p.next;
28728
+ } while (p !== a);
28729
+ return false;
28730
+ }
28731
+ function locallyInside(a, b) {
28732
+ return area(a.prev, a, a.next) < 0 ? area(a, b, a.next) >= 0 && area(a, a.prev, b) >= 0 : area(a, b, a.prev) < 0 || area(a, a.next, b) < 0;
28733
+ }
28734
+ function middleInside(a, b) {
28735
+ let p = a, inside = false;
28736
+ const px = (a.x + b.x) / 2, py = (a.y + b.y) / 2;
28737
+ do {
28738
+ if (p.y > py !== p.next.y > py && p.next.y !== p.y && px < (p.next.x - p.x) * (py - p.y) / (p.next.y - p.y) + p.x)
28739
+ inside = !inside;
28740
+ p = p.next;
28741
+ } while (p !== a);
28742
+ return inside;
28743
+ }
28744
+ function splitPolygon(a, b) {
28745
+ const a2 = new Node(a.i, a.x, a.y), b2 = new Node(b.i, b.x, b.y), an = a.next, bp = b.prev;
28746
+ a.next = b;
28747
+ b.prev = a;
28748
+ a2.next = an;
28749
+ an.prev = a2;
28750
+ b2.next = a2;
28751
+ a2.prev = b2;
28752
+ bp.next = b2;
28753
+ b2.prev = bp;
28754
+ return b2;
28755
+ }
28756
+ function insertNode(i, x, y, last) {
28757
+ const p = new Node(i, x, y);
28758
+ if (!last) {
28759
+ p.prev = p;
28760
+ p.next = p;
28761
+ } else {
28762
+ p.next = last.next;
28763
+ p.prev = last;
28764
+ last.next.prev = p;
28765
+ last.next = p;
28766
+ }
28767
+ return p;
28768
+ }
28769
+ function removeNode(p) {
28770
+ p.next.prev = p.prev;
28771
+ p.prev.next = p.next;
28772
+ if (p.prevZ) p.prevZ.nextZ = p.nextZ;
28773
+ if (p.nextZ) p.nextZ.prevZ = p.prevZ;
28774
+ }
28775
+ function Node(i, x, y) {
28776
+ this.i = i;
28777
+ this.x = x;
28778
+ this.y = y;
28779
+ this.prev = null;
28780
+ this.next = null;
28781
+ this.z = 0;
28782
+ this.prevZ = null;
28783
+ this.nextZ = null;
28784
+ this.steiner = false;
28785
+ }
28786
+ function signedArea(data, start, end, dim) {
28787
+ let sum = 0;
28788
+ for (let i = start, j = end - dim; i < end; i += dim) {
28789
+ sum += (data[j] - data[i]) * (data[i + 1] + data[j + 1]);
28790
+ j = i;
28791
+ }
28792
+ return sum;
28793
+ }
28794
+ var equals2 = (a, b) => a.x === b.x && a.y === b.y;
28795
+ var linePoint = (v1, v2, t) => t === 1 ? { x: v2.x, y: v2.y } : { x: (v2.x - v1.x) * t + v1.x, y: (v2.y - v1.y) * t + v1.y };
28796
+ function pathPoints(points) {
28797
+ const out = [];
28798
+ let last;
28799
+ for (let i = 1; i < points.length; i++) {
28800
+ const v1 = { x: points[i - 1][0], y: points[i - 1][1] };
28801
+ const v2 = { x: points[i][0], y: points[i][1] };
28802
+ for (let d = 0; d <= 1; d++) {
28803
+ const point = linePoint(v1, v2, d / 1);
28804
+ if (last && equals2(last, point)) continue;
28805
+ out.push(point);
28806
+ last = point;
28807
+ }
28808
+ }
28809
+ return out;
28810
+ }
28811
+ function area2(contour) {
28812
+ const n = contour.length;
28813
+ let a = 0;
28814
+ for (let p = n - 1, q = 0; q < n; p = q++) a += contour[p].x * contour[q].y - contour[q].x * contour[p].y;
28815
+ return a * 0.5;
28816
+ }
28817
+ var isClockWise = (pts) => area2(pts) < 0;
28818
+ function removeDupEndPts(points) {
28819
+ const l = points.length;
28820
+ if (l > 2 && equals2(points[l - 1], points[0])) points.pop();
28821
+ }
28822
+ function triangulateShape(contour, holes) {
28823
+ const vertices = [];
28824
+ const holeIndices = [];
28825
+ const faces = [];
28826
+ removeDupEndPts(contour);
28827
+ for (const p of contour) vertices.push(p.x, p.y);
28828
+ let holeIndex = contour.length;
28829
+ holes.forEach(removeDupEndPts);
28830
+ for (let i = 0; i < holes.length; i++) {
28831
+ holeIndices.push(holeIndex);
28832
+ holeIndex += holes[i].length;
28833
+ for (const p of holes[i]) vertices.push(p.x, p.y);
28834
+ }
28835
+ const triangles = Earcut.triangulate(vertices, holeIndices);
28836
+ for (let i = 0; i < triangles.length; i += 3) faces.push(triangles.slice(i, i + 3));
28837
+ return faces;
28838
+ }
28839
+ function computeVertexNormals(positions, indices) {
28840
+ const normals = new Float32Array(positions.length);
28841
+ const get = (array, i) => [array[i * 3], array[i * 3 + 1], array[i * 3 + 2]];
28842
+ const face = (vA, vB, vC) => {
28843
+ const pA = get(positions, vA);
28844
+ const pB = get(positions, vB);
28845
+ const pC = get(positions, vC);
28846
+ const cb = [pC[0] - pB[0], pC[1] - pB[1], pC[2] - pB[2]];
28847
+ const ab = [pA[0] - pB[0], pA[1] - pB[1], pA[2] - pB[2]];
28848
+ return [cb[1] * ab[2] - cb[2] * ab[1], cb[2] * ab[0] - cb[0] * ab[2], cb[0] * ab[1] - cb[1] * ab[0]];
28849
+ };
28850
+ const set = (i, x, y, z) => {
28851
+ normals[i * 3] = x;
28852
+ normals[i * 3 + 1] = y;
28853
+ normals[i * 3 + 2] = z;
28854
+ };
28855
+ if (indices) {
28856
+ for (let i = 0; i < indices.length; i += 3) {
28857
+ const vA = indices[i];
28858
+ const vB = indices[i + 1];
28859
+ const vC = indices[i + 2];
28860
+ const cb = face(vA, vB, vC);
28861
+ for (const v of [vA, vB, vC]) {
28862
+ const n = get(normals, v);
28863
+ set(v, n[0] + cb[0], n[1] + cb[1], n[2] + cb[2]);
28864
+ }
28865
+ }
28866
+ } else {
28867
+ for (let i = 0; i < positions.length / 3; i += 3) {
28868
+ const cb = face(i, i + 1, i + 2);
28869
+ set(i, cb[0], cb[1], cb[2]);
28870
+ set(i + 1, cb[0], cb[1], cb[2]);
28871
+ set(i + 2, cb[0], cb[1], cb[2]);
28872
+ }
28873
+ }
28874
+ for (let i = 0; i < normals.length / 3; i++) {
28875
+ const [x, y, z] = get(normals, i);
28876
+ const s = 1 / (Math.sqrt(x * x + y * y + z * z) || 1);
28877
+ set(i, x * s, y * s, z * s);
28878
+ }
28879
+ return normals;
28880
+ }
28881
+ function extrude(outline, depth = 1, steps = 1, bevel = void 0) {
28882
+ const parameters = { shape: outline, depth, steps, bevel: bevel ?? {} };
28883
+ const verticesArray = [];
28884
+ const uvArray = [];
28885
+ const groups = [];
28886
+ const placeholder = [];
28887
+ const bevelEnabled = bevel !== false;
28888
+ const spec = bevel === false || bevel === void 0 ? {} : bevel;
28889
+ let bevelThickness = spec.thickness !== void 0 ? spec.thickness : 0.2;
28890
+ let bevelSize = spec.size !== void 0 ? spec.size : bevelThickness - 0.1;
28891
+ let bevelOffset = spec.offset !== void 0 ? spec.offset : 0;
28892
+ let bevelSegments = spec.segments !== void 0 ? spec.segments : 3;
28893
+ if (!bevelEnabled) {
28894
+ bevelSegments = 0;
28895
+ bevelThickness = 0;
28896
+ bevelSize = 0;
28897
+ bevelOffset = 0;
28898
+ }
28899
+ let vertices = pathPoints(outline.outer);
28900
+ const holes = (outline.holes ?? []).map(pathPoints);
28901
+ const reverse = !isClockWise(vertices);
28902
+ if (reverse) {
28903
+ vertices = vertices.reverse();
28904
+ for (let h = 0; h < holes.length; h++) {
28905
+ const ahole = holes[h];
28906
+ if (isClockWise(ahole)) holes[h] = ahole.reverse();
28907
+ }
28908
+ }
28909
+ const faces = triangulateShape(vertices, holes);
28910
+ const contour = vertices;
28911
+ for (const ahole of holes) vertices = vertices.concat(ahole);
28912
+ const scalePt2 = (pt, vec, size) => ({ x: pt.x + vec.x * size, y: pt.y + vec.y * size });
28913
+ const vlen = vertices.length;
28914
+ const flen = faces.length;
28915
+ const getBevelVec = (inPt, inPrev, inNext) => {
28916
+ let vTransX;
28917
+ let vTransY;
28918
+ let shrinkBy;
28919
+ const vPrevX = inPt.x - inPrev.x;
28920
+ const vPrevY = inPt.y - inPrev.y;
28921
+ const vNextX = inNext.x - inPt.x;
28922
+ const vNextY = inNext.y - inPt.y;
28923
+ const vPrevLensq = vPrevX * vPrevX + vPrevY * vPrevY;
28924
+ const collinear0 = vPrevX * vNextY - vPrevY * vNextX;
28925
+ if (Math.abs(collinear0) > Number.EPSILON) {
28926
+ const vPrevLen = Math.sqrt(vPrevLensq);
28927
+ const vNextLen = Math.sqrt(vNextX * vNextX + vNextY * vNextY);
28928
+ const ptPrevShiftX = inPrev.x - vPrevY / vPrevLen;
28929
+ const ptPrevShiftY = inPrev.y + vPrevX / vPrevLen;
28930
+ const ptNextShiftX = inNext.x - vNextY / vNextLen;
28931
+ const ptNextShiftY = inNext.y + vNextX / vNextLen;
28932
+ const sf = ((ptNextShiftX - ptPrevShiftX) * vNextY - (ptNextShiftY - ptPrevShiftY) * vNextX) / (vPrevX * vNextY - vPrevY * vNextX);
28933
+ vTransX = ptPrevShiftX + vPrevX * sf - inPt.x;
28934
+ vTransY = ptPrevShiftY + vPrevY * sf - inPt.y;
28935
+ const vTransLensq = vTransX * vTransX + vTransY * vTransY;
28936
+ if (vTransLensq <= 2) return { x: vTransX, y: vTransY };
28937
+ shrinkBy = Math.sqrt(vTransLensq / 2);
28938
+ } else {
28939
+ let directionEq = false;
28940
+ if (vPrevX > Number.EPSILON) {
28941
+ if (vNextX > Number.EPSILON) directionEq = true;
28942
+ } else if (vPrevX < -Number.EPSILON) {
28943
+ if (vNextX < -Number.EPSILON) directionEq = true;
28944
+ } else if (Math.sign(vPrevY) === Math.sign(vNextY)) {
28945
+ directionEq = true;
28946
+ }
28947
+ if (directionEq) {
28948
+ vTransX = -vPrevY;
28949
+ vTransY = vPrevX;
28950
+ shrinkBy = Math.sqrt(vPrevLensq);
28951
+ } else {
28952
+ vTransX = vPrevX;
28953
+ vTransY = vPrevY;
28954
+ shrinkBy = Math.sqrt(vPrevLensq / 2);
28955
+ }
28956
+ }
28957
+ return { x: vTransX / shrinkBy, y: vTransY / shrinkBy };
28958
+ };
28959
+ const movements = (ring2) => {
28960
+ const out = [];
28961
+ for (let i = 0, il = ring2.length, j = il - 1, k = i + 1; i < il; i++, j++, k++) {
28962
+ if (j === il) j = 0;
28963
+ if (k === il) k = 0;
28964
+ out[i] = getBevelVec(ring2[i], ring2[j], ring2[k]);
28965
+ }
28966
+ return out;
28967
+ };
28968
+ const contourMovements = movements(contour);
28969
+ const holesMovements = [];
28970
+ let verticesMovements = contourMovements.concat();
28971
+ for (const ahole of holes) {
28972
+ const oneHoleMovements = movements(ahole);
28973
+ holesMovements.push(oneHoleMovements);
28974
+ verticesMovements = verticesMovements.concat(oneHoleMovements);
28975
+ }
28976
+ const v = (x, y, z) => {
28977
+ placeholder.push(x);
28978
+ placeholder.push(y);
28979
+ placeholder.push(z);
28980
+ };
28981
+ const bevelLayer = (b, zOf) => {
28982
+ const t = b / bevelSegments;
28983
+ const z = bevelThickness * Math.cos(t * Math.PI / 2);
28984
+ const bs2 = bevelSize * Math.sin(t * Math.PI / 2) + bevelOffset;
28985
+ for (let i = 0; i < contour.length; i++) {
28986
+ const vert = scalePt2(contour[i], contourMovements[i], bs2);
28987
+ v(vert.x, vert.y, zOf(z));
28988
+ }
28989
+ for (let h = 0; h < holes.length; h++) {
28990
+ const ahole = holes[h];
28991
+ const oneHoleMovements = holesMovements[h];
28992
+ for (let i = 0; i < ahole.length; i++) {
28993
+ const vert = scalePt2(ahole[i], oneHoleMovements[i], bs2);
28994
+ v(vert.x, vert.y, zOf(z));
28995
+ }
28996
+ }
28997
+ };
28998
+ for (let b = 0; b < bevelSegments; b++) bevelLayer(b, (z) => -z);
28999
+ const bs = bevelSize + bevelOffset;
29000
+ for (let i = 0; i < vlen; i++) {
29001
+ const vert = bevelEnabled ? scalePt2(vertices[i], verticesMovements[i], bs) : vertices[i];
29002
+ v(vert.x, vert.y, 0);
29003
+ }
29004
+ for (let s = 1; s <= steps; s++) {
29005
+ for (let i = 0; i < vlen; i++) {
29006
+ const vert = bevelEnabled ? scalePt2(vertices[i], verticesMovements[i], bs) : vertices[i];
29007
+ v(vert.x, vert.y, depth / steps * s);
29008
+ }
29009
+ }
29010
+ for (let b = bevelSegments - 1; b >= 0; b--) bevelLayer(b, (z) => depth + z);
29011
+ const addVertex = (index) => {
29012
+ verticesArray.push(placeholder[index * 3 + 0]);
29013
+ verticesArray.push(placeholder[index * 3 + 1]);
29014
+ verticesArray.push(placeholder[index * 3 + 2]);
29015
+ };
29016
+ const addUV = (x, y) => {
29017
+ uvArray.push(x);
29018
+ uvArray.push(y);
29019
+ };
29020
+ const at = (index, axis) => verticesArray[index * 3 + axis];
29021
+ const f3 = (a, b, c) => {
29022
+ addVertex(a);
29023
+ addVertex(b);
29024
+ addVertex(c);
29025
+ const nextIndex = verticesArray.length / 3;
29026
+ for (const index of [nextIndex - 3, nextIndex - 2, nextIndex - 1]) addUV(at(index, 0), at(index, 1));
29027
+ };
29028
+ const f4 = (a, b, c, d) => {
29029
+ addVertex(a);
29030
+ addVertex(b);
29031
+ addVertex(d);
29032
+ addVertex(b);
29033
+ addVertex(c);
29034
+ addVertex(d);
29035
+ const nextIndex = verticesArray.length / 3;
29036
+ const iA = nextIndex - 6;
29037
+ const iB = nextIndex - 3;
29038
+ const iC = nextIndex - 2;
29039
+ const iD = nextIndex - 1;
29040
+ const byX = Math.abs(at(iA, 1) - at(iB, 1)) < Math.abs(at(iA, 0) - at(iB, 0));
29041
+ const uv = (index) => [byX ? at(index, 0) : at(index, 1), 1 - at(index, 2)];
29042
+ const uvs = [uv(iA), uv(iB), uv(iC), uv(iD)];
29043
+ for (const k of [0, 1, 3, 1, 2, 3]) addUV(...uvs[k]);
29044
+ };
29045
+ let start = verticesArray.length / 3;
29046
+ if (bevelEnabled) {
29047
+ let offset = 0;
29048
+ for (let i = 0; i < flen; i++) {
29049
+ const face = faces[i];
29050
+ f3(face[2] + offset, face[1] + offset, face[0] + offset);
29051
+ }
29052
+ const layer = steps + bevelSegments * 2;
29053
+ offset = vlen * layer;
29054
+ for (let i = 0; i < flen; i++) {
29055
+ const face = faces[i];
29056
+ f3(face[0] + offset, face[1] + offset, face[2] + offset);
29057
+ }
29058
+ } else {
29059
+ for (let i = 0; i < flen; i++) {
29060
+ const face = faces[i];
29061
+ f3(face[2], face[1], face[0]);
29062
+ }
29063
+ for (let i = 0; i < flen; i++) {
29064
+ const face = faces[i];
29065
+ f3(face[0] + vlen * steps, face[1] + vlen * steps, face[2] + vlen * steps);
29066
+ }
29067
+ }
29068
+ groups.push({ start, count: verticesArray.length / 3 - start, materialIndex: 0 });
29069
+ start = verticesArray.length / 3;
29070
+ const sidewalls = (ring2, layeroffset2) => {
29071
+ let i = ring2.length;
29072
+ while (--i >= 0) {
29073
+ const j = i;
29074
+ let k = i - 1;
29075
+ if (k < 0) k = ring2.length - 1;
29076
+ for (let s = 0, sl = steps + bevelSegments * 2; s < sl; s++) {
29077
+ const slen1 = vlen * s;
29078
+ const slen2 = vlen * (s + 1);
29079
+ f4(layeroffset2 + j + slen1, layeroffset2 + k + slen1, layeroffset2 + k + slen2, layeroffset2 + j + slen2);
29080
+ }
29081
+ }
29082
+ };
29083
+ let layeroffset = 0;
29084
+ sidewalls(contour, layeroffset);
29085
+ layeroffset += contour.length;
29086
+ for (const ahole of holes) {
29087
+ sidewalls(ahole, layeroffset);
29088
+ layeroffset += ahole.length;
29089
+ }
29090
+ groups.push({ start, count: verticesArray.length / 3 - start, materialIndex: 1 });
29091
+ const positions = new Float32Array(verticesArray);
29092
+ return { type: "ExtrudeGeometry", parameters, positions, normals: computeVertexNormals(positions), uvs: new Float32Array(uvArray), groups };
29093
+ }
29094
+ var PARAMETER_KEYS = {
29095
+ box: ["size", "segments"],
29096
+ cylinder: ["radiusTop", "radiusBottom", "height", "radialSegments", "heightSegments", "openEnded", "thetaStart", "thetaLength"],
29097
+ cone: ["radius", "height", "radialSegments", "heightSegments", "openEnded", "thetaStart", "thetaLength"],
29098
+ sphere: ["radius", "widthSegments", "heightSegments", "phiStart", "phiLength", "thetaStart", "thetaLength"],
29099
+ plane: ["width", "height", "widthSegments", "heightSegments"],
29100
+ circle: ["radius", "segments", "thetaStart", "thetaLength"],
29101
+ ring: ["innerRadius", "outerRadius", "thetaSegments", "phiSegments", "thetaStart", "thetaLength"],
29102
+ lathe: ["points", "segments", "phiStart", "phiLength"],
29103
+ torus: ["radius", "tube", "radialSegments", "tubularSegments", "arc"],
29104
+ extrude: ["shape", "depth", "steps", "bevel"],
29105
+ difference: ["size", "subtract"],
29106
+ mesh: ["positions", "normals", "uvs", "indices"]
29107
+ };
29108
+ var SEGMENT_KEYS = {
29109
+ cylinder: ["radialSegments"],
29110
+ cone: ["radialSegments"],
29111
+ sphere: ["widthSegments", "heightSegments"],
29112
+ circle: ["segments"],
29113
+ ring: ["thetaSegments"],
29114
+ lathe: ["segments"],
29115
+ torus: ["radialSegments", "tubularSegments"]
29116
+ };
29117
+ var SEGMENT_DEFAULTS = { radialSegments: 32, widthSegments: 32, heightSegments: 16, segments: 12, thetaSegments: 32, tubularSegments: 48 };
29118
+ var segmentDefault = (kind, key) => kind === "circle" && key === "segments" ? 32 : kind === "torus" && key === "radialSegments" ? 12 : SEGMENT_DEFAULTS[key];
29119
+ function primitiveParameters(node, options = {}) {
29120
+ const out = {};
29121
+ const source = node;
29122
+ for (const key of PARAMETER_KEYS[node.kind]) if (source[key] !== void 0) out[key] = source[key];
29123
+ const detail = options.detail ?? 1;
29124
+ if (detail !== 1) {
29125
+ const floor = options.minSegments ?? 3;
29126
+ for (const key of SEGMENT_KEYS[node.kind] ?? []) {
29127
+ const given = out[key] ?? segmentDefault(node.kind, key);
29128
+ out[key] = Math.max(floor, Math.round(given * detail));
29129
+ }
29130
+ }
29131
+ return out;
29132
+ }
29133
+ function mesh(p) {
29134
+ const positions = new Float32Array(p.positions);
29135
+ const indices = p.indices ? indexArray(p.indices) : void 0;
29136
+ return {
29137
+ type: "BufferGeometry",
29138
+ parameters: {},
29139
+ positions,
29140
+ normals: p.normals ? new Float32Array(p.normals) : computeVertexNormals(positions, indices),
29141
+ uvs: p.uvs ? new Float32Array(p.uvs) : new Float32Array(positions.length / 3 * 2),
29142
+ ...indices ? { indices } : {},
29143
+ groups: []
29144
+ };
29145
+ }
29146
+ function make(kind, p) {
29147
+ switch (kind) {
29148
+ case "box": {
29149
+ const size = p.size ?? [1, 1, 1];
29150
+ const segments = p.segments ?? [1, 1, 1];
29151
+ return box(size[0], size[1], size[2], segments[0], segments[1], segments[2]);
29152
+ }
29153
+ case "cylinder":
29154
+ return cylinder(p.radiusTop, p.radiusBottom, p.height, p.radialSegments, p.heightSegments, p.openEnded, p.thetaStart, p.thetaLength);
29155
+ case "cone":
29156
+ return cone(p.radius, p.height, p.radialSegments, p.heightSegments, p.openEnded, p.thetaStart, p.thetaLength);
29157
+ case "sphere":
29158
+ return sphere(p.radius, p.widthSegments, p.heightSegments, p.phiStart, p.phiLength, p.thetaStart, p.thetaLength);
29159
+ case "plane":
29160
+ return plane(p.width, p.height, p.widthSegments, p.heightSegments);
29161
+ case "circle":
29162
+ return circle(p.radius, p.segments, p.thetaStart, p.thetaLength);
29163
+ case "ring":
29164
+ return ring(p.innerRadius, p.outerRadius, p.thetaSegments, p.phiSegments, p.thetaStart, p.thetaLength);
29165
+ case "lathe":
29166
+ return lathe(p.points, p.segments, p.phiStart, p.phiLength);
29167
+ case "torus":
29168
+ return torus(p.radius, p.tube, p.radialSegments, p.tubularSegments, p.arc);
29169
+ case "extrude":
29170
+ return extrude(p.shape, p.depth, p.steps, p.bevel);
29171
+ case "difference":
29172
+ return difference(p.size, p.subtract ?? []);
29173
+ case "mesh":
29174
+ return mesh(p);
29175
+ default:
29176
+ throw new Error(`game-shapes: unknown primitive kind "${String(kind)}"`);
29177
+ }
29178
+ }
29179
+ var templates = /* @__PURE__ */ new Map();
29180
+ var templateLimit = 4096;
29181
+ var stats = { hits: 0, misses: 0 };
29182
+ function buildPrimitive(node, options = {}) {
29183
+ const parameters = primitiveParameters(node, options);
29184
+ if (node.kind === "mesh" || templateLimit === 0) return make(node.kind, parameters);
29185
+ const key = `${node.kind}:${canonicalJson(parameters)}`;
29186
+ const cached = templates.get(key);
29187
+ if (cached) {
29188
+ stats.hits++;
29189
+ templates.delete(key);
29190
+ templates.set(key, cached);
29191
+ return cached;
29192
+ }
29193
+ stats.misses++;
29194
+ const built = make(node.kind, parameters);
29195
+ templates.set(key, built);
29196
+ if (templates.size > templateLimit) templates.delete(templates.keys().next().value);
29197
+ return built;
29198
+ }
29199
+ var num = (v) => typeof v === "number" && Number.isFinite(v) ? null : "expected a finite number";
29200
+ var bool = (v) => typeof v === "boolean" ? null : "expected a boolean";
29201
+ var str = (v) => typeof v === "string" ? null : "expected a string";
29202
+ var int = (min) => (v) => typeof v === "number" && Number.isInteger(v) && v >= min ? null : `expected an integer >= ${min}`;
29203
+ var range = (lo, hi, loOpen = false) => (v) => typeof v === "number" && (loOpen ? v > lo : v >= lo) && v <= hi ? null : `expected a number in ${loOpen ? "(" : "["}${lo}, ${hi}]`;
29204
+ var tuple = (n, item = num) => (v) => {
29205
+ if (!Array.isArray(v) || v.length !== n) return `expected an array of ${n}`;
29206
+ for (const x of v) if (item(x)) return `expected an array of ${n} numbers`;
29207
+ return null;
29208
+ };
29209
+ var list = (item, min = 0) => (v) => {
29210
+ if (!Array.isArray(v)) return "expected an array";
29211
+ if (v.length < min) return `expected at least ${min} items`;
29212
+ for (let i = 0; i < v.length; i++) {
29213
+ const e = item(v[i]);
29214
+ if (e) return `[${i}]: ${e}`;
29215
+ }
29216
+ return null;
29217
+ };
29218
+ var color = (v) => typeof v === "number" && Number.isInteger(v) && v >= 0 && v <= 16777215 || typeof v === "string" && /^#[0-9a-fA-F]{6}$/.test(v) ? null : 'expected 0xRRGGBB or "#rrggbb"';
29219
+ var oneOf = (values) => (v) => values.includes(v) ? null : `expected one of ${values.map((x) => JSON.stringify(x)).join(", ")}`;
29220
+ var object = (fields, required = []) => (v) => {
29221
+ if (!v || typeof v !== "object" || Array.isArray(v)) return "expected an object";
29222
+ const record = v;
29223
+ for (const key of required) if (record[key] === void 0) return `${key}: required`;
29224
+ for (const key of Object.keys(record)) {
29225
+ if (record[key] === void 0) continue;
29226
+ const check = fields[key];
29227
+ if (!check) return `${key}: unknown field`;
29228
+ const e = check(record[key]);
29229
+ if (e) return `${key}: ${e}`;
29230
+ }
29231
+ return null;
29232
+ };
29233
+ var ORDERS = ["XYZ", "YXZ", "ZXY", "ZYX", "YZX", "XZY"];
29234
+ var TRANSFORM = {
29235
+ position: tuple(3),
29236
+ rotation: tuple(3),
29237
+ rotationOrder: oneOf(ORDERS),
29238
+ scale: (v) => typeof v === "number" ? num(v) : tuple(3)(v),
29239
+ heading: num,
29240
+ matrix: tuple(16)
29241
+ };
29242
+ var UV = object({ u0: num, v0: num, u1: num, v1: num }, ["u0", "v0", "u1", "v1"]);
29243
+ var INSTANCE = object({ ...TRANSFORM, color });
29244
+ var COMMON = {
29245
+ ...TRANSFORM,
29246
+ kind: str,
29247
+ name: str,
29248
+ part: str,
29249
+ material: str,
29250
+ color,
29251
+ uv: UV,
29252
+ instances: list(INSTANCE),
29253
+ minDetail: range(0, 1, true),
29254
+ tags: list(str)
29255
+ };
29256
+ var vec2 = tuple(2);
29257
+ var BEVEL = (v) => v === false ? null : object({ thickness: num, size: num, offset: num, segments: int(1) })(v);
29258
+ var KINDS = {
29259
+ group: { fields: {} },
29260
+ box: { fields: { size: tuple(3), segments: tuple(3, int(1)) } },
29261
+ cylinder: { fields: { radiusTop: num, radiusBottom: num, height: num, radialSegments: int(1), heightSegments: int(1), openEnded: bool, thetaStart: num, thetaLength: num } },
29262
+ cone: { fields: { radius: num, height: num, radialSegments: int(1), heightSegments: int(1), openEnded: bool, thetaStart: num, thetaLength: num } },
29263
+ sphere: { fields: { radius: num, widthSegments: int(3), heightSegments: int(2), phiStart: num, phiLength: num, thetaStart: num, thetaLength: num } },
29264
+ plane: { fields: { width: num, height: num, widthSegments: int(1), heightSegments: int(1) } },
29265
+ circle: { fields: { radius: num, segments: int(3), thetaStart: num, thetaLength: num } },
29266
+ ring: { fields: { innerRadius: num, outerRadius: num, thetaSegments: int(3), phiSegments: int(1), thetaStart: num, thetaLength: num } },
29267
+ lathe: { fields: { points: list(vec2, 2), segments: int(1), phiStart: num, phiLength: num }, required: ["points"] },
29268
+ torus: { fields: { radius: num, tube: num, radialSegments: int(1), tubularSegments: int(1), arc: num } },
29269
+ extrude: {
29270
+ fields: { shape: object({ outer: list(vec2, 3), holes: list(list(vec2, 3)) }, ["outer"]), depth: num, steps: int(1), bevel: BEVEL },
29271
+ required: ["shape"]
29272
+ },
29273
+ difference: { fields: { size: tuple(3), subtract: list(object({ min: vec2, max: vec2 }, ["min", "max"])) }, required: ["size", "subtract"] },
29274
+ mesh: {
29275
+ fields: {
29276
+ positions: (v) => list(num)(v) ?? (v.length % 3 === 0 ? null : "expected a multiple of 3 numbers"),
29277
+ normals: list(num),
29278
+ uvs: list(num),
29279
+ indices: list(int(0))
29280
+ },
29281
+ required: ["positions"]
29282
+ },
29283
+ point: { fields: { data: () => null } },
29284
+ custom: { fields: { generator: str, params: () => null }, required: ["generator"] }
29285
+ };
29286
+
29287
+ // ../game-shapes-three/dist/index.js
29288
+ var UV_BEFORE_NORMAL = /* @__PURE__ */ new Set(["LatheGeometry", "ExtrudeGeometry"]);
29289
+ var INDEX_FIRST = /* @__PURE__ */ new Set(["BoxGeometry", "CylinderGeometry", "ConeGeometry", "SphereGeometry", "PlaneGeometry", "CircleGeometry", "RingGeometry", "LatheGeometry", "TorusGeometry"]);
29290
+ var isPrimitive = (value) => typeof value.type === "string";
29291
+ function threeParameters(THREE, p) {
29292
+ if (p.type === "LatheGeometry") {
29293
+ const points = p.parameters.points.map(({ x, y }) => new THREE.Vector2(x, y));
29294
+ return { ...p.parameters, points };
29295
+ }
29296
+ return { ...p.parameters };
29297
+ }
29298
+ function toGeometry(THREE, source, options = {}) {
29299
+ const copy = options.copy !== false;
29300
+ const primitive = isPrimitive(source) ? source : null;
29301
+ const ThreeClass = primitive && primitive.type !== "BufferGeometry" ? THREE[primitive.type] : void 0;
29302
+ const geometry = ThreeClass ? Reflect.construct(THREE.BufferGeometry, [], ThreeClass) : new THREE.BufferGeometry();
29303
+ if (primitive && ThreeClass) {
29304
+ Object.assign(geometry, { type: primitive.type, parameters: threeParameters(THREE, primitive) });
29305
+ }
29306
+ const attribute = (array, size) => copy ? new THREE.Float32BufferAttribute(array, size) : new THREE.BufferAttribute(array, size);
29307
+ const index = source.indices;
29308
+ const setIndex = () => {
29309
+ if (!index) return;
29310
+ geometry.setIndex(copy ? index instanceof Uint32Array ? new THREE.Uint32BufferAttribute(index, 1) : new THREE.Uint16BufferAttribute(index, 1) : new THREE.BufferAttribute(index, 1));
29311
+ };
29312
+ const type = primitive?.type ?? "BufferGeometry";
29313
+ if (INDEX_FIRST.has(type)) setIndex();
29314
+ geometry.setAttribute("position", attribute(source.positions, 3));
29315
+ if (UV_BEFORE_NORMAL.has(type)) {
29316
+ geometry.setAttribute("uv", attribute(source.uvs, 2));
29317
+ geometry.setAttribute("normal", attribute(source.normals, 3));
29318
+ } else {
29319
+ geometry.setAttribute("normal", attribute(source.normals, 3));
29320
+ geometry.setAttribute("uv", attribute(source.uvs, 2));
29321
+ }
29322
+ if (!primitive && source.colors) geometry.setAttribute("color", attribute(source.colors, 3));
29323
+ if (!INDEX_FIRST.has(type)) setIndex();
29324
+ if (primitive) for (const group of primitive.groups) geometry.addGroup(group.start, group.count, group.materialIndex);
29325
+ return geometry;
29326
+ }
29327
+ var SHAPE_GEOMETRY_TYPES = ["BoxGeometry", "CylinderGeometry", "ConeGeometry", "SphereGeometry", "PlaneGeometry", "CircleGeometry", "RingGeometry", "LatheGeometry", "TorusGeometry", "ExtrudeGeometry"];
29328
+ function linePoints(path) {
29329
+ if (path.autoClose || path.curves.length === 0) return null;
29330
+ const points = [];
29331
+ for (const [index, curve] of path.curves.entries()) {
29332
+ if (!curve.isLineCurve || !curve.v1 || !curve.v2) return null;
29333
+ if (index === 0) points.push([curve.v1.x, curve.v1.y]);
29334
+ else {
29335
+ const last = points[points.length - 1];
29336
+ if (last[0] !== curve.v1.x || last[1] !== curve.v1.y) return null;
29337
+ }
29338
+ points.push([curve.v2.x, curve.v2.y]);
29339
+ }
29340
+ return points;
29341
+ }
29342
+ function extrudeOf(shapes, options = {}) {
29343
+ if (Array.isArray(shapes) || !shapes || options.extrudePath !== void 0 || options.UVGenerator !== void 0) return null;
29344
+ const shape = shapes;
29345
+ const outer = linePoints(shape);
29346
+ if (!outer) return null;
29347
+ const holes = [];
29348
+ for (const hole of shape.holes ?? []) {
29349
+ const points = linePoints(hole);
29350
+ if (!points) return null;
29351
+ holes.push(points);
29352
+ }
29353
+ const outline = holes.length ? { outer, holes } : { outer };
29354
+ const bevel = options.bevelEnabled === false ? false : {
29355
+ ...options.bevelThickness !== void 0 ? { thickness: options.bevelThickness } : {},
29356
+ ...options.bevelSize !== void 0 ? { size: options.bevelSize } : {},
29357
+ ...options.bevelOffset !== void 0 ? { offset: options.bevelOffset } : {},
29358
+ ...options.bevelSegments !== void 0 ? { segments: options.bevelSegments } : {}
29359
+ };
29360
+ return extrude(outline, options.depth, options.steps, bevel);
29361
+ }
29362
+ var namespaces = /* @__PURE__ */ new WeakMap();
29363
+ var shims = /* @__PURE__ */ new WeakSet();
29364
+ function shapeGeometries(THREE, options = {}) {
29365
+ if (shims.has(THREE)) return THREE;
29366
+ const cache = options.cache !== false;
29367
+ const key = cache ? "cache" : "nocache";
29368
+ let byKey = namespaces.get(THREE);
29369
+ if (!byKey) {
29370
+ byKey = /* @__PURE__ */ new Map();
29371
+ namespaces.set(THREE, byKey);
29372
+ }
29373
+ const existing = byKey.get(key);
29374
+ if (existing) return existing;
29375
+ const made = (p) => toGeometry(THREE, p);
29376
+ const viaCache = (node, direct) => cache ? buildPrimitive(node) : direct();
29377
+ const defined = (o) => Object.fromEntries(Object.entries(o).filter(([, v]) => v !== void 0));
29378
+ const constructors = {
29379
+ BoxGeometry: (width, height, depth, ws = 1, hs = 1, ds = 1) => made(viaCache({ kind: "box", size: [width ?? 1, height ?? 1, depth ?? 1], segments: [ws, hs, ds] }, () => box(width, height, depth, ws, hs, ds))),
29380
+ CylinderGeometry: (radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength) => made(viaCache({ kind: "cylinder", ...defined({ radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength }) }, () => cylinder(radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength))),
29381
+ ConeGeometry: (radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength) => made(viaCache({ kind: "cone", ...defined({ radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength }) }, () => cone(radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength))),
29382
+ SphereGeometry: (radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength) => made(viaCache({ kind: "sphere", ...defined({ radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength }) }, () => sphere(radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength))),
29383
+ PlaneGeometry: (width, height, widthSegments, heightSegments) => made(viaCache({ kind: "plane", ...defined({ width, height, widthSegments, heightSegments }) }, () => plane(width, height, widthSegments, heightSegments))),
29384
+ CircleGeometry: (radius, segments, thetaStart, thetaLength) => made(viaCache({ kind: "circle", ...defined({ radius, segments, thetaStart, thetaLength }) }, () => circle(radius, segments, thetaStart, thetaLength))),
29385
+ RingGeometry: (innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength) => made(viaCache({ kind: "ring", ...defined({ innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength }) }, () => ring(innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength))),
29386
+ LatheGeometry: (points, segments, phiStart, phiLength) => {
29387
+ if (!points) return new THREE.LatheGeometry(void 0, segments, phiStart, phiLength);
29388
+ const profile = points.map((p) => [p.x, p.y]);
29389
+ return made(viaCache({ kind: "lathe", points: profile, ...defined({ segments, phiStart, phiLength }) }, () => lathe(profile, segments, phiStart, phiLength)));
29390
+ },
29391
+ TorusGeometry: (radius, tube, radialSegments, tubularSegments, arc) => made(viaCache({ kind: "torus", ...defined({ radius, tube, radialSegments, tubularSegments, arc }) }, () => torus(radius, tube, radialSegments, tubularSegments, arc))),
29392
+ ExtrudeGeometry: (shapes, extrudeOptions) => {
29393
+ const buffers = shapes === void 0 ? null : extrudeOf(shapes, extrudeOptions);
29394
+ if (!buffers) return new THREE.ExtrudeGeometry(shapes, extrudeOptions);
29395
+ const geometry = toGeometry(THREE, buffers);
29396
+ geometry.parameters = { shapes, options: extrudeOptions ?? {} };
29397
+ return geometry;
29398
+ }
29399
+ };
29400
+ const namespace = { ...THREE };
29401
+ for (const type of SHAPE_GEOMETRY_TYPES) {
29402
+ const make2 = constructors[type];
29403
+ const Constructor = function(...args) {
29404
+ return make2(...args);
29405
+ };
29406
+ Constructor.prototype = THREE[type].prototype;
29407
+ Object.defineProperty(Constructor, "name", { value: type });
29408
+ namespace[type] = Constructor;
29409
+ }
29410
+ const result = namespace;
29411
+ byKey.set(key, result);
29412
+ shims.add(result);
29413
+ return result;
29414
+ }
29415
+
29416
+ // ../game-contracts/dist/index.js
29417
+ var DEFAULT_IGNITION_RULES = {
29418
+ fillCurve: [
29419
+ [0, 0.6],
29420
+ [0.1, 1],
29421
+ [0.35, 0.6],
29422
+ [0.65, 0.3],
29423
+ [0.9, 0.15],
29424
+ [1, 0.12]
29425
+ ],
29426
+ flameFillInfluence: 0.5,
29427
+ flameDefaults: { incendiary: 0.7, tracer: 0.2 },
29428
+ sparkTarget: { steel: 1, iron: 1, aluminium: 0.25 },
29429
+ sparkMetalDefault: 0.5,
29430
+ sparkFluid: { diesel: 0.15 },
29431
+ fireNear: { radius: 1.5, chancePerSecond: 0.5 }
29432
+ };
29433
+ var resolveIgnitionRules = (rules) => ({
29434
+ ...DEFAULT_IGNITION_RULES,
29435
+ ...rules,
29436
+ flameDefaults: { ...DEFAULT_IGNITION_RULES.flameDefaults, ...rules?.flameDefaults },
29437
+ sparkTarget: { ...DEFAULT_IGNITION_RULES.sparkTarget, ...rules?.sparkTarget },
29438
+ sparkFluid: { ...DEFAULT_IGNITION_RULES.sparkFluid, ...rules?.sparkFluid },
29439
+ fireNear: { ...DEFAULT_IGNITION_RULES.fireNear, ...rules?.fireNear }
29440
+ });
29441
+ var fillFactor = (fill2, curve = DEFAULT_IGNITION_RULES.fillCurve) => {
29442
+ if (curve.length === 0) return 1;
29443
+ const f = Math.min(1, Math.max(0, fill2));
29444
+ if (f <= curve[0][0]) return curve[0][1];
29445
+ for (let i = 1; i < curve.length; i++) {
29446
+ const [x1, y1] = curve[i];
29447
+ const [x0, y0] = curve[i - 1];
29448
+ if (f <= x1) return x1 === x0 ? y1 : y0 + (y1 - y0) * (f - x0) / (x1 - x0);
29449
+ }
29450
+ return curve[curve.length - 1][1];
29451
+ };
29452
+ var sparkTargetFactor = (materialId, metal, rules = DEFAULT_IGNITION_RULES) => !metal ? 0 : rules.sparkTarget[materialId] ?? rules.sparkMetalDefault;
29453
+ var ignitionChance = (hit, target, rules = DEFAULT_IGNITION_RULES) => {
29454
+ const k = fillFactor(target.fill, rules.fillCurve);
29455
+ const spark = (hit.ignition?.spark ?? 0) * target.sparkTarget * (target.fluid === void 0 ? 1 : rules.sparkFluid[target.fluid] ?? 1) * k;
29456
+ const flameBase = hit.ignition?.flame ?? Math.max(hit.incendiary ? rules.flameDefaults.incendiary : 0, hit.tracer ? rules.flameDefaults.tracer : 0);
29457
+ const flame = flameBase * (1 - rules.flameFillInfluence * (1 - k));
29458
+ return 1 - (1 - Math.min(1, Math.max(0, spark))) * (1 - Math.min(1, Math.max(0, flame)));
29459
+ };
29460
+ var UNSAFE_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
29461
+ var isPlainObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value) && Object.getPrototypeOf(value) === Object.prototype;
29462
+ var deepMerge = (base, patch) => {
29463
+ if (!patch) return base;
29464
+ const result = { ...base };
29465
+ for (const [key, value] of Object.entries(patch)) {
29466
+ if (value === void 0 || UNSAFE_KEYS.has(key)) continue;
29467
+ const current = result[key];
29468
+ result[key] = isPlainObject(current) && isPlainObject(value) ? deepMerge(current, value) : value;
29469
+ }
29470
+ return result;
29471
+ };
29472
+ var mergeById = (shipped, extra) => {
29473
+ const entries = /* @__PURE__ */ new Map();
29474
+ for (const entry of [...shipped, ...extra ?? []]) entries.set(entry.id, entry);
29475
+ return entries;
29476
+ };
29477
+ var applyPatches = (entries, patches) => {
29478
+ for (const [id, patch] of Object.entries(patches ?? {})) {
29479
+ const entry = entries.get(id);
29480
+ if (entry) entries.set(id, deepMerge(entry, patch));
29481
+ }
29482
+ };
29483
+ var removeIds = (entries, ids) => {
29484
+ for (const id of ids ?? []) entries.delete(id);
29485
+ };
29486
+
27898
29487
  // ../game-vehicles/dist/index.js
27899
29488
  var __defProp2 = Object.defineProperty;
27900
29489
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
@@ -28580,9 +30169,9 @@ var GameVehiclesThree = (() => {
28580
30169
  return envTex;
28581
30170
  }
28582
30171
  kit.studioEnvironment = studioEnvironment;
28583
- function makeMaterial(color, o) {
30172
+ function makeMaterial(color2, o) {
28584
30173
  o = o || {};
28585
- const c = color instanceof THREE.Color ? color : new THREE.Color(color);
30174
+ const c = color2 instanceof THREE.Color ? color2 : new THREE.Color(color2);
28586
30175
  const key = "s" + c.getHexString() + JSON.stringify(o, function(k, v) {
28587
30176
  return v && v.isColor ? "#" + v.getHexString() : v && v.isTexture ? v.uuid : v;
28588
30177
  });
@@ -28598,8 +30187,8 @@ var GameVehiclesThree = (() => {
28598
30187
  }
28599
30188
  return cache[key];
28600
30189
  }
28601
- function makeFlatMaterial(color, o) {
28602
- return makeMaterial(color, Object.assign({ flatShading: true, roughness: 0.92 }, o || {}));
30190
+ function makeFlatMaterial(color2, o) {
30191
+ return makeMaterial(color2, Object.assign({ flatShading: true, roughness: 0.92 }, o || {}));
28603
30192
  }
28604
30193
  const DOUBLE_SIDE = THREE.DoubleSide;
28605
30194
  function toColor(hex) {
@@ -28816,46 +30405,79 @@ var GameVehiclesThree = (() => {
28816
30405
  }
28817
30406
  const p = geo.attributes.position;
28818
30407
  const n = p.count;
28819
- const FN = [];
28820
- const map = {};
28821
- const A = new V3();
28822
- const B = new V3();
28823
- const C = new V3();
28824
- const e1 = new V3();
28825
- const e2 = new V3();
30408
+ const faces = n / 3;
30409
+ const FN = new Float64Array(faces * 3);
30410
+ const map = /* @__PURE__ */ new Map();
30411
+ const RANGE = 65536;
28826
30412
  function key(i) {
28827
- return Math.round(p.getX(i) * 2e3) + "," + Math.round(p.getY(i) * 2e3) + "," + Math.round(p.getZ(i) * 2e3);
30413
+ const x = Math.round(p.getX(i) * 2e3);
30414
+ const y = Math.round(p.getY(i) * 2e3);
30415
+ const z = Math.round(p.getZ(i) * 2e3);
30416
+ if (Math.abs(x) < RANGE && Math.abs(y) < RANGE && Math.abs(z) < RANGE) return ((x + RANGE) * 131072 + (y + RANGE)) * 131072 + (z + RANGE);
30417
+ return x + "," + y + "," + z;
28828
30418
  }
28829
30419
  const keys = new Array(n);
28830
- for (let f = 0; f < n / 3; f++) {
28831
- A.fromBufferAttribute(p, 3 * f);
28832
- B.fromBufferAttribute(p, 3 * f + 1);
28833
- C.fromBufferAttribute(p, 3 * f + 2);
28834
- const nn = new V3().crossVectors(e1.subVectors(C, B), e2.subVectors(A, B));
28835
- if (nn.lengthSq() > 1e-20) nn.normalize();
28836
- FN.push(nn);
30420
+ for (let f = 0; f < faces; f++) {
30421
+ const ax = p.getX(3 * f);
30422
+ const ay = p.getY(3 * f);
30423
+ const az = p.getZ(3 * f);
30424
+ const bx = p.getX(3 * f + 1);
30425
+ const by = p.getY(3 * f + 1);
30426
+ const bz = p.getZ(3 * f + 1);
30427
+ const cx = p.getX(3 * f + 2);
30428
+ const cy = p.getY(3 * f + 2);
30429
+ const cz = p.getZ(3 * f + 2);
30430
+ const e1x = cx - bx;
30431
+ const e1y = cy - by;
30432
+ const e1z = cz - bz;
30433
+ const e2x = ax - bx;
30434
+ const e2y = ay - by;
30435
+ const e2z = az - bz;
30436
+ let nx = e1y * e2z - e1z * e2y;
30437
+ let ny = e1z * e2x - e1x * e2z;
30438
+ let nz = e1x * e2y - e1y * e2x;
30439
+ if (nx * nx + ny * ny + nz * nz > 1e-20) {
30440
+ const inv = 1 / (Math.sqrt(nx * nx + ny * ny + nz * nz) || 1);
30441
+ nx *= inv;
30442
+ ny *= inv;
30443
+ nz *= inv;
30444
+ }
30445
+ FN[3 * f] = nx;
30446
+ FN[3 * f + 1] = ny;
30447
+ FN[3 * f + 2] = nz;
28837
30448
  for (let k = 0; k < 3; k++) {
28838
30449
  const kk = key(3 * f + k);
28839
30450
  keys[3 * f + k] = kk;
28840
- (map[kk] || (map[kk] = [])).push(f);
30451
+ const list2 = map.get(kk);
30452
+ if (list2) list2.push(f);
30453
+ else map.set(kk, [f]);
28841
30454
  }
28842
30455
  }
28843
30456
  const cs = Math.cos(deg * PI / 180);
28844
30457
  const out = new Float32Array(n * 3);
28845
- const s = new V3();
28846
30458
  for (let i = 0; i < n; i++) {
28847
- const fi = i / 3 | 0;
28848
- const list = map[keys[i]];
28849
- s.set(0, 0, 0);
28850
- for (let j = 0; j < list.length; j++) {
28851
- const g = FN[list[j]];
28852
- if (g.dot(FN[fi]) >= cs) s.add(g);
28853
- }
28854
- if (s.lengthSq() < 1e-20) s.copy(FN[fi]);
28855
- s.normalize();
28856
- out[3 * i] = s.x;
28857
- out[3 * i + 1] = s.y;
28858
- out[3 * i + 2] = s.z;
30459
+ const fi = (i / 3 | 0) * 3;
30460
+ const list2 = map.get(keys[i]);
30461
+ let sx = 0;
30462
+ let sy = 0;
30463
+ let sz = 0;
30464
+ for (let j = 0; j < list2.length; j++) {
30465
+ const g = list2[j] * 3;
30466
+ if (FN[g] * FN[fi] + FN[g + 1] * FN[fi + 1] + FN[g + 2] * FN[fi + 2] >= cs) {
30467
+ sx += FN[g];
30468
+ sy += FN[g + 1];
30469
+ sz += FN[g + 2];
30470
+ }
30471
+ }
30472
+ if (sx * sx + sy * sy + sz * sz < 1e-20) {
30473
+ sx = FN[fi];
30474
+ sy = FN[fi + 1];
30475
+ sz = FN[fi + 2];
30476
+ }
30477
+ const inv = 1 / (Math.sqrt(sx * sx + sy * sy + sz * sz) || 1);
30478
+ out[3 * i] = sx * inv;
30479
+ out[3 * i + 1] = sy * inv;
30480
+ out[3 * i + 2] = sz * inv;
28859
30481
  }
28860
30482
  geo.setAttribute("normal", new THREE.BufferAttribute(out, 3));
28861
30483
  geo.userData.crease = true;
@@ -28914,7 +30536,7 @@ var GameVehiclesThree = (() => {
28914
30536
  const pos = [];
28915
30537
  const col = [];
28916
30538
  const idx = [];
28917
- const ring = seg + 1;
30539
+ const ring2 = seg + 1;
28918
30540
  st.forEach(function(s) {
28919
30541
  for (let j = 0; j <= seg; j++) {
28920
30542
  const a = j / seg * PI * 2;
@@ -28932,8 +30554,8 @@ var GameVehiclesThree = (() => {
28932
30554
  });
28933
30555
  for (let i = 0; i < st.length - 1; i++)
28934
30556
  for (let k = 0; k < seg; k++) {
28935
- const a0 = i * ring + k;
28936
- const b0 = a0 + ring;
30557
+ const a0 = i * ring2 + k;
30558
+ const b0 = a0 + ring2;
28937
30559
  idx.push(a0, a0 + 1, b0, a0 + 1, b0 + 1, b0);
28938
30560
  }
28939
30561
  ;
@@ -28947,7 +30569,7 @@ var GameVehiclesThree = (() => {
28947
30569
  col.push(cc.r, cc.g, cc.b);
28948
30570
  }
28949
30571
  for (let k = 0; k < seg; k++) {
28950
- const a = si * ring + k;
30572
+ const a = si * ring2 + k;
28951
30573
  if (e === 0) idx.push(ci, a + 1, a);
28952
30574
  else idx.push(ci, a, a + 1);
28953
30575
  }
@@ -29085,13 +30707,13 @@ var GameVehiclesThree = (() => {
29085
30707
  });
29086
30708
  tris = next;
29087
30709
  });
29088
- function build(list) {
30710
+ function build(list2) {
29089
30711
  const g = new THREE.BufferGeometry();
29090
30712
  let off = 0;
29091
30713
  names.forEach(function(nm, a) {
29092
- const arr = new Float32Array(list.length * 3 * sizes[a]);
30714
+ const arr = new Float32Array(list2.length * 3 * sizes[a]);
29093
30715
  let w = 0;
29094
- list.forEach(function(t) {
30716
+ list2.forEach(function(t) {
29095
30717
  for (let k = 0; k < 3; k++) for (let q = 0; q < sizes[a]; q++) arr[w++] = t[k][off + q];
29096
30718
  });
29097
30719
  g.setAttribute(nm, new THREE.BufferAttribute(arr, sizes[a]));
@@ -29106,10 +30728,10 @@ var GameVehiclesThree = (() => {
29106
30728
  });
29107
30729
  return out;
29108
30730
  }
29109
- function mergeGeometries(list) {
30731
+ function mergeGeometries(list2) {
29110
30732
  const pos = [];
29111
30733
  const nor = [];
29112
- list.forEach(function(g2) {
30734
+ list2.forEach(function(g2) {
29113
30735
  const n = g2.index ? g2.toNonIndexed() : g2;
29114
30736
  if (!n.attributes.normal) n.computeVertexNormals();
29115
30737
  const pa = n.attributes.position.array;
@@ -29168,13 +30790,13 @@ var GameVehiclesThree = (() => {
29168
30790
  };
29169
30791
  kit.holeSide = function(poly, o) {
29170
30792
  o = o || {};
29171
- let area = 0;
30793
+ let area3 = 0;
29172
30794
  for (let i = 0; i < poly.length; i++) {
29173
30795
  const a = poly[i];
29174
30796
  const b = poly[(i + 1) % poly.length];
29175
- area += a[0] * b[1] - b[0] * a[1];
30797
+ area3 += a[0] * b[1] - b[0] * a[1];
29176
30798
  }
29177
- const sg = area > 0 ? 1 : -1;
30799
+ const sg = area3 > 0 ? 1 : -1;
29178
30800
  const E2 = poly.map(function(a, i) {
29179
30801
  const b = poly[(i + 1) % poly.length];
29180
30802
  const dx = b[0] - a[0];
@@ -29475,11 +31097,11 @@ var GameVehiclesThree = (() => {
29475
31097
  return d.clone().applyQuaternion(this.vehicle.quaternion);
29476
31098
  }
29477
31099
  /** Declares or refines a damage zone: `c.zone(id, label, box, parts, options)`. Pass `label === false` to remove an auto-derived zone. */
29478
- zone(id, label, box, parts, o) {
31100
+ zone(id, label, box2, parts, o) {
29479
31101
  const d = Object.assign({ id }, o || {});
29480
31102
  if (label === false) d.remove = true;
29481
31103
  else if (label) d.name = label;
29482
- if (box) d.box = I.normalizeBox(box);
31104
+ if (box2) d.box = I.normalizeBox(box2);
29483
31105
  if (parts) d.objs = Array.isArray(parts) ? parts.slice() : [parts];
29484
31106
  this.zoneDefs.push(d);
29485
31107
  return d;
@@ -29628,7 +31250,7 @@ var GameVehiclesThree = (() => {
29628
31250
  const seg = o.seg || 24;
29629
31251
  const pos = [];
29630
31252
  const idx = [];
29631
- const ring = seg + 1;
31253
+ const ring2 = seg + 1;
29632
31254
  const axisY = o.axis === "y";
29633
31255
  st.forEach(function(s) {
29634
31256
  const a0 = s[1];
@@ -29650,8 +31272,8 @@ var GameVehiclesThree = (() => {
29650
31272
  });
29651
31273
  for (let i = 0; i < st.length - 1; i++)
29652
31274
  for (let k = 0; k < seg; k++) {
29653
- const A = i * ring + k;
29654
- const B = A + ring;
31275
+ const A = i * ring2 + k;
31276
+ const B = A + ring2;
29655
31277
  if (axisY) idx.push(A, B, A + 1, A + 1, B, B + 1);
29656
31278
  else idx.push(A, A + 1, B, A + 1, B + 1, B);
29657
31279
  }
@@ -29664,7 +31286,7 @@ var GameVehiclesThree = (() => {
29664
31286
  if (axisY) pos.push(cc, s[0], s[5] || 0);
29665
31287
  else pos.push(s[0], cc, s[5] || 0);
29666
31288
  for (let k = 0; k < seg; k++) {
29667
- const a = si * ring + k;
31289
+ const a = si * ring2 + k;
29668
31290
  const flip = e === 0 !== axisY;
29669
31291
  if (flip) idx.push(ci, a + 1, a);
29670
31292
  else idx.push(ci, a, a + 1);
@@ -29892,15 +31514,15 @@ var GameVehiclesThree = (() => {
29892
31514
  c.part("glass", L, m, pos, o.reach || 0.9);
29893
31515
  return m;
29894
31516
  };
29895
- kit.asGlass = function(c, mesh, label, type, o) {
31517
+ kit.asGlass = function(c, mesh2, label, type, o) {
29896
31518
  o = o || {};
29897
- const i = c.deform.indexOf(mesh);
31519
+ const i = c.deform.indexOf(mesh2);
29898
31520
  if (i >= 0) c.deform.splice(i, 1);
29899
- if (mesh.parent) mesh.parent.remove(mesh);
29900
- const geo = mesh.geometry;
29901
- geo.applyMatrix4(new THREE.Matrix4().compose(mesh.position, mesh.quaternion, mesh.scale));
31521
+ if (mesh2.parent) mesh2.parent.remove(mesh2);
31522
+ const geo = mesh2.geometry;
31523
+ geo.applyMatrix4(new THREE.Matrix4().compose(mesh2.position, mesh2.quaternion, mesh2.scale));
29902
31524
  if (o.reuv !== false) o.reuv = true;
29903
- return kit.addGlass(c, geo, label, type, Object.assign({ mat: mesh.material }, o));
31525
+ return kit.addGlass(c, geo, label, type, Object.assign({ mat: mesh2.material }, o));
29904
31526
  };
29905
31527
  kit.sideWindows = function(c, polys, Wg, T, label, o) {
29906
31528
  o = o || {};
@@ -29946,12 +31568,12 @@ var GameVehiclesThree = (() => {
29946
31568
  });
29947
31569
  });
29948
31570
  };
29949
- kit.cutMesh = function(mesh, tests, deg, o) {
29950
- const src = o && o.sub ? subdivide(mesh.geometry, o.sub) : mesh.geometry;
31571
+ kit.cutMesh = function(mesh2, tests, deg, o) {
31572
+ const src = o && o.sub ? subdivide(mesh2.geometry, o.sub) : mesh2.geometry;
29951
31573
  const r = cutGeometry(src, tests);
29952
31574
  crease(r.geo, deg || 42);
29953
- mesh.geometry.dispose();
29954
- mesh.geometry = r.geo;
31575
+ mesh2.geometry.dispose();
31576
+ mesh2.geometry = r.geo;
29955
31577
  return r.cut;
29956
31578
  };
29957
31579
  kit.quadDef = function(pb, pt, Wg, T, which, bev, o) {
@@ -30149,8 +31771,8 @@ var GameVehiclesThree = (() => {
30149
31771
  const pz = nR === 1 ? 0 : (i ? 1 : -1) * w / 4;
30150
31772
  const back = gm(g, new THREE.CylinderGeometry(r * 1.06, r * 1.06, d * 0.8, 22), MATERIALS.housing, 0, 0, pz);
30151
31773
  back.rotation.z = PI / 2;
30152
- const ring = gm(g, new THREE.TorusGeometry(r * 1.02, 0.013, 8, 30), MATERIALS.chrome, d / 2 - 6e-3, 0, pz);
30153
- ring.rotation.y = PI / 2;
31774
+ const ring2 = gm(g, new THREE.TorusGeometry(r * 1.02, 0.013, 8, 30), MATERIALS.chrome, d / 2 - 6e-3, 0, pz);
31775
+ ring2.rotation.y = PI / 2;
30154
31776
  const bowl = gm(g, new THREE.SphereGeometry(r * 0.96, 18, 10, 0, PI * 2, 0, PI / 2), MATERIALS.reflectorLit, d / 2 - 0.012, 0, pz);
30155
31777
  bowl.rotation.z = PI / 2;
30156
31778
  bowl.scale.y = 0.55;
@@ -30227,8 +31849,8 @@ var GameVehiclesThree = (() => {
30227
31849
  const e = gm(g, new THREE.CylinderGeometry(r * 0.9, r * 0.9, 0.012, 20), q * ls > 0 ? MATERIALS.tail : MATERIALS.tail, d / 2 - 0.02, 0, pz);
30228
31850
  e.rotation.z = PI / 2;
30229
31851
  inner.push(e);
30230
- const ring = gm(g, new THREE.TorusGeometry(r, 0.01, 6, 24), MATERIALS.chrome, d / 2 - 4e-3, 0, pz);
30231
- ring.rotation.y = PI / 2;
31852
+ const ring2 = gm(g, new THREE.TorusGeometry(r, 0.01, 6, 24), MATERIALS.chrome, d / 2 - 4e-3, 0, pz);
31853
+ ring2.rotation.y = PI / 2;
30232
31854
  const ln = gm(g, new THREE.SphereGeometry(r, 16, 8, 0, PI * 2, 0, PI / 2), MATERIALS.lensRed, d / 2 - 0.01, 0, pz);
30233
31855
  ln.rotation.z = -PI / 2;
30234
31856
  ln.scale.y = 0.25;
@@ -30321,7 +31943,7 @@ var GameVehiclesThree = (() => {
30321
31943
  } else if (st === "mesh") {
30322
31944
  gm(g, roundedBoxGeometry(0.05, h, w, Math.min(0.03, h * 0.3)), MATERIALS.housing);
30323
31945
  const cell = 0.026;
30324
- const list = [];
31946
+ const list2 = [];
30325
31947
  const rows = Math.floor(h * 0.85 / (cell * 1.6));
30326
31948
  const cols = Math.floor(w * 0.9 / (cell * 1.8));
30327
31949
  for (let rI = 0; rI < rows; rI++)
@@ -30330,9 +31952,9 @@ var GameVehiclesThree = (() => {
30330
31952
  hg.rotateZ(PI / 2);
30331
31953
  hg.rotateX(PI / 6);
30332
31954
  hg.translate(0.026, -h * 0.42 + (rI + 0.5) * h * 0.85 / rows, -w * 0.45 + (cI + 0.5 + rI % 2 * 0.5 - 0.25) * w * 0.9 / cols);
30333
- list.push(hg);
31955
+ list2.push(hg);
30334
31956
  }
30335
- if (list.length) gm(g, mergeGeometries(list), MATERIALS.trim);
31957
+ if (list2.length) gm(g, mergeGeometries(list2), MATERIALS.trim);
30336
31958
  gm(g, roundedBoxGeometry(0.022, 0.014, w, 6e-3), MATERIALS.chrome, 0.03, h / 2 - 8e-3, 0);
30337
31959
  } else if (st === "big") {
30338
31960
  const fr = roundedBoxGeometry(0.06, h, w, 0.03);
@@ -31167,7 +32789,7 @@ var GameVehiclesThree = (() => {
31167
32789
  m.underbodyGroup = ug;
31168
32790
  const DK = makeMaterial("#1a1b1c", { roughness: 0.75, metalness: 0.3 });
31169
32791
  const ST = MATERIALS.steel;
31170
- function box(w, h, d, mat, x, y, z) {
32792
+ function box2(w, h, d, mat, x, y, z) {
31171
32793
  return c.roundBox(w, h, d, Math.min(0.02, h * 0.4), mat, x, y, z, { parent: ug });
31172
32794
  }
31173
32795
  function rod(a, b, r, mat) {
@@ -31184,9 +32806,9 @@ var GameVehiclesThree = (() => {
31184
32806
  rod(new V3(rx, rr, -zW), new V3(rx, rr, zW), 0.045, ST);
31185
32807
  c.sphere(0.13, ST, rx, rr, 0, 1, 0.85, 1, { parent: ug });
31186
32808
  rod(new V3(rx + 0.1, rr, 0), new V3(fx - 0.6, yU + 0.04, 0), 0.035, ST);
31187
- } else box(0.09, 0.08, zW * 2, DK, rx + 0.08, Math.max(yU, rr - 0.12), 0);
32809
+ } else box2(0.09, 0.08, zW * 2, DK, rx + 0.08, Math.max(yU, rr - 0.12), 0);
31188
32810
  if (!ev) {
31189
- box(Math.min(0.5, (fx - rx) * 0.2), 0.1, 0.38, DK, fx - 0.25, yU + 0.01, -0.05);
32811
+ box2(Math.min(0.5, (fx - rx) * 0.2), 0.1, 0.38, DK, fx - 0.25, yU + 0.01, -0.05);
31190
32812
  const tz = W * 0.3;
31191
32813
  const mx = rx - 0.15;
31192
32814
  const ty = Math.max(0.14, by - 0.06);
@@ -31203,10 +32825,10 @@ var GameVehiclesThree = (() => {
31203
32825
  { parent: ug, seg: 30, rs: 6 }
31204
32826
  );
31205
32827
  c.cylinder(0.1, 0.1, 0.42, ST, mx, ty + 0.02, tz, "x", { parent: ug });
31206
- box(0.24, 0.06, 0.2, DK, (fx + rx) / 2 + 0.1, ty, 0.16);
31207
- box(0.55, 0.18, W * 0.5, makeMaterial("#232527", { roughness: 0.7 }), rx + 0.62, Math.max(0.16, by - 0.02), -W * 0.1);
32828
+ box2(0.24, 0.06, 0.2, DK, (fx + rx) / 2 + 0.1, ty, 0.16);
32829
+ box2(0.55, 0.18, W * 0.5, makeMaterial("#232527", { roughness: 0.7 }), rx + 0.62, Math.max(0.16, by - 0.02), -W * 0.1);
31208
32830
  } else {
31209
- box(
32831
+ box2(
31210
32832
  (fx - rx) * 0.72,
31211
32833
  0.1,
31212
32834
  W - 0.4,
@@ -31215,7 +32837,7 @@ var GameVehiclesThree = (() => {
31215
32837
  Math.max(0.14, by - 0.03),
31216
32838
  0
31217
32839
  );
31218
- for (let k = 0; k < 6; k++) box(0.03, 0.02, W - 0.45, ST, rx + 0.4 + k * (fx - rx - 0.8) / 5, Math.max(0.14, by - 0.03) - 0.06, 0);
32840
+ for (let k = 0; k < 6; k++) box2(0.03, 0.02, W - 0.45, ST, rx + 0.4 + k * (fx - rx - 0.8) / 5, Math.max(0.14, by - 0.03) - 0.06, 0);
31219
32841
  }
31220
32842
  if (o.spare && m.rear < rx - 0.7) {
31221
32843
  c.cylinder(0.32, 0.32, 0.2, MATERIALS.rubber, rx - 0.55, Math.max(0.2, by - 0.05), 0, null, { parent: ug });
@@ -31539,16 +33161,16 @@ var GameVehiclesThree = (() => {
31539
33161
  }
31540
33162
  } else {
31541
33163
  const ns = o.spokes || 28;
31542
- const list = [];
33164
+ const list2 = [];
31543
33165
  for (let jj = 0; jj < ns; jj++) {
31544
33166
  const a2 = jj / ns * PI * 2;
31545
33167
  const cg = new THREE.CylinderGeometry(25e-4, 25e-4, sl, 4);
31546
33168
  cg.applyMatrix4(
31547
33169
  new THREE.Matrix4().makeRotationZ(a2 - PI / 2).setPosition(Math.cos(a2) * sl / 2, Math.sin(a2) * sl / 2, (jj % 2 ? 1 : -1) * 0.012)
31548
33170
  );
31549
- list.push(cg);
33171
+ list2.push(cg);
31550
33172
  }
31551
- g.add(new THREE.Mesh(mergeGeometries(list), MATERIALS.chrome));
33173
+ g.add(new THREE.Mesh(mergeGeometries(list2), MATERIALS.chrome));
31552
33174
  }
31553
33175
  const hub = new THREE.Mesh(new THREE.CylinderGeometry(0.035, 0.035, 0.1, 12), MATERIALS.steel);
31554
33176
  hub.rotation.x = PI / 2;
@@ -31728,9 +33350,9 @@ var GameVehiclesThree = (() => {
31728
33350
  return puffTexture(k * 17, true);
31729
33351
  });
31730
33352
  }
31731
- const list = fire ? FIRE_TEXTURES : SMOKE_TEXTURES;
33353
+ const list2 = fire ? FIRE_TEXTURES : SMOKE_TEXTURES;
31732
33354
  const mat = new THREE.SpriteMaterial({
31733
- map: list[Math.floor(Math.random() * list.length)],
33355
+ map: list2[Math.floor(Math.random() * list2.length)],
31734
33356
  color: new THREE.Color(col),
31735
33357
  transparent: true,
31736
33358
  depthWrite: false,
@@ -33033,7 +34655,7 @@ var GameVehiclesThree = (() => {
33033
34655
  }
33034
34656
  });
33035
34657
  const dset = new Set(c.deform);
33036
- const box = new THREE.Box3();
34658
+ const box2 = new THREE.Box3();
33037
34659
  c.vehicle.children.forEach(function(o) {
33038
34660
  if (dset.has(o) || o.userData.noFollow) return;
33039
34661
  if (!(o.isMesh || o.isGroup && o.userData.rigid)) return;
@@ -33044,10 +34666,10 @@ var GameVehiclesThree = (() => {
33044
34666
  if (!o.geometry.boundingBox) o.geometry.computeBoundingBox();
33045
34667
  o.userData.bb0 = o.geometry.boundingBox.clone().applyMatrix4(o.matrix);
33046
34668
  } else {
33047
- box.setFromObject(o);
33048
- box.applyMatrix4(gInv);
33049
- o.userData.c0 = box.getCenter(new V3());
33050
- o.userData.bb0 = box.clone();
34669
+ box2.setFromObject(o);
34670
+ box2.applyMatrix4(gInv);
34671
+ o.userData.c0 = box2.getCenter(new V3());
34672
+ o.userData.bb0 = box2.clone();
33051
34673
  }
33052
34674
  o.userData.pos0 = o.position.clone();
33053
34675
  }
@@ -33341,11 +34963,11 @@ var GameVehiclesThree = (() => {
33341
34963
  [12, "#d8322a", kit.t("blast.lethal", { m: 12 })],
33342
34964
  [30, "#e0a548", kit.t("blast.injury", { m: 30 })]
33343
34965
  ].forEach(function(r) {
33344
- const ring = new THREE.Mesh(new THREE.RingGeometry(r[0] - 0.25, r[0], 96), boomMat(r[1], 0.85));
33345
- ring.rotation.x = -PI / 2;
33346
- ring.position.y = 0.06;
33347
- ring.renderOrder = 5;
33348
- g.add(ring);
34966
+ const ring2 = new THREE.Mesh(new THREE.RingGeometry(r[0] - 0.25, r[0], 96), boomMat(r[1], 0.85));
34967
+ ring2.rotation.x = -PI / 2;
34968
+ ring2.position.y = 0.06;
34969
+ ring2.renderOrder = 5;
34970
+ g.add(ring2);
33349
34971
  const fill2 = new THREE.Mesh(new THREE.CircleGeometry(r[0], 96), boomMat(r[1], 0.07));
33350
34972
  fill2.rotation.x = -PI / 2;
33351
34973
  fill2.position.y = 0.05;
@@ -33362,7 +34984,7 @@ var GameVehiclesThree = (() => {
33362
34984
  lb.rotation.x = -PI / 2;
33363
34985
  lb.position.set(0, 0.08, r[0] + r[0] * 0.06);
33364
34986
  g.add(lb);
33365
- c.bigFx.rings.push(ring, fill2, lb);
34987
+ c.bigFx.rings.push(ring2, fill2, lb);
33366
34988
  });
33367
34989
  }
33368
34990
  function detonate(c) {
@@ -33635,7 +35257,7 @@ var GameVehiclesThree = (() => {
33635
35257
  const I = kit._;
33636
35258
  const { MATERIALS } = I;
33637
35259
  function rollMeshes(c) {
33638
- const list = [];
35260
+ const list2 = [];
33639
35261
  const thin = [];
33640
35262
  c.root.updateMatrixWorld(true);
33641
35263
  const inv = new THREE.Matrix4().copy(c.vehicle.matrixWorld).invert();
@@ -33653,9 +35275,9 @@ var GameVehiclesThree = (() => {
33653
35275
  thin.push({ o: ob, M });
33654
35276
  return;
33655
35277
  }
33656
- list.push({ o: ob, M });
35278
+ list2.push({ o: ob, M });
33657
35279
  });
33658
- return { list, thin };
35280
+ return { list: list2, thin };
33659
35281
  }
33660
35282
  function convexHull(pts) {
33661
35283
  pts.sort(function(a, b) {
@@ -33738,7 +35360,7 @@ var GameVehiclesThree = (() => {
33738
35360
  };
33739
35361
  function rollContact(c, A, q) {
33740
35362
  const m = c.meta;
33741
- const list = [];
35363
+ const list2 = [];
33742
35364
  const dy = A.cen[0] - q[0];
33743
35365
  const dz = A.cen[1] - q[1];
33744
35366
  const dl = Math.hypot(dy, dz) || 1;
@@ -33746,17 +35368,17 @@ var GameVehiclesThree = (() => {
33746
35368
  const f = 0.75;
33747
35369
  const bike = m.kind === "bike";
33748
35370
  (bike ? [0] : [-0.28, 0, 0.28]).forEach(function(k) {
33749
- list.push([new V3(A.x + k * A.L, q[0], q[1]), dir]);
35371
+ list2.push([new V3(A.x + k * A.L, q[0], q[1]), dir]);
33750
35372
  });
33751
35373
  if (!bike && Math.abs(dir.z) > 0.75 && m.top - m.belt > 0.25 && A.hits < 3) {
33752
35374
  const sd = -Math.sign(dir.z);
33753
35375
  const yw = m.belt + (m.top - m.belt) * 0.45;
33754
35376
  [-0.25, 0.2].forEach(function(k) {
33755
35377
  const h = I.probe(c, new V3(A.x + k * A.L, yw, sd * (m.width / 2 + 2)), new V3(0, 0, -sd), 2 + m.width);
33756
- if (h) list.push([h.p, new V3(0, 0, -sd)]);
35378
+ if (h) list2.push([h.p, new V3(0, 0, -sd)]);
33757
35379
  });
33758
35380
  }
33759
- list.forEach(function(e) {
35381
+ list2.forEach(function(e) {
33760
35382
  I.impact(c, e[0], e[1], f, { noStain: true, maxDepth: 0.1 });
33761
35383
  const pf = c.toEffects(e[0]);
33762
35384
  pf.y = Math.max(0.03, pf.y);
@@ -33766,15 +35388,15 @@ var GameVehiclesThree = (() => {
33766
35388
  });
33767
35389
  A.hits++;
33768
35390
  A.bounce = A.hits === 1 ? 0.06 : 0.1;
33769
- if (m.kind === "boat") I.burst(c, "water", c.toEffects(list[0][0]).setY(0.05), 30, { speed: 3 });
35391
+ if (m.kind === "boat") I.burst(c, "water", c.toEffects(list2[0][0]).setY(0.05), 30, { speed: 3 });
33770
35392
  }
33771
- function exactMinY(c, list) {
35393
+ function exactMinY(c, list2) {
33772
35394
  c.root.updateMatrixWorld(true);
33773
35395
  const inv = new THREE.Matrix4().copy(c.root.matrixWorld).invert();
33774
35396
  const M = new THREE.Matrix4();
33775
35397
  const v = new V3();
33776
35398
  let mn = 1e9;
33777
- list.forEach(function(e) {
35399
+ list2.forEach(function(e) {
33778
35400
  const ob = e.o;
33779
35401
  if (!ob.parent || !I.shown(c, ob)) return;
33780
35402
  M.multiplyMatrices(inv, ob.matrixWorld);
@@ -34473,6 +36095,153 @@ var GameVehiclesThree = (() => {
34473
36095
  return hole;
34474
36096
  }
34475
36097
  const _zr = new THREE.Raycaster();
36098
+ const PROXY_MIN_TRIANGLES = 500;
36099
+ const STROKE_REACH = 0.6;
36100
+ const _pv = new V3();
36101
+ const _pm = new THREE.Matrix4();
36102
+ function decalRegion(c, z) {
36103
+ const B = z.box;
36104
+ const lo = [0, 1, 2].map(function(k) {
36105
+ return I.boxLo(B, k) - STROKE_REACH;
36106
+ });
36107
+ const hi = [0, 1, 2].map(function(k) {
36108
+ return I.boxHi(B, k) + STROKE_REACH;
36109
+ });
36110
+ const a = axisOf(z.dir);
36111
+ const dn = z.dir.clone().normalize();
36112
+ const sg = z.dir.getComponent(a) > 0 ? 1 : -1;
36113
+ const outer = sg > 0 ? I.boxLo(B, a) - 0.6 : I.boxHi(B, a) + 0.6;
36114
+ const far = 0.6 + (I.boxHi(B, a) - I.boxLo(B, a)) + 0.05;
36115
+ for (let i = 0; i < 8; i++) {
36116
+ const p = new V3();
36117
+ p.setComponent(a, outer);
36118
+ [0, 1, 2].filter(function(k) {
36119
+ return k !== a;
36120
+ }).forEach(function(k, j) {
36121
+ p.setComponent(k, i >> j & 1 ? I.boxHi(B, k) : I.boxLo(B, k));
36122
+ });
36123
+ for (let e = 0; e < 2; e++) {
36124
+ const q = e ? p.clone().addScaledVector(dn, far) : p;
36125
+ for (let k = 0; k < 3; k++) {
36126
+ lo[k] = Math.min(lo[k], q.getComponent(k) - 0.05);
36127
+ hi[k] = Math.max(hi[k], q.getComponent(k) + 0.05);
36128
+ }
36129
+ }
36130
+ }
36131
+ return { lo, hi };
36132
+ }
36133
+ function regionCands(c, z, cands) {
36134
+ if (!cands.some(heavy)) return cands;
36135
+ const R = decalRegion(c, z);
36136
+ const Mw = c.vehicle.matrixWorld;
36137
+ return cands.map(function(o) {
36138
+ if (!heavy(o)) return o;
36139
+ if (!o.geometry.boundingSphere) o.geometry.computeBoundingSphere();
36140
+ if (!o.geometry.boundingBox) o.geometry.computeBoundingBox();
36141
+ return proxyIn(o, Mw, R);
36142
+ });
36143
+ }
36144
+ function heavy(o) {
36145
+ const g = o.geometry;
36146
+ const pos = g && g.attributes && g.attributes.position;
36147
+ return o.raycast === THREE.Mesh.prototype.raycast && !o.isSkinnedMesh && !Array.isArray(o.material) && pos && !pos.isInterleavedBufferAttribute && pos.itemSize === 3 && !g.groups.length && !(g.morphAttributes && g.morphAttributes.position) && (g.index ? g.index.count : pos.count) / 3 >= PROXY_MIN_TRIANGLES;
36148
+ }
36149
+ function proxyIn(o, Mw, R) {
36150
+ _pm.copy(o.matrixWorld).invert().multiply(Mw);
36151
+ const lo = [Infinity, Infinity, Infinity];
36152
+ const hi = [-Infinity, -Infinity, -Infinity];
36153
+ for (let i = 0; i < 8; i++) {
36154
+ _pv.set(i & 1 ? R.hi[0] : R.lo[0], i & 2 ? R.hi[1] : R.lo[1], i & 4 ? R.hi[2] : R.lo[2]).applyMatrix4(_pm);
36155
+ for (let k = 0; k < 3; k++) {
36156
+ lo[k] = Math.min(lo[k], _pv.getComponent(k));
36157
+ hi[k] = Math.max(hi[k], _pv.getComponent(k));
36158
+ }
36159
+ }
36160
+ const g = o.geometry;
36161
+ const P = g.attributes.position.array;
36162
+ const ix = g.index ? g.index.array : null;
36163
+ const n = ix ? ix.length : P.length / 3;
36164
+ const keep = new Uint32Array(n - n % 3);
36165
+ let nk = 0;
36166
+ for (let t = 0; t + 2 < n; t += 3) {
36167
+ const a = (ix ? ix[t] : t) * 3;
36168
+ const b = (ix ? ix[t + 1] : t + 1) * 3;
36169
+ const d = (ix ? ix[t + 2] : t + 2) * 3;
36170
+ let out = false;
36171
+ for (let k = 0; k < 3 && !out; k++) {
36172
+ const u = P[a + k];
36173
+ const v = P[b + k];
36174
+ const w = P[d + k];
36175
+ out = Math.max(u, v, w) < lo[k] || Math.min(u, v, w) > hi[k];
36176
+ }
36177
+ if (!out) {
36178
+ keep[nk++] = ix ? ix[t] : t;
36179
+ keep[nk++] = ix ? ix[t + 1] : t + 1;
36180
+ keep[nk++] = ix ? ix[t + 2] : t + 2;
36181
+ }
36182
+ }
36183
+ if (!nk) return null;
36184
+ const kept = keep.slice(0, nk);
36185
+ const box2 = new Float32Array(kept.length / 3 * 6);
36186
+ for (let t = 0, j = 0; t < kept.length; t += 3, j += 6) {
36187
+ const a = kept[t] * 3;
36188
+ const b = kept[t + 1] * 3;
36189
+ const d = kept[t + 2] * 3;
36190
+ for (let k = 0; k < 3; k++) {
36191
+ box2[j + k] = Math.min(P[a + k], P[b + k], P[d + k]);
36192
+ box2[j + 3 + k] = Math.max(P[a + k], P[b + k], P[d + k]);
36193
+ }
36194
+ }
36195
+ const pg = new THREE.BufferGeometry();
36196
+ pg.setAttribute("position", g.attributes.position);
36197
+ pg.setIndex(new THREE.BufferAttribute(new Uint32Array(kept.length), 1));
36198
+ pg.boundingSphere = g.boundingSphere;
36199
+ pg.boundingBox = g.boundingBox;
36200
+ const proxy = new THREE.Mesh(pg, o.material);
36201
+ proxy.layers.mask = o.layers.mask;
36202
+ proxy.proxyOf = o;
36203
+ proxy.kept = kept;
36204
+ proxy.keptBox = box2;
36205
+ return proxy;
36206
+ }
36207
+ function narrowTo(rc, proxy) {
36208
+ const o = proxy.proxyOf;
36209
+ const ray = rc.ray;
36210
+ _pm.copy(o.matrixWorld).invert();
36211
+ _pv.copy(ray.origin).applyMatrix4(_pm);
36212
+ const x0 = _pv.x;
36213
+ const y0 = _pv.y;
36214
+ const z0 = _pv.z;
36215
+ _pv.copy(ray.direction).multiplyScalar(rc.far).add(ray.origin).applyMatrix4(_pm);
36216
+ const lo0 = Math.min(x0, _pv.x) - 1e-4;
36217
+ const lo1 = Math.min(y0, _pv.y) - 1e-4;
36218
+ const lo2 = Math.min(z0, _pv.z) - 1e-4;
36219
+ const hi0 = Math.max(x0, _pv.x) + 1e-4;
36220
+ const hi1 = Math.max(y0, _pv.y) + 1e-4;
36221
+ const hi2 = Math.max(z0, _pv.z) + 1e-4;
36222
+ const K = proxy.kept;
36223
+ const X = proxy.keptBox;
36224
+ const dst = proxy.geometry.index.array;
36225
+ let m = 0;
36226
+ for (let t = 0, j = 0; t < K.length; t += 3, j += 6) {
36227
+ if (X[j + 3] < lo0 || X[j] > hi0 || X[j + 4] < lo1 || X[j + 1] > hi1 || X[j + 5] < lo2 || X[j + 2] > hi2) continue;
36228
+ dst[m++] = K[t];
36229
+ dst[m++] = K[t + 1];
36230
+ dst[m++] = K[t + 2];
36231
+ }
36232
+ proxy.geometry.setDrawRange(0, m);
36233
+ }
36234
+ function castAt(rc, cands) {
36235
+ for (let i = 0; i < cands.length; i++) {
36236
+ const q = cands[i];
36237
+ if (!q.proxyOf) continue;
36238
+ q.matrixWorld.copy(q.proxyOf.matrixWorld);
36239
+ narrowTo(rc, q);
36240
+ }
36241
+ const hits = rc.intersectObjects(cands, false);
36242
+ for (let i = 0; i < hits.length; i++) if (hits[i].object.proxyOf) hits[i].object = hits[i].object.proxyOf;
36243
+ return hits;
36244
+ }
34476
36245
  function zoneCands(c, z, inv, glassToo) {
34477
36246
  const out = [];
34478
36247
  c.vehicle.traverse(function(o) {
@@ -34525,7 +36294,7 @@ var GameVehiclesThree = (() => {
34525
36294
  });
34526
36295
  _zr.set(org.clone().applyMatrix4(Mw), d.clone().transformDirection(Mw));
34527
36296
  _zr.far = 0.6 + (I.boxHi(B, a) - I.boxLo(B, a)) + 0.05;
34528
- const hits = _zr.intersectObjects(cands, false);
36297
+ const hits = castAt(_zr, cands);
34529
36298
  for (let i = 0; i < hits.length; i++) {
34530
36299
  const h = hits[i];
34531
36300
  if (!h.face) continue;
@@ -34553,7 +36322,7 @@ var GameVehiclesThree = (() => {
34553
36322
  const q = s.p.clone().addScaledVector(t, len * 0.5 * k / M);
34554
36323
  _rt.set(q.clone().addScaledVector(n, 0.08).applyMatrix4(Mw), n.clone().negate().transformDirection(Mw));
34555
36324
  _rt.far = 0.2;
34556
- const h = _rt.intersectObjects(cands, false).find(function(x) {
36325
+ const h = castAt(_rt, cands).find(function(x) {
34557
36326
  return x.face;
34558
36327
  });
34559
36328
  if (!h) return null;
@@ -34624,6 +36393,7 @@ var GameVehiclesThree = (() => {
34624
36393
  const R = c.rand;
34625
36394
  const need = (spec.fine || 0) + (spec.deep || 0) + (spec.chip || 0) + (spec.rust || 0) + (spec.tear || 0) + (spec.ding || 0) + (spec.soot || 0) + (spec.crater || 0);
34626
36395
  if (!need) return [];
36396
+ cands = regionCands(c, z, cands).filter(Boolean);
34627
36397
  const S = zoneSurf(c, z, need + 2, R, cands);
34628
36398
  let k = 0;
34629
36399
  const ang0 = R() * PI;
@@ -34702,8 +36472,25 @@ var GameVehiclesThree = (() => {
34702
36472
  }
34703
36473
  function subdivIn(geo, rel, B, maxLen) {
34704
36474
  const a = geo.attributes.position.array;
34705
- const out = [];
34706
- const v = new V3();
36475
+ let out = new Float32Array(a.length + 4096);
36476
+ let used = 0;
36477
+ const push = function(a0, a1, a2, b0, b1, b2, c0, c1, c2) {
36478
+ if (used + 9 > out.length) {
36479
+ const bigger = new Float32Array(out.length * 2);
36480
+ bigger.set(out);
36481
+ out = bigger;
36482
+ }
36483
+ out[used] = a0;
36484
+ out[used + 1] = a1;
36485
+ out[used + 2] = a2;
36486
+ out[used + 3] = b0;
36487
+ out[used + 4] = b1;
36488
+ out[used + 5] = b2;
36489
+ out[used + 6] = c0;
36490
+ out[used + 7] = c1;
36491
+ out[used + 8] = c2;
36492
+ used += 9;
36493
+ };
34707
36494
  const e = 0.15;
34708
36495
  function d(p, q) {
34709
36496
  return Math.hypot(p[0] - q[0], p[1] - q[1], p[2] - q[2]);
@@ -34717,7 +36504,7 @@ var GameVehiclesThree = (() => {
34717
36504
  const ca = d(C, A);
34718
36505
  const mx = Math.max(ab, bc, ca);
34719
36506
  if (mx <= maxLen || depth > 9) {
34720
- out.push(A[0], A[1], A[2], Bv[0], Bv[1], Bv[2], C[0], C[1], C[2]);
36507
+ push(A[0], A[1], A[2], Bv[0], Bv[1], Bv[2], C[0], C[1], C[2]);
34721
36508
  return;
34722
36509
  }
34723
36510
  if (mx === ab) {
@@ -34734,31 +36521,26 @@ var GameVehiclesThree = (() => {
34734
36521
  tri(F2, Bv, C, depth + 1);
34735
36522
  }
34736
36523
  }
36524
+ const M = rel.elements;
36525
+ const at = function(x, y, z, k) {
36526
+ const w = 1 / (M[3] * x + M[7] * y + M[11] * z + M[15]);
36527
+ return k === 0 ? (M[0] * x + M[4] * y + M[8] * z + M[12]) * w : k === 1 ? (M[1] * x + M[5] * y + M[9] * z + M[13]) * w : (M[2] * x + M[6] * y + M[10] * z + M[14]) * w;
36528
+ };
36529
+ const lo = [B.x0 - e, B.y0 - e, B.z0 - e];
36530
+ const hi = [B.x1 + e, B.y1 + e, B.z1 + e];
34737
36531
  for (let i = 0; i < a.length; i += 9) {
34738
- const A = [a[i], a[i + 1], a[i + 2]];
34739
- const Bv = [a[i + 3], a[i + 4], a[i + 5]];
34740
- const C = [a[i + 6], a[i + 7], a[i + 8]];
34741
- let x0 = 1e9;
34742
- let x1 = -1e9;
34743
- let y0 = 1e9;
34744
- let y1 = -1e9;
34745
- let z0 = 1e9;
34746
- let z1 = -1e9;
34747
- [A, Bv, C].forEach(function(p) {
34748
- v.set(p[0], p[1], p[2]).applyMatrix4(rel);
34749
- x0 = Math.min(x0, v.x);
34750
- x1 = Math.max(x1, v.x);
34751
- y0 = Math.min(y0, v.y);
34752
- y1 = Math.max(y1, v.y);
34753
- z0 = Math.min(z0, v.z);
34754
- z1 = Math.max(z1, v.z);
34755
- });
34756
- if (x1 < B.x0 - e || x0 > B.x1 + e || y1 < B.y0 - e || y0 > B.y1 + e || z1 < B.z0 - e || z0 > B.z1 + e)
34757
- out.push(A[0], A[1], A[2], Bv[0], Bv[1], Bv[2], C[0], C[1], C[2]);
34758
- else tri(A, Bv, C, 0);
36532
+ let outside = false;
36533
+ for (let k = 0; k < 3 && !outside; k++) {
36534
+ const p = at(a[i], a[i + 1], a[i + 2], k);
36535
+ const q = at(a[i + 3], a[i + 4], a[i + 5], k);
36536
+ const r = at(a[i + 6], a[i + 7], a[i + 8], k);
36537
+ outside = Math.max(p, q, r) < lo[k] || Math.min(p, q, r) > hi[k];
36538
+ }
36539
+ if (outside) push(a[i], a[i + 1], a[i + 2], a[i + 3], a[i + 4], a[i + 5], a[i + 6], a[i + 7], a[i + 8]);
36540
+ else tri([a[i], a[i + 1], a[i + 2]], [a[i + 3], a[i + 4], a[i + 5]], [a[i + 6], a[i + 7], a[i + 8]], 0);
34759
36541
  }
34760
36542
  const g = new THREE.BufferGeometry();
34761
- g.setAttribute("position", new THREE.Float32BufferAttribute(out, 3));
36543
+ g.setAttribute("position", new THREE.BufferAttribute(out.slice(0, used), 3));
34762
36544
  g.userData.crease = true;
34763
36545
  g.userData.p0 = null;
34764
36546
  return g;
@@ -34781,6 +36563,17 @@ var GameVehiclesThree = (() => {
34781
36563
  });
34782
36564
  return out;
34783
36565
  }
36566
+ function boxInFrame(B, m, tmp) {
36567
+ const r = [Infinity, Infinity, Infinity, -Infinity, -Infinity, -Infinity];
36568
+ for (let i = 0; i < 8; i++) {
36569
+ tmp.set(i & 1 ? B.x1 : B.x0, i & 2 ? B.y1 : B.y0, i & 4 ? B.z1 : B.z0).applyMatrix4(m);
36570
+ for (let k = 0; k < 3; k++) {
36571
+ r[k] = Math.min(r[k], tmp.getComponent(k) - 1e-4);
36572
+ r[k + 3] = Math.max(r[k + 3], tmp.getComponent(k) + 1e-4);
36573
+ }
36574
+ }
36575
+ return r;
36576
+ }
34784
36577
  function zoneDent(c, z, dents, dirty, opt) {
34785
36578
  opt = opt || {};
34786
36579
  const B = z.box;
@@ -34835,6 +36628,7 @@ var GameVehiclesThree = (() => {
34835
36628
  g = msh.geometry = g.clone();
34836
36629
  msh.userData.zCloned = true;
34837
36630
  }
36631
+ let boundsDue = false;
34838
36632
  const nonIdx = !g.index;
34839
36633
  const onlyPos = Object.keys(g.attributes).every(function(k) {
34840
36634
  return k === "position" || k === "normal";
@@ -34843,15 +36637,17 @@ var GameVehiclesThree = (() => {
34843
36637
  const ng = subdivIn(g, rel, B, opt.sub || 0.075);
34844
36638
  g.dispose();
34845
36639
  g = msh.geometry = ng;
34846
- ng.computeBoundingSphere();
34847
- ng.computeBoundingBox();
36640
+ boundsDue = true;
34848
36641
  dirty.add(msh);
34849
36642
  }
34850
36643
  irel.copy(rel).invert();
34851
36644
  const pos = g.attributes.position;
34852
36645
  let changed = false;
36646
+ const near = boxInFrame(B, irel, v);
34853
36647
  for (let i = 0; i < pos.count; i++) {
34854
- v.fromBufferAttribute(pos, i).applyMatrix4(rel);
36648
+ v.fromBufferAttribute(pos, i);
36649
+ if (v.x < near[0] || v.x > near[3] || v.y < near[1] || v.y > near[4] || v.z < near[2] || v.z > near[5]) continue;
36650
+ v.applyMatrix4(rel);
34855
36651
  const f = field(v);
34856
36652
  if (f <= 1e-5) continue;
34857
36653
  v.addScaledVector(d, f);
@@ -34872,9 +36668,11 @@ var GameVehiclesThree = (() => {
34872
36668
  }
34873
36669
  if (changed) {
34874
36670
  pos.needsUpdate = true;
36671
+ dirty.add(msh);
36672
+ }
36673
+ if (changed || boundsDue) {
34875
36674
  g.computeBoundingSphere();
34876
36675
  g.computeBoundingBox();
34877
- dirty.add(msh);
34878
36676
  }
34879
36677
  });
34880
36678
  const dset = new Set(c.deform);
@@ -35954,9 +37752,9 @@ var GameVehiclesThree = (() => {
35954
37752
  down: new V3(0, 1, 0)
35955
37753
  }[d] || null;
35956
37754
  }
35957
- function resolveObjs(c, list, z) {
37755
+ function resolveObjs(c, list2, z) {
35958
37756
  const out = [];
35959
- (list || []).forEach(function(o) {
37757
+ (list2 || []).forEach(function(o) {
35960
37758
  if (!o) return;
35961
37759
  if (typeof o === "string") {
35962
37760
  c.parts.forEach(function(p) {
@@ -35984,22 +37782,22 @@ var GameVehiclesThree = (() => {
35984
37782
  }
35985
37783
  function deriveZones(c) {
35986
37784
  const m = c.meta;
35987
- let list = [];
37785
+ let list2 = [];
35988
37786
  const byId = {};
35989
37787
  (m.zones === false ? [] : I.autoZones(c)).forEach(function(z) {
35990
37788
  byId[z.id] = z;
35991
- list.push(z);
37789
+ list2.push(z);
35992
37790
  });
35993
37791
  (c.zoneDefs || []).forEach(function(d) {
35994
37792
  let z = byId[d.id];
35995
37793
  if (d.remove) {
35996
37794
  if (z) {
35997
- list.splice(list.indexOf(z), 1);
37795
+ list2.splice(list2.indexOf(z), 1);
35998
37796
  delete byId[d.id];
35999
37797
  }
36000
- list.slice().forEach(function(q) {
37798
+ list2.slice().forEach(function(q) {
36001
37799
  if (q.id.indexOf(d.id + "_") === 0 && /^\d+$/.test(q.id.slice(d.id.length + 1))) {
36002
- list.splice(list.indexOf(q), 1);
37800
+ list2.splice(list2.indexOf(q), 1);
36003
37801
  delete byId[q.id];
36004
37802
  }
36005
37803
  });
@@ -36012,7 +37810,7 @@ var GameVehiclesThree = (() => {
36012
37810
  } else {
36013
37811
  z = Object.assign({ type: "panel" }, d);
36014
37812
  byId[d.id] = z;
36015
- list.push(z);
37813
+ list2.push(z);
36016
37814
  }
36017
37815
  });
36018
37816
  const inv = I.worldInverseOf(c);
@@ -36045,10 +37843,10 @@ var GameVehiclesThree = (() => {
36045
37843
  }
36046
37844
  z.box = I.normalizeBox(bb);
36047
37845
  });
36048
- list = list.filter(function(z) {
37846
+ list2 = list2.filter(function(z) {
36049
37847
  return z.box && z.name;
36050
37848
  });
36051
- list.forEach(function(z) {
37849
+ list2.forEach(function(z) {
36052
37850
  z.glass = (z.glass || []).slice();
36053
37851
  z.lights = (z.lights || []).slice();
36054
37852
  z.wheels = (z.wheels || []).slice();
@@ -36085,7 +37883,7 @@ var GameVehiclesThree = (() => {
36085
37883
  if (owner.has(g) || !g.parent || !g.userData.glass || g.userData.ghost) return;
36086
37884
  const cg = I.localBox(c, g, inv).getCenter(new V3());
36087
37885
  let best = null;
36088
- list.forEach(function(z) {
37886
+ list2.forEach(function(z) {
36089
37887
  if (z.internal || z.type === "wheel" || z.type === "light") return;
36090
37888
  if (I.boxContains(z.box, cg.x, cg.y, cg.z, 0.05) && (!best || I.boxVolume(z.box) < I.boxVolume(best.box))) best = z;
36091
37889
  });
@@ -36094,7 +37892,7 @@ var GameVehiclesThree = (() => {
36094
37892
  owner.set(g, best);
36095
37893
  }
36096
37894
  });
36097
- const looseParts = list.filter(function(z) {
37895
+ const looseParts = list2.filter(function(z) {
36098
37896
  return z.type === "part";
36099
37897
  });
36100
37898
  if (looseParts.length)
@@ -36119,7 +37917,7 @@ var GameVehiclesThree = (() => {
36119
37917
  });
36120
37918
  }
36121
37919
  });
36122
- list.forEach(function(z) {
37920
+ list2.forEach(function(z) {
36123
37921
  if (!z.mirror) return;
36124
37922
  z.mirrors = [];
36125
37923
  const B = z.box;
@@ -36151,21 +37949,21 @@ var GameVehiclesThree = (() => {
36151
37949
  });
36152
37950
  }
36153
37951
  });
36154
- list.forEach(function(z) {
37952
+ list2.forEach(function(z) {
36155
37953
  const B = z.box;
36156
37954
  z.map = z.map || [Math.max(B.x0, R - 0.3), Math.min(B.x1, F + 0.3), Math.max(B.z0, -W / 2 - 0.35), Math.min(B.z1, W / 2 + 0.35)];
36157
37955
  });
36158
- carMap(c, list);
37956
+ carMap(c, list2);
36159
37957
  c.zoneOwners = owner;
36160
- return list;
37958
+ return list2;
36161
37959
  }
36162
- function carMap(c, list) {
37960
+ function carMap(c, list2) {
36163
37961
  const m = c.meta;
36164
37962
  const W = m.width || 1.7;
36165
37963
  const hw = W / 2;
36166
37964
  const gh = m.glasshouse;
36167
37965
  if ((m.kind || "car") !== "car" || !gh || gh.fb == null) return;
36168
- list.forEach(function(z) {
37966
+ list2.forEach(function(z) {
36169
37967
  if (z.mapSet) return;
36170
37968
  const B = z.box;
36171
37969
  const s = z.side;
@@ -36228,8 +38026,8 @@ var GameVehiclesThree = (() => {
36228
38026
  const top = m.top || belt + 0.5;
36229
38027
  const hw = W / 2;
36230
38028
  const WH = I.wheelInfo(c);
36231
- function add2(id, name, type, box, o) {
36232
- const z = Object.assign({ id, name, type, box: I.normalizeBox(box) }, o || {});
38029
+ function add2(id, name, type, box2, o) {
38030
+ const z = Object.assign({ id, name, type, box: I.normalizeBox(box2) }, o || {});
36233
38031
  Z.push(z);
36234
38032
  return z;
36235
38033
  }
@@ -37723,9 +39521,9 @@ var GameVehiclesThree = (() => {
37723
39521
  const kind = kindOf2(zone);
37724
39522
  if (!kind || !zone.box) continue;
37725
39523
  const b = zone.box;
37726
- const box = new THREE.Box3(new THREE.Vector3(b.x0, b.y0, b.z0), new THREE.Vector3(b.x1, b.y1, b.z1));
37727
- if (matrix) box.applyMatrix4(matrix);
37728
- out.push({ material: kind.material, zone: zone.id, part: kind.part, side: zone.side === 0 ? "center" : zone.side < 0 ? "left" : "right", box });
39524
+ const box2 = new THREE.Box3(new THREE.Vector3(b.x0, b.y0, b.z0), new THREE.Vector3(b.x1, b.y1, b.z1));
39525
+ if (matrix) box2.applyMatrix4(matrix);
39526
+ out.push({ material: kind.material, zone: zone.id, part: kind.part, side: zone.side === 0 ? "center" : zone.side < 0 ? "left" : "right", box: box2 });
37729
39527
  }
37730
39528
  return out;
37731
39529
  };
@@ -37734,7 +39532,7 @@ var GameVehiclesThree = (() => {
37734
39532
  const opts = options || {};
37735
39533
  if (!opts.THREE || !opts.THREE.Vector3) throw new Error("createVehicleKit: options.THREE (the three.js namespace) is required");
37736
39534
  const lod = createLod(opts.lod);
37737
- const THREE = wrapThreeForLod(opts.THREE, lod);
39535
+ const THREE = wrapThreeForLod(shapeGeometries(opts.THREE), lod);
37738
39536
  const strings = resolveStrings(opts.locale);
37739
39537
  const t = createTranslate(strings);
37740
39538
  const doc = opts.document || (typeof document !== "undefined" ? document : void 0);
@@ -37957,6 +39755,20 @@ var GameVehiclesThree = (() => {
37957
39755
  else kit.applyArmor(c);
37958
39756
  }
37959
39757
  if (zoneState == null && st === "damaged" && kit.config.damagedScenario) zoneState = kit.zoneScenario(c, kit.config.damagedScenario);
39758
+ else if (zoneState && zoneState.scenario != null) {
39759
+ c.scenario = zoneState.scenario;
39760
+ let fromScenario = { health: {}, flags: {} };
39761
+ try {
39762
+ fromScenario = kit.zoneScenario(c, zoneState.scenario);
39763
+ } catch (e) {
39764
+ ;
39765
+ (c.zoneErrors = c.zoneErrors || []).push("scenario: " + (e && e.message));
39766
+ }
39767
+ zoneState = {
39768
+ health: Object.assign({}, fromScenario.health, zoneState.health),
39769
+ flags: Object.assign({}, fromScenario.flags, zoneState.flags)
39770
+ };
39771
+ }
37960
39772
  if (zoneState) kit.applyZones(c, zoneState);
37961
39773
  else {
37962
39774
  c.zoneState = { health: {}, flags: {} };
@@ -38120,19 +39932,19 @@ var GameVehiclesThree = (() => {
38120
39932
  for (const z of zones) {
38121
39933
  let role = roleOfZone(z);
38122
39934
  if (z === hubZone) role = "frame";
38123
- const box = boxOf(z);
38124
- const area = areaOf(box.size);
39935
+ const box2 = boxOf(z);
39936
+ const area3 = areaOf(box2.size);
38125
39937
  const id = z.id;
38126
39938
  const label = String(z.name ?? id);
38127
39939
  const tags = [...z.tags ?? []];
38128
39940
  if (role === "rim") {
38129
39941
  const wheels = z.wheels ?? [];
38130
39942
  const r = Math.max(0.2, ...wheels.map((w) => w.userData?.r ?? 0.3));
38131
- const sz = Math.sign(box.center[2]) || 1;
38132
- const rimBox = { center: [box.center[0], box.center[1], box.center[2] - sz * box.size[2] * 0.25], size: [box.size[0] * 0.7, box.size[1] * 0.7, box.size[2] * 0.5] };
39943
+ const sz = Math.sign(box2.center[2]) || 1;
39944
+ const rimBox = { center: [box2.center[0], box2.center[1], box2.center[2] - sz * box2.size[2] * 0.25], size: [box2.size[0] * 0.7, box2.size[1] * 0.7, box2.size[2] * 0.5] };
38133
39945
  add2({ id, role, name: label, material: kind === "plane" || kind === "heli" ? "aluminium" : "steel", box: rimBox, mass: 22 * r * Math.max(1, wheels.length), hp: 12e3 * armour, zoneId: id, visual: kind !== "plane" && !/landing/.test(id), tags: ["wheel", ...tags] });
38134
39946
  const tyreId = id.replace(/^wheels?/, "tyre").replace(/^(?!tyre)/, "tyre_");
38135
- const tyreBox = { center: box.center, size: [box.size[0] * 0.98, box.size[1] * 0.98, box.size[2]] };
39947
+ const tyreBox = { center: box2.center, size: [box2.size[0] * 0.98, box2.size[1] * 0.98, box2.size[2]] };
38136
39948
  add2({
38137
39949
  id: tyreId,
38138
39950
  role: "tyre",
@@ -38152,29 +39964,29 @@ var GameVehiclesThree = (() => {
38152
39964
  if (role === "glass") {
38153
39965
  const glass = (z.glass ?? [])[0];
38154
39966
  const laminated = glass?.userData?.glass?.type === "laminated" || m.bullet;
38155
- add2({ id, role, name: label, material: "glass", box, mass: 10 * area, hp: laminated ? 4e3 : 450, zoneId: id, visual: false, tags: ["glass", ...tags] });
39967
+ add2({ id, role, name: label, material: "glass", box: box2, mass: 10 * area3, hp: laminated ? 4e3 : 450, zoneId: id, visual: false, tags: ["glass", ...tags] });
38156
39968
  continue;
38157
39969
  }
38158
39970
  if (role === "light") {
38159
- add2({ id, role, name: label, material: "glass", box, mass: 1.2 + 4 * area, hp: 320, zoneId: id, visual: true, tags: ["light", ...tags] });
39971
+ add2({ id, role, name: label, material: "glass", box: box2, mass: 1.2 + 4 * area3, hp: 320, zoneId: id, visual: true, tags: ["light", ...tags] });
38160
39972
  continue;
38161
39973
  }
38162
39974
  if (role === "bumper") {
38163
- add2({ id, role, name: label, material: "plastic", box, mass: 6 + 5 * area, hp: 9e3, ignitionC: 400, zoneId: id, visual: true, tags: ["bumper", ...tags] });
39975
+ add2({ id, role, name: label, material: "plastic", box: box2, mass: 6 + 5 * area3, hp: 9e3, ignitionC: 400, zoneId: id, visual: true, tags: ["bumper", ...tags] });
38164
39976
  continue;
38165
39977
  }
38166
39978
  if (role === "engine") {
38167
39979
  const kg2 = { bike: 55, quad: 90, car: 150, tractor: 450, truck: 600, bus: 450, tank: 900, boat: 90, plane: 160, heli: 150 }[kind];
38168
- add2({ id, role, name: label, material: kind === "plane" || kind === "heli" ? "aluminium" : "steel", box, mass: kg2, hp: 6e4 * armour, ignitionC: 260, zoneId: id, visual: false, tags: ["engine", ...tags] });
39980
+ add2({ id, role, name: label, material: kind === "plane" || kind === "heli" ? "aluminium" : "steel", box: box2, mass: kg2, hp: 6e4 * armour, ignitionC: 260, zoneId: id, visual: false, tags: ["engine", ...tags] });
38169
39981
  continue;
38170
39982
  }
38171
39983
  if (role === "radiator") {
38172
- add2({ id, role, name: label, material: "aluminium", box, mass: 8, hp: 3e3, zoneId: id, visual: false, contains: { fluid: "coolant", liters: kind === "truck" || kind === "bus" ? 18 : 7, pressurized: true }, tags: ["radiator", ...tags] });
39984
+ add2({ id, role, name: label, material: "aluminium", box: box2, mass: 8, hp: 3e3, zoneId: id, visual: false, contains: { fluid: "coolant", liters: kind === "truck" || kind === "bus" ? 18 : 7, pressurized: true }, tags: ["radiator", ...tags] });
38173
39985
  continue;
38174
39986
  }
38175
39987
  if (role === "fuel_tank") {
38176
39988
  if (fuelless) {
38177
- add2({ id, role: "other", name: label, material: "steel", box, mass: 20, hp: 25e3, zoneId: id, visual: false, tags });
39989
+ add2({ id, role: "other", name: label, material: "steel", box: box2, mass: 20, hp: 25e3, zoneId: id, visual: false, tags });
38178
39990
  continue;
38179
39991
  }
38180
39992
  const liters = { bike: 14, quad: 16, car: 55, tractor: 150, truck: 300, bus: 200, tank: 600, boat: 90, plane: 120, heli: 300 }[kind];
@@ -38184,7 +39996,7 @@ var GameVehiclesThree = (() => {
38184
39996
  role,
38185
39997
  name: label,
38186
39998
  material: "steel",
38187
- box,
39999
+ box: box2,
38188
40000
  mass: 14 + liters * 0.8,
38189
40001
  hp: 25e3 * armour,
38190
40002
  zoneId: id,
@@ -38197,21 +40009,21 @@ var GameVehiclesThree = (() => {
38197
40009
  continue;
38198
40010
  }
38199
40011
  if (role === "battery") {
38200
- add2({ id, role, name: label, material: "plastic", box, mass: 14, hp: 1500, zoneId: id, visual: true, ignitionC: 200, tags: ["battery", ...tags] });
40012
+ add2({ id, role, name: label, material: "plastic", box: box2, mass: 14, hp: 1500, zoneId: id, visual: true, ignitionC: 200, tags: ["battery", ...tags] });
38201
40013
  continue;
38202
40014
  }
38203
40015
  if (role === "frame") {
38204
- add2({ id, role, name: label, material: "steel", box: floorPan(box), mass: mass * 0.25, hp: 15e4 * armour, zoneId: id, visual: false, tags: ["frame", ...tags] });
40016
+ add2({ id, role, name: label, material: "steel", box: floorPan(box2), mass: mass * 0.25, hp: 15e4 * armour, zoneId: id, visual: false, tags: ["frame", ...tags] });
38205
40017
  continue;
38206
40018
  }
38207
40019
  const roofLike = role === "roof";
38208
- const kg = (skin === "steel" ? STEEL_KG_M2 : ALU_KG_M2) * area * (role === "door" ? 1.6 : 1);
40020
+ const kg = (skin === "steel" ? STEEL_KG_M2 : ALU_KG_M2) * area3 * (role === "door" ? 1.6 : 1);
38209
40021
  add2({
38210
40022
  id,
38211
40023
  role,
38212
40024
  name: label,
38213
40025
  material: skin,
38214
- box,
40026
+ box: box2,
38215
40027
  mass: Math.max(2, kg),
38216
40028
  hp: (roofLike ? 3e4 : 2e4) * armour,
38217
40029
  zoneId: id,
@@ -38433,7 +40245,7 @@ var GameVehiclesThree = (() => {
38433
40245
  const my = kind === "bike" || kind === "quad" ? (m.top ?? belt + 0.25) - 0.1 : belt + 0.12;
38434
40246
  for (const s of [-1, 1]) {
38435
40247
  const door = zones.find((z) => z.type === "door" && z.side === s && (z.mirrors ?? []).length);
38436
- let box = { center: [mx, my, s * half], size: [0.14, 0.12, 0.2] };
40248
+ let box2 = { center: [mx, my, s * half], size: [0.14, 0.12, 0.2] };
38437
40249
  if (door) {
38438
40250
  const bb = door.mirrors.reduce(
38439
40251
  (acc, o) => {
@@ -38446,14 +40258,14 @@ var GameVehiclesThree = (() => {
38446
40258
  },
38447
40259
  null
38448
40260
  );
38449
- if (bb) box = { center: [(bb[0] + bb[1]) / 2, (bb[2] + bb[3]) / 2, (bb[4] + bb[5]) / 2], size: [Math.max(0.06, bb[1] - bb[0]), Math.max(0.06, bb[3] - bb[2]), Math.max(0.06, bb[5] - bb[4])] };
40261
+ if (bb) box2 = { center: [(bb[0] + bb[1]) / 2, (bb[2] + bb[3]) / 2, (bb[4] + bb[5]) / 2], size: [Math.max(0.06, bb[1] - bb[0]), Math.max(0.06, bb[3] - bb[2]), Math.max(0.06, bb[5] - bb[4])] };
38450
40262
  }
38451
40263
  add2({
38452
40264
  id: `mirror_${side(s)}`,
38453
40265
  role: "mirror",
38454
40266
  name: t("mechanics.mirror", { side: t(`sides.${side(s)}`), sideM: t(`sides.${side(s)}M`) }),
38455
40267
  material: "plastic",
38456
- box,
40268
+ box: box2,
38457
40269
  mass: 1.1,
38458
40270
  hp: 1500,
38459
40271
  ignitionC: 400,
@@ -38639,13 +40451,13 @@ var GameVehiclesThree = (() => {
38639
40451
  (parent ?? this.c.vehicle).add(m);
38640
40452
  return m;
38641
40453
  }
38642
- surface(axis, sign, B, samples) {
40454
+ surface(axis, sign2, B, samples) {
38643
40455
  const V3 = this.THREE.Vector3;
38644
40456
  const hits = [];
38645
40457
  const far = 3;
38646
40458
  for (const [u, v] of samples) {
38647
- const o = axis === "z" ? new V3(u, v, sign * (Math.max(Math.abs(B.z0), Math.abs(B.z1)) + 1)) : new V3(sign * (Math.max(Math.abs(B.x0), Math.abs(B.x1)) + 1), u, v);
38648
- const d = axis === "z" ? new V3(0, 0, -sign) : new V3(-sign, 0, 0);
40459
+ const o = axis === "z" ? new V3(u, v, sign2 * (Math.max(Math.abs(B.z0), Math.abs(B.z1)) + 1)) : new V3(sign2 * (Math.max(Math.abs(B.x0), Math.abs(B.x1)) + 1), u, v);
40460
+ const d = axis === "z" ? new V3(0, 0, -sign2) : new V3(-sign2, 0, 0);
38649
40461
  const h = this.I.probe(this.c, o, d, far);
38650
40462
  if (h) hits.push(axis === "z" ? h.p.z : h.p.x);
38651
40463
  }
@@ -38795,12 +40607,12 @@ var GameVehiclesThree = (() => {
38795
40607
  const z = this.zone(p);
38796
40608
  if (!z) return false;
38797
40609
  const V3 = this.THREE.Vector3;
38798
- const list = z.glass.filter((g) => g.parent && g.visible);
38799
- if (!list.length) return false;
40610
+ const list2 = z.glass.filter((g) => g.parent && g.visible);
40611
+ if (!list2.length) return false;
38800
40612
  const pt = new V3(...point);
38801
- let best = list[0];
40613
+ let best = list2[0];
38802
40614
  let bd = Infinity;
38803
- for (const g of list) {
40615
+ for (const g of list2) {
38804
40616
  g.geometry.computeBoundingBox();
38805
40617
  const bb = g.geometry.boundingBox.clone().applyMatrix4(g.matrix);
38806
40618
  const d = bb.distanceToPoint(pt);
@@ -39097,6 +40909,9 @@ var GameVehiclesThree = (() => {
39097
40909
  const headless = !!options.headless;
39098
40910
  const seedBase = strHash(`${c.key}|${id}|${options.seed ?? 0}`);
39099
40911
  let rand = rng(seedBase);
40912
+ const ignitionRules = resolveIgnitionRules(options.ignition);
40913
+ const fuelFraction = clamp(options.fuel ?? 1, 0, 1);
40914
+ let igniteRand = rng(strHash(`${c.key}|${id}|ignition|${options.seed ?? 0}`));
39100
40915
  let clock = 0;
39101
40916
  let model;
39102
40917
  let vis = null;
@@ -39164,7 +40979,7 @@ var GameVehiclesThree = (() => {
39164
40979
  dents: [],
39165
40980
  holes: [],
39166
40981
  cracks: [],
39167
- liters: d.contains?.liters,
40982
+ liters: d.contains ? d.role === "fuel_tank" ? d.contains.liters * fuelFraction : d.contains.liters : void 0,
39168
40983
  lost: false,
39169
40984
  status: "intact",
39170
40985
  flat: false,
@@ -39182,6 +40997,7 @@ var GameVehiclesThree = (() => {
39182
40997
  wasLit = true;
39183
40998
  deadEngine = false;
39184
40999
  rand = rng(seedBase);
41000
+ igniteRand = rng(strHash(`${c.key}|${id}|ignition|${options.seed ?? 0}`));
39185
41001
  steerSign = rand() < 0.5 ? -1 : 1;
39186
41002
  vis = headless ? null : new VehicleVisuals(kit, c, model);
39187
41003
  recomputeGroups();
@@ -39203,8 +41019,8 @@ var GameVehiclesThree = (() => {
39203
41019
  comps.get(r).push(p);
39204
41020
  }
39205
41021
  const hubRoot = parent.has(model.hub) ? find(model.hub) : "";
39206
- const list = [...comps.entries()].sort((a, b) => a[0] === hubRoot ? -1 : b[0] === hubRoot ? 1 : 0);
39207
- groupsCache = list.map(([, v]) => v);
41022
+ const list2 = [...comps.entries()].sort((a, b) => a[0] === hubRoot ? -1 : b[0] === hubRoot ? 1 : 0);
41023
+ groupsCache = list2.map(([, v]) => v);
39208
41024
  groupOf = /* @__PURE__ */ new Map();
39209
41025
  groupsCache.forEach((g, i) => g.forEach((p) => groupOf.set(p, i)));
39210
41026
  return groupsCache;
@@ -39476,8 +41292,19 @@ var GameVehiclesThree = (() => {
39476
41292
  if (!p.burning && p.temp > AMBIENT) p.temp = Math.max(AMBIENT, p.temp - dt * 6);
39477
41293
  }
39478
41294
  for (const f of flames) heat(centreOf(f.def), 0.8, 500, dt * 0.5, out, 0);
41295
+ fireNearLeak(flames, dt, out);
39479
41296
  thermal(out);
39480
41297
  };
41298
+ const fireNearLeak = (flames, dt, out) => {
41299
+ const tank = tankPart();
41300
+ const leak = tank ? leaks.get(tank.def.id) : void 0;
41301
+ if (!tank || !leak || tank.lost || tank.burning || exploded || leak.fluid !== "fuel" && leak.fluid !== "diesel") return;
41302
+ if (leak.pud?.fire) return light(tank, out);
41303
+ const { radius, chancePerSecond } = ignitionRules.fireNear;
41304
+ if (chancePerSecond <= 0) return;
41305
+ const near = flames.some((f) => f !== tank && distToBox(tank.def, centreOf(f.def)) - Math.max(...f.def.box.size) / 2 <= radius);
41306
+ if (near && igniteRand() < 1 - Math.exp(-chancePerSecond * dt)) light(tank, out);
41307
+ };
39481
41308
  const normalOf = (d, v) => faceNormal(d, v);
39482
41309
  const ballistic = (h, out) => {
39483
41310
  sync();
@@ -39545,10 +41372,21 @@ var GameVehiclesThree = (() => {
39545
41372
  let amount = through ? E * 0.6 : E * 0.25;
39546
41373
  if (through && (d.role === "battery" || d.role === "alternator")) amount = Math.max(amount, p.hp * 0.65);
39547
41374
  damage(p, amount, "ballistic", h.source, out, worldPoint);
39548
- if (d.role === "fuel_tank" && E > 1500 && (p.liters ?? 0) > 1) p.temp = Math.max(p.temp, d.ignitionC ?? 260);
41375
+ if (through && d.role === "fuel_tank") rollIgnition(p, h, metal, out);
39549
41376
  }
39550
41377
  }
39551
41378
  };
41379
+ const light = (tank, out) => {
41380
+ tank.temp = Math.max(tank.temp, (tank.def.ignitionC ?? 260) + 1);
41381
+ if ((tank.liters ?? 0) > 0.5) ignite(tank, out);
41382
+ };
41383
+ const rollIgnition = (tank, h, metal, out) => {
41384
+ const d = tank.def;
41385
+ if (!d.contains || tank.burning || (tank.liters ?? 0) <= 0.05) return;
41386
+ const fill2 = d.contains.liters > 0 ? (tank.liters ?? 0) / d.contains.liters : 0;
41387
+ const chance = ignitionChance(h, { sparkTarget: sparkTargetFactor(d.material, metal, ignitionRules), fill: fill2, fluid: d.contains.fluid }, ignitionRules);
41388
+ if (chance > 0 && igniteRand() < chance) light(tank, out);
41389
+ };
39552
41390
  const blunt = (h, out) => {
39553
41391
  sync();
39554
41392
  const M = toFrameMatrix();
@@ -39612,7 +41450,7 @@ var GameVehiclesThree = (() => {
39612
41450
  const verdict = kit.blastDamage(c, E / (1 + dist * dist * 4) / 50);
39613
41451
  if (verdict === "explosion") explode(tank, h.source, out);
39614
41452
  else if (verdict === "fire") {
39615
- tank.temp = Math.max(tank.temp, tank.def.ignitionC ?? 260);
41453
+ light(tank, out);
39616
41454
  startLeak(tank, centreOf(tank.def).setY(tank.def.box.center[1] - tank.def.box.size[1] / 2 + 0.05), 12, out, dir);
39617
41455
  }
39618
41456
  }
@@ -39626,9 +41464,9 @@ var GameVehiclesThree = (() => {
39626
41464
  thermal(out);
39627
41465
  };
39628
41466
  const sound = (role) => {
39629
- const list = [...ps.values()].filter((p) => p.def.role === role);
39630
- if (!list.length) return true;
39631
- return list.every((p) => !p.lost && attached(p.def.id) && p.hp >= p.def.hp * 0.5);
41467
+ const list2 = [...ps.values()].filter((p) => p.def.role === role);
41468
+ if (!list2.length) return true;
41469
+ return list2.every((p) => !p.lost && attached(p.def.id) && p.hp >= p.def.hp * 0.5);
39632
41470
  };
39633
41471
  const tankPart = () => [...ps.values()].find((p) => p.def.role === "fuel_tank" && p.def.contains);
39634
41472
  const computeStatus = () => {
@@ -39820,8 +41658,8 @@ var GameVehiclesThree = (() => {
39820
41658
  queue = [];
39821
41659
  const hood = c.hood;
39822
41660
  if (hood) {
39823
- const sign = hood.sign || 1;
39824
- const cur = hood.piv.rotation.z / sign;
41661
+ const sign2 = hood.sign || 1;
41662
+ const cur = hood.piv.rotation.z / sign2;
39825
41663
  if (Math.abs(cur - hood.ang) > 1e-4) {
39826
41664
  hood.ang = cur;
39827
41665
  hood.target = cur;
@@ -39874,7 +41712,7 @@ var GameVehiclesThree = (() => {
39874
41712
  const reset = () => {
39875
41713
  const old = c;
39876
41714
  const parent = old.root.parent;
39877
- const next = kit.build(old.key, old.state);
41715
+ const next = kit.build(old.key, old.state, old.scenario != null ? { scenario: old.scenario } : void 0);
39878
41716
  if (parent) {
39879
41717
  next.root.position.copy(old.root.position);
39880
41718
  next.root.quaternion.copy(old.root.quaternion);
@@ -39929,7 +41767,8 @@ var GameVehiclesThree = (() => {
39929
41767
  }
39930
41768
  function buildVehicleItem(kit, key, options = {}) {
39931
41769
  const THREE = kit.THREE;
39932
- const vehicle = options.lod ? kit.build(key, options.state ?? "intact", void 0, { lod: true }) : kit.build(key, options.state ?? "intact");
41770
+ const zoneState = options.scenario != null ? { scenario: options.scenario } : void 0;
41771
+ const vehicle = options.lod ? kit.build(key, options.state ?? "intact", zoneState, { lod: true }) : kit.build(key, options.state ?? "intact", zoneState);
39933
41772
  const m = vehicle.meta;
39934
41773
  const root = new THREE.Group();
39935
41774
  root.name = key;
@@ -39942,34 +41781,6 @@ var GameVehiclesThree = (() => {
39942
41781
  return { root, vehicle };
39943
41782
  }
39944
41783
 
39945
- // ../game-contracts/dist/index.js
39946
- var UNSAFE_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
39947
- var isPlainObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value) && Object.getPrototypeOf(value) === Object.prototype;
39948
- var deepMerge = (base, patch) => {
39949
- if (!patch) return base;
39950
- const result = { ...base };
39951
- for (const [key, value] of Object.entries(patch)) {
39952
- if (value === void 0 || UNSAFE_KEYS.has(key)) continue;
39953
- const current = result[key];
39954
- result[key] = isPlainObject(current) && isPlainObject(value) ? deepMerge(current, value) : value;
39955
- }
39956
- return result;
39957
- };
39958
- var mergeById = (shipped, extra) => {
39959
- const entries = /* @__PURE__ */ new Map();
39960
- for (const entry of [...shipped, ...extra ?? []]) entries.set(entry.id, entry);
39961
- return entries;
39962
- };
39963
- var applyPatches = (entries, patches) => {
39964
- for (const [id, patch] of Object.entries(patches ?? {})) {
39965
- const entry = entries.get(id);
39966
- if (entry) entries.set(id, deepMerge(entry, patch));
39967
- }
39968
- };
39969
- var removeIds = (entries, ids) => {
39970
- for (const id of ids ?? []) entries.delete(id);
39971
- };
39972
-
39973
41784
  // ../game-vehicles-driving/dist/index.js
39974
41785
  var defaultArcadeSpec = {
39975
41786
  length: 4.3,
@@ -40105,7 +41916,7 @@ var GameVehiclesThree = (() => {
40105
41916
  { id: "blood", grip: 0.5 }
40106
41917
  ];
40107
41918
  function createSurfaces(options = {}) {
40108
- const entries = mergeById(defaultSurfaces, options.packs?.flatMap((pack) => pack.surfaces ?? []));
41919
+ const entries = mergeById(defaultSurfaces, options.packs?.flatMap((pack2) => pack2.surfaces ?? []));
40109
41920
  applyPatches(entries, options.patch);
40110
41921
  removeIds(entries, options.remove);
40111
41922
  const fallback = entries.get("dry_asphalt") ?? { id: "dry_asphalt", grip: 1 };
@@ -40398,6 +42209,7 @@ var GameVehiclesThree = (() => {
40398
42209
  "vehicles_kill_battery",
40399
42210
  "vehicles_rollover",
40400
42211
  "vehicles_melt",
42212
+ "vehicles_burnt_wreck",
40401
42213
  "vehicles_drive_arcade",
40402
42214
  "vehicles_drive_semi"
40403
42215
  ];
@@ -40429,7 +42241,7 @@ var GameVehiclesThree = (() => {
40429
42241
  en: {
40430
42242
  group: "Vehicles",
40431
42243
  name: "Vehicles area",
40432
- items: { hatch: "Compact hatch", sedan: "Midsize sedan", pickup: "Midsize pickup", sport_bike: "Sport bike", box_truck: "Box truck", city_bus: "City bus", battle_tank: "Battle tank", attack_helicopter: "Attack helicopter" },
42244
+ items: { hatch: "Compact hatch", sedan: "Midsize sedan", pickup: "Midsize pickup", sport_bike: "Sport bike", box_truck: "Box truck", city_bus: "City bus", battle_tank: "Battle tank", attack_helicopter: "Attack helicopter", sedan_burnt: "Burnt sedan", hatch_burnt: "Burnt hatch" },
40433
42245
  controls: { quality: "Quality", paint_by_seed: "Paint by seed", color_seed: "Colour seed", palette: "Palette", driving: "Driving", surface: "Surface" },
40434
42246
  hints: {
40435
42247
  quality: "High: the kit at full detail. Light: fewer segments and no interior (the light mode of the fleet); applies to the vehicles placed from now on",
@@ -40462,7 +42274,8 @@ var GameVehiclesThree = (() => {
40462
42274
  vehicles_rollover: "Vehicles: roll over",
40463
42275
  vehicles_melt: "Vehicles: melt (long fire burns the tyres)",
40464
42276
  vehicles_drive_arcade: "Vehicles: arcade driving down a lane that ends in a wall",
40465
- vehicles_drive_semi: "Vehicles: semi-simulation braking on dry, wet and mud"
42277
+ vehicles_drive_semi: "Vehicles: semi-simulation braking on dry, wet and mud",
42278
+ vehicles_burnt_wreck: "Vehicles: the burnt sedan comes out of the kit burnt, with the glass gone"
40466
42279
  },
40467
42280
  checks: {
40468
42281
  windshield_holes: "Windshield: {0} hole(s), went through {1:b} (expected: 1, true)",
@@ -40487,13 +42300,15 @@ var GameVehiclesThree = (() => {
40487
42300
  arcade_bounce: "Arcade: the car bounces back at {0} m/s (expected: below 0)",
40488
42301
  arcade_noise: "Arcade: {0} engine noise(s) and {1} crash noise(s) (expected: 1 or more each)",
40489
42302
  semi_order: "Semi: braking from 80 km/h takes dry {0} m, wet {1} m, mud {2} m (expected: dry shorter than wet shorter than mud)",
40490
- semi_mud: "Semi: a 2WD car on mud {0:on} (expected: bogged on, a bog event)"
42303
+ semi_mud: "Semi: a 2WD car on mud {0:on} (expected: bogged on, a bog event)",
42304
+ wreck_burnt: "Burnt sedan: burnt flag {0:b} (expected: yes)",
42305
+ wreck_glass: "Burnt sedan: {0} glass zone(s), {1} still above 0 (expected: 1 or more, none above 0)"
40491
42306
  }
40492
42307
  },
40493
42308
  "pt-BR": {
40494
42309
  group: "Ve\xEDculos",
40495
42310
  name: "\xC1rea de ve\xEDculos",
40496
- items: { hatch: "Hatch compacto", sedan: "Sed\xE3 m\xE9dio", pickup: "Picape m\xE9dia", sport_bike: "Moto esportiva", box_truck: "Caminh\xE3o ba\xFA", city_bus: "\xD4nibus urbano", battle_tank: "Tanque de guerra", attack_helicopter: "Helic\xF3ptero de ataque" },
42311
+ items: { hatch: "Hatch compacto", sedan: "Sed\xE3 m\xE9dio", pickup: "Picape m\xE9dia", sport_bike: "Moto esportiva", box_truck: "Caminh\xE3o ba\xFA", city_bus: "\xD4nibus urbano", battle_tank: "Tanque de guerra", attack_helicopter: "Helic\xF3ptero de ataque", sedan_burnt: "Sed\xE3 queimado", hatch_burnt: "Hatch queimado" },
40497
42312
  controls: { quality: "Qualidade", paint_by_seed: "Pintar pela semente", color_seed: "Semente da cor", palette: "Paleta", driving: "Dire\xE7\xE3o", surface: "Piso" },
40498
42313
  hints: {
40499
42314
  quality: "Alta: o kit com todo o detalhe. Leve: menos segmentos e sem interior (o modo leve da frota); vale para os ve\xEDculos postos daqui em diante",
@@ -40526,7 +42341,8 @@ var GameVehiclesThree = (() => {
40526
42341
  vehicles_rollover: "Ve\xEDculos: capotar",
40527
42342
  vehicles_melt: "Ve\xEDculos: derreter (fogo longo queima os pneus)",
40528
42343
  vehicles_drive_arcade: "Ve\xEDculos: dire\xE7\xE3o arcade numa pista que acaba num muro",
40529
- vehicles_drive_semi: "Ve\xEDculos: frenagem da semissimula\xE7\xE3o no seco, no molhado e na lama"
42344
+ vehicles_drive_semi: "Ve\xEDculos: frenagem da semissimula\xE7\xE3o no seco, no molhado e na lama",
42345
+ vehicles_burnt_wreck: "Ve\xEDculos: o sed\xE3 queimado sai do kit queimado, sem os vidros"
40530
42346
  },
40531
42347
  checks: {
40532
42348
  windshield_holes: "Para-brisa: {0} furo(s), atravessou {1:b} (esperado: 1, sim)",
@@ -40551,7 +42367,9 @@ var GameVehiclesThree = (() => {
40551
42367
  arcade_bounce: "Arcade: o carro volta a {0} m/s (esperado: abaixo de 0)",
40552
42368
  arcade_noise: "Arcade: {0} ru\xEDdo(s) de motor e {1} de batida (esperado: 1 ou mais de cada)",
40553
42369
  semi_order: "Semi: frear de 80 km/h leva no seco {0} m, no molhado {1} m, na lama {2} m (esperado: seco menor que molhado menor que lama)",
40554
- semi_mud: "Semi: um carro 2WD na lama {0:on} (esperado: atolado, com evento de atolamento)"
42370
+ semi_mud: "Semi: um carro 2WD na lama {0:on} (esperado: atolado, com evento de atolamento)",
42371
+ wreck_burnt: "Sed\xE3 queimado: marca de queimado {0:b} (esperado: sim)",
42372
+ wreck_glass: "Sed\xE3 queimado: {0} zona(s) de vidro, {1} ainda acima de 0 (esperado: 1 ou mais, nenhuma acima de 0)"
40555
42373
  }
40556
42374
  }
40557
42375
  };
@@ -40710,6 +42528,14 @@ var GameVehiclesThree = (() => {
40710
42528
  const t = part(room, v, "tyre_front_left");
40711
42529
  expect(events(room, "melt", v) >= 1 && (t.status === "melted" || t.melt > 0.5), say("tyre_melt", t.status, Math.round(t.melt * 100), events(room, "melt", v)));
40712
42530
  }),
42531
+ // new in the kit: the burnt wreck comes ready from the kit (the fleet's `burnt` scenario built into the vehicle), no damage applied by the area
42532
+ scenario("vehicles_burnt_wreck", ({ room, expect }) => {
42533
+ const c = room.spawn("sedan_burnt", [0, 0, -7], 0).root.userData.vehicle;
42534
+ expect(c.zoneState.flags.burnt === true, say("wreck_burnt", c.zoneState.flags.burnt === true));
42535
+ const glass = c.zones.filter((z) => z.type === "glass");
42536
+ const up = glass.filter((z) => (c.zoneState.health[z.id] ?? 100) > 0);
42537
+ expect(glass.length >= 1 && up.length === 0, say("wreck_glass", glass.length, up.length));
42538
+ }),
40713
42539
  // new in the kit: the drivers, headless (no vehicle is spawned)
40714
42540
  scenario("vehicles_drive_arcade", ({ expect }) => {
40715
42541
  const driver = createArcadeDriver();
@@ -40986,9 +42812,14 @@ var GameVehiclesThree = (() => {
40986
42812
  glass: "glass_burst",
40987
42813
  sparks: "impact_metal",
40988
42814
  leak: "vehicle_leak",
42815
+ leakIgnited: "vehicle_leak_ignited",
40989
42816
  exhaust: "vehicle_exhaust"
40990
42817
  };
40991
42818
  var defaultSoundIds = { engine: "engine_saw", horn: "horn", crash: "sfx_impact" };
42819
+ var DEFAULT_TEST_WRECKS = [
42820
+ { key: "sedan_burnt", vehicle: "midsize_sedan", scenario: "burnt" },
42821
+ { key: "hatch_burnt", vehicle: "compact_hatch", scenario: "burnt" }
42822
+ ];
40992
42823
 
40993
42824
  // src/test-area/module.ts
40994
42825
  var VEHICLES_AREA_ID = "vehicles_area";
@@ -41002,6 +42833,8 @@ var GameVehiclesThree = (() => {
41002
42833
  const locale = options.locale ?? "pt-BR";
41003
42834
  const text = TEXT[locale] ?? TEXT["pt-BR"];
41004
42835
  const keys = options.vehicles ?? DEFAULT_TEST_VEHICLES;
42836
+ const wrecks = options.wrecks ?? DEFAULT_TEST_WRECKS;
42837
+ const entries = [...keys.map((key) => ({ key, id: itemId(key) })), ...wrecks.map((w) => ({ key: w.vehicle, id: w.key, scenario: w.scenario }))];
41005
42838
  const effectIds = { ...defaultEffectIds, ...options.effects };
41006
42839
  const soundIds = { ...defaultSoundIds, ...options.sounds };
41007
42840
  const settings = { quality: "high", paint: false, seed: 1, palette: "auto", driving: "arcade", surface: "dry_asphalt" };
@@ -41036,29 +42869,31 @@ var GameVehiclesThree = (() => {
41036
42869
  const paletteFor = (key) => settings.palette === "civil" ? paintPalettes.civil : settings.palette === "military" ? paintPalettes.military : paletteOf(key);
41037
42870
  const paintOf = (entry) => {
41038
42871
  if (!settings.paint) return;
41039
- const color = colorFromSeed(settings.seed + entry.index, paletteFor(entry.key));
42872
+ const color2 = colorFromSeed(settings.seed + entry.index, paletteFor(entry.key));
41040
42873
  if (!entry.paint) {
41041
42874
  const vehicle = entry.item.vehicle;
41042
42875
  const primary = primaryPaint(entry.item.vehicle);
41043
42876
  if (!primary) return;
41044
42877
  entry.paint = primary.clone();
41045
- vehicle.vehicle.traverse((mesh) => {
41046
- if (!mesh.isMesh) return;
41047
- if (Array.isArray(mesh.material)) mesh.material = mesh.material.map((m) => m === primary ? entry.paint : m);
41048
- else if (mesh.material === primary) mesh.material = entry.paint;
42878
+ vehicle.vehicle.traverse((mesh2) => {
42879
+ if (!mesh2.isMesh) return;
42880
+ if (Array.isArray(mesh2.material)) mesh2.material = mesh2.material.map((m) => m === primary ? entry.paint : m);
42881
+ else if (mesh2.material === primary) mesh2.material = entry.paint;
41049
42882
  });
41050
42883
  }
41051
- entry.paint.color.set(color);
42884
+ entry.paint.color.set(color2);
41052
42885
  };
41053
- const item = (key) => ({
41054
- id: itemId(key),
41055
- name: text.items[itemId(key)] ?? key,
42886
+ const item = ({ key, id: itemKey, scenario }) => ({
42887
+ id: itemKey,
42888
+ name: text.items[itemKey] ?? key,
41056
42889
  movable: false,
42890
+ // the first build of a vehicle takes most of a second
42891
+ slow: true,
41057
42892
  build: (THREE) => {
41058
42893
  const kit = kitFor(THREE);
41059
- const built = buildVehicleItem(kit, key, { lod: settings.quality === "lite" });
42894
+ const built = buildVehicleItem(kit, key, { lod: settings.quality === "lite", ...scenario ? { scenario } : {} });
41060
42895
  built.root.userData.kit = kit;
41061
- const entry = { root: built.root, key, item: built, index: counter++, helpers: [] };
42896
+ const entry = { root: built.root, key, ...scenario ? { scenario } : {}, item: built, index: counter++, helpers: [] };
41062
42897
  placed.set(built.root.uuid, entry);
41063
42898
  measure(entry);
41064
42899
  paintOf(entry);
@@ -41067,7 +42902,7 @@ var GameVehiclesThree = (() => {
41067
42902
  impl: (root, id) => {
41068
42903
  const r = root;
41069
42904
  const kit = r.userData.kit;
41070
- const d = createVehicleDestructible(kit, r.userData.vehicle, { id, frame: root, name: text.items[itemId(key)] ?? key });
42905
+ const d = createVehicleDestructible(kit, r.userData.vehicle, { id, frame: root, name: text.items[itemKey] ?? key });
41071
42906
  tapEffects(d);
41072
42907
  r.userData.destructible = d;
41073
42908
  return d;
@@ -41094,7 +42929,7 @@ var GameVehiclesThree = (() => {
41094
42929
  for (const e of events) {
41095
42930
  const position = e.point ?? e.worldPoint;
41096
42931
  if (!position) continue;
41097
- if (e.type === "ignite") fx.play({ effect: effectIds.ignite, point: position });
42932
+ if (e.type === "ignite") fx.play({ effect: /fuel_tank|tank/.test(e.part ?? "") ? effectIds.leakIgnited : effectIds.ignite, point: position });
41098
42933
  else if (e.type === "explode") fx.play({ effect: effectIds.explode, point: position });
41099
42934
  else if (e.type === "leak") fx.play({ effect: effectIds.leak, point: position });
41100
42935
  else if (e.type === "fracture" && /glass|window|windshield/.test(e.part ?? "")) fx.play({ effect: effectIds.glass, point: position });
@@ -41127,12 +42962,12 @@ var GameVehiclesThree = (() => {
41127
42962
  const bounds = new three.Box3();
41128
42963
  const piece = new three.Box3();
41129
42964
  const matrix = new three.Matrix4();
41130
- entry.root.traverse((mesh) => {
41131
- if (!mesh.isMesh || !mesh.geometry || mesh.userData.ghost) return;
41132
- for (let p = mesh; p; p = p.parent) if (p.visible === false) return;
41133
- if (mesh.userData.helper) return;
41134
- mesh.geometry.computeBoundingBox();
41135
- piece.copy(mesh.geometry.boundingBox).applyMatrix4(matrix.multiplyMatrices(inverse, mesh.matrixWorld));
42965
+ entry.root.traverse((mesh2) => {
42966
+ if (!mesh2.isMesh || !mesh2.geometry || mesh2.userData.ghost) return;
42967
+ for (let p = mesh2; p; p = p.parent) if (p.visible === false) return;
42968
+ if (mesh2.userData.helper) return;
42969
+ mesh2.geometry.computeBoundingBox();
42970
+ piece.copy(mesh2.geometry.boundingBox).applyMatrix4(matrix.multiplyMatrices(inverse, mesh2.matrixWorld));
41136
42971
  bounds.union(piece);
41137
42972
  });
41138
42973
  const size = bounds.getSize(new three.Vector3());
@@ -41153,8 +42988,8 @@ var GameVehiclesThree = (() => {
41153
42988
  if (!host?.bench || !three) return;
41154
42989
  clearHelpers();
41155
42990
  const kit = [...placed.values()][0] && ([...placed.values()][0].root.userData.kit ?? void 0);
41156
- const mark = (entry, box, color) => {
41157
- const helper = new three.Box3Helper(box, color);
42991
+ const mark = (entry, box2, color2) => {
42992
+ const helper = new three.Box3Helper(box2, color2);
41158
42993
  helper.userData.helper = true;
41159
42994
  entry.root.add(helper);
41160
42995
  entry.helpers.push(helper);
@@ -41168,8 +43003,8 @@ var GameVehiclesThree = (() => {
41168
43003
  if (host.bench.layer("zones")) {
41169
43004
  for (const zone of entry.item.vehicle.zones ?? []) {
41170
43005
  if (!zone.box || zone.type === "internal") continue;
41171
- const box = new three.Box3(new three.Vector3(zone.box.x0, zone.box.y0, zone.box.z0), new three.Vector3(zone.box.x1, zone.box.y1, zone.box.z1)).applyMatrix4(matrix);
41172
- mark(entry, box, ZONE_COLOURS[zone.type] ?? 16777215);
43006
+ const box2 = new three.Box3(new three.Vector3(zone.box.x0, zone.box.y0, zone.box.z0), new three.Vector3(zone.box.x1, zone.box.y1, zone.box.z1)).applyMatrix4(matrix);
43007
+ mark(entry, box2, ZONE_COLOURS[zone.type] ?? 16777215);
41173
43008
  }
41174
43009
  }
41175
43010
  }
@@ -41318,11 +43153,11 @@ var GameVehiclesThree = (() => {
41318
43153
  let drawCalls = 0;
41319
43154
  let triangles = 0;
41320
43155
  for (const entry of placed.values()) {
41321
- entry.root.traverse((mesh) => {
41322
- if (!mesh.isMesh || mesh.userData.helper) return;
41323
- for (let p = mesh; p; p = p.parent) if (p.visible === false) return;
43156
+ entry.root.traverse((mesh2) => {
43157
+ if (!mesh2.isMesh || mesh2.userData.helper) return;
43158
+ for (let p = mesh2; p; p = p.parent) if (p.visible === false) return;
41324
43159
  drawCalls += 1;
41325
- const g = mesh.geometry;
43160
+ const g = mesh2.geometry;
41326
43161
  triangles += (g.index ? g.index.count : g.attributes.position.count) / 3;
41327
43162
  });
41328
43163
  }
@@ -41341,7 +43176,7 @@ var GameVehiclesThree = (() => {
41341
43176
  for (const entry of placed.values()) {
41342
43177
  const want = fleetDims(entry.key);
41343
43178
  const got = entry.size;
41344
- if (!want || !got) continue;
43179
+ if (!want || !got || entry.scenario) continue;
41345
43180
  worst = Math.max(worst, Math.abs(got.length - want.length), Math.abs(got.width - want.width), Math.abs(got.height - want.height));
41346
43181
  }
41347
43182
  return Math.round(worst * 1e3);
@@ -41353,23 +43188,23 @@ var GameVehiclesThree = (() => {
41353
43188
  get placed() {
41354
43189
  return placed;
41355
43190
  },
41356
- items: () => keys.map(item),
43191
+ items: () => entries.map(item),
41357
43192
  area: () => {
41358
43193
  const gap = 1.6;
41359
43194
  const WIDE = 6;
41360
- const rowOf = (list, z) => {
43195
+ const rowOf = (list2, z) => {
41361
43196
  let cursor = 0;
41362
- const spots = list.map((key) => {
41363
- const width = fleetDims(key)?.width ?? 2;
43197
+ const spots = list2.map((entry) => {
43198
+ const width = fleetDims(entry.key)?.width ?? 2;
41364
43199
  const x = cursor + width / 2;
41365
43200
  cursor += width + gap;
41366
- return { key, x };
43201
+ return { id: entry.id, x };
41367
43202
  });
41368
43203
  return { spots, z, width: Math.max(0, cursor - gap) };
41369
43204
  };
41370
- const front = rowOf(keys.filter((key) => (fleetDims(key)?.width ?? 2) <= WIDE), 0);
41371
- const back = rowOf(keys.filter((key) => (fleetDims(key)?.width ?? 2) > WIDE), -16);
41372
- const placements = [front, back].flatMap((row) => row.spots.map(({ key, x }) => ({ item: itemId(key), position: [x - row.width / 2, 0, row.z], rotationY: 0 })));
43205
+ const front = rowOf(entries.filter((e) => (fleetDims(e.key)?.width ?? 2) <= WIDE), 0);
43206
+ const back = rowOf(entries.filter((e) => (fleetDims(e.key)?.width ?? 2) > WIDE), -16);
43207
+ const placements = [front, back].flatMap((row) => row.spots.map(({ id, x }) => ({ item: id, position: [x - row.width / 2, 0, row.z], rotationY: 0 })));
41373
43208
  return { placements, view: { eye: [0, 5, Math.max(14, front.width * 0.6)], target: [0, 1, -2] } };
41374
43209
  },
41375
43210
  controls: () => {