@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.
- package/dist/index.d.ts +1293 -97
- package/dist/index.global.js +434 -108
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +420 -96
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -445,10 +445,11 @@ function merge(base, extra) {
|
|
|
445
445
|
return out;
|
|
446
446
|
}
|
|
447
447
|
function assignDeep(target, source) {
|
|
448
|
+
const t = target;
|
|
448
449
|
Object.keys(source || {}).forEach(function(k) {
|
|
449
450
|
const v = source[k];
|
|
450
|
-
if (v && typeof v === "object" && !Array.isArray(v))
|
|
451
|
-
else if (v !== void 0)
|
|
451
|
+
if (v && typeof v === "object" && !Array.isArray(v)) t[k] = assignDeep(t[k] && typeof t[k] === "object" ? t[k] : {}, v);
|
|
452
|
+
else if (v !== void 0) t[k] = v;
|
|
452
453
|
});
|
|
453
454
|
return target;
|
|
454
455
|
}
|
|
@@ -831,7 +832,9 @@ function installMaterials(kit) {
|
|
|
831
832
|
return t;
|
|
832
833
|
}
|
|
833
834
|
kit.textTexture = textTexture;
|
|
834
|
-
|
|
835
|
+
const shared = { RUST, cache: cache2, studioEnvironment, makeMaterial, makeFlatMaterial, DOUBLE_SIDE, toColor, MATERIALS, paintColor, texCache, textTexture };
|
|
836
|
+
Object.assign(I, shared);
|
|
837
|
+
return shared;
|
|
835
838
|
}
|
|
836
839
|
|
|
837
840
|
// src/tri-index.ts
|
|
@@ -986,7 +989,8 @@ function scratchOf(THREE) {
|
|
|
986
989
|
}
|
|
987
990
|
return s;
|
|
988
991
|
}
|
|
989
|
-
function indexable(THREE,
|
|
992
|
+
function indexable(THREE, object) {
|
|
993
|
+
const mesh = object;
|
|
990
994
|
const geo = mesh.geometry;
|
|
991
995
|
if (mesh.raycast !== THREE.Mesh.prototype.raycast) return false;
|
|
992
996
|
if (!mesh.isMesh || mesh.isSkinnedMesh || mesh.isInstancedMesh || mesh.isBatchedMesh || !geo || !geo.isBufferGeometry) return false;
|
|
@@ -1585,21 +1589,23 @@ function installGeometry(kit) {
|
|
|
1585
1589
|
let wb = 0;
|
|
1586
1590
|
segs.forEach(function(seg) {
|
|
1587
1591
|
if (typeof seg[0] === "number") {
|
|
1592
|
+
const run = seg;
|
|
1588
1593
|
for (let a = 0; a < names.length; a++) {
|
|
1589
1594
|
const size = sizes[a];
|
|
1590
1595
|
if (!idx) {
|
|
1591
|
-
dst[a].set(arrs[a].subarray(
|
|
1592
|
-
w[a] += (
|
|
1596
|
+
dst[a].set(arrs[a].subarray(run[0] * 3 * size, run[1] * 3 * size), w[a]);
|
|
1597
|
+
w[a] += (run[1] - run[0]) * 3 * size;
|
|
1593
1598
|
continue;
|
|
1594
1599
|
}
|
|
1595
|
-
for (let f =
|
|
1600
|
+
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];
|
|
1596
1601
|
}
|
|
1597
1602
|
if (boxesOut2 && ti) {
|
|
1598
|
-
boxesOut2.set(ti.boxes.subarray(
|
|
1599
|
-
wb += (
|
|
1603
|
+
boxesOut2.set(ti.boxes.subarray(run[0] * 6, run[1] * 6), wb);
|
|
1604
|
+
wb += (run[1] - run[0]) * 6;
|
|
1600
1605
|
}
|
|
1601
1606
|
return;
|
|
1602
1607
|
}
|
|
1608
|
+
;
|
|
1603
1609
|
seg.forEach(function(t) {
|
|
1604
1610
|
if (boxesOut2) {
|
|
1605
1611
|
for (let k = 0; k < 3; k++) {
|
|
@@ -1793,7 +1799,9 @@ function installGeometry(kit) {
|
|
|
1793
1799
|
}
|
|
1794
1800
|
};
|
|
1795
1801
|
};
|
|
1796
|
-
|
|
1802
|
+
const shared = { roundedBoxGeometry, taper, subdivide, crease, creaseTask, refreshBounds, pathShape, tumble, loftGeometry, hullGeometry, cutGeometry, mergeGeometries, uvProject };
|
|
1803
|
+
Object.assign(I, shared);
|
|
1804
|
+
return shared;
|
|
1797
1805
|
}
|
|
1798
1806
|
|
|
1799
1807
|
// src/context.ts
|
|
@@ -2048,6 +2056,7 @@ function installContext(kit) {
|
|
|
2048
2056
|
}
|
|
2049
2057
|
kit.BuildContext = BuildContext;
|
|
2050
2058
|
I.BuildContext = BuildContext;
|
|
2059
|
+
return { resolveLabel, BuildContext };
|
|
2051
2060
|
}
|
|
2052
2061
|
|
|
2053
2062
|
// src/warp.ts
|
|
@@ -2243,7 +2252,9 @@ function installWarp(kit) {
|
|
|
2243
2252
|
kit.applyWarp = applyWarp;
|
|
2244
2253
|
kit.geo.resample = resample;
|
|
2245
2254
|
kit.geo.smoothLoft = smoothLoft;
|
|
2246
|
-
|
|
2255
|
+
const shared = { makeWarp, applyWarp, resample, smoothLoft };
|
|
2256
|
+
Object.assign(I, shared);
|
|
2257
|
+
return shared;
|
|
2247
2258
|
}
|
|
2248
2259
|
|
|
2249
2260
|
// src/body.ts
|
|
@@ -2309,23 +2320,24 @@ function installBody(kit) {
|
|
|
2309
2320
|
o.arches.forEach(function(a) {
|
|
2310
2321
|
const a0 = Math.asin(clamp((o.bottomY - a[1]) / a[2], -1, 1));
|
|
2311
2322
|
const rr = a[2] - 0.01;
|
|
2323
|
+
const archInner = o.archInner;
|
|
2312
2324
|
if (o.archInner == null) {
|
|
2313
2325
|
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);
|
|
2314
2326
|
wl.rotation.x = PI / 2;
|
|
2315
2327
|
wl.castShadow = false;
|
|
2316
2328
|
} else
|
|
2317
2329
|
[1, -1].forEach(function(s) {
|
|
2318
|
-
const len = o.W / 2 - 0.06 -
|
|
2330
|
+
const len = o.W / 2 - 0.06 - archInner;
|
|
2319
2331
|
const w2 = c.add(
|
|
2320
2332
|
new THREE.CylinderGeometry(rr, rr, len, 20, 1, true, a0 + PI / 2, PI - 2 * a0),
|
|
2321
2333
|
MATERIALS.dark,
|
|
2322
2334
|
a[0],
|
|
2323
2335
|
a[1],
|
|
2324
|
-
s * (
|
|
2336
|
+
s * (archInner + len / 2)
|
|
2325
2337
|
);
|
|
2326
2338
|
w2.rotation.x = PI / 2;
|
|
2327
2339
|
w2.castShadow = false;
|
|
2328
|
-
const cap = c.add(new THREE.CircleGeometry(rr, 20, a0, PI - 2 * a0), MATERIALS.dark, a[0], a[1], s *
|
|
2340
|
+
const cap = c.add(new THREE.CircleGeometry(rr, 20, a0, PI - 2 * a0), MATERIALS.dark, a[0], a[1], s * archInner);
|
|
2329
2341
|
cap.castShadow = false;
|
|
2330
2342
|
});
|
|
2331
2343
|
});
|
|
@@ -2402,8 +2414,12 @@ function installBody(kit) {
|
|
|
2402
2414
|
if (!q.isMesh || !q.visible || q.userData.glass || q.userData.decal || q.isSprite) return;
|
|
2403
2415
|
if (o.all || dset.has(q) || c.paints && c.paints.has(q.material)) cands.push(q);
|
|
2404
2416
|
});
|
|
2405
|
-
const
|
|
2406
|
-
const
|
|
2417
|
+
const dv = dir;
|
|
2418
|
+
const da = dir;
|
|
2419
|
+
const d = (dv.isVector3 ? dv.clone() : new V3(da[0], da[1], da[2])).normalize();
|
|
2420
|
+
const ov = org;
|
|
2421
|
+
const oa = org;
|
|
2422
|
+
const p0 = ov.isVector3 ? ov.clone() : new V3(oa[0], oa[1], oa[2]);
|
|
2407
2423
|
_sr.set(p0.clone().applyMatrix4(Mw), d.clone().transformDirection(Mw));
|
|
2408
2424
|
_sr.near = 0;
|
|
2409
2425
|
_sr.far = o.max || 20;
|
|
@@ -2420,7 +2436,9 @@ function installBody(kit) {
|
|
|
2420
2436
|
const h = kit.surfaceAt(c, new V3(x0, y, z || 0), new V3(-sg, 0, 0));
|
|
2421
2437
|
return h ? h.p.x : items ? profX(items, y, front !== false) : null;
|
|
2422
2438
|
};
|
|
2423
|
-
|
|
2439
|
+
const shared = { halfAt, shell, autoWindows, profX, _sr };
|
|
2440
|
+
Object.assign(I, shared);
|
|
2441
|
+
return shared;
|
|
2424
2442
|
}
|
|
2425
2443
|
|
|
2426
2444
|
// src/glass.ts
|
|
@@ -2429,7 +2447,8 @@ function installGlass(kit) {
|
|
|
2429
2447
|
const V3 = THREE.Vector3;
|
|
2430
2448
|
const I = kit._;
|
|
2431
2449
|
const { MATERIALS, crease, cutGeometry, pathShape, subdivide, tumble, uvProject } = I;
|
|
2432
|
-
|
|
2450
|
+
const paneSeals = /* @__PURE__ */ new WeakMap();
|
|
2451
|
+
I.paneSeals = paneSeals;
|
|
2433
2452
|
kit.addGlass = function(c, geo, label, type, o) {
|
|
2434
2453
|
o = o || {};
|
|
2435
2454
|
if (!geo.attributes.uv || o.reuv) o.aspect = uvProject(geo, o.uvAxes);
|
|
@@ -2526,7 +2545,7 @@ function installGlass(kit) {
|
|
|
2526
2545
|
};
|
|
2527
2546
|
kit.quadDef = function(pb, pt, Wg, T, which, bev, o) {
|
|
2528
2547
|
o = o || {};
|
|
2529
|
-
|
|
2548
|
+
const bv = bev == null ? 0.05 : bev;
|
|
2530
2549
|
const dx = pt[0] - pb[0];
|
|
2531
2550
|
const dy = pt[1] - pb[1];
|
|
2532
2551
|
const L = Math.hypot(dx, dy);
|
|
@@ -2535,13 +2554,13 @@ function installGlass(kit) {
|
|
|
2535
2554
|
const nx = which === "front" ? uy : -uy;
|
|
2536
2555
|
const ny = which === "front" ? -ux : ux;
|
|
2537
2556
|
const ins = o.inset || 0.09;
|
|
2538
|
-
const off =
|
|
2557
|
+
const off = bv + 6e-3;
|
|
2539
2558
|
const sd = o.side || 0.1;
|
|
2540
2559
|
const b = [pb[0] + ux * ins + nx * off, pb[1] + uy * ins + ny * off];
|
|
2541
2560
|
const t = [pt[0] - ux * ins * 1.3 + nx * off, pt[1] - uy * ins * 1.3 + ny * off];
|
|
2542
2561
|
const hb = I.halfAt(Wg, T, b[1]) - sd;
|
|
2543
2562
|
const ht = I.halfAt(Wg, T, t[1]) - sd;
|
|
2544
|
-
return { pb, pt, L, u: [ux, uy], n: [nx, ny], ins, b, t, hb, ht, which, bev, Wg, T };
|
|
2563
|
+
return { pb, pt, L, u: [ux, uy], n: [nx, ny], ins, b, t, hb, ht, which, bev: bv, Wg, T };
|
|
2545
2564
|
};
|
|
2546
2565
|
kit.glassQuad = function(c, q, label, o) {
|
|
2547
2566
|
o = o || {};
|
|
@@ -2595,7 +2614,9 @@ function installGlass(kit) {
|
|
|
2595
2614
|
c.quads.push(q);
|
|
2596
2615
|
return m;
|
|
2597
2616
|
};
|
|
2598
|
-
|
|
2617
|
+
const shared = { paneSeals };
|
|
2618
|
+
Object.assign(I, shared);
|
|
2619
|
+
return shared;
|
|
2599
2620
|
}
|
|
2600
2621
|
|
|
2601
2622
|
// src/lights.ts
|
|
@@ -2932,7 +2953,9 @@ function installLights(kit) {
|
|
|
2932
2953
|
if (o.emblem !== false) kit.emblem(c, 0.05, st === "closed" ? h * 0.12 : 0, 0, Math.min(0.05, h * 0.3), g);
|
|
2933
2954
|
return g;
|
|
2934
2955
|
};
|
|
2935
|
-
|
|
2956
|
+
const shared = { lampGroup, gm, wedgeY, haloTex, glowTexture, haloMats, halo, lampKit };
|
|
2957
|
+
Object.assign(I, shared);
|
|
2958
|
+
return shared;
|
|
2936
2959
|
}
|
|
2937
2960
|
|
|
2938
2961
|
// src/interior.ts
|
|
@@ -3184,7 +3207,9 @@ function installInterior(kit) {
|
|
|
3184
3207
|
c.roundBox(o.x0 - o.x1 + 1, 0.03, zi * 2, 0.01, MATERIALS.carpet, (o.x0 + o.x1) / 2, o.floor, 0);
|
|
3185
3208
|
return n;
|
|
3186
3209
|
};
|
|
3187
|
-
|
|
3210
|
+
const shared = { consoleBox };
|
|
3211
|
+
Object.assign(I, shared);
|
|
3212
|
+
return shared;
|
|
3188
3213
|
}
|
|
3189
3214
|
|
|
3190
3215
|
// src/hood.ts
|
|
@@ -3579,7 +3604,9 @@ function installHood(kit) {
|
|
|
3579
3604
|
};
|
|
3580
3605
|
return out;
|
|
3581
3606
|
};
|
|
3582
|
-
|
|
3607
|
+
const shared = {};
|
|
3608
|
+
Object.assign(I, shared);
|
|
3609
|
+
return shared;
|
|
3583
3610
|
}
|
|
3584
3611
|
|
|
3585
3612
|
// src/car.ts
|
|
@@ -3937,7 +3964,9 @@ function installCar(kit) {
|
|
|
3937
3964
|
});
|
|
3938
3965
|
return out;
|
|
3939
3966
|
};
|
|
3940
|
-
|
|
3967
|
+
const shared = {};
|
|
3968
|
+
Object.assign(I, shared);
|
|
3969
|
+
return shared;
|
|
3941
3970
|
}
|
|
3942
3971
|
|
|
3943
3972
|
// src/trucks.ts
|
|
@@ -4082,7 +4111,9 @@ function installTrucks(kit) {
|
|
|
4082
4111
|
m.rear = rear;
|
|
4083
4112
|
m.length = L;
|
|
4084
4113
|
};
|
|
4085
|
-
|
|
4114
|
+
const shared = {};
|
|
4115
|
+
Object.assign(I, shared);
|
|
4116
|
+
return shared;
|
|
4086
4117
|
}
|
|
4087
4118
|
|
|
4088
4119
|
// src/wheels.ts
|
|
@@ -4221,7 +4252,9 @@ function installWheels(kit) {
|
|
|
4221
4252
|
c.part("track", kit.t("parts.track", { s: z > 0 ? 1 : -1 }), tm, new V3((x0 + x1) / 2, 0.3, z), 1.4);
|
|
4222
4253
|
return { mesh: tm, wheels: gs, sprocket: spr, idler: idl };
|
|
4223
4254
|
};
|
|
4224
|
-
|
|
4255
|
+
const shared = {};
|
|
4256
|
+
Object.assign(I, shared);
|
|
4257
|
+
return shared;
|
|
4225
4258
|
}
|
|
4226
4259
|
|
|
4227
4260
|
// src/particles.ts
|
|
@@ -4653,7 +4686,7 @@ function installParticles(kit) {
|
|
|
4653
4686
|
}
|
|
4654
4687
|
});
|
|
4655
4688
|
}
|
|
4656
|
-
|
|
4689
|
+
const shared = {
|
|
4657
4690
|
PARTICLE_LIMIT,
|
|
4658
4691
|
PARTICLE_GEOMETRIES,
|
|
4659
4692
|
PARTICLE_MATERIALS,
|
|
@@ -4673,7 +4706,9 @@ function installParticles(kit) {
|
|
|
4673
4706
|
burst,
|
|
4674
4707
|
exhaustLook,
|
|
4675
4708
|
tickEmit
|
|
4676
|
-
}
|
|
4709
|
+
};
|
|
4710
|
+
Object.assign(I, shared);
|
|
4711
|
+
return shared;
|
|
4677
4712
|
}
|
|
4678
4713
|
|
|
4679
4714
|
// src/fluids.ts
|
|
@@ -5147,7 +5182,9 @@ function installFluids(kit) {
|
|
|
5147
5182
|
}
|
|
5148
5183
|
return n;
|
|
5149
5184
|
};
|
|
5150
|
-
|
|
5185
|
+
const shared = { _fr, buildDrip, DOWNHILL, PN, puddleGeometry, rimGeometry, puddle, shapePuddle, updateFluids };
|
|
5186
|
+
Object.assign(I, shared);
|
|
5187
|
+
return shared;
|
|
5151
5188
|
}
|
|
5152
5189
|
|
|
5153
5190
|
// src/glass-damage.ts
|
|
@@ -5471,8 +5508,20 @@ function installGlassDamage(kit) {
|
|
|
5471
5508
|
if (!L || L.broken) return;
|
|
5472
5509
|
L.broken = true;
|
|
5473
5510
|
L.lens.forEach(function(m) {
|
|
5474
|
-
m.
|
|
5511
|
+
const rim = L.lensMaterial ? glassRim(m.geometry, c.rand) : null;
|
|
5512
|
+
if (!rim) {
|
|
5513
|
+
m.visible = false;
|
|
5514
|
+
return;
|
|
5515
|
+
}
|
|
5516
|
+
m.geometry.dispose();
|
|
5517
|
+
m.geometry = rim;
|
|
5518
|
+
m.material = MATERIALS.glassEdge;
|
|
5519
|
+
m.userData.lensRim = true;
|
|
5475
5520
|
});
|
|
5521
|
+
if (L.lensMaterial)
|
|
5522
|
+
(L.reflector || []).forEach(function(m) {
|
|
5523
|
+
m.material = MATERIALS.broken;
|
|
5524
|
+
});
|
|
5476
5525
|
L.inner.forEach(function(m) {
|
|
5477
5526
|
m.material = MATERIALS.bulbBroken;
|
|
5478
5527
|
});
|
|
@@ -5480,11 +5529,40 @@ function installGlassDamage(kit) {
|
|
|
5480
5529
|
h.visible = false;
|
|
5481
5530
|
});
|
|
5482
5531
|
const p = L.group ? L.group.position.clone() : L.inner[0] ? L.inner[0].position.clone() : new V3();
|
|
5483
|
-
|
|
5484
|
-
I.burst(c, "
|
|
5532
|
+
const glass = L.lensMaterial !== "plastic";
|
|
5533
|
+
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" });
|
|
5534
|
+
I.burst(c, "plastic", c.toEffects(p), glass ? 2 : 5, { dir: c.dirToEffects(dir.clone().negate()), speed: 1 });
|
|
5485
5535
|
}
|
|
5486
5536
|
kit.breakLight = breakLight;
|
|
5487
|
-
|
|
5537
|
+
const crazedCache = /* @__PURE__ */ new Map();
|
|
5538
|
+
const CRAZED_OPACITY = 0.6;
|
|
5539
|
+
function crazed(material) {
|
|
5540
|
+
const known = crazedCache.get(material);
|
|
5541
|
+
if (known) return known;
|
|
5542
|
+
const m = I.crackLens(material).clone();
|
|
5543
|
+
m.opacity = Math.max(m.opacity ?? 1, CRAZED_OPACITY);
|
|
5544
|
+
m.transparent = true;
|
|
5545
|
+
m.userData.shared = true;
|
|
5546
|
+
crazedCache.set(material, m);
|
|
5547
|
+
return m;
|
|
5548
|
+
}
|
|
5549
|
+
function crackLight(c, L, dir, pierced) {
|
|
5550
|
+
if (!L || L.broken) return;
|
|
5551
|
+
if (!L.cracked) {
|
|
5552
|
+
L.cracked = true;
|
|
5553
|
+
for (const m of L.lens) if (m.material && !Array.isArray(m.material)) m.material = crazed(m.material);
|
|
5554
|
+
}
|
|
5555
|
+
const p = L.group ? L.group.position.clone() : L.inner[0] ? L.inner[0].position.clone() : new V3();
|
|
5556
|
+
I.burst(c, "lens", c.toEffects(p), 3, { dir: c.dirToEffects(dir.clone().negate()), speed: 0.9, variant: L.tint === "red" ? "red" : "clear" });
|
|
5557
|
+
if (!pierced || L.dark) return;
|
|
5558
|
+
L.dark = true;
|
|
5559
|
+
for (const m of L.inner) m.material = MATERIALS.bulbBroken;
|
|
5560
|
+
for (const h of L.halo ?? []) h.visible = false;
|
|
5561
|
+
}
|
|
5562
|
+
kit.crackLight = crackLight;
|
|
5563
|
+
const shared = { glassUV, drawWeb, crackGlass, glassRim, shatterGlass, hitGlass, breakLight, crackLight };
|
|
5564
|
+
Object.assign(I, shared);
|
|
5565
|
+
return shared;
|
|
5488
5566
|
}
|
|
5489
5567
|
|
|
5490
5568
|
// src/impact.ts
|
|
@@ -5958,7 +6036,7 @@ function installImpact(kit) {
|
|
|
5958
6036
|
return hit;
|
|
5959
6037
|
}
|
|
5960
6038
|
kit.zoneImpact = zoneImpact;
|
|
5961
|
-
|
|
6039
|
+
const shared = {
|
|
5962
6040
|
dentField,
|
|
5963
6041
|
hangBumper,
|
|
5964
6042
|
tankFuel,
|
|
@@ -5974,7 +6052,9 @@ function installImpact(kit) {
|
|
|
5974
6052
|
_pr,
|
|
5975
6053
|
probe,
|
|
5976
6054
|
zoneImpact
|
|
5977
|
-
}
|
|
6055
|
+
};
|
|
6056
|
+
Object.assign(I, shared);
|
|
6057
|
+
return shared;
|
|
5978
6058
|
}
|
|
5979
6059
|
|
|
5980
6060
|
// src/explosion.ts
|
|
@@ -6359,7 +6439,9 @@ function installExplosion(kit) {
|
|
|
6359
6439
|
}
|
|
6360
6440
|
}
|
|
6361
6441
|
}
|
|
6362
|
-
|
|
6442
|
+
const shared = { BURNT, BURNT_RUB, boomMat, enginePos, fling, burnAll, bigBoomFx, detonate, tickBoom, tickFlying };
|
|
6443
|
+
Object.assign(I, shared);
|
|
6444
|
+
return shared;
|
|
6363
6445
|
}
|
|
6364
6446
|
|
|
6365
6447
|
// src/rollover.ts
|
|
@@ -6561,7 +6643,8 @@ function installRollover(kit) {
|
|
|
6561
6643
|
c.parts.forEach(function(p) {
|
|
6562
6644
|
if (p.kind !== "rotor" && p.kind !== "tail_rotor" || !p.obj) return;
|
|
6563
6645
|
const main = p.kind === "rotor";
|
|
6564
|
-
p.obj.traverse(function(
|
|
6646
|
+
p.obj.traverse(function(node) {
|
|
6647
|
+
const o = node;
|
|
6565
6648
|
if (!o.isMesh || !o.visible) return;
|
|
6566
6649
|
const bb = new THREE.Box3().setFromObject(o).applyMatrix4(inv);
|
|
6567
6650
|
if (!main && bb.min.y >= -0.01) return;
|
|
@@ -6633,7 +6716,9 @@ function installRollover(kit) {
|
|
|
6633
6716
|
if (p >= 1) finishRoll(c);
|
|
6634
6717
|
}
|
|
6635
6718
|
kit.rollContact = rollContact;
|
|
6636
|
-
|
|
6719
|
+
const shared = { rollMeshes, convexHull, rollContact, exactMinY, finishRoll, tickRoll };
|
|
6720
|
+
Object.assign(I, shared);
|
|
6721
|
+
return shared;
|
|
6637
6722
|
}
|
|
6638
6723
|
|
|
6639
6724
|
// src/tick.ts
|
|
@@ -6671,7 +6756,9 @@ function installTick(kit) {
|
|
|
6671
6756
|
c.hood.target = open ? c.hood.open : 0;
|
|
6672
6757
|
return true;
|
|
6673
6758
|
};
|
|
6674
|
-
|
|
6759
|
+
const shared = {};
|
|
6760
|
+
Object.assign(I, shared);
|
|
6761
|
+
return shared;
|
|
6675
6762
|
}
|
|
6676
6763
|
|
|
6677
6764
|
// src/armor.ts
|
|
@@ -6923,7 +7010,9 @@ function installArmor(kit) {
|
|
|
6923
7010
|
}
|
|
6924
7011
|
}
|
|
6925
7012
|
kit.applyArmor = applyArmor;
|
|
6926
|
-
|
|
7013
|
+
const shared = { STEEL_MATERIAL, PLATE_MATERIALS, jerryCan, applyArmor };
|
|
7014
|
+
Object.assign(I, shared);
|
|
7015
|
+
return shared;
|
|
6927
7016
|
}
|
|
6928
7017
|
|
|
6929
7018
|
// src/zone-core.ts
|
|
@@ -6942,8 +7031,8 @@ function installZoneCore(kit) {
|
|
|
6942
7031
|
return { id: b.id, name: kit.t("bands." + b.id), min: b.min, health: b.health, color: b.color };
|
|
6943
7032
|
});
|
|
6944
7033
|
function bandOf(h) {
|
|
6945
|
-
|
|
6946
|
-
for (let i = 0; i < BANDS.length; i++) if (
|
|
7034
|
+
const v = Math.round(clamp(h == null ? 100 : h, 0, 100));
|
|
7035
|
+
for (let i = 0; i < BANDS.length; i++) if (v >= BANDS[i].min) return i;
|
|
6947
7036
|
return 4;
|
|
6948
7037
|
}
|
|
6949
7038
|
kit.bands = BANDS;
|
|
@@ -6969,8 +7058,12 @@ function installZoneCore(kit) {
|
|
|
6969
7058
|
z0: Math.min(b[4], b[5]),
|
|
6970
7059
|
z1: Math.max(b[4], b[5])
|
|
6971
7060
|
};
|
|
6972
|
-
if (b.isBox3)
|
|
6973
|
-
|
|
7061
|
+
if (b.isBox3) {
|
|
7062
|
+
const box = b;
|
|
7063
|
+
return { x0: box.min.x, x1: box.max.x, y0: box.min.y, y1: box.max.y, z0: box.min.z, z1: box.max.z };
|
|
7064
|
+
}
|
|
7065
|
+
const r = b;
|
|
7066
|
+
return { x0: r.x0, x1: r.x1, y0: r.y0, y1: r.y1, z0: r.z0, z1: r.z1 };
|
|
6974
7067
|
}
|
|
6975
7068
|
kit.normalizeBox = normalizeBox;
|
|
6976
7069
|
function boxLo(B, a) {
|
|
@@ -7007,7 +7100,8 @@ function installZoneCore(kit) {
|
|
|
7007
7100
|
const bb = new THREE.Box3();
|
|
7008
7101
|
const tmp = new THREE.Box3();
|
|
7009
7102
|
const M = new THREE.Matrix4();
|
|
7010
|
-
o.traverse(function(
|
|
7103
|
+
o.traverse(function(node) {
|
|
7104
|
+
const x = node;
|
|
7011
7105
|
if (!x.isMesh || !x.geometry || !x.geometry.attributes.position || x.userData.decal) return;
|
|
7012
7106
|
if (!x.geometry.boundingBox) x.geometry.computeBoundingBox();
|
|
7013
7107
|
tmp.copy(x.geometry.boundingBox).applyMatrix4(M.multiplyMatrices(inv, x.matrixWorld));
|
|
@@ -7073,7 +7167,7 @@ function installZoneCore(kit) {
|
|
|
7073
7167
|
for (let q = o; q && q !== c.vehicle; q = q.parent) if (q.visible === false) return false;
|
|
7074
7168
|
return !!o;
|
|
7075
7169
|
}
|
|
7076
|
-
|
|
7170
|
+
const shared = {
|
|
7077
7171
|
BANDS,
|
|
7078
7172
|
bandOf,
|
|
7079
7173
|
ZONE_WEIGHTS,
|
|
@@ -7096,7 +7190,9 @@ function installZoneCore(kit) {
|
|
|
7096
7190
|
lightBoxOf,
|
|
7097
7191
|
hideObj,
|
|
7098
7192
|
shown
|
|
7099
|
-
}
|
|
7193
|
+
};
|
|
7194
|
+
Object.assign(I, shared);
|
|
7195
|
+
return shared;
|
|
7100
7196
|
}
|
|
7101
7197
|
|
|
7102
7198
|
// src/zone-decals.ts
|
|
@@ -7381,7 +7477,10 @@ function installZoneDecals(kit) {
|
|
|
7381
7477
|
narrowTo(rc, q);
|
|
7382
7478
|
}
|
|
7383
7479
|
const hits = rc.intersectObjects(cands, false);
|
|
7384
|
-
for (let i = 0; i < hits.length; i++)
|
|
7480
|
+
for (let i = 0; i < hits.length; i++) {
|
|
7481
|
+
const proxyOf = hits[i].object.proxyOf;
|
|
7482
|
+
if (proxyOf) hits[i].object = proxyOf;
|
|
7483
|
+
}
|
|
7385
7484
|
return hits;
|
|
7386
7485
|
}
|
|
7387
7486
|
function zoneCands(c, z, inv, glassToo) {
|
|
@@ -7582,7 +7681,7 @@ function installZoneDecals(kit) {
|
|
|
7582
7681
|
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));
|
|
7583
7682
|
return S;
|
|
7584
7683
|
}
|
|
7585
|
-
|
|
7684
|
+
const shared = {
|
|
7586
7685
|
dmat,
|
|
7587
7686
|
DAMAGE_MATERIALS,
|
|
7588
7687
|
_zq,
|
|
@@ -7603,7 +7702,9 @@ function installZoneDecals(kit) {
|
|
|
7603
7702
|
ribbonGeo,
|
|
7604
7703
|
scratchDecal,
|
|
7605
7704
|
zoneDecals
|
|
7606
|
-
}
|
|
7705
|
+
};
|
|
7706
|
+
Object.assign(I, shared);
|
|
7707
|
+
return shared;
|
|
7607
7708
|
}
|
|
7608
7709
|
|
|
7609
7710
|
// src/zone-dent.ts
|
|
@@ -7961,7 +8062,9 @@ function installZoneDent(kit) {
|
|
|
7961
8062
|
});
|
|
7962
8063
|
return piv;
|
|
7963
8064
|
}
|
|
7964
|
-
|
|
8065
|
+
const shared = { sm, subdivIn, dentTargets, zoneDent, cutPanel, pivotOf };
|
|
8066
|
+
Object.assign(I, shared);
|
|
8067
|
+
return shared;
|
|
7965
8068
|
}
|
|
7966
8069
|
|
|
7967
8070
|
// src/damage-panels.ts
|
|
@@ -8314,7 +8417,9 @@ function installDamagePanels(kit) {
|
|
|
8314
8417
|
const sgn = new V3().crossVectors(axisV, tangent).dot(outv) > 0 ? 1 : -1;
|
|
8315
8418
|
piv.quaternion.setFromAxisAngle(axisV, sgn * (0.6 + R() * 0.3));
|
|
8316
8419
|
}
|
|
8317
|
-
|
|
8420
|
+
const shared = { panelBand, roofOff, tailOff, followersIn, windowsOver, doorGap, mirrorHang, doorHang, lidHang, flapHang };
|
|
8421
|
+
Object.assign(I, shared);
|
|
8422
|
+
return shared;
|
|
8318
8423
|
}
|
|
8319
8424
|
|
|
8320
8425
|
// src/damage-parts.ts
|
|
@@ -8430,7 +8535,8 @@ function installDamageParts(kit) {
|
|
|
8430
8535
|
}
|
|
8431
8536
|
function tireMeshes(w) {
|
|
8432
8537
|
const out = [];
|
|
8433
|
-
w.traverse(function(
|
|
8538
|
+
w.traverse(function(node) {
|
|
8539
|
+
const o = node;
|
|
8434
8540
|
if (o.isMesh && o.material === MATERIALS.rubber) out.push(o);
|
|
8435
8541
|
});
|
|
8436
8542
|
return out;
|
|
@@ -8489,7 +8595,8 @@ function installDamageParts(kit) {
|
|
|
8489
8595
|
c.zoneDrops.push({ x: w.position.x, z: w.position.z, d: r * 0.24 });
|
|
8490
8596
|
} else if (b === 4) {
|
|
8491
8597
|
let rr = 0;
|
|
8492
|
-
w.traverse(function(
|
|
8598
|
+
w.traverse(function(node) {
|
|
8599
|
+
const o = node;
|
|
8493
8600
|
if (!o.isMesh || o.material === MATERIALS.rubber) return;
|
|
8494
8601
|
if (!o.geometry.boundingSphere) o.geometry.computeBoundingSphere();
|
|
8495
8602
|
const cc = o.geometry.boundingSphere.center.clone().applyMatrix4(o.matrix);
|
|
@@ -8697,7 +8804,8 @@ function installDamageParts(kit) {
|
|
|
8697
8804
|
const xf = H.x0 + (H.x1 - H.x0) * (0.5 + R() * 0.1);
|
|
8698
8805
|
const k = 0.55 + R() * 0.2;
|
|
8699
8806
|
const v = new V3();
|
|
8700
|
-
H.piv.children.forEach(function(
|
|
8807
|
+
H.piv.children.forEach(function(node) {
|
|
8808
|
+
const msh = node;
|
|
8701
8809
|
if (!msh.isMesh) return;
|
|
8702
8810
|
msh.updateMatrix();
|
|
8703
8811
|
const M = msh.matrix;
|
|
@@ -8890,7 +8998,7 @@ function installDamageParts(kit) {
|
|
|
8890
8998
|
});
|
|
8891
8999
|
void K;
|
|
8892
9000
|
}
|
|
8893
|
-
|
|
9001
|
+
const shared = {
|
|
8894
9002
|
glassPt,
|
|
8895
9003
|
glassIn,
|
|
8896
9004
|
glassBand,
|
|
@@ -8908,7 +9016,9 @@ function installDamageParts(kit) {
|
|
|
8908
9016
|
bumperBand,
|
|
8909
9017
|
partBand,
|
|
8910
9018
|
bendAft
|
|
8911
|
-
}
|
|
9019
|
+
};
|
|
9020
|
+
Object.assign(I, shared);
|
|
9021
|
+
return shared;
|
|
8912
9022
|
}
|
|
8913
9023
|
|
|
8914
9024
|
// src/zone-derive.ts
|
|
@@ -8931,7 +9041,8 @@ function installZoneDerive(kit) {
|
|
|
8931
9041
|
}
|
|
8932
9042
|
function resolveObjs(c, list, z) {
|
|
8933
9043
|
const out = [];
|
|
8934
|
-
(list || []).forEach(function(
|
|
9044
|
+
(list || []).forEach(function(item) {
|
|
9045
|
+
const o = item;
|
|
8935
9046
|
if (!o) return;
|
|
8936
9047
|
if (typeof o === "string") {
|
|
8937
9048
|
c.parts.forEach(function(p) {
|
|
@@ -9180,7 +9291,9 @@ function installZoneDerive(kit) {
|
|
|
9180
9291
|
return null;
|
|
9181
9292
|
}
|
|
9182
9293
|
kit.zoneOwner = ownerOf;
|
|
9183
|
-
|
|
9294
|
+
const shared = { parseDir, resolveObjs, deriveZones, carMap, zonesOf, ownerOf };
|
|
9295
|
+
Object.assign(I, shared);
|
|
9296
|
+
return shared;
|
|
9184
9297
|
}
|
|
9185
9298
|
|
|
9186
9299
|
// src/zone-auto.ts
|
|
@@ -9975,7 +10088,9 @@ function installZoneAuto(kit) {
|
|
|
9975
10088
|
if (!wheelsDone) wheelZones(false);
|
|
9976
10089
|
return Z;
|
|
9977
10090
|
}
|
|
9978
|
-
|
|
10091
|
+
const shared = { autoZones };
|
|
10092
|
+
Object.assign(I, shared);
|
|
10093
|
+
return shared;
|
|
9979
10094
|
}
|
|
9980
10095
|
|
|
9981
10096
|
// src/zone-apply.ts
|
|
@@ -10186,7 +10301,9 @@ function installZoneApply(kit) {
|
|
|
10186
10301
|
c.rand = R0;
|
|
10187
10302
|
return c.zoneState;
|
|
10188
10303
|
};
|
|
10189
|
-
|
|
10304
|
+
const shared = { fadePaint, abandonFx, burntFx, settleDrops };
|
|
10305
|
+
Object.assign(I, shared);
|
|
10306
|
+
return shared;
|
|
10190
10307
|
}
|
|
10191
10308
|
|
|
10192
10309
|
// src/scenarios.ts
|
|
@@ -10343,7 +10460,9 @@ function installScenarios(kit) {
|
|
|
10343
10460
|
}
|
|
10344
10461
|
return { p, dir };
|
|
10345
10462
|
};
|
|
10346
|
-
|
|
10463
|
+
const shared = { BODY_TYPES };
|
|
10464
|
+
Object.assign(I, shared);
|
|
10465
|
+
return shared;
|
|
10347
10466
|
}
|
|
10348
10467
|
|
|
10349
10468
|
// src/ui.ts
|
|
@@ -10500,7 +10619,8 @@ function installUi(kit) {
|
|
|
10500
10619
|
}
|
|
10501
10620
|
g.addEventListener("click", pick);
|
|
10502
10621
|
g.addEventListener("keydown", function(e) {
|
|
10503
|
-
|
|
10622
|
+
const key = e.key;
|
|
10623
|
+
if (key === "Enter" || key === " ") {
|
|
10504
10624
|
e.preventDefault();
|
|
10505
10625
|
pick();
|
|
10506
10626
|
}
|
|
@@ -10513,7 +10633,7 @@ function installUi(kit) {
|
|
|
10513
10633
|
return kit.bands.map(function(B, i) {
|
|
10514
10634
|
const b = el("button", null, B.name);
|
|
10515
10635
|
b.type = "button";
|
|
10516
|
-
b.dataset.b = i;
|
|
10636
|
+
b.dataset.b = String(i);
|
|
10517
10637
|
b.style.setProperty("--band", B.color);
|
|
10518
10638
|
b.addEventListener("click", function() {
|
|
10519
10639
|
if (onPick) onPick(B.health, i);
|
|
@@ -10741,6 +10861,7 @@ function createVehicleKit(options) {
|
|
|
10741
10861
|
hash,
|
|
10742
10862
|
clamp,
|
|
10743
10863
|
smooth,
|
|
10864
|
+
// filled by the modules below, each with the helpers it shares
|
|
10744
10865
|
_: {}
|
|
10745
10866
|
};
|
|
10746
10867
|
kit.fuels = {};
|
|
@@ -10818,8 +10939,8 @@ function createVehicleKit(options) {
|
|
|
10818
10939
|
fn.apply(kit, args);
|
|
10819
10940
|
});
|
|
10820
10941
|
};
|
|
10821
|
-
kit.configure = function(
|
|
10822
|
-
o =
|
|
10942
|
+
kit.configure = function(cfg) {
|
|
10943
|
+
const o = cfg || {};
|
|
10823
10944
|
if (o.bands)
|
|
10824
10945
|
o.bands.forEach(function(b, i) {
|
|
10825
10946
|
if (kit.bands[i] && b) Object.assign(kit.bands[i], b);
|
|
@@ -10855,7 +10976,8 @@ function createVehicleKit(options) {
|
|
|
10855
10976
|
}
|
|
10856
10977
|
;
|
|
10857
10978
|
["impactStain", "defaultSplat", "defaultGroup", "damagedScenario"].forEach(function(k) {
|
|
10858
|
-
|
|
10979
|
+
const v = o[k];
|
|
10980
|
+
if (v !== void 0) kit.config[k] = v;
|
|
10859
10981
|
});
|
|
10860
10982
|
return kit;
|
|
10861
10983
|
};
|
|
@@ -11037,6 +11159,8 @@ var MECHANICS = {
|
|
|
11037
11159
|
heli: ["battery", "alternator", "gearbox"]
|
|
11038
11160
|
};
|
|
11039
11161
|
var HITCH_CHANCE = { car: 30, truck: 60, bus: 0, tractor: 100, quad: 40, bike: 0, tank: 0, boat: 0, plane: 0, heli: 0 };
|
|
11162
|
+
var GLASS_LENS_HP = 320;
|
|
11163
|
+
var PLASTIC_LENS_HP = 900;
|
|
11040
11164
|
var STEEL_KG_M2 = 7;
|
|
11041
11165
|
var ALU_KG_M2 = 3.2;
|
|
11042
11166
|
var kindOf = (c) => {
|
|
@@ -11194,7 +11318,9 @@ function buildVehicleModel(kit, c, options = {}) {
|
|
|
11194
11318
|
continue;
|
|
11195
11319
|
}
|
|
11196
11320
|
if (role === "light") {
|
|
11197
|
-
|
|
11321
|
+
const lens = /^head/.test(id) ? spec.headlightLens ?? "polycarbonate" : "acrylic";
|
|
11322
|
+
const glassLens = lens === "glass";
|
|
11323
|
+
add({ id, role, name: label, material: glassLens ? "glass" : "plastic", box, mass: 1.2 + 4 * area, hp: glassLens ? GLASS_LENS_HP : PLASTIC_LENS_HP, zoneId: id, visual: true, tags: ["light", `lens_${lens}`, ...tags] });
|
|
11198
11324
|
continue;
|
|
11199
11325
|
}
|
|
11200
11326
|
if (role === "bumper") {
|
|
@@ -11651,21 +11777,188 @@ function subdivideNear(THREE, params) {
|
|
|
11651
11777
|
mesh.geometry = g;
|
|
11652
11778
|
}
|
|
11653
11779
|
|
|
11780
|
+
// src/destructible/door-open.ts
|
|
11781
|
+
var STRIP_SMOOTH_DEG = 180;
|
|
11782
|
+
var SKIN_BAND = 0.05;
|
|
11783
|
+
var BODY_FACING = 0.5;
|
|
11784
|
+
var FIELDS = 4;
|
|
11785
|
+
var SEAM_THIN = 0.03;
|
|
11786
|
+
var SEAM_AT_EDGE = 0.04;
|
|
11787
|
+
var SEAM_TALL = 0.4;
|
|
11788
|
+
var SLIVER_AREA = 1e-10;
|
|
11789
|
+
function cutStripOverDoor(vehicleKit, params) {
|
|
11790
|
+
const kit = vehicleKit;
|
|
11791
|
+
const strip = params.strip;
|
|
11792
|
+
const toVehicle = params.toVehicle;
|
|
11793
|
+
const { x0, x1 } = params;
|
|
11794
|
+
const THREE = kit.THREE;
|
|
11795
|
+
const at = new THREE.Vector3();
|
|
11796
|
+
const along = (x, y, z) => at.set(x, y, z).applyMatrix4(toVehicle).x;
|
|
11797
|
+
const piece = (tests) => {
|
|
11798
|
+
const mesh = new THREE.Mesh(strip.geometry.clone(), strip.material);
|
|
11799
|
+
kit.cutMesh(mesh, tests, STRIP_SMOOTH_DEG, {});
|
|
11800
|
+
return mesh;
|
|
11801
|
+
};
|
|
11802
|
+
const over = piece([{ sdf: (x, y, z) => along(x, y, z) - x0 }, { sdf: (x, y, z) => x1 - along(x, y, z) }]);
|
|
11803
|
+
const after = piece([{ sdf: (x, y, z) => along(x, y, z) - x1 }]);
|
|
11804
|
+
kit.cutMesh(strip, [{ sdf: (x, y, z) => x0 - along(x, y, z) }], STRIP_SMOOTH_DEG, {});
|
|
11805
|
+
const joined = joinTriangles(THREE, strip.geometry, after.geometry);
|
|
11806
|
+
strip.geometry.dispose();
|
|
11807
|
+
after.geometry.dispose();
|
|
11808
|
+
strip.geometry = joined;
|
|
11809
|
+
return over;
|
|
11810
|
+
}
|
|
11811
|
+
function joinTriangles(THREE, first, second) {
|
|
11812
|
+
const a = first.index ? first.toNonIndexed() : first;
|
|
11813
|
+
const b = second.index ? second.toNonIndexed() : second;
|
|
11814
|
+
const flags = [...solidTriangles(THREE, a), ...solidTriangles(THREE, b)];
|
|
11815
|
+
const both = new THREE.BufferGeometry();
|
|
11816
|
+
for (const name of Object.keys(a.attributes)) {
|
|
11817
|
+
const p = a.getAttribute(name);
|
|
11818
|
+
const q = b.getAttribute(name);
|
|
11819
|
+
if (!q || q.itemSize !== p.itemSize) continue;
|
|
11820
|
+
const array = new Float32Array(p.array.length + q.array.length);
|
|
11821
|
+
array.set(p.array, 0);
|
|
11822
|
+
array.set(q.array, p.array.length);
|
|
11823
|
+
both.setAttribute(name, new THREE.Float32BufferAttribute(array, p.itemSize));
|
|
11824
|
+
}
|
|
11825
|
+
if (a !== first) a.dispose();
|
|
11826
|
+
if (b !== second) b.dispose();
|
|
11827
|
+
const out = pickTriangles(THREE, both, flags, true) ?? new THREE.BufferGeometry();
|
|
11828
|
+
both.dispose();
|
|
11829
|
+
return out;
|
|
11830
|
+
}
|
|
11831
|
+
function solidTriangles(THREE, geometry) {
|
|
11832
|
+
const pos = geometry.getAttribute("position");
|
|
11833
|
+
const triangle = new THREE.Triangle();
|
|
11834
|
+
const flags = [];
|
|
11835
|
+
for (let t = 0; t * 3 + 2 < pos.count; t++) {
|
|
11836
|
+
triangle.a.fromBufferAttribute(pos, t * 3);
|
|
11837
|
+
triangle.b.fromBufferAttribute(pos, t * 3 + 1);
|
|
11838
|
+
triangle.c.fromBufferAttribute(pos, t * 3 + 2);
|
|
11839
|
+
flags.push(triangle.getArea() > SLIVER_AREA);
|
|
11840
|
+
}
|
|
11841
|
+
return flags;
|
|
11842
|
+
}
|
|
11843
|
+
function splitDoorSkin(three, meshes, toVehicleOf, side2, depth) {
|
|
11844
|
+
const THREE = three;
|
|
11845
|
+
const pieces = meshes;
|
|
11846
|
+
const toVehicle = toVehicleOf;
|
|
11847
|
+
const v = new THREE.Vector3();
|
|
11848
|
+
const corners = [new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3()];
|
|
11849
|
+
const triangle = new THREE.Triangle();
|
|
11850
|
+
const centres = pieces.map((mesh) => {
|
|
11851
|
+
const geometry = mesh.geometry.index ? mesh.geometry.toNonIndexed() : mesh.geometry;
|
|
11852
|
+
const matrix = toVehicle(mesh);
|
|
11853
|
+
const pos = geometry.getAttribute("position");
|
|
11854
|
+
const out = new Float32Array(pos.count / 3 * FIELDS);
|
|
11855
|
+
for (let t = 0; t * 3 + 2 < pos.count; t++) {
|
|
11856
|
+
let y = 0;
|
|
11857
|
+
let across = 0;
|
|
11858
|
+
for (let k = 0; k < 3; k++) {
|
|
11859
|
+
corners[k].fromBufferAttribute(pos, t * 3 + k).applyMatrix4(matrix);
|
|
11860
|
+
y += corners[k].y / 3;
|
|
11861
|
+
across += side2 * corners[k].z / 3;
|
|
11862
|
+
}
|
|
11863
|
+
out[t * FIELDS] = y;
|
|
11864
|
+
out[t * FIELDS + 1] = across;
|
|
11865
|
+
triangle.set(corners[0], corners[1], corners[2]).getNormal(v);
|
|
11866
|
+
out[t * FIELDS + 2] = v.y;
|
|
11867
|
+
out[t * FIELDS + 3] = v.x;
|
|
11868
|
+
}
|
|
11869
|
+
return { geometry, out };
|
|
11870
|
+
});
|
|
11871
|
+
const outer = /* @__PURE__ */ new Map();
|
|
11872
|
+
for (const { out } of centres)
|
|
11873
|
+
for (let t = 0; t * FIELDS < out.length; t++) {
|
|
11874
|
+
const band = Math.floor(out[t * FIELDS] / SKIN_BAND);
|
|
11875
|
+
outer.set(band, Math.max(outer.get(band) ?? -Infinity, out[t * FIELDS + 1]));
|
|
11876
|
+
}
|
|
11877
|
+
const surfaceAt = (y) => {
|
|
11878
|
+
const band = Math.floor(y / SKIN_BAND);
|
|
11879
|
+
return Math.max(outer.get(band - 1) ?? -Infinity, outer.get(band) ?? -Infinity, outer.get(band + 1) ?? -Infinity);
|
|
11880
|
+
};
|
|
11881
|
+
return centres.map(({ geometry, out }, i) => {
|
|
11882
|
+
const near = [];
|
|
11883
|
+
for (let t = 0; t * FIELDS < out.length; t++) {
|
|
11884
|
+
const f = t * FIELDS;
|
|
11885
|
+
const body = out[f + 1] < surfaceAt(out[f]) - depth && (out[f + 2] < -BODY_FACING || Math.abs(out[f + 3]) > BODY_FACING);
|
|
11886
|
+
near.push(!body);
|
|
11887
|
+
}
|
|
11888
|
+
const result = { skin: pickTriangles(THREE, geometry, near, true), deep: pickTriangles(THREE, geometry, near, false) };
|
|
11889
|
+
if (geometry !== pieces[i].geometry) geometry.dispose();
|
|
11890
|
+
return result;
|
|
11891
|
+
});
|
|
11892
|
+
}
|
|
11893
|
+
function leaveDeepSkinOnBody(three, meshes, params) {
|
|
11894
|
+
const THREE = three;
|
|
11895
|
+
const pieces = meshes;
|
|
11896
|
+
const toVehicle = params.toVehicle;
|
|
11897
|
+
const { side: side2, depth } = params;
|
|
11898
|
+
const split = splitDoorSkin(THREE, pieces, (mesh) => new THREE.Matrix4().multiplyMatrices(toVehicle, mesh.matrixWorld), side2, depth);
|
|
11899
|
+
split.forEach(({ skin, deep }, i) => {
|
|
11900
|
+
const piece = pieces[i];
|
|
11901
|
+
if (!deep || !skin || !piece.parent) return;
|
|
11902
|
+
const body = new THREE.Mesh(deep, piece.material);
|
|
11903
|
+
body.position.copy(piece.position);
|
|
11904
|
+
body.quaternion.copy(piece.quaternion);
|
|
11905
|
+
body.scale.copy(piece.scale);
|
|
11906
|
+
body.castShadow = piece.castShadow;
|
|
11907
|
+
body.receiveShadow = piece.receiveShadow;
|
|
11908
|
+
piece.parent.add(body);
|
|
11909
|
+
piece.geometry.dispose();
|
|
11910
|
+
piece.geometry = skin;
|
|
11911
|
+
});
|
|
11912
|
+
}
|
|
11913
|
+
function pickTriangles(THREE, geometry, flags, wanted) {
|
|
11914
|
+
const count = flags.filter((flag) => flag === wanted).length;
|
|
11915
|
+
if (!count) return null;
|
|
11916
|
+
const out = new THREE.BufferGeometry();
|
|
11917
|
+
for (const name of Object.keys(geometry.attributes)) {
|
|
11918
|
+
const attribute = geometry.getAttribute(name);
|
|
11919
|
+
const size = attribute.itemSize;
|
|
11920
|
+
const source = attribute.array;
|
|
11921
|
+
const array = new Float32Array(count * 3 * size);
|
|
11922
|
+
let w = 0;
|
|
11923
|
+
flags.forEach((flag, t) => {
|
|
11924
|
+
if (flag !== wanted) return;
|
|
11925
|
+
array.set(source.subarray(t * 3 * size, (t + 1) * 3 * size), w);
|
|
11926
|
+
w += 3 * size;
|
|
11927
|
+
});
|
|
11928
|
+
out.setAttribute(name, new THREE.Float32BufferAttribute(array, size));
|
|
11929
|
+
}
|
|
11930
|
+
out.computeBoundingBox();
|
|
11931
|
+
out.computeBoundingSphere();
|
|
11932
|
+
return out;
|
|
11933
|
+
}
|
|
11934
|
+
function isDoorSeam(three, params) {
|
|
11935
|
+
const THREE = three;
|
|
11936
|
+
const box = params.box;
|
|
11937
|
+
const { zone, side: side2, dark } = params;
|
|
11938
|
+
if (!dark || box.isEmpty()) return false;
|
|
11939
|
+
const size = box.getSize(new THREE.Vector3());
|
|
11940
|
+
const centre = box.getCenter(new THREE.Vector3());
|
|
11941
|
+
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;
|
|
11942
|
+
if (centre.y < zone.y0 || centre.y > zone.y1) return false;
|
|
11943
|
+
return Math.abs(centre.x - zone.x0) < SEAM_AT_EDGE || Math.abs(centre.x - zone.x1) < SEAM_AT_EDGE;
|
|
11944
|
+
}
|
|
11945
|
+
|
|
11654
11946
|
// src/destructible/visual.ts
|
|
11655
11947
|
var HOLE_DECAL_SCALE = 2.4;
|
|
11656
11948
|
var DOOR_DEPTH = 0.07;
|
|
11949
|
+
var DOOR_SKIN_DEPTH = 0.09;
|
|
11950
|
+
var DOOR_FLOOR_DEPTH = 0.2;
|
|
11657
11951
|
var DOOR_EDGE_PIECES = 8;
|
|
11658
11952
|
var DOOR_EDGE_REACH = 0.08;
|
|
11659
11953
|
var DOOR_CARD_COLOR = "#3b3e42";
|
|
11660
11954
|
var DOOR_LINER_COLOR = "#5a5e64";
|
|
11661
11955
|
var DOOR_LINER_DARK = 0.15;
|
|
11662
|
-
var DOOR_STRIP_THIN = 0.
|
|
11956
|
+
var DOOR_STRIP_THIN = 0.13;
|
|
11663
11957
|
var DOOR_STRIP_NEAR = 0.04;
|
|
11664
11958
|
var DOOR_STRIP_TALL = 0.22;
|
|
11665
|
-
var
|
|
11666
|
-
var DOOR_STRIP_VERTICES = 2e4;
|
|
11959
|
+
var DOOR_STRIP_VERTICES = 6e4;
|
|
11667
11960
|
var DOOR_SILL = 0.25;
|
|
11668
|
-
var DOOR_STRIP_OVER = 0.
|
|
11961
|
+
var DOOR_STRIP_OVER = 0.05;
|
|
11669
11962
|
var DOOR_TOP_OVER_PANE = 0.03;
|
|
11670
11963
|
var HOLE_TEXTURE_SIZE = 64;
|
|
11671
11964
|
var LAMINATED_HP = 1e3;
|
|
@@ -11774,6 +12067,10 @@ var VehicleVisuals = class {
|
|
|
11774
12067
|
__publicField(this, "skins", /* @__PURE__ */ new Map());
|
|
11775
12068
|
/** How high each door's cut reaches. */
|
|
11776
12069
|
__publicField(this, "doorTops", /* @__PURE__ */ new Map());
|
|
12070
|
+
/** 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. */
|
|
12071
|
+
__publicField(this, "seams", /* @__PURE__ */ new Map());
|
|
12072
|
+
/** Doors and lids standing open now. */
|
|
12073
|
+
__publicField(this, "openNow", /* @__PURE__ */ new Set());
|
|
11777
12074
|
__publicField(this, "lightsOn", true);
|
|
11778
12075
|
/** Heavy body meshes whose triangle index is still to build (null once done). */
|
|
11779
12076
|
__publicField(this, "warming");
|
|
@@ -11955,6 +12252,11 @@ var VehicleVisuals = class {
|
|
|
11955
12252
|
}
|
|
11956
12253
|
panel.visible = open && !this.skins.get(id);
|
|
11957
12254
|
recess.visible = open && !this.skins.get(id);
|
|
12255
|
+
if (open) this.openNow.add(id);
|
|
12256
|
+
else this.openNow.delete(id);
|
|
12257
|
+
this.seams.forEach((doors, seam) => {
|
|
12258
|
+
if (doors.has(id)) seam.visible = ![...doors].some((door) => this.openNow.has(door));
|
|
12259
|
+
});
|
|
11958
12260
|
};
|
|
11959
12261
|
const euler = piv.rotation;
|
|
11960
12262
|
const quaternion = piv.quaternion;
|
|
@@ -11997,11 +12299,13 @@ var VehicleVisuals = class {
|
|
|
11997
12299
|
const pcs = I.cutPanel(this.c, z, rect, true, dirty, { anyN: true }).map((x) => x.mesh).filter((m) => !!m);
|
|
11998
12300
|
this.mend(dirty);
|
|
11999
12301
|
if (pcs.length) {
|
|
12302
|
+
leaveDeepSkinOnBody(this.THREE, pcs, { toVehicle: inv, side: z.side < 0 ? -1 : 1, depth: DOOR_SKIN_DEPTH });
|
|
12000
12303
|
const panes = I.windowsOver(this.c, z, inv);
|
|
12001
12304
|
const seals = panes.map((g) => I.paneSeals.get(g)).filter((s) => !!s);
|
|
12002
12305
|
const mirrors = this.mirrorsOn(z);
|
|
12003
12306
|
const frames = this.framesAround(panes, inv);
|
|
12004
|
-
|
|
12307
|
+
const followers = I.followersIn(this.c, z, inv).filter((o) => !this.takeSeam(o, id, z, inv) && !this.inFloor(o, piv, z, inv));
|
|
12308
|
+
objs = [...pcs, ...followers, ...panes, ...seals, ...mirrors, ...frames];
|
|
12005
12309
|
}
|
|
12006
12310
|
} else {
|
|
12007
12311
|
const pcs = this.cutZone(z);
|
|
@@ -12029,6 +12333,25 @@ var VehicleVisuals = class {
|
|
|
12029
12333
|
this.c.root.updateMatrixWorld(true);
|
|
12030
12334
|
return objs.length > 0;
|
|
12031
12335
|
}
|
|
12336
|
+
/** 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. */
|
|
12337
|
+
inFloor(o, piv, z, inv) {
|
|
12338
|
+
const side2 = z.side < 0 ? -1 : 1;
|
|
12339
|
+
const centre = this.I.localBox(this.c, o, inv).getCenter(new this.THREE.Vector3());
|
|
12340
|
+
const skin = side2 * (piv.position.z - side2 * 0.016);
|
|
12341
|
+
return centre.y < z.box.y0 + DOOR_SILL && side2 * centre.z < skin - DOOR_FLOOR_DEPTH;
|
|
12342
|
+
}
|
|
12343
|
+
/** 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. */
|
|
12344
|
+
takeSeam(o, id, z, inv) {
|
|
12345
|
+
const B = z.box;
|
|
12346
|
+
const box = this.I.localBox(this.c, o, inv);
|
|
12347
|
+
const color = o.material?.color;
|
|
12348
|
+
const dark = !!color && color.getHSL({ h: 0, s: 0, l: 0 }).l < DOOR_LINER_DARK;
|
|
12349
|
+
if (!o.isMesh || !isDoorSeam(this.THREE, { box, zone: { x0: B.x0, x1: B.x1, y0: B.y0, y1: B.y1 }, side: z.side, dark })) return false;
|
|
12350
|
+
const doors = this.seams.get(o) ?? /* @__PURE__ */ new Set();
|
|
12351
|
+
doors.add(id);
|
|
12352
|
+
this.seams.set(o, doors);
|
|
12353
|
+
return true;
|
|
12354
|
+
}
|
|
12032
12355
|
/** 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. */
|
|
12033
12356
|
doorEdges(piv, z, y1) {
|
|
12034
12357
|
const THREE = this.THREE;
|
|
@@ -12050,13 +12373,15 @@ var VehicleVisuals = class {
|
|
|
12050
12373
|
const at = this.surface("z", side2, B, [[x, y]]);
|
|
12051
12374
|
return at != null && Math.abs(at - flat) < DOOR_EDGE_REACH ? at : flat;
|
|
12052
12375
|
});
|
|
12053
|
-
const band = (lift) => {
|
|
12376
|
+
const band = (lift, path, closed) => {
|
|
12054
12377
|
const position = [];
|
|
12055
12378
|
const index = [];
|
|
12056
|
-
|
|
12057
|
-
|
|
12379
|
+
path.forEach((at, i) => {
|
|
12380
|
+
const [x, y] = loop[at];
|
|
12381
|
+
position.push(x, y, heights[at] + side2 * lift, x, y, heights[at] + side2 * (lift - DOOR_DEPTH));
|
|
12382
|
+
if (!closed && i === path.length - 1) return;
|
|
12058
12383
|
const a = i * 2;
|
|
12059
|
-
const b = (i + 1) %
|
|
12384
|
+
const b = (i + 1) % path.length * 2;
|
|
12060
12385
|
index.push(a, a + 1, b, b, a + 1, b + 1);
|
|
12061
12386
|
});
|
|
12062
12387
|
const g = new THREE.BufferGeometry();
|
|
@@ -12084,8 +12409,11 @@ var VehicleVisuals = class {
|
|
|
12084
12409
|
card.castShadow = false;
|
|
12085
12410
|
this.c.vehicle.add(card);
|
|
12086
12411
|
piv.attach(card);
|
|
12087
|
-
const
|
|
12088
|
-
const
|
|
12412
|
+
const all = loop.map((_, i) => i);
|
|
12413
|
+
const top = 2 * DOOR_EDGE_PIECES;
|
|
12414
|
+
const sides = [...all.slice(3 * DOOR_EDGE_PIECES), ...all.slice(0, top + 1)];
|
|
12415
|
+
const edges = new THREE.Mesh(band(2e-3, all, true), paint);
|
|
12416
|
+
const lining = new THREE.Mesh(band(2e-3, sides, false), paint);
|
|
12089
12417
|
for (const m of [edges, lining]) {
|
|
12090
12418
|
m.userData.noFollow = true;
|
|
12091
12419
|
m.castShadow = false;
|
|
@@ -12142,26 +12470,14 @@ var VehicleVisuals = class {
|
|
|
12142
12470
|
const box = this.I.localBox(this.c, o, inv);
|
|
12143
12471
|
const size = box.getSize(new THREE.Vector3());
|
|
12144
12472
|
const mid = box.getCenter(new THREE.Vector3());
|
|
12145
|
-
if (Math.sign(mid.z) !== Math.sign(z.side) || size.z > DOOR_STRIP_THIN || size.y > DOOR_STRIP_TALL || Math.min(box.max.x, x1) - Math.max(box.min.x, x0) <
|
|
12473
|
+
if (Math.sign(mid.z) !== Math.sign(z.side) || size.z > DOOR_STRIP_THIN || size.y > DOOR_STRIP_TALL || Math.min(box.max.x, x1) - Math.max(box.min.x, x0) < DOOR_STRIP_OVER || mid.y < y0 || mid.y > y1) continue;
|
|
12146
12474
|
const toVehicle = new THREE.Matrix4().multiplyMatrices(inv, o.matrixWorld);
|
|
12147
|
-
const
|
|
12148
|
-
const sdf = (x, y, zz) => {
|
|
12149
|
-
v.set(x, y, zz).applyMatrix4(toVehicle);
|
|
12150
|
-
return Math.max(x0 - v.x, v.x - x1);
|
|
12151
|
-
};
|
|
12152
|
-
const over = new THREE.Mesh(o.geometry.clone(), o.material);
|
|
12475
|
+
const over = cutStripOverDoor(this.kit, { strip: o, toVehicle, x0, x1 });
|
|
12153
12476
|
over.position.copy(o.position);
|
|
12154
12477
|
over.quaternion.copy(o.quaternion);
|
|
12155
12478
|
over.scale.copy(o.scale);
|
|
12156
12479
|
this.c.vehicle.add(over);
|
|
12157
12480
|
over.updateMatrixWorld(true);
|
|
12158
|
-
const overToVehicle = new THREE.Matrix4().multiplyMatrices(inv, over.matrixWorld);
|
|
12159
|
-
const w = new THREE.Vector3();
|
|
12160
|
-
this.kit.cutMesh(over, [{ sdf: (x, y, zz) => {
|
|
12161
|
-
w.set(x, y, zz).applyMatrix4(overToVehicle);
|
|
12162
|
-
return -Math.max(x0 - w.x, w.x - x1);
|
|
12163
|
-
} }], STRIP_SMOOTH_DEG, {});
|
|
12164
|
-
this.kit.cutMesh(o, [{ sdf }], STRIP_SMOOTH_DEG, {});
|
|
12165
12481
|
over.userData.noFollow = true;
|
|
12166
12482
|
piv.attach(over);
|
|
12167
12483
|
}
|
|
@@ -12742,11 +13058,18 @@ var VehicleVisuals = class {
|
|
|
12742
13058
|
}
|
|
12743
13059
|
}
|
|
12744
13060
|
}
|
|
13061
|
+
/** 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. */
|
|
13062
|
+
crackLight(p, pierced) {
|
|
13063
|
+
const z = this.zone(p);
|
|
13064
|
+
if (!z) return;
|
|
13065
|
+
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);
|
|
13066
|
+
}
|
|
12745
13067
|
/** The lens of a light breaks and its unit stays (damaged) or goes (destroyed). */
|
|
12746
13068
|
breakLight(p, gone) {
|
|
12747
13069
|
const z = this.zone(p);
|
|
12748
13070
|
if (!z) return;
|
|
12749
13071
|
for (const L of z.lights) {
|
|
13072
|
+
L.lensMaterial = p.material;
|
|
12750
13073
|
this.kit.breakLight(this.c, L, new this.THREE.Vector3(p.box.center[0] > 0 ? -1 : 1, 0, 0));
|
|
12751
13074
|
if (gone) {
|
|
12752
13075
|
if (L.group) L.group.visible = false;
|
|
@@ -13392,6 +13715,7 @@ function createVehicleDestructible(kit, vehicleCtx, options = {}) {
|
|
|
13392
13715
|
wear(p, amount, out);
|
|
13393
13716
|
syncZone(p);
|
|
13394
13717
|
if (p.hp <= 0) lose(p, "broken", out, cause);
|
|
13718
|
+
else if (p.def.role === "light") vis?.crackLight(p.def, dtype === "ballistic");
|
|
13395
13719
|
if (p.def.role === "tyre" && !p.flat && p.hp < p.def.hp * 0.6 && !p.lost) {
|
|
13396
13720
|
p.flat = true;
|
|
13397
13721
|
vis?.tyreFlat(p.def, 0.24);
|
|
@@ -14204,7 +14528,7 @@ function createVehicleDestructible(kit, vehicleCtx, options = {}) {
|
|
|
14204
14528
|
if (!list.length) return 1;
|
|
14205
14529
|
return Math.min(...list.map((p) => p.lost || !attached(p.def.id) ? 0 : p.hp / p.def.hp));
|
|
14206
14530
|
};
|
|
14207
|
-
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) }));
|
|
14531
|
+
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 }));
|
|
14208
14532
|
const status = computeStatus();
|
|
14209
14533
|
const brakeSystem = [...ps.values()].find((p) => p.def.role === "brakes" && p.def.contains);
|
|
14210
14534
|
const fluidLeft = brakeSystem ? clamp((brakeSystem.liters ?? 0) / brakeSystem.def.contains.liters / BRAKE_FLUID_NEEDED, 0, 1) : 1;
|