@adatechnology/game-vehicles-three 0.6.4 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-MRUPKE7J.js → chunk-NPS4X64L.js} +864 -60
- package/dist/chunk-NPS4X64L.js.map +1 -0
- package/dist/index.d.ts +267 -14
- package/dist/index.global.js +2057 -401
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +19 -1
- package/dist/{testing-C-BgV7gj.d.ts → testing-Cb10i9fm.d.ts} +23 -9
- package/dist/testing.d.ts +3 -1
- package/dist/testing.js +1 -1
- package/package.json +8 -8
- package/dist/chunk-MRUPKE7J.js.map +0 -1
package/dist/index.global.js
CHANGED
|
@@ -23,6 +23,8 @@ var GameVehiclesThree = (() => {
|
|
|
23
23
|
__export(index_exports, {
|
|
24
24
|
BIKE_ENGINE: () => BIKE_ENGINE,
|
|
25
25
|
CAR_ENGINE: () => CAR_ENGINE,
|
|
26
|
+
CAR_RECORDED_RPM: () => CAR_RECORDED_RPM,
|
|
27
|
+
CAR_START_RUN_STOP: () => CAR_START_RUN_STOP,
|
|
26
28
|
CRASH_SPEEDS: () => CRASH_SPEEDS,
|
|
27
29
|
DASHBOARD_LOOK: () => DASHBOARD_LOOK,
|
|
28
30
|
DEFAULT_TEST_VEHICLES: () => DEFAULT_TEST_VEHICLES,
|
|
@@ -31,6 +33,7 @@ var GameVehiclesThree = (() => {
|
|
|
31
33
|
ENGINE_PROFILES: () => ENGINE_PROFILES,
|
|
32
34
|
LAMP_RULES: () => LAMP_RULES,
|
|
33
35
|
LITE_CLASSES: () => LITE_CLASSES,
|
|
36
|
+
MIST_RULES: () => MIST_RULES,
|
|
34
37
|
PAGE_ITEM_ALIASES: () => PAGE_ITEM_ALIASES,
|
|
35
38
|
PAGE_SCENARIO_ALIASES: () => PAGE_SCENARIO_ALIASES,
|
|
36
39
|
PROVING_AREA_ID: () => PROVING_AREA_ID,
|
|
@@ -41,20 +44,26 @@ var GameVehiclesThree = (() => {
|
|
|
41
44
|
VEHICLE_LOD_DISTANCE: () => VEHICLE_LOD_DISTANCE,
|
|
42
45
|
VEHICLE_LOOPS: () => VEHICLE_LOOPS,
|
|
43
46
|
VEHICLE_LOOP_FALLOFF: () => VEHICLE_LOOP_FALLOFF,
|
|
47
|
+
VEHICLE_PRELOAD_SOUNDS: () => VEHICLE_PRELOAD_SOUNDS,
|
|
48
|
+
VEHICLE_SAMPLE_ALIASES: () => VEHICLE_SAMPLE_ALIASES,
|
|
44
49
|
VEHICLE_SCENARIO_IDS: () => VEHICLE_SCENARIO_IDS,
|
|
45
50
|
VEHICLE_SOUNDS: () => VEHICLE_SOUNDS,
|
|
46
51
|
VEHICLE_SOUND_BANK: () => VEHICLE_SOUND_BANK,
|
|
47
52
|
classColor: () => classColor,
|
|
48
53
|
classify: () => classify,
|
|
49
54
|
createCabinSmoke: () => createCabinSmoke,
|
|
55
|
+
createEngineBudget: () => createEngineBudget,
|
|
50
56
|
createGearGuess: () => createGearGuess,
|
|
51
57
|
createProvingModule: () => createProvingModule,
|
|
58
|
+
createVehicleBody: () => createVehicleBody,
|
|
52
59
|
createVehicleDashboard: () => createVehicleDashboard,
|
|
53
60
|
createVehicleLamps: () => createVehicleLamps,
|
|
54
61
|
createVehicleLod: () => createVehicleLod,
|
|
55
62
|
createVehicleSound: () => createVehicleSound,
|
|
56
63
|
createVehiclesTestModule: () => createVehiclesTestModule,
|
|
57
64
|
createVehiclesThree: () => createVehiclesThree,
|
|
65
|
+
createWheelRoll: () => createWheelRoll,
|
|
66
|
+
createWindshieldMist: () => createWindshieldMist,
|
|
58
67
|
defaultEffectIds: () => defaultEffectIds,
|
|
59
68
|
defaultSoundIds: () => defaultSoundIds,
|
|
60
69
|
engineMix: () => engineMix,
|
|
@@ -70,6 +79,10 @@ var GameVehiclesThree = (() => {
|
|
|
70
79
|
|
|
71
80
|
// ../game-contracts/dist/index.js
|
|
72
81
|
var DEFAULT_BLAST_IMPULSE = { bodyArea: 0.7, lift: 0.15, minSpeed: 0.3, tntPerJoule: 0.24 / 2e5 };
|
|
82
|
+
var LAUNCHED = "launched";
|
|
83
|
+
function launchBody(root, velocity) {
|
|
84
|
+
root.userData[LAUNCHED] = [velocity[0], velocity[1], velocity[2]];
|
|
85
|
+
}
|
|
73
86
|
var DEFAULT_COST_ALLOCATION_BYTES = 1024 * 1024;
|
|
74
87
|
var DEFAULT_IGNITION_RULES = {
|
|
75
88
|
fillCurve: [
|
|
@@ -3861,9 +3874,9 @@ var GameVehiclesThree = (() => {
|
|
|
3861
3874
|
let x = bx + (Hd[0] - bx) * v;
|
|
3862
3875
|
const y = by + (Hd[1] - by) * v;
|
|
3863
3876
|
let z = bz + (Hd[2] - bz) * v;
|
|
3864
|
-
const
|
|
3877
|
+
const chord2 = Math.hypot(C[0] - T[0], C[1] - T[1]) * (1 - v);
|
|
3865
3878
|
x -= roach * u * Math.sin(v * PI) * (u > 0.7 ? 1 : u / 0.7);
|
|
3866
|
-
z += cam *
|
|
3879
|
+
z += cam * chord2 * 4 * u * (1 - u) * (0.6 + 0.4 * (1 - v));
|
|
3867
3880
|
pos.push(x, y, z);
|
|
3868
3881
|
}
|
|
3869
3882
|
}
|
|
@@ -5092,12 +5105,24 @@ var GameVehiclesThree = (() => {
|
|
|
5092
5105
|
}
|
|
5093
5106
|
);
|
|
5094
5107
|
}
|
|
5108
|
+
var WIPER_SWEEP = 1.5;
|
|
5109
|
+
function tagWiper(params) {
|
|
5110
|
+
var _a;
|
|
5111
|
+
const tag = { arm: params.index, sweep: WIPER_SWEEP, spindle: [params.spindle.x, params.spindle.y, params.spindle.z], axis: [params.normal.x, params.normal.y, params.normal.z] };
|
|
5112
|
+
(_a = params.context).wipers ?? (_a.wipers = []);
|
|
5113
|
+
for (const part of params.parts) params.context.wipers.push({ part, tag });
|
|
5114
|
+
}
|
|
5115
|
+
function markSunroof(pane, slide) {
|
|
5116
|
+
pane.name = "sunroof";
|
|
5117
|
+
pane.userData.sunroof = { slide };
|
|
5118
|
+
return pane;
|
|
5119
|
+
}
|
|
5095
5120
|
function installCarsExtra(fx) {
|
|
5096
5121
|
const kit = fx.kit;
|
|
5097
5122
|
const THREE = kit.THREE;
|
|
5098
5123
|
const trl = fx.t;
|
|
5099
5124
|
const lbl = fx.label;
|
|
5100
|
-
const V3 = kit.V3, PI = Math.PI, MT = kit.materials, CM = kit.makeMaterial, G2 = kit.geo, profX = kit.profX, halfAt = kit.halfAt,
|
|
5125
|
+
const V3 = kit.V3, PI = Math.PI, MT = kit.materials, CM = kit.makeMaterial, G2 = kit.geo, profX = kit.profX, halfAt = kit.halfAt, clamp6 = kit.clamp, smooth2 = kit.smooth;
|
|
5101
5126
|
const GLOSS = CM("#07080a", { roughness: 0.18, metalness: 0.5 });
|
|
5102
5127
|
const ALLOY = CM("#b9bec2", { metalness: 0.75, roughness: 0.3 });
|
|
5103
5128
|
const ALLOYD = CM("#3a3e42", { metalness: 0.6, roughness: 0.35 });
|
|
@@ -5111,7 +5136,7 @@ var GameVehiclesThree = (() => {
|
|
|
5111
5136
|
const a = (y - o.ys) / (o.belt - o.ys);
|
|
5112
5137
|
return o.kt * a * a;
|
|
5113
5138
|
}
|
|
5114
|
-
const b =
|
|
5139
|
+
const b = clamp6((o.ys - y) / (o.ys - o.yb), 0, 1.25);
|
|
5115
5140
|
return o.kb * b * b;
|
|
5116
5141
|
}
|
|
5117
5142
|
const f = function(x, y, z) {
|
|
@@ -5191,13 +5216,13 @@ var GameVehiclesThree = (() => {
|
|
|
5191
5216
|
});
|
|
5192
5217
|
}
|
|
5193
5218
|
function roofAt(gh, x) {
|
|
5194
|
-
const rR = gh.roofR || gh.roof, t =
|
|
5219
|
+
const rR = gh.roofR || gh.roof, t = clamp6((x - gh.rt) / (gh.ft - gh.rt), 0, 1);
|
|
5195
5220
|
return rR + (gh.roof - rR) * t + (gh.crown || 0) * 4 * t * (1 - t);
|
|
5196
5221
|
}
|
|
5197
5222
|
function windows(gh) {
|
|
5198
5223
|
const inn = 0.07, rise = gh.rise || 0;
|
|
5199
5224
|
function ybAt(x) {
|
|
5200
|
-
return gh.belt + 0.035 + rise *
|
|
5225
|
+
return gh.belt + 0.035 + rise * clamp6((gh.fb - x) / (gh.fb - gh.rb), 0, 1);
|
|
5201
5226
|
}
|
|
5202
5227
|
function lx(x0, x1, y, top) {
|
|
5203
5228
|
return x0 + (x1 - x0) * (y - gh.belt) / (top - gh.belt);
|
|
@@ -5400,7 +5425,7 @@ var GameVehiclesThree = (() => {
|
|
|
5400
5425
|
}
|
|
5401
5426
|
const G22 = { P, N, nu, nv, y0: o.y0, y1: o.y1, len: tot * (full ? 2 : 1), E, sd };
|
|
5402
5427
|
G22.at = function(u, y) {
|
|
5403
|
-
const fi =
|
|
5428
|
+
const fi = clamp6(u, 0, 1) * nu, fj = clamp6((y - o.y0) / (o.y1 - o.y0), 0, 1) * nv, i0 = Math.min(nu - 1, Math.floor(fi)), j0 = Math.min(nv - 1, Math.floor(fj)), a = fi - i0, b = fj - j0;
|
|
5404
5429
|
function L(M) {
|
|
5405
5430
|
return M[i0][j0].clone().multiplyScalar((1 - a) * (1 - b)).addScaledVector(M[i0 + 1][j0], a * (1 - b)).addScaledVector(M[i0][j0 + 1], (1 - a) * b).addScaledVector(M[i0 + 1][j0 + 1], a * b);
|
|
5406
5431
|
}
|
|
@@ -5588,7 +5613,7 @@ var GameVehiclesThree = (() => {
|
|
|
5588
5613
|
off: 3e-3,
|
|
5589
5614
|
nv: 4
|
|
5590
5615
|
});
|
|
5591
|
-
skin(c, Gd, o.refl || REFL, { u0: pu, u1: 1 - pu, yb, yt, off: 6e-3, nv: 4 });
|
|
5616
|
+
const reflector = skin(c, Gd, o.refl || REFL, { u0: pu, u1: 1 - pu, yb, yt, off: 6e-3, nv: 4 });
|
|
5592
5617
|
(o.proj || []).forEach(function(q) {
|
|
5593
5618
|
const r = sh(q[0]), y = (r[0] + r[1]) / 2 + (q[1] || 0), s = Gd.at(q[0], y), rad = q[2] || Math.min(0.034, (r[1] - r[0]) * 0.4);
|
|
5594
5619
|
const cup = onSurf(c.cylinder(rad * 1.35, rad * 1.2, 0.012, LH, 0, 0, 0), s, 8e-3);
|
|
@@ -5619,7 +5644,7 @@ var GameVehiclesThree = (() => {
|
|
|
5619
5644
|
lens.push(ln);
|
|
5620
5645
|
if (!inner.length) inner.push(ln);
|
|
5621
5646
|
const cs = Gd.at(0.5, (rg[0] + rg[1]) / 2).p;
|
|
5622
|
-
regLight(c, "headlight", o.label || (sd > 0 ? trl("labels.right_headlight") : trl("labels.left_headlight")), inner, lens, cs);
|
|
5647
|
+
Object.assign(regLight(c, "headlight", o.label || (sd > 0 ? trl("labels.right_headlight") : trl("labels.left_headlight")), inner, lens, cs), { reflector: [reflector] });
|
|
5623
5648
|
return Gd;
|
|
5624
5649
|
};
|
|
5625
5650
|
K.tail = function(sd, o) {
|
|
@@ -5980,7 +6005,7 @@ var GameVehiclesThree = (() => {
|
|
|
5980
6005
|
c.roundBox(x1 - x0, 0.08, 0.035, 0.015, MT.trim, (x0 + x1) / 2, by + 0.05, sd * (hw - 8e-3));
|
|
5981
6006
|
if (s.clad)
|
|
5982
6007
|
s.arches.forEach(function(a) {
|
|
5983
|
-
const a0 = Math.asin(
|
|
6008
|
+
const a0 = Math.asin(clamp6((by - a[1]) / a[2], -1, 1)), tor = c.add(new THREE.TorusGeometry(a[2] + 0.02, 0.035, 6, 26, PI - 2 * a0), MT.trim, a[0], a[1], sd * (hw - 0.01));
|
|
5984
6009
|
tor.rotation.z = a0;
|
|
5985
6010
|
tor.scale.z = 0.8;
|
|
5986
6011
|
});
|
|
@@ -6005,12 +6030,18 @@ var GameVehiclesThree = (() => {
|
|
|
6005
6030
|
(s.wiper === 1 ? [[0.12, 0.66, -0.5]] : [
|
|
6006
6031
|
[-0.3, 0.42, -0.36],
|
|
6007
6032
|
[0.2, 0.42, -0.36]
|
|
6008
|
-
]).forEach(function(q) {
|
|
6033
|
+
]).forEach(function(q, index) {
|
|
6009
6034
|
const p0 = new V3(gh.fb, gh.belt, q[0]).addScaledVector(wd, 0.07).addScaledVector(wn, 0.035), p1 = p0.clone().addScaledVector(wd, q[1] * 0.42);
|
|
6010
6035
|
p1.z += q[2];
|
|
6011
|
-
c.rod(p0, p1, 9e-3, MT.trim);
|
|
6012
|
-
c.cylinder(0.018, 0.018, 0.03, MT.trim, p0.x, p0.y, p0.z);
|
|
6036
|
+
const blade = c.rod(p0, p1, 9e-3, MT.trim);
|
|
6037
|
+
const cap = c.cylinder(0.018, 0.018, 0.03, MT.trim, p0.x, p0.y, p0.z);
|
|
6038
|
+
tagWiper({ context: c, parts: [blade, cap], spindle: p0, normal: wn, index });
|
|
6013
6039
|
});
|
|
6040
|
+
if (s.sunroof) {
|
|
6041
|
+
const sx = gh.rt + (gh.ft - gh.rt) * 0.62, sl = 0.62, sw = 2 * (halfAt(gh.Wg, T, gh.roof) - 0.24), sy = roofAt(gh, sx), tilt = Math.atan2(roofAt(gh, sx + 0.3) - roofAt(gh, sx - 0.3), 0.6);
|
|
6042
|
+
c.roundBox(sl, 8e-3, sw, 0.01, PLASTIC, sx, sy + 4e-3, 0, { rot: [0, 0, tilt] }).castShadow = false;
|
|
6043
|
+
markSunroof(c.roundBox(sl + 0.03, 0.012, sw + 0.03, 0.01, MT.tint, sx, sy + 0.013, 0, { rot: [0, 0, tilt] }), sl * 0.85);
|
|
6044
|
+
}
|
|
6014
6045
|
if (s.fin !== false)
|
|
6015
6046
|
c.sphere(0.1, s.roofCol ? c.paint(s.roofCol) : GLOSS, gh.rt + 0.2, roofAt(gh, gh.rt + 0.2) + 0.045, 0, 1, 0.45, 0.28, {
|
|
6016
6047
|
tl: PI / 2
|
|
@@ -6111,7 +6142,7 @@ var GameVehiclesThree = (() => {
|
|
|
6111
6142
|
c.cylinder(0.06, 0.06, 0.012, MT.head, x + 0.055, y, z, "x");
|
|
6112
6143
|
}
|
|
6113
6144
|
function sm(t) {
|
|
6114
|
-
t =
|
|
6145
|
+
t = clamp6(t, 0, 1);
|
|
6115
6146
|
return t * t * (3 - 2 * t);
|
|
6116
6147
|
}
|
|
6117
6148
|
function sideGrid(S, sd, o) {
|
|
@@ -6128,7 +6159,7 @@ var GameVehiclesThree = (() => {
|
|
|
6128
6159
|
}
|
|
6129
6160
|
const G22 = { P, N, nu, nv, y0: o.y0, y1: o.y1, len: Math.abs(o.x1 - o.x0) };
|
|
6130
6161
|
G22.at = function(u, y) {
|
|
6131
|
-
const fi =
|
|
6162
|
+
const fi = clamp6(u, 0, 1) * nu, fj = clamp6((y - o.y0) / (o.y1 - o.y0), 0, 1) * nv, i0 = Math.min(nu - 1, Math.floor(fi)), j0 = Math.min(nv - 1, Math.floor(fj)), a = fi - i0, b = fj - j0;
|
|
6132
6163
|
function L(M) {
|
|
6133
6164
|
return M[i0][j0].clone().multiplyScalar((1 - a) * (1 - b)).addScaledVector(M[i0 + 1][j0], a * (1 - b)).addScaledVector(M[i0][j0 + 1], (1 - a) * b).addScaledVector(M[i0 + 1][j0 + 1], a * b);
|
|
6134
6165
|
}
|
|
@@ -6986,6 +7017,7 @@ var GameVehiclesThree = (() => {
|
|
|
6986
7017
|
function(c) {
|
|
6987
7018
|
const hex = "#8c2b2b";
|
|
6988
7019
|
car(c, {
|
|
7020
|
+
sunroof: fx.hasSunroof("turbo_hatch"),
|
|
6989
7021
|
W: 1.751,
|
|
6990
7022
|
col: hex,
|
|
6991
7023
|
shelf: 0.42,
|
|
@@ -7263,6 +7295,7 @@ var GameVehiclesThree = (() => {
|
|
|
7263
7295
|
function(c) {
|
|
7264
7296
|
const hex = "#5a5f66";
|
|
7265
7297
|
car(c, {
|
|
7298
|
+
sunroof: fx.hasSunroof("fastback_sedan"),
|
|
7266
7299
|
W: 1.799,
|
|
7267
7300
|
col: hex,
|
|
7268
7301
|
bottomY: 0.2,
|
|
@@ -7557,6 +7590,8 @@ var GameVehiclesThree = (() => {
|
|
|
7557
7590
|
fx.register(
|
|
7558
7591
|
{
|
|
7559
7592
|
key: "classic_six_sedan",
|
|
7593
|
+
// glass headlight lenses, as on cars of its time: they shatter (a modern car's are polycarbonate)
|
|
7594
|
+
headlightLens: "glass",
|
|
7560
7595
|
group: "cars",
|
|
7561
7596
|
name: trl("vehicles.classic_six_sedan.name"),
|
|
7562
7597
|
inspired: trl("vehicles.classic_six_sedan.inspired"),
|
|
@@ -7858,7 +7893,7 @@ var GameVehiclesThree = (() => {
|
|
|
7858
7893
|
const g = K.grid(1, 0, { z1: 0.66, y0: 0.27, y1: 0.61, du: 0.03, dv: 0.03 }), zt = 0.6, zb = 0.43, yB0 = 0.3, yT = 0.585;
|
|
7859
7894
|
const gyb = function(u) {
|
|
7860
7895
|
const z = Math.abs(g.zu(u));
|
|
7861
|
-
return z <= zb ? yB0 : yB0 + (yT - 0.02 - yB0) *
|
|
7896
|
+
return z <= zb ? yB0 : yB0 + (yT - 0.02 - yB0) * clamp6((z - zb) / (zt - zb), 0, 1);
|
|
7862
7897
|
};
|
|
7863
7898
|
K.skin(g, grilleMat("mesh"), { u0: g.uz(-zt), u1: g.uz(zt), yb: gyb, yt: yT, off: 0.022, tile: 0.05, nv: 6 });
|
|
7864
7899
|
outline(c2, g, { u0: g.uz(-zt), u1: g.uz(zt), yb: gyb, yt: yT }, 0.012, LH, 0.024);
|
|
@@ -8667,7 +8702,7 @@ var GameVehiclesThree = (() => {
|
|
|
8667
8702
|
lightsY: 0.82
|
|
8668
8703
|
});
|
|
8669
8704
|
const tx = -1.25, len2 = 6.2, ty = 2.08, sy = 0.82, sz = 1.16;
|
|
8670
|
-
function
|
|
8705
|
+
function hz2(y) {
|
|
8671
8706
|
const d = (y - ty) / sy;
|
|
8672
8707
|
return sz * Math.sqrt(Math.max(0, 1 - d * d));
|
|
8673
8708
|
}
|
|
@@ -8721,12 +8756,12 @@ var GameVehiclesThree = (() => {
|
|
|
8721
8756
|
[1, -1].forEach(function(s) {
|
|
8722
8757
|
c.cylinder(0.12, 0.12, 2.3, ALU, 0.25, 1.36, s * 1, "x");
|
|
8723
8758
|
c.cylinder(0.1, 0.1, 0.02, MT.dark, -0.91, 1.36, s * 1, "x");
|
|
8724
|
-
c.roundBox(0.42, 0.32, 0.012, 0.01, CM("#d9771c"), tx + 1.6, ty - 0.25, s * (
|
|
8725
|
-
c.text("33", 0.36, 0.13, tx + 1.6, ty - 0.18, s * (
|
|
8726
|
-
c.text("1203", 0.36, 0.13, tx + 1.6, ty - 0.32, s * (
|
|
8727
|
-
const dia = c.roundBox(0.3, 0.3, 0.012, 0.01, CM("#c3271c"), tx + 2.15, ty - 0.25, s * (
|
|
8759
|
+
c.roundBox(0.42, 0.32, 0.012, 0.01, CM("#d9771c"), tx + 1.6, ty - 0.25, s * (hz2(ty - 0.1) + 6e-3));
|
|
8760
|
+
c.text("33", 0.36, 0.13, tx + 1.6, ty - 0.18, s * (hz2(ty - 0.1) + 0.014), s > 0 ? "+z" : "-z", { fg: "#111", size: 0.85 });
|
|
8761
|
+
c.text("1203", 0.36, 0.13, tx + 1.6, ty - 0.32, s * (hz2(ty - 0.1) + 0.014), s > 0 ? "+z" : "-z", { fg: "#111", size: 0.85 });
|
|
8762
|
+
const dia = c.roundBox(0.3, 0.3, 0.012, 0.01, CM("#c3271c"), tx + 2.15, ty - 0.25, s * (hz2(ty - 0.05) + 6e-3));
|
|
8728
8763
|
dia.rotation.z = PI / 4;
|
|
8729
|
-
c.text("3", 0.18, 0.18, tx + 2.15, ty - 0.27, s * (
|
|
8764
|
+
c.text("3", 0.18, 0.18, tx + 2.15, ty - 0.27, s * (hz2(ty - 0.05) + 0.014), s > 0 ? "+z" : "-z", { fg: "#fff", size: 0.9 });
|
|
8730
8765
|
c.text(trl("texts.flammable"), 1.12, 0.3, tx - 0.625, ty + 0.12, s * (sz + 0.012), s > 0 ? "+z" : "-z", { fg: "#b3261e" });
|
|
8731
8766
|
for (let k = 0; k < 11; k++)
|
|
8732
8767
|
c.roundBox(
|
|
@@ -8737,7 +8772,7 @@ var GameVehiclesThree = (() => {
|
|
|
8737
8772
|
k % 2 ? REFL_W : REFL_R,
|
|
8738
8773
|
tx - 2.8 + k * 0.55,
|
|
8739
8774
|
ty - sy * 0.72,
|
|
8740
|
-
s * (
|
|
8775
|
+
s * (hz2(ty - sy * 0.62) + 6e-3)
|
|
8741
8776
|
);
|
|
8742
8777
|
c.roundBox(0.42, 0.42, 0.25, 0.04, CM("#b3261e"), 2.2, 1, s * (W / 2 - 0.15));
|
|
8743
8778
|
});
|
|
@@ -9494,8 +9529,10 @@ var GameVehiclesThree = (() => {
|
|
|
9494
9529
|
c.cylinder(0.36, 0.38, 0.1, plate, -1.3, 3.13, 0);
|
|
9495
9530
|
c.cylinder(0.3, 0.3, 0.05, MT.steel, -1.3, 3.2, 0);
|
|
9496
9531
|
c.roundBox(0.2, 0.08, 1.3, 0.03, MT.trim, bx0 - 0.25, 3.13, 0);
|
|
9497
|
-
[-0.45, 0, 0.45].forEach(function(z) {
|
|
9498
|
-
c.roundBox(0.14, 0.08, 0.3, 0.03, MT.amber, bx0 - 0.25, 3.2, z);
|
|
9532
|
+
[-0.45, 0, 0.45].forEach(function(z, i) {
|
|
9533
|
+
const lamp = c.roundBox(0.14, 0.08, 0.3, 0.03, MT.amber, bx0 - 0.25, 3.2, z);
|
|
9534
|
+
lamp.userData.lamp = "beacon";
|
|
9535
|
+
lamp.userData.beaconSide = i % 2;
|
|
9499
9536
|
});
|
|
9500
9537
|
c.rod(new V3(-2.5, 3.08, 0.6), new V3(-2.5, 3.6, 0.6), 8e-3, MT.trim);
|
|
9501
9538
|
c.rod(new V3(-2.8, 3.08, -0.6), new V3(-2.8, 3.4, -0.6), 0.01, MT.trim);
|
|
@@ -11753,7 +11790,7 @@ var GameVehiclesThree = (() => {
|
|
|
11753
11790
|
m.castShadow = true;
|
|
11754
11791
|
m.receiveShadow = false;
|
|
11755
11792
|
for (let k = 0; k < 14; k++) {
|
|
11756
|
-
const hx = x0 + 0.2 + (x1 - x0 - 0.4) * kit.hash(k, 1, 7),
|
|
11793
|
+
const hx = x0 + 0.2 + (x1 - x0 - 0.4) * kit.hash(k, 1, 7), hz2 = (kit.hash(k, 2, 7) - 0.5) * w * 0.85, n = 3 + Math.floor(kit.hash(k, 4, 7) * 3);
|
|
11757
11794
|
for (let q = 0; q < n; q++) {
|
|
11758
11795
|
const r = 0.07 + kit.hash(k, q, 11) * 0.07, geo = new THREE.IcosahedronGeometry(r, 1), p = geo.attributes.position;
|
|
11759
11796
|
for (let vi = 0; vi < p.count; vi++) {
|
|
@@ -11761,7 +11798,7 @@ var GameVehiclesThree = (() => {
|
|
|
11761
11798
|
p.setXYZ(vi, p.getX(vi) * f, p.getY(vi) * f * 0.8, p.getZ(vi) * f);
|
|
11762
11799
|
}
|
|
11763
11800
|
geo.computeVertexNormals();
|
|
11764
|
-
const ang = q / n * PI * 2 + k, tf = c.add(geo, (k + q) % 2 ? NET : NET2, hx + Math.cos(ang) * 0.1, prof(
|
|
11801
|
+
const ang = q / n * PI * 2 + k, tf = c.add(geo, (k + q) % 2 ? NET : NET2, hx + Math.cos(ang) * 0.1, prof(hz2) + 0.1 + r * 0.5, hz2 + Math.sin(ang) * 0.1);
|
|
11765
11802
|
tf.rotation.set(kit.hash(k, q, 1) * 3, kit.hash(k, q, 2) * 3, 0);
|
|
11766
11803
|
}
|
|
11767
11804
|
}
|
|
@@ -13644,7 +13681,7 @@ var GameVehiclesThree = (() => {
|
|
|
13644
13681
|
}
|
|
13645
13682
|
};
|
|
13646
13683
|
}
|
|
13647
|
-
function militaryRotor(c, x, y, z, n, len,
|
|
13684
|
+
function militaryRotor(c, x, y, z, n, len, chord2, mat, o) {
|
|
13648
13685
|
o = o || {};
|
|
13649
13686
|
const g = new THREE.Group();
|
|
13650
13687
|
g.position.set(x, y, z);
|
|
@@ -13652,7 +13689,7 @@ var GameVehiclesThree = (() => {
|
|
|
13652
13689
|
for (let i = 0; i < n; i++) {
|
|
13653
13690
|
const piv = new THREE.Group();
|
|
13654
13691
|
piv.rotation[o.axis === "z" ? "z" : "y"] = i / n * PI * 2 + (o.phase || 0);
|
|
13655
|
-
const geo = G2.roundedBox(len, o.th || 0.06,
|
|
13692
|
+
const geo = G2.roundedBox(len, o.th || 0.06, chord2, 0.02);
|
|
13656
13693
|
geo.translate(len / 2 + (o.hub || 0.3), 0, 0);
|
|
13657
13694
|
if (o.droop) {
|
|
13658
13695
|
const p = geo.attributes.position;
|
|
@@ -13667,7 +13704,7 @@ var GameVehiclesThree = (() => {
|
|
|
13667
13704
|
if (o.axis === "z") b.rotation.x = PI / 2;
|
|
13668
13705
|
piv.add(b);
|
|
13669
13706
|
if (o.tip) {
|
|
13670
|
-
const tp = new THREE.Mesh(G2.roundedBox(0.25, (o.th || 0.06) + 5e-3,
|
|
13707
|
+
const tp = new THREE.Mesh(G2.roundedBox(0.25, (o.th || 0.06) + 5e-3, chord2 + 5e-3, 0.01), o.tip);
|
|
13671
13708
|
tp.position.set(len + (o.hub || 0.3) - 0.12, -(o.droop || 0), 0);
|
|
13672
13709
|
if (o.axis === "z") tp.rotation.x = PI / 2;
|
|
13673
13710
|
piv.add(tp);
|
|
@@ -14017,7 +14054,7 @@ var GameVehiclesThree = (() => {
|
|
|
14017
14054
|
const THREE = kit.THREE;
|
|
14018
14055
|
const trl = fx.t;
|
|
14019
14056
|
const lbl = fx.label;
|
|
14020
|
-
const V3 = kit.V3, PI = Math.PI, MT = kit.materials, CM = kit.makeMaterial, G2 = kit.geo, profX = kit.profX, halfAt = kit.halfAt,
|
|
14057
|
+
const V3 = kit.V3, PI = Math.PI, MT = kit.materials, CM = kit.makeMaterial, G2 = kit.geo, profX = kit.profX, halfAt = kit.halfAt, clamp6 = kit.clamp, smooth2 = kit.smooth;
|
|
14021
14058
|
const GLOSS = CM("#07080a", { roughness: 0.18, metalness: 0.5 });
|
|
14022
14059
|
const ALLOY = CM("#b9bec2", { metalness: 0.75, roughness: 0.3 });
|
|
14023
14060
|
const ALLOYD = CM("#3a3e42", { metalness: 0.6, roughness: 0.35 });
|
|
@@ -14036,7 +14073,7 @@ var GameVehiclesThree = (() => {
|
|
|
14036
14073
|
const a = (y - o.ys) / (o.belt - o.ys);
|
|
14037
14074
|
return o.kt * a * a;
|
|
14038
14075
|
}
|
|
14039
|
-
const b =
|
|
14076
|
+
const b = clamp6((o.ys - y) / (o.ys - o.yb), 0, 1.25);
|
|
14040
14077
|
return o.kb * b * b;
|
|
14041
14078
|
}
|
|
14042
14079
|
const f = function(x, y, z) {
|
|
@@ -14216,13 +14253,13 @@ var GameVehiclesThree = (() => {
|
|
|
14216
14253
|
return L;
|
|
14217
14254
|
}
|
|
14218
14255
|
function roofAt(gh, x) {
|
|
14219
|
-
const rR = gh.roofR || gh.roof, t =
|
|
14256
|
+
const rR = gh.roofR || gh.roof, t = clamp6((x - gh.rt) / (gh.ft - gh.rt), 0, 1);
|
|
14220
14257
|
return rR + (gh.roof - rR) * t + (gh.crown || 0) * 4 * t * (1 - t);
|
|
14221
14258
|
}
|
|
14222
14259
|
function windows(gh) {
|
|
14223
14260
|
const inn = 0.07, rise = gh.rise || 0;
|
|
14224
14261
|
function ybAt(x) {
|
|
14225
|
-
return gh.belt + 0.035 + rise *
|
|
14262
|
+
return gh.belt + 0.035 + rise * clamp6((gh.fb - x) / (gh.fb - gh.rb), 0, 1);
|
|
14226
14263
|
}
|
|
14227
14264
|
function lx(x0, x1, y, top) {
|
|
14228
14265
|
return x0 + (x1 - x0) * (y - gh.belt) / (top - gh.belt);
|
|
@@ -14433,7 +14470,7 @@ var GameVehiclesThree = (() => {
|
|
|
14433
14470
|
}
|
|
14434
14471
|
const G22 = { P, N, nu, nv, y0: o.y0, y1: o.y1, len: tot * (full ? 2 : 1), E, sd };
|
|
14435
14472
|
G22.at = function(u, y) {
|
|
14436
|
-
const fi =
|
|
14473
|
+
const fi = clamp6(u, 0, 1) * nu, fj = clamp6((y - o.y0) / (o.y1 - o.y0), 0, 1) * nv, i0 = Math.min(nu - 1, Math.floor(fi)), j0 = Math.min(nv - 1, Math.floor(fj)), a = fi - i0, b = fj - j0;
|
|
14437
14474
|
function L(M) {
|
|
14438
14475
|
return M[i0][j0].clone().multiplyScalar((1 - a) * (1 - b)).addScaledVector(M[i0 + 1][j0], a * (1 - b)).addScaledVector(M[i0][j0 + 1], (1 - a) * b).addScaledVector(M[i0 + 1][j0 + 1], a * b);
|
|
14439
14476
|
}
|
|
@@ -14994,7 +15031,7 @@ var GameVehiclesThree = (() => {
|
|
|
14994
15031
|
c.roundBox(x1 - x0, 0.08, 0.035, 0.015, MT.trim, (x0 + x1) / 2, by + 0.05, sd * (hw - 8e-3));
|
|
14995
15032
|
if (s.clad)
|
|
14996
15033
|
s.arches.forEach(function(a) {
|
|
14997
|
-
const a0 = Math.asin(
|
|
15034
|
+
const a0 = Math.asin(clamp6((by - a[1]) / a[2], -1, 1)), tor = c.add(new THREE.TorusGeometry(a[2] + 0.02, 0.035, 6, 26, PI - 2 * a0), MT.trim, a[0], a[1], sd * (hw - 0.01));
|
|
14998
15035
|
tor.rotation.z = a0;
|
|
14999
15036
|
tor.scale.z = 0.8;
|
|
15000
15037
|
});
|
|
@@ -15012,8 +15049,11 @@ var GameVehiclesThree = (() => {
|
|
|
15012
15049
|
);
|
|
15013
15050
|
});
|
|
15014
15051
|
const wy = gh.belt + 0.06, wx = gh.fb - 0.03;
|
|
15015
|
-
[-0.3, 0.2].forEach(function(z) {
|
|
15016
|
-
|
|
15052
|
+
[-0.3, 0.2].forEach(function(z, index) {
|
|
15053
|
+
const spindle = new V3(wx + 0.02, wy, z + 0.02);
|
|
15054
|
+
const blade = c.rod(spindle, new V3(wx - 0.13, wy + 0.13, z - 0.36), 9e-3, MT.trim);
|
|
15055
|
+
const along = new V3(gh.ft - gh.fb, gh.roof - gh.belt, 0).normalize();
|
|
15056
|
+
tagWiper({ context: c, parts: [blade], spindle, normal: new V3(along.y, -along.x, 0), index });
|
|
15017
15057
|
});
|
|
15018
15058
|
if (s.fin !== false)
|
|
15019
15059
|
c.sphere(0.1, s.roofCol ? c.paint(s.roofCol) : GLOSS, gh.rt + 0.2, roofAt(gh, gh.rt + 0.2) + 0.045, 0, 1, 0.45, 0.28, {
|
|
@@ -15115,7 +15155,7 @@ var GameVehiclesThree = (() => {
|
|
|
15115
15155
|
c.cylinder(0.06, 0.06, 0.012, MT.head, x + 0.055, y, z, "x");
|
|
15116
15156
|
}
|
|
15117
15157
|
function sm(t) {
|
|
15118
|
-
t =
|
|
15158
|
+
t = clamp6(t, 0, 1);
|
|
15119
15159
|
return t * t * (3 - 2 * t);
|
|
15120
15160
|
}
|
|
15121
15161
|
function sideGrid(S, sd, o) {
|
|
@@ -15132,7 +15172,7 @@ var GameVehiclesThree = (() => {
|
|
|
15132
15172
|
}
|
|
15133
15173
|
const G22 = { P, N, nu, nv, y0: o.y0, y1: o.y1, len: Math.abs(o.x1 - o.x0) };
|
|
15134
15174
|
G22.at = function(u, y) {
|
|
15135
|
-
const fi =
|
|
15175
|
+
const fi = clamp6(u, 0, 1) * nu, fj = clamp6((y - o.y0) / (o.y1 - o.y0), 0, 1) * nv, i0 = Math.min(nu - 1, Math.floor(fi)), j0 = Math.min(nv - 1, Math.floor(fj)), a = fi - i0, b = fj - j0;
|
|
15136
15176
|
function L(M) {
|
|
15137
15177
|
return M[i0][j0].clone().multiplyScalar((1 - a) * (1 - b)).addScaledVector(M[i0 + 1][j0], a * (1 - b)).addScaledVector(M[i0][j0 + 1], (1 - a) * b).addScaledVector(M[i0 + 1][j0 + 1], a * b);
|
|
15138
15178
|
}
|
|
@@ -15293,7 +15333,7 @@ var GameVehiclesThree = (() => {
|
|
|
15293
15333
|
return function(c, I) {
|
|
15294
15334
|
const gh = I.gh, col = c.meta.color;
|
|
15295
15335
|
function yb(x) {
|
|
15296
|
-
return gh.belt + 0.035 + (gh.rise || 0) *
|
|
15336
|
+
return gh.belt + 0.035 + (gh.rise || 0) * clamp6((gh.fb - x) / (gh.fb - gh.rb), 0, 1);
|
|
15297
15337
|
}
|
|
15298
15338
|
;
|
|
15299
15339
|
[1, -1].forEach(function(sd) {
|
|
@@ -16534,6 +16574,10 @@ var GameVehiclesThree = (() => {
|
|
|
16534
16574
|
}
|
|
16535
16575
|
}
|
|
16536
16576
|
});
|
|
16577
|
+
beacon[1].userData.lamp = "beacon";
|
|
16578
|
+
beacon[1].userData.beaconSide = 0;
|
|
16579
|
+
beacon[2].userData.lamp = "beacon";
|
|
16580
|
+
beacon[2].userData.beaconSide = 1;
|
|
16537
16581
|
c2.meta.top = top + 0.15;
|
|
16538
16582
|
c2.meta.roof.y = Math.max(c2.meta.roof.y, top + 0.15);
|
|
16539
16583
|
const fx2 = I.fxB + 0.12, push = [];
|
|
@@ -17836,7 +17880,9 @@ var GameVehiclesThree = (() => {
|
|
|
17836
17880
|
c.roundBox(0.5, 0.018, 6e-3, 2e-3, c.paint("#f2c21a"), -0.7, 0.825, z);
|
|
17837
17881
|
c.text("PRF", 0.2, 0.08, -0.7, 0.73, z + s * 2e-3, f, { fg: "#1f3f8f", size: 0.85 });
|
|
17838
17882
|
c.text(trl("texts.federal_highway_police"), 0.3, 0.035, 0.24, 1, s * 0.3, f, { fg: "#f4f2ea", w: 1024, h: 120, size: 0.8 });
|
|
17839
|
-
c.roundBox(0.05, 0.05, 0.04, 0.012, s > 0 ? MT.blue : MT.tail, 0.62, 0.95, s * 0.3, { def: true });
|
|
17883
|
+
const flasher = c.roundBox(0.05, 0.05, 0.04, 0.012, s > 0 ? MT.blue : MT.tail, 0.62, 0.95, s * 0.3, { def: true });
|
|
17884
|
+
flasher.userData.lamp = "beacon";
|
|
17885
|
+
flasher.userData.beaconSide = s > 0 ? 1 : 0;
|
|
17840
17886
|
});
|
|
17841
17887
|
c.cylinder(0.04, 0.045, 0.06, MT.trim, 0.66, 0.66, 0.36, "x");
|
|
17842
17888
|
}
|
|
@@ -18089,6 +18135,8 @@ var GameVehiclesThree = (() => {
|
|
|
18089
18135
|
fx.register(
|
|
18090
18136
|
{
|
|
18091
18137
|
key: "beetle",
|
|
18138
|
+
// glass headlight lenses, as on cars of its time: they shatter (a modern car's are polycarbonate)
|
|
18139
|
+
headlightLens: "glass",
|
|
18092
18140
|
group: "cars",
|
|
18093
18141
|
name: trl("vehicles.beetle.name"),
|
|
18094
18142
|
inspired: trl("vehicles.beetle.inspired"),
|
|
@@ -18164,7 +18212,7 @@ var GameVehiclesThree = (() => {
|
|
|
18164
18212
|
return n.y > 0.3 && ce.x > 0.9 && ce.y > 0.6;
|
|
18165
18213
|
},
|
|
18166
18214
|
sdf: function(x, y, z) {
|
|
18167
|
-
const t =
|
|
18215
|
+
const t = clamp6((x - 1.17) / 0.5, 0, 1);
|
|
18168
18216
|
return Math.max(0.94 - x, x - 1.69, Math.abs(z) - (0.44 - 0.16 * t * t));
|
|
18169
18217
|
}
|
|
18170
18218
|
});
|
|
@@ -18868,8 +18916,8 @@ var GameVehiclesThree = (() => {
|
|
|
18868
18916
|
];
|
|
18869
18917
|
body(c, RB, col);
|
|
18870
18918
|
[1, -1].forEach(function(s) {
|
|
18871
|
-
const x = -0.3, y = 0.6,
|
|
18872
|
-
c.text(trl("texts.bis_125"), 0.2, 0.05, x, y, s *
|
|
18919
|
+
const x = -0.3, y = 0.6, hz2 = loftHalf(RB, x, y) + 4e-3;
|
|
18920
|
+
c.text(trl("texts.bis_125"), 0.2, 0.05, x, y, s * hz2, s > 0 ? "+z" : "-z", { fg: "#f2f0ea", size: 0.85 });
|
|
18873
18921
|
body(
|
|
18874
18922
|
c,
|
|
18875
18923
|
[
|
|
@@ -22162,7 +22210,7 @@ var GameVehiclesThree = (() => {
|
|
|
22162
22210
|
const THREE = kit.THREE;
|
|
22163
22211
|
const trl = fx.t;
|
|
22164
22212
|
const lbl = fx.label;
|
|
22165
|
-
const V3 = kit.V3, PI = Math.PI, MT = kit.materials, CM = kit.makeMaterial,
|
|
22213
|
+
const V3 = kit.V3, PI = Math.PI, MT = kit.materials, CM = kit.makeMaterial, clamp6 = kit.clamp, smooth2 = kit.smooth;
|
|
22166
22214
|
const CLAD = CM("#1a1b1d", { roughness: 0.82 }), LINER = CM("#1c1d1f", { roughness: 0.92 }), RIMDARK = CM("#2a2d30", { metalness: 0.6, roughness: 0.4 });
|
|
22167
22215
|
const RIMSIL = CM("#b9bec2", { metalness: 0.75, roughness: 0.3 }), RIMGUN = CM("#55595d", { metalness: 0.7, roughness: 0.35 });
|
|
22168
22216
|
function axles(WB, oF, L, dF, dR) {
|
|
@@ -22193,16 +22241,16 @@ var GameVehiclesThree = (() => {
|
|
|
22193
22241
|
const m = c.meta, W = m.width, by = o.bottom != null ? o.bottom : m.clearance, top = o.top != null ? o.top : m.belt;
|
|
22194
22242
|
const Wg = m.glasshouse && m.glasshouse.Wg || W, front = m.front, rear = m.rear;
|
|
22195
22243
|
const tuck = o.tuck == null ? 0.045 : o.tuck, peak = o.peak || 0.45;
|
|
22196
|
-
const B = o.sh != null ? o.sh :
|
|
22244
|
+
const B = o.sh != null ? o.sh : clamp6(1 - (Wg + 0.06) / W, 0, 0.06);
|
|
22197
22245
|
const Rf = o.Rf || 0.55, Rr = o.Rr || 0.42, pf = o.pf == null ? 0.08 : o.pf, pr = o.pr == null ? 0.05 : o.pr;
|
|
22198
22246
|
const bowF = o.bowF == null ? 0.07 : o.bowF, bowR = o.bowR == null ? 0.04 : o.bowR, Rb = o.Rb || 0.35, hw = W / 2;
|
|
22199
22247
|
const crown = o.crown == null ? 0.045 : o.crown, xc = o.crownX != null ? o.crownX : m.glasshouse ? m.glasshouse.fb : front - 1, y0 = by + 0.55 * (top - by);
|
|
22200
22248
|
function sc(y) {
|
|
22201
|
-
const t =
|
|
22249
|
+
const t = clamp6((y - by) / (top - by), 0, 1);
|
|
22202
22250
|
return t < peak ? 1 - tuck * Math.pow(1 - t / peak, 2) : 1 - B * Math.pow((t - peak) / (1 - peak), 2);
|
|
22203
22251
|
}
|
|
22204
22252
|
function F(v2) {
|
|
22205
|
-
const a = smooth2((v2.x - (front - Rf)) / Rf), b = smooth2((rear + Rr - v2.x) / Rr), zz =
|
|
22253
|
+
const a = smooth2((v2.x - (front - Rf)) / Rf), b = smooth2((rear + Rr - v2.x) / Rr), zz = clamp6(v2.z / hw, -1, 1) * clamp6(v2.z / hw, -1, 1);
|
|
22206
22254
|
const bf = smooth2((v2.x - (front - Rb)) / Rb), br = smooth2((rear + Rb - v2.x) / Rb);
|
|
22207
22255
|
const cr = crown * (1 - zz) * smooth2((v2.y - y0) / (top - y0)) * smooth2((v2.x - xc) / 0.3);
|
|
22208
22256
|
v2.x += -bowF * zz * bf + bowR * zz * br;
|
|
@@ -22279,7 +22327,7 @@ var GameVehiclesThree = (() => {
|
|
|
22279
22327
|
o = o || {};
|
|
22280
22328
|
const wd = o.w || 0.075, dp = o.d || 0.045, mat = o.mat || CLAD, out = [];
|
|
22281
22329
|
arches.forEach(function(a) {
|
|
22282
|
-
const a0 = Math.asin(
|
|
22330
|
+
const a0 = Math.asin(clamp6((by - a[1]) / a[2], -1, 1)) - 0.02, r0 = a[2] - (o.inner == null ? 0.055 : o.inner), r1 = a[2] + wd;
|
|
22283
22331
|
const sh = new THREE.Shape();
|
|
22284
22332
|
if (o.trap) {
|
|
22285
22333
|
const yb0 = Math.sin(a0) * r1, xb0 = Math.cos(a0) * r1, top = r1 * 0.93, xt = r1 * 0.52;
|
|
@@ -22629,7 +22677,7 @@ var GameVehiclesThree = (() => {
|
|
|
22629
22677
|
function roof(c, drop, x0, x1) {
|
|
22630
22678
|
const m = c.meta, b = m.glasshouse.belt, h = m.top - b;
|
|
22631
22679
|
function dy(x, y) {
|
|
22632
|
-
const t =
|
|
22680
|
+
const t = clamp6((y - b) / h, 0, 1);
|
|
22633
22681
|
return t <= 0 ? 0 : drop * smooth2((x0 - x) / (x0 - x1)) * t;
|
|
22634
22682
|
}
|
|
22635
22683
|
c.root.updateMatrixWorld(true);
|
|
@@ -23116,17 +23164,17 @@ var GameVehiclesThree = (() => {
|
|
|
23116
23164
|
}
|
|
23117
23165
|
beltline(c2, -0.35, 0.035, col);
|
|
23118
23166
|
pillarC(c2, -1.12, [-1.36, 1.25]);
|
|
23119
|
-
const E = glasshouse(c2),
|
|
23167
|
+
const E = glasshouse(c2), hz2 = function(y) {
|
|
23120
23168
|
return kit.halfAt(m.glasshouse.Wg, m.tumble, y) + 0.03;
|
|
23121
23169
|
};
|
|
23122
23170
|
[1, -1].forEach(function(sd) {
|
|
23123
23171
|
c2.tube(
|
|
23124
23172
|
[
|
|
23125
|
-
[m.glasshouse.fb - 0.08, E.yb - 0.03, sd *
|
|
23126
|
-
[-0.35, E.yb - 0.03, sd *
|
|
23127
|
-
[-1.45, E.yb + 0.01, sd *
|
|
23128
|
-
[E.back(E.yb + 0.15) + 0.05, E.yb + 0.15, sd *
|
|
23129
|
-
[E.back(E.top - 0.05) + 0.06, E.top - 0.05, sd *
|
|
23173
|
+
[m.glasshouse.fb - 0.08, E.yb - 0.03, sd * hz2(E.yb)],
|
|
23174
|
+
[-0.35, E.yb - 0.03, sd * hz2(E.yb)],
|
|
23175
|
+
[-1.45, E.yb + 0.01, sd * hz2(E.yb)],
|
|
23176
|
+
[E.back(E.yb + 0.15) + 0.05, E.yb + 0.15, sd * hz2(E.yb + 0.15)],
|
|
23177
|
+
[E.back(E.top - 0.05) + 0.06, E.top - 0.05, sd * hz2(E.top - 0.05)]
|
|
23130
23178
|
],
|
|
23131
23179
|
9e-3,
|
|
23132
23180
|
MT.chrome,
|
|
@@ -23823,8 +23871,8 @@ var GameVehiclesThree = (() => {
|
|
|
23823
23871
|
setOnHit(pt, function(c2, p0) {
|
|
23824
23872
|
const o = p0.obj;
|
|
23825
23873
|
if (o && o.userData.hung && o.parent && o.parent !== c2.vehicle) {
|
|
23826
|
-
o.parent.rotation.x =
|
|
23827
|
-
o.parent.rotation.y =
|
|
23874
|
+
o.parent.rotation.x = clamp6(o.parent.rotation.x, -0.22, 0.22);
|
|
23875
|
+
o.parent.rotation.y = clamp6(o.parent.rotation.y, -0.08, 0.08);
|
|
23828
23876
|
}
|
|
23829
23877
|
});
|
|
23830
23878
|
});
|
|
@@ -24365,18 +24413,19 @@ var GameVehiclesThree = (() => {
|
|
|
24365
24413
|
c2.roundBox(0.03, 0.12, 1.9, 0.01, rd, m.rear - 8e-3, 1.1, 0);
|
|
24366
24414
|
const beaconBar = [c2.roundBox(0.3, 0.08, 1.5, 0.03, MT.trim, 0.6, m.top + 0.04, 0)];
|
|
24367
24415
|
[-0.5, -0.17, 0.17, 0.5].forEach(function(z, i) {
|
|
24368
|
-
|
|
24369
|
-
|
|
24370
|
-
|
|
24371
|
-
|
|
24372
|
-
|
|
24373
|
-
|
|
24374
|
-
|
|
24375
|
-
|
|
24376
|
-
|
|
24377
|
-
z
|
|
24378
|
-
)
|
|
24416
|
+
const lamp = c2.roundBox(
|
|
24417
|
+
0.24,
|
|
24418
|
+
0.1,
|
|
24419
|
+
0.3,
|
|
24420
|
+
0.04,
|
|
24421
|
+
i % 2 ? MT.tail : CM("#f2f2f2", { emissive: new THREE.Color("#ffffff"), emissiveIntensity: 0.6 }),
|
|
24422
|
+
0.6,
|
|
24423
|
+
m.top + 0.13,
|
|
24424
|
+
z
|
|
24379
24425
|
);
|
|
24426
|
+
lamp.userData.lamp = "beacon";
|
|
24427
|
+
lamp.userData.beaconSide = z < 0 ? 0 : 1;
|
|
24428
|
+
beaconBar.push(lamp);
|
|
24380
24429
|
});
|
|
24381
24430
|
beaconBar.push(
|
|
24382
24431
|
c2.roundBox(
|
|
@@ -24475,7 +24524,7 @@ var GameVehiclesThree = (() => {
|
|
|
24475
24524
|
const shared2 = fx.shared;
|
|
24476
24525
|
const trl = fx.t;
|
|
24477
24526
|
const lbl = fx.label;
|
|
24478
|
-
const V3 = kit.V3, PI = Math.PI, MT = kit.materials, CM = kit.makeMaterial, _paintCol = kit.paintColor, G2 = kit.geo, DS = THREE.DoubleSide,
|
|
24527
|
+
const V3 = kit.V3, PI = Math.PI, MT = kit.materials, CM = kit.makeMaterial, _paintCol = kit.paintColor, G2 = kit.geo, DS = THREE.DoubleSide, clamp6 = kit.clamp;
|
|
24479
24528
|
function colorize(geo, fn) {
|
|
24480
24529
|
const p = geo.attributes.position, col = new Float32Array(p.count * 3);
|
|
24481
24530
|
for (let i = 0; i < p.count; i++) {
|
|
@@ -24491,7 +24540,7 @@ var GameVehiclesThree = (() => {
|
|
|
24491
24540
|
return a + (b - a) * t;
|
|
24492
24541
|
}
|
|
24493
24542
|
function sstep(a, b, x) {
|
|
24494
|
-
const t =
|
|
24543
|
+
const t = clamp6((x - a) / (b - a), 0, 1);
|
|
24495
24544
|
return t * t * (3 - 2 * t);
|
|
24496
24545
|
}
|
|
24497
24546
|
function tab(T) {
|
|
@@ -24568,7 +24617,7 @@ var GameVehiclesThree = (() => {
|
|
|
24568
24617
|
o,
|
|
24569
24618
|
sec,
|
|
24570
24619
|
t: function(x) {
|
|
24571
|
-
return
|
|
24620
|
+
return clamp6((x - o.x0) / o.L, 0, 1);
|
|
24572
24621
|
},
|
|
24573
24622
|
/* half beam of the hull at height y (inside, so floors and decks do not leak) */
|
|
24574
24623
|
half: function(x, y) {
|
|
@@ -24742,7 +24791,7 @@ var GameVehiclesThree = (() => {
|
|
|
24742
24791
|
for (let i = 0, j = poly.length - 1; i < poly.length; j = i++) {
|
|
24743
24792
|
const a = poly[i], b = poly[j];
|
|
24744
24793
|
if (a[1] > y !== b[1] > y && x < (b[0] - a[0]) * (y - a[1]) / (b[1] - a[1]) + a[0]) inside = !inside;
|
|
24745
|
-
const vx = b[0] - a[0], vy = b[1] - a[1], wx = x - a[0], wy = y - a[1], t =
|
|
24794
|
+
const vx = b[0] - a[0], vy = b[1] - a[1], wx = x - a[0], wy = y - a[1], t = clamp6((wx * vx + wy * vy) / (vx * vx + vy * vy), 0, 1);
|
|
24746
24795
|
d = Math.min(d, Math.hypot(wx - vx * t, wy - vy * t));
|
|
24747
24796
|
}
|
|
24748
24797
|
return inside ? -d : d;
|
|
@@ -27290,6 +27339,7 @@ var GameVehiclesThree = (() => {
|
|
|
27290
27339
|
shared: shared2,
|
|
27291
27340
|
t,
|
|
27292
27341
|
label: (key) => ({ key, label: t("labels." + key) }),
|
|
27342
|
+
hasSunroof: (key) => !!options.sunroofs?.includes(key),
|
|
27293
27343
|
register(spec, build) {
|
|
27294
27344
|
if (!groups.has(spec.group) || only && !only.has(spec.key) || skip.has(spec.key)) return;
|
|
27295
27345
|
kit.register({ ...spec, seedKey: legacyVehicleSeeds[spec.key] }, build);
|
|
@@ -27864,7 +27914,8 @@ var GameVehiclesThree = (() => {
|
|
|
27864
27914
|
const tmp = new THREE.Box3();
|
|
27865
27915
|
let pruned = 0;
|
|
27866
27916
|
c.vehicle.updateMatrixWorld(true);
|
|
27867
|
-
c.vehicle.traverse((
|
|
27917
|
+
c.vehicle.traverse((node) => {
|
|
27918
|
+
const o = node;
|
|
27868
27919
|
if (!o.isMesh || o.isInstancedMesh || o.isSkinnedMesh || !o.geometry || !o.geometry.attributes.position) return;
|
|
27869
27920
|
for (let p = o; p; p = p.parent) if (p.visible === false) return;
|
|
27870
27921
|
if (o.userData && (o.userData.ghost || o.userData.skipLite)) return;
|
|
@@ -27967,7 +28018,8 @@ var GameVehiclesThree = (() => {
|
|
|
27967
28018
|
function count(root) {
|
|
27968
28019
|
let triangles = 0;
|
|
27969
28020
|
let drawCalls = 0;
|
|
27970
|
-
root.traverse((
|
|
28021
|
+
root.traverse((node) => {
|
|
28022
|
+
const o = node;
|
|
27971
28023
|
if (!o.isMesh || !o.geometry) return;
|
|
27972
28024
|
for (let p = o; p; p = p.parent) if (p.visible === false) return;
|
|
27973
28025
|
const g = o.geometry;
|
|
@@ -27982,7 +28034,8 @@ var GameVehiclesThree = (() => {
|
|
|
27982
28034
|
let best = null;
|
|
27983
28035
|
let bestCount = -1;
|
|
27984
28036
|
const counts = /* @__PURE__ */ new Map();
|
|
27985
|
-
c.vehicle.traverse((
|
|
28037
|
+
c.vehicle.traverse((node) => {
|
|
28038
|
+
const o = node;
|
|
27986
28039
|
if (!o.isMesh || !o.geometry) return;
|
|
27987
28040
|
const mats = Array.isArray(o.material) ? o.material : [o.material];
|
|
27988
28041
|
const g = o.geometry;
|
|
@@ -28027,7 +28080,8 @@ var GameVehiclesThree = (() => {
|
|
|
28027
28080
|
const bounds = new THREE.Box3();
|
|
28028
28081
|
const piece = new THREE.Box3();
|
|
28029
28082
|
const turned = new THREE.Matrix4();
|
|
28030
|
-
c.vehicle.traverse((
|
|
28083
|
+
c.vehicle.traverse((node) => {
|
|
28084
|
+
const m = node;
|
|
28031
28085
|
if (!m.isMesh || !m.geometry || m.userData.ghost) return;
|
|
28032
28086
|
for (let p = m; p; p = p.parent) if (p.visible === false) return;
|
|
28033
28087
|
m.geometry.computeBoundingBox();
|
|
@@ -28056,7 +28110,8 @@ var GameVehiclesThree = (() => {
|
|
|
28056
28110
|
if (color2 && primary) {
|
|
28057
28111
|
const repainted = primary.clone();
|
|
28058
28112
|
repainted.color.set(color2);
|
|
28059
|
-
c.vehicle.traverse((
|
|
28113
|
+
c.vehicle.traverse((node) => {
|
|
28114
|
+
const m = node;
|
|
28060
28115
|
if (!m.isMesh) return;
|
|
28061
28116
|
if (Array.isArray(m.material)) m.material = m.material.map((x) => x === primary ? repainted : x);
|
|
28062
28117
|
else if (m.material === primary) m.material = repainted;
|
|
@@ -28092,7 +28147,8 @@ var GameVehiclesThree = (() => {
|
|
|
28092
28147
|
context: quality === "high" ? c : null,
|
|
28093
28148
|
driverEye,
|
|
28094
28149
|
dispose() {
|
|
28095
|
-
group.traverse((
|
|
28150
|
+
group.traverse((node) => {
|
|
28151
|
+
const m = node;
|
|
28096
28152
|
if (m.geometry) m.geometry.dispose();
|
|
28097
28153
|
});
|
|
28098
28154
|
}
|
|
@@ -28114,7 +28170,7 @@ var GameVehiclesThree = (() => {
|
|
|
28114
28170
|
}
|
|
28115
28171
|
}
|
|
28116
28172
|
|
|
28117
|
-
// ../game-shapes/dist/chunk-
|
|
28173
|
+
// ../game-shapes/dist/chunk-FZQTELDQ.js
|
|
28118
28174
|
function canonicalJson(value) {
|
|
28119
28175
|
if (value === null) return "null";
|
|
28120
28176
|
if (typeof value === "number") return Object.is(value, -0) ? "-0" : Number.isFinite(value) ? String(value) : JSON.stringify(String(value));
|
|
@@ -28990,17 +29046,19 @@ var GameVehiclesThree = (() => {
|
|
|
28990
29046
|
if (p.prevZ) p.prevZ.nextZ = p.nextZ;
|
|
28991
29047
|
if (p.nextZ) p.nextZ.prevZ = p.prevZ;
|
|
28992
29048
|
}
|
|
28993
|
-
|
|
28994
|
-
|
|
28995
|
-
|
|
28996
|
-
|
|
28997
|
-
|
|
28998
|
-
|
|
28999
|
-
|
|
29000
|
-
|
|
29001
|
-
|
|
29002
|
-
|
|
29003
|
-
|
|
29049
|
+
var Node = class {
|
|
29050
|
+
constructor(i, x, y) {
|
|
29051
|
+
this.i = i;
|
|
29052
|
+
this.x = x;
|
|
29053
|
+
this.y = y;
|
|
29054
|
+
this.prev = null;
|
|
29055
|
+
this.next = null;
|
|
29056
|
+
this.z = 0;
|
|
29057
|
+
this.prevZ = null;
|
|
29058
|
+
this.nextZ = null;
|
|
29059
|
+
this.steiner = false;
|
|
29060
|
+
}
|
|
29061
|
+
};
|
|
29004
29062
|
function signedArea(data, start2, end, dim) {
|
|
29005
29063
|
let sum = 0;
|
|
29006
29064
|
for (let i = start2, j = end - dim; i < end; i += dim) {
|
|
@@ -29267,8 +29325,8 @@ var GameVehiclesThree = (() => {
|
|
|
29267
29325
|
const face = faces[i];
|
|
29268
29326
|
f3(face[2] + offset, face[1] + offset, face[0] + offset);
|
|
29269
29327
|
}
|
|
29270
|
-
const
|
|
29271
|
-
offset = vlen *
|
|
29328
|
+
const layer2 = steps + bevelSegments * 2;
|
|
29329
|
+
offset = vlen * layer2;
|
|
29272
29330
|
for (let i = 0; i < flen; i++) {
|
|
29273
29331
|
const face = faces[i];
|
|
29274
29332
|
f3(face[0] + offset, face[1] + offset, face[2] + offset);
|
|
@@ -30151,10 +30209,11 @@ var GameVehiclesThree = (() => {
|
|
|
30151
30209
|
return out;
|
|
30152
30210
|
}
|
|
30153
30211
|
function assignDeep(target, source) {
|
|
30212
|
+
const t = target;
|
|
30154
30213
|
Object.keys(source || {}).forEach(function(k) {
|
|
30155
30214
|
const v = source[k];
|
|
30156
|
-
if (v && typeof v === "object" && !Array.isArray(v))
|
|
30157
|
-
else if (v !== void 0)
|
|
30215
|
+
if (v && typeof v === "object" && !Array.isArray(v)) t[k] = assignDeep(t[k] && typeof t[k] === "object" ? t[k] : {}, v);
|
|
30216
|
+
else if (v !== void 0) t[k] = v;
|
|
30158
30217
|
});
|
|
30159
30218
|
return target;
|
|
30160
30219
|
}
|
|
@@ -30421,30 +30480,30 @@ var GameVehiclesThree = (() => {
|
|
|
30421
30480
|
function makeFlatMaterial(color2, o) {
|
|
30422
30481
|
return makeMaterial(color2, Object.assign({ flatShading: true, roughness: 0.92 }, o || {}));
|
|
30423
30482
|
}
|
|
30424
|
-
const
|
|
30483
|
+
const DOUBLE_SIDE2 = THREE.DoubleSide;
|
|
30425
30484
|
function toColor(hex) {
|
|
30426
30485
|
return new THREE.Color(hex);
|
|
30427
30486
|
}
|
|
30428
30487
|
const MATERIALS = {
|
|
30429
30488
|
trim: makeMaterial("#17191b", { roughness: 0.7 }),
|
|
30430
|
-
rubber: makeMaterial("#111111", { roughness: 0.95, side:
|
|
30489
|
+
rubber: makeMaterial("#111111", { roughness: 0.95, side: DOUBLE_SIDE2 }),
|
|
30431
30490
|
chrome: makeMaterial("#b8bcbf", { metalness: 0.9, roughness: 0.28 }),
|
|
30432
30491
|
steel: makeMaterial("#6c7175", { metalness: 0.7, roughness: 0.45 }),
|
|
30433
|
-
glass: makeMaterial("#2a3c44", { roughness: 0.05, metalness: 0.25, transparent: true, opacity: 0.4, depthWrite: false, side:
|
|
30434
|
-
tint: makeMaterial("#121a1e", { roughness: 0.05, metalness: 0.3, transparent: true, opacity: 0.62, depthWrite: false, side:
|
|
30492
|
+
glass: makeMaterial("#2a3c44", { roughness: 0.05, metalness: 0.25, transparent: true, opacity: 0.4, depthWrite: false, side: DOUBLE_SIDE2 }),
|
|
30493
|
+
tint: makeMaterial("#121a1e", { roughness: 0.05, metalness: 0.3, transparent: true, opacity: 0.62, depthWrite: false, side: DOUBLE_SIDE2 }),
|
|
30435
30494
|
/* rear glass: darker, so the interior does not look like an open bed seen from behind */
|
|
30436
|
-
rearTint: makeMaterial("#0c1114", { roughness: 0.04, metalness: 0.45, transparent: true, opacity: 0.84, depthWrite: false, side:
|
|
30437
|
-
glassDark: makeMaterial("#0c1317", { roughness: 0.06, metalness: 0.75, side:
|
|
30438
|
-
armorGlass: makeMaterial("#1d302d", { roughness: 0.08, metalness: 0.4, transparent: true, opacity: 0.6, depthWrite: false, side:
|
|
30439
|
-
glassEdge: makeMaterial("#a9bcc1", { roughness: 0.25, metalness: 0.1, transparent: true, opacity: 0.6, depthWrite: false, side:
|
|
30495
|
+
rearTint: makeMaterial("#0c1114", { roughness: 0.04, metalness: 0.45, transparent: true, opacity: 0.84, depthWrite: false, side: DOUBLE_SIDE2 }),
|
|
30496
|
+
glassDark: makeMaterial("#0c1317", { roughness: 0.06, metalness: 0.75, side: DOUBLE_SIDE2 }),
|
|
30497
|
+
armorGlass: makeMaterial("#1d302d", { roughness: 0.08, metalness: 0.4, transparent: true, opacity: 0.6, depthWrite: false, side: DOUBLE_SIDE2 }),
|
|
30498
|
+
glassEdge: makeMaterial("#a9bcc1", { roughness: 0.25, metalness: 0.1, transparent: true, opacity: 0.6, depthWrite: false, side: DOUBLE_SIDE2 }),
|
|
30440
30499
|
lens: makeMaterial("#eef3f5", { roughness: 0.03, metalness: 0.1, transparent: true, opacity: 0.16, depthWrite: false }),
|
|
30441
30500
|
lensRed: makeMaterial("#c0281c", { roughness: 0.04, metalness: 0.1, transparent: true, opacity: 0.42, depthWrite: false }),
|
|
30442
30501
|
lensAmber: makeMaterial("#d88a2a", { roughness: 0.04, transparent: true, opacity: 0.4, depthWrite: false }),
|
|
30443
30502
|
housing: makeMaterial("#111214", { roughness: 0.45, metalness: 0.2 }),
|
|
30444
|
-
reflector: makeMaterial("#dfe3e6", { metalness: 0.9, roughness: 0.12, side:
|
|
30445
|
-
reflectorLit: makeMaterial("#e8e2cc", { metalness: 0.6, roughness: 0.18, emissive: toColor("#cfc19a"), emissiveIntensity: 1.6, side:
|
|
30446
|
-
hole: makeMaterial("#040506", { roughness: 1, side:
|
|
30447
|
-
dark: makeMaterial("#0a0b0c", { roughness: 1, side:
|
|
30503
|
+
reflector: makeMaterial("#dfe3e6", { metalness: 0.9, roughness: 0.12, side: DOUBLE_SIDE2 }),
|
|
30504
|
+
reflectorLit: makeMaterial("#e8e2cc", { metalness: 0.6, roughness: 0.18, emissive: toColor("#cfc19a"), emissiveIntensity: 1.6, side: DOUBLE_SIDE2 }),
|
|
30505
|
+
hole: makeMaterial("#040506", { roughness: 1, side: DOUBLE_SIDE2 }),
|
|
30506
|
+
dark: makeMaterial("#0a0b0c", { roughness: 1, side: DOUBLE_SIDE2 }),
|
|
30448
30507
|
head: makeMaterial("#efe6c9", { emissive: toColor("#f0dcaa"), emissiveIntensity: 1.7, roughness: 0.2 }),
|
|
30449
30508
|
led: makeMaterial("#e6f2ff", { emissive: toColor("#cfe6ff"), emissiveIntensity: 1.6, roughness: 0.2 }),
|
|
30450
30509
|
tail: makeMaterial("#8a1a14", { emissive: toColor("#7a0d08"), emissiveIntensity: 0.8, roughness: 0.25 }),
|
|
@@ -30457,14 +30516,14 @@ var GameVehiclesThree = (() => {
|
|
|
30457
30516
|
wood: makeMaterial("#6b4a2e", { roughness: 0.9 }),
|
|
30458
30517
|
leather: makeMaterial("#4a2f20", { roughness: 0.7 }),
|
|
30459
30518
|
seat: makeMaterial("#1e1f22", { roughness: 0.85 }),
|
|
30460
|
-
alu: makeMaterial("#8e959a", { metalness: 0.6, roughness: 0.42, side:
|
|
30519
|
+
alu: makeMaterial("#8e959a", { metalness: 0.6, roughness: 0.42, side: DOUBLE_SIDE2 }),
|
|
30461
30520
|
carpet: makeMaterial("#141517", { roughness: 1 }),
|
|
30462
30521
|
plastic: makeMaterial("#1f2023", { roughness: 0.75 }),
|
|
30463
|
-
headliner: makeMaterial("#6f6c66", { roughness: 0.95, side:
|
|
30522
|
+
headliner: makeMaterial("#6f6c66", { roughness: 0.95, side: DOUBLE_SIDE2 }),
|
|
30464
30523
|
gauge: makeMaterial("#0d1512", { emissive: toColor("#4fbf8a"), emissiveIntensity: 0.35, roughness: 0.4 }),
|
|
30465
30524
|
screen: makeMaterial("#0b1220", { emissive: toColor("#3d6cb0"), emissiveIntensity: 0.4, roughness: 0.2 }),
|
|
30466
|
-
bay: makeMaterial("#2c3033", { roughness: 0.8, metalness: 0.2, emissive: toColor("#0c0e10"), emissiveIntensity: 1, side:
|
|
30467
|
-
hoodLiner: makeMaterial("#1c1d1e", { roughness: 0.95, side:
|
|
30525
|
+
bay: makeMaterial("#2c3033", { roughness: 0.8, metalness: 0.2, emissive: toColor("#0c0e10"), emissiveIntensity: 1, side: DOUBLE_SIDE2 }),
|
|
30526
|
+
hoodLiner: makeMaterial("#1c1d1e", { roughness: 0.95, side: DOUBLE_SIDE2 }),
|
|
30468
30527
|
block: makeMaterial("#a3abb0", { metalness: 0.55, roughness: 0.38, emissive: toColor("#1a1d1f"), emissiveIntensity: 1 }),
|
|
30469
30528
|
cover: makeMaterial("#3c4044", { metalness: 0.4, roughness: 0.35, emissive: toColor("#101213"), emissiveIntensity: 1 }),
|
|
30470
30529
|
radiator: makeMaterial("#3a3f42", { metalness: 0.5, roughness: 0.55 }),
|
|
@@ -30531,7 +30590,9 @@ var GameVehiclesThree = (() => {
|
|
|
30531
30590
|
return t;
|
|
30532
30591
|
}
|
|
30533
30592
|
kit.textTexture = textTexture;
|
|
30534
|
-
|
|
30593
|
+
const shared2 = { RUST, cache: cache2, studioEnvironment, makeMaterial, makeFlatMaterial, DOUBLE_SIDE: DOUBLE_SIDE2, toColor, MATERIALS, paintColor, texCache, textTexture };
|
|
30594
|
+
Object.assign(I, shared2);
|
|
30595
|
+
return shared2;
|
|
30535
30596
|
}
|
|
30536
30597
|
var TRI_BLOCK = 32;
|
|
30537
30598
|
var cache = /* @__PURE__ */ new WeakMap();
|
|
@@ -30684,7 +30745,8 @@ var GameVehiclesThree = (() => {
|
|
|
30684
30745
|
}
|
|
30685
30746
|
return s;
|
|
30686
30747
|
}
|
|
30687
|
-
function indexable(THREE,
|
|
30748
|
+
function indexable(THREE, object2) {
|
|
30749
|
+
const mesh2 = object2;
|
|
30688
30750
|
const geo = mesh2.geometry;
|
|
30689
30751
|
if (mesh2.raycast !== THREE.Mesh.prototype.raycast) return false;
|
|
30690
30752
|
if (!mesh2.isMesh || mesh2.isSkinnedMesh || mesh2.isInstancedMesh || mesh2.isBatchedMesh || !geo || !geo.isBufferGeometry) return false;
|
|
@@ -30771,7 +30833,7 @@ var GameVehiclesThree = (() => {
|
|
|
30771
30833
|
const nr = g.attributes.normal;
|
|
30772
30834
|
const hx = w / 2 - r;
|
|
30773
30835
|
const hy = h / 2 - r;
|
|
30774
|
-
const
|
|
30836
|
+
const hz2 = d / 2 - r;
|
|
30775
30837
|
function map(v, hi) {
|
|
30776
30838
|
const i = Math.round((v + 0.5) * n);
|
|
30777
30839
|
return i <= nb ? -hi - r * (nb - i) / nb : hi + r * (i - nb - 1) / nb;
|
|
@@ -30780,8 +30842,8 @@ var GameVehiclesThree = (() => {
|
|
|
30780
30842
|
const c = new V3();
|
|
30781
30843
|
const dir = new V3();
|
|
30782
30844
|
for (let i = 0; i < p.count; i++) {
|
|
30783
|
-
q.set(map(p.getX(i), hx), map(p.getY(i), hy), map(p.getZ(i),
|
|
30784
|
-
c.set(clamp(q.x, -hx, hx), clamp(q.y, -hy, hy), clamp(q.z, -
|
|
30845
|
+
q.set(map(p.getX(i), hx), map(p.getY(i), hy), map(p.getZ(i), hz2));
|
|
30846
|
+
c.set(clamp(q.x, -hx, hx), clamp(q.y, -hy, hy), clamp(q.z, -hz2, hz2));
|
|
30785
30847
|
dir.subVectors(q, c);
|
|
30786
30848
|
if (dir.lengthSq() > 1e-12) {
|
|
30787
30849
|
dir.normalize();
|
|
@@ -31281,21 +31343,23 @@ var GameVehiclesThree = (() => {
|
|
|
31281
31343
|
let wb = 0;
|
|
31282
31344
|
segs.forEach(function(seg) {
|
|
31283
31345
|
if (typeof seg[0] === "number") {
|
|
31346
|
+
const run = seg;
|
|
31284
31347
|
for (let a = 0; a < names.length; a++) {
|
|
31285
31348
|
const size = sizes[a];
|
|
31286
31349
|
if (!idx) {
|
|
31287
|
-
dst[a].set(arrs[a].subarray(
|
|
31288
|
-
w[a] += (
|
|
31350
|
+
dst[a].set(arrs[a].subarray(run[0] * 3 * size, run[1] * 3 * size), w[a]);
|
|
31351
|
+
w[a] += (run[1] - run[0]) * 3 * size;
|
|
31289
31352
|
continue;
|
|
31290
31353
|
}
|
|
31291
|
-
for (let f =
|
|
31354
|
+
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];
|
|
31292
31355
|
}
|
|
31293
31356
|
if (boxesOut2 && ti) {
|
|
31294
|
-
boxesOut2.set(ti.boxes.subarray(
|
|
31295
|
-
wb += (
|
|
31357
|
+
boxesOut2.set(ti.boxes.subarray(run[0] * 6, run[1] * 6), wb);
|
|
31358
|
+
wb += (run[1] - run[0]) * 6;
|
|
31296
31359
|
}
|
|
31297
31360
|
return;
|
|
31298
31361
|
}
|
|
31362
|
+
;
|
|
31299
31363
|
seg.forEach(function(t) {
|
|
31300
31364
|
if (boxesOut2) {
|
|
31301
31365
|
for (let k = 0; k < 3; k++) {
|
|
@@ -31489,14 +31553,16 @@ var GameVehiclesThree = (() => {
|
|
|
31489
31553
|
}
|
|
31490
31554
|
};
|
|
31491
31555
|
};
|
|
31492
|
-
|
|
31556
|
+
const shared2 = { roundedBoxGeometry, taper, subdivide, crease, creaseTask, refreshBounds, pathShape, tumble, loftGeometry, hullGeometry, cutGeometry, mergeGeometries, uvProject };
|
|
31557
|
+
Object.assign(I, shared2);
|
|
31558
|
+
return shared2;
|
|
31493
31559
|
}
|
|
31494
31560
|
function installContext(kit) {
|
|
31495
31561
|
const THREE = kit.THREE;
|
|
31496
31562
|
const V3 = THREE.Vector3;
|
|
31497
31563
|
const PI = Math.PI;
|
|
31498
31564
|
const I = kit._;
|
|
31499
|
-
const { makeMaterial, DOUBLE_SIDE, MATERIALS, crease, mergeGeometries, paintColor, roundedBoxGeometry, subdivide, taper, textTexture } = I;
|
|
31565
|
+
const { makeMaterial, DOUBLE_SIDE: DOUBLE_SIDE2, MATERIALS, crease, mergeGeometries, paintColor, roundedBoxGeometry, subdivide, taper, textTexture } = I;
|
|
31500
31566
|
function resolveLabel(l) {
|
|
31501
31567
|
if (l && typeof l === "object") return { key: l.key, label: l.label != null ? l.label : kit.t("parts." + l.key) };
|
|
31502
31568
|
return { label: l };
|
|
@@ -31546,7 +31612,7 @@ var GameVehiclesThree = (() => {
|
|
|
31546
31612
|
o = Object.assign({}, o || {});
|
|
31547
31613
|
const matte = o.matte != null ? o.matte : this.meta.matte;
|
|
31548
31614
|
delete o.matte;
|
|
31549
|
-
const base = matte ? { roughness: this.state === "damaged" ? 0.92 : 0.82, metalness: 0.08, side:
|
|
31615
|
+
const base = matte ? { roughness: this.state === "damaged" ? 0.92 : 0.82, metalness: 0.08, side: DOUBLE_SIDE2 } : { roughness: this.state === "damaged" ? 0.75 : 0.42, metalness: 0.3, side: DOUBLE_SIDE2 };
|
|
31550
31616
|
const pm = makeMaterial(paintColor(hex, this.state), Object.assign(base, o));
|
|
31551
31617
|
this.paints.add(pm);
|
|
31552
31618
|
return pm;
|
|
@@ -31741,6 +31807,7 @@ var GameVehiclesThree = (() => {
|
|
|
31741
31807
|
}
|
|
31742
31808
|
kit.BuildContext = BuildContext;
|
|
31743
31809
|
I.BuildContext = BuildContext;
|
|
31810
|
+
return { resolveLabel, BuildContext };
|
|
31744
31811
|
}
|
|
31745
31812
|
function installWarp(kit) {
|
|
31746
31813
|
const THREE = kit.THREE;
|
|
@@ -31934,7 +32001,9 @@ var GameVehiclesThree = (() => {
|
|
|
31934
32001
|
kit.applyWarp = applyWarp;
|
|
31935
32002
|
kit.geo.resample = resample;
|
|
31936
32003
|
kit.geo.smoothLoft = smoothLoft;
|
|
31937
|
-
|
|
32004
|
+
const shared2 = { makeWarp, applyWarp, resample, smoothLoft };
|
|
32005
|
+
Object.assign(I, shared2);
|
|
32006
|
+
return shared2;
|
|
31938
32007
|
}
|
|
31939
32008
|
function installBody(kit) {
|
|
31940
32009
|
const THREE = kit.THREE;
|
|
@@ -31998,23 +32067,24 @@ var GameVehiclesThree = (() => {
|
|
|
31998
32067
|
o.arches.forEach(function(a) {
|
|
31999
32068
|
const a0 = Math.asin(clamp((o.bottomY - a[1]) / a[2], -1, 1));
|
|
32000
32069
|
const rr = a[2] - 0.01;
|
|
32070
|
+
const archInner = o.archInner;
|
|
32001
32071
|
if (o.archInner == null) {
|
|
32002
32072
|
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);
|
|
32003
32073
|
wl.rotation.x = PI / 2;
|
|
32004
32074
|
wl.castShadow = false;
|
|
32005
32075
|
} else
|
|
32006
32076
|
[1, -1].forEach(function(s) {
|
|
32007
|
-
const len = o.W / 2 - 0.06 -
|
|
32077
|
+
const len = o.W / 2 - 0.06 - archInner;
|
|
32008
32078
|
const w2 = c.add(
|
|
32009
32079
|
new THREE.CylinderGeometry(rr, rr, len, 20, 1, true, a0 + PI / 2, PI - 2 * a0),
|
|
32010
32080
|
MATERIALS.dark,
|
|
32011
32081
|
a[0],
|
|
32012
32082
|
a[1],
|
|
32013
|
-
s * (
|
|
32083
|
+
s * (archInner + len / 2)
|
|
32014
32084
|
);
|
|
32015
32085
|
w2.rotation.x = PI / 2;
|
|
32016
32086
|
w2.castShadow = false;
|
|
32017
|
-
const cap = c.add(new THREE.CircleGeometry(rr, 20, a0, PI - 2 * a0), MATERIALS.dark, a[0], a[1], s *
|
|
32087
|
+
const cap = c.add(new THREE.CircleGeometry(rr, 20, a0, PI - 2 * a0), MATERIALS.dark, a[0], a[1], s * archInner);
|
|
32018
32088
|
cap.castShadow = false;
|
|
32019
32089
|
});
|
|
32020
32090
|
});
|
|
@@ -32091,8 +32161,12 @@ var GameVehiclesThree = (() => {
|
|
|
32091
32161
|
if (!q.isMesh || !q.visible || q.userData.glass || q.userData.decal || q.isSprite) return;
|
|
32092
32162
|
if (o.all || dset.has(q) || c.paints && c.paints.has(q.material)) cands.push(q);
|
|
32093
32163
|
});
|
|
32094
|
-
const
|
|
32095
|
-
const
|
|
32164
|
+
const dv = dir;
|
|
32165
|
+
const da = dir;
|
|
32166
|
+
const d = (dv.isVector3 ? dv.clone() : new V3(da[0], da[1], da[2])).normalize();
|
|
32167
|
+
const ov = org;
|
|
32168
|
+
const oa = org;
|
|
32169
|
+
const p0 = ov.isVector3 ? ov.clone() : new V3(oa[0], oa[1], oa[2]);
|
|
32096
32170
|
_sr.set(p0.clone().applyMatrix4(Mw), d.clone().transformDirection(Mw));
|
|
32097
32171
|
_sr.near = 0;
|
|
32098
32172
|
_sr.far = o.max || 20;
|
|
@@ -32109,14 +32183,17 @@ var GameVehiclesThree = (() => {
|
|
|
32109
32183
|
const h = kit.surfaceAt(c, new V3(x0, y, z || 0), new V3(-sg, 0, 0));
|
|
32110
32184
|
return h ? h.p.x : items ? profX(items, y, front !== false) : null;
|
|
32111
32185
|
};
|
|
32112
|
-
|
|
32186
|
+
const shared2 = { halfAt, shell, autoWindows, profX, _sr };
|
|
32187
|
+
Object.assign(I, shared2);
|
|
32188
|
+
return shared2;
|
|
32113
32189
|
}
|
|
32114
32190
|
function installGlass(kit) {
|
|
32115
32191
|
const THREE = kit.THREE;
|
|
32116
32192
|
const V3 = THREE.Vector3;
|
|
32117
32193
|
const I = kit._;
|
|
32118
32194
|
const { MATERIALS, crease, cutGeometry, pathShape, subdivide, tumble, uvProject } = I;
|
|
32119
|
-
|
|
32195
|
+
const paneSeals = /* @__PURE__ */ new WeakMap();
|
|
32196
|
+
I.paneSeals = paneSeals;
|
|
32120
32197
|
kit.addGlass = function(c, geo, label, type, o) {
|
|
32121
32198
|
o = o || {};
|
|
32122
32199
|
if (!geo.attributes.uv || o.reuv) o.aspect = uvProject(geo, o.uvAxes);
|
|
@@ -32213,7 +32290,7 @@ var GameVehiclesThree = (() => {
|
|
|
32213
32290
|
};
|
|
32214
32291
|
kit.quadDef = function(pb, pt, Wg, T, which, bev, o) {
|
|
32215
32292
|
o = o || {};
|
|
32216
|
-
|
|
32293
|
+
const bv = bev == null ? 0.05 : bev;
|
|
32217
32294
|
const dx = pt[0] - pb[0];
|
|
32218
32295
|
const dy = pt[1] - pb[1];
|
|
32219
32296
|
const L = Math.hypot(dx, dy);
|
|
@@ -32222,13 +32299,13 @@ var GameVehiclesThree = (() => {
|
|
|
32222
32299
|
const nx = which === "front" ? uy : -uy;
|
|
32223
32300
|
const ny = which === "front" ? -ux : ux;
|
|
32224
32301
|
const ins = o.inset || 0.09;
|
|
32225
|
-
const off =
|
|
32302
|
+
const off = bv + 6e-3;
|
|
32226
32303
|
const sd = o.side || 0.1;
|
|
32227
32304
|
const b = [pb[0] + ux * ins + nx * off, pb[1] + uy * ins + ny * off];
|
|
32228
32305
|
const t = [pt[0] - ux * ins * 1.3 + nx * off, pt[1] - uy * ins * 1.3 + ny * off];
|
|
32229
32306
|
const hb = I.halfAt(Wg, T, b[1]) - sd;
|
|
32230
32307
|
const ht = I.halfAt(Wg, T, t[1]) - sd;
|
|
32231
|
-
return { pb, pt, L, u: [ux, uy], n: [nx, ny], ins, b, t, hb, ht, which, bev, Wg, T };
|
|
32308
|
+
return { pb, pt, L, u: [ux, uy], n: [nx, ny], ins, b, t, hb, ht, which, bev: bv, Wg, T };
|
|
32232
32309
|
};
|
|
32233
32310
|
kit.glassQuad = function(c, q, label, o) {
|
|
32234
32311
|
o = o || {};
|
|
@@ -32282,7 +32359,9 @@ var GameVehiclesThree = (() => {
|
|
|
32282
32359
|
c.quads.push(q);
|
|
32283
32360
|
return m;
|
|
32284
32361
|
};
|
|
32285
|
-
|
|
32362
|
+
const shared2 = { paneSeals };
|
|
32363
|
+
Object.assign(I, shared2);
|
|
32364
|
+
return shared2;
|
|
32286
32365
|
}
|
|
32287
32366
|
function installLights(kit) {
|
|
32288
32367
|
const THREE = kit.THREE;
|
|
@@ -32617,7 +32696,9 @@ var GameVehiclesThree = (() => {
|
|
|
32617
32696
|
if (o.emblem !== false) kit.emblem(c, 0.05, st === "closed" ? h * 0.12 : 0, 0, Math.min(0.05, h * 0.3), g);
|
|
32618
32697
|
return g;
|
|
32619
32698
|
};
|
|
32620
|
-
|
|
32699
|
+
const shared2 = { lampGroup, gm, wedgeY, haloTex, glowTexture, haloMats, halo, lampKit };
|
|
32700
|
+
Object.assign(I, shared2);
|
|
32701
|
+
return shared2;
|
|
32621
32702
|
}
|
|
32622
32703
|
function installInterior(kit) {
|
|
32623
32704
|
const THREE = kit.THREE;
|
|
@@ -32867,7 +32948,9 @@ var GameVehiclesThree = (() => {
|
|
|
32867
32948
|
c.roundBox(o.x0 - o.x1 + 1, 0.03, zi * 2, 0.01, MATERIALS.carpet, (o.x0 + o.x1) / 2, o.floor, 0);
|
|
32868
32949
|
return n;
|
|
32869
32950
|
};
|
|
32870
|
-
|
|
32951
|
+
const shared2 = { consoleBox };
|
|
32952
|
+
Object.assign(I, shared2);
|
|
32953
|
+
return shared2;
|
|
32871
32954
|
}
|
|
32872
32955
|
var HOOD_LIFT = 8e-3;
|
|
32873
32956
|
function installHood(kit) {
|
|
@@ -33260,7 +33343,9 @@ var GameVehiclesThree = (() => {
|
|
|
33260
33343
|
};
|
|
33261
33344
|
return out;
|
|
33262
33345
|
};
|
|
33263
|
-
|
|
33346
|
+
const shared2 = {};
|
|
33347
|
+
Object.assign(I, shared2);
|
|
33348
|
+
return shared2;
|
|
33264
33349
|
}
|
|
33265
33350
|
function installCar(kit) {
|
|
33266
33351
|
const THREE = kit.THREE;
|
|
@@ -33504,13 +33589,13 @@ var GameVehiclesThree = (() => {
|
|
|
33504
33589
|
);
|
|
33505
33590
|
const hy = hl.y || s.headY || s.noseY - 0.06;
|
|
33506
33591
|
const hx = I.profX(it, hy, true);
|
|
33507
|
-
const
|
|
33592
|
+
const hz2 = W / 2 - hl.in - hl.w / 2;
|
|
33508
33593
|
[1, -1].forEach(function(sd) {
|
|
33509
33594
|
kit.headlight(c, {
|
|
33510
33595
|
style: hl.style,
|
|
33511
33596
|
x: hx + 0.02 + (hl.dx || 0),
|
|
33512
33597
|
y: hy,
|
|
33513
|
-
z: sd *
|
|
33598
|
+
z: sd * hz2,
|
|
33514
33599
|
w: hl.w,
|
|
33515
33600
|
h: hl.h,
|
|
33516
33601
|
side: sd,
|
|
@@ -33518,7 +33603,7 @@ var GameVehiclesThree = (() => {
|
|
|
33518
33603
|
mat: hl.mat
|
|
33519
33604
|
});
|
|
33520
33605
|
});
|
|
33521
|
-
if (hl.style === "ledbar") kit.lightBar(c, hx + 0.03, hy + hl.h * 0.3, -
|
|
33606
|
+
if (hl.style === "ledbar") kit.lightBar(c, hx + 0.03, hy + hl.h * 0.3, -hz2 + hl.w / 2, hz2 - hl.w / 2, 0.018, 1);
|
|
33522
33607
|
if (s.grille !== false && !s.noGrille) {
|
|
33523
33608
|
const gr = Object.assign({ style: "bars", w: W * 0.44, h: Math.max(0.08, hy - bumperY - 0.12) }, s.grille || {});
|
|
33524
33609
|
const gy = gr.y || (bumperY + hy) / 2 + 0.02;
|
|
@@ -33616,7 +33701,9 @@ var GameVehiclesThree = (() => {
|
|
|
33616
33701
|
});
|
|
33617
33702
|
return out;
|
|
33618
33703
|
};
|
|
33619
|
-
|
|
33704
|
+
const shared2 = {};
|
|
33705
|
+
Object.assign(I, shared2);
|
|
33706
|
+
return shared2;
|
|
33620
33707
|
}
|
|
33621
33708
|
function installTrucks(kit) {
|
|
33622
33709
|
const THREE = kit.THREE;
|
|
@@ -33759,7 +33846,9 @@ var GameVehiclesThree = (() => {
|
|
|
33759
33846
|
m.rear = rear;
|
|
33760
33847
|
m.length = L;
|
|
33761
33848
|
};
|
|
33762
|
-
|
|
33849
|
+
const shared2 = {};
|
|
33850
|
+
Object.assign(I, shared2);
|
|
33851
|
+
return shared2;
|
|
33763
33852
|
}
|
|
33764
33853
|
function installWheels(kit) {
|
|
33765
33854
|
const THREE = kit.THREE;
|
|
@@ -33896,7 +33985,9 @@ var GameVehiclesThree = (() => {
|
|
|
33896
33985
|
c.part("track", kit.t("parts.track", { s: z > 0 ? 1 : -1 }), tm, new V3((x0 + x1) / 2, 0.3, z), 1.4);
|
|
33897
33986
|
return { mesh: tm, wheels: gs, sprocket: spr, idler: idl };
|
|
33898
33987
|
};
|
|
33899
|
-
|
|
33988
|
+
const shared2 = {};
|
|
33989
|
+
Object.assign(I, shared2);
|
|
33990
|
+
return shared2;
|
|
33900
33991
|
}
|
|
33901
33992
|
var ROUTED_PARTICLE_TYPES = { smoke: "particle_puff", dust: "particle_puff", fire: "particle_glow" };
|
|
33902
33993
|
var PUFF_LOOKS = {
|
|
@@ -34321,7 +34412,7 @@ var GameVehiclesThree = (() => {
|
|
|
34321
34412
|
}
|
|
34322
34413
|
});
|
|
34323
34414
|
}
|
|
34324
|
-
|
|
34415
|
+
const shared2 = {
|
|
34325
34416
|
PARTICLE_LIMIT,
|
|
34326
34417
|
PARTICLE_GEOMETRIES,
|
|
34327
34418
|
PARTICLE_MATERIALS,
|
|
@@ -34341,7 +34432,9 @@ var GameVehiclesThree = (() => {
|
|
|
34341
34432
|
burst,
|
|
34342
34433
|
exhaustLook,
|
|
34343
34434
|
tickEmit
|
|
34344
|
-
}
|
|
34435
|
+
};
|
|
34436
|
+
Object.assign(I, shared2);
|
|
34437
|
+
return shared2;
|
|
34345
34438
|
}
|
|
34346
34439
|
var PUDDLE_COLORS = {
|
|
34347
34440
|
coolant: 3123279,
|
|
@@ -34356,7 +34449,7 @@ var GameVehiclesThree = (() => {
|
|
|
34356
34449
|
const V3 = THREE.Vector3;
|
|
34357
34450
|
const PI = Math.PI;
|
|
34358
34451
|
const I = kit._;
|
|
34359
|
-
const { DOUBLE_SIDE } = I;
|
|
34452
|
+
const { DOUBLE_SIDE: DOUBLE_SIDE2 } = I;
|
|
34360
34453
|
kit.fluidTypes = {};
|
|
34361
34454
|
kit.defineFluid = function(key, def) {
|
|
34362
34455
|
const d = Object.assign({ dryTime: 600, roughFresh: 0.12, roughDry: 0.92, metalFresh: 0.15, metalDry: 0, wipeable: false }, def || {});
|
|
@@ -34377,7 +34470,7 @@ var GameVehiclesThree = (() => {
|
|
|
34377
34470
|
color: fdef.freshC.clone(),
|
|
34378
34471
|
roughness: fdef.roughFresh,
|
|
34379
34472
|
metalness: fdef.metalFresh,
|
|
34380
|
-
side:
|
|
34473
|
+
side: DOUBLE_SIDE2,
|
|
34381
34474
|
polygonOffset: true,
|
|
34382
34475
|
polygonOffsetFactor: -2,
|
|
34383
34476
|
polygonOffsetUnits: -4
|
|
@@ -34635,7 +34728,7 @@ var GameVehiclesThree = (() => {
|
|
|
34635
34728
|
metalness: 0.7,
|
|
34636
34729
|
transparent: true,
|
|
34637
34730
|
opacity: 0,
|
|
34638
|
-
side:
|
|
34731
|
+
side: DOUBLE_SIDE2,
|
|
34639
34732
|
depthWrite: false
|
|
34640
34733
|
})
|
|
34641
34734
|
);
|
|
@@ -34649,7 +34742,7 @@ var GameVehiclesThree = (() => {
|
|
|
34649
34742
|
} else if (kind === "gasoline") {
|
|
34650
34743
|
const haze = new THREE.Mesh(
|
|
34651
34744
|
puddleGeometry(),
|
|
34652
|
-
new THREE.MeshBasicMaterial({ color: 10465982, transparent: true, opacity: 0.035, depthWrite: false, side:
|
|
34745
|
+
new THREE.MeshBasicMaterial({ color: 10465982, transparent: true, opacity: 0.035, depthWrite: false, side: DOUBLE_SIDE2 })
|
|
34653
34746
|
);
|
|
34654
34747
|
haze.position.set(q.x, 0.22, q.z);
|
|
34655
34748
|
haze.raycast = function() {
|
|
@@ -34813,7 +34906,9 @@ var GameVehiclesThree = (() => {
|
|
|
34813
34906
|
}
|
|
34814
34907
|
return n;
|
|
34815
34908
|
};
|
|
34816
|
-
|
|
34909
|
+
const shared2 = { _fr, buildDrip, DOWNHILL, PN, puddleGeometry, rimGeometry, puddle, shapePuddle, updateFluids };
|
|
34910
|
+
Object.assign(I, shared2);
|
|
34911
|
+
return shared2;
|
|
34817
34912
|
}
|
|
34818
34913
|
function crackedGlassMaterial(THREE, texture) {
|
|
34819
34914
|
return new THREE.MeshStandardMaterial({
|
|
@@ -35135,8 +35230,20 @@ var GameVehiclesThree = (() => {
|
|
|
35135
35230
|
if (!L || L.broken) return;
|
|
35136
35231
|
L.broken = true;
|
|
35137
35232
|
L.lens.forEach(function(m) {
|
|
35138
|
-
m.
|
|
35233
|
+
const rim = L.lensMaterial ? glassRim(m.geometry, c.rand) : null;
|
|
35234
|
+
if (!rim) {
|
|
35235
|
+
m.visible = false;
|
|
35236
|
+
return;
|
|
35237
|
+
}
|
|
35238
|
+
m.geometry.dispose();
|
|
35239
|
+
m.geometry = rim;
|
|
35240
|
+
m.material = MATERIALS.glassEdge;
|
|
35241
|
+
m.userData.lensRim = true;
|
|
35139
35242
|
});
|
|
35243
|
+
if (L.lensMaterial)
|
|
35244
|
+
(L.reflector || []).forEach(function(m) {
|
|
35245
|
+
m.material = MATERIALS.broken;
|
|
35246
|
+
});
|
|
35140
35247
|
L.inner.forEach(function(m) {
|
|
35141
35248
|
m.material = MATERIALS.bulbBroken;
|
|
35142
35249
|
});
|
|
@@ -35144,18 +35251,47 @@ var GameVehiclesThree = (() => {
|
|
|
35144
35251
|
h.visible = false;
|
|
35145
35252
|
});
|
|
35146
35253
|
const p = L.group ? L.group.position.clone() : L.inner[0] ? L.inner[0].position.clone() : new V3();
|
|
35147
|
-
|
|
35148
|
-
I.burst(c, "
|
|
35254
|
+
const glass = L.lensMaterial !== "plastic";
|
|
35255
|
+
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" });
|
|
35256
|
+
I.burst(c, "plastic", c.toEffects(p), glass ? 2 : 5, { dir: c.dirToEffects(dir.clone().negate()), speed: 1 });
|
|
35149
35257
|
}
|
|
35150
35258
|
kit.breakLight = breakLight;
|
|
35151
|
-
|
|
35259
|
+
const crazedCache = /* @__PURE__ */ new Map();
|
|
35260
|
+
const CRAZED_OPACITY = 0.6;
|
|
35261
|
+
function crazed(material) {
|
|
35262
|
+
const known = crazedCache.get(material);
|
|
35263
|
+
if (known) return known;
|
|
35264
|
+
const m = I.crackLens(material).clone();
|
|
35265
|
+
m.opacity = Math.max(m.opacity ?? 1, CRAZED_OPACITY);
|
|
35266
|
+
m.transparent = true;
|
|
35267
|
+
m.userData.shared = true;
|
|
35268
|
+
crazedCache.set(material, m);
|
|
35269
|
+
return m;
|
|
35270
|
+
}
|
|
35271
|
+
function crackLight(c, L, dir, pierced) {
|
|
35272
|
+
if (!L || L.broken) return;
|
|
35273
|
+
if (!L.cracked) {
|
|
35274
|
+
L.cracked = true;
|
|
35275
|
+
for (const m of L.lens) if (m.material && !Array.isArray(m.material)) m.material = crazed(m.material);
|
|
35276
|
+
}
|
|
35277
|
+
const p = L.group ? L.group.position.clone() : L.inner[0] ? L.inner[0].position.clone() : new V3();
|
|
35278
|
+
I.burst(c, "lens", c.toEffects(p), 3, { dir: c.dirToEffects(dir.clone().negate()), speed: 0.9, variant: L.tint === "red" ? "red" : "clear" });
|
|
35279
|
+
if (!pierced || L.dark) return;
|
|
35280
|
+
L.dark = true;
|
|
35281
|
+
for (const m of L.inner) m.material = MATERIALS.bulbBroken;
|
|
35282
|
+
for (const h of L.halo ?? []) h.visible = false;
|
|
35283
|
+
}
|
|
35284
|
+
kit.crackLight = crackLight;
|
|
35285
|
+
const shared2 = { glassUV, drawWeb, crackGlass, glassRim, shatterGlass, hitGlass, breakLight, crackLight };
|
|
35286
|
+
Object.assign(I, shared2);
|
|
35287
|
+
return shared2;
|
|
35152
35288
|
}
|
|
35153
35289
|
function installImpact(kit) {
|
|
35154
35290
|
const THREE = kit.THREE;
|
|
35155
35291
|
const V3 = THREE.Vector3;
|
|
35156
35292
|
const PI = Math.PI;
|
|
35157
35293
|
const I = kit._;
|
|
35158
|
-
const { makeMaterial, DOUBLE_SIDE, crease, paintColor } = I;
|
|
35294
|
+
const { makeMaterial, DOUBLE_SIDE: DOUBLE_SIDE2, crease, paintColor } = I;
|
|
35159
35295
|
function dentField(v, H) {
|
|
35160
35296
|
const d = v.distanceTo(H.p);
|
|
35161
35297
|
if (d >= H.R) return 0;
|
|
@@ -35504,7 +35640,7 @@ var GameVehiclesThree = (() => {
|
|
|
35504
35640
|
I.burst(c, "scrap", pf, Math.round(force * 5), {
|
|
35505
35641
|
dir: df,
|
|
35506
35642
|
speed: 1.4,
|
|
35507
|
-
mat: makeMaterial(paintColor(m.color || "#777", c.state), { roughness: 0.5, metalness: 0.3, side:
|
|
35643
|
+
mat: makeMaterial(paintColor(m.color || "#777", c.state), { roughness: 0.5, metalness: 0.3, side: DOUBLE_SIDE2 })
|
|
35508
35644
|
});
|
|
35509
35645
|
I.burst(c, "plastic", pf, 2, { dir: df, speed: 1.2 });
|
|
35510
35646
|
}
|
|
@@ -35620,7 +35756,7 @@ var GameVehiclesThree = (() => {
|
|
|
35620
35756
|
return hit;
|
|
35621
35757
|
}
|
|
35622
35758
|
kit.zoneImpact = zoneImpact;
|
|
35623
|
-
|
|
35759
|
+
const shared2 = {
|
|
35624
35760
|
dentField,
|
|
35625
35761
|
hangBumper,
|
|
35626
35762
|
tankFuel,
|
|
@@ -35636,14 +35772,16 @@ var GameVehiclesThree = (() => {
|
|
|
35636
35772
|
_pr,
|
|
35637
35773
|
probe,
|
|
35638
35774
|
zoneImpact
|
|
35639
|
-
}
|
|
35775
|
+
};
|
|
35776
|
+
Object.assign(I, shared2);
|
|
35777
|
+
return shared2;
|
|
35640
35778
|
}
|
|
35641
35779
|
function installExplosion(kit) {
|
|
35642
35780
|
const THREE = kit.THREE;
|
|
35643
35781
|
const V3 = THREE.Vector3;
|
|
35644
35782
|
const PI = Math.PI;
|
|
35645
35783
|
const I = kit._;
|
|
35646
|
-
const { makeMaterial, DOUBLE_SIDE, MATERIALS, paintColor, textTexture } = I;
|
|
35784
|
+
const { makeMaterial, DOUBLE_SIDE: DOUBLE_SIDE2, MATERIALS, paintColor, textTexture } = I;
|
|
35647
35785
|
const BURNT = ["#1d1a17", "#26211c", "#171514", "#2e2620"].map(function(h, i) {
|
|
35648
35786
|
return makeMaterial(h, { roughness: 1, metalness: i === 3 ? 0.35 : 0.15 });
|
|
35649
35787
|
});
|
|
@@ -35654,7 +35792,7 @@ var GameVehiclesThree = (() => {
|
|
|
35654
35792
|
transparent: true,
|
|
35655
35793
|
opacity: op,
|
|
35656
35794
|
depthWrite: false,
|
|
35657
|
-
side:
|
|
35795
|
+
side: DOUBLE_SIDE2,
|
|
35658
35796
|
fog: false,
|
|
35659
35797
|
blending: add2 ? THREE.AdditiveBlending : THREE.NormalBlending
|
|
35660
35798
|
});
|
|
@@ -35842,7 +35980,7 @@ var GameVehiclesThree = (() => {
|
|
|
35842
35980
|
I.burst(c, "scrap", cen, 14, {
|
|
35843
35981
|
speed: 5,
|
|
35844
35982
|
spread: 1.5,
|
|
35845
|
-
mat: makeMaterial(paintColor(m.color || "#777", c.state), { roughness: 0.5, metalness: 0.3, side:
|
|
35983
|
+
mat: makeMaterial(paintColor(m.color || "#777", c.state), { roughness: 0.5, metalness: 0.3, side: DOUBLE_SIDE2 })
|
|
35846
35984
|
});
|
|
35847
35985
|
I.burst(c, "plastic", cen, 8, { speed: 4 });
|
|
35848
35986
|
c.glass.slice().forEach(function(gm2) {
|
|
@@ -36019,7 +36157,9 @@ var GameVehiclesThree = (() => {
|
|
|
36019
36157
|
}
|
|
36020
36158
|
}
|
|
36021
36159
|
}
|
|
36022
|
-
|
|
36160
|
+
const shared2 = { BURNT, BURNT_RUB, boomMat, enginePos, fling, burnAll, bigBoomFx, detonate, tickBoom, tickFlying };
|
|
36161
|
+
Object.assign(I, shared2);
|
|
36162
|
+
return shared2;
|
|
36023
36163
|
}
|
|
36024
36164
|
function installRollover(kit) {
|
|
36025
36165
|
const THREE = kit.THREE;
|
|
@@ -36219,7 +36359,8 @@ var GameVehiclesThree = (() => {
|
|
|
36219
36359
|
c.parts.forEach(function(p) {
|
|
36220
36360
|
if (p.kind !== "rotor" && p.kind !== "tail_rotor" || !p.obj) return;
|
|
36221
36361
|
const main = p.kind === "rotor";
|
|
36222
|
-
p.obj.traverse(function(
|
|
36362
|
+
p.obj.traverse(function(node) {
|
|
36363
|
+
const o = node;
|
|
36223
36364
|
if (!o.isMesh || !o.visible) return;
|
|
36224
36365
|
const bb = new THREE.Box3().setFromObject(o).applyMatrix4(inv);
|
|
36225
36366
|
if (!main && bb.min.y >= -0.01) return;
|
|
@@ -36291,7 +36432,9 @@ var GameVehiclesThree = (() => {
|
|
|
36291
36432
|
if (p >= 1) finishRoll(c);
|
|
36292
36433
|
}
|
|
36293
36434
|
kit.rollContact = rollContact;
|
|
36294
|
-
|
|
36435
|
+
const shared2 = { rollMeshes, convexHull, rollContact, exactMinY, finishRoll, tickRoll };
|
|
36436
|
+
Object.assign(I, shared2);
|
|
36437
|
+
return shared2;
|
|
36295
36438
|
}
|
|
36296
36439
|
function installTick(kit) {
|
|
36297
36440
|
const I = kit._;
|
|
@@ -36327,7 +36470,9 @@ var GameVehiclesThree = (() => {
|
|
|
36327
36470
|
c.hood.target = open ? c.hood.open : 0;
|
|
36328
36471
|
return true;
|
|
36329
36472
|
};
|
|
36330
|
-
|
|
36473
|
+
const shared2 = {};
|
|
36474
|
+
Object.assign(I, shared2);
|
|
36475
|
+
return shared2;
|
|
36331
36476
|
}
|
|
36332
36477
|
function installArmor(kit) {
|
|
36333
36478
|
const THREE = kit.THREE;
|
|
@@ -36577,7 +36722,9 @@ var GameVehiclesThree = (() => {
|
|
|
36577
36722
|
}
|
|
36578
36723
|
}
|
|
36579
36724
|
kit.applyArmor = applyArmor;
|
|
36580
|
-
|
|
36725
|
+
const shared2 = { STEEL_MATERIAL, PLATE_MATERIALS, jerryCan, applyArmor };
|
|
36726
|
+
Object.assign(I, shared2);
|
|
36727
|
+
return shared2;
|
|
36581
36728
|
}
|
|
36582
36729
|
function installZoneCore(kit) {
|
|
36583
36730
|
const THREE = kit.THREE;
|
|
@@ -36594,8 +36741,8 @@ var GameVehiclesThree = (() => {
|
|
|
36594
36741
|
return { id: b.id, name: kit.t("bands." + b.id), min: b.min, health: b.health, color: b.color };
|
|
36595
36742
|
});
|
|
36596
36743
|
function bandOf(h) {
|
|
36597
|
-
|
|
36598
|
-
for (let i = 0; i < BANDS.length; i++) if (
|
|
36744
|
+
const v = Math.round(clamp(h == null ? 100 : h, 0, 100));
|
|
36745
|
+
for (let i = 0; i < BANDS.length; i++) if (v >= BANDS[i].min) return i;
|
|
36599
36746
|
return 4;
|
|
36600
36747
|
}
|
|
36601
36748
|
kit.bands = BANDS;
|
|
@@ -36621,8 +36768,12 @@ var GameVehiclesThree = (() => {
|
|
|
36621
36768
|
z0: Math.min(b[4], b[5]),
|
|
36622
36769
|
z1: Math.max(b[4], b[5])
|
|
36623
36770
|
};
|
|
36624
|
-
if (b.isBox3)
|
|
36625
|
-
|
|
36771
|
+
if (b.isBox3) {
|
|
36772
|
+
const box2 = b;
|
|
36773
|
+
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 };
|
|
36774
|
+
}
|
|
36775
|
+
const r = b;
|
|
36776
|
+
return { x0: r.x0, x1: r.x1, y0: r.y0, y1: r.y1, z0: r.z0, z1: r.z1 };
|
|
36626
36777
|
}
|
|
36627
36778
|
kit.normalizeBox = normalizeBox;
|
|
36628
36779
|
function boxLo(B, a) {
|
|
@@ -36659,7 +36810,8 @@ var GameVehiclesThree = (() => {
|
|
|
36659
36810
|
const bb = new THREE.Box3();
|
|
36660
36811
|
const tmp = new THREE.Box3();
|
|
36661
36812
|
const M = new THREE.Matrix4();
|
|
36662
|
-
o.traverse(function(
|
|
36813
|
+
o.traverse(function(node) {
|
|
36814
|
+
const x = node;
|
|
36663
36815
|
if (!x.isMesh || !x.geometry || !x.geometry.attributes.position || x.userData.decal) return;
|
|
36664
36816
|
if (!x.geometry.boundingBox) x.geometry.computeBoundingBox();
|
|
36665
36817
|
tmp.copy(x.geometry.boundingBox).applyMatrix4(M.multiplyMatrices(inv, x.matrixWorld));
|
|
@@ -36725,7 +36877,7 @@ var GameVehiclesThree = (() => {
|
|
|
36725
36877
|
for (let q = o; q && q !== c.vehicle; q = q.parent) if (q.visible === false) return false;
|
|
36726
36878
|
return !!o;
|
|
36727
36879
|
}
|
|
36728
|
-
|
|
36880
|
+
const shared2 = {
|
|
36729
36881
|
BANDS,
|
|
36730
36882
|
bandOf,
|
|
36731
36883
|
ZONE_WEIGHTS,
|
|
@@ -36748,16 +36900,18 @@ var GameVehiclesThree = (() => {
|
|
|
36748
36900
|
lightBoxOf,
|
|
36749
36901
|
hideObj,
|
|
36750
36902
|
shown
|
|
36751
|
-
}
|
|
36903
|
+
};
|
|
36904
|
+
Object.assign(I, shared2);
|
|
36905
|
+
return shared2;
|
|
36752
36906
|
}
|
|
36753
36907
|
function installZoneDecals(kit) {
|
|
36754
36908
|
const THREE = kit.THREE;
|
|
36755
36909
|
const V3 = THREE.Vector3;
|
|
36756
36910
|
const PI = Math.PI;
|
|
36757
36911
|
const I = kit._;
|
|
36758
|
-
const { makeMaterial, DOUBLE_SIDE } = I;
|
|
36912
|
+
const { makeMaterial, DOUBLE_SIDE: DOUBLE_SIDE2 } = I;
|
|
36759
36913
|
function dmat(hex, o) {
|
|
36760
|
-
return makeMaterial(hex, Object.assign({ polygonOffset: true, polygonOffsetFactor: -2, polygonOffsetUnits: -3, side:
|
|
36914
|
+
return makeMaterial(hex, Object.assign({ polygonOffset: true, polygonOffsetFactor: -2, polygonOffsetUnits: -3, side: DOUBLE_SIDE2 }, o || {}));
|
|
36761
36915
|
}
|
|
36762
36916
|
const DAMAGE_MATERIALS = {
|
|
36763
36917
|
/* without an environment map, high-metalness metal turns black and chipped paint looks like a bullet hole: light, barely metallic metal */
|
|
@@ -36775,7 +36929,7 @@ var GameVehiclesThree = (() => {
|
|
|
36775
36929
|
transparent: true,
|
|
36776
36930
|
opacity: 0.62,
|
|
36777
36931
|
depthWrite: false,
|
|
36778
|
-
side:
|
|
36932
|
+
side: DOUBLE_SIDE2,
|
|
36779
36933
|
polygonOffset: true,
|
|
36780
36934
|
polygonOffsetFactor: -2,
|
|
36781
36935
|
polygonOffsetUnits: -3
|
|
@@ -37031,7 +37185,10 @@ var GameVehiclesThree = (() => {
|
|
|
37031
37185
|
narrowTo(rc, q);
|
|
37032
37186
|
}
|
|
37033
37187
|
const hits = rc.intersectObjects(cands, false);
|
|
37034
|
-
for (let i = 0; i < hits.length; i++)
|
|
37188
|
+
for (let i = 0; i < hits.length; i++) {
|
|
37189
|
+
const proxyOf = hits[i].object.proxyOf;
|
|
37190
|
+
if (proxyOf) hits[i].object = proxyOf;
|
|
37191
|
+
}
|
|
37035
37192
|
return hits;
|
|
37036
37193
|
}
|
|
37037
37194
|
function zoneCands(c, z, inv, glassToo) {
|
|
@@ -37232,7 +37389,7 @@ var GameVehiclesThree = (() => {
|
|
|
37232
37389
|
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));
|
|
37233
37390
|
return S;
|
|
37234
37391
|
}
|
|
37235
|
-
|
|
37392
|
+
const shared2 = {
|
|
37236
37393
|
dmat,
|
|
37237
37394
|
DAMAGE_MATERIALS,
|
|
37238
37395
|
_zq,
|
|
@@ -37253,7 +37410,9 @@ var GameVehiclesThree = (() => {
|
|
|
37253
37410
|
ribbonGeo,
|
|
37254
37411
|
scratchDecal,
|
|
37255
37412
|
zoneDecals
|
|
37256
|
-
}
|
|
37413
|
+
};
|
|
37414
|
+
Object.assign(I, shared2);
|
|
37415
|
+
return shared2;
|
|
37257
37416
|
}
|
|
37258
37417
|
function installZoneDent(kit) {
|
|
37259
37418
|
const THREE = kit.THREE;
|
|
@@ -37609,7 +37768,9 @@ var GameVehiclesThree = (() => {
|
|
|
37609
37768
|
});
|
|
37610
37769
|
return piv;
|
|
37611
37770
|
}
|
|
37612
|
-
|
|
37771
|
+
const shared2 = { sm, subdivIn, dentTargets, zoneDent, cutPanel, pivotOf };
|
|
37772
|
+
Object.assign(I, shared2);
|
|
37773
|
+
return shared2;
|
|
37613
37774
|
}
|
|
37614
37775
|
function installDamagePanels(kit) {
|
|
37615
37776
|
const THREE = kit.THREE;
|
|
@@ -37960,7 +38121,9 @@ var GameVehiclesThree = (() => {
|
|
|
37960
38121
|
const sgn = new V3().crossVectors(axisV, tangent).dot(outv) > 0 ? 1 : -1;
|
|
37961
38122
|
piv.quaternion.setFromAxisAngle(axisV, sgn * (0.6 + R() * 0.3));
|
|
37962
38123
|
}
|
|
37963
|
-
|
|
38124
|
+
const shared2 = { panelBand, roofOff, tailOff, followersIn, windowsOver, doorGap, mirrorHang, doorHang, lidHang, flapHang };
|
|
38125
|
+
Object.assign(I, shared2);
|
|
38126
|
+
return shared2;
|
|
37964
38127
|
}
|
|
37965
38128
|
function installDamageParts(kit) {
|
|
37966
38129
|
const THREE = kit.THREE;
|
|
@@ -38074,7 +38237,8 @@ var GameVehiclesThree = (() => {
|
|
|
38074
38237
|
}
|
|
38075
38238
|
function tireMeshes(w) {
|
|
38076
38239
|
const out = [];
|
|
38077
|
-
w.traverse(function(
|
|
38240
|
+
w.traverse(function(node) {
|
|
38241
|
+
const o = node;
|
|
38078
38242
|
if (o.isMesh && o.material === MATERIALS.rubber) out.push(o);
|
|
38079
38243
|
});
|
|
38080
38244
|
return out;
|
|
@@ -38133,7 +38297,8 @@ var GameVehiclesThree = (() => {
|
|
|
38133
38297
|
c.zoneDrops.push({ x: w.position.x, z: w.position.z, d: r * 0.24 });
|
|
38134
38298
|
} else if (b === 4) {
|
|
38135
38299
|
let rr = 0;
|
|
38136
|
-
w.traverse(function(
|
|
38300
|
+
w.traverse(function(node) {
|
|
38301
|
+
const o = node;
|
|
38137
38302
|
if (!o.isMesh || o.material === MATERIALS.rubber) return;
|
|
38138
38303
|
if (!o.geometry.boundingSphere) o.geometry.computeBoundingSphere();
|
|
38139
38304
|
const cc = o.geometry.boundingSphere.center.clone().applyMatrix4(o.matrix);
|
|
@@ -38341,7 +38506,8 @@ var GameVehiclesThree = (() => {
|
|
|
38341
38506
|
const xf = H.x0 + (H.x1 - H.x0) * (0.5 + R() * 0.1);
|
|
38342
38507
|
const k = 0.55 + R() * 0.2;
|
|
38343
38508
|
const v = new V3();
|
|
38344
|
-
H.piv.children.forEach(function(
|
|
38509
|
+
H.piv.children.forEach(function(node) {
|
|
38510
|
+
const msh = node;
|
|
38345
38511
|
if (!msh.isMesh) return;
|
|
38346
38512
|
msh.updateMatrix();
|
|
38347
38513
|
const M = msh.matrix;
|
|
@@ -38534,7 +38700,7 @@ var GameVehiclesThree = (() => {
|
|
|
38534
38700
|
});
|
|
38535
38701
|
void K;
|
|
38536
38702
|
}
|
|
38537
|
-
|
|
38703
|
+
const shared2 = {
|
|
38538
38704
|
glassPt,
|
|
38539
38705
|
glassIn,
|
|
38540
38706
|
glassBand,
|
|
@@ -38552,7 +38718,9 @@ var GameVehiclesThree = (() => {
|
|
|
38552
38718
|
bumperBand,
|
|
38553
38719
|
partBand,
|
|
38554
38720
|
bendAft
|
|
38555
|
-
}
|
|
38721
|
+
};
|
|
38722
|
+
Object.assign(I, shared2);
|
|
38723
|
+
return shared2;
|
|
38556
38724
|
}
|
|
38557
38725
|
function installZoneDerive(kit) {
|
|
38558
38726
|
const THREE = kit.THREE;
|
|
@@ -38573,7 +38741,8 @@ var GameVehiclesThree = (() => {
|
|
|
38573
38741
|
}
|
|
38574
38742
|
function resolveObjs(c, list2, z) {
|
|
38575
38743
|
const out = [];
|
|
38576
|
-
(list2 || []).forEach(function(
|
|
38744
|
+
(list2 || []).forEach(function(item) {
|
|
38745
|
+
const o = item;
|
|
38577
38746
|
if (!o) return;
|
|
38578
38747
|
if (typeof o === "string") {
|
|
38579
38748
|
c.parts.forEach(function(p) {
|
|
@@ -38822,7 +38991,9 @@ var GameVehiclesThree = (() => {
|
|
|
38822
38991
|
return null;
|
|
38823
38992
|
}
|
|
38824
38993
|
kit.zoneOwner = ownerOf;
|
|
38825
|
-
|
|
38994
|
+
const shared2 = { parseDir, resolveObjs, deriveZones, carMap, zonesOf, ownerOf };
|
|
38995
|
+
Object.assign(I, shared2);
|
|
38996
|
+
return shared2;
|
|
38826
38997
|
}
|
|
38827
38998
|
var REAR_GLASS_KEYS = ["rear_window", "window_rear", "quarter_glass"];
|
|
38828
38999
|
function installZoneAuto(kit) {
|
|
@@ -39615,7 +39786,9 @@ var GameVehiclesThree = (() => {
|
|
|
39615
39786
|
if (!wheelsDone) wheelZones(false);
|
|
39616
39787
|
return Z;
|
|
39617
39788
|
}
|
|
39618
|
-
|
|
39789
|
+
const shared2 = { autoZones };
|
|
39790
|
+
Object.assign(I, shared2);
|
|
39791
|
+
return shared2;
|
|
39619
39792
|
}
|
|
39620
39793
|
function installZoneApply(kit) {
|
|
39621
39794
|
const THREE = kit.THREE;
|
|
@@ -39824,7 +39997,9 @@ var GameVehiclesThree = (() => {
|
|
|
39824
39997
|
c.rand = R0;
|
|
39825
39998
|
return c.zoneState;
|
|
39826
39999
|
};
|
|
39827
|
-
|
|
40000
|
+
const shared2 = { fadePaint, abandonFx, burntFx, settleDrops };
|
|
40001
|
+
Object.assign(I, shared2);
|
|
40002
|
+
return shared2;
|
|
39828
40003
|
}
|
|
39829
40004
|
function installScenarios(kit) {
|
|
39830
40005
|
const THREE = kit.THREE;
|
|
@@ -39979,7 +40154,9 @@ var GameVehiclesThree = (() => {
|
|
|
39979
40154
|
}
|
|
39980
40155
|
return { p, dir };
|
|
39981
40156
|
};
|
|
39982
|
-
|
|
40157
|
+
const shared2 = { BODY_TYPES };
|
|
40158
|
+
Object.assign(I, shared2);
|
|
40159
|
+
return shared2;
|
|
39983
40160
|
}
|
|
39984
40161
|
var SVGNS = "http://www.w3.org/2000/svg";
|
|
39985
40162
|
var BAND_TEXT = ["#10140f", "#1c1606", "#1f1206", "#fff3ef", "#f1f2f2"];
|
|
@@ -40134,7 +40311,8 @@ var GameVehiclesThree = (() => {
|
|
|
40134
40311
|
}
|
|
40135
40312
|
g.addEventListener("click", pick);
|
|
40136
40313
|
g.addEventListener("keydown", function(e) {
|
|
40137
|
-
|
|
40314
|
+
const key = e.key;
|
|
40315
|
+
if (key === "Enter" || key === " ") {
|
|
40138
40316
|
e.preventDefault();
|
|
40139
40317
|
pick();
|
|
40140
40318
|
}
|
|
@@ -40147,7 +40325,7 @@ var GameVehiclesThree = (() => {
|
|
|
40147
40325
|
return kit.bands.map(function(B, i) {
|
|
40148
40326
|
const b = el("button", null, B.name);
|
|
40149
40327
|
b.type = "button";
|
|
40150
|
-
b.dataset.b = i;
|
|
40328
|
+
b.dataset.b = String(i);
|
|
40151
40329
|
b.style.setProperty("--band", B.color);
|
|
40152
40330
|
b.addEventListener("click", function() {
|
|
40153
40331
|
if (onPick) onPick(B.health, i);
|
|
@@ -40369,6 +40547,7 @@ var GameVehiclesThree = (() => {
|
|
|
40369
40547
|
hash,
|
|
40370
40548
|
clamp,
|
|
40371
40549
|
smooth,
|
|
40550
|
+
// filled by the modules below, each with the helpers it shares
|
|
40372
40551
|
_: {}
|
|
40373
40552
|
};
|
|
40374
40553
|
kit.fuels = {};
|
|
@@ -40446,8 +40625,8 @@ var GameVehiclesThree = (() => {
|
|
|
40446
40625
|
fn.apply(kit, args);
|
|
40447
40626
|
});
|
|
40448
40627
|
};
|
|
40449
|
-
kit.configure = function(
|
|
40450
|
-
o =
|
|
40628
|
+
kit.configure = function(cfg) {
|
|
40629
|
+
const o = cfg || {};
|
|
40451
40630
|
if (o.bands)
|
|
40452
40631
|
o.bands.forEach(function(b, i) {
|
|
40453
40632
|
if (kit.bands[i] && b) Object.assign(kit.bands[i], b);
|
|
@@ -40483,7 +40662,8 @@ var GameVehiclesThree = (() => {
|
|
|
40483
40662
|
}
|
|
40484
40663
|
;
|
|
40485
40664
|
["impactStain", "defaultSplat", "defaultGroup", "damagedScenario"].forEach(function(k) {
|
|
40486
|
-
|
|
40665
|
+
const v = o[k];
|
|
40666
|
+
if (v !== void 0) kit.config[k] = v;
|
|
40487
40667
|
});
|
|
40488
40668
|
return kit;
|
|
40489
40669
|
};
|
|
@@ -40658,6 +40838,8 @@ var GameVehiclesThree = (() => {
|
|
|
40658
40838
|
heli: ["battery", "alternator", "gearbox"]
|
|
40659
40839
|
};
|
|
40660
40840
|
var HITCH_CHANCE = { car: 30, truck: 60, bus: 0, tractor: 100, quad: 40, bike: 0, tank: 0, boat: 0, plane: 0, heli: 0 };
|
|
40841
|
+
var GLASS_LENS_HP = 320;
|
|
40842
|
+
var PLASTIC_LENS_HP = 900;
|
|
40661
40843
|
var STEEL_KG_M2 = 7;
|
|
40662
40844
|
var ALU_KG_M2 = 3.2;
|
|
40663
40845
|
var kindOf = (c) => {
|
|
@@ -40815,7 +40997,9 @@ var GameVehiclesThree = (() => {
|
|
|
40815
40997
|
continue;
|
|
40816
40998
|
}
|
|
40817
40999
|
if (role === "light") {
|
|
40818
|
-
|
|
41000
|
+
const lens = /^head/.test(id) ? spec.headlightLens ?? "polycarbonate" : "acrylic";
|
|
41001
|
+
const glassLens = lens === "glass";
|
|
41002
|
+
add2({ 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] });
|
|
40819
41003
|
continue;
|
|
40820
41004
|
}
|
|
40821
41005
|
if (role === "bumper") {
|
|
@@ -41269,20 +41453,185 @@ var GameVehiclesThree = (() => {
|
|
|
41269
41453
|
mesh2.geometry.dispose();
|
|
41270
41454
|
mesh2.geometry = g;
|
|
41271
41455
|
}
|
|
41456
|
+
var STRIP_SMOOTH_DEG = 180;
|
|
41457
|
+
var SKIN_BAND = 0.05;
|
|
41458
|
+
var BODY_FACING = 0.5;
|
|
41459
|
+
var FIELDS = 4;
|
|
41460
|
+
var SEAM_THIN = 0.03;
|
|
41461
|
+
var SEAM_AT_EDGE = 0.04;
|
|
41462
|
+
var SEAM_TALL = 0.4;
|
|
41463
|
+
var SLIVER_AREA = 1e-10;
|
|
41464
|
+
function cutStripOverDoor(vehicleKit, params) {
|
|
41465
|
+
const kit = vehicleKit;
|
|
41466
|
+
const strip = params.strip;
|
|
41467
|
+
const toVehicle = params.toVehicle;
|
|
41468
|
+
const { x0, x1 } = params;
|
|
41469
|
+
const THREE = kit.THREE;
|
|
41470
|
+
const at = new THREE.Vector3();
|
|
41471
|
+
const along = (x, y, z) => at.set(x, y, z).applyMatrix4(toVehicle).x;
|
|
41472
|
+
const piece = (tests) => {
|
|
41473
|
+
const mesh2 = new THREE.Mesh(strip.geometry.clone(), strip.material);
|
|
41474
|
+
kit.cutMesh(mesh2, tests, STRIP_SMOOTH_DEG, {});
|
|
41475
|
+
return mesh2;
|
|
41476
|
+
};
|
|
41477
|
+
const over = piece([{ sdf: (x, y, z) => along(x, y, z) - x0 }, { sdf: (x, y, z) => x1 - along(x, y, z) }]);
|
|
41478
|
+
const after = piece([{ sdf: (x, y, z) => along(x, y, z) - x1 }]);
|
|
41479
|
+
kit.cutMesh(strip, [{ sdf: (x, y, z) => x0 - along(x, y, z) }], STRIP_SMOOTH_DEG, {});
|
|
41480
|
+
const joined = joinTriangles(THREE, strip.geometry, after.geometry);
|
|
41481
|
+
strip.geometry.dispose();
|
|
41482
|
+
after.geometry.dispose();
|
|
41483
|
+
strip.geometry = joined;
|
|
41484
|
+
return over;
|
|
41485
|
+
}
|
|
41486
|
+
function joinTriangles(THREE, first, second) {
|
|
41487
|
+
const a = first.index ? first.toNonIndexed() : first;
|
|
41488
|
+
const b = second.index ? second.toNonIndexed() : second;
|
|
41489
|
+
const flags = [...solidTriangles(THREE, a), ...solidTriangles(THREE, b)];
|
|
41490
|
+
const both = new THREE.BufferGeometry();
|
|
41491
|
+
for (const name of Object.keys(a.attributes)) {
|
|
41492
|
+
const p = a.getAttribute(name);
|
|
41493
|
+
const q = b.getAttribute(name);
|
|
41494
|
+
if (!q || q.itemSize !== p.itemSize) continue;
|
|
41495
|
+
const array = new Float32Array(p.array.length + q.array.length);
|
|
41496
|
+
array.set(p.array, 0);
|
|
41497
|
+
array.set(q.array, p.array.length);
|
|
41498
|
+
both.setAttribute(name, new THREE.Float32BufferAttribute(array, p.itemSize));
|
|
41499
|
+
}
|
|
41500
|
+
if (a !== first) a.dispose();
|
|
41501
|
+
if (b !== second) b.dispose();
|
|
41502
|
+
const out = pickTriangles(THREE, both, flags, true) ?? new THREE.BufferGeometry();
|
|
41503
|
+
both.dispose();
|
|
41504
|
+
return out;
|
|
41505
|
+
}
|
|
41506
|
+
function solidTriangles(THREE, geometry) {
|
|
41507
|
+
const pos = geometry.getAttribute("position");
|
|
41508
|
+
const triangle = new THREE.Triangle();
|
|
41509
|
+
const flags = [];
|
|
41510
|
+
for (let t = 0; t * 3 + 2 < pos.count; t++) {
|
|
41511
|
+
triangle.a.fromBufferAttribute(pos, t * 3);
|
|
41512
|
+
triangle.b.fromBufferAttribute(pos, t * 3 + 1);
|
|
41513
|
+
triangle.c.fromBufferAttribute(pos, t * 3 + 2);
|
|
41514
|
+
flags.push(triangle.getArea() > SLIVER_AREA);
|
|
41515
|
+
}
|
|
41516
|
+
return flags;
|
|
41517
|
+
}
|
|
41518
|
+
function splitDoorSkin(three, meshes, toVehicleOf, side2, depth) {
|
|
41519
|
+
const THREE = three;
|
|
41520
|
+
const pieces = meshes;
|
|
41521
|
+
const toVehicle = toVehicleOf;
|
|
41522
|
+
const v = new THREE.Vector3();
|
|
41523
|
+
const corners = [new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3()];
|
|
41524
|
+
const triangle = new THREE.Triangle();
|
|
41525
|
+
const centres = pieces.map((mesh2) => {
|
|
41526
|
+
const geometry = mesh2.geometry.index ? mesh2.geometry.toNonIndexed() : mesh2.geometry;
|
|
41527
|
+
const matrix = toVehicle(mesh2);
|
|
41528
|
+
const pos = geometry.getAttribute("position");
|
|
41529
|
+
const out = new Float32Array(pos.count / 3 * FIELDS);
|
|
41530
|
+
for (let t = 0; t * 3 + 2 < pos.count; t++) {
|
|
41531
|
+
let y = 0;
|
|
41532
|
+
let across = 0;
|
|
41533
|
+
for (let k = 0; k < 3; k++) {
|
|
41534
|
+
corners[k].fromBufferAttribute(pos, t * 3 + k).applyMatrix4(matrix);
|
|
41535
|
+
y += corners[k].y / 3;
|
|
41536
|
+
across += side2 * corners[k].z / 3;
|
|
41537
|
+
}
|
|
41538
|
+
out[t * FIELDS] = y;
|
|
41539
|
+
out[t * FIELDS + 1] = across;
|
|
41540
|
+
triangle.set(corners[0], corners[1], corners[2]).getNormal(v);
|
|
41541
|
+
out[t * FIELDS + 2] = v.y;
|
|
41542
|
+
out[t * FIELDS + 3] = v.x;
|
|
41543
|
+
}
|
|
41544
|
+
return { geometry, out };
|
|
41545
|
+
});
|
|
41546
|
+
const outer = /* @__PURE__ */ new Map();
|
|
41547
|
+
for (const { out } of centres)
|
|
41548
|
+
for (let t = 0; t * FIELDS < out.length; t++) {
|
|
41549
|
+
const band = Math.floor(out[t * FIELDS] / SKIN_BAND);
|
|
41550
|
+
outer.set(band, Math.max(outer.get(band) ?? -Infinity, out[t * FIELDS + 1]));
|
|
41551
|
+
}
|
|
41552
|
+
const surfaceAt = (y) => {
|
|
41553
|
+
const band = Math.floor(y / SKIN_BAND);
|
|
41554
|
+
return Math.max(outer.get(band - 1) ?? -Infinity, outer.get(band) ?? -Infinity, outer.get(band + 1) ?? -Infinity);
|
|
41555
|
+
};
|
|
41556
|
+
return centres.map(({ geometry, out }, i) => {
|
|
41557
|
+
const near = [];
|
|
41558
|
+
for (let t = 0; t * FIELDS < out.length; t++) {
|
|
41559
|
+
const f = t * FIELDS;
|
|
41560
|
+
const body = out[f + 1] < surfaceAt(out[f]) - depth && (out[f + 2] < -BODY_FACING || Math.abs(out[f + 3]) > BODY_FACING);
|
|
41561
|
+
near.push(!body);
|
|
41562
|
+
}
|
|
41563
|
+
const result = { skin: pickTriangles(THREE, geometry, near, true), deep: pickTriangles(THREE, geometry, near, false) };
|
|
41564
|
+
if (geometry !== pieces[i].geometry) geometry.dispose();
|
|
41565
|
+
return result;
|
|
41566
|
+
});
|
|
41567
|
+
}
|
|
41568
|
+
function leaveDeepSkinOnBody(three, meshes, params) {
|
|
41569
|
+
const THREE = three;
|
|
41570
|
+
const pieces = meshes;
|
|
41571
|
+
const toVehicle = params.toVehicle;
|
|
41572
|
+
const { side: side2, depth } = params;
|
|
41573
|
+
const split = splitDoorSkin(THREE, pieces, (mesh2) => new THREE.Matrix4().multiplyMatrices(toVehicle, mesh2.matrixWorld), side2, depth);
|
|
41574
|
+
split.forEach(({ skin, deep }, i) => {
|
|
41575
|
+
const piece = pieces[i];
|
|
41576
|
+
if (!deep || !skin || !piece.parent) return;
|
|
41577
|
+
const body = new THREE.Mesh(deep, piece.material);
|
|
41578
|
+
body.position.copy(piece.position);
|
|
41579
|
+
body.quaternion.copy(piece.quaternion);
|
|
41580
|
+
body.scale.copy(piece.scale);
|
|
41581
|
+
body.castShadow = piece.castShadow;
|
|
41582
|
+
body.receiveShadow = piece.receiveShadow;
|
|
41583
|
+
piece.parent.add(body);
|
|
41584
|
+
piece.geometry.dispose();
|
|
41585
|
+
piece.geometry = skin;
|
|
41586
|
+
});
|
|
41587
|
+
}
|
|
41588
|
+
function pickTriangles(THREE, geometry, flags, wanted) {
|
|
41589
|
+
const count2 = flags.filter((flag) => flag === wanted).length;
|
|
41590
|
+
if (!count2) return null;
|
|
41591
|
+
const out = new THREE.BufferGeometry();
|
|
41592
|
+
for (const name of Object.keys(geometry.attributes)) {
|
|
41593
|
+
const attribute = geometry.getAttribute(name);
|
|
41594
|
+
const size = attribute.itemSize;
|
|
41595
|
+
const source = attribute.array;
|
|
41596
|
+
const array = new Float32Array(count2 * 3 * size);
|
|
41597
|
+
let w = 0;
|
|
41598
|
+
flags.forEach((flag, t) => {
|
|
41599
|
+
if (flag !== wanted) return;
|
|
41600
|
+
array.set(source.subarray(t * 3 * size, (t + 1) * 3 * size), w);
|
|
41601
|
+
w += 3 * size;
|
|
41602
|
+
});
|
|
41603
|
+
out.setAttribute(name, new THREE.Float32BufferAttribute(array, size));
|
|
41604
|
+
}
|
|
41605
|
+
out.computeBoundingBox();
|
|
41606
|
+
out.computeBoundingSphere();
|
|
41607
|
+
return out;
|
|
41608
|
+
}
|
|
41609
|
+
function isDoorSeam(three, params) {
|
|
41610
|
+
const THREE = three;
|
|
41611
|
+
const box2 = params.box;
|
|
41612
|
+
const { zone, side: side2, dark } = params;
|
|
41613
|
+
if (!dark || box2.isEmpty()) return false;
|
|
41614
|
+
const size = box2.getSize(new THREE.Vector3());
|
|
41615
|
+
const centre = box2.getCenter(new THREE.Vector3());
|
|
41616
|
+
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;
|
|
41617
|
+
if (centre.y < zone.y0 || centre.y > zone.y1) return false;
|
|
41618
|
+
return Math.abs(centre.x - zone.x0) < SEAM_AT_EDGE || Math.abs(centre.x - zone.x1) < SEAM_AT_EDGE;
|
|
41619
|
+
}
|
|
41272
41620
|
var HOLE_DECAL_SCALE = 2.4;
|
|
41273
41621
|
var DOOR_DEPTH = 0.07;
|
|
41622
|
+
var DOOR_SKIN_DEPTH = 0.09;
|
|
41623
|
+
var DOOR_FLOOR_DEPTH = 0.2;
|
|
41274
41624
|
var DOOR_EDGE_PIECES = 8;
|
|
41275
41625
|
var DOOR_EDGE_REACH = 0.08;
|
|
41276
41626
|
var DOOR_CARD_COLOR = "#3b3e42";
|
|
41277
41627
|
var DOOR_LINER_COLOR = "#5a5e64";
|
|
41278
41628
|
var DOOR_LINER_DARK = 0.15;
|
|
41279
|
-
var DOOR_STRIP_THIN = 0.
|
|
41629
|
+
var DOOR_STRIP_THIN = 0.13;
|
|
41280
41630
|
var DOOR_STRIP_NEAR = 0.04;
|
|
41281
41631
|
var DOOR_STRIP_TALL = 0.22;
|
|
41282
|
-
var
|
|
41283
|
-
var DOOR_STRIP_VERTICES = 2e4;
|
|
41632
|
+
var DOOR_STRIP_VERTICES = 6e4;
|
|
41284
41633
|
var DOOR_SILL = 0.25;
|
|
41285
|
-
var DOOR_STRIP_OVER = 0.
|
|
41634
|
+
var DOOR_STRIP_OVER = 0.05;
|
|
41286
41635
|
var DOOR_TOP_OVER_PANE = 0.03;
|
|
41287
41636
|
var HOLE_TEXTURE_SIZE = 64;
|
|
41288
41637
|
var LAMINATED_HP = 1e3;
|
|
@@ -41386,6 +41735,8 @@ var GameVehiclesThree = (() => {
|
|
|
41386
41735
|
__publicField(this, "syncPlates", /* @__PURE__ */ new Map());
|
|
41387
41736
|
__publicField(this, "skins", /* @__PURE__ */ new Map());
|
|
41388
41737
|
__publicField(this, "doorTops", /* @__PURE__ */ new Map());
|
|
41738
|
+
__publicField(this, "seams", /* @__PURE__ */ new Map());
|
|
41739
|
+
__publicField(this, "openNow", /* @__PURE__ */ new Set());
|
|
41389
41740
|
__publicField(this, "lightsOn", true);
|
|
41390
41741
|
__publicField(this, "warming");
|
|
41391
41742
|
__publicField(this, "tornThisFrame", false);
|
|
@@ -41562,6 +41913,11 @@ var GameVehiclesThree = (() => {
|
|
|
41562
41913
|
}
|
|
41563
41914
|
panel.visible = open && !this.skins.get(id);
|
|
41564
41915
|
recess.visible = open && !this.skins.get(id);
|
|
41916
|
+
if (open) this.openNow.add(id);
|
|
41917
|
+
else this.openNow.delete(id);
|
|
41918
|
+
this.seams.forEach((doors, seam) => {
|
|
41919
|
+
if (doors.has(id)) seam.visible = ![...doors].some((door) => this.openNow.has(door));
|
|
41920
|
+
});
|
|
41565
41921
|
};
|
|
41566
41922
|
const euler = piv.rotation;
|
|
41567
41923
|
const quaternion = piv.quaternion;
|
|
@@ -41604,11 +41960,13 @@ var GameVehiclesThree = (() => {
|
|
|
41604
41960
|
const pcs = I.cutPanel(this.c, z, rect, true, dirty, { anyN: true }).map((x) => x.mesh).filter((m) => !!m);
|
|
41605
41961
|
this.mend(dirty);
|
|
41606
41962
|
if (pcs.length) {
|
|
41963
|
+
leaveDeepSkinOnBody(this.THREE, pcs, { toVehicle: inv, side: z.side < 0 ? -1 : 1, depth: DOOR_SKIN_DEPTH });
|
|
41607
41964
|
const panes = I.windowsOver(this.c, z, inv);
|
|
41608
41965
|
const seals = panes.map((g) => I.paneSeals.get(g)).filter((s) => !!s);
|
|
41609
41966
|
const mirrors = this.mirrorsOn(z);
|
|
41610
41967
|
const frames = this.framesAround(panes, inv);
|
|
41611
|
-
|
|
41968
|
+
const followers = I.followersIn(this.c, z, inv).filter((o) => !this.takeSeam(o, id, z, inv) && !this.inFloor(o, piv, z, inv));
|
|
41969
|
+
objs = [...pcs, ...followers, ...panes, ...seals, ...mirrors, ...frames];
|
|
41612
41970
|
}
|
|
41613
41971
|
} else {
|
|
41614
41972
|
const pcs = this.cutZone(z);
|
|
@@ -41636,6 +41994,25 @@ var GameVehiclesThree = (() => {
|
|
|
41636
41994
|
this.c.root.updateMatrixWorld(true);
|
|
41637
41995
|
return objs.length > 0;
|
|
41638
41996
|
}
|
|
41997
|
+
/** 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. */
|
|
41998
|
+
inFloor(o, piv, z, inv) {
|
|
41999
|
+
const side2 = z.side < 0 ? -1 : 1;
|
|
42000
|
+
const centre = this.I.localBox(this.c, o, inv).getCenter(new this.THREE.Vector3());
|
|
42001
|
+
const skin = side2 * (piv.position.z - side2 * 0.016);
|
|
42002
|
+
return centre.y < z.box.y0 + DOOR_SILL && side2 * centre.z < skin - DOOR_FLOOR_DEPTH;
|
|
42003
|
+
}
|
|
42004
|
+
/** 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. */
|
|
42005
|
+
takeSeam(o, id, z, inv) {
|
|
42006
|
+
const B = z.box;
|
|
42007
|
+
const box2 = this.I.localBox(this.c, o, inv);
|
|
42008
|
+
const color2 = o.material?.color;
|
|
42009
|
+
const dark = !!color2 && color2.getHSL({ h: 0, s: 0, l: 0 }).l < DOOR_LINER_DARK;
|
|
42010
|
+
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;
|
|
42011
|
+
const doors = this.seams.get(o) ?? /* @__PURE__ */ new Set();
|
|
42012
|
+
doors.add(id);
|
|
42013
|
+
this.seams.set(o, doors);
|
|
42014
|
+
return true;
|
|
42015
|
+
}
|
|
41639
42016
|
/** 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. */
|
|
41640
42017
|
doorEdges(piv, z, y1) {
|
|
41641
42018
|
const THREE = this.THREE;
|
|
@@ -41657,13 +42034,15 @@ var GameVehiclesThree = (() => {
|
|
|
41657
42034
|
const at = this.surface("z", side2, B, [[x, y]]);
|
|
41658
42035
|
return at != null && Math.abs(at - flat) < DOOR_EDGE_REACH ? at : flat;
|
|
41659
42036
|
});
|
|
41660
|
-
const band = (lift) => {
|
|
42037
|
+
const band = (lift, path, closed) => {
|
|
41661
42038
|
const position = [];
|
|
41662
42039
|
const index = [];
|
|
41663
|
-
|
|
41664
|
-
|
|
42040
|
+
path.forEach((at, i) => {
|
|
42041
|
+
const [x, y] = loop[at];
|
|
42042
|
+
position.push(x, y, heights[at] + side2 * lift, x, y, heights[at] + side2 * (lift - DOOR_DEPTH));
|
|
42043
|
+
if (!closed && i === path.length - 1) return;
|
|
41665
42044
|
const a = i * 2;
|
|
41666
|
-
const b = (i + 1) %
|
|
42045
|
+
const b = (i + 1) % path.length * 2;
|
|
41667
42046
|
index.push(a, a + 1, b, b, a + 1, b + 1);
|
|
41668
42047
|
});
|
|
41669
42048
|
const g = new THREE.BufferGeometry();
|
|
@@ -41691,8 +42070,11 @@ var GameVehiclesThree = (() => {
|
|
|
41691
42070
|
card.castShadow = false;
|
|
41692
42071
|
this.c.vehicle.add(card);
|
|
41693
42072
|
piv.attach(card);
|
|
41694
|
-
const
|
|
41695
|
-
const
|
|
42073
|
+
const all = loop.map((_, i) => i);
|
|
42074
|
+
const top = 2 * DOOR_EDGE_PIECES;
|
|
42075
|
+
const sides = [...all.slice(3 * DOOR_EDGE_PIECES), ...all.slice(0, top + 1)];
|
|
42076
|
+
const edges = new THREE.Mesh(band(2e-3, all, true), paint);
|
|
42077
|
+
const lining = new THREE.Mesh(band(2e-3, sides, false), paint);
|
|
41696
42078
|
for (const m of [edges, lining]) {
|
|
41697
42079
|
m.userData.noFollow = true;
|
|
41698
42080
|
m.castShadow = false;
|
|
@@ -41749,26 +42131,14 @@ var GameVehiclesThree = (() => {
|
|
|
41749
42131
|
const box2 = this.I.localBox(this.c, o, inv);
|
|
41750
42132
|
const size = box2.getSize(new THREE.Vector3());
|
|
41751
42133
|
const mid = box2.getCenter(new THREE.Vector3());
|
|
41752
|
-
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) <
|
|
42134
|
+
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;
|
|
41753
42135
|
const toVehicle = new THREE.Matrix4().multiplyMatrices(inv, o.matrixWorld);
|
|
41754
|
-
const
|
|
41755
|
-
const sdf = (x, y, zz) => {
|
|
41756
|
-
v.set(x, y, zz).applyMatrix4(toVehicle);
|
|
41757
|
-
return Math.max(x0 - v.x, v.x - x1);
|
|
41758
|
-
};
|
|
41759
|
-
const over = new THREE.Mesh(o.geometry.clone(), o.material);
|
|
42136
|
+
const over = cutStripOverDoor(this.kit, { strip: o, toVehicle, x0, x1 });
|
|
41760
42137
|
over.position.copy(o.position);
|
|
41761
42138
|
over.quaternion.copy(o.quaternion);
|
|
41762
42139
|
over.scale.copy(o.scale);
|
|
41763
42140
|
this.c.vehicle.add(over);
|
|
41764
42141
|
over.updateMatrixWorld(true);
|
|
41765
|
-
const overToVehicle = new THREE.Matrix4().multiplyMatrices(inv, over.matrixWorld);
|
|
41766
|
-
const w = new THREE.Vector3();
|
|
41767
|
-
this.kit.cutMesh(over, [{ sdf: (x, y, zz) => {
|
|
41768
|
-
w.set(x, y, zz).applyMatrix4(overToVehicle);
|
|
41769
|
-
return -Math.max(x0 - w.x, w.x - x1);
|
|
41770
|
-
} }], STRIP_SMOOTH_DEG, {});
|
|
41771
|
-
this.kit.cutMesh(o, [{ sdf }], STRIP_SMOOTH_DEG, {});
|
|
41772
42142
|
over.userData.noFollow = true;
|
|
41773
42143
|
piv.attach(over);
|
|
41774
42144
|
}
|
|
@@ -42349,11 +42719,18 @@ var GameVehiclesThree = (() => {
|
|
|
42349
42719
|
}
|
|
42350
42720
|
}
|
|
42351
42721
|
}
|
|
42722
|
+
/** 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. */
|
|
42723
|
+
crackLight(p, pierced) {
|
|
42724
|
+
const z = this.zone(p);
|
|
42725
|
+
if (!z) return;
|
|
42726
|
+
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);
|
|
42727
|
+
}
|
|
42352
42728
|
/** The lens of a light breaks and its unit stays (damaged) or goes (destroyed). */
|
|
42353
42729
|
breakLight(p, gone) {
|
|
42354
42730
|
const z = this.zone(p);
|
|
42355
42731
|
if (!z) return;
|
|
42356
42732
|
for (const L of z.lights) {
|
|
42733
|
+
L.lensMaterial = p.material;
|
|
42357
42734
|
this.kit.breakLight(this.c, L, new this.THREE.Vector3(p.box.center[0] > 0 ? -1 : 1, 0, 0));
|
|
42358
42735
|
if (gone) {
|
|
42359
42736
|
if (L.group) L.group.visible = false;
|
|
@@ -42995,6 +43372,7 @@ var GameVehiclesThree = (() => {
|
|
|
42995
43372
|
wear(p, amount, out);
|
|
42996
43373
|
syncZone(p);
|
|
42997
43374
|
if (p.hp <= 0) lose(p, "broken", out, cause);
|
|
43375
|
+
else if (p.def.role === "light") vis?.crackLight(p.def, dtype === "ballistic");
|
|
42998
43376
|
if (p.def.role === "tyre" && !p.flat && p.hp < p.def.hp * 0.6 && !p.lost) {
|
|
42999
43377
|
p.flat = true;
|
|
43000
43378
|
vis?.tyreFlat(p.def, 0.24);
|
|
@@ -43807,7 +44185,7 @@ var GameVehiclesThree = (() => {
|
|
|
43807
44185
|
if (!list2.length) return 1;
|
|
43808
44186
|
return Math.min(...list2.map((p) => p.lost || !attached(p.def.id) ? 0 : p.hp / p.def.hp));
|
|
43809
44187
|
};
|
|
43810
|
-
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) }));
|
|
44188
|
+
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 }));
|
|
43811
44189
|
const status = computeStatus();
|
|
43812
44190
|
const brakeSystem = [...ps.values()].find((p) => p.def.role === "brakes" && p.def.contains);
|
|
43813
44191
|
const fluidLeft = brakeSystem ? clamp((brakeSystem.liters ?? 0) / brakeSystem.def.contains.liters / BRAKE_FLUID_NEEDED, 0, 1) : 1;
|
|
@@ -44035,7 +44413,7 @@ var GameVehiclesThree = (() => {
|
|
|
44035
44413
|
};
|
|
44036
44414
|
}
|
|
44037
44415
|
|
|
44038
|
-
// ../game-audio/dist/chunk-
|
|
44416
|
+
// ../game-audio/dist/chunk-UUWKSG4J.js
|
|
44039
44417
|
var DISTANCE_CURVES = {
|
|
44040
44418
|
/** The game's `sfx`: `vol / (1 + d² × 0.004)`, cutoff `/ (1 + d × 0.01)`, silent below 0.01 (jogo L62091–62092, L62101). */
|
|
44041
44419
|
game_sfx: { model: "inverse_square", k: 4e-3, cutoffK: 0.01, minGain: 0.01 },
|
|
@@ -44558,6 +44936,7 @@ var GameVehiclesThree = (() => {
|
|
|
44558
44936
|
burst: 20,
|
|
44559
44937
|
burstSpacing: 0.06
|
|
44560
44938
|
};
|
|
44939
|
+
var CATALOG = new Map([...SFX_CATALOG, ...SFX_IMPACTS].map((entry) => [entry.id, entry]));
|
|
44561
44940
|
var PT = {
|
|
44562
44941
|
group: "Som",
|
|
44563
44942
|
name: "Painel de som (arquivos e C1\u2013C10)",
|
|
@@ -44632,9 +45011,9 @@ var GameVehiclesThree = (() => {
|
|
|
44632
45011
|
strengths: { light: "leve", medium: "m\xE9dio", heavy: "forte" },
|
|
44633
45012
|
states: { file: "A", synth: "S", missing: "F" },
|
|
44634
45013
|
criteria: { C1: "C1 Sincronia", C2: "C2 Certo p/ a\xE7\xE3o", C3: "C3 Dist\xE2ncia", C4: "C4 Posi\xE7\xE3o", C5: "C5 Varia\xE7\xE3o", C6: "C6 Volume", C7: "C7 Intensidade", C8: "C8 Cauda", C9: "C9 Rajada", C10: "C10 Escuta" },
|
|
44635
|
-
metrics: { source: "1 \xB7 Fonte do que tocou", chosen: "1 \xB7 Escolhido", matrix: "2 \xB7 Matriz", last: "\xDAltimo tocado", ab: "4 \xB7 A \xD7 B", blind: "4 \xB7 X", verdicts: "4 \xB7 Prefer\xEAncias", state: "5 \xB7 Medi\xE7\xE3o", count: "1 \xB7 Cat\xE1logo" },
|
|
45014
|
+
metrics: { source: "1 \xB7 Fonte do que tocou", chosen: "1 \xB7 Escolhido", matrix: "2 \xB7 Matriz", last: "\xDAltimo tocado", ab: "4 \xB7 A \xD7 B", blind: "4 \xB7 X", verdicts: "4 \xB7 Prefer\xEAncias", state: "5 \xB7 Medi\xE7\xE3o", count: "1 \xB7 Cat\xE1logo", unlicensed: "1 \xB7 Arquivo sem licen\xE7a" },
|
|
44636
45015
|
run: { idle: "parada", measuring: "medindo\u2026", done: "pronta", failed: "falhou", recording: "gravando\u2026", recorded: "grava\xE7\xE3o baixada" },
|
|
44637
|
-
words: { none: "\u2014", hidden: "? (revele)", prefers: "prefere", approved: "aprovado pelo dono" },
|
|
45016
|
+
words: { none: "\u2014", hidden: "? (revele)", prefers: "prefere", approved: "aprovado pelo dono", local_file: "arquivo do pacote local", sdk_file: "grava\xE7\xE3o do SDK", synth: "s\xEDntese do SDK" },
|
|
44638
45017
|
sources: { sdk: "SDK", user: "seu som", synth: "sintetizado" },
|
|
44639
45018
|
probe: "Fonte do som",
|
|
44640
45019
|
wall: "Parede (oclus\xE3o)",
|
|
@@ -44705,9 +45084,9 @@ var GameVehiclesThree = (() => {
|
|
|
44705
45084
|
environments: { indoor: "indoor", outdoor: "outdoor" },
|
|
44706
45085
|
strengths: { light: "light", medium: "medium", heavy: "heavy" },
|
|
44707
45086
|
criteria: { C1: "C1 Sync", C2: "C2 Right sound", C3: "C3 Distance", C4: "C4 Position", C5: "C5 Variation", C6: "C6 Level", C7: "C7 Strength", C8: "C8 Tail", C9: "C9 Burst", C10: "C10 Listening" },
|
|
44708
|
-
metrics: { source: "1 \xB7 Source of what played", chosen: "1 \xB7 Chosen", matrix: "2 \xB7 Matrix", last: "Last played", ab: "4 \xB7 A \xD7 B", blind: "4 \xB7 X", verdicts: "4 \xB7 Preferences", state: "5 \xB7 Measurement", count: "1 \xB7 Catalogue" },
|
|
45087
|
+
metrics: { source: "1 \xB7 Source of what played", chosen: "1 \xB7 Chosen", matrix: "2 \xB7 Matrix", last: "Last played", ab: "4 \xB7 A \xD7 B", blind: "4 \xB7 X", verdicts: "4 \xB7 Preferences", state: "5 \xB7 Measurement", count: "1 \xB7 Catalogue", unlicensed: "1 \xB7 File without licence" },
|
|
44709
45088
|
run: { idle: "idle", measuring: "measuring\u2026", done: "done", failed: "failed", recording: "recording\u2026", recorded: "recording downloaded" },
|
|
44710
|
-
words: { none: "\u2014", hidden: "? (reveal)", prefers: "prefers", approved: "approved by the owner" },
|
|
45089
|
+
words: { none: "\u2014", hidden: "? (reveal)", prefers: "prefers", approved: "approved by the owner", local_file: "local pack file", sdk_file: "SDK recording", synth: "SDK synthesis" },
|
|
44711
45090
|
sources: { sdk: "SDK", user: "your sound", synth: "synthesized" },
|
|
44712
45091
|
probe: "Sound source",
|
|
44713
45092
|
wall: "Wall (occlusion)",
|
|
@@ -44861,9 +45240,137 @@ var GameVehiclesThree = (() => {
|
|
|
44861
45240
|
duration: 0.5,
|
|
44862
45241
|
layers: [{ source: { kind: "osc", wave: "sine", frequency: { set: 880 } }, repeat: { count: 3, spacing: 0.7 }, envelope: [[0, 0.06, "set"], [0.5, 1e-4, "exp", "fixed"]] }],
|
|
44863
45242
|
falloff: { model: "none" }
|
|
45243
|
+
},
|
|
45244
|
+
{
|
|
45245
|
+
// the parking sensor: a short high beep, repeated by the cabin faster as the obstacle comes close
|
|
45246
|
+
id: "parking_beep",
|
|
45247
|
+
bus: "world",
|
|
45248
|
+
duration: 0.09,
|
|
45249
|
+
layers: [{ source: { kind: "osc", wave: "sine", frequency: { set: 2300 } }, envelope: [[0, 0.07, "set"], [0.08, 1e-4, "exp", "fixed"]] }],
|
|
45250
|
+
falloff: { model: "none" }
|
|
45251
|
+
},
|
|
45252
|
+
{
|
|
45253
|
+
// an emergency siren's wail: a tone rising and falling slowly (one sweep about every 3 s), played again by the cabin as it ends
|
|
45254
|
+
id: "siren_wail",
|
|
45255
|
+
bus: "world",
|
|
45256
|
+
order: "siren",
|
|
45257
|
+
duration: 3,
|
|
45258
|
+
tail: 0.05,
|
|
45259
|
+
layers: [
|
|
45260
|
+
{
|
|
45261
|
+
source: { kind: "osc", wave: "sawtooth", frequency: { set: 1050 } },
|
|
45262
|
+
modulators: [{ target: "frequency", wave: "sine", rate: 0.33, depth: 420 }],
|
|
45263
|
+
filters: { mode: "serial", bank: [{ type: "lowpass", frequency: { set: 2400 } }] },
|
|
45264
|
+
envelope: [[0, 1e-4, "set", "fixed"], [0.08, 0.07, "linear"], [2.95, 0.07, "set"], [3, 1e-4, "exp", "fixed"]]
|
|
45265
|
+
}
|
|
45266
|
+
],
|
|
45267
|
+
falloff: { model: "none" }
|
|
45268
|
+
},
|
|
45269
|
+
{
|
|
45270
|
+
// the yelp: the same tone swept fast, for a junction
|
|
45271
|
+
id: "siren_yelp",
|
|
45272
|
+
bus: "world",
|
|
45273
|
+
order: "siren",
|
|
45274
|
+
duration: 2,
|
|
45275
|
+
tail: 0.05,
|
|
45276
|
+
layers: [
|
|
45277
|
+
{
|
|
45278
|
+
source: { kind: "osc", wave: "sawtooth", frequency: { set: 1100 } },
|
|
45279
|
+
modulators: [{ target: "frequency", wave: "triangle", rate: 4, depth: 380 }],
|
|
45280
|
+
filters: { mode: "serial", bank: [{ type: "lowpass", frequency: { set: 2600 } }] },
|
|
45281
|
+
envelope: [[0, 1e-4, "set", "fixed"], [0.05, 0.07, "linear"], [1.95, 0.07, "set"], [2, 1e-4, "exp", "fixed"]]
|
|
45282
|
+
}
|
|
45283
|
+
],
|
|
45284
|
+
falloff: { model: "none" }
|
|
45285
|
+
},
|
|
45286
|
+
{
|
|
45287
|
+
// the wires under the column touching: a crackle of bright noise
|
|
45288
|
+
id: "hotwire_spark",
|
|
45289
|
+
bus: "world",
|
|
45290
|
+
duration: 0.12,
|
|
45291
|
+
layers: [
|
|
45292
|
+
{
|
|
45293
|
+
source: { kind: "noise", offset: "random" },
|
|
45294
|
+
filters: { mode: "serial", bank: [{ type: "highpass", frequency: { set: 3200 } }] },
|
|
45295
|
+
modulators: [{ target: "gain", wave: "square", rate: 60, depth: 0.1, base: 0.12 }],
|
|
45296
|
+
envelope: [[0, 0.2, "set"], [0.12, 1e-4, "exp", "fixed"]]
|
|
45297
|
+
}
|
|
45298
|
+
],
|
|
45299
|
+
falloff: { model: "none" }
|
|
45300
|
+
},
|
|
45301
|
+
{
|
|
45302
|
+
// the glovebox latch: a small plastic click and the lid dropping
|
|
45303
|
+
id: "glovebox_latch",
|
|
45304
|
+
bus: "world",
|
|
45305
|
+
duration: 0.14,
|
|
45306
|
+
layers: [
|
|
45307
|
+
{ source: { kind: "noise", offset: "random" }, filters: { mode: "serial", bank: [{ type: "bandpass", frequency: { set: 1800 }, q: 2 }] }, envelope: [[0, 0.16, "set"], [0.03, 1e-4, "exp", "fixed"]] },
|
|
45308
|
+
{ source: { kind: "osc", wave: "triangle", frequency: { set: 240 } }, envelope: [[0, 1e-4, "set", "fixed"], [0.06, 0.08, "linear"], [0.14, 1e-4, "exp", "fixed"]] }
|
|
45309
|
+
],
|
|
45310
|
+
falloff: { model: "none" }
|
|
44864
45311
|
}
|
|
44865
45312
|
];
|
|
44866
45313
|
var CABIN_BANK = { id: "vehicle_cabin", sounds: CABIN_SOUNDS, loops: [] };
|
|
45314
|
+
var hz = (midi) => 440 * 2 ** ((midi - 69) / 12);
|
|
45315
|
+
var layer = (note, beat, wave, level) => {
|
|
45316
|
+
const [at, midi, beats] = note;
|
|
45317
|
+
const length = beats * beat;
|
|
45318
|
+
return {
|
|
45319
|
+
at: at * beat,
|
|
45320
|
+
duration: length,
|
|
45321
|
+
source: { kind: "osc", wave, frequency: { set: hz(midi) } },
|
|
45322
|
+
envelope: [[0, 1e-4, "set"], [0.01, level, "linear"], [Math.max(0.02, length * 0.9), level * 0.35, "linear"], [length, 1e-4, "exp", "fixed"]]
|
|
45323
|
+
};
|
|
45324
|
+
};
|
|
45325
|
+
function radioTrack(spec) {
|
|
45326
|
+
const beat = 60 / spec.bpm;
|
|
45327
|
+
const recipes = Array.from({ length: spec.bars }, (_, bar) => {
|
|
45328
|
+
const inBar = (notes) => notes.filter((n) => n[0] >= bar * 4 && n[0] < bar * 4 + 4).map((n) => [n[0] - bar * 4, n[1], n[2]]);
|
|
45329
|
+
const layers2 = [
|
|
45330
|
+
...inBar(spec.bass).map((n) => layer(n, beat, "triangle", 0.16)),
|
|
45331
|
+
...inBar(spec.chords).map((n) => layer(n, beat, "sine", 0.05)),
|
|
45332
|
+
...inBar(spec.melody).map((n) => layer(n, beat, spec.wave, 0.07))
|
|
45333
|
+
];
|
|
45334
|
+
return { id: `${spec.id}_${bar}`, bus: "world", duration: 4 * beat, layers: layers2, falloff: { model: "none" } };
|
|
45335
|
+
});
|
|
45336
|
+
return { song: { id: spec.id, barSeconds: 4 * beat, bars: recipes.map((r) => r.id) }, recipes };
|
|
45337
|
+
}
|
|
45338
|
+
var chord = (bar, root, minor = false) => [[bar * 4, root, 4], [bar * 4, root + (minor ? 3 : 4), 4], [bar * 4, root + 7, 4]];
|
|
45339
|
+
var bassLine = (roots, pattern) => roots.flatMap((root, bar) => pattern.map((b) => [bar * 4 + b, root - 12, 0.9]));
|
|
45340
|
+
var TRACKS = [
|
|
45341
|
+
// a bright pop loop: I–V–vi–IV in C
|
|
45342
|
+
radioTrack({
|
|
45343
|
+
id: "radio_track_pop",
|
|
45344
|
+
bpm: 112,
|
|
45345
|
+
bars: 4,
|
|
45346
|
+
wave: "square",
|
|
45347
|
+
bass: bassLine([48, 55, 57, 53], [0, 1.5, 2, 3]),
|
|
45348
|
+
chords: [...chord(0, 60), ...chord(1, 55), ...chord(2, 57, true), ...chord(3, 53)],
|
|
45349
|
+
melody: [[0, 76, 1], [1, 74, 0.5], [1.5, 72, 1.5], [4, 74, 1], [5, 76, 1], [6, 79, 2], [8, 76, 1], [9, 74, 1], [10, 72, 2], [12, 72, 1], [13, 74, 1], [14, 72, 2]]
|
|
45350
|
+
}),
|
|
45351
|
+
// a syncopated loop in A minor, the bass on the off-beats
|
|
45352
|
+
radioTrack({
|
|
45353
|
+
id: "radio_track_groove",
|
|
45354
|
+
bpm: 100,
|
|
45355
|
+
bars: 4,
|
|
45356
|
+
wave: "triangle",
|
|
45357
|
+
bass: bassLine([57, 62, 64, 57], [0, 0.75, 1.5, 2.5, 3.25]),
|
|
45358
|
+
chords: [...chord(0, 57, true), ...chord(1, 62, true), ...chord(2, 64), ...chord(3, 57, true)],
|
|
45359
|
+
melody: [[0.5, 72, 0.5], [1.25, 76, 0.75], [2.5, 74, 1], [4.5, 77, 0.5], [5.25, 74, 0.75], [6.5, 72, 1.5], [8.5, 71, 0.5], [9.25, 74, 0.75], [10.5, 76, 1.5], [12.5, 72, 0.5], [13.25, 69, 2]]
|
|
45360
|
+
}),
|
|
45361
|
+
// a slow blues-like loop in F with a swung melody
|
|
45362
|
+
radioTrack({
|
|
45363
|
+
id: "radio_track_slow",
|
|
45364
|
+
bpm: 76,
|
|
45365
|
+
bars: 4,
|
|
45366
|
+
wave: "sine",
|
|
45367
|
+
bass: bassLine([53, 58, 53, 60], [0, 2]),
|
|
45368
|
+
chords: [...chord(0, 65), ...chord(1, 58), ...chord(2, 65), ...chord(3, 60)],
|
|
45369
|
+
melody: [[0, 72, 1.5], [1.67, 75, 0.33], [2, 77, 2], [4, 74, 1], [5, 72, 1], [6, 70, 2], [8, 72, 1.5], [9.67, 69, 0.33], [10, 65, 2], [12, 67, 1], [13, 70, 1], [14, 72, 2]]
|
|
45370
|
+
})
|
|
45371
|
+
];
|
|
45372
|
+
var RADIO_TRACKS = TRACKS.map((t) => t.song);
|
|
45373
|
+
var RADIO_BANK = { id: "vehicle_radio", sounds: TRACKS.flatMap((t) => t.recipes), loops: [] };
|
|
44867
45374
|
var FOLEY_FALLOFF = {
|
|
44868
45375
|
model: "inverse_square",
|
|
44869
45376
|
k: 0.02,
|
|
@@ -45470,11 +45977,11 @@ var GameVehiclesThree = (() => {
|
|
|
45470
45977
|
...s.splash ? [sceneNoise({ type: "bandpass", f: s.splash.f * take.f, f2: s.splash.f2 * take.f, q: 1.4, d: s.splash.d * take.t * weight ** 0.4, vol: s.splash.vol * gait.vol * take.v * weight ** 0.5 })] : []
|
|
45471
45978
|
];
|
|
45472
45979
|
}
|
|
45473
|
-
var quieter = (level, layers2) => layers2.map((
|
|
45474
|
-
const gain =
|
|
45475
|
-
if (typeof gain === "number") return { ...
|
|
45476
|
-
if (Array.isArray(gain)) return { ...
|
|
45477
|
-
return
|
|
45980
|
+
var quieter = (level, layers2) => layers2.map((layer2) => {
|
|
45981
|
+
const gain = layer2.gain ?? 1;
|
|
45982
|
+
if (typeof gain === "number") return { ...layer2, gain: gain * level };
|
|
45983
|
+
if (Array.isArray(gain)) return { ...layer2, gain: [gain[0] * level, gain[1] * level] };
|
|
45984
|
+
return layer2;
|
|
45478
45985
|
});
|
|
45479
45986
|
var recipe = (id, layers2, falloff, bus = "world") => ({ id, bus, pan: true, layers: layers2, falloff, sources: ["sdk"] });
|
|
45480
45987
|
var takeId = (id, index) => `${id}_${String(index + 1).padStart(2, "0")}`;
|
|
@@ -45490,7 +45997,7 @@ var GameVehiclesThree = (() => {
|
|
|
45490
45997
|
(take) => quieter(LANDING_LEVEL, [
|
|
45491
45998
|
// both feet, a hair apart, then the knees taking the weight (a low body thump) and the clothes settling
|
|
45492
45999
|
...footLayers(surface, take, GAITS.run, LANDINGS[landing2].weight),
|
|
45493
|
-
...footLayers(surface, { ...take, v: take.v * 0.6 }, GAITS.run, LANDINGS[landing2].weight * 0.6).map((
|
|
46000
|
+
...footLayers(surface, { ...take, v: take.v * 0.6 }, GAITS.run, LANDINGS[landing2].weight * 0.6).map((layer2) => ({ ...layer2, at: (typeof layer2.at === "number" ? layer2.at : 0) + 0.018 * take.t })),
|
|
45494
46001
|
sceneTone({ f: 60 * take.f, f2: 38, d: 0.14 * LANDINGS[landing2].weight * take.t, vol: 0.22 * LANDINGS[landing2].weight ** 0.7 * take.v, delay: 0.02 }),
|
|
45495
46002
|
sceneNoise({ type: "bandpass", f: [1800, 2600], q: 0.8, d: 0.18, vol: LANDINGS[landing2].cloth * take.v, delay: 0.04 })
|
|
45496
46003
|
]),
|
|
@@ -45536,7 +46043,7 @@ var GameVehiclesThree = (() => {
|
|
|
45536
46043
|
fall_damage: (take) => [
|
|
45537
46044
|
...BODY.body_fall(take),
|
|
45538
46045
|
sceneNoise({ type: "highpass", f: 2800, d: 0.02, vol: 0.35 * take.v, delay: 0.01 }),
|
|
45539
|
-
...voice({ f0: 170, f1: 110, d: 0.32, fA: 650, fB: 1150, noise: 0.25, vol: 0.32 })(take).map((
|
|
46046
|
+
...voice({ f0: 170, f1: 110, d: 0.32, fA: 650, fB: 1150, noise: 0.25, vol: 0.32 })(take).map((layer2) => ({ ...layer2, at: 0.08 }))
|
|
45540
46047
|
],
|
|
45541
46048
|
player_hurt: voice({ f0: 150, f1: 105, d: 0.26, fA: 620, fB: 1100, noise: 0.3, vol: 0.35 }),
|
|
45542
46049
|
player_breath_run: (take) => [
|
|
@@ -45594,6 +46101,109 @@ var GameVehiclesThree = (() => {
|
|
|
45594
46101
|
};
|
|
45595
46102
|
var BODY_FOLEY_SET_IDS = [...FOOTSTEP_SOUND_IDS, ...LAND_SOUND_IDS, ...BODY_SOUND_IDS];
|
|
45596
46103
|
|
|
46104
|
+
// src/audio/engine-mix.ts
|
|
46105
|
+
var clamp01 = (v) => v < 0 ? 0 : v > 1 ? 1 : v;
|
|
46106
|
+
var firingHz = (profile, rpm) => rpm / 60 * (profile.cylinders / 2);
|
|
46107
|
+
var rpmShare = (profile, rpm) => clamp01((rpm - profile.idleRpm) / (profile.redlineRpm - profile.idleRpm));
|
|
46108
|
+
var layerWeight = (centre, width, n) => {
|
|
46109
|
+
const d = Math.abs(n - centre) / width;
|
|
46110
|
+
return d >= 1 ? 0 : Math.cos(d * Math.PI / 2);
|
|
46111
|
+
};
|
|
46112
|
+
function engineMix(profile, input) {
|
|
46113
|
+
const throttle = clamp01(input.throttle);
|
|
46114
|
+
const on = input.rpm > 0;
|
|
46115
|
+
const n = rpmShare(profile, input.rpm);
|
|
46116
|
+
const level = on ? profile.closedThrottle + (1 - profile.closedThrottle) * throttle : 0;
|
|
46117
|
+
const open = 0.5 * n + 0.5 * throttle;
|
|
46118
|
+
const hz2 = firingHz(profile, input.rpm);
|
|
46119
|
+
const tones = profile.layers.map((layer2) => ({
|
|
46120
|
+
sound: layer2.sound,
|
|
46121
|
+
volume: layer2.gain * level * layerWeight(layer2.centre, layer2.width, n),
|
|
46122
|
+
frequency: hz2 * layer2.harmonic,
|
|
46123
|
+
cutoff: layer2.cutoff[0] + (layer2.cutoff[1] - layer2.cutoff[0]) * open
|
|
46124
|
+
}));
|
|
46125
|
+
const load = profile.load;
|
|
46126
|
+
return [
|
|
46127
|
+
...tones,
|
|
46128
|
+
{ sound: load.sound, volume: on ? load.gain * (0.15 + 0.85 * throttle) * (0.35 + 0.65 * n) : 0, cutoff: load.cutoff[0] + (load.cutoff[1] - load.cutoff[0]) * open }
|
|
46129
|
+
];
|
|
46130
|
+
}
|
|
46131
|
+
function createGearGuess(profile) {
|
|
46132
|
+
let gear = 0;
|
|
46133
|
+
return {
|
|
46134
|
+
rpm(speed, throttle) {
|
|
46135
|
+
const v = Math.abs(speed);
|
|
46136
|
+
const ratios = profile.rpmPerMps;
|
|
46137
|
+
if (v < 0.3) {
|
|
46138
|
+
gear = 0;
|
|
46139
|
+
return profile.idleRpm + (profile.redlineRpm - profile.idleRpm) * 0.12 * clamp01(throttle);
|
|
46140
|
+
}
|
|
46141
|
+
const at = (g) => v * ratios[g];
|
|
46142
|
+
while (gear < ratios.length - 1 && at(gear) > profile.redlineRpm * 0.85) gear++;
|
|
46143
|
+
while (gear > 0 && at(gear) < profile.redlineRpm * 0.4) gear--;
|
|
46144
|
+
return Math.max(profile.idleRpm, Math.min(profile.redlineRpm, at(gear)));
|
|
46145
|
+
},
|
|
46146
|
+
get gear() {
|
|
46147
|
+
return gear;
|
|
46148
|
+
}
|
|
46149
|
+
};
|
|
46150
|
+
}
|
|
46151
|
+
|
|
46152
|
+
// src/audio/profiles.ts
|
|
46153
|
+
var DEFAULT_VEHICLE_SOUND_KEYS = {
|
|
46154
|
+
start: "engine_start",
|
|
46155
|
+
stop: "engine_stop",
|
|
46156
|
+
fail: "engine_fail",
|
|
46157
|
+
crashLight: "crash_light",
|
|
46158
|
+
crashMedium: "crash_medium",
|
|
46159
|
+
crashHeavy: "crash_heavy",
|
|
46160
|
+
skidAsphalt: "tire_skid_asphalt",
|
|
46161
|
+
skidDirt: "tire_skid_dirt",
|
|
46162
|
+
roll: "tire_roll",
|
|
46163
|
+
brakeSqueal: "brake_squeal",
|
|
46164
|
+
hitBody: "vehicle_hit_pedestrian",
|
|
46165
|
+
siren: "siren",
|
|
46166
|
+
rotor: "helicopter_rotor_loop"
|
|
46167
|
+
};
|
|
46168
|
+
var CRASH_SPEEDS = { medium: 6, heavy: 14 };
|
|
46169
|
+
var layers = (id, cutoffs, gains) => [
|
|
46170
|
+
{ sound: `engine_${id}_low`, centre: 0, width: 0.5, harmonic: 1, gain: gains[0], cutoff: cutoffs[0] },
|
|
46171
|
+
{ sound: `engine_${id}_mid`, centre: 0.45, width: 0.5, harmonic: 1, gain: gains[1], cutoff: cutoffs[1] },
|
|
46172
|
+
{ sound: `engine_${id}_high`, centre: 1, width: 0.6, harmonic: 2, gain: gains[2], cutoff: cutoffs[2] }
|
|
46173
|
+
];
|
|
46174
|
+
var CAR_ENGINE = {
|
|
46175
|
+
id: "car",
|
|
46176
|
+
cylinders: 4,
|
|
46177
|
+
idleRpm: 800,
|
|
46178
|
+
redlineRpm: 6500,
|
|
46179
|
+
// a 5-speed hatch: 1st tops at ~13 m/s, 5th at ~50 m/s
|
|
46180
|
+
rpmPerMps: [500, 300, 205, 155, 125],
|
|
46181
|
+
layers: layers("car", [[220, 520], [420, 1300], [900, 2600]], [0.11, 0.075, 0.04]),
|
|
46182
|
+
load: { sound: "engine_car_load", gain: 0.05, cutoff: [350, 1600] },
|
|
46183
|
+
closedThrottle: 0.55
|
|
46184
|
+
};
|
|
46185
|
+
var TRUCK_ENGINE = {
|
|
46186
|
+
id: "truck",
|
|
46187
|
+
cylinders: 6,
|
|
46188
|
+
idleRpm: 650,
|
|
46189
|
+
redlineRpm: 2600,
|
|
46190
|
+
rpmPerMps: [420, 260, 170, 120, 90, 72],
|
|
46191
|
+
layers: layers("truck", [[160, 380], [300, 800], [600, 1500]], [0.13, 0.08, 0.035]),
|
|
46192
|
+
load: { sound: "engine_truck_load", gain: 0.06, cutoff: [250, 900] },
|
|
46193
|
+
closedThrottle: 0.6
|
|
46194
|
+
};
|
|
46195
|
+
var BIKE_ENGINE = {
|
|
46196
|
+
id: "bike",
|
|
46197
|
+
cylinders: 4,
|
|
46198
|
+
idleRpm: 1300,
|
|
46199
|
+
redlineRpm: 12e3,
|
|
46200
|
+
rpmPerMps: [900, 640, 500, 410, 350, 310],
|
|
46201
|
+
layers: layers("bike", [[350, 900], [700, 2200], [1500, 4200]], [0.08, 0.07, 0.05]),
|
|
46202
|
+
load: { sound: "engine_bike_load", gain: 0.045, cutoff: [600, 2600] },
|
|
46203
|
+
closedThrottle: 0.5
|
|
46204
|
+
};
|
|
46205
|
+
var ENGINE_PROFILES = { car: CAR_ENGINE, truck: TRUCK_ENGINE, bike: BIKE_ENGINE };
|
|
46206
|
+
|
|
45597
46207
|
// src/audio/bank.ts
|
|
45598
46208
|
var VEHICLE_LOOP_FALLOFF = { model: "inverse_square", k: 4e-3, cutoffK: 0.01 };
|
|
45599
46209
|
var SDK = "sdk: vehicle sounds (sons/checklist-sons.md 5.6)";
|
|
@@ -45632,7 +46242,16 @@ var GameVehiclesThree = (() => {
|
|
|
45632
46242
|
...engineLoops("bike", 600, 1400, 2800, 1200),
|
|
45633
46243
|
noiseLoop("tire_skid_asphalt", "bandpass", 1900, 5, "rubber squealing on asphalt: a narrow band of noise near 2 kHz"),
|
|
45634
46244
|
noiseLoop("tire_skid_dirt", "lowpass", 700, 0.8, "tyres sliding on dirt and gravel: a dull, wide hiss"),
|
|
45635
|
-
noiseLoop("tire_roll", "lowpass", 400, 0.7, "road noise of the tyres rolling, brighter with the speed")
|
|
46245
|
+
noiseLoop("tire_roll", "lowpass", 400, 0.7, "road noise of the tyres rolling, brighter with the speed"),
|
|
46246
|
+
// a pad on a disc: a thin, nearly pure whistle near 3.4 kHz (a narrow band of noise, so it wavers as a real squeal does)
|
|
46247
|
+
// a siren: a square through a low-pass, its pitch swept by the vehicle every frame (wail: a slow rise and fall; yelp: a fast one)
|
|
46248
|
+
toneLoop("siren", "square", "lowpass", 2600, 0.8, "emergency siren, the sweep driven by the vehicle"),
|
|
46249
|
+
// the blades: a low rumble chopped at the blade-pass rate (≈ 18 Hz for a light helicopter's main rotor)
|
|
46250
|
+
{
|
|
46251
|
+
...noiseLoop("helicopter_rotor_loop", "lowpass", 320, 0.9, "helicopter rotor: low rumble chopped by the blades"),
|
|
46252
|
+
modulators: [{ target: "gain", wave: "sine", rate: 18, depth: 0.45, base: 0.55 }]
|
|
46253
|
+
},
|
|
46254
|
+
noiseLoop("brake_squeal", "bandpass", 3400, 28, "brake pads squealing on the discs as the car comes to a stop")
|
|
45636
46255
|
];
|
|
45637
46256
|
var recipe2 = (id, layers2, line) => ({ ...sceneRecipe(id, layers2, line), sources: [SDK, line] });
|
|
45638
46257
|
var crank = (count2, spacing) => [
|
|
@@ -45676,6 +46295,17 @@ var GameVehiclesThree = (() => {
|
|
|
45676
46295
|
],
|
|
45677
46296
|
"crash above 50 km/h: metal folding, the glass going, debris falling"
|
|
45678
46297
|
),
|
|
46298
|
+
// a body hit by a car: the dull slap of the bumper on a person, the body folding over the bonnet, at speed a crack of the windscreen
|
|
46299
|
+
recipe2(
|
|
46300
|
+
"vehicle_hit_pedestrian",
|
|
46301
|
+
[
|
|
46302
|
+
sceneTone({ f: 95, f2: 50, d: 0.14, vol: 0.9 }),
|
|
46303
|
+
sceneNoise({ type: "lowpass", f: 600, d: 0.12, vol: 0.8 }),
|
|
46304
|
+
sceneNoise({ type: "bandpass", f: 280, q: 1.2, d: 0.18, vol: 0.55, delay: 0.09 }),
|
|
46305
|
+
sceneNoise({ type: "highpass", f: 2600, d: 0.05, vol: 0.18, delay: 0.1 })
|
|
46306
|
+
],
|
|
46307
|
+
"a person hit by a car: the bumper slap, the body on the bonnet"
|
|
46308
|
+
),
|
|
45679
46309
|
// the game's horn (two squares at 415 and 523 Hz, jogo L70272) heard from where the car is; a truck's air horn lower and longer
|
|
45680
46310
|
recipe2("horn_car", [sceneTone({ wave: "square", f: 415, d: 0.6, vol: 0.09 }), sceneTone({ wave: "square", f: 523, d: 0.6, vol: 0.09 })], "car horn: the game chord, placed and panned"),
|
|
45681
46311
|
recipe2("horn_truck", [sceneTone({ wave: "sawtooth", f: 220, d: 1.1, vol: 0.1 }), sceneTone({ wave: "sawtooth", f: 277, d: 1.1, vol: 0.08 }), sceneNoise({ type: "bandpass", f: 900, q: 2, d: 1.1, vol: 0.05 })], "truck air horn: low reedy chord"),
|
|
@@ -45685,107 +46315,65 @@ var GameVehiclesThree = (() => {
|
|
|
45685
46315
|
recipe2("car_trunk_close", [sceneTone({ f: 90, f2: 55, d: 0.15, vol: 0.65 }), sceneNoise({ type: "bandpass", f: 500, q: 1, d: 0.12, vol: 0.5 }), ...latch(0.01, 0.28), sceneNoise({ type: "bandpass", f: 1800, q: 3, d: 0.04, vol: 0.1, delay: 0.06 })], "trunk or hatch shut: a lighter thump, the latch and a small rattle"),
|
|
45686
46316
|
recipe2("car_hood_close", [sceneTone({ f: 70, f2: 40, d: 0.22, vol: 0.8 }), sceneNoise({ type: "bandpass", f: 850, q: 1.4, d: 0.2, vol: 0.6, wet: 0.3 }), sceneTone({ f: 900, f2: 860, d: 0.18, vol: 0.05 }), ...latch(0.015, 0.3)], "hood slammed: a big sheet of metal ringing a little, the latch")
|
|
45687
46317
|
];
|
|
45688
|
-
var
|
|
45689
|
-
|
|
45690
|
-
|
|
45691
|
-
|
|
45692
|
-
|
|
45693
|
-
|
|
45694
|
-
|
|
45695
|
-
|
|
45696
|
-
return d >= 1 ? 0 : Math.cos(d * Math.PI / 2);
|
|
46318
|
+
var CAR_RECORDED_RPM = { idle: 1e3, high: 2520 };
|
|
46319
|
+
var CAR_START_RUN_STOP = {
|
|
46320
|
+
/** The take the times below were measured on. */
|
|
46321
|
+
take: "_01.",
|
|
46322
|
+
/** The starter and the engine catching (at 0.58 s) and flaring; the loops take over at the crank time of the vehicle. */
|
|
46323
|
+
start: { offset: 0, duration: 1.3 },
|
|
46324
|
+
/** The ignition off: the engine running down to the end of the file. */
|
|
46325
|
+
stop: { offset: 9.96, duration: 0.64 }
|
|
45697
46326
|
};
|
|
45698
|
-
|
|
45699
|
-
|
|
45700
|
-
|
|
45701
|
-
|
|
45702
|
-
|
|
45703
|
-
|
|
45704
|
-
|
|
45705
|
-
|
|
45706
|
-
|
|
45707
|
-
|
|
45708
|
-
|
|
45709
|
-
|
|
45710
|
-
|
|
45711
|
-
|
|
45712
|
-
|
|
45713
|
-
|
|
45714
|
-
|
|
45715
|
-
|
|
45716
|
-
|
|
45717
|
-
|
|
45718
|
-
|
|
46327
|
+
var carLayer = (id, file, rpm, harmonic, offset) => ({
|
|
46328
|
+
id,
|
|
46329
|
+
file,
|
|
46330
|
+
loop: true,
|
|
46331
|
+
// the layer's oscillator plays the firing frequency times its harmonic: the file sounds at that frequency for the RPM it was recorded at
|
|
46332
|
+
baseFrequency: firingHz(CAR_ENGINE, rpm) * harmonic,
|
|
46333
|
+
falloff: VEHICLE_LOOP_FALLOFF,
|
|
46334
|
+
...offset === void 0 ? {} : { offset }
|
|
46335
|
+
});
|
|
46336
|
+
var VEHICLE_SAMPLE_ALIASES = [
|
|
46337
|
+
carLayer("engine_car_low", "engine_loop_car_idle", CAR_RECORDED_RPM.idle, 1),
|
|
46338
|
+
carLayer("engine_car_mid", "engine_loop_car_high", CAR_RECORDED_RPM.high, 1),
|
|
46339
|
+
// the same file as the mid layer, read from two seconds in, so the two do not sum in phase where they cross
|
|
46340
|
+
carLayer("engine_car_high", "engine_loop_car_high", CAR_RECORDED_RPM.high, 2, 2),
|
|
46341
|
+
// the cut points are of take _01 (10.6 s); _02 (21.9 s) starts already running and idles at 9.96 s, so it is left out of both
|
|
46342
|
+
{ id: "engine_start", file: "engine_start_run_stop", only: CAR_START_RUN_STOP.take, ...CAR_START_RUN_STOP.start, falloff: VEHICLE_LOOP_FALLOFF },
|
|
46343
|
+
{ id: "engine_stop", file: "engine_start_run_stop", only: CAR_START_RUN_STOP.take, ...CAR_START_RUN_STOP.stop, falloff: VEHICLE_LOOP_FALLOFF },
|
|
46344
|
+
{ id: "car_door_close", file: "car_door_shut" },
|
|
46345
|
+
{ id: "car_trunk_close", file: "car_trunk_shut" }
|
|
46346
|
+
];
|
|
46347
|
+
var VEHICLE_PRELOAD_SOUNDS = [...VEHICLE_SAMPLE_ALIASES.map((alias) => alias.id), "car_door_open"];
|
|
46348
|
+
var VEHICLE_SOUND_BANK = { id: "vehicles_three", sounds: VEHICLE_SOUNDS, loops: VEHICLE_LOOPS, sampleAliases: VEHICLE_SAMPLE_ALIASES };
|
|
46349
|
+
|
|
46350
|
+
// src/audio/engine-budget.ts
|
|
46351
|
+
var distanceSq = (a, b) => (a[0] - b[0]) ** 2 + (a[1] - b[1]) ** 2 + (a[2] - b[2]) ** 2;
|
|
46352
|
+
function createEngineBudget(options) {
|
|
46353
|
+
const max = Math.max(1, options.max ?? 6);
|
|
46354
|
+
const places = /* @__PURE__ */ new Map();
|
|
45719
46355
|
return {
|
|
45720
|
-
|
|
45721
|
-
const
|
|
45722
|
-
|
|
45723
|
-
if (
|
|
45724
|
-
|
|
45725
|
-
|
|
46356
|
+
admit(vehicle, position) {
|
|
46357
|
+
const own = distanceSq(position, options.listener());
|
|
46358
|
+
places.set(vehicle, own);
|
|
46359
|
+
if (places.size <= max) return true;
|
|
46360
|
+
let nearer = 0;
|
|
46361
|
+
for (const [other, d] of places) {
|
|
46362
|
+
if (other === vehicle) continue;
|
|
46363
|
+
if (d < own) nearer++;
|
|
46364
|
+
if (nearer >= max) return false;
|
|
45726
46365
|
}
|
|
45727
|
-
|
|
45728
|
-
while (gear < ratios.length - 1 && at(gear) > profile.redlineRpm * 0.85) gear++;
|
|
45729
|
-
while (gear > 0 && at(gear) < profile.redlineRpm * 0.4) gear--;
|
|
45730
|
-
return Math.max(profile.idleRpm, Math.min(profile.redlineRpm, at(gear)));
|
|
46366
|
+
return true;
|
|
45731
46367
|
},
|
|
45732
|
-
|
|
45733
|
-
|
|
46368
|
+
release(vehicle) {
|
|
46369
|
+
places.delete(vehicle);
|
|
46370
|
+
},
|
|
46371
|
+
get size() {
|
|
46372
|
+
return places.size;
|
|
45734
46373
|
}
|
|
45735
46374
|
};
|
|
45736
46375
|
}
|
|
45737
46376
|
|
|
45738
|
-
// src/audio/profiles.ts
|
|
45739
|
-
var DEFAULT_VEHICLE_SOUND_KEYS = {
|
|
45740
|
-
start: "engine_start",
|
|
45741
|
-
stop: "engine_stop",
|
|
45742
|
-
fail: "engine_fail",
|
|
45743
|
-
crashLight: "crash_light",
|
|
45744
|
-
crashMedium: "crash_medium",
|
|
45745
|
-
crashHeavy: "crash_heavy",
|
|
45746
|
-
skidAsphalt: "tire_skid_asphalt",
|
|
45747
|
-
skidDirt: "tire_skid_dirt",
|
|
45748
|
-
roll: "tire_roll"
|
|
45749
|
-
};
|
|
45750
|
-
var CRASH_SPEEDS = { medium: 6, heavy: 14 };
|
|
45751
|
-
var layers = (id, cutoffs, gains) => [
|
|
45752
|
-
{ sound: `engine_${id}_low`, centre: 0, width: 0.5, harmonic: 1, gain: gains[0], cutoff: cutoffs[0] },
|
|
45753
|
-
{ sound: `engine_${id}_mid`, centre: 0.45, width: 0.5, harmonic: 1, gain: gains[1], cutoff: cutoffs[1] },
|
|
45754
|
-
{ sound: `engine_${id}_high`, centre: 1, width: 0.6, harmonic: 2, gain: gains[2], cutoff: cutoffs[2] }
|
|
45755
|
-
];
|
|
45756
|
-
var CAR_ENGINE = {
|
|
45757
|
-
id: "car",
|
|
45758
|
-
cylinders: 4,
|
|
45759
|
-
idleRpm: 800,
|
|
45760
|
-
redlineRpm: 6500,
|
|
45761
|
-
// a 5-speed hatch: 1st tops at ~13 m/s, 5th at ~50 m/s
|
|
45762
|
-
rpmPerMps: [500, 300, 205, 155, 125],
|
|
45763
|
-
layers: layers("car", [[220, 520], [420, 1300], [900, 2600]], [0.11, 0.075, 0.04]),
|
|
45764
|
-
load: { sound: "engine_car_load", gain: 0.05, cutoff: [350, 1600] },
|
|
45765
|
-
closedThrottle: 0.55
|
|
45766
|
-
};
|
|
45767
|
-
var TRUCK_ENGINE = {
|
|
45768
|
-
id: "truck",
|
|
45769
|
-
cylinders: 6,
|
|
45770
|
-
idleRpm: 650,
|
|
45771
|
-
redlineRpm: 2600,
|
|
45772
|
-
rpmPerMps: [420, 260, 170, 120, 90, 72],
|
|
45773
|
-
layers: layers("truck", [[160, 380], [300, 800], [600, 1500]], [0.13, 0.08, 0.035]),
|
|
45774
|
-
load: { sound: "engine_truck_load", gain: 0.06, cutoff: [250, 900] },
|
|
45775
|
-
closedThrottle: 0.6
|
|
45776
|
-
};
|
|
45777
|
-
var BIKE_ENGINE = {
|
|
45778
|
-
id: "bike",
|
|
45779
|
-
cylinders: 4,
|
|
45780
|
-
idleRpm: 1300,
|
|
45781
|
-
redlineRpm: 12e3,
|
|
45782
|
-
rpmPerMps: [900, 640, 500, 410, 350, 310],
|
|
45783
|
-
layers: layers("bike", [[350, 900], [700, 2200], [1500, 4200]], [0.08, 0.07, 0.05]),
|
|
45784
|
-
load: { sound: "engine_bike_load", gain: 0.045, cutoff: [600, 2600] },
|
|
45785
|
-
closedThrottle: 0.5
|
|
45786
|
-
};
|
|
45787
|
-
var ENGINE_PROFILES = { car: CAR_ENGINE, truck: TRUCK_ENGINE, bike: BIKE_ENGINE };
|
|
45788
|
-
|
|
45789
46377
|
// src/audio/vehicle-sound.ts
|
|
45790
46378
|
var clamp012 = (v) => v < 0 ? 0 : v > 1 ? 1 : v;
|
|
45791
46379
|
function createVehicleSound(audio, options = {}) {
|
|
@@ -45794,8 +46382,10 @@ var GameVehiclesThree = (() => {
|
|
|
45794
46382
|
const crankSeconds = options.crankSeconds ?? 0.75;
|
|
45795
46383
|
const gears = createGearGuess(profile);
|
|
45796
46384
|
const loops = /* @__PURE__ */ new Map();
|
|
46385
|
+
const budget = options.budget;
|
|
46386
|
+
const self = {};
|
|
45797
46387
|
const levels = {};
|
|
45798
|
-
const state = { running: false, cranking: 0, catches: false, flare: 0, rpm: 0 };
|
|
46388
|
+
const state = { running: false, cranking: 0, catches: false, flare: 0, rpm: 0, sirenPhase: 0 };
|
|
45799
46389
|
const loopOf = (sound) => {
|
|
45800
46390
|
let handle = loops.get(sound);
|
|
45801
46391
|
if (!handle && audio?.loop) {
|
|
@@ -45829,6 +46419,11 @@ var GameVehiclesThree = (() => {
|
|
|
45829
46419
|
play(kind === "heavy" ? keys.crashHeavy : kind === "medium" ? keys.crashMedium : keys.crashLight, position, Math.min(1, 0.35 + v / 20));
|
|
45830
46420
|
return kind;
|
|
45831
46421
|
},
|
|
46422
|
+
hit(speed, position, sound) {
|
|
46423
|
+
const v = Math.abs(speed);
|
|
46424
|
+
if (v < 0.5) return;
|
|
46425
|
+
play(sound ?? keys.hitBody, position, Math.min(1, 0.3 + v / 15));
|
|
46426
|
+
},
|
|
45832
46427
|
update(frame) {
|
|
45833
46428
|
if (state.cranking > 0) {
|
|
45834
46429
|
state.cranking -= frame.dt;
|
|
@@ -45842,20 +46437,33 @@ var GameVehiclesThree = (() => {
|
|
|
45842
46437
|
const driven = frame.rpm ?? gears.rpm(frame.speed, throttle);
|
|
45843
46438
|
const rpm = state.running ? Math.max(driven, profile.idleRpm * (1 + 1.2 * state.flare * state.flare)) : 0;
|
|
45844
46439
|
state.rpm = rpm;
|
|
45845
|
-
|
|
45846
|
-
|
|
46440
|
+
const heard = budget ? budget.admit(self, frame.position) ? 1 : 0 : 1;
|
|
46441
|
+
for (const layer2 of engineMix(profile, { rpm, throttle: Math.max(throttle, state.flare * 0.6) })) {
|
|
46442
|
+
setLoop(layer2.sound, heard * layer2.volume, frame.position, { ...layer2.frequency === void 0 ? {} : { frequency: layer2.frequency }, cutoff: layer2.cutoff });
|
|
45847
46443
|
}
|
|
45848
46444
|
const speed = Math.abs(frame.speed);
|
|
45849
46445
|
const slide = clamp012(((frame.slip ?? 0) - 0.15) / 0.5) * clamp012(speed / 4);
|
|
45850
46446
|
const dirt = frame.surface === "dirt";
|
|
45851
|
-
setLoop(keys.skidAsphalt, dirt ? 0 : 0.16 * slide, frame.position, { cutoff: 1700 + 600 * slide });
|
|
45852
|
-
setLoop(keys.skidDirt, dirt ? 0.2 * slide : 0, frame.position, { cutoff: 500 + 500 * slide });
|
|
45853
|
-
setLoop(keys.roll, 0.06 * clamp012(speed / 25), frame.position, { cutoff: 250 + 45 * Math.min(speed, 40) });
|
|
46447
|
+
setLoop(keys.skidAsphalt, heard * (dirt ? 0 : 0.16 * slide), frame.position, { cutoff: 1700 + 600 * slide });
|
|
46448
|
+
setLoop(keys.skidDirt, heard * (dirt ? 0.2 * slide : 0), frame.position, { cutoff: 500 + 500 * slide });
|
|
46449
|
+
setLoop(keys.roll, heard * 0.06 * clamp012(speed / 25), frame.position, { cutoff: 250 + 45 * Math.min(speed, 40) });
|
|
46450
|
+
const squeal = clamp012(((frame.brake ?? 0) - 0.3) / 0.4) * clamp012(speed / 0.8) * clamp012((5 - speed) / 2) * (slide > 0 ? 0 : 1);
|
|
46451
|
+
setLoop(keys.brakeSqueal, heard * 0.05 * squeal, frame.position, { cutoff: 3200 + 400 * squeal });
|
|
46452
|
+
const siren = frame.siren ?? "off";
|
|
46453
|
+
if (siren !== "off" || loops.has(keys.siren)) {
|
|
46454
|
+
const period = siren === "yelp" ? 0.25 : 4;
|
|
46455
|
+
state.sirenPhase = (state.sirenPhase + frame.dt / period) % 1;
|
|
46456
|
+
const tri = state.sirenPhase < 0.5 ? state.sirenPhase * 2 : 2 - state.sirenPhase * 2;
|
|
46457
|
+
setLoop(keys.siren, heard * (siren === "off" ? 0 : 0.07), frame.position, { frequency: 650 + 850 * tri, cutoff: 2600 });
|
|
46458
|
+
}
|
|
46459
|
+
const rotor = clamp012(frame.rotor ?? 0);
|
|
46460
|
+
setLoop(keys.rotor, heard * 0.12 * rotor, frame.position, { cutoff: 180 + 220 * rotor });
|
|
45854
46461
|
},
|
|
45855
46462
|
get reading() {
|
|
45856
46463
|
return { running: state.running, rpm: state.rpm, levels: { ...levels } };
|
|
45857
46464
|
},
|
|
45858
46465
|
dispose() {
|
|
46466
|
+
budget?.release(self);
|
|
45859
46467
|
for (const handle of loops.values()) handle.stop();
|
|
45860
46468
|
loops.clear();
|
|
45861
46469
|
}
|
|
@@ -46245,7 +46853,15 @@ var GameVehiclesThree = (() => {
|
|
|
46245
46853
|
var clamp22 = (x, a, b) => Math.max(a, Math.min(b, x));
|
|
46246
46854
|
var MAX_SUBSTEP = 1 / 240;
|
|
46247
46855
|
var FLAT_BELOW = 0.2;
|
|
46856
|
+
var RIM_RADIUS_SHARE = 0.7;
|
|
46857
|
+
var RIM_FRICTION = 0.4;
|
|
46858
|
+
var RIM_ROLLING = 0.25;
|
|
46859
|
+
var FLAT_SAG = 0.05;
|
|
46860
|
+
var FLAT_ROLLING = 6;
|
|
46248
46861
|
var STALL_HEALTH = 0.3;
|
|
46862
|
+
var CLUTCH_BITE = 0.7;
|
|
46863
|
+
var STALL_RPM = 0.5;
|
|
46864
|
+
var STALL_GAS = 0.35;
|
|
46249
46865
|
var defaultSemiSpec = {
|
|
46250
46866
|
mass: 1300,
|
|
46251
46867
|
centreHeight: 0.5,
|
|
@@ -46386,7 +47002,14 @@ var GameVehiclesThree = (() => {
|
|
|
46386
47002
|
const accelInput = reversing ? input.brake : input.throttle;
|
|
46387
47003
|
const brakeInput = clamp22(reversing ? input.throttle : input.brake, 0, 1);
|
|
46388
47004
|
const ratio = ratioOf(state.gear) * spec.finalDrive;
|
|
46389
|
-
state.
|
|
47005
|
+
const engaged = input.clutch == null || state.gear === 0 ? 1 : 1 - clamp22(input.clutch, 0, 1);
|
|
47006
|
+
const coupled = wheelRpm * ratio;
|
|
47007
|
+
const free = spec.engine.idleRpm + clamp22(accelInput, 0, 1) * (spec.engine.redlineRpm * 0.7 - spec.engine.idleRpm);
|
|
47008
|
+
state.rpm = clamp22(coupled * engaged + Math.max(coupled, free) * (1 - engaged), spec.engine.idleRpm, spec.engine.redlineRpm + 200);
|
|
47009
|
+
if (input.clutch != null && state.gear !== 0 && state.engineOn && engaged > CLUTCH_BITE && coupled < spec.engine.idleRpm * STALL_RPM && accelInput < STALL_GAS) {
|
|
47010
|
+
state.engineOn = false;
|
|
47011
|
+
events.push({ type: "stall" });
|
|
47012
|
+
}
|
|
46390
47013
|
if (!state.engineOn || state.fuel <= 0) state.rpm = 0;
|
|
46391
47014
|
let throttle = clamp22(accelInput, 0, 1);
|
|
46392
47015
|
if (engineHealth < STALL_HEALTH && throttle > 0.8) {
|
|
@@ -46397,12 +47020,13 @@ var GameVehiclesThree = (() => {
|
|
|
46397
47020
|
}
|
|
46398
47021
|
throttle *= 0.5;
|
|
46399
47022
|
} else stallWatch.throttleTime = 0;
|
|
46400
|
-
|
|
47023
|
+
const starting = input.start ?? (accelInput > 0 && Math.abs(state.u) < 0.5);
|
|
47024
|
+
if (!state.engineOn && starting && engineHealth >= STALL_HEALTH && state.fuel > 0) state.engineOn = true;
|
|
46401
47025
|
if (state.fuel <= 0 && state.engineOn) {
|
|
46402
47026
|
state.engineOn = false;
|
|
46403
47027
|
events.push({ type: "out_of_fuel" });
|
|
46404
47028
|
}
|
|
46405
|
-
const engineTorque = state.engineOn ? torqueAt(spec, state.rpm) * throttle * (0.55 + 0.45 * engineHealth) : 0;
|
|
47029
|
+
const engineTorque = state.engineOn ? torqueAt(spec, state.rpm) * throttle * (0.55 + 0.45 * engineHealth) * clamp22(input.powerLimit ?? 1, 0, 1) * engaged : 0;
|
|
46406
47030
|
const driveForceTotal = state.gear === 0 ? 0 : (reversing ? -1 : 1) * engineTorque * ratio * spec.efficiency / spec.wheelRadius;
|
|
46407
47031
|
if (state.engineOn) {
|
|
46408
47032
|
const burned = fuelRate(fuelModel, state.rpm / spec.engine.redlineRpm, throttle, cargo / baseMass, engineHealth) * dt;
|
|
@@ -46420,19 +47044,21 @@ var GameVehiclesThree = (() => {
|
|
|
46420
47044
|
const wz = state.z - w.x * sn + w.z * cs;
|
|
46421
47045
|
const ground = world.ground ? world.ground(wx, wz) : {};
|
|
46422
47046
|
const surface = surfaces.get(contamination && contamination.left > 0 && surfaces.get(contamination.id).grip < surfaces.get(ground.surface ?? "dry_asphalt").grip ? contamination.id : ground.surface ?? "dry_asphalt");
|
|
47047
|
+
const tyreHealth = cond.tyres ? clamp22(cond.tyres[i] ?? 1, 0, 1) : 1;
|
|
47048
|
+
const rim = !!cond.rims?.[i];
|
|
47049
|
+
const flat = rim || tyreHealth < FLAT_BELOW;
|
|
47050
|
+
const radius = rim ? spec.rimRadius ?? spec.wheelRadius * RIM_RADIUS_SHARE : flat ? spec.wheelRadius - FLAT_SAG : spec.wheelRadius;
|
|
46423
47051
|
const top = state.height + w.x * state.pitch - w.z * state.roll;
|
|
46424
|
-
const length = top - (ground.height ?? 0) -
|
|
47052
|
+
const length = top - (ground.height ?? 0) - radius;
|
|
46425
47053
|
const compression = ride - length;
|
|
46426
47054
|
const rate = -(state.heightRate + w.x * state.pitchRate - w.z * state.rollRate);
|
|
46427
47055
|
const k = spec.suspension.spring * (0.5 + 0.5 * suspensionHealth);
|
|
46428
47056
|
const c = spec.suspension.damper * (0.5 + 0.5 * suspensionHealth);
|
|
46429
47057
|
const load = Math.max(0, k * compression + c * rate);
|
|
46430
|
-
const tyreHealth = cond.tyres ? clamp22(cond.tyres[i] ?? 1, 0, 1) : 1;
|
|
46431
|
-
const flat = tyreHealth < FLAT_BELOW;
|
|
46432
47058
|
const bog = !!surface.bogs && !spec.fourWheelDrive;
|
|
46433
47059
|
if (bog) bogging = true;
|
|
46434
|
-
const grip = surfaceGrip(surface, state.u) * (flat ? 0.5 : 1);
|
|
46435
|
-
wheelState.push({ n: load, grip, surface: surface.id, bog, flat });
|
|
47060
|
+
const grip = surfaceGrip(surface, state.u) * (rim ? RIM_FRICTION / spec.tyre.friction : flat ? 0.5 : 1);
|
|
47061
|
+
wheelState.push({ n: load, grip, surface: surface.id, bog, flat, rim });
|
|
46436
47062
|
sumN += load;
|
|
46437
47063
|
sumNA += load * w.x;
|
|
46438
47064
|
sumNB += load * w.z;
|
|
@@ -46468,7 +47094,7 @@ var GameVehiclesThree = (() => {
|
|
|
46468
47094
|
if (locked || lockedByBrake) fl += moving ? -Math.sign(vl) * capacity * (lockedByBrake ? SLIDING_GRIP : 1) : 0;
|
|
46469
47095
|
else if (brakeShare > 0 && moving) fl += -Math.sign(vl) * brakeShare;
|
|
46470
47096
|
if (brakeShare > 0 && moving) brakeWork += Math.min(brakeShare, capacity) * Math.abs(vl) * dt;
|
|
46471
|
-
const rolling = ws.bog && accelInput > 0 ? spec.bogResistance : spec.rolling * (ws.flat ?
|
|
47097
|
+
const rolling = ws.bog && accelInput > 0 ? spec.bogResistance : ws.rim ? RIM_ROLLING : spec.rolling * (ws.flat ? FLAT_ROLLING : 1);
|
|
46472
47098
|
const alpha = Math.atan2(vc, Math.abs(vl) + 0.5);
|
|
46473
47099
|
let fc = -Math.tanh(spec.tyre.corneringStiffness * alpha) * capacity;
|
|
46474
47100
|
if (locked) fc *= 0.6;
|
|
@@ -46543,6 +47169,21 @@ var GameVehiclesThree = (() => {
|
|
|
46543
47169
|
const brakeForce = base.brakeForce ?? body.mass * 9.81 * (carRatio + (0.6 - carRatio) * heavyShare);
|
|
46544
47170
|
return { ...spec, mass: body.mass, wheels, fourWheelDrive: driveAll, engine, gears, drag, brakeForce, tyre: { ...spec.tyre, friction: 0.8 + 0.03 * stats2.handling } };
|
|
46545
47171
|
}
|
|
47172
|
+
var DRIVE_PROFILES = {
|
|
47173
|
+
eco: { throttle: 0.7, upshift: 0.55, downshift: 0.25 },
|
|
47174
|
+
normal: { throttle: 1, upshift: 0.85, downshift: 0.35 },
|
|
47175
|
+
sport: { throttle: 1, upshift: 0.97, downshift: 0.55 }
|
|
47176
|
+
};
|
|
47177
|
+
var DEFAULT_TRACTION = { slip: 0.97, floor: 0.35 };
|
|
47178
|
+
function tractionLimit(slips, options = DEFAULT_TRACTION) {
|
|
47179
|
+
const worst = Math.max(0, ...slips);
|
|
47180
|
+
if (worst <= options.slip) return 1;
|
|
47181
|
+
return Math.max(options.floor, 1 - (worst - options.slip) / (1 - options.slip));
|
|
47182
|
+
}
|
|
47183
|
+
var DEFAULT_CRUISE = { gain: 0.35, minSpeed: 8.3 };
|
|
47184
|
+
function cruiseThrottle(target, speed, options = DEFAULT_CRUISE) {
|
|
47185
|
+
return Math.max(0, Math.min(1, (target - speed) * options.gain + 0.12));
|
|
47186
|
+
}
|
|
46546
47187
|
var DEFAULT_CONTROL_KEYS = {
|
|
46547
47188
|
throttle: ["KeyW", "ArrowUp"],
|
|
46548
47189
|
brake: ["KeyS", "ArrowDown"],
|
|
@@ -46550,6 +47191,10 @@ var GameVehiclesThree = (() => {
|
|
|
46550
47191
|
right: ["KeyD", "ArrowRight"],
|
|
46551
47192
|
handbrake: ["Space"],
|
|
46552
47193
|
horn: ["KeyH"],
|
|
47194
|
+
clutch: ["KeyC"],
|
|
47195
|
+
flash: ["KeyX"],
|
|
47196
|
+
washer: ["KeyZ"],
|
|
47197
|
+
hotwire: ["KeyI"],
|
|
46553
47198
|
ignition: ["KeyI"],
|
|
46554
47199
|
gearbox: ["KeyM"],
|
|
46555
47200
|
gear_up: ["KeyE"],
|
|
@@ -46563,13 +47208,24 @@ var GameVehiclesThree = (() => {
|
|
|
46563
47208
|
alarm: ["KeyY"],
|
|
46564
47209
|
radio: ["KeyR"],
|
|
46565
47210
|
radio_source: ["KeyT"],
|
|
47211
|
+
radio_track: ["BracketRight"],
|
|
46566
47212
|
exit: ["KeyF"],
|
|
46567
47213
|
indicator_left: ["Comma"],
|
|
46568
47214
|
indicator_right: ["Period"],
|
|
46569
47215
|
hazard: ["KeyB"],
|
|
46570
47216
|
wipers: ["KeyO"],
|
|
46571
|
-
seatbelt: ["KeyJ"]
|
|
47217
|
+
seatbelt: ["KeyJ"],
|
|
47218
|
+
drive_profile: ["Digit7"],
|
|
47219
|
+
traction_control: ["Digit8"],
|
|
47220
|
+
abs: ["Digit9"],
|
|
47221
|
+
cruise: ["Digit0"],
|
|
47222
|
+
climate: ["Minus"],
|
|
47223
|
+
demist: ["Equal"],
|
|
47224
|
+
siren: ["Semicolon"],
|
|
47225
|
+
beacon: ["Quote"],
|
|
47226
|
+
glovebox: ["Slash"]
|
|
46572
47227
|
};
|
|
47228
|
+
var HELD_KEYS = ["throttle", "brake", "left", "right", "handbrake", "horn", "clutch", "flash", "washer", "hotwire"];
|
|
46573
47229
|
function createVehicleControls(options) {
|
|
46574
47230
|
const keys = { ...DEFAULT_CONTROL_KEYS, ...options.keys };
|
|
46575
47231
|
const auto4 = options.autoFourWheel ?? { slip: 0.18, releaseSeconds: 2 };
|
|
@@ -46577,7 +47233,7 @@ var GameVehiclesThree = (() => {
|
|
|
46577
47233
|
const held = /* @__PURE__ */ new Set();
|
|
46578
47234
|
const any = (codes) => codes.some((c) => held.has(c));
|
|
46579
47235
|
const commandOf = /* @__PURE__ */ new Map();
|
|
46580
|
-
for (const [command2, codes] of Object.entries(keys)) if (!
|
|
47236
|
+
for (const [command2, codes] of Object.entries(keys)) if (!HELD_KEYS.includes(command2)) for (const code of codes) commandOf.set(code, command2);
|
|
46581
47237
|
const driving = new Set(Object.values(keys).flat());
|
|
46582
47238
|
const state = {
|
|
46583
47239
|
ignition: !!options.running,
|
|
@@ -46586,18 +47242,38 @@ var GameVehiclesThree = (() => {
|
|
|
46586
47242
|
parkingBrake: false,
|
|
46587
47243
|
driveMode: options.fourWheelDrive ? "auto" : "4x2",
|
|
46588
47244
|
fourWheelEngaged: false,
|
|
46589
|
-
lamps: { mode: "off", fog: false, interior: false },
|
|
47245
|
+
lamps: { mode: "off", fog: false, interior: false, flash: false },
|
|
46590
47246
|
brakeLights: false,
|
|
46591
47247
|
reverseLights: false,
|
|
46592
47248
|
horn: false,
|
|
46593
47249
|
alarm: "off",
|
|
46594
|
-
radio: { on: false, source: "radio" },
|
|
47250
|
+
radio: { on: false, source: "radio", track: 0 },
|
|
46595
47251
|
indicator: "off",
|
|
46596
47252
|
blinkOn: false,
|
|
46597
47253
|
tick: false,
|
|
46598
47254
|
wipers: "off",
|
|
46599
|
-
|
|
46600
|
-
|
|
47255
|
+
washer: false,
|
|
47256
|
+
seatbelt: false,
|
|
47257
|
+
clutch: 0,
|
|
47258
|
+
profile: "normal",
|
|
47259
|
+
tractionControl: true,
|
|
47260
|
+
abs: true,
|
|
47261
|
+
cruise: { on: false, speed: 0 },
|
|
47262
|
+
climate: { on: false, demist: false },
|
|
47263
|
+
cranking: false,
|
|
47264
|
+
hotwire: { progress: 0, done: false },
|
|
47265
|
+
siren: "off",
|
|
47266
|
+
beacon: false,
|
|
47267
|
+
beaconSide: 0,
|
|
47268
|
+
glovebox: false
|
|
47269
|
+
};
|
|
47270
|
+
const hasKey = options.hasKey !== false;
|
|
47271
|
+
const hotwireSeconds = Math.max(0.1, options.hotwireSeconds ?? 8);
|
|
47272
|
+
const beaconHz = options.beaconHz ?? 2.5;
|
|
47273
|
+
let beaconClock = 0;
|
|
47274
|
+
let crankAsked = false;
|
|
47275
|
+
let lastSpeed = 0;
|
|
47276
|
+
let engineRunning = !!options.running;
|
|
46601
47277
|
const blinkHz = options.blinkHz ?? 1.5;
|
|
46602
47278
|
const cancelAt = options.indicatorCancel ?? 0.15;
|
|
46603
47279
|
let blink = 0;
|
|
@@ -46609,15 +47285,21 @@ var GameVehiclesThree = (() => {
|
|
|
46609
47285
|
const emit = (event) => options.onEvent?.(event);
|
|
46610
47286
|
const LAMPS = ["off", "position", "low"];
|
|
46611
47287
|
const MODES = ["4x2", "4x4", "auto"];
|
|
47288
|
+
const WIPERS = ["off", "intermittent", "slow", "fast"];
|
|
47289
|
+
const PROFILES = ["eco", "normal", "sport"];
|
|
47290
|
+
const SIRENS = ["off", "wail", "yelp"];
|
|
46612
47291
|
const command = (c) => {
|
|
46613
47292
|
switch (c) {
|
|
46614
47293
|
case "ignition":
|
|
47294
|
+
if (!hasKey && !state.hotwire.done) return emit({ type: "refused", command: c, reason: "no_key" });
|
|
46615
47295
|
state.ignition = !state.ignition;
|
|
46616
47296
|
if (state.ignition && state.alarm !== "off") state.alarm = "off";
|
|
47297
|
+
if (state.ignition) crankAsked = true;
|
|
47298
|
+
else state.cruise.on = false;
|
|
46617
47299
|
break;
|
|
46618
47300
|
case "gearbox":
|
|
46619
47301
|
state.gearbox = state.gearbox === "automatic" ? "manual" : "automatic";
|
|
46620
|
-
state.gear = Math.max(1, state.gear);
|
|
47302
|
+
state.gear = options.clutchPedal && state.gearbox === "manual" && Math.abs(lastSpeed) < 0.5 ? 0 : Math.max(1, state.gear);
|
|
46621
47303
|
break;
|
|
46622
47304
|
case "gear_up":
|
|
46623
47305
|
case "gear_down":
|
|
@@ -46656,6 +47338,9 @@ var GameVehiclesThree = (() => {
|
|
|
46656
47338
|
case "radio_source":
|
|
46657
47339
|
state.radio.source = state.radio.source === "radio" ? "tape" : "radio";
|
|
46658
47340
|
break;
|
|
47341
|
+
case "radio_track":
|
|
47342
|
+
state.radio.track = (state.radio.track + 1) % Math.max(1, options.radioTracks ?? 3);
|
|
47343
|
+
break;
|
|
46659
47344
|
case "exit":
|
|
46660
47345
|
break;
|
|
46661
47346
|
case "indicator_left":
|
|
@@ -46672,11 +47357,48 @@ var GameVehiclesThree = (() => {
|
|
|
46672
47357
|
blink = 0;
|
|
46673
47358
|
break;
|
|
46674
47359
|
case "wipers":
|
|
46675
|
-
state.wipers = state.wipers
|
|
47360
|
+
state.wipers = WIPERS[(WIPERS.indexOf(state.wipers) + 1) % WIPERS.length];
|
|
47361
|
+
break;
|
|
47362
|
+
case "drive_profile":
|
|
47363
|
+
state.profile = PROFILES[(PROFILES.indexOf(state.profile) + 1) % PROFILES.length];
|
|
47364
|
+
break;
|
|
47365
|
+
case "traction_control":
|
|
47366
|
+
state.tractionControl = !state.tractionControl;
|
|
47367
|
+
break;
|
|
47368
|
+
case "abs":
|
|
47369
|
+
state.abs = !state.abs;
|
|
47370
|
+
break;
|
|
47371
|
+
case "cruise":
|
|
47372
|
+
if (state.cruise.on) state.cruise.on = false;
|
|
47373
|
+
else if (!engineRunning) return emit({ type: "refused", command: c, reason: "ignition_off" });
|
|
47374
|
+
else if (lastSpeed < DEFAULT_CRUISE.minSpeed) return emit({ type: "refused", command: c, reason: "too_slow" });
|
|
47375
|
+
else state.cruise = { on: true, speed: lastSpeed };
|
|
47376
|
+
break;
|
|
47377
|
+
case "climate":
|
|
47378
|
+
state.climate.on = !state.climate.on;
|
|
47379
|
+
if (!state.climate.on) state.climate.demist = false;
|
|
47380
|
+
break;
|
|
47381
|
+
case "demist":
|
|
47382
|
+
state.climate.demist = !state.climate.demist;
|
|
47383
|
+
if (state.climate.demist) state.climate.on = true;
|
|
46676
47384
|
break;
|
|
46677
47385
|
case "seatbelt":
|
|
46678
47386
|
state.seatbelt = !state.seatbelt;
|
|
46679
47387
|
break;
|
|
47388
|
+
case "siren":
|
|
47389
|
+
if (!options.emergency) return emit({ type: "refused", command: c, reason: "no_siren" });
|
|
47390
|
+
state.siren = SIRENS[(SIRENS.indexOf(state.siren) + 1) % SIRENS.length];
|
|
47391
|
+
if (state.siren !== "off") state.beacon = true;
|
|
47392
|
+
break;
|
|
47393
|
+
case "beacon":
|
|
47394
|
+
if (!options.emergency) return emit({ type: "refused", command: c, reason: "no_siren" });
|
|
47395
|
+
state.beacon = !state.beacon;
|
|
47396
|
+
if (!state.beacon) state.siren = "off";
|
|
47397
|
+
beaconClock = 0;
|
|
47398
|
+
break;
|
|
47399
|
+
case "glovebox":
|
|
47400
|
+
state.glovebox = !state.glovebox;
|
|
47401
|
+
break;
|
|
46680
47402
|
}
|
|
46681
47403
|
emit({ type: "command", command: c, state });
|
|
46682
47404
|
};
|
|
@@ -46715,17 +47437,66 @@ var GameVehiclesThree = (() => {
|
|
|
46715
47437
|
else if (turned && way < cancelAt) state.indicator = "off";
|
|
46716
47438
|
}
|
|
46717
47439
|
} else state.blinkOn = false;
|
|
47440
|
+
if (state.beacon) {
|
|
47441
|
+
beaconClock += dt;
|
|
47442
|
+
state.beaconSide = Math.floor(beaconClock * beaconHz) % 2;
|
|
47443
|
+
}
|
|
47444
|
+
if (!hasKey && !state.hotwire.done && !state.ignition && any(keys.hotwire)) {
|
|
47445
|
+
if (state.hotwire.progress === 0) {
|
|
47446
|
+
if (state.alarm === "armed") state.alarm = "ringing";
|
|
47447
|
+
emit({ type: "hotwire", stage: "started" });
|
|
47448
|
+
}
|
|
47449
|
+
state.hotwire.progress = Math.min(1, state.hotwire.progress + dt / hotwireSeconds);
|
|
47450
|
+
if (state.hotwire.progress >= 1) {
|
|
47451
|
+
state.hotwire.done = true;
|
|
47452
|
+
state.ignition = true;
|
|
47453
|
+
crankAsked = true;
|
|
47454
|
+
emit({ type: "hotwire", stage: "joined" });
|
|
47455
|
+
}
|
|
47456
|
+
}
|
|
46718
47457
|
state.horn = any(keys.horn);
|
|
46719
|
-
|
|
47458
|
+
state.lamps.flash = any(keys.flash);
|
|
47459
|
+
state.washer = any(keys.washer);
|
|
47460
|
+
state.clutch = ease(state.clutch, any(keys.clutch) ? 1 : 0, any(keys.clutch) ? 8 : 2.5, dt);
|
|
47461
|
+
const speed = driver?.state.u ?? 0;
|
|
47462
|
+
lastSpeed = speed;
|
|
47463
|
+
if (state.cruise.on && (brake > 0.05 || state.clutch > 0.5 || handbrake)) {
|
|
47464
|
+
state.cruise.on = false;
|
|
47465
|
+
emit({ type: "cruise_cancelled" });
|
|
47466
|
+
}
|
|
47467
|
+
const tune = DRIVE_PROFILES[state.profile];
|
|
47468
|
+
let gasNow = state.ignition ? throttle * tune.throttle : 0;
|
|
47469
|
+
if (state.cruise.on && state.ignition) gasNow = Math.max(gasNow, cruiseThrottle(state.cruise.speed, speed));
|
|
47470
|
+
const gasStart = state.gearbox === "automatic" && state.ignition && !engineRunning && throttle > 0 && Math.abs(speed) < 0.5;
|
|
47471
|
+
state.cranking = false;
|
|
47472
|
+
if (crankAsked || gasStart) {
|
|
47473
|
+
crankAsked = false;
|
|
47474
|
+
if (options.canCrank && !options.canCrank()) emit({ type: "refused", command: "ignition", reason: "battery_flat" });
|
|
47475
|
+
else {
|
|
47476
|
+
state.cranking = true;
|
|
47477
|
+
options.onCrank?.();
|
|
47478
|
+
}
|
|
47479
|
+
}
|
|
47480
|
+
const driven = (driver?.state.slip ?? []).filter((_, i) => driver?.spec.wheels?.[i]?.drive ?? true);
|
|
47481
|
+
const powerLimit = (state.tractionControl ? tractionLimit(driven) : 1) * (options.powerLimit?.() ?? 1);
|
|
46720
47482
|
const reversing = state.gearbox === "manual" ? state.gear < 0 : (driver?.state.gear ?? 1) < 0;
|
|
46721
47483
|
state.reverseLights = reversing;
|
|
46722
|
-
state.brakeLights = handbrake || (reversing ? gasNow > 0.05 &&
|
|
46723
|
-
|
|
46724
|
-
|
|
47484
|
+
state.brakeLights = handbrake || (reversing ? gasNow > 0.05 && speed < -0.3 : brake > 0.05);
|
|
47485
|
+
const common = { steer, handbrake, horn: state.horn, start: state.cranking, powerLimit };
|
|
47486
|
+
if (state.gearbox === "automatic") return { ...common, throttle: gasNow, brake };
|
|
47487
|
+
const pedals = state.gear < 0 ? { throttle: brake, brake: gasNow } : { throttle: gasNow, brake };
|
|
47488
|
+
return { ...common, ...pedals, gear: state.gear, ...options.clutchPedal ? { clutch: state.clutch } : {} };
|
|
46725
47489
|
},
|
|
46726
47490
|
after(driver, dt) {
|
|
46727
|
-
if (driver.state.engineOn && !state.ignition && driver.state.u !== 0) state.ignition = true;
|
|
46728
47491
|
if (!state.ignition && driver.state.engineOn) driver.state.engineOn = false;
|
|
47492
|
+
engineRunning = driver.state.engineOn;
|
|
47493
|
+
if (!engineRunning) state.cruise.on = false;
|
|
47494
|
+
const spec = driver.spec;
|
|
47495
|
+
spec.abs = state.abs;
|
|
47496
|
+
if (spec.upshiftFraction != null) {
|
|
47497
|
+
spec.upshiftFraction = DRIVE_PROFILES[state.profile].upshift;
|
|
47498
|
+
spec.downshiftFraction = DRIVE_PROFILES[state.profile].downshift;
|
|
47499
|
+
}
|
|
46729
47500
|
if (state.driveMode === "auto" && options.fourWheelDrive) {
|
|
46730
47501
|
const slip = Math.max(0, ...driver.state.slip);
|
|
46731
47502
|
if (slip > auto4.slip) {
|
|
@@ -46739,6 +47510,10 @@ var GameVehiclesThree = (() => {
|
|
|
46739
47510
|
held.clear();
|
|
46740
47511
|
throttle = brake = steer = 0;
|
|
46741
47512
|
state.horn = false;
|
|
47513
|
+
state.lamps.flash = false;
|
|
47514
|
+
state.washer = false;
|
|
47515
|
+
state.clutch = 0;
|
|
47516
|
+
state.cruise.on = false;
|
|
46742
47517
|
}
|
|
46743
47518
|
};
|
|
46744
47519
|
}
|
|
@@ -46753,15 +47528,212 @@ var GameVehiclesThree = (() => {
|
|
|
46753
47528
|
best = tyre;
|
|
46754
47529
|
}
|
|
46755
47530
|
}
|
|
46756
|
-
return best
|
|
47531
|
+
return best;
|
|
46757
47532
|
});
|
|
46758
47533
|
return {
|
|
46759
|
-
tyres,
|
|
47534
|
+
tyres: tyres.map((tyre) => tyre?.health ?? 1),
|
|
47535
|
+
rims: tyres.map((tyre) => !!tyre?.rim),
|
|
46760
47536
|
...report.brakes != null ? { brakes: report.brakes } : {},
|
|
46761
47537
|
...report.engine != null ? { engine: report.engine } : {},
|
|
46762
47538
|
...report.suspension != null ? { suspension: report.suspension } : {}
|
|
46763
47539
|
};
|
|
46764
47540
|
}
|
|
47541
|
+
var DEFAULT_LOADS = { position: 20, low: 110, high: 130, fog: 110, interior: 10, radio: 25, wipers: 60, indicators: 42, horn: 60, alarm: 5, brakeLights: 42, climate: 180, siren: 100, beacon: 70 };
|
|
47542
|
+
var clamp3 = (x, a, b) => Math.max(a, Math.min(b, x));
|
|
47543
|
+
function createVehicleSystems(options = {}) {
|
|
47544
|
+
const loads = { ...DEFAULT_LOADS, ...options.loads };
|
|
47545
|
+
const capacity = options.batteryWh ?? 720;
|
|
47546
|
+
const alternator = options.alternatorW ?? { idle: 350, full: 1100 };
|
|
47547
|
+
const crankCharge = options.crankCharge ?? 0.25;
|
|
47548
|
+
const startWh = options.startWh ?? 0.6;
|
|
47549
|
+
const ambient = options.ambientC ?? 25;
|
|
47550
|
+
const thermostat = options.thermostatC ?? 90;
|
|
47551
|
+
const limp = options.limpC ?? 115;
|
|
47552
|
+
const seize = options.seizeC ?? 130;
|
|
47553
|
+
const heat = options.heatPerSecond ?? 0.5;
|
|
47554
|
+
const cooling = options.cooling ?? { stopped: 4e-3, fast: 0.03 };
|
|
47555
|
+
const state = { charge: clamp3(options.charge ?? 1, 0, 1), coolantC: ambient, temperature: 0, overheating: false, seized: false, spares: options.spares ?? 1, netW: 0 };
|
|
47556
|
+
const draw = (c) => {
|
|
47557
|
+
const lamps = c.lamps;
|
|
47558
|
+
let w = lamps.mode === "off" ? 0 : loads.position;
|
|
47559
|
+
if (lamps.mode === "low") w += loads.low;
|
|
47560
|
+
if (lamps.mode === "high") w += loads.low + loads.high;
|
|
47561
|
+
if (lamps.flash) w += loads.high;
|
|
47562
|
+
if (lamps.fog) w += loads.fog;
|
|
47563
|
+
if (lamps.interior) w += loads.interior;
|
|
47564
|
+
if (c.radio.on) w += loads.radio;
|
|
47565
|
+
if (c.wipers !== "off" || c.washer) w += loads.wipers;
|
|
47566
|
+
if (c.indicator !== "off") w += loads.indicators * (c.indicator === "hazard" ? 2 : 1) * 0.5;
|
|
47567
|
+
if (c.horn) w += loads.horn;
|
|
47568
|
+
if (c.alarm !== "off") w += loads.alarm;
|
|
47569
|
+
if (c.brakeLights) w += loads.brakeLights;
|
|
47570
|
+
if (c.climate.on) w += loads.climate;
|
|
47571
|
+
if (c.siren !== "off") w += loads.siren;
|
|
47572
|
+
if (c.beacon) w += loads.beacon;
|
|
47573
|
+
return w;
|
|
47574
|
+
};
|
|
47575
|
+
return {
|
|
47576
|
+
state,
|
|
47577
|
+
canCrank: () => state.charge >= crankCharge && !state.seized,
|
|
47578
|
+
crank() {
|
|
47579
|
+
state.charge = clamp3(state.charge - startWh / capacity, 0, 1);
|
|
47580
|
+
},
|
|
47581
|
+
powerLimit: () => state.coolantC <= limp ? 1 : clamp3(1 - (state.coolantC - limp) / (seize - limp), 0.25, 1),
|
|
47582
|
+
step({ driver, controls, throttle, dt, radiator = 1, coolantC }) {
|
|
47583
|
+
const events = [];
|
|
47584
|
+
const running = driver.state.engineOn;
|
|
47585
|
+
const charging = running ? alternator.idle + (alternator.full - alternator.idle) * clamp3((driver.state.rpm - 900) / 1100, 0, 1) : 0;
|
|
47586
|
+
const net = charging - draw(controls);
|
|
47587
|
+
state.netW = net;
|
|
47588
|
+
const before = state.charge;
|
|
47589
|
+
state.charge = clamp3(state.charge + net * dt / 3600 / capacity, 0, 1);
|
|
47590
|
+
if (before >= crankCharge && state.charge < crankCharge && !running) events.push({ type: "battery_flat" });
|
|
47591
|
+
const work = running ? clamp3(0.15 + 0.85 * throttle * (driver.state.rpm / 6500), 0, 1) : 0;
|
|
47592
|
+
const air = cooling.stopped + (cooling.fast - cooling.stopped) * clamp3(Math.abs(driver.state.u) / 27.8, 0, 1);
|
|
47593
|
+
const cool = air * clamp3(radiator, 0.05, 1) * (running ? 1 + (controls.climate.on ? 0.15 : 0) : 1);
|
|
47594
|
+
const opened = state.coolantC >= thermostat ? 1 : 0.15;
|
|
47595
|
+
state.coolantC += (heat * work - cool * opened * (state.coolantC - ambient)) * dt;
|
|
47596
|
+
state.coolantC = coolantC ?? Math.max(ambient, state.coolantC);
|
|
47597
|
+
state.temperature = clamp3((state.coolantC - ambient) / (seize - ambient), 0, 1);
|
|
47598
|
+
const hot = state.coolantC > limp;
|
|
47599
|
+
if (hot && !state.overheating) events.push({ type: "overheating" });
|
|
47600
|
+
state.overheating = hot;
|
|
47601
|
+
if (state.coolantC >= seize && !state.seized) {
|
|
47602
|
+
state.seized = true;
|
|
47603
|
+
events.push({ type: "seized" });
|
|
47604
|
+
}
|
|
47605
|
+
if (state.seized) driver.state.engineOn = false;
|
|
47606
|
+
return events;
|
|
47607
|
+
},
|
|
47608
|
+
fitSpare(driver, wheel) {
|
|
47609
|
+
if (state.spares <= 0) return { type: "no_spare" };
|
|
47610
|
+
state.spares--;
|
|
47611
|
+
const tyres = [...driver.condition.tyres ?? []];
|
|
47612
|
+
tyres[wheel] = 1;
|
|
47613
|
+
driver.condition = { ...driver.condition, tyres };
|
|
47614
|
+
return { type: "spare_fitted", wheel };
|
|
47615
|
+
},
|
|
47616
|
+
charge(share) {
|
|
47617
|
+
state.charge = clamp3(state.charge + share, 0, 1);
|
|
47618
|
+
}
|
|
47619
|
+
};
|
|
47620
|
+
}
|
|
47621
|
+
var DEFAULT_EJECTION = { frontal: 8.3, side: 6, keep: 0.8, lift: 2.5 };
|
|
47622
|
+
function ejectionOf(pulse, belted, options = DEFAULT_EJECTION) {
|
|
47623
|
+
if (belted) return null;
|
|
47624
|
+
const du = pulse.after.u - pulse.before.u;
|
|
47625
|
+
const dw = pulse.after.w - pulse.before.w;
|
|
47626
|
+
const deltaV = Math.hypot(du, dw);
|
|
47627
|
+
const frontal = Math.abs(du) >= Math.abs(dw);
|
|
47628
|
+
if (frontal && Math.abs(du) < options.frontal && !pulse.rolled) return null;
|
|
47629
|
+
if (!frontal && Math.abs(dw) < options.side && !pulse.rolled) return null;
|
|
47630
|
+
const exit = frontal ? du < 0 ? "windshield" : "rear_window" : dw < 0 ? "right_window" : "left_window";
|
|
47631
|
+
return { exit, velocity: [pulse.before.u * options.keep, pulse.before.w * options.keep, options.lift], deltaV };
|
|
47632
|
+
}
|
|
47633
|
+
var DEFAULT_PARKING_SENSOR = { range: 1.5, solid: 0.3, slowest: 0.8, fastest: 0.12 };
|
|
47634
|
+
function parkingBeepInterval(distance, options = DEFAULT_PARKING_SENSOR) {
|
|
47635
|
+
if (distance > options.range) return null;
|
|
47636
|
+
if (distance <= options.solid) return 0;
|
|
47637
|
+
const t = (distance - options.solid) / (options.range - options.solid);
|
|
47638
|
+
return options.fastest + (options.slowest - options.fastest) * t;
|
|
47639
|
+
}
|
|
47640
|
+
function bumperDistance(params) {
|
|
47641
|
+
const [hx, hz2] = params.heading;
|
|
47642
|
+
const sign2 = params.forward ? 1 : -1;
|
|
47643
|
+
let best = Infinity;
|
|
47644
|
+
for (const [ox, oz] of params.obstacles) {
|
|
47645
|
+
const dx = ox - params.x;
|
|
47646
|
+
const dz = oz - params.z;
|
|
47647
|
+
const along = (dx * hx + dz * hz2) * sign2 - params.length / 2;
|
|
47648
|
+
const side2 = Math.abs(-dx * hz2 + dz * hx);
|
|
47649
|
+
if (along >= 0 && side2 <= params.width / 2 + 0.2) best = Math.min(best, along);
|
|
47650
|
+
}
|
|
47651
|
+
return best;
|
|
47652
|
+
}
|
|
47653
|
+
var GLOVEBOX = { id: "glovebox", slots: 6, capacityKg: 4, access: "cabin" };
|
|
47654
|
+
var trunkFor = (litres = 450) => ({ id: "trunk", slots: Math.max(4, Math.round(litres / 25)), capacityKg: Math.round(litres / 4), access: "lid" });
|
|
47655
|
+
var weightOf = (stack) => stack.unitKg * stack.count;
|
|
47656
|
+
function createVehicleStorage(options = {}) {
|
|
47657
|
+
const compartments = [...options.compartments ?? [GLOVEBOX, trunkFor()]];
|
|
47658
|
+
const slots = new Map(compartments.map((c) => [c.id, Array.from({ length: c.slots }, () => null)]));
|
|
47659
|
+
const specOf = (id) => compartments.find((c) => c.id === id);
|
|
47660
|
+
const load = (id) => (slots.get(id) ?? []).reduce((kg, s) => kg + (s ? weightOf(s) : 0), 0);
|
|
47661
|
+
const reachable2 = (id, access) => {
|
|
47662
|
+
const spec = specOf(id);
|
|
47663
|
+
if (!spec) return false;
|
|
47664
|
+
return spec.access === "lid" ? access.lid >= 0.5 : access.gloveboxOpen && (access.seated || access.frontDoorOpen);
|
|
47665
|
+
};
|
|
47666
|
+
const place = (id, stack) => {
|
|
47667
|
+
const spec = specOf(id);
|
|
47668
|
+
const list2 = slots.get(id);
|
|
47669
|
+
if (!spec || !list2) return "missing";
|
|
47670
|
+
if (load(id) + weightOf(stack) > spec.capacityKg + 1e-9) return "too_heavy";
|
|
47671
|
+
const same = stack.data === void 0 ? list2.findIndex((s) => s !== null && s.itemId === stack.itemId && s.data === void 0) : -1;
|
|
47672
|
+
if (same >= 0) {
|
|
47673
|
+
const s = list2[same];
|
|
47674
|
+
list2[same] = { ...s, count: s.count + stack.count };
|
|
47675
|
+
return "ok";
|
|
47676
|
+
}
|
|
47677
|
+
const free = list2.indexOf(null);
|
|
47678
|
+
if (free < 0) return "full";
|
|
47679
|
+
list2[free] = { ...stack };
|
|
47680
|
+
return "ok";
|
|
47681
|
+
};
|
|
47682
|
+
return {
|
|
47683
|
+
compartments,
|
|
47684
|
+
reachable: reachable2,
|
|
47685
|
+
contents: (id) => [...slots.get(id) ?? []],
|
|
47686
|
+
loadKg: (id) => id === void 0 ? compartments.reduce((kg, c) => kg + load(c.id), 0) : load(id),
|
|
47687
|
+
put(id, stack, access) {
|
|
47688
|
+
if (!specOf(id)) return "missing";
|
|
47689
|
+
if (!reachable2(id, access)) return "shut";
|
|
47690
|
+
return place(id, stack);
|
|
47691
|
+
},
|
|
47692
|
+
take(id, slot, access) {
|
|
47693
|
+
const list2 = slots.get(id);
|
|
47694
|
+
if (!list2 || !reachable2(id, access)) return null;
|
|
47695
|
+
const stack = list2[slot] ?? null;
|
|
47696
|
+
if (stack) list2[slot] = null;
|
|
47697
|
+
return stack;
|
|
47698
|
+
},
|
|
47699
|
+
stock(id, stacks) {
|
|
47700
|
+
return stacks.filter((s) => place(id, s) !== "ok");
|
|
47701
|
+
},
|
|
47702
|
+
clear() {
|
|
47703
|
+
for (const list2 of slots.values()) list2.fill(null);
|
|
47704
|
+
}
|
|
47705
|
+
};
|
|
47706
|
+
}
|
|
47707
|
+
var clamp4 = (x, a, b) => Math.max(a, Math.min(b, x));
|
|
47708
|
+
function createWindshieldFog(options = {}) {
|
|
47709
|
+
const outside = options.outsideHumidity ?? 0.6;
|
|
47710
|
+
const breath = options.breath ?? 4e-3;
|
|
47711
|
+
const wet = options.wet ?? 2e-3;
|
|
47712
|
+
const air = options.air ?? { shut: 2e-3, window: 0.05, climate: 0.01, demist: 0.06 };
|
|
47713
|
+
const coldSpan = options.coldSpan ?? 15;
|
|
47714
|
+
const rates = options.rates ?? { build: 0.05, clear: 0.03, demist: 0.25 };
|
|
47715
|
+
const state = { humidity: outside, fog: 0 };
|
|
47716
|
+
return {
|
|
47717
|
+
state,
|
|
47718
|
+
step({ dt, occupants, outsideC, cabinC, rain = 0, speed = 0, windows = 0, climate, engineWarm = 1 }) {
|
|
47719
|
+
const exchange = air.shut + air.window * clamp4(windows, 0, 1) + (climate.on ? air.climate : 0) + (climate.demist ? air.demist : 0);
|
|
47720
|
+
const source = breath * Math.max(0, occupants) + wet * clamp4(rain, 0, 1) * (occupants > 0 ? 1 : 0);
|
|
47721
|
+
const towards = climate.on ? outside * 0.4 : outside;
|
|
47722
|
+
state.humidity = clamp4(state.humidity + (source - exchange * (state.humidity - towards)) * dt, 0, 1);
|
|
47723
|
+
const cold = Math.max(0, cabinC - outsideC) * (1 - 0.7 * clamp4(windows, 0, 1)) + 6 * clamp4(rain, 0, 1) + 2 * clamp4(speed / 27.8, 0, 1);
|
|
47724
|
+
const warmed = climate.demist ? cold * (1 - 0.9 * clamp4(engineWarm, 0, 1)) : cold;
|
|
47725
|
+
const clearUpTo = 1 - 0.5 * clamp4(warmed / coldSpan, 0, 1);
|
|
47726
|
+
const target = clamp4((state.humidity - clearUpTo) * 6, 0, 1);
|
|
47727
|
+
const down = climate.demist ? rates.demist * (0.3 + 0.7 * clamp4(engineWarm, 0, 1)) : rates.clear;
|
|
47728
|
+
state.fog = target > state.fog ? Math.min(target, state.fog + rates.build * dt) : Math.max(target, state.fog - down * dt);
|
|
47729
|
+
return state;
|
|
47730
|
+
},
|
|
47731
|
+
set(next) {
|
|
47732
|
+
if (next.humidity !== void 0) state.humidity = clamp4(next.humidity, 0, 1);
|
|
47733
|
+
if (next.fog !== void 0) state.fog = clamp4(next.fog, 0, 1);
|
|
47734
|
+
}
|
|
47735
|
+
};
|
|
47736
|
+
}
|
|
46765
47737
|
|
|
46766
47738
|
// src/vehicle-lod.ts
|
|
46767
47739
|
var VEHICLE_LOD_DISTANCE = 14;
|
|
@@ -46784,7 +47756,8 @@ var GameVehiclesThree = (() => {
|
|
|
46784
47756
|
culled.clear();
|
|
46785
47757
|
modelKey = keyOf();
|
|
46786
47758
|
isUploaded = false;
|
|
46787
|
-
full.traverse((
|
|
47759
|
+
full.traverse((node) => {
|
|
47760
|
+
const object2 = node;
|
|
46788
47761
|
if (!object2.isMesh || culled.has(object2)) return;
|
|
46789
47762
|
culled.set(object2, object2.frustumCulled);
|
|
46790
47763
|
object2.frustumCulled = false;
|
|
@@ -46811,7 +47784,8 @@ var GameVehiclesThree = (() => {
|
|
|
46811
47784
|
const shadowProxyOf = (fused) => {
|
|
46812
47785
|
const positions = [];
|
|
46813
47786
|
const indices = [];
|
|
46814
|
-
for (const
|
|
47787
|
+
for (const child of fused.children) {
|
|
47788
|
+
const mesh2 = child;
|
|
46815
47789
|
if (!mesh2.isMesh || !mesh2.castShadow) continue;
|
|
46816
47790
|
const geometry2 = mesh2.geometry.clone().applyMatrix4(mesh2.matrix);
|
|
46817
47791
|
const offset = positions.length / 3;
|
|
@@ -46850,7 +47824,8 @@ var GameVehiclesThree = (() => {
|
|
|
46850
47824
|
lite.visible = isFused;
|
|
46851
47825
|
shadow ?? (shadow = shadowProxyOf(lite));
|
|
46852
47826
|
shadow.visible = !isFused;
|
|
46853
|
-
full.traverse((
|
|
47827
|
+
full.traverse((node) => {
|
|
47828
|
+
const object2 = node;
|
|
46854
47829
|
if (!object2.isMesh || !object2.castShadow) return;
|
|
46855
47830
|
castsShadow.add(object2);
|
|
46856
47831
|
object2.castShadow = false;
|
|
@@ -46872,7 +47847,8 @@ var GameVehiclesThree = (() => {
|
|
|
46872
47847
|
root.updateMatrixWorld(true);
|
|
46873
47848
|
const inverse = new THREE.Matrix4().copy(root.matrixWorld).invert();
|
|
46874
47849
|
const textured = [];
|
|
46875
|
-
full.traverse((
|
|
47850
|
+
full.traverse((node) => {
|
|
47851
|
+
const object2 = node;
|
|
46876
47852
|
if (!object2.isMesh || object2.userData.skipLite || !isShown2(object2, full)) return;
|
|
46877
47853
|
const materials = Array.isArray(object2.material) ? object2.material : [object2.material];
|
|
46878
47854
|
if (materials.some((material) => material?.map && !/plate/i.test(material.name ?? "")) && !/plate/i.test(object2.name ?? "")) textured.push(object2);
|
|
@@ -47402,6 +48378,7 @@ var GameVehiclesThree = (() => {
|
|
|
47402
48378
|
var itemId = (key) => ITEM_OF[key] ?? key;
|
|
47403
48379
|
var LANE = { z: 11, from: -12, wall: 13 };
|
|
47404
48380
|
var SPARK_EVERY_S = 0.08;
|
|
48381
|
+
var TYRE_DAMAGE = /* @__PURE__ */ new Set(["flat_tyre", "torn_tyre", "run_flat"]);
|
|
47405
48382
|
var LEAF_REST_RADIANS = 0.02;
|
|
47406
48383
|
var MATERIAL_COLOURS = { metal: 13421772, glass: 4500223, rubber: 16750848, fuel: 16724736 };
|
|
47407
48384
|
var LANE_START_S = 1.2;
|
|
@@ -47697,7 +48674,8 @@ var GameVehiclesThree = (() => {
|
|
|
47697
48674
|
state.time += dt;
|
|
47698
48675
|
const braking = settings.damage !== "into_wall" && gap() < brakeAt() && state.time > 0.5;
|
|
47699
48676
|
const moving = state.time > LANE_START_S;
|
|
47700
|
-
const
|
|
48677
|
+
const straight = settings.damage === "into_wall" || TYRE_DAMAGE.has(settings.damage) || !moving;
|
|
48678
|
+
const input = { ...idle2, throttle: braking || !moving ? 0 : 1, brake: braking ? 1 : 0, steer: straight ? 0 : Math.sin(state.time * 1.4) * 0.15 };
|
|
47701
48679
|
if (mode === "arcade") {
|
|
47702
48680
|
const { events } = arcade.step(input, dt, { blocked: (x, z, yaw) => vehicleCorners(arcade.spec, x, z, yaw).some(([px]) => px >= LANE.wall) });
|
|
47703
48681
|
for (const e of events) {
|
|
@@ -47735,7 +48713,8 @@ var GameVehiclesThree = (() => {
|
|
|
47735
48713
|
speed,
|
|
47736
48714
|
throttle: input.throttle,
|
|
47737
48715
|
...semiState ? { rpm: semiState.rpm, slip: Math.max(0, ...semiState.slip.map(Math.abs)) } : { slip: braking && speed > 3 ? 0.6 : 0 },
|
|
47738
|
-
surface: /dirt|gravel|sand|grass|mud/.test(settings.surface) ? "dirt" : "asphalt"
|
|
48716
|
+
surface: /dirt|gravel|sand|grass|mud/.test(settings.surface) ? "dirt" : "asphalt",
|
|
48717
|
+
brake: input.brake
|
|
47739
48718
|
});
|
|
47740
48719
|
}
|
|
47741
48720
|
state.exhaust -= dt;
|
|
@@ -47911,6 +48890,7 @@ var GameVehiclesThree = (() => {
|
|
|
47911
48890
|
if (isRenderPools(lent.pools)) lent.pools.materials.register("vehicles.cracked-glass", () => crackedGlassMaterial(three, new three.DataTexture(new Uint8Array(4), 1, 1)));
|
|
47912
48891
|
lent.audio?.register?.(LIBRARY_BANK);
|
|
47913
48892
|
lent.audio?.register?.(VEHICLE_SOUND_BANK);
|
|
48893
|
+
lent.audio?.preload?.(VEHICLE_PRELOAD_SOUNDS);
|
|
47914
48894
|
return () => {
|
|
47915
48895
|
stopChange?.();
|
|
47916
48896
|
stopFrame();
|
|
@@ -48348,6 +49328,127 @@ var GameVehiclesThree = (() => {
|
|
|
48348
49328
|
return { ...certificate, results, status: statusOf(results) };
|
|
48349
49329
|
}
|
|
48350
49330
|
|
|
49331
|
+
// src/body.ts
|
|
49332
|
+
var OPEN_SOUND = "car_door_open";
|
|
49333
|
+
var SHUT_SOUND = { door: "car_door_close", hood: "car_hood_close", lid: "car_trunk_close" };
|
|
49334
|
+
var clamp5 = (x, a, b) => Math.max(a, Math.min(b, x));
|
|
49335
|
+
function createVehicleBody(built2, options) {
|
|
49336
|
+
const swing = options.swingSeconds ?? 1.2;
|
|
49337
|
+
const windowSeconds = options.windowSeconds ?? 3.5;
|
|
49338
|
+
const travel = options.windowTravel ?? 0.92;
|
|
49339
|
+
const root = built2.context?.vehicle ?? built2.group;
|
|
49340
|
+
const poses = /* @__PURE__ */ new Map();
|
|
49341
|
+
for (const clip of options.clips) {
|
|
49342
|
+
if (!clip.id.startsWith("open_")) continue;
|
|
49343
|
+
const last = clip.keys[clip.keys.length - 1];
|
|
49344
|
+
for (const [id, pose] of Object.entries(last?.parts ?? {})) if (pose.rotation) poses.set(id, pose.rotation);
|
|
49345
|
+
}
|
|
49346
|
+
const hinges = /* @__PURE__ */ new Map();
|
|
49347
|
+
for (const [id, open] of poses) {
|
|
49348
|
+
const pivot = root.getObjectByName(id);
|
|
49349
|
+
if (pivot) hinges.set(id, { pivot, open, now: 0, target: 0 });
|
|
49350
|
+
}
|
|
49351
|
+
const kind = (part) => part.startsWith("door") ? "door" : part === "hood" ? "hood" : "lid";
|
|
49352
|
+
const panes = /* @__PURE__ */ new Map();
|
|
49353
|
+
for (const glass of built2.context?.glass ?? []) {
|
|
49354
|
+
const g = glass.userData.glass;
|
|
49355
|
+
if (!g || g.key !== "window_front" && g.key !== "window_rear") continue;
|
|
49356
|
+
const id = `${g.key === "window_front" ? "front" : "rear"}_${(g.side ?? 1) < 0 ? "left" : "right"}`;
|
|
49357
|
+
if (panes.has(id) || !glass.geometry) continue;
|
|
49358
|
+
glass.geometry.computeBoundingBox();
|
|
49359
|
+
const box2 = glass.geometry.boundingBox;
|
|
49360
|
+
if (box2) panes.set(id, { pane: glass, drop: (box2.max.y - box2.min.y) * travel, now: 0, target: 0, applied: 0 });
|
|
49361
|
+
}
|
|
49362
|
+
const sunroofs = [];
|
|
49363
|
+
const wipers = [];
|
|
49364
|
+
const T = options.THREE;
|
|
49365
|
+
const turn = new T.Quaternion();
|
|
49366
|
+
root.traverse((o) => {
|
|
49367
|
+
const sun = o.userData.sunroof;
|
|
49368
|
+
if (sun) sunroofs.push({ obj: o, slide: sun.slide, base: o.position.x });
|
|
49369
|
+
});
|
|
49370
|
+
for (const { part, tag } of built2.context?.wipers ?? [])
|
|
49371
|
+
wipers.push({ obj: part, arm: tag.arm, sweep: tag.sweep, spindle: new T.Vector3(...tag.spindle), axis: new T.Vector3(...tag.axis), rest: part.position.clone(), restQ: part.quaternion.clone() });
|
|
49372
|
+
let sunNow = 0;
|
|
49373
|
+
let sunTarget = 0;
|
|
49374
|
+
let wipePhase = 0;
|
|
49375
|
+
let locked = false;
|
|
49376
|
+
const placeWiper = (w, angle) => {
|
|
49377
|
+
if (angle === 0) {
|
|
49378
|
+
w.obj.position.copy(w.rest);
|
|
49379
|
+
w.obj.quaternion.copy(w.restQ);
|
|
49380
|
+
return;
|
|
49381
|
+
}
|
|
49382
|
+
turn.setFromAxisAngle(w.axis, angle);
|
|
49383
|
+
w.obj.position.copy(w.rest).sub(w.spindle).applyQuaternion(turn).add(w.spindle);
|
|
49384
|
+
w.obj.quaternion.copy(turn).multiply(w.restQ);
|
|
49385
|
+
};
|
|
49386
|
+
const ease = (now, target, seconds, dt) => now + clamp5(target - now, -dt / seconds, dt / seconds);
|
|
49387
|
+
return {
|
|
49388
|
+
parts: [...hinges.keys()],
|
|
49389
|
+
windows: [...panes.keys()],
|
|
49390
|
+
hasSunroof: sunroofs.length > 0,
|
|
49391
|
+
wipers: new Set(wipers.map((w) => w.arm)).size,
|
|
49392
|
+
get locked() {
|
|
49393
|
+
return locked;
|
|
49394
|
+
},
|
|
49395
|
+
openness: (part) => hinges.get(part)?.now ?? 0,
|
|
49396
|
+
toggle(part) {
|
|
49397
|
+
const h = hinges.get(part);
|
|
49398
|
+
if (!h) return [{ type: "refused", part, reason: "missing" }];
|
|
49399
|
+
if (locked && kind(part) !== "hood" && h.target === 0) return [{ type: "refused", part, reason: "locked" }];
|
|
49400
|
+
h.target = h.target > 0 ? 0 : 1;
|
|
49401
|
+
return h.target > 0 ? [{ type: "sound", key: OPEN_SOUND, part }] : [];
|
|
49402
|
+
},
|
|
49403
|
+
window: (id) => panes.get(id)?.now ?? 0,
|
|
49404
|
+
toggleWindow(id) {
|
|
49405
|
+
const w = panes.get(id);
|
|
49406
|
+
if (w) w.target = w.target > 0.5 ? 0 : 1;
|
|
49407
|
+
},
|
|
49408
|
+
setWindow(id, open) {
|
|
49409
|
+
const w = panes.get(id);
|
|
49410
|
+
if (w) w.target = clamp5(open, 0, 1);
|
|
49411
|
+
},
|
|
49412
|
+
toggleSunroof() {
|
|
49413
|
+
sunTarget = sunTarget > 0.5 ? 0 : 1;
|
|
49414
|
+
},
|
|
49415
|
+
lock(on) {
|
|
49416
|
+
locked = on;
|
|
49417
|
+
return [{ type: "sound", key: "blinker_tick", part: "doors" }];
|
|
49418
|
+
},
|
|
49419
|
+
update(dt, wipe = 0) {
|
|
49420
|
+
const events = [];
|
|
49421
|
+
for (const [id, h] of hinges) {
|
|
49422
|
+
if (h.now === h.target) continue;
|
|
49423
|
+
h.now = ease(h.now, h.target, swing, dt);
|
|
49424
|
+
h.pivot.rotation.set(h.open[0] * h.now, h.open[1] * h.now, h.open[2] * h.now);
|
|
49425
|
+
if (h.now === 0) events.push({ type: "sound", key: SHUT_SOUND[kind(id)] ?? "car_door_close", part: id });
|
|
49426
|
+
}
|
|
49427
|
+
for (const w of panes.values()) {
|
|
49428
|
+
if (w.now === w.target) continue;
|
|
49429
|
+
w.now = ease(w.now, w.target, windowSeconds, dt);
|
|
49430
|
+
const offset = -w.drop * w.now;
|
|
49431
|
+
w.pane.position.y += offset - w.applied;
|
|
49432
|
+
w.applied = offset;
|
|
49433
|
+
}
|
|
49434
|
+
if (sunNow !== sunTarget) {
|
|
49435
|
+
sunNow = ease(sunNow, sunTarget, 2.5, dt);
|
|
49436
|
+
for (const s of sunroofs) s.obj.position.x = s.base - s.slide * sunNow;
|
|
49437
|
+
}
|
|
49438
|
+
wipePhase = wipe > 0 ? (wipePhase + dt * wipe) % 1 : wipePhase > 0 ? Math.min(1, wipePhase + dt * 1.5) % 1 : 0;
|
|
49439
|
+
const sweep = Math.sin(Math.PI * wipePhase);
|
|
49440
|
+
for (const w of wipers) placeWiper(w, w.sweep * sweep);
|
|
49441
|
+
return events;
|
|
49442
|
+
},
|
|
49443
|
+
dispose() {
|
|
49444
|
+
for (const h of hinges.values()) h.pivot.rotation.set(0, 0, 0);
|
|
49445
|
+
for (const w of panes.values()) w.pane.position.y -= w.applied;
|
|
49446
|
+
for (const s of sunroofs) s.obj.position.x = s.base;
|
|
49447
|
+
for (const w of wipers) placeWiper(w, 0);
|
|
49448
|
+
}
|
|
49449
|
+
};
|
|
49450
|
+
}
|
|
49451
|
+
|
|
48351
49452
|
// src/dashboard.ts
|
|
48352
49453
|
var DASHBOARD_LOOK = {
|
|
48353
49454
|
face: "#0b1110",
|
|
@@ -48522,6 +49623,8 @@ var GameVehiclesThree = (() => {
|
|
|
48522
49623
|
lamp(g, 104, 214, r.highBeam, DASHBOARD_LOOK.blue, beam);
|
|
48523
49624
|
lamp(g, 152, 214, r.lowBeam || r.fog, r.fog ? DASHBOARD_LOOK.amber : DASHBOARD_LOOK.green, beam);
|
|
48524
49625
|
bar(g, 40, r.fuel, false, "F");
|
|
49626
|
+
lamp(g, 104, 244, !!r.cruise, DASHBOARD_LOOK.green, letter("CRZ"));
|
|
49627
|
+
if (r.profile && r.profile !== "normal") lamp(g, 152, 244, true, r.profile === "eco" ? DASHBOARD_LOOK.green : DASHBOARD_LOOK.amber, letter(r.profile === "eco" ? "E" : "S"));
|
|
48525
49628
|
} else {
|
|
48526
49629
|
dial(g, r.rpm / 1e3, Math.ceil(redline / 1e3) + 1, 1, redline / 1e3, (v) => String(Math.round(v)));
|
|
48527
49630
|
g.fillStyle = DASHBOARD_LOOK.marks;
|
|
@@ -48530,7 +49633,9 @@ var GameVehiclesThree = (() => {
|
|
|
48530
49633
|
g.fillText(r.gear < 0 ? "R" : r.gear === 0 ? "N" : String(r.gear), SIZE / 2, SIZE / 2 + 54);
|
|
48531
49634
|
lamp(g, 86, 178, r.parkingBrake, DASHBOARD_LOOK.red, ring2("P"));
|
|
48532
49635
|
lamp(g, 128, 214, r.ignition && !r.seatbelt, DASHBOARD_LOOK.red, belt);
|
|
48533
|
-
lamp(g, 170, 178, warn, DASHBOARD_LOOK.red, letter("+\u2212"));
|
|
49636
|
+
lamp(g, 170, 178, warn || r.engineOn && r.charging === false, DASHBOARD_LOOK.red, letter("+\u2212"));
|
|
49637
|
+
lamp(g, 104, 244, r.ignition && !!r.tractionOff, DASHBOARD_LOOK.amber, letter("TC"));
|
|
49638
|
+
lamp(g, 152, 244, r.ignition && !!r.absOff, DASHBOARD_LOOK.amber, letter("ABS"));
|
|
48534
49639
|
lamp(g, 86, 214, warn, DASHBOARD_LOOK.red, letter("OIL"));
|
|
48535
49640
|
lamp(g, 170, 214, r.fourWheel, DASHBOARD_LOOK.green, letter("4x4"));
|
|
48536
49641
|
bar(g, SIZE - 40, r.temperature, true, "T");
|
|
@@ -48566,7 +49671,7 @@ var GameVehiclesThree = (() => {
|
|
|
48566
49671
|
|
|
48567
49672
|
// src/lamps.ts
|
|
48568
49673
|
var LAMP_RULES = {
|
|
48569
|
-
glow: { head: { off: 0.04, position: 0.3, low: 1, high: 1.35 }, tail: { off: 0.15, on: 0.7, brake: 1.6 }, fog: { off: 0.04, on: 1.1 }, amber: { off: 0.1, on: 2.2 } },
|
|
49674
|
+
glow: { head: { off: 0.04, position: 0.3, low: 1, high: 1.35 }, tail: { off: 0.15, on: 0.7, brake: 1.6 }, fog: { off: 0.04, on: 1.1 }, amber: { off: 0.1, on: 2.2 }, beacon: { off: 0.35, dark: 0.12, lit: 2.8 } },
|
|
48570
49675
|
low: { color: 16773584, intensity: 2.4, distance: 32, angle: 0.42, penumbra: 0.55, decay: 1.6, drop: 0.09 },
|
|
48571
49676
|
high: { color: 16774882, intensity: 3.6, distance: 70, angle: 0.3, penumbra: 0.45, decay: 1.4, drop: 0.015 },
|
|
48572
49677
|
fog: { color: 16773320, intensity: 1.6, distance: 16, angle: 0.75, penumbra: 0.7, decay: 1.8, drop: 0.12 },
|
|
@@ -48583,7 +49688,11 @@ var GameVehiclesThree = (() => {
|
|
|
48583
49688
|
if (o.userData?.lamp === "fog" && o.material && !bulbs.includes(o)) bulbs.push(o);
|
|
48584
49689
|
});
|
|
48585
49690
|
if (bulbs.length) lamps.push({ kind: "fog", inner: bulbs });
|
|
48586
|
-
const
|
|
49691
|
+
const beacons = [];
|
|
49692
|
+
built2.group.traverse((o) => {
|
|
49693
|
+
if (o.userData?.lamp === "beacon" && o.material) beacons.push({ mesh: o, side: o.userData.beaconSide === 1 ? 1 : 0 });
|
|
49694
|
+
});
|
|
49695
|
+
const has = { head: lamps.some((l) => l.kind === "headlight"), tail: lamps.some((l) => l.kind === "taillight"), fog: lamps.some((l) => l.kind === "fog"), indicators: false, beacon: beacons.length > 0 };
|
|
48587
49696
|
const originals = /* @__PURE__ */ new Map();
|
|
48588
49697
|
const copies = /* @__PURE__ */ new Map();
|
|
48589
49698
|
const base = /* @__PURE__ */ new Map();
|
|
@@ -48598,6 +49707,7 @@ var GameVehiclesThree = (() => {
|
|
|
48598
49707
|
mesh2.material = copy;
|
|
48599
49708
|
return copy;
|
|
48600
49709
|
};
|
|
49710
|
+
for (const b of beacons) own(b.mesh);
|
|
48601
49711
|
const haloBase = /* @__PURE__ */ new Map();
|
|
48602
49712
|
for (const l of lamps) {
|
|
48603
49713
|
for (const m of l.inner) own(m);
|
|
@@ -48673,6 +49783,8 @@ var GameVehiclesThree = (() => {
|
|
|
48673
49783
|
else if (l.kind === "fog") glow(l, state.fog ? g.fog.on : g.fog.off);
|
|
48674
49784
|
}
|
|
48675
49785
|
for (const m of amber) glowMesh(m, state[sideOf.get(m) ?? "left"] ? g.amber.on : g.amber.off);
|
|
49786
|
+
const lit = state.beacon ?? null;
|
|
49787
|
+
for (const b of beacons) glowMesh(b.mesh, lit === null ? g.beacon.off : lit === b.side ? g.beacon.lit : g.beacon.dark);
|
|
48676
49788
|
const beamId = state.mode === "low" || state.mode === "high" ? state.mode : null;
|
|
48677
49789
|
for (const id of ["low", "high"]) beam(id, beamId === id, () => spots(front, LAMP_RULES[id]));
|
|
48678
49790
|
beam("fog", state.fog && has.fog, () => spots(fogAnchors, LAMP_RULES.fog));
|
|
@@ -48686,7 +49798,7 @@ var GameVehiclesThree = (() => {
|
|
|
48686
49798
|
return { ...state };
|
|
48687
49799
|
},
|
|
48688
49800
|
set(next) {
|
|
48689
|
-
if (next.mode === state.mode && next.fog === state.fog && next.interior === state.interior && next.brake === state.brake && next.reverse === state.reverse && next.left === state.left && next.right === state.right) return;
|
|
49801
|
+
if (next.mode === state.mode && next.fog === state.fog && next.interior === state.interior && next.brake === state.brake && next.reverse === state.reverse && next.left === state.left && next.right === state.right && (next.beacon ?? null) === (state.beacon ?? null)) return;
|
|
48690
49802
|
Object.assign(state, next);
|
|
48691
49803
|
apply();
|
|
48692
49804
|
},
|
|
@@ -48695,15 +49807,17 @@ var GameVehiclesThree = (() => {
|
|
|
48695
49807
|
sources.clear();
|
|
48696
49808
|
for (const a of anchors) a.removeFromParent();
|
|
48697
49809
|
anchors.length = 0;
|
|
49810
|
+
const giveBack = (m) => {
|
|
49811
|
+
const copy = m.material;
|
|
49812
|
+
const original = originals.get(m);
|
|
49813
|
+
if (!original) return;
|
|
49814
|
+
originals.delete(m);
|
|
49815
|
+
m.material = original;
|
|
49816
|
+
if (copy && !Array.isArray(copy)) copy.dispose?.();
|
|
49817
|
+
};
|
|
49818
|
+
for (const b of beacons) giveBack(b.mesh);
|
|
48698
49819
|
for (const l of lamps) {
|
|
48699
|
-
for (const m of l.inner)
|
|
48700
|
-
const copy = m.material;
|
|
48701
|
-
const original = originals.get(m);
|
|
48702
|
-
if (original) {
|
|
48703
|
-
m.material = original;
|
|
48704
|
-
if (copy && !Array.isArray(copy)) copy.dispose?.();
|
|
48705
|
-
}
|
|
48706
|
-
}
|
|
49820
|
+
for (const m of l.inner) giveBack(m);
|
|
48707
49821
|
for (const h of l.halo ?? []) {
|
|
48708
49822
|
h.visible = true;
|
|
48709
49823
|
const s = haloBase.get(h) ?? 1;
|
|
@@ -48717,14 +49831,85 @@ var GameVehiclesThree = (() => {
|
|
|
48717
49831
|
};
|
|
48718
49832
|
}
|
|
48719
49833
|
|
|
49834
|
+
// src/windshield-mist.ts
|
|
49835
|
+
var MIST_RULES = { color: 15001836, opacity: 0.72, others: 0.8 };
|
|
49836
|
+
var DOUBLE_SIDE = 2;
|
|
49837
|
+
function createWindshieldMist(THREE, built2) {
|
|
49838
|
+
const glass = (built2.context?.glass ?? []).filter((p) => p?.geometry);
|
|
49839
|
+
const films = [];
|
|
49840
|
+
for (const pane of glass) {
|
|
49841
|
+
const side2 = !Array.isArray(pane.material) && pane.material?.side || DOUBLE_SIDE;
|
|
49842
|
+
const material = new THREE.MeshBasicMaterial({ color: MIST_RULES.color, transparent: true, opacity: 0, depthWrite: false, side: side2, polygonOffset: true, polygonOffsetFactor: -1, polygonOffsetUnits: -1 });
|
|
49843
|
+
const mesh2 = new THREE.Mesh(pane.geometry, material);
|
|
49844
|
+
mesh2.name = "windshield_mist";
|
|
49845
|
+
mesh2.raycast = () => {
|
|
49846
|
+
};
|
|
49847
|
+
mesh2.userData.mist = true;
|
|
49848
|
+
mesh2.renderOrder = pane.renderOrder + 1;
|
|
49849
|
+
mesh2.visible = false;
|
|
49850
|
+
pane.add(mesh2);
|
|
49851
|
+
films.push({ mesh: mesh2, material, share: pane.userData.glass?.key === "windshield" ? 1 : MIST_RULES.others });
|
|
49852
|
+
}
|
|
49853
|
+
let fog = 0;
|
|
49854
|
+
return {
|
|
49855
|
+
panes: films.length,
|
|
49856
|
+
get fog() {
|
|
49857
|
+
return fog;
|
|
49858
|
+
},
|
|
49859
|
+
set(next) {
|
|
49860
|
+
const share = Math.max(0, Math.min(1, next));
|
|
49861
|
+
if (Math.abs(share - fog) < 5e-3 && share > 0 === fog > 0) return;
|
|
49862
|
+
fog = share;
|
|
49863
|
+
for (const f of films) {
|
|
49864
|
+
f.material.opacity = MIST_RULES.opacity * fog * f.share;
|
|
49865
|
+
f.mesh.visible = fog > 0.01;
|
|
49866
|
+
}
|
|
49867
|
+
},
|
|
49868
|
+
dispose() {
|
|
49869
|
+
for (const f of films) {
|
|
49870
|
+
f.mesh.removeFromParent();
|
|
49871
|
+
f.material.dispose();
|
|
49872
|
+
}
|
|
49873
|
+
films.length = 0;
|
|
49874
|
+
}
|
|
49875
|
+
};
|
|
49876
|
+
}
|
|
49877
|
+
|
|
48720
49878
|
// src/test-area/proving/cockpit.ts
|
|
48721
|
-
var DEFAULT_COCKPIT_SOUNDS = {
|
|
49879
|
+
var DEFAULT_COCKPIT_SOUNDS = {
|
|
49880
|
+
horn: "horn",
|
|
49881
|
+
blinker: "blinker_tick",
|
|
49882
|
+
starter: "starter_crank",
|
|
49883
|
+
alarm: "car_alarm",
|
|
49884
|
+
chirp: "alarm_chirp",
|
|
49885
|
+
wiper: "wiper_swish",
|
|
49886
|
+
chime: "seatbelt_chime",
|
|
49887
|
+
radio: "radio_static",
|
|
49888
|
+
beep: "parking_beep",
|
|
49889
|
+
wail: "siren_wail",
|
|
49890
|
+
yelp: "siren_yelp",
|
|
49891
|
+
spark: "hotwire_spark",
|
|
49892
|
+
glovebox: "glovebox_latch"
|
|
49893
|
+
};
|
|
49894
|
+
var BODY_KEYS = {
|
|
49895
|
+
Digit1: "door_front_left",
|
|
49896
|
+
Digit2: "door_front_right",
|
|
49897
|
+
Digit3: "door_rear_left",
|
|
49898
|
+
Digit4: "door_rear_right",
|
|
49899
|
+
Digit5: "hood",
|
|
49900
|
+
Digit6: "lid"
|
|
49901
|
+
};
|
|
49902
|
+
var WINDOW_KEYS = { Digit1: "front_left", Digit2: "front_right", Digit3: "rear_left", Digit4: "rear_right" };
|
|
49903
|
+
var LOCK_KEY = "KeyV";
|
|
49904
|
+
var WIPE_RATE = { off: 0, intermittent: 0.25, slow: 0.7, fast: 1.4 };
|
|
48722
49905
|
function createCockpit(o) {
|
|
48723
49906
|
const sounds = { ...DEFAULT_COCKPIT_SOUNDS, ...o.sounds };
|
|
48724
49907
|
const spec = subjectSpec(o.subject);
|
|
48725
49908
|
const driver = createSemiSimDriver(spec);
|
|
48726
49909
|
driver.place(o.place[0], o.place[1], o.place[2]);
|
|
48727
49910
|
const lamps = createVehicleLamps(o.THREE, o.built, { lights: o.host.lights, owner: "proving-ground" });
|
|
49911
|
+
const mist = createWindshieldMist(o.THREE, o.built);
|
|
49912
|
+
const fog = createWindshieldFog();
|
|
48728
49913
|
const audio = o.host.audio;
|
|
48729
49914
|
const top = o.subject.stats.maxSpeedKmh;
|
|
48730
49915
|
const dashboard = o.gauge ? createVehicleDashboard(o.THREE, o.built, { gauge: o.gauge, needle: o.needle, redlineRpm: spec.engine.redlineRpm, maxKmh: top ? Math.ceil((top + 10) / 20) * 20 : void 0 }) : null;
|
|
@@ -48735,27 +49920,77 @@ var GameVehiclesThree = (() => {
|
|
|
48735
49920
|
let wipeAgain = 0;
|
|
48736
49921
|
let chimeAgain = 0;
|
|
48737
49922
|
let radioAgain = 0;
|
|
49923
|
+
let beepAgain = 0;
|
|
49924
|
+
let bar = 0;
|
|
48738
49925
|
let exitAsked = false;
|
|
49926
|
+
let sirenAgain = 0;
|
|
49927
|
+
let sparkAgain = 0;
|
|
49928
|
+
let wiresBefore = 0;
|
|
48739
49929
|
let gas = 0;
|
|
49930
|
+
const systems = createVehicleSystems();
|
|
49931
|
+
const context = o.built.context;
|
|
49932
|
+
const destructible = o.kit && context ? createVehicleDestructible(o.kit, context, { id: "driven", frame: o.built.group }) : null;
|
|
49933
|
+
const body = destructible ? createVehicleBody(o.built, { THREE: o.THREE, clips: destructible.animations() }) : null;
|
|
49934
|
+
const compartments = [];
|
|
49935
|
+
if (!body || body.parts.some((p) => p.startsWith("door"))) compartments.push(GLOVEBOX);
|
|
49936
|
+
if (body?.parts.includes("lid")) compartments.push(trunkFor(o.trunkLitres));
|
|
49937
|
+
const storage = createVehicleStorage({ compartments });
|
|
49938
|
+
for (const c of compartments) storage.stock(c.id, o.stock?.(c.id) ?? []);
|
|
49939
|
+
const access = () => ({
|
|
49940
|
+
seated: true,
|
|
49941
|
+
frontDoorOpen: (body?.openness("door_front_left") ?? 0) >= 0.5 || (body?.openness("door_front_right") ?? 0) >= 0.5,
|
|
49942
|
+
gloveboxOpen: controls.state.glovebox,
|
|
49943
|
+
lid: body?.openness("lid") ?? 0
|
|
49944
|
+
});
|
|
49945
|
+
const bodyEvents = (events) => {
|
|
49946
|
+
for (const event of events) {
|
|
49947
|
+
if (event.type === "sound") play(event.key, 0.9);
|
|
49948
|
+
o.onEvent?.(event);
|
|
49949
|
+
}
|
|
49950
|
+
};
|
|
48740
49951
|
const controls = createVehicleControls({
|
|
49952
|
+
canCrank: systems.canCrank,
|
|
49953
|
+
onCrank: systems.crank,
|
|
49954
|
+
powerLimit: systems.powerLimit,
|
|
48741
49955
|
gears: spec.gears?.length ?? 5,
|
|
48742
49956
|
fourWheelDrive: !!o.subject.body.fourWheelDrive,
|
|
48743
49957
|
fogLamps: lamps.has.fog,
|
|
49958
|
+
clutchPedal: true,
|
|
49959
|
+
radioTracks: RADIO_TRACKS.length,
|
|
49960
|
+
hasKey: o.hasKey,
|
|
49961
|
+
emergency: lamps.has.beacon,
|
|
48744
49962
|
onEvent: (event) => {
|
|
48745
49963
|
if (event.type === "command") {
|
|
48746
|
-
if (event.command === "ignition" && event.state.ignition && sounds.starter) play(sounds.starter);
|
|
48747
49964
|
if (event.command === "ignition" && !event.state.ignition) driver.state.engineOn = false;
|
|
48748
49965
|
if (event.command === "alarm" && event.state.alarm === "armed") play(sounds.chirp);
|
|
48749
49966
|
if (event.command === "alarm") alarmAgain = 0;
|
|
48750
|
-
if (event.command === "radio" || event.command === "radio_source"
|
|
49967
|
+
if (event.command === "radio" || event.command === "radio_source" || event.command === "radio_track") {
|
|
49968
|
+
radioAgain = 0;
|
|
49969
|
+
bar = 0;
|
|
49970
|
+
}
|
|
48751
49971
|
if (event.command === "exit") exitAsked = true;
|
|
49972
|
+
if (event.command === "siren") sirenAgain = 0;
|
|
49973
|
+
if (event.command === "glovebox") play(sounds.glovebox, 0.8);
|
|
48752
49974
|
}
|
|
48753
49975
|
o.onEvent?.(event);
|
|
48754
49976
|
}
|
|
48755
49977
|
});
|
|
48756
49978
|
driver.state.engineOn = false;
|
|
48757
49979
|
const target = typeof window !== "undefined" ? window : null;
|
|
49980
|
+
const bodyKey = (e) => {
|
|
49981
|
+
if (!body) return false;
|
|
49982
|
+
if (e.code === LOCK_KEY) bodyEvents(body.lock(!body.locked));
|
|
49983
|
+
else if (e.shiftKey && e.code === "Digit5") body.toggleSunroof();
|
|
49984
|
+
else if (e.shiftKey && WINDOW_KEYS[e.code]) body.toggleWindow(WINDOW_KEYS[e.code]);
|
|
49985
|
+
else if (!e.shiftKey && BODY_KEYS[e.code]) bodyEvents(body.toggle(BODY_KEYS[e.code]));
|
|
49986
|
+
else return false;
|
|
49987
|
+
return true;
|
|
49988
|
+
};
|
|
48758
49989
|
const down = (e) => {
|
|
49990
|
+
if (!e.repeat && bodyKey(e)) {
|
|
49991
|
+
e.stopImmediatePropagation();
|
|
49992
|
+
return;
|
|
49993
|
+
}
|
|
48759
49994
|
if (!controls.key(e.code, true)) return;
|
|
48760
49995
|
e.stopImmediatePropagation();
|
|
48761
49996
|
if (e.code.startsWith("Arrow") || e.code === "Space") e.preventDefault();
|
|
@@ -48767,9 +50002,19 @@ var GameVehiclesThree = (() => {
|
|
|
48767
50002
|
target?.addEventListener("keydown", down, true);
|
|
48768
50003
|
target?.addEventListener("keyup", up, true);
|
|
48769
50004
|
target?.addEventListener("blur", blur);
|
|
48770
|
-
|
|
50005
|
+
const cockpit = {
|
|
50006
|
+
radiator: 1,
|
|
50007
|
+
storage,
|
|
50008
|
+
access,
|
|
50009
|
+
fog,
|
|
50010
|
+
mist,
|
|
50011
|
+
weather: { ...o.weather ?? { outsideC: 25, rain: 0 } },
|
|
50012
|
+
emergency: lamps.has.beacon,
|
|
48771
50013
|
driver,
|
|
48772
50014
|
controls,
|
|
50015
|
+
systems,
|
|
50016
|
+
body,
|
|
50017
|
+
destructible,
|
|
48773
50018
|
lamps,
|
|
48774
50019
|
dashboard,
|
|
48775
50020
|
get throttle() {
|
|
@@ -48778,18 +50023,39 @@ var GameVehiclesThree = (() => {
|
|
|
48778
50023
|
step(dt) {
|
|
48779
50024
|
const input = controls.input(dt, driver);
|
|
48780
50025
|
gas = input.throttle;
|
|
48781
|
-
|
|
50026
|
+
if (input.start && sounds.starter) play(sounds.starter);
|
|
50027
|
+
const engine = driver.step(input, dt).events;
|
|
48782
50028
|
controls.after(driver, dt);
|
|
48783
50029
|
const s = controls.state;
|
|
50030
|
+
const report = [...engine.filter((e) => e.type !== "shift"), ...systems.step({ driver, controls: s, throttle: input.throttle, dt, radiator: cockpit.radiator })];
|
|
50031
|
+
for (const event of report) o.onEvent?.(event);
|
|
50032
|
+
const powered = driver.state.engineOn || systems.state.charge > 0;
|
|
50033
|
+
const high = s.lamps.mode === "high" || s.lamps.flash;
|
|
48784
50034
|
lamps.set({
|
|
48785
|
-
mode: s.lamps.mode,
|
|
50035
|
+
mode: !powered ? "off" : s.lamps.flash ? "high" : s.lamps.mode,
|
|
48786
50036
|
fog: s.lamps.fog,
|
|
48787
50037
|
interior: s.lamps.interior,
|
|
48788
50038
|
brake: s.brakeLights,
|
|
48789
50039
|
reverse: s.reverseLights,
|
|
48790
50040
|
left: s.blinkOn && (s.indicator === "left" || s.indicator === "hazard"),
|
|
48791
|
-
right: s.blinkOn && (s.indicator === "right" || s.indicator === "hazard")
|
|
48792
|
-
|
|
50041
|
+
right: s.blinkOn && (s.indicator === "right" || s.indicator === "hazard"),
|
|
50042
|
+
beacon: s.beacon && powered ? s.beaconSide : null
|
|
50043
|
+
});
|
|
50044
|
+
const w = cockpit.weather;
|
|
50045
|
+
const windows = body ? body.windows.reduce((sum, id) => sum + body.window(id), 0) / Math.max(1, body.windows.length) : 0;
|
|
50046
|
+
const warm = systems.state.temperature;
|
|
50047
|
+
const cabinC = s.climate.on ? 22 : w.outsideC + (driver.state.engineOn ? 3 + 5 * Math.min(1, warm * 2) : 2);
|
|
50048
|
+
mist.set(fog.step({ dt, occupants: 1, outsideC: w.outsideC, cabinC, rain: w.rain, speed: Math.abs(driver.state.u), windows, climate: s.climate, engineWarm: driver.state.engineOn ? Math.min(1, warm * 2) : 0 }).fog);
|
|
50049
|
+
if (s.siren !== "off" && powered && (sirenAgain -= dt) <= 0) {
|
|
50050
|
+
play(s.siren === "wail" ? sounds.wail : sounds.yelp);
|
|
50051
|
+
sirenAgain = s.siren === "wail" ? 2.95 : 1.95;
|
|
50052
|
+
}
|
|
50053
|
+
const working = s.hotwire.progress > wiresBefore;
|
|
50054
|
+
wiresBefore = s.hotwire.progress;
|
|
50055
|
+
if (working && (sparkAgain -= dt) <= 0) {
|
|
50056
|
+
play(sounds.spark, 0.7);
|
|
50057
|
+
sparkAgain = 0.45 + 0.4 * (s.hotwire.progress * 7 % 1);
|
|
50058
|
+
}
|
|
48793
50059
|
dashboard?.update(
|
|
48794
50060
|
{
|
|
48795
50061
|
kmh: Math.abs(driver.state.u) * 3.6,
|
|
@@ -48799,7 +50065,14 @@ var GameVehiclesThree = (() => {
|
|
|
48799
50065
|
engineOn: driver.state.engineOn,
|
|
48800
50066
|
left: s.blinkOn && (s.indicator === "left" || s.indicator === "hazard"),
|
|
48801
50067
|
right: s.blinkOn && (s.indicator === "right" || s.indicator === "hazard"),
|
|
48802
|
-
highBeam:
|
|
50068
|
+
highBeam: high,
|
|
50069
|
+
fuel: driver.state.fuel / spec.tank.capacity,
|
|
50070
|
+
temperature: systems.state.temperature,
|
|
50071
|
+
cruise: s.cruise.on,
|
|
50072
|
+
profile: s.profile,
|
|
50073
|
+
tractionOff: !s.tractionControl,
|
|
50074
|
+
absOff: !s.abs,
|
|
50075
|
+
charging: systems.state.netW >= 0,
|
|
48803
50076
|
lowBeam: s.lamps.mode === "low" || s.lamps.mode === "position",
|
|
48804
50077
|
fog: s.lamps.fog,
|
|
48805
50078
|
parkingBrake: s.parkingBrake,
|
|
@@ -48808,7 +50081,19 @@ var GameVehiclesThree = (() => {
|
|
|
48808
50081
|
},
|
|
48809
50082
|
dt
|
|
48810
50083
|
);
|
|
50084
|
+
if (body) bodyEvents(body.update(dt, s.washer ? 1.2 : WIPE_RATE[s.wipers] ?? 0));
|
|
48811
50085
|
if (s.tick) play(sounds.blinker, 0.8);
|
|
50086
|
+
const near = o.obstacles?.() ?? [];
|
|
50087
|
+
if (s.ignition && near.length && Math.abs(driver.state.u) < 3) {
|
|
50088
|
+
const g = o.built.group;
|
|
50089
|
+
const reversing = driver.state.gear < 0 || driver.state.u < -0.05;
|
|
50090
|
+
const distance = bumperDistance({ x: g.position.x, z: g.position.z, heading: [Math.sin(g.rotation.y), Math.cos(g.rotation.y)], length: o.built.length, width: o.built.width, forward: !reversing, obstacles: near });
|
|
50091
|
+
const every = parkingBeepInterval(distance);
|
|
50092
|
+
if (every != null && (beepAgain -= dt) <= 0) {
|
|
50093
|
+
play(sounds.beep, 0.7);
|
|
50094
|
+
beepAgain = every === 0 ? 0.09 : every;
|
|
50095
|
+
}
|
|
50096
|
+
}
|
|
48812
50097
|
if (s.horn && (hornAgain -= dt) <= 0) {
|
|
48813
50098
|
play(sounds.horn);
|
|
48814
50099
|
hornAgain = 0.5;
|
|
@@ -48817,9 +50102,9 @@ var GameVehiclesThree = (() => {
|
|
|
48817
50102
|
play(sounds.alarm);
|
|
48818
50103
|
alarmAgain = 2.9;
|
|
48819
50104
|
}
|
|
48820
|
-
if (s.wipers !== "off" && (wipeAgain -= dt) <= 0) {
|
|
50105
|
+
if ((s.wipers !== "off" || s.washer) && (wipeAgain -= dt) <= 0) {
|
|
48821
50106
|
play(sounds.wiper, 0.7);
|
|
48822
|
-
wipeAgain = s.wipers === "fast" ? 0.6 : 1.4;
|
|
50107
|
+
wipeAgain = s.washer || s.wipers === "fast" ? 0.6 : s.wipers === "slow" ? 1.4 : 4;
|
|
48823
50108
|
}
|
|
48824
50109
|
const kmh2 = Math.abs(driver.state.u) * 3.6;
|
|
48825
50110
|
if (!s.seatbelt && s.ignition && kmh2 > 10 && (chimeAgain -= dt) <= 0) {
|
|
@@ -48827,8 +50112,13 @@ var GameVehiclesThree = (() => {
|
|
|
48827
50112
|
chimeAgain = 6;
|
|
48828
50113
|
}
|
|
48829
50114
|
if (s.radio.on && (radioAgain -= dt) <= 0) {
|
|
48830
|
-
|
|
48831
|
-
|
|
50115
|
+
const song = RADIO_TRACKS[s.radio.track % RADIO_TRACKS.length];
|
|
50116
|
+
if (song) {
|
|
50117
|
+
play(song.bars[bar % song.bars.length], s.radio.source === "tape" ? 0.8 : 0.7);
|
|
50118
|
+
bar++;
|
|
50119
|
+
}
|
|
50120
|
+
if (s.radio.source === "radio") play(sounds.radio, 0.12);
|
|
50121
|
+
radioAgain = song?.barSeconds ?? 2;
|
|
48832
50122
|
}
|
|
48833
50123
|
if (exitAsked) {
|
|
48834
50124
|
exitAsked = false;
|
|
@@ -48841,11 +50131,174 @@ var GameVehiclesThree = (() => {
|
|
|
48841
50131
|
target?.removeEventListener("blur", blur);
|
|
48842
50132
|
controls.release();
|
|
48843
50133
|
lamps.dispose();
|
|
50134
|
+
mist.dispose();
|
|
50135
|
+
storage.clear();
|
|
48844
50136
|
dashboard?.dispose();
|
|
50137
|
+
body?.dispose();
|
|
50138
|
+
destructible?.dispose?.();
|
|
50139
|
+
}
|
|
50140
|
+
};
|
|
50141
|
+
return cockpit;
|
|
50142
|
+
}
|
|
50143
|
+
|
|
50144
|
+
// src/wheel-roll.ts
|
|
50145
|
+
var DEFAULT_RADIUS = 0.32;
|
|
50146
|
+
function createWheelRoll(THREE, built2) {
|
|
50147
|
+
const wheels = (built2.context?.wheels ?? []).map((wheel) => ({
|
|
50148
|
+
wheel,
|
|
50149
|
+
rest: wheel.quaternion.clone(),
|
|
50150
|
+
radius: Number(wheel.userData.r) || DEFAULT_RADIUS,
|
|
50151
|
+
// in the kit's frame the front is +x: the wheels ahead of the middle steer
|
|
50152
|
+
front: wheel.position.x > 0,
|
|
50153
|
+
angle: 0
|
|
50154
|
+
}));
|
|
50155
|
+
const axle = new THREE.Vector3(0, 0, 1);
|
|
50156
|
+
const up = new THREE.Vector3(0, 1, 0);
|
|
50157
|
+
const spin = new THREE.Quaternion();
|
|
50158
|
+
const steering = new THREE.Quaternion();
|
|
50159
|
+
return {
|
|
50160
|
+
count: wheels.length,
|
|
50161
|
+
roll(distance, steer) {
|
|
50162
|
+
for (const w of wheels) {
|
|
50163
|
+
w.angle = (w.angle - distance / w.radius) % (Math.PI * 2);
|
|
50164
|
+
spin.setFromAxisAngle(axle, w.angle);
|
|
50165
|
+
steering.setFromAxisAngle(up, w.front ? steer : 0);
|
|
50166
|
+
w.wheel.quaternion.copy(w.rest).premultiply(spin).premultiply(steering);
|
|
50167
|
+
}
|
|
50168
|
+
},
|
|
50169
|
+
dispose() {
|
|
50170
|
+
for (const w of wheels) w.wheel.quaternion.copy(w.rest);
|
|
48845
50171
|
}
|
|
48846
50172
|
};
|
|
48847
50173
|
}
|
|
48848
50174
|
|
|
50175
|
+
// src/test-area/proving/crash.ts
|
|
50176
|
+
var GLASS_BLOW = 6e3;
|
|
50177
|
+
function createProvingCrash(host, occupant) {
|
|
50178
|
+
const thrown = [];
|
|
50179
|
+
const breakGlass = (destructible, exit, forward) => {
|
|
50180
|
+
if (!destructible) return;
|
|
50181
|
+
const want = exit === "windshield" ? "windshield" : exit === "rear_window" ? "rear" : exit.startsWith("left") ? "left" : "right";
|
|
50182
|
+
const pane = destructible.describe().parts.find((p) => p.id.includes(exit === "windshield" || exit === "rear_window" ? want : "window") && (exit === "windshield" || exit === "rear_window" || p.id.includes(want)));
|
|
50183
|
+
if (!pane) return;
|
|
50184
|
+
destructible.hit({ type: "blunt", partId: pane.id, point: destructible.partWorldCenter(pane.id), direction: forward, energy: GLASS_BLOW, radius: 0.35, source: "occupant" });
|
|
50185
|
+
};
|
|
50186
|
+
return {
|
|
50187
|
+
crash({ car, u, w, belted, destructible }) {
|
|
50188
|
+
const ejection = ejectionOf({ before: { u, w }, after: { u: 0, w: 0 } }, belted);
|
|
50189
|
+
if (!ejection) return null;
|
|
50190
|
+
const s = Math.sin(car.rotationY);
|
|
50191
|
+
const c = Math.cos(car.rotationY);
|
|
50192
|
+
const forward = [s, 0, c];
|
|
50193
|
+
const right = [-c, 0, s];
|
|
50194
|
+
breakGlass(destructible, ejection.exit, forward);
|
|
50195
|
+
const [vf, vr, vu] = ejection.velocity;
|
|
50196
|
+
const start2 = [car.position.x + forward[0] * 1.2, 1.1, car.position.z + forward[2] * 1.2];
|
|
50197
|
+
const placed = occupant ? host.addObject?.(occupant, { position: start2, rotationY: car.rotationY }) : null;
|
|
50198
|
+
if (placed) {
|
|
50199
|
+
launchBody(placed.root, [forward[0] * vf + right[0] * vr, vu, forward[2] * vf + right[2] * vr]);
|
|
50200
|
+
thrown.push(placed.remove);
|
|
50201
|
+
}
|
|
50202
|
+
return ejection;
|
|
50203
|
+
},
|
|
50204
|
+
dispose() {
|
|
50205
|
+
for (const remove of thrown.splice(0)) remove();
|
|
50206
|
+
}
|
|
50207
|
+
};
|
|
50208
|
+
}
|
|
50209
|
+
|
|
50210
|
+
// src/test-area/proving/systems-text.ts
|
|
50211
|
+
var SYSTEMS_TEXT = {
|
|
50212
|
+
"pt-BR": {
|
|
50213
|
+
keys: "C embreagem (c\xE2mbio manual) \xB7 X lampejo do farol alto \xB7 Z esguicho do limpador \xB7 7 modo econ\xF4mico/normal/esporte \xB7 8 controle de tra\xE7\xE3o \xB7 9 ABS \xB7 0 piloto autom\xE1tico \xB7 - ar-condicionado \xB7 = desemba\xE7ador \xB7 ] troca a faixa do r\xE1dio ou da fita \xB7 ; sirene \xB7 ' giroflex (ve\xEDculo de emerg\xEAncia) \xB7 / porta-luvas \xB7 sem a chave, segure I: liga\xE7\xE3o direta",
|
|
50214
|
+
profile: "Modo de condu\xE7\xE3o",
|
|
50215
|
+
profiles: { eco: "econ\xF4mico", normal: "normal", sport: "esporte" },
|
|
50216
|
+
traction: "Controle de tra\xE7\xE3o",
|
|
50217
|
+
abs: "ABS",
|
|
50218
|
+
cruise: "Piloto autom\xE1tico",
|
|
50219
|
+
cruiseSet: "Piloto autom\xE1tico: segurando {0} km/h",
|
|
50220
|
+
climate: "Ar-condicionado",
|
|
50221
|
+
demist: "Desemba\xE7ador",
|
|
50222
|
+
wiperModes: { off: "desligado", intermittent: "intermitente", slow: "lento", fast: "r\xE1pido" },
|
|
50223
|
+
refused: { battery_flat: "Bateria descarregada: o motor de partida n\xE3o gira", too_slow: "Piloto autom\xE1tico s\xF3 acima de 30 km/h", locked: "Porta travada", missing: "Este ve\xEDculo n\xE3o tem essa pe\xE7a", no_key: "Sem a chave: segure I para fazer a liga\xE7\xE3o direta", no_siren: "Este ve\xEDculo n\xE3o tem sirene nem giroflex" },
|
|
50224
|
+
events: {
|
|
50225
|
+
stall: "O motor morreu",
|
|
50226
|
+
out_of_fuel: "Acabou o combust\xEDvel",
|
|
50227
|
+
bogged: "Atolou",
|
|
50228
|
+
aquaplaning: "Aquaplanagem",
|
|
50229
|
+
battery_flat: "A bateria descarregou",
|
|
50230
|
+
overheating: "Motor superaquecendo: perdendo pot\xEAncia",
|
|
50231
|
+
seized: "O motor fundiu de tanto esquentar",
|
|
50232
|
+
spare_fitted: "Estepe colocado",
|
|
50233
|
+
no_spare: "N\xE3o h\xE1 estepe",
|
|
50234
|
+
cruise_cancelled: "Piloto autom\xE1tico desligado",
|
|
50235
|
+
hotwire_started: "Fios descascados sob a coluna: continue segurando I",
|
|
50236
|
+
hotwire_joined: "Liga\xE7\xE3o direta feita: a igni\xE7\xE3o pegou e o motor de partida gira"
|
|
50237
|
+
},
|
|
50238
|
+
actions: { puncture: "Furar pneu (dianteiro esquerdo)", fit_spare: "Trocar pelo estepe", refuel: "Abastecer", drain_battery: "Descarregar bateria", jump_start: "Chupeta (carregar bateria)", break_radiator: "Furar o radiador", empty_tank: "Deixar o tanque na reserva", remote_lock: "Controle: travar (arma o alarme)", remote_unlock: "Controle: destravar", force_door: "For\xE7ar a porta do motorista", crash_wall: "Bater no muro (parada seca)", park_behind: "Estacionar um carro atr\xE1s (sensor de r\xE9)", take_key: "Tirar a chave (liga\xE7\xE3o direta) / devolver", cold_rain: "Tempo: frio e chuva / bom", glovebox_contents: "Ver o porta-luvas", trunk_contents: "Ver o porta-malas", take_from_trunk: "Tirar um item do porta-malas para o ch\xE3o" },
|
|
50239
|
+
siren: "Sirene",
|
|
50240
|
+
sirenModes: { off: "desligada", wail: "cont\xEDnua", yelp: "r\xE1pida (cruzamento)" },
|
|
50241
|
+
beacon: "Giroflex",
|
|
50242
|
+
glovebox: "Porta-luvas",
|
|
50243
|
+
lid: { open: "aberto", shut: "fechado" },
|
|
50244
|
+
storage: { names: { glovebox: "Porta-luvas", trunk: "Porta-malas" }, empty: "{0}: vazio", shut: "{0} fechado: abra antes (porta-luvas com / sentado, porta-malas com 6)", list: "{0} ({1} kg): {2}", none: "Este ve\xEDculo n\xE3o tem {0}", taken: "{0} tirado do porta-malas e posto no ch\xE3o", ground: "{0} tirado do porta-malas (sem cat\xE1logo de itens nesta sala para p\xF4-lo no ch\xE3o)" },
|
|
50245
|
+
fog: { misted: "O para-brisa emba\xE7ou por dentro: = desemba\xE7ador, ar-condicionado ou um vidro aberto", clear: "Para-brisa desemba\xE7ado", weather: "L\xE1 fora: 8 \xB0C e chuva", fair: "L\xE1 fora: 25 \xB0C, sem chuva", metric: "Vidro emba\xE7ado" },
|
|
50246
|
+
keyTaken: "Sem a chave no contato: segure I para a liga\xE7\xE3o direta",
|
|
50247
|
+
keyBack: "Chave de volta no contato",
|
|
50248
|
+
parking: { placed: "Carro parado 3 m atr\xE1s: d\xEA r\xE9 e escute o sensor", none: "Sem cat\xE1logo de ve\xEDculos nesta sala: o sensor n\xE3o tem o que ver" },
|
|
50249
|
+
track: "faixa {0}",
|
|
50250
|
+
adjust: { seat_forward: "Banco: frente/tr\xE1s (m)", seat_height: "Banco: altura (m)", mirror_left: "Retrovisor esquerdo: \xE2ngulo", mirror_right: "Retrovisor direito: \xE2ngulo" },
|
|
50251
|
+
crash: { mild: "Batida a {0} km/h: fraca demais para lan\xE7ar quem est\xE1 sem cinto", stayed: "Batida a {0} km/h: o cinto segurou o motorista", ejected: "Batida a {0} km/h sem cinto: o motorista saiu pelo {1}", exits: { windshield: "para-brisa", left_window: "vidro esquerdo", right_window: "vidro direito", rear_window: "vidro traseiro" } },
|
|
50252
|
+
bodyKeys: "1 a 4 portas \xB7 5 cap\xF4 \xB7 6 porta-malas \xB7 Shift+1 a 4 vidros \xB7 Shift+5 teto solar \xB7 V trava as portas",
|
|
50253
|
+
remote: { locked: "Travado pelo controle: alarme armado", unlocked: "Destravado pelo controle", forced: "Porta for\xE7ada" },
|
|
50254
|
+
done: { puncture: "Pneu dianteiro esquerdo furado", refuel: "Tanque cheio", drain_battery: "Bateria quase sem carga", jump_start: "Bateria carregada", break_radiator: "Radiador furado: o motor vai esquentar", empty_tank: "Tanque na reserva" }
|
|
50255
|
+
},
|
|
50256
|
+
en: {
|
|
50257
|
+
keys: "C clutch (manual gearbox) \xB7 X flash the high beam \xB7 Z washer \xB7 7 eco/normal/sport \xB7 8 traction control \xB7 9 ABS \xB7 0 cruise control \xB7 - air conditioning \xB7 = demister \xB7 ] next radio or tape track \xB7 ; siren \xB7 ' beacon (emergency vehicle) \xB7 / glovebox \xB7 without the key, hold I: hotwire",
|
|
50258
|
+
profile: "Drive profile",
|
|
50259
|
+
profiles: { eco: "eco", normal: "normal", sport: "sport" },
|
|
50260
|
+
traction: "Traction control",
|
|
50261
|
+
abs: "ABS",
|
|
50262
|
+
cruise: "Cruise control",
|
|
50263
|
+
cruiseSet: "Cruise control: holding {0} km/h",
|
|
50264
|
+
climate: "Air conditioning",
|
|
50265
|
+
demist: "Demister",
|
|
50266
|
+
wiperModes: { off: "off", intermittent: "intermittent", slow: "slow", fast: "fast" },
|
|
50267
|
+
refused: { battery_flat: "Flat battery: the starter does not turn", too_slow: "Cruise control only above 30 km/h", locked: "The door is locked", missing: "This vehicle has no such part", no_key: "No key: hold I to hotwire it", no_siren: "This vehicle has no siren or beacon" },
|
|
50268
|
+
events: {
|
|
50269
|
+
stall: "The engine stalled",
|
|
50270
|
+
out_of_fuel: "Out of fuel",
|
|
50271
|
+
bogged: "Bogged down",
|
|
50272
|
+
aquaplaning: "Aquaplaning",
|
|
50273
|
+
battery_flat: "The battery went flat",
|
|
50274
|
+
overheating: "Engine overheating: losing power",
|
|
50275
|
+
seized: "The engine seized from the heat",
|
|
50276
|
+
spare_fitted: "Spare tyre fitted",
|
|
50277
|
+
no_spare: "No spare tyre left",
|
|
50278
|
+
cruise_cancelled: "Cruise control off",
|
|
50279
|
+
hotwire_started: "Wires stripped under the column: keep holding I",
|
|
50280
|
+
hotwire_joined: "Hotwired: the ignition is live and the starter turns"
|
|
50281
|
+
},
|
|
50282
|
+
actions: { puncture: "Puncture a tyre (front left)", fit_spare: "Fit the spare", refuel: "Refuel", drain_battery: "Drain the battery", jump_start: "Jump start (charge the battery)", break_radiator: "Puncture the radiator", empty_tank: "Leave the tank on reserve", remote_lock: "Remote: lock (arms the alarm)", remote_unlock: "Remote: unlock", force_door: "Force the driver's door", crash_wall: "Hit a wall (dead stop)", park_behind: "Park a car behind (rear sensor)", take_key: "Take the key out (hotwire) / give it back", cold_rain: "Weather: cold and rain / fair", glovebox_contents: "Look in the glovebox", trunk_contents: "Look in the trunk", take_from_trunk: "Take an item out of the trunk to the ground" },
|
|
50283
|
+
siren: "Siren",
|
|
50284
|
+
sirenModes: { off: "off", wail: "wail", yelp: "yelp (junction)" },
|
|
50285
|
+
beacon: "Beacon",
|
|
50286
|
+
glovebox: "Glovebox",
|
|
50287
|
+
lid: { open: "open", shut: "shut" },
|
|
50288
|
+
storage: { names: { glovebox: "Glovebox", trunk: "Trunk" }, empty: "{0}: empty", shut: "{0} shut: open it first (glovebox with / while seated, trunk with 6)", list: "{0} ({1} kg): {2}", none: "This vehicle has no {0}", taken: "{0} taken out of the trunk and put on the ground", ground: "{0} taken out of the trunk (no item catalogue in this room to put it on the ground)" },
|
|
50289
|
+
fog: { misted: "The windshield misted up inside: = demister, air conditioning or a window down", clear: "Windshield clear", weather: "Outside: 8 \xB0C and rain", fair: "Outside: 25 \xB0C, no rain", metric: "Glass misted" },
|
|
50290
|
+
keyTaken: "No key in the ignition: hold I to hotwire",
|
|
50291
|
+
keyBack: "Key back in the ignition",
|
|
50292
|
+
parking: { placed: "A car parked 3 m behind: reverse and listen to the sensor", none: "No vehicle catalogue in this room: the sensor has nothing to see" },
|
|
50293
|
+
track: "track {0}",
|
|
50294
|
+
adjust: { seat_forward: "Seat: forward/back (m)", seat_height: "Seat: height (m)", mirror_left: "Left mirror: angle", mirror_right: "Right mirror: angle" },
|
|
50295
|
+
crash: { mild: "Crash at {0} km/h: too mild to throw an unbelted occupant out", stayed: "Crash at {0} km/h: the belt held the driver", ejected: "Crash at {0} km/h without a belt: the driver went out through the {1}", exits: { windshield: "windshield", left_window: "left window", right_window: "right window", rear_window: "rear window" } },
|
|
50296
|
+
bodyKeys: "1 to 4 doors \xB7 5 hood \xB7 6 trunk \xB7 Shift+1 to 4 windows \xB7 Shift+5 sunroof \xB7 V locks the doors",
|
|
50297
|
+
remote: { locked: "Locked by the remote: alarm armed", unlocked: "Unlocked by the remote", forced: "Door forced" },
|
|
50298
|
+
done: { puncture: "Front left tyre punctured", refuel: "Tank full", drain_battery: "Battery almost flat", jump_start: "Battery charged", break_radiator: "Radiator punctured: the engine will heat up", empty_tank: "Tank on reserve" }
|
|
50299
|
+
}
|
|
50300
|
+
};
|
|
50301
|
+
|
|
48849
50302
|
// src/test-area/proving/text.ts
|
|
48850
50303
|
var PROVING_TEXT = {
|
|
48851
50304
|
"pt-BR": {
|
|
@@ -48990,9 +50443,11 @@ var GameVehiclesThree = (() => {
|
|
|
48990
50443
|
right: { x: 0.79, y: 0.72, width: 0.19, height: 0.13, rounded: 0.3 },
|
|
48991
50444
|
reverse: { x: 0.36, y: 0.13, width: 0.28, height: 0.18, rounded: 0.06 }
|
|
48992
50445
|
};
|
|
50446
|
+
var ADJUST_KEYS = { seat_forward: "seatForward", seat_height: "seatHeight", mirror_left: "mirrorLeft", mirror_right: "mirrorRight" };
|
|
48993
50447
|
function createProvingModule(options) {
|
|
48994
50448
|
const locale = options.locale ?? "pt-BR";
|
|
48995
50449
|
const text = PROVING_TEXT[locale] ?? PROVING_TEXT["pt-BR"];
|
|
50450
|
+
const sysText = SYSTEMS_TEXT[locale] ?? SYSTEMS_TEXT["pt-BR"];
|
|
48996
50451
|
const tests = options.tests ?? createProvingTests();
|
|
48997
50452
|
const vehicles = options.vehicles;
|
|
48998
50453
|
const sounds = { ...defaultSoundIds, ...options.sounds };
|
|
@@ -49009,7 +50464,19 @@ var GameVehiclesThree = (() => {
|
|
|
49009
50464
|
let run = null;
|
|
49010
50465
|
let parking = null;
|
|
49011
50466
|
let driving = null;
|
|
50467
|
+
let crashes = null;
|
|
50468
|
+
let wheels = null;
|
|
50469
|
+
let lastAt = null;
|
|
50470
|
+
let parked = null;
|
|
50471
|
+
const adjust = { seatForward: 0, seatHeight: 0, mirrorLeft: 0, mirrorRight: 0 };
|
|
50472
|
+
const aimed = (pose2) => {
|
|
50473
|
+
const turn = pose2.id === "left" ? adjust.mirrorLeft : pose2.id === "right" ? -adjust.mirrorRight : 0;
|
|
50474
|
+
return turn ? { ...pose2, look: [pose2.look[0] + turn, pose2.look[1], pose2.look[2]] } : pose2;
|
|
50475
|
+
};
|
|
49012
50476
|
let gearbox = "automatic";
|
|
50477
|
+
let hasKey = true;
|
|
50478
|
+
let weather = { outsideC: 25, rain: 0 };
|
|
50479
|
+
let misted = false;
|
|
49013
50480
|
let lastGear = null;
|
|
49014
50481
|
let driveClock = 0;
|
|
49015
50482
|
let queue = [];
|
|
@@ -49170,6 +50637,8 @@ var GameVehiclesThree = (() => {
|
|
|
49170
50637
|
};
|
|
49171
50638
|
const removeCar = () => {
|
|
49172
50639
|
if (!car) return;
|
|
50640
|
+
wheels = null;
|
|
50641
|
+
lastAt = null;
|
|
49173
50642
|
discardObject3D(car.built.group);
|
|
49174
50643
|
car = null;
|
|
49175
50644
|
};
|
|
@@ -49183,6 +50652,7 @@ var GameVehiclesThree = (() => {
|
|
|
49183
50652
|
built2.group.add(guides);
|
|
49184
50653
|
host.scene.add(built2.group);
|
|
49185
50654
|
car = { built: built2, guides, subject };
|
|
50655
|
+
wheels = createWheelRoll(three, built2);
|
|
49186
50656
|
pose({ x: 0, z: TRACK.start, yaw: 0, pitch: 0, roll: 0, height: 0 }, 0);
|
|
49187
50657
|
rig.vehicle?.reset();
|
|
49188
50658
|
drawBoard();
|
|
@@ -49233,11 +50703,18 @@ var GameVehiclesThree = (() => {
|
|
|
49233
50703
|
car.built.group.position.set(TRACK.x0 + wrapped, 0, TRACK.z + s.z);
|
|
49234
50704
|
car.built.group.rotation.set(-s.pitch, s.yaw + Math.PI / 2, s.roll, "YXZ");
|
|
49235
50705
|
bendGuides(steer);
|
|
50706
|
+
if (lastAt) {
|
|
50707
|
+
const along = (s.x - lastAt.x) * Math.cos(s.yaw) - (s.z - lastAt.z) * Math.sin(s.yaw);
|
|
50708
|
+
if (Math.abs(along) < 5) wheels?.roll(along, steer);
|
|
50709
|
+
}
|
|
50710
|
+
lastAt = { x: s.x, z: s.z };
|
|
49236
50711
|
};
|
|
49237
50712
|
const frameOf = (speed) => {
|
|
49238
50713
|
if (!car) return null;
|
|
49239
50714
|
const g = car.built.group;
|
|
49240
|
-
|
|
50715
|
+
const size = { length: car.built.length, width: car.built.width, height: car.built.height };
|
|
50716
|
+
const [ex, ey, ez] = car.built.driverEye ?? defaultEye(size);
|
|
50717
|
+
return { x: g.position.x, y: g.position.y, z: g.position.z, yaw: g.rotation.y, pitch: -g.rotation.x, roll: g.rotation.z, speed, ...size, eye: [ex, ey + adjust.seatHeight, ez + adjust.seatForward] };
|
|
49241
50718
|
};
|
|
49242
50719
|
const applyCamera = () => {
|
|
49243
50720
|
if (!host?.setViewCamera) return;
|
|
@@ -49319,26 +50796,42 @@ var GameVehiclesThree = (() => {
|
|
|
49319
50796
|
run = null;
|
|
49320
50797
|
queue = [];
|
|
49321
50798
|
parking = null;
|
|
49322
|
-
setSurface("dry_asphalt");
|
|
50799
|
+
setSurface(weather.rain > 0 ? "wet_asphalt" : "dry_asphalt");
|
|
50800
|
+
misted = false;
|
|
49323
50801
|
driving = createCockpit({
|
|
49324
50802
|
THREE: three,
|
|
49325
50803
|
host,
|
|
49326
50804
|
built: car.built,
|
|
49327
50805
|
subject: car.subject,
|
|
49328
50806
|
place: [0, 0, 0],
|
|
50807
|
+
kit: kitFor(three),
|
|
50808
|
+
obstacles: () => parked ? [[parked.root.position.x, parked.root.position.z]] : [],
|
|
49329
50809
|
gauge: kitFor(three).materials?.gauge,
|
|
49330
50810
|
needle: kitFor(three).materials?.amber,
|
|
49331
50811
|
// the engine's own sound turns the key (starter, catch, idle by RPM)
|
|
49332
50812
|
sounds: { starter: "" },
|
|
50813
|
+
hasKey,
|
|
50814
|
+
weather,
|
|
50815
|
+
stock: (compartment) => options.stock?.(compartment, settings.vehicle) ?? [],
|
|
49333
50816
|
onExit: () => stopDriving(),
|
|
49334
50817
|
onEvent: (event) => {
|
|
49335
|
-
if (event.type === "
|
|
50818
|
+
if (event.type === "hotwire") {
|
|
50819
|
+
host?.log(sysText.events[event.stage === "joined" ? "hotwire_joined" : "hotwire_started"], { vehicle: settings.vehicle, stage: event.stage }, "proving_system");
|
|
50820
|
+
if (event.stage === "joined" && car && driving?.systems.canCrank() !== false) engine?.start([car.built.group.position.x, 0.5, car.built.group.position.z]);
|
|
50821
|
+
return;
|
|
50822
|
+
}
|
|
50823
|
+
if (event.type === "refused") return host?.log(text.cabin.refused[event.reason] ?? sysText.refused[event.reason] ?? event.reason);
|
|
50824
|
+
if (event.type === "sound") return;
|
|
50825
|
+
if (event.type !== "command") {
|
|
50826
|
+
if (event.type === "out_of_fuel" || event.type === "stall" || event.type === "seized") engine?.stop([car?.built.group.position.x ?? 0, 0.5, car?.built.group.position.z ?? 0]);
|
|
50827
|
+
return host?.log(sysText.events[event.type] ?? event.type, { vehicle: settings.vehicle, ...event }, "proving_system");
|
|
50828
|
+
}
|
|
49336
50829
|
const st = event.state;
|
|
49337
50830
|
const line = cabinLine(event.command, st);
|
|
49338
50831
|
if (line) host?.log(line);
|
|
49339
50832
|
if (event.command === "ignition" && car) {
|
|
49340
50833
|
const at = [car.built.group.position.x, 0.5, car.built.group.position.z];
|
|
49341
|
-
if (st.ignition) engine?.start(at);
|
|
50834
|
+
if (st.ignition && driving?.systems.canCrank() !== false) engine?.start(at);
|
|
49342
50835
|
else engine?.stop(at);
|
|
49343
50836
|
}
|
|
49344
50837
|
if (event.command === "gearbox") {
|
|
@@ -49357,7 +50850,7 @@ var GameVehiclesThree = (() => {
|
|
|
49357
50850
|
rig.vehicle?.reset();
|
|
49358
50851
|
stopEngine();
|
|
49359
50852
|
engine = createVehicleSound(host.audio, { sounds });
|
|
49360
|
-
host.bench?.sheet?.({ kicker: text.name, title: fillText(text.log.drive, name(settings.vehicle)), body: text.cabin.keys });
|
|
50853
|
+
host.bench?.sheet?.({ kicker: text.name, title: fillText(text.log.drive, name(settings.vehicle)), body: `${text.cabin.keys} \xB7 ${sysText.keys} \xB7 ${sysText.bodyKeys}` });
|
|
49361
50854
|
host.log(fillText(text.log.drive, name(settings.vehicle)));
|
|
49362
50855
|
};
|
|
49363
50856
|
const onOff = (on) => on ? text.cabin.on : text.cabin.off;
|
|
@@ -49386,19 +50879,156 @@ var GameVehiclesThree = (() => {
|
|
|
49386
50879
|
return `${c.alarm}: ${c.alarmStates[st.alarm]}`;
|
|
49387
50880
|
case "radio":
|
|
49388
50881
|
case "radio_source":
|
|
49389
|
-
|
|
50882
|
+
case "radio_track":
|
|
50883
|
+
return `${c.radio}: ${st.radio.on ? `${c.sources[st.radio.source]} \xB7 ${fillText(sysText.track, st.radio.track + 1)}` : c.off}`;
|
|
49390
50884
|
case "indicator_left":
|
|
49391
50885
|
case "indicator_right":
|
|
49392
50886
|
case "hazard":
|
|
49393
50887
|
return `${c.indicator}: ${c.indicators[st.indicator]}`;
|
|
49394
50888
|
case "wipers":
|
|
49395
|
-
return `${c.wipers}: ${
|
|
50889
|
+
return `${c.wipers}: ${sysText.wiperModes[st.wipers]}`;
|
|
50890
|
+
case "drive_profile":
|
|
50891
|
+
return `${sysText.profile}: ${sysText.profiles[st.profile]}`;
|
|
50892
|
+
case "traction_control":
|
|
50893
|
+
return `${sysText.traction}: ${onOff(st.tractionControl)}`;
|
|
50894
|
+
case "abs":
|
|
50895
|
+
return `${sysText.abs}: ${onOff(st.abs)}`;
|
|
50896
|
+
case "cruise":
|
|
50897
|
+
return st.cruise.on ? fillText(sysText.cruiseSet, Math.round(st.cruise.speed * 3.6)) : `${sysText.cruise}: ${c.off}`;
|
|
50898
|
+
case "climate":
|
|
50899
|
+
return `${sysText.climate}: ${onOff(st.climate.on)}`;
|
|
50900
|
+
case "demist":
|
|
50901
|
+
return `${sysText.demist}: ${onOff(st.climate.demist)}`;
|
|
49396
50902
|
case "seatbelt":
|
|
49397
50903
|
return `${c.seatbelt}: ${onOff(st.seatbelt)}`;
|
|
50904
|
+
case "siren":
|
|
50905
|
+
return `${sysText.siren}: ${sysText.sirenModes[st.siren]}`;
|
|
50906
|
+
case "beacon":
|
|
50907
|
+
return `${sysText.beacon}: ${onOff(st.beacon)}`;
|
|
50908
|
+
case "glovebox":
|
|
50909
|
+
return `${sysText.glovebox}: ${sysText.lid[st.glovebox ? "open" : "shut"]}`;
|
|
49398
50910
|
default:
|
|
49399
50911
|
return null;
|
|
49400
50912
|
}
|
|
49401
50913
|
};
|
|
50914
|
+
const itemName = (id) => options.itemName?.(id) ?? id;
|
|
50915
|
+
const listCompartment = (cockpit, id) => {
|
|
50916
|
+
const label = sysText.storage.names[id];
|
|
50917
|
+
const data = { vehicle: settings.vehicle, compartment: id };
|
|
50918
|
+
if (!cockpit.storage.compartments.some((c) => c.id === id)) return host?.log(fillText(sysText.storage.none, label.toLowerCase()), data, "proving_storage");
|
|
50919
|
+
if (!cockpit.storage.reachable(id, cockpit.access())) return host?.log(fillText(sysText.storage.shut, label), data, "proving_storage");
|
|
50920
|
+
const stacks = cockpit.storage.contents(id).filter((x) => x !== null);
|
|
50921
|
+
if (!stacks.length) return host?.log(fillText(sysText.storage.empty, label), data, "proving_storage");
|
|
50922
|
+
host?.log(fillText(sysText.storage.list, label, cockpit.storage.loadKg(id).toFixed(1), stacks.map((x) => x.count > 1 ? `${x.count}\xD7 ${itemName(x.itemId)}` : itemName(x.itemId)).join(", ")), { ...data, stacks: stacks.map((x) => ({ item: x.itemId, count: x.count })) }, "proving_storage");
|
|
50923
|
+
};
|
|
50924
|
+
const systemsAction = (id) => {
|
|
50925
|
+
if (id === "take_key") {
|
|
50926
|
+
hasKey = !hasKey;
|
|
50927
|
+
if (driving) stopDriving();
|
|
50928
|
+
startDriving();
|
|
50929
|
+
host?.log(hasKey ? sysText.keyBack : sysText.keyTaken, { vehicle: settings.vehicle, hasKey }, "proving_system");
|
|
50930
|
+
return;
|
|
50931
|
+
}
|
|
50932
|
+
if (id === "cold_rain") {
|
|
50933
|
+
weather = weather.rain > 0 ? { outsideC: 25, rain: 0 } : { outsideC: 8, rain: 1 };
|
|
50934
|
+
if (driving) driving.weather = { ...weather };
|
|
50935
|
+
setSurface(weather.rain > 0 ? "wet_asphalt" : "dry_asphalt");
|
|
50936
|
+
host?.log(weather.rain > 0 ? sysText.fog.weather : sysText.fog.fair, { vehicle: settings.vehicle, ...weather }, "proving_system");
|
|
50937
|
+
return;
|
|
50938
|
+
}
|
|
50939
|
+
if (!driving) startDriving();
|
|
50940
|
+
const cockpit = driving;
|
|
50941
|
+
if (!cockpit) return;
|
|
50942
|
+
const d = cockpit.driver;
|
|
50943
|
+
const done = (key) => host?.log(sysText.done[key], { vehicle: settings.vehicle, action: key }, "proving_system");
|
|
50944
|
+
switch (id) {
|
|
50945
|
+
case "puncture": {
|
|
50946
|
+
const tyres = d.spec.wheels.map((_, i) => d.condition.tyres?.[i] ?? 1);
|
|
50947
|
+
tyres[0] = 0;
|
|
50948
|
+
d.condition = { ...d.condition, tyres };
|
|
50949
|
+
return done("puncture");
|
|
50950
|
+
}
|
|
50951
|
+
case "fit_spare": {
|
|
50952
|
+
const flat = d.spec.wheels.findIndex((_, i) => (d.condition.tyres?.[i] ?? 1) < 0.2);
|
|
50953
|
+
const event = cockpit.systems.fitSpare(d, Math.max(0, flat));
|
|
50954
|
+
host?.log(sysText.events[event.type], { vehicle: settings.vehicle, ...event }, "proving_system");
|
|
50955
|
+
return;
|
|
50956
|
+
}
|
|
50957
|
+
case "refuel":
|
|
50958
|
+
d.refuel(d.spec.tank.capacity);
|
|
50959
|
+
return done("refuel");
|
|
50960
|
+
case "empty_tank":
|
|
50961
|
+
d.state.fuel = Math.min(d.state.fuel, d.spec.tank.capacity * 0.04);
|
|
50962
|
+
return done("empty_tank");
|
|
50963
|
+
case "drain_battery":
|
|
50964
|
+
cockpit.systems.charge(-(cockpit.systems.state.charge - 0.15));
|
|
50965
|
+
return done("drain_battery");
|
|
50966
|
+
case "jump_start":
|
|
50967
|
+
cockpit.systems.charge(1);
|
|
50968
|
+
return done("jump_start");
|
|
50969
|
+
case "break_radiator":
|
|
50970
|
+
cockpit.radiator = 0.05;
|
|
50971
|
+
return done("break_radiator");
|
|
50972
|
+
case "remote_lock":
|
|
50973
|
+
case "remote_unlock": {
|
|
50974
|
+
const lock = id === "remote_lock";
|
|
50975
|
+
cockpit.body?.lock(lock);
|
|
50976
|
+
cockpit.controls.state.alarm = lock ? "armed" : "off";
|
|
50977
|
+
host?.audio?.play?.({ sound: "alarm_chirp", position: [car?.built.group.position.x ?? 0, 1, car?.built.group.position.z ?? 0] });
|
|
50978
|
+
host?.log(sysText.remote[lock ? "locked" : "unlocked"], { vehicle: settings.vehicle, locked: lock }, "proving_system");
|
|
50979
|
+
return;
|
|
50980
|
+
}
|
|
50981
|
+
case "crash_wall": {
|
|
50982
|
+
const g = car?.built.group;
|
|
50983
|
+
if (!g || !host) return;
|
|
50984
|
+
crashes ?? (crashes = createProvingCrash(host, options.occupant));
|
|
50985
|
+
const speed = d.state.u;
|
|
50986
|
+
const ejection = crashes.crash({ car: { position: g.position, rotationY: g.rotation.y }, u: d.state.u, w: d.state.w, belted: cockpit.controls.state.seatbelt, destructible: cockpit.destructible });
|
|
50987
|
+
d.state.u = d.state.w = d.state.yawRate = 0;
|
|
50988
|
+
const kmh2 = Math.round(Math.abs(speed) * 3.6);
|
|
50989
|
+
const belted = cockpit.controls.state.seatbelt;
|
|
50990
|
+
host.log(ejection ? fillText(sysText.crash.ejected, kmh2, sysText.crash.exits[ejection.exit]) : fillText(belted ? sysText.crash.stayed : sysText.crash.mild, kmh2), { vehicle: settings.vehicle, kmh: kmh2, belted: cockpit.controls.state.seatbelt, ejection }, "proving_crash");
|
|
50991
|
+
return;
|
|
50992
|
+
}
|
|
50993
|
+
case "park_behind": {
|
|
50994
|
+
const g = car?.built.group;
|
|
50995
|
+
if (!g || !host) return;
|
|
50996
|
+
parked?.remove();
|
|
50997
|
+
const back = (car?.built.length ?? 4.5) / 2 + 3 + 2.3;
|
|
50998
|
+
const at = [g.position.x - Math.sin(g.rotation.y) * back, 0, g.position.z - Math.cos(g.rotation.y) * back];
|
|
50999
|
+
const placed = host.addObject?.(options.parkedCar ?? "sedan", { position: at, rotationY: g.rotation.y });
|
|
51000
|
+
parked = placed ? { root: placed.root, remove: placed.remove } : null;
|
|
51001
|
+
host.log(placed ? sysText.parking.placed : sysText.parking.none, { vehicle: settings.vehicle }, "proving_system");
|
|
51002
|
+
return;
|
|
51003
|
+
}
|
|
51004
|
+
case "glovebox_contents":
|
|
51005
|
+
return listCompartment(cockpit, "glovebox");
|
|
51006
|
+
case "trunk_contents":
|
|
51007
|
+
return listCompartment(cockpit, "trunk");
|
|
51008
|
+
case "take_from_trunk": {
|
|
51009
|
+
const storage = cockpit.storage;
|
|
51010
|
+
if (!storage.compartments.some((c) => c.id === "trunk")) return listCompartment(cockpit, "trunk");
|
|
51011
|
+
const slot = storage.contents("trunk").findIndex((x) => x !== null);
|
|
51012
|
+
if (slot < 0 || !storage.reachable("trunk", cockpit.access())) return listCompartment(cockpit, "trunk");
|
|
51013
|
+
const stack = storage.take("trunk", slot, cockpit.access());
|
|
51014
|
+
if (!stack) return;
|
|
51015
|
+
const g = car?.built.group;
|
|
51016
|
+
const back = (car?.built.length ?? 4.5) / 2 + 0.8;
|
|
51017
|
+
const placed = g ? host?.addObject?.(stack.itemId, { position: [g.position.x - Math.sin(g.rotation.y) * back, 0, g.position.z - Math.cos(g.rotation.y) * back] }) : null;
|
|
51018
|
+
host?.log(fillText(placed ? sysText.storage.taken : sysText.storage.ground, itemName(stack.itemId)), { vehicle: settings.vehicle, item: stack.itemId, count: stack.count, placed: !!placed }, "proving_storage");
|
|
51019
|
+
return;
|
|
51020
|
+
}
|
|
51021
|
+
case "force_door": {
|
|
51022
|
+
const body = cockpit.body;
|
|
51023
|
+
if (!body) return;
|
|
51024
|
+
if (body.locked) body.lock(false);
|
|
51025
|
+
body.toggle("door_front_left");
|
|
51026
|
+
if (cockpit.controls.state.alarm === "armed") cockpit.controls.state.alarm = "ringing";
|
|
51027
|
+
host?.log(sysText.remote.forced, { vehicle: settings.vehicle, alarm: cockpit.controls.state.alarm }, "proving_system");
|
|
51028
|
+
return;
|
|
51029
|
+
}
|
|
51030
|
+
}
|
|
51031
|
+
};
|
|
49402
51032
|
const gearName = (gear) => gear < 0 ? "R" : gear === 0 ? "N" : String(gear);
|
|
49403
51033
|
const onChange = (change) => {
|
|
49404
51034
|
if (change.kind === "layer") {
|
|
@@ -49407,6 +51037,7 @@ var GameVehiclesThree = (() => {
|
|
|
49407
51037
|
}
|
|
49408
51038
|
if (change.kind === "action") {
|
|
49409
51039
|
if (change.id === "drive") return driving ? stopDriving() : startDriving();
|
|
51040
|
+
if (change.id in sysText.actions) return systemsAction(change.id);
|
|
49410
51041
|
if (change.id === "run_test" || change.id === "run_all" || change.id === "reverse_park") stopDriving();
|
|
49411
51042
|
if (change.id === "run_test") {
|
|
49412
51043
|
queue = [];
|
|
@@ -49453,6 +51084,12 @@ var GameVehiclesThree = (() => {
|
|
|
49453
51084
|
settings.camera = String(change.value);
|
|
49454
51085
|
applyCamera();
|
|
49455
51086
|
break;
|
|
51087
|
+
case "seat_forward":
|
|
51088
|
+
case "seat_height":
|
|
51089
|
+
case "mirror_left":
|
|
51090
|
+
case "mirror_right":
|
|
51091
|
+
adjust[ADJUST_KEYS[change.id]] = Number(change.value);
|
|
51092
|
+
break;
|
|
49456
51093
|
case "time_scale":
|
|
49457
51094
|
settings.timeScale = Number(change.value);
|
|
49458
51095
|
break;
|
|
@@ -49487,6 +51124,13 @@ var GameVehiclesThree = (() => {
|
|
|
49487
51124
|
const d = driving;
|
|
49488
51125
|
d.step(dt);
|
|
49489
51126
|
if (!driving) return;
|
|
51127
|
+
if (!misted && d.fog.state.fog > 0.6) {
|
|
51128
|
+
misted = true;
|
|
51129
|
+
host.log(sysText.fog.misted, { vehicle: settings.vehicle, fog: +d.fog.state.fog.toFixed(2), humidity: +d.fog.state.humidity.toFixed(2) }, "proving_system");
|
|
51130
|
+
} else if (misted && d.fog.state.fog < 0.1) {
|
|
51131
|
+
misted = false;
|
|
51132
|
+
host.log(sysText.fog.clear, { vehicle: settings.vehicle }, "proving_system");
|
|
51133
|
+
}
|
|
49490
51134
|
pose(d.driver.state, d.driver.state.steerAngle);
|
|
49491
51135
|
speed = d.driver.state.u;
|
|
49492
51136
|
steer = d.driver.state.steerAngle;
|
|
@@ -49502,7 +51146,7 @@ var GameVehiclesThree = (() => {
|
|
|
49502
51146
|
if (car) engine?.update({ dt, position: [car.built.group.position.x, 0.5, car.built.group.position.z], speed, throttle: run ? 1 : driving?.throttle ?? 0, rpm: driving ? driving.driver.state.rpm : void 0 });
|
|
49503
51147
|
const f = frameOf(speed);
|
|
49504
51148
|
if (f && rig.vehicle && settings.camera !== "room") rig.vehicle.update(rig.camera, f, dt);
|
|
49505
|
-
if (f && rig.vehicle) for (const m of rig.mirrors) rig.vehicle.placeMirror(m.camera, m.pose, f);
|
|
51149
|
+
if (f && rig.vehicle) for (const m of rig.mirrors) rig.vehicle.placeMirror(m.camera, aimed(m.pose), f);
|
|
49506
51150
|
void steer;
|
|
49507
51151
|
const key = `${host.bench?.layer("mirrors")}|${host.bench?.layer("reverse_camera")}`;
|
|
49508
51152
|
if (key !== mirrorKey) {
|
|
@@ -49521,6 +51165,10 @@ var GameVehiclesThree = (() => {
|
|
|
49521
51165
|
const speedNow = () => Math.abs(run?.driver.state.u ?? driving?.driver.state.u ?? parking?.driver.state.u ?? 0) * 3.6;
|
|
49522
51166
|
const counts = (verdict) => certificateOf(settings.vehicle)?.results.filter((r) => r.verdict === verdict).length ?? 0;
|
|
49523
51167
|
const teardown = () => {
|
|
51168
|
+
crashes?.dispose();
|
|
51169
|
+
crashes = null;
|
|
51170
|
+
parked?.remove();
|
|
51171
|
+
parked = null;
|
|
49524
51172
|
stopDriving();
|
|
49525
51173
|
stopEngine();
|
|
49526
51174
|
for (const m of rig.mirrors) m.remove();
|
|
@@ -49551,9 +51199,14 @@ var GameVehiclesThree = (() => {
|
|
|
49551
51199
|
{ kind: "choice", id: "vehicle", name: text.controls.vehicle, hint: text.hints.vehicle, options: vehicles.map((id) => ({ id, name: name(id) })), default: settings.vehicle },
|
|
49552
51200
|
{ kind: "choice", id: "test", name: text.controls.test, hint: text.hints.test, options: measured.map((id) => ({ id, name: text.tests[id] ?? id })), default: settings.test },
|
|
49553
51201
|
{ kind: "choice", id: "camera", name: text.controls.camera, hint: text.hints.camera, options: ["room", "chase", "cockpit", "hood"].map((id) => ({ id, name: text.cameras[id] })), default: settings.camera },
|
|
51202
|
+
{ kind: "number", id: "seat_forward", name: sysText.adjust.seat_forward, min: -0.2, max: 0.2, step: 0.02, default: 0 },
|
|
51203
|
+
{ kind: "number", id: "seat_height", name: sysText.adjust.seat_height, min: -0.1, max: 0.1, step: 0.01, default: 0 },
|
|
51204
|
+
{ kind: "number", id: "mirror_left", name: sysText.adjust.mirror_left, min: -0.3, max: 0.3, step: 0.02, default: 0 },
|
|
51205
|
+
{ kind: "number", id: "mirror_right", name: sysText.adjust.mirror_right, min: -0.3, max: 0.3, step: 0.02, default: 0 },
|
|
49554
51206
|
{ kind: "number", id: "time_scale", name: text.controls.time_scale, hint: text.hints.time_scale, min: 1, max: 20, step: 1, default: settings.timeScale },
|
|
49555
51207
|
{ kind: "choice", id: "visual_check", name: text.controls.visual_check, hint: text.hints.visual_check, options: VISUAL_CHECKS.map((id) => ({ id, name: text.tests[id] ?? id })), default: settings.visual },
|
|
49556
51208
|
{ kind: "action", id: "drive", name: text.actions.drive },
|
|
51209
|
+
...Object.keys(sysText.actions).map((id) => ({ kind: "action", id, name: sysText.actions[id] })),
|
|
49557
51210
|
{ kind: "choice", id: "gearbox", name: text.controls.gearbox, hint: text.hints.gearbox, options: ["automatic", "manual"].map((id) => ({ id, name: text.gearbox[id] })), default: gearbox },
|
|
49558
51211
|
{ kind: "action", id: "run_test", name: text.actions.run_test },
|
|
49559
51212
|
{ kind: "action", id: "run_all", name: text.actions.run_all },
|
|
@@ -49573,6 +51226,7 @@ var GameVehiclesThree = (() => {
|
|
|
49573
51226
|
{ id: "gear", name: text.metrics.gear, read: () => driving?.driver.state.gear ?? run?.driver.state.gear ?? 0 },
|
|
49574
51227
|
{ id: "rpm", name: text.metrics.rpm, unit: "rpm", digits: 0, read: () => driving?.driver.state.rpm ?? run?.driver.state.rpm ?? 0 },
|
|
49575
51228
|
{ id: "time", name: text.metrics.time, unit: "s", digits: 1, read: () => run?.time ?? 0 },
|
|
51229
|
+
{ id: "fog", name: sysText.fog.metric, unit: "%", digits: 0, read: () => (driving?.fog.state.fog ?? 0) * 100 },
|
|
49576
51230
|
{ id: "value", name: text.metrics.value, digits: 1, read: () => run ? run.trace[run.trace.length - 1]?.[1] ?? 0 : 0 },
|
|
49577
51231
|
{ id: "passed", name: text.metrics.passed, read: () => counts("pass") },
|
|
49578
51232
|
{ id: "failed", name: text.metrics.failed, read: () => counts("fail") },
|
|
@@ -49587,6 +51241,8 @@ var GameVehiclesThree = (() => {
|
|
|
49587
51241
|
rig.vehicle = createVehicleCamera(three);
|
|
49588
51242
|
lent.audio?.register?.(LIBRARY_BANK);
|
|
49589
51243
|
lent.audio?.register?.(CABIN_BANK);
|
|
51244
|
+
lent.audio?.register?.(VEHICLE_SOUND_BANK);
|
|
51245
|
+
lent.audio?.register?.(RADIO_BANK);
|
|
49590
51246
|
const stopChange = lent.bench?.onChange(onChange);
|
|
49591
51247
|
const stopFrame = lent.onFrame(frame);
|
|
49592
51248
|
const stopClear = lent.onClear?.(() => {
|