@adatechnology/game-vehicles 0.6.2 → 0.6.4

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.
@@ -62,7 +62,7 @@ var GameVehicles = (() => {
62
62
  wrapThreeForLod: () => wrapThreeForLod
63
63
  });
64
64
 
65
- // ../game-shapes/dist/chunk-M5N2SHNL.js
65
+ // ../game-shapes/dist/chunk-FZQTELDQ.js
66
66
  function canonicalJson(value) {
67
67
  if (value === null) return "null";
68
68
  if (typeof value === "number") return Object.is(value, -0) ? "-0" : Number.isFinite(value) ? String(value) : JSON.stringify(String(value));
@@ -938,17 +938,19 @@ var GameVehicles = (() => {
938
938
  if (p.prevZ) p.prevZ.nextZ = p.nextZ;
939
939
  if (p.nextZ) p.nextZ.prevZ = p.prevZ;
940
940
  }
941
- function Node(i, x, y) {
942
- this.i = i;
943
- this.x = x;
944
- this.y = y;
945
- this.prev = null;
946
- this.next = null;
947
- this.z = 0;
948
- this.prevZ = null;
949
- this.nextZ = null;
950
- this.steiner = false;
951
- }
941
+ var Node = class {
942
+ constructor(i, x, y) {
943
+ this.i = i;
944
+ this.x = x;
945
+ this.y = y;
946
+ this.prev = null;
947
+ this.next = null;
948
+ this.z = 0;
949
+ this.prevZ = null;
950
+ this.nextZ = null;
951
+ this.steiner = false;
952
+ }
953
+ };
952
954
  function signedArea(data, start2, end, dim) {
953
955
  let sum = 0;
954
956
  for (let i = start2, j = end - dim; i < end; i += dim) {
@@ -2141,10 +2143,11 @@ var GameVehicles = (() => {
2141
2143
  return out;
2142
2144
  }
2143
2145
  function assignDeep(target, source) {
2146
+ const t = target;
2144
2147
  Object.keys(source || {}).forEach(function(k) {
2145
2148
  const v = source[k];
2146
- if (v && typeof v === "object" && !Array.isArray(v)) target[k] = assignDeep(target[k] && typeof target[k] === "object" ? target[k] : {}, v);
2147
- else if (v !== void 0) target[k] = v;
2149
+ if (v && typeof v === "object" && !Array.isArray(v)) t[k] = assignDeep(t[k] && typeof t[k] === "object" ? t[k] : {}, v);
2150
+ else if (v !== void 0) t[k] = v;
2148
2151
  });
2149
2152
  return target;
2150
2153
  }
@@ -2527,7 +2530,9 @@ var GameVehicles = (() => {
2527
2530
  return t;
2528
2531
  }
2529
2532
  kit.textTexture = textTexture;
2530
- Object.assign(I, { RUST, cache: cache2, studioEnvironment, makeMaterial, makeFlatMaterial, DOUBLE_SIDE, toColor, MATERIALS, paintColor, texCache, textTexture });
2533
+ const shared = { RUST, cache: cache2, studioEnvironment, makeMaterial, makeFlatMaterial, DOUBLE_SIDE, toColor, MATERIALS, paintColor, texCache, textTexture };
2534
+ Object.assign(I, shared);
2535
+ return shared;
2531
2536
  }
2532
2537
 
2533
2538
  // src/tri-index.ts
@@ -2682,7 +2687,8 @@ var GameVehicles = (() => {
2682
2687
  }
2683
2688
  return s;
2684
2689
  }
2685
- function indexable(THREE, mesh2) {
2690
+ function indexable(THREE, object2) {
2691
+ const mesh2 = object2;
2686
2692
  const geo = mesh2.geometry;
2687
2693
  if (mesh2.raycast !== THREE.Mesh.prototype.raycast) return false;
2688
2694
  if (!mesh2.isMesh || mesh2.isSkinnedMesh || mesh2.isInstancedMesh || mesh2.isBatchedMesh || !geo || !geo.isBufferGeometry) return false;
@@ -3281,21 +3287,23 @@ var GameVehicles = (() => {
3281
3287
  let wb = 0;
3282
3288
  segs.forEach(function(seg) {
3283
3289
  if (typeof seg[0] === "number") {
3290
+ const run = seg;
3284
3291
  for (let a = 0; a < names.length; a++) {
3285
3292
  const size = sizes[a];
3286
3293
  if (!idx) {
3287
- dst[a].set(arrs[a].subarray(seg[0] * 3 * size, seg[1] * 3 * size), w[a]);
3288
- w[a] += (seg[1] - seg[0]) * 3 * size;
3294
+ dst[a].set(arrs[a].subarray(run[0] * 3 * size, run[1] * 3 * size), w[a]);
3295
+ w[a] += (run[1] - run[0]) * 3 * size;
3289
3296
  continue;
3290
3297
  }
3291
- for (let f = seg[0] * 3; f < seg[1] * 3; f++) for (let q = 0; q < size; q++) dst[a][w[a]++] = arrs[a][idx[f] * size + q];
3298
+ for (let f = run[0] * 3; f < run[1] * 3; f++) for (let q = 0; q < size; q++) dst[a][w[a]++] = arrs[a][idx[f] * size + q];
3292
3299
  }
3293
3300
  if (boxesOut2 && ti) {
3294
- boxesOut2.set(ti.boxes.subarray(seg[0] * 6, seg[1] * 6), wb);
3295
- wb += (seg[1] - seg[0]) * 6;
3301
+ boxesOut2.set(ti.boxes.subarray(run[0] * 6, run[1] * 6), wb);
3302
+ wb += (run[1] - run[0]) * 6;
3296
3303
  }
3297
3304
  return;
3298
3305
  }
3306
+ ;
3299
3307
  seg.forEach(function(t) {
3300
3308
  if (boxesOut2) {
3301
3309
  for (let k = 0; k < 3; k++) {
@@ -3489,7 +3497,9 @@ var GameVehicles = (() => {
3489
3497
  }
3490
3498
  };
3491
3499
  };
3492
- Object.assign(I, { roundedBoxGeometry, taper, subdivide, crease, creaseTask, refreshBounds, pathShape, tumble, loftGeometry, hullGeometry, cutGeometry, mergeGeometries, uvProject });
3500
+ const shared = { roundedBoxGeometry, taper, subdivide, crease, creaseTask, refreshBounds, pathShape, tumble, loftGeometry, hullGeometry, cutGeometry, mergeGeometries, uvProject };
3501
+ Object.assign(I, shared);
3502
+ return shared;
3493
3503
  }
3494
3504
 
3495
3505
  // src/context.ts
@@ -3743,6 +3753,7 @@ var GameVehicles = (() => {
3743
3753
  }
3744
3754
  kit.BuildContext = BuildContext;
3745
3755
  I.BuildContext = BuildContext;
3756
+ return { resolveLabel, BuildContext };
3746
3757
  }
3747
3758
 
3748
3759
  // src/warp.ts
@@ -3938,7 +3949,9 @@ var GameVehicles = (() => {
3938
3949
  kit.applyWarp = applyWarp;
3939
3950
  kit.geo.resample = resample;
3940
3951
  kit.geo.smoothLoft = smoothLoft;
3941
- Object.assign(I, { makeWarp, applyWarp, resample, smoothLoft });
3952
+ const shared = { makeWarp, applyWarp, resample, smoothLoft };
3953
+ Object.assign(I, shared);
3954
+ return shared;
3942
3955
  }
3943
3956
 
3944
3957
  // src/body.ts
@@ -4004,23 +4017,24 @@ var GameVehicles = (() => {
4004
4017
  o.arches.forEach(function(a) {
4005
4018
  const a0 = Math.asin(clamp((o.bottomY - a[1]) / a[2], -1, 1));
4006
4019
  const rr = a[2] - 0.01;
4020
+ const archInner = o.archInner;
4007
4021
  if (o.archInner == null) {
4008
4022
  const wl = c.add(new THREE.CylinderGeometry(rr, rr, o.W - 0.12, 20, 1, true, a0 + PI / 2, PI - 2 * a0), MATERIALS.dark, a[0], a[1], 0);
4009
4023
  wl.rotation.x = PI / 2;
4010
4024
  wl.castShadow = false;
4011
4025
  } else
4012
4026
  [1, -1].forEach(function(s) {
4013
- const len = o.W / 2 - 0.06 - o.archInner;
4027
+ const len = o.W / 2 - 0.06 - archInner;
4014
4028
  const w2 = c.add(
4015
4029
  new THREE.CylinderGeometry(rr, rr, len, 20, 1, true, a0 + PI / 2, PI - 2 * a0),
4016
4030
  MATERIALS.dark,
4017
4031
  a[0],
4018
4032
  a[1],
4019
- s * (o.archInner + len / 2)
4033
+ s * (archInner + len / 2)
4020
4034
  );
4021
4035
  w2.rotation.x = PI / 2;
4022
4036
  w2.castShadow = false;
4023
- const cap = c.add(new THREE.CircleGeometry(rr, 20, a0, PI - 2 * a0), MATERIALS.dark, a[0], a[1], s * o.archInner);
4037
+ const cap = c.add(new THREE.CircleGeometry(rr, 20, a0, PI - 2 * a0), MATERIALS.dark, a[0], a[1], s * archInner);
4024
4038
  cap.castShadow = false;
4025
4039
  });
4026
4040
  });
@@ -4097,8 +4111,12 @@ var GameVehicles = (() => {
4097
4111
  if (!q.isMesh || !q.visible || q.userData.glass || q.userData.decal || q.isSprite) return;
4098
4112
  if (o.all || dset.has(q) || c.paints && c.paints.has(q.material)) cands.push(q);
4099
4113
  });
4100
- const d = (dir.isVector3 ? dir.clone() : new V3(dir[0], dir[1], dir[2])).normalize();
4101
- const p0 = org.isVector3 ? org.clone() : new V3(org[0], org[1], org[2]);
4114
+ const dv = dir;
4115
+ const da = dir;
4116
+ const d = (dv.isVector3 ? dv.clone() : new V3(da[0], da[1], da[2])).normalize();
4117
+ const ov = org;
4118
+ const oa = org;
4119
+ const p0 = ov.isVector3 ? ov.clone() : new V3(oa[0], oa[1], oa[2]);
4102
4120
  _sr.set(p0.clone().applyMatrix4(Mw), d.clone().transformDirection(Mw));
4103
4121
  _sr.near = 0;
4104
4122
  _sr.far = o.max || 20;
@@ -4115,7 +4133,9 @@ var GameVehicles = (() => {
4115
4133
  const h = kit.surfaceAt(c, new V3(x0, y, z || 0), new V3(-sg, 0, 0));
4116
4134
  return h ? h.p.x : items ? profX(items, y, front !== false) : null;
4117
4135
  };
4118
- Object.assign(I, { halfAt, shell, autoWindows, profX, _sr });
4136
+ const shared = { halfAt, shell, autoWindows, profX, _sr };
4137
+ Object.assign(I, shared);
4138
+ return shared;
4119
4139
  }
4120
4140
 
4121
4141
  // src/glass.ts
@@ -4124,7 +4144,8 @@ var GameVehicles = (() => {
4124
4144
  const V3 = THREE.Vector3;
4125
4145
  const I = kit._;
4126
4146
  const { MATERIALS, crease, cutGeometry, pathShape, subdivide, tumble, uvProject } = I;
4127
- I.paneSeals = /* @__PURE__ */ new WeakMap();
4147
+ const paneSeals = /* @__PURE__ */ new WeakMap();
4148
+ I.paneSeals = paneSeals;
4128
4149
  kit.addGlass = function(c, geo, label, type, o) {
4129
4150
  o = o || {};
4130
4151
  if (!geo.attributes.uv || o.reuv) o.aspect = uvProject(geo, o.uvAxes);
@@ -4221,7 +4242,7 @@ var GameVehicles = (() => {
4221
4242
  };
4222
4243
  kit.quadDef = function(pb, pt, Wg, T, which, bev, o) {
4223
4244
  o = o || {};
4224
- bev = bev == null ? 0.05 : bev;
4245
+ const bv = bev == null ? 0.05 : bev;
4225
4246
  const dx = pt[0] - pb[0];
4226
4247
  const dy = pt[1] - pb[1];
4227
4248
  const L = Math.hypot(dx, dy);
@@ -4230,13 +4251,13 @@ var GameVehicles = (() => {
4230
4251
  const nx = which === "front" ? uy : -uy;
4231
4252
  const ny = which === "front" ? -ux : ux;
4232
4253
  const ins = o.inset || 0.09;
4233
- const off = bev + 6e-3;
4254
+ const off = bv + 6e-3;
4234
4255
  const sd = o.side || 0.1;
4235
4256
  const b = [pb[0] + ux * ins + nx * off, pb[1] + uy * ins + ny * off];
4236
4257
  const t = [pt[0] - ux * ins * 1.3 + nx * off, pt[1] - uy * ins * 1.3 + ny * off];
4237
4258
  const hb = I.halfAt(Wg, T, b[1]) - sd;
4238
4259
  const ht = I.halfAt(Wg, T, t[1]) - sd;
4239
- return { pb, pt, L, u: [ux, uy], n: [nx, ny], ins, b, t, hb, ht, which, bev, Wg, T };
4260
+ return { pb, pt, L, u: [ux, uy], n: [nx, ny], ins, b, t, hb, ht, which, bev: bv, Wg, T };
4240
4261
  };
4241
4262
  kit.glassQuad = function(c, q, label, o) {
4242
4263
  o = o || {};
@@ -4290,7 +4311,9 @@ var GameVehicles = (() => {
4290
4311
  c.quads.push(q);
4291
4312
  return m;
4292
4313
  };
4293
- Object.assign(I, {});
4314
+ const shared = { paneSeals };
4315
+ Object.assign(I, shared);
4316
+ return shared;
4294
4317
  }
4295
4318
 
4296
4319
  // src/lights.ts
@@ -4627,7 +4650,9 @@ var GameVehicles = (() => {
4627
4650
  if (o.emblem !== false) kit.emblem(c, 0.05, st === "closed" ? h * 0.12 : 0, 0, Math.min(0.05, h * 0.3), g);
4628
4651
  return g;
4629
4652
  };
4630
- Object.assign(I, { lampGroup, gm, wedgeY, haloTex, glowTexture, haloMats, halo, lampKit });
4653
+ const shared = { lampGroup, gm, wedgeY, haloTex, glowTexture, haloMats, halo, lampKit };
4654
+ Object.assign(I, shared);
4655
+ return shared;
4631
4656
  }
4632
4657
 
4633
4658
  // src/interior.ts
@@ -4879,7 +4904,9 @@ var GameVehicles = (() => {
4879
4904
  c.roundBox(o.x0 - o.x1 + 1, 0.03, zi * 2, 0.01, MATERIALS.carpet, (o.x0 + o.x1) / 2, o.floor, 0);
4880
4905
  return n;
4881
4906
  };
4882
- Object.assign(I, { consoleBox });
4907
+ const shared = { consoleBox };
4908
+ Object.assign(I, shared);
4909
+ return shared;
4883
4910
  }
4884
4911
 
4885
4912
  // src/hood.ts
@@ -5274,7 +5301,9 @@ var GameVehicles = (() => {
5274
5301
  };
5275
5302
  return out;
5276
5303
  };
5277
- Object.assign(I, {});
5304
+ const shared = {};
5305
+ Object.assign(I, shared);
5306
+ return shared;
5278
5307
  }
5279
5308
 
5280
5309
  // src/car.ts
@@ -5632,7 +5661,9 @@ var GameVehicles = (() => {
5632
5661
  });
5633
5662
  return out;
5634
5663
  };
5635
- Object.assign(I, {});
5664
+ const shared = {};
5665
+ Object.assign(I, shared);
5666
+ return shared;
5636
5667
  }
5637
5668
 
5638
5669
  // src/trucks.ts
@@ -5777,7 +5808,9 @@ var GameVehicles = (() => {
5777
5808
  m.rear = rear;
5778
5809
  m.length = L;
5779
5810
  };
5780
- Object.assign(I, {});
5811
+ const shared = {};
5812
+ Object.assign(I, shared);
5813
+ return shared;
5781
5814
  }
5782
5815
 
5783
5816
  // src/wheels.ts
@@ -5916,7 +5949,9 @@ var GameVehicles = (() => {
5916
5949
  c.part("track", kit.t("parts.track", { s: z > 0 ? 1 : -1 }), tm, new V3((x0 + x1) / 2, 0.3, z), 1.4);
5917
5950
  return { mesh: tm, wheels: gs, sprocket: spr, idler: idl };
5918
5951
  };
5919
- Object.assign(I, {});
5952
+ const shared = {};
5953
+ Object.assign(I, shared);
5954
+ return shared;
5920
5955
  }
5921
5956
 
5922
5957
  // src/routed-particles.ts
@@ -6345,7 +6380,7 @@ var GameVehicles = (() => {
6345
6380
  }
6346
6381
  });
6347
6382
  }
6348
- Object.assign(I, {
6383
+ const shared = {
6349
6384
  PARTICLE_LIMIT,
6350
6385
  PARTICLE_GEOMETRIES,
6351
6386
  PARTICLE_MATERIALS,
@@ -6365,7 +6400,9 @@ var GameVehicles = (() => {
6365
6400
  burst,
6366
6401
  exhaustLook,
6367
6402
  tickEmit
6368
- });
6403
+ };
6404
+ Object.assign(I, shared);
6405
+ return shared;
6369
6406
  }
6370
6407
 
6371
6408
  // src/fluids.ts
@@ -6839,7 +6876,9 @@ var GameVehicles = (() => {
6839
6876
  }
6840
6877
  return n;
6841
6878
  };
6842
- Object.assign(I, { _fr, buildDrip, DOWNHILL, PN, puddleGeometry, rimGeometry, puddle, shapePuddle, updateFluids });
6879
+ const shared = { _fr, buildDrip, DOWNHILL, PN, puddleGeometry, rimGeometry, puddle, shapePuddle, updateFluids };
6880
+ Object.assign(I, shared);
6881
+ return shared;
6843
6882
  }
6844
6883
 
6845
6884
  // src/glass-damage.ts
@@ -7163,8 +7202,20 @@ var GameVehicles = (() => {
7163
7202
  if (!L || L.broken) return;
7164
7203
  L.broken = true;
7165
7204
  L.lens.forEach(function(m) {
7166
- m.visible = false;
7205
+ const rim = L.lensMaterial ? glassRim(m.geometry, c.rand) : null;
7206
+ if (!rim) {
7207
+ m.visible = false;
7208
+ return;
7209
+ }
7210
+ m.geometry.dispose();
7211
+ m.geometry = rim;
7212
+ m.material = MATERIALS.glassEdge;
7213
+ m.userData.lensRim = true;
7167
7214
  });
7215
+ if (L.lensMaterial)
7216
+ (L.reflector || []).forEach(function(m) {
7217
+ m.material = MATERIALS.broken;
7218
+ });
7168
7219
  L.inner.forEach(function(m) {
7169
7220
  m.material = MATERIALS.bulbBroken;
7170
7221
  });
@@ -7172,11 +7223,40 @@ var GameVehicles = (() => {
7172
7223
  h.visible = false;
7173
7224
  });
7174
7225
  const p = L.group ? L.group.position.clone() : L.inner[0] ? L.inner[0].position.clone() : new V3();
7175
- I.burst(c, "lens", c.toEffects(p), 10, { dir: c.dirToEffects(dir.clone().negate()), speed: 1.4, variant: L.tint === "red" ? "red" : "clear" });
7176
- I.burst(c, "plastic", c.toEffects(p), 2, { dir: c.dirToEffects(dir.clone().negate()), speed: 1 });
7226
+ const glass = L.lensMaterial !== "plastic";
7227
+ I.burst(c, "lens", c.toEffects(p), glass ? 10 : 5, { dir: c.dirToEffects(dir.clone().negate()), speed: glass ? 1.4 : 1.1, variant: L.tint === "red" ? "red" : "clear" });
7228
+ I.burst(c, "plastic", c.toEffects(p), glass ? 2 : 5, { dir: c.dirToEffects(dir.clone().negate()), speed: 1 });
7177
7229
  }
7178
7230
  kit.breakLight = breakLight;
7179
- Object.assign(I, { glassUV, drawWeb, crackGlass, glassRim, shatterGlass, hitGlass, breakLight });
7231
+ const crazedCache = /* @__PURE__ */ new Map();
7232
+ const CRAZED_OPACITY = 0.6;
7233
+ function crazed(material) {
7234
+ const known = crazedCache.get(material);
7235
+ if (known) return known;
7236
+ const m = I.crackLens(material).clone();
7237
+ m.opacity = Math.max(m.opacity ?? 1, CRAZED_OPACITY);
7238
+ m.transparent = true;
7239
+ m.userData.shared = true;
7240
+ crazedCache.set(material, m);
7241
+ return m;
7242
+ }
7243
+ function crackLight(c, L, dir, pierced) {
7244
+ if (!L || L.broken) return;
7245
+ if (!L.cracked) {
7246
+ L.cracked = true;
7247
+ for (const m of L.lens) if (m.material && !Array.isArray(m.material)) m.material = crazed(m.material);
7248
+ }
7249
+ const p = L.group ? L.group.position.clone() : L.inner[0] ? L.inner[0].position.clone() : new V3();
7250
+ I.burst(c, "lens", c.toEffects(p), 3, { dir: c.dirToEffects(dir.clone().negate()), speed: 0.9, variant: L.tint === "red" ? "red" : "clear" });
7251
+ if (!pierced || L.dark) return;
7252
+ L.dark = true;
7253
+ for (const m of L.inner) m.material = MATERIALS.bulbBroken;
7254
+ for (const h of L.halo ?? []) h.visible = false;
7255
+ }
7256
+ kit.crackLight = crackLight;
7257
+ const shared = { glassUV, drawWeb, crackGlass, glassRim, shatterGlass, hitGlass, breakLight, crackLight };
7258
+ Object.assign(I, shared);
7259
+ return shared;
7180
7260
  }
7181
7261
 
7182
7262
  // src/impact.ts
@@ -7650,7 +7730,7 @@ var GameVehicles = (() => {
7650
7730
  return hit;
7651
7731
  }
7652
7732
  kit.zoneImpact = zoneImpact;
7653
- Object.assign(I, {
7733
+ const shared = {
7654
7734
  dentField,
7655
7735
  hangBumper,
7656
7736
  tankFuel,
@@ -7666,7 +7746,9 @@ var GameVehicles = (() => {
7666
7746
  _pr,
7667
7747
  probe,
7668
7748
  zoneImpact
7669
- });
7749
+ };
7750
+ Object.assign(I, shared);
7751
+ return shared;
7670
7752
  }
7671
7753
 
7672
7754
  // src/explosion.ts
@@ -8051,7 +8133,9 @@ var GameVehicles = (() => {
8051
8133
  }
8052
8134
  }
8053
8135
  }
8054
- Object.assign(I, { BURNT, BURNT_RUB, boomMat, enginePos, fling, burnAll, bigBoomFx, detonate, tickBoom, tickFlying });
8136
+ const shared = { BURNT, BURNT_RUB, boomMat, enginePos, fling, burnAll, bigBoomFx, detonate, tickBoom, tickFlying };
8137
+ Object.assign(I, shared);
8138
+ return shared;
8055
8139
  }
8056
8140
 
8057
8141
  // src/rollover.ts
@@ -8253,7 +8337,8 @@ var GameVehicles = (() => {
8253
8337
  c.parts.forEach(function(p) {
8254
8338
  if (p.kind !== "rotor" && p.kind !== "tail_rotor" || !p.obj) return;
8255
8339
  const main = p.kind === "rotor";
8256
- p.obj.traverse(function(o) {
8340
+ p.obj.traverse(function(node) {
8341
+ const o = node;
8257
8342
  if (!o.isMesh || !o.visible) return;
8258
8343
  const bb = new THREE.Box3().setFromObject(o).applyMatrix4(inv);
8259
8344
  if (!main && bb.min.y >= -0.01) return;
@@ -8325,7 +8410,9 @@ var GameVehicles = (() => {
8325
8410
  if (p >= 1) finishRoll(c);
8326
8411
  }
8327
8412
  kit.rollContact = rollContact;
8328
- Object.assign(I, { rollMeshes, convexHull, rollContact, exactMinY, finishRoll, tickRoll });
8413
+ const shared = { rollMeshes, convexHull, rollContact, exactMinY, finishRoll, tickRoll };
8414
+ Object.assign(I, shared);
8415
+ return shared;
8329
8416
  }
8330
8417
 
8331
8418
  // src/tick.ts
@@ -8363,7 +8450,9 @@ var GameVehicles = (() => {
8363
8450
  c.hood.target = open ? c.hood.open : 0;
8364
8451
  return true;
8365
8452
  };
8366
- Object.assign(I, {});
8453
+ const shared = {};
8454
+ Object.assign(I, shared);
8455
+ return shared;
8367
8456
  }
8368
8457
 
8369
8458
  // src/armor.ts
@@ -8615,7 +8704,9 @@ var GameVehicles = (() => {
8615
8704
  }
8616
8705
  }
8617
8706
  kit.applyArmor = applyArmor;
8618
- Object.assign(I, { STEEL_MATERIAL, PLATE_MATERIALS, jerryCan, applyArmor });
8707
+ const shared = { STEEL_MATERIAL, PLATE_MATERIALS, jerryCan, applyArmor };
8708
+ Object.assign(I, shared);
8709
+ return shared;
8619
8710
  }
8620
8711
 
8621
8712
  // src/zone-core.ts
@@ -8634,8 +8725,8 @@ var GameVehicles = (() => {
8634
8725
  return { id: b.id, name: kit.t("bands." + b.id), min: b.min, health: b.health, color: b.color };
8635
8726
  });
8636
8727
  function bandOf(h) {
8637
- h = Math.round(clamp(h == null ? 100 : h, 0, 100));
8638
- for (let i = 0; i < BANDS.length; i++) if (h >= BANDS[i].min) return i;
8728
+ const v = Math.round(clamp(h == null ? 100 : h, 0, 100));
8729
+ for (let i = 0; i < BANDS.length; i++) if (v >= BANDS[i].min) return i;
8639
8730
  return 4;
8640
8731
  }
8641
8732
  kit.bands = BANDS;
@@ -8661,8 +8752,12 @@ var GameVehicles = (() => {
8661
8752
  z0: Math.min(b[4], b[5]),
8662
8753
  z1: Math.max(b[4], b[5])
8663
8754
  };
8664
- if (b.isBox3) return { x0: b.min.x, x1: b.max.x, y0: b.min.y, y1: b.max.y, z0: b.min.z, z1: b.max.z };
8665
- return { x0: b.x0, x1: b.x1, y0: b.y0, y1: b.y1, z0: b.z0, z1: b.z1 };
8755
+ if (b.isBox3) {
8756
+ const box2 = b;
8757
+ return { x0: box2.min.x, x1: box2.max.x, y0: box2.min.y, y1: box2.max.y, z0: box2.min.z, z1: box2.max.z };
8758
+ }
8759
+ const r = b;
8760
+ return { x0: r.x0, x1: r.x1, y0: r.y0, y1: r.y1, z0: r.z0, z1: r.z1 };
8666
8761
  }
8667
8762
  kit.normalizeBox = normalizeBox;
8668
8763
  function boxLo(B, a) {
@@ -8699,7 +8794,8 @@ var GameVehicles = (() => {
8699
8794
  const bb = new THREE.Box3();
8700
8795
  const tmp = new THREE.Box3();
8701
8796
  const M = new THREE.Matrix4();
8702
- o.traverse(function(x) {
8797
+ o.traverse(function(node) {
8798
+ const x = node;
8703
8799
  if (!x.isMesh || !x.geometry || !x.geometry.attributes.position || x.userData.decal) return;
8704
8800
  if (!x.geometry.boundingBox) x.geometry.computeBoundingBox();
8705
8801
  tmp.copy(x.geometry.boundingBox).applyMatrix4(M.multiplyMatrices(inv, x.matrixWorld));
@@ -8765,7 +8861,7 @@ var GameVehicles = (() => {
8765
8861
  for (let q = o; q && q !== c.vehicle; q = q.parent) if (q.visible === false) return false;
8766
8862
  return !!o;
8767
8863
  }
8768
- Object.assign(I, {
8864
+ const shared = {
8769
8865
  BANDS,
8770
8866
  bandOf,
8771
8867
  ZONE_WEIGHTS,
@@ -8788,7 +8884,9 @@ var GameVehicles = (() => {
8788
8884
  lightBoxOf,
8789
8885
  hideObj,
8790
8886
  shown
8791
- });
8887
+ };
8888
+ Object.assign(I, shared);
8889
+ return shared;
8792
8890
  }
8793
8891
 
8794
8892
  // src/zone-decals.ts
@@ -9073,7 +9171,10 @@ var GameVehicles = (() => {
9073
9171
  narrowTo(rc, q);
9074
9172
  }
9075
9173
  const hits = rc.intersectObjects(cands, false);
9076
- for (let i = 0; i < hits.length; i++) if (hits[i].object.proxyOf) hits[i].object = hits[i].object.proxyOf;
9174
+ for (let i = 0; i < hits.length; i++) {
9175
+ const proxyOf = hits[i].object.proxyOf;
9176
+ if (proxyOf) hits[i].object = proxyOf;
9177
+ }
9077
9178
  return hits;
9078
9179
  }
9079
9180
  function zoneCands(c, z, inv, glassToo) {
@@ -9274,7 +9375,7 @@ var GameVehicles = (() => {
9274
9375
  for (i = 0; i < (spec.tear || 0); i++) if (s = nx()) tears.push(tearDecal(c, s.p, s.n, 0.07 + R() * 0.06, R, s.obj));
9275
9376
  return S;
9276
9377
  }
9277
- Object.assign(I, {
9378
+ const shared = {
9278
9379
  dmat,
9279
9380
  DAMAGE_MATERIALS,
9280
9381
  _zq,
@@ -9295,7 +9396,9 @@ var GameVehicles = (() => {
9295
9396
  ribbonGeo,
9296
9397
  scratchDecal,
9297
9398
  zoneDecals
9298
- });
9399
+ };
9400
+ Object.assign(I, shared);
9401
+ return shared;
9299
9402
  }
9300
9403
 
9301
9404
  // src/zone-dent.ts
@@ -9653,7 +9756,9 @@ var GameVehicles = (() => {
9653
9756
  });
9654
9757
  return piv;
9655
9758
  }
9656
- Object.assign(I, { sm, subdivIn, dentTargets, zoneDent, cutPanel, pivotOf });
9759
+ const shared = { sm, subdivIn, dentTargets, zoneDent, cutPanel, pivotOf };
9760
+ Object.assign(I, shared);
9761
+ return shared;
9657
9762
  }
9658
9763
 
9659
9764
  // src/damage-panels.ts
@@ -10006,7 +10111,9 @@ var GameVehicles = (() => {
10006
10111
  const sgn = new V3().crossVectors(axisV, tangent).dot(outv) > 0 ? 1 : -1;
10007
10112
  piv.quaternion.setFromAxisAngle(axisV, sgn * (0.6 + R() * 0.3));
10008
10113
  }
10009
- Object.assign(I, { panelBand, roofOff, tailOff, followersIn, windowsOver, doorGap, mirrorHang, doorHang, lidHang, flapHang });
10114
+ const shared = { panelBand, roofOff, tailOff, followersIn, windowsOver, doorGap, mirrorHang, doorHang, lidHang, flapHang };
10115
+ Object.assign(I, shared);
10116
+ return shared;
10010
10117
  }
10011
10118
 
10012
10119
  // src/damage-parts.ts
@@ -10122,7 +10229,8 @@ var GameVehicles = (() => {
10122
10229
  }
10123
10230
  function tireMeshes(w) {
10124
10231
  const out = [];
10125
- w.traverse(function(o) {
10232
+ w.traverse(function(node) {
10233
+ const o = node;
10126
10234
  if (o.isMesh && o.material === MATERIALS.rubber) out.push(o);
10127
10235
  });
10128
10236
  return out;
@@ -10181,7 +10289,8 @@ var GameVehicles = (() => {
10181
10289
  c.zoneDrops.push({ x: w.position.x, z: w.position.z, d: r * 0.24 });
10182
10290
  } else if (b === 4) {
10183
10291
  let rr = 0;
10184
- w.traverse(function(o) {
10292
+ w.traverse(function(node) {
10293
+ const o = node;
10185
10294
  if (!o.isMesh || o.material === MATERIALS.rubber) return;
10186
10295
  if (!o.geometry.boundingSphere) o.geometry.computeBoundingSphere();
10187
10296
  const cc = o.geometry.boundingSphere.center.clone().applyMatrix4(o.matrix);
@@ -10389,7 +10498,8 @@ var GameVehicles = (() => {
10389
10498
  const xf = H.x0 + (H.x1 - H.x0) * (0.5 + R() * 0.1);
10390
10499
  const k = 0.55 + R() * 0.2;
10391
10500
  const v = new V3();
10392
- H.piv.children.forEach(function(msh) {
10501
+ H.piv.children.forEach(function(node) {
10502
+ const msh = node;
10393
10503
  if (!msh.isMesh) return;
10394
10504
  msh.updateMatrix();
10395
10505
  const M = msh.matrix;
@@ -10582,7 +10692,7 @@ var GameVehicles = (() => {
10582
10692
  });
10583
10693
  void K;
10584
10694
  }
10585
- Object.assign(I, {
10695
+ const shared = {
10586
10696
  glassPt,
10587
10697
  glassIn,
10588
10698
  glassBand,
@@ -10600,7 +10710,9 @@ var GameVehicles = (() => {
10600
10710
  bumperBand,
10601
10711
  partBand,
10602
10712
  bendAft
10603
- });
10713
+ };
10714
+ Object.assign(I, shared);
10715
+ return shared;
10604
10716
  }
10605
10717
 
10606
10718
  // src/zone-derive.ts
@@ -10623,7 +10735,8 @@ var GameVehicles = (() => {
10623
10735
  }
10624
10736
  function resolveObjs(c, list2, z) {
10625
10737
  const out = [];
10626
- (list2 || []).forEach(function(o) {
10738
+ (list2 || []).forEach(function(item) {
10739
+ const o = item;
10627
10740
  if (!o) return;
10628
10741
  if (typeof o === "string") {
10629
10742
  c.parts.forEach(function(p) {
@@ -10872,7 +10985,9 @@ var GameVehicles = (() => {
10872
10985
  return null;
10873
10986
  }
10874
10987
  kit.zoneOwner = ownerOf;
10875
- Object.assign(I, { parseDir, resolveObjs, deriveZones, carMap, zonesOf, ownerOf });
10988
+ const shared = { parseDir, resolveObjs, deriveZones, carMap, zonesOf, ownerOf };
10989
+ Object.assign(I, shared);
10990
+ return shared;
10876
10991
  }
10877
10992
 
10878
10993
  // src/zone-auto.ts
@@ -11667,7 +11782,9 @@ var GameVehicles = (() => {
11667
11782
  if (!wheelsDone) wheelZones(false);
11668
11783
  return Z;
11669
11784
  }
11670
- Object.assign(I, { autoZones });
11785
+ const shared = { autoZones };
11786
+ Object.assign(I, shared);
11787
+ return shared;
11671
11788
  }
11672
11789
 
11673
11790
  // src/zone-apply.ts
@@ -11878,7 +11995,9 @@ var GameVehicles = (() => {
11878
11995
  c.rand = R0;
11879
11996
  return c.zoneState;
11880
11997
  };
11881
- Object.assign(I, { fadePaint, abandonFx, burntFx, settleDrops });
11998
+ const shared = { fadePaint, abandonFx, burntFx, settleDrops };
11999
+ Object.assign(I, shared);
12000
+ return shared;
11882
12001
  }
11883
12002
 
11884
12003
  // src/scenarios.ts
@@ -12035,7 +12154,9 @@ var GameVehicles = (() => {
12035
12154
  }
12036
12155
  return { p, dir };
12037
12156
  };
12038
- Object.assign(I, { BODY_TYPES });
12157
+ const shared = { BODY_TYPES };
12158
+ Object.assign(I, shared);
12159
+ return shared;
12039
12160
  }
12040
12161
 
12041
12162
  // src/ui.ts
@@ -12192,7 +12313,8 @@ var GameVehicles = (() => {
12192
12313
  }
12193
12314
  g.addEventListener("click", pick);
12194
12315
  g.addEventListener("keydown", function(e) {
12195
- if (e.key === "Enter" || e.key === " ") {
12316
+ const key = e.key;
12317
+ if (key === "Enter" || key === " ") {
12196
12318
  e.preventDefault();
12197
12319
  pick();
12198
12320
  }
@@ -12205,7 +12327,7 @@ var GameVehicles = (() => {
12205
12327
  return kit.bands.map(function(B, i) {
12206
12328
  const b = el("button", null, B.name);
12207
12329
  b.type = "button";
12208
- b.dataset.b = i;
12330
+ b.dataset.b = String(i);
12209
12331
  b.style.setProperty("--band", B.color);
12210
12332
  b.addEventListener("click", function() {
12211
12333
  if (onPick) onPick(B.health, i);
@@ -12433,6 +12555,7 @@ var GameVehicles = (() => {
12433
12555
  hash,
12434
12556
  clamp,
12435
12557
  smooth,
12558
+ // filled by the modules below, each with the helpers it shares
12436
12559
  _: {}
12437
12560
  };
12438
12561
  kit.fuels = {};
@@ -12510,8 +12633,8 @@ var GameVehicles = (() => {
12510
12633
  fn.apply(kit, args);
12511
12634
  });
12512
12635
  };
12513
- kit.configure = function(o) {
12514
- o = o || {};
12636
+ kit.configure = function(cfg) {
12637
+ const o = cfg || {};
12515
12638
  if (o.bands)
12516
12639
  o.bands.forEach(function(b, i) {
12517
12640
  if (kit.bands[i] && b) Object.assign(kit.bands[i], b);
@@ -12547,7 +12670,8 @@ var GameVehicles = (() => {
12547
12670
  }
12548
12671
  ;
12549
12672
  ["impactStain", "defaultSplat", "defaultGroup", "damagedScenario"].forEach(function(k) {
12550
- if (o[k] !== void 0) kit.config[k] = o[k];
12673
+ const v = o[k];
12674
+ if (v !== void 0) kit.config[k] = v;
12551
12675
  });
12552
12676
  return kit;
12553
12677
  };
@@ -12726,6 +12850,8 @@ var GameVehicles = (() => {
12726
12850
  heli: ["battery", "alternator", "gearbox"]
12727
12851
  };
12728
12852
  var HITCH_CHANCE = { car: 30, truck: 60, bus: 0, tractor: 100, quad: 40, bike: 0, tank: 0, boat: 0, plane: 0, heli: 0 };
12853
+ var GLASS_LENS_HP = 320;
12854
+ var PLASTIC_LENS_HP = 900;
12729
12855
  var STEEL_KG_M2 = 7;
12730
12856
  var ALU_KG_M2 = 3.2;
12731
12857
  var kindOf = (c) => {
@@ -12883,7 +13009,9 @@ var GameVehicles = (() => {
12883
13009
  continue;
12884
13010
  }
12885
13011
  if (role === "light") {
12886
- add({ id, role, name: label, material: "glass", box: box2, mass: 1.2 + 4 * area3, hp: 320, zoneId: id, visual: true, tags: ["light", ...tags] });
13012
+ const lens = /^head/.test(id) ? spec.headlightLens ?? "polycarbonate" : "acrylic";
13013
+ const glassLens = lens === "glass";
13014
+ add({ id, role, name: label, material: glassLens ? "glass" : "plastic", box: box2, mass: 1.2 + 4 * area3, hp: glassLens ? GLASS_LENS_HP : PLASTIC_LENS_HP, zoneId: id, visual: true, tags: ["light", `lens_${lens}`, ...tags] });
12887
13015
  continue;
12888
13016
  }
12889
13017
  if (role === "bumper") {
@@ -13340,21 +13468,188 @@ var GameVehicles = (() => {
13340
13468
  mesh2.geometry = g;
13341
13469
  }
13342
13470
 
13471
+ // src/destructible/door-open.ts
13472
+ var STRIP_SMOOTH_DEG = 180;
13473
+ var SKIN_BAND = 0.05;
13474
+ var BODY_FACING = 0.5;
13475
+ var FIELDS = 4;
13476
+ var SEAM_THIN = 0.03;
13477
+ var SEAM_AT_EDGE = 0.04;
13478
+ var SEAM_TALL = 0.4;
13479
+ var SLIVER_AREA = 1e-10;
13480
+ function cutStripOverDoor(vehicleKit, params) {
13481
+ const kit = vehicleKit;
13482
+ const strip = params.strip;
13483
+ const toVehicle = params.toVehicle;
13484
+ const { x0, x1 } = params;
13485
+ const THREE = kit.THREE;
13486
+ const at = new THREE.Vector3();
13487
+ const along = (x, y, z) => at.set(x, y, z).applyMatrix4(toVehicle).x;
13488
+ const piece = (tests) => {
13489
+ const mesh2 = new THREE.Mesh(strip.geometry.clone(), strip.material);
13490
+ kit.cutMesh(mesh2, tests, STRIP_SMOOTH_DEG, {});
13491
+ return mesh2;
13492
+ };
13493
+ const over = piece([{ sdf: (x, y, z) => along(x, y, z) - x0 }, { sdf: (x, y, z) => x1 - along(x, y, z) }]);
13494
+ const after = piece([{ sdf: (x, y, z) => along(x, y, z) - x1 }]);
13495
+ kit.cutMesh(strip, [{ sdf: (x, y, z) => x0 - along(x, y, z) }], STRIP_SMOOTH_DEG, {});
13496
+ const joined = joinTriangles(THREE, strip.geometry, after.geometry);
13497
+ strip.geometry.dispose();
13498
+ after.geometry.dispose();
13499
+ strip.geometry = joined;
13500
+ return over;
13501
+ }
13502
+ function joinTriangles(THREE, first, second) {
13503
+ const a = first.index ? first.toNonIndexed() : first;
13504
+ const b = second.index ? second.toNonIndexed() : second;
13505
+ const flags = [...solidTriangles(THREE, a), ...solidTriangles(THREE, b)];
13506
+ const both = new THREE.BufferGeometry();
13507
+ for (const name of Object.keys(a.attributes)) {
13508
+ const p = a.getAttribute(name);
13509
+ const q = b.getAttribute(name);
13510
+ if (!q || q.itemSize !== p.itemSize) continue;
13511
+ const array = new Float32Array(p.array.length + q.array.length);
13512
+ array.set(p.array, 0);
13513
+ array.set(q.array, p.array.length);
13514
+ both.setAttribute(name, new THREE.Float32BufferAttribute(array, p.itemSize));
13515
+ }
13516
+ if (a !== first) a.dispose();
13517
+ if (b !== second) b.dispose();
13518
+ const out = pickTriangles(THREE, both, flags, true) ?? new THREE.BufferGeometry();
13519
+ both.dispose();
13520
+ return out;
13521
+ }
13522
+ function solidTriangles(THREE, geometry) {
13523
+ const pos = geometry.getAttribute("position");
13524
+ const triangle = new THREE.Triangle();
13525
+ const flags = [];
13526
+ for (let t = 0; t * 3 + 2 < pos.count; t++) {
13527
+ triangle.a.fromBufferAttribute(pos, t * 3);
13528
+ triangle.b.fromBufferAttribute(pos, t * 3 + 1);
13529
+ triangle.c.fromBufferAttribute(pos, t * 3 + 2);
13530
+ flags.push(triangle.getArea() > SLIVER_AREA);
13531
+ }
13532
+ return flags;
13533
+ }
13534
+ function splitDoorSkin(three, meshes, toVehicleOf, side2, depth) {
13535
+ const THREE = three;
13536
+ const pieces = meshes;
13537
+ const toVehicle = toVehicleOf;
13538
+ const v = new THREE.Vector3();
13539
+ const corners = [new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3()];
13540
+ const triangle = new THREE.Triangle();
13541
+ const centres = pieces.map((mesh2) => {
13542
+ const geometry = mesh2.geometry.index ? mesh2.geometry.toNonIndexed() : mesh2.geometry;
13543
+ const matrix = toVehicle(mesh2);
13544
+ const pos = geometry.getAttribute("position");
13545
+ const out = new Float32Array(pos.count / 3 * FIELDS);
13546
+ for (let t = 0; t * 3 + 2 < pos.count; t++) {
13547
+ let y = 0;
13548
+ let across = 0;
13549
+ for (let k = 0; k < 3; k++) {
13550
+ corners[k].fromBufferAttribute(pos, t * 3 + k).applyMatrix4(matrix);
13551
+ y += corners[k].y / 3;
13552
+ across += side2 * corners[k].z / 3;
13553
+ }
13554
+ out[t * FIELDS] = y;
13555
+ out[t * FIELDS + 1] = across;
13556
+ triangle.set(corners[0], corners[1], corners[2]).getNormal(v);
13557
+ out[t * FIELDS + 2] = v.y;
13558
+ out[t * FIELDS + 3] = v.x;
13559
+ }
13560
+ return { geometry, out };
13561
+ });
13562
+ const outer = /* @__PURE__ */ new Map();
13563
+ for (const { out } of centres)
13564
+ for (let t = 0; t * FIELDS < out.length; t++) {
13565
+ const band = Math.floor(out[t * FIELDS] / SKIN_BAND);
13566
+ outer.set(band, Math.max(outer.get(band) ?? -Infinity, out[t * FIELDS + 1]));
13567
+ }
13568
+ const surfaceAt = (y) => {
13569
+ const band = Math.floor(y / SKIN_BAND);
13570
+ return Math.max(outer.get(band - 1) ?? -Infinity, outer.get(band) ?? -Infinity, outer.get(band + 1) ?? -Infinity);
13571
+ };
13572
+ return centres.map(({ geometry, out }, i) => {
13573
+ const near = [];
13574
+ for (let t = 0; t * FIELDS < out.length; t++) {
13575
+ const f = t * FIELDS;
13576
+ const body = out[f + 1] < surfaceAt(out[f]) - depth && (out[f + 2] < -BODY_FACING || Math.abs(out[f + 3]) > BODY_FACING);
13577
+ near.push(!body);
13578
+ }
13579
+ const result = { skin: pickTriangles(THREE, geometry, near, true), deep: pickTriangles(THREE, geometry, near, false) };
13580
+ if (geometry !== pieces[i].geometry) geometry.dispose();
13581
+ return result;
13582
+ });
13583
+ }
13584
+ function leaveDeepSkinOnBody(three, meshes, params) {
13585
+ const THREE = three;
13586
+ const pieces = meshes;
13587
+ const toVehicle = params.toVehicle;
13588
+ const { side: side2, depth } = params;
13589
+ const split = splitDoorSkin(THREE, pieces, (mesh2) => new THREE.Matrix4().multiplyMatrices(toVehicle, mesh2.matrixWorld), side2, depth);
13590
+ split.forEach(({ skin, deep }, i) => {
13591
+ const piece = pieces[i];
13592
+ if (!deep || !skin || !piece.parent) return;
13593
+ const body = new THREE.Mesh(deep, piece.material);
13594
+ body.position.copy(piece.position);
13595
+ body.quaternion.copy(piece.quaternion);
13596
+ body.scale.copy(piece.scale);
13597
+ body.castShadow = piece.castShadow;
13598
+ body.receiveShadow = piece.receiveShadow;
13599
+ piece.parent.add(body);
13600
+ piece.geometry.dispose();
13601
+ piece.geometry = skin;
13602
+ });
13603
+ }
13604
+ function pickTriangles(THREE, geometry, flags, wanted) {
13605
+ const count = flags.filter((flag) => flag === wanted).length;
13606
+ if (!count) return null;
13607
+ const out = new THREE.BufferGeometry();
13608
+ for (const name of Object.keys(geometry.attributes)) {
13609
+ const attribute = geometry.getAttribute(name);
13610
+ const size = attribute.itemSize;
13611
+ const source = attribute.array;
13612
+ const array = new Float32Array(count * 3 * size);
13613
+ let w = 0;
13614
+ flags.forEach((flag, t) => {
13615
+ if (flag !== wanted) return;
13616
+ array.set(source.subarray(t * 3 * size, (t + 1) * 3 * size), w);
13617
+ w += 3 * size;
13618
+ });
13619
+ out.setAttribute(name, new THREE.Float32BufferAttribute(array, size));
13620
+ }
13621
+ out.computeBoundingBox();
13622
+ out.computeBoundingSphere();
13623
+ return out;
13624
+ }
13625
+ function isDoorSeam(three, params) {
13626
+ const THREE = three;
13627
+ const box2 = params.box;
13628
+ const { zone, side: side2, dark } = params;
13629
+ if (!dark || box2.isEmpty()) return false;
13630
+ const size = box2.getSize(new THREE.Vector3());
13631
+ const centre = box2.getCenter(new THREE.Vector3());
13632
+ if (Math.sign(centre.z) !== Math.sign(side2) || size.x > SEAM_THIN || size.z > SEAM_THIN || size.y < (zone.y1 - zone.y0) * SEAM_TALL) return false;
13633
+ if (centre.y < zone.y0 || centre.y > zone.y1) return false;
13634
+ return Math.abs(centre.x - zone.x0) < SEAM_AT_EDGE || Math.abs(centre.x - zone.x1) < SEAM_AT_EDGE;
13635
+ }
13636
+
13343
13637
  // src/destructible/visual.ts
13344
13638
  var HOLE_DECAL_SCALE = 2.4;
13345
13639
  var DOOR_DEPTH = 0.07;
13640
+ var DOOR_SKIN_DEPTH = 0.09;
13641
+ var DOOR_FLOOR_DEPTH = 0.2;
13346
13642
  var DOOR_EDGE_PIECES = 8;
13347
13643
  var DOOR_EDGE_REACH = 0.08;
13348
13644
  var DOOR_CARD_COLOR = "#3b3e42";
13349
13645
  var DOOR_LINER_COLOR = "#5a5e64";
13350
13646
  var DOOR_LINER_DARK = 0.15;
13351
- var DOOR_STRIP_THIN = 0.08;
13647
+ var DOOR_STRIP_THIN = 0.13;
13352
13648
  var DOOR_STRIP_NEAR = 0.04;
13353
13649
  var DOOR_STRIP_TALL = 0.22;
13354
- var STRIP_SMOOTH_DEG = 180;
13355
- var DOOR_STRIP_VERTICES = 2e4;
13650
+ var DOOR_STRIP_VERTICES = 6e4;
13356
13651
  var DOOR_SILL = 0.25;
13357
- var DOOR_STRIP_OVER = 0.3;
13652
+ var DOOR_STRIP_OVER = 0.05;
13358
13653
  var DOOR_TOP_OVER_PANE = 0.03;
13359
13654
  var HOLE_TEXTURE_SIZE = 64;
13360
13655
  var LAMINATED_HP = 1e3;
@@ -13463,6 +13758,10 @@ var GameVehicles = (() => {
13463
13758
  __publicField(this, "skins", /* @__PURE__ */ new Map());
13464
13759
  /** How high each door's cut reaches. */
13465
13760
  __publicField(this, "doorTops", /* @__PURE__ */ new Map());
13761
+ /** The shut lines drawn on the body at a door's edges, by line: the doors whose edge it marks. Shown only while all of them are closed. */
13762
+ __publicField(this, "seams", /* @__PURE__ */ new Map());
13763
+ /** Doors and lids standing open now. */
13764
+ __publicField(this, "openNow", /* @__PURE__ */ new Set());
13466
13765
  __publicField(this, "lightsOn", true);
13467
13766
  /** Heavy body meshes whose triangle index is still to build (null once done). */
13468
13767
  __publicField(this, "warming");
@@ -13644,6 +13943,11 @@ var GameVehicles = (() => {
13644
13943
  }
13645
13944
  panel.visible = open && !this.skins.get(id);
13646
13945
  recess.visible = open && !this.skins.get(id);
13946
+ if (open) this.openNow.add(id);
13947
+ else this.openNow.delete(id);
13948
+ this.seams.forEach((doors, seam) => {
13949
+ if (doors.has(id)) seam.visible = ![...doors].some((door) => this.openNow.has(door));
13950
+ });
13647
13951
  };
13648
13952
  const euler = piv.rotation;
13649
13953
  const quaternion = piv.quaternion;
@@ -13686,11 +13990,13 @@ var GameVehicles = (() => {
13686
13990
  const pcs = I.cutPanel(this.c, z, rect, true, dirty, { anyN: true }).map((x) => x.mesh).filter((m) => !!m);
13687
13991
  this.mend(dirty);
13688
13992
  if (pcs.length) {
13993
+ leaveDeepSkinOnBody(this.THREE, pcs, { toVehicle: inv, side: z.side < 0 ? -1 : 1, depth: DOOR_SKIN_DEPTH });
13689
13994
  const panes = I.windowsOver(this.c, z, inv);
13690
13995
  const seals = panes.map((g) => I.paneSeals.get(g)).filter((s) => !!s);
13691
13996
  const mirrors = this.mirrorsOn(z);
13692
13997
  const frames = this.framesAround(panes, inv);
13693
- objs = [...pcs, ...I.followersIn(this.c, z, inv), ...panes, ...seals, ...mirrors, ...frames];
13998
+ const followers = I.followersIn(this.c, z, inv).filter((o) => !this.takeSeam(o, id, z, inv) && !this.inFloor(o, piv, z, inv));
13999
+ objs = [...pcs, ...followers, ...panes, ...seals, ...mirrors, ...frames];
13694
14000
  }
13695
14001
  } else {
13696
14002
  const pcs = this.cutZone(z);
@@ -13718,6 +14024,25 @@ var GameVehicles = (() => {
13718
14024
  this.c.root.updateMatrixWorld(true);
13719
14025
  return objs.length > 0;
13720
14026
  }
14027
+ /** A thin part at the foot of the opening, well inside the skin (a step, a sill trim, a rail on the floor), is the floor's: it does not swing with the door. */
14028
+ inFloor(o, piv, z, inv) {
14029
+ const side2 = z.side < 0 ? -1 : 1;
14030
+ const centre = this.I.localBox(this.c, o, inv).getCenter(new this.THREE.Vector3());
14031
+ const skin = side2 * (piv.position.z - side2 * 0.016);
14032
+ return centre.y < z.box.y0 + DOOR_SILL && side2 * centre.z < skin - DOOR_FLOOR_DEPTH;
14033
+ }
14034
+ /** A shut line drawn at the door's edge stays on the body, hidden while a door it marks stands open; answers whether `o` is one. */
14035
+ takeSeam(o, id, z, inv) {
14036
+ const B = z.box;
14037
+ const box2 = this.I.localBox(this.c, o, inv);
14038
+ const color2 = o.material?.color;
14039
+ const dark = !!color2 && color2.getHSL({ h: 0, s: 0, l: 0 }).l < DOOR_LINER_DARK;
14040
+ if (!o.isMesh || !isDoorSeam(this.THREE, { box: box2, zone: { x0: B.x0, x1: B.x1, y0: B.y0, y1: B.y1 }, side: z.side, dark })) return false;
14041
+ const doors = this.seams.get(o) ?? /* @__PURE__ */ new Set();
14042
+ doors.add(id);
14043
+ this.seams.set(o, doors);
14044
+ return true;
14045
+ }
13721
14046
  /** A door has edges: a band that follows the skin all round closes it to its card and hides where the cut followed the triangles of the shell; the same band, in the same paint as on a real car, lines the opening. */
13722
14047
  doorEdges(piv, z, y1) {
13723
14048
  const THREE = this.THREE;
@@ -13739,13 +14064,15 @@ var GameVehicles = (() => {
13739
14064
  const at = this.surface("z", side2, B, [[x, y]]);
13740
14065
  return at != null && Math.abs(at - flat) < DOOR_EDGE_REACH ? at : flat;
13741
14066
  });
13742
- const band = (lift) => {
14067
+ const band = (lift, path, closed) => {
13743
14068
  const position = [];
13744
14069
  const index = [];
13745
- loop.forEach(([x, y], i) => {
13746
- position.push(x, y, heights[i] + side2 * lift, x, y, heights[i] + side2 * (lift - DOOR_DEPTH));
14070
+ path.forEach((at, i) => {
14071
+ const [x, y] = loop[at];
14072
+ position.push(x, y, heights[at] + side2 * lift, x, y, heights[at] + side2 * (lift - DOOR_DEPTH));
14073
+ if (!closed && i === path.length - 1) return;
13747
14074
  const a = i * 2;
13748
- const b = (i + 1) % loop.length * 2;
14075
+ const b = (i + 1) % path.length * 2;
13749
14076
  index.push(a, a + 1, b, b, a + 1, b + 1);
13750
14077
  });
13751
14078
  const g = new THREE.BufferGeometry();
@@ -13773,8 +14100,11 @@ var GameVehicles = (() => {
13773
14100
  card.castShadow = false;
13774
14101
  this.c.vehicle.add(card);
13775
14102
  piv.attach(card);
13776
- const edges = new THREE.Mesh(band(2e-3), paint);
13777
- const lining = new THREE.Mesh(band(2e-3), paint);
14103
+ const all = loop.map((_, i) => i);
14104
+ const top = 2 * DOOR_EDGE_PIECES;
14105
+ const sides = [...all.slice(3 * DOOR_EDGE_PIECES), ...all.slice(0, top + 1)];
14106
+ const edges = new THREE.Mesh(band(2e-3, all, true), paint);
14107
+ const lining = new THREE.Mesh(band(2e-3, sides, false), paint);
13778
14108
  for (const m of [edges, lining]) {
13779
14109
  m.userData.noFollow = true;
13780
14110
  m.castShadow = false;
@@ -13831,26 +14161,14 @@ var GameVehicles = (() => {
13831
14161
  const box2 = this.I.localBox(this.c, o, inv);
13832
14162
  const size = box2.getSize(new THREE.Vector3());
13833
14163
  const mid = box2.getCenter(new THREE.Vector3());
13834
- if (Math.sign(mid.z) !== Math.sign(z.side) || size.z > DOOR_STRIP_THIN || size.y > DOOR_STRIP_TALL || Math.min(box2.max.x, x1) - Math.max(box2.min.x, x0) < (x1 - x0) * DOOR_STRIP_OVER || mid.y < y0 || mid.y > y1) continue;
14164
+ if (Math.sign(mid.z) !== Math.sign(z.side) || size.z > DOOR_STRIP_THIN || size.y > DOOR_STRIP_TALL || Math.min(box2.max.x, x1) - Math.max(box2.min.x, x0) < DOOR_STRIP_OVER || mid.y < y0 || mid.y > y1) continue;
13835
14165
  const toVehicle = new THREE.Matrix4().multiplyMatrices(inv, o.matrixWorld);
13836
- const v = new THREE.Vector3();
13837
- const sdf = (x, y, zz) => {
13838
- v.set(x, y, zz).applyMatrix4(toVehicle);
13839
- return Math.max(x0 - v.x, v.x - x1);
13840
- };
13841
- const over = new THREE.Mesh(o.geometry.clone(), o.material);
14166
+ const over = cutStripOverDoor(this.kit, { strip: o, toVehicle, x0, x1 });
13842
14167
  over.position.copy(o.position);
13843
14168
  over.quaternion.copy(o.quaternion);
13844
14169
  over.scale.copy(o.scale);
13845
14170
  this.c.vehicle.add(over);
13846
14171
  over.updateMatrixWorld(true);
13847
- const overToVehicle = new THREE.Matrix4().multiplyMatrices(inv, over.matrixWorld);
13848
- const w = new THREE.Vector3();
13849
- this.kit.cutMesh(over, [{ sdf: (x, y, zz) => {
13850
- w.set(x, y, zz).applyMatrix4(overToVehicle);
13851
- return -Math.max(x0 - w.x, w.x - x1);
13852
- } }], STRIP_SMOOTH_DEG, {});
13853
- this.kit.cutMesh(o, [{ sdf }], STRIP_SMOOTH_DEG, {});
13854
14172
  over.userData.noFollow = true;
13855
14173
  piv.attach(over);
13856
14174
  }
@@ -14431,11 +14749,18 @@ var GameVehicles = (() => {
14431
14749
  }
14432
14750
  }
14433
14751
  }
14752
+ /** The lens of a light is holed or cracked and stays; `pierced`: a round went through it to the bulb, and the lamp goes dark. */
14753
+ crackLight(p, pierced) {
14754
+ const z = this.zone(p);
14755
+ if (!z) return;
14756
+ for (const L of z.lights) this.kit.crackLight(this.c, L, new this.THREE.Vector3(p.box.center[0] > 0 ? -1 : 1, 0, 0), pierced);
14757
+ }
14434
14758
  /** The lens of a light breaks and its unit stays (damaged) or goes (destroyed). */
14435
14759
  breakLight(p, gone) {
14436
14760
  const z = this.zone(p);
14437
14761
  if (!z) return;
14438
14762
  for (const L of z.lights) {
14763
+ L.lensMaterial = p.material;
14439
14764
  this.kit.breakLight(this.c, L, new this.THREE.Vector3(p.box.center[0] > 0 ? -1 : 1, 0, 0));
14440
14765
  if (gone) {
14441
14766
  if (L.group) L.group.visible = false;
@@ -15081,6 +15406,7 @@ var GameVehicles = (() => {
15081
15406
  wear(p, amount, out);
15082
15407
  syncZone(p);
15083
15408
  if (p.hp <= 0) lose(p, "broken", out, cause);
15409
+ else if (p.def.role === "light") vis?.crackLight(p.def, dtype === "ballistic");
15084
15410
  if (p.def.role === "tyre" && !p.flat && p.hp < p.def.hp * 0.6 && !p.lost) {
15085
15411
  p.flat = true;
15086
15412
  vis?.tyreFlat(p.def, 0.24);
@@ -15893,7 +16219,7 @@ var GameVehicles = (() => {
15893
16219
  if (!list2.length) return 1;
15894
16220
  return Math.min(...list2.map((p) => p.lost || !attached(p.def.id) ? 0 : p.hp / p.def.hp));
15895
16221
  };
15896
- const tyres = [...ps.values()].filter((p) => p.def.role === "tyre").map((p) => ({ x: p.def.box.center[0], z: p.def.box.center[2], health: tyreHealth(p) }));
16222
+ const tyres = [...ps.values()].filter((p) => p.def.role === "tyre").map((p) => ({ x: p.def.box.center[0], z: p.def.box.center[2], health: tyreHealth(p), rim: p.lost }));
15897
16223
  const status = computeStatus();
15898
16224
  const brakeSystem = [...ps.values()].find((p) => p.def.role === "brakes" && p.def.contains);
15899
16225
  const fluidLeft = brakeSystem ? clamp((brakeSystem.liters ?? 0) / brakeSystem.def.contains.liters / BRAKE_FLUID_NEEDED, 0, 1) : 1;