@adatechnology/game-destruction-three 0.7.1 → 0.7.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.global.js +1007 -366
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +2 -48
- package/dist/index.js.map +1 -1
- package/package.json +6 -6
package/dist/index.global.js
CHANGED
|
@@ -1361,77 +1361,77 @@ var GameDestructionThree = (() => {
|
|
|
1361
1361
|
}));
|
|
1362
1362
|
}
|
|
1363
1363
|
function spawnPuff(pool, random, init) {
|
|
1364
|
-
const
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
return
|
|
1394
|
-
}
|
|
1395
|
-
function ageOrKeep2(
|
|
1396
|
-
|
|
1397
|
-
return
|
|
1398
|
-
}
|
|
1399
|
-
function moveOnRing(
|
|
1364
|
+
const puff3 = pool.acquire();
|
|
1365
|
+
puff3.x = init.x ?? 0;
|
|
1366
|
+
puff3.y = init.y ?? 0;
|
|
1367
|
+
puff3.z = init.z ?? 0;
|
|
1368
|
+
puff3.vx = init.vx ?? 0;
|
|
1369
|
+
puff3.vy = init.vy ?? 0;
|
|
1370
|
+
puff3.vz = init.vz ?? 0;
|
|
1371
|
+
puff3.s0 = init.s0 ?? 0.2;
|
|
1372
|
+
puff3.s1 = init.s1 ?? 1;
|
|
1373
|
+
puff3.sg = init.sg ?? 0.1;
|
|
1374
|
+
puff3.gk = init.gk ?? 6;
|
|
1375
|
+
puff3.life = init.life ?? 3;
|
|
1376
|
+
puff3.t = 0;
|
|
1377
|
+
puff3.h0 = init.h0 ?? 0;
|
|
1378
|
+
puff3.hl = init.hl ?? 0.4;
|
|
1379
|
+
puff3.drag = init.drag ?? 3;
|
|
1380
|
+
puff3.buoy = init.buoy ?? 0.5;
|
|
1381
|
+
puff3.grav = init.grav ?? 0;
|
|
1382
|
+
puff3.kind = init.kind ?? 0;
|
|
1383
|
+
puff3.seed = random.next();
|
|
1384
|
+
puff3.wind = init.wind ?? 1;
|
|
1385
|
+
puff3.color = init.color ?? SMOKE_COLORS.grey;
|
|
1386
|
+
puff3.ring = init.ring ?? null;
|
|
1387
|
+
puff3.ph = init.ph ?? 0;
|
|
1388
|
+
puff3.th = init.th ?? 0;
|
|
1389
|
+
puff3.rng = random;
|
|
1390
|
+
puff3.age = 0;
|
|
1391
|
+
puff3.heat = 0;
|
|
1392
|
+
puff3.size = 0;
|
|
1393
|
+
return puff3;
|
|
1394
|
+
}
|
|
1395
|
+
function ageOrKeep2(puff3, dt) {
|
|
1396
|
+
puff3.t += dt;
|
|
1397
|
+
return puff3.t < puff3.life;
|
|
1398
|
+
}
|
|
1399
|
+
function moveOnRing(puff3, ring2, wind) {
|
|
1400
1400
|
const ringTime = ring2.t;
|
|
1401
1401
|
const centerY = ring2.y0 + ring2.rise * (1 - Math.exp(-ringTime * ring2.rk));
|
|
1402
1402
|
const majorRadius = ring2.R0 + (ring2.R1 - ring2.R0) * (1 - Math.exp(-ringTime * 1.6));
|
|
1403
|
-
const theta =
|
|
1403
|
+
const theta = puff3.th + ringTime * ring2.roll;
|
|
1404
1404
|
const minorRadius = ring2.r * (0.8 + 0.4 * Math.min(1, ringTime));
|
|
1405
1405
|
const radius = majorRadius + minorRadius * Math.cos(theta);
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
}
|
|
1410
|
-
function moveFree(
|
|
1411
|
-
const damping = Math.exp(-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
if (
|
|
1420
|
-
|
|
1421
|
-
if (
|
|
1406
|
+
puff3.x = ring2.x + Math.cos(puff3.ph) * radius + wind.x * ringTime * 0.6;
|
|
1407
|
+
puff3.z = ring2.z + Math.sin(puff3.ph) * radius + wind.z * ringTime * 0.6;
|
|
1408
|
+
puff3.y = centerY + minorRadius * Math.sin(theta);
|
|
1409
|
+
}
|
|
1410
|
+
function moveFree(puff3, dt, age, heat, wind) {
|
|
1411
|
+
const damping = Math.exp(-puff3.drag * dt);
|
|
1412
|
+
puff3.vx *= damping;
|
|
1413
|
+
puff3.vy *= damping;
|
|
1414
|
+
puff3.vz *= damping;
|
|
1415
|
+
puff3.vy += (puff3.buoy * (heat > 0 ? 1.6 : 1) - puff3.grav) * dt;
|
|
1416
|
+
puff3.x += (puff3.vx + wind.x * puff3.wind * age) * dt;
|
|
1417
|
+
puff3.y += puff3.vy * dt;
|
|
1418
|
+
puff3.z += (puff3.vz + wind.z * puff3.wind * age) * dt;
|
|
1419
|
+
if (puff3.y < puff3.s0 * FLOOR_FRACTION) {
|
|
1420
|
+
puff3.y = puff3.s0 * FLOOR_FRACTION;
|
|
1421
|
+
if (puff3.vy < 0) puff3.vy *= FLOOR_BOUNCE;
|
|
1422
1422
|
}
|
|
1423
1423
|
}
|
|
1424
1424
|
function updatePuffs(pool, dt, wind) {
|
|
1425
1425
|
pool.compact(ageOrKeep2, dt);
|
|
1426
|
-
for (const
|
|
1427
|
-
const age =
|
|
1428
|
-
const heat =
|
|
1429
|
-
if (
|
|
1430
|
-
else moveFree(
|
|
1431
|
-
const size =
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1426
|
+
for (const puff3 of pool.items) {
|
|
1427
|
+
const age = puff3.t / puff3.life;
|
|
1428
|
+
const heat = puff3.h0 > 0 ? puff3.h0 * Math.pow(Math.max(0, 1 - puff3.t / puff3.hl), 1.25) : 0;
|
|
1429
|
+
if (puff3.ring) moveOnRing(puff3, puff3.ring, wind);
|
|
1430
|
+
else moveFree(puff3, dt, age, heat, wind);
|
|
1431
|
+
const size = puff3.s0 + (puff3.s1 - puff3.s0) * (1 - Math.exp(-puff3.t * puff3.gk)) + puff3.sg * Math.min(puff3.t, GROWTH_CAP_SECONDS);
|
|
1432
|
+
puff3.size = size * Math.min(1, puff3.t * ARRIVAL_FRAME + ARRIVAL_BASE);
|
|
1433
|
+
puff3.age = age;
|
|
1434
|
+
puff3.heat = heat;
|
|
1435
1435
|
}
|
|
1436
1436
|
}
|
|
1437
1437
|
var GROUND_LIFT = 0.02;
|
|
@@ -1488,9 +1488,9 @@ var GameDestructionThree = (() => {
|
|
|
1488
1488
|
var HOT_GLOW_COLOR = [1, 0.45, 0.12];
|
|
1489
1489
|
function addPuff(core, random, init) {
|
|
1490
1490
|
core.spawned.puffs++;
|
|
1491
|
-
const
|
|
1492
|
-
core.trace?.puff?.(
|
|
1493
|
-
return
|
|
1491
|
+
const puff3 = spawnPuff(core.puffs, random, init);
|
|
1492
|
+
core.trace?.puff?.(puff3);
|
|
1493
|
+
return puff3;
|
|
1494
1494
|
}
|
|
1495
1495
|
function addSpark(core, init) {
|
|
1496
1496
|
core.spawned.sparks++;
|
|
@@ -1672,6 +1672,7 @@ var GameDestructionThree = (() => {
|
|
|
1672
1672
|
var neg = call("neg");
|
|
1673
1673
|
var abs = call("abs");
|
|
1674
1674
|
var sqrt = call("sqrt");
|
|
1675
|
+
var exp = call("exp");
|
|
1675
1676
|
var sin = call("sin");
|
|
1676
1677
|
var cos = call("cos");
|
|
1677
1678
|
var atan2 = call("atan2");
|
|
@@ -1717,10 +1718,12 @@ var GameDestructionThree = (() => {
|
|
|
1717
1718
|
var INDEX = { $: "index" };
|
|
1718
1719
|
var QUALITY = { $: "quality" };
|
|
1719
1720
|
var FRESH = { $: "fresh" };
|
|
1721
|
+
var DIRECTION = { $: "direction" };
|
|
1720
1722
|
var CAMERA_POSITION = { $: "cameraPosition" };
|
|
1721
1723
|
var burst = (system, count, spawn2) => ({ op: "burst", system, count, spawn: spawn2 });
|
|
1722
1724
|
var spawn = (system, options) => ({ op: "spawn", system, spawn: options });
|
|
1723
1725
|
var emit = (key, system, rate, options) => ({ op: "emit", key, system, rate, spawn: options });
|
|
1726
|
+
var mesh = (options) => ({ op: "mesh", spawn: options });
|
|
1724
1727
|
var debris = (options) => ({ op: "debris", spawn: options });
|
|
1725
1728
|
var decal = (...args) => ({ op: "decal", args });
|
|
1726
1729
|
var ring = (...args) => ({ op: "ring", args });
|
|
@@ -2732,6 +2735,241 @@ var GameDestructionThree = (() => {
|
|
|
2732
2735
|
)
|
|
2733
2736
|
]
|
|
2734
2737
|
};
|
|
2738
|
+
var SPOTS_X = [-3, 1, 5];
|
|
2739
|
+
var SPOTS_Z = [-1, -2.4, 0.4];
|
|
2740
|
+
var FOG_AND_ASH = {
|
|
2741
|
+
id: "fog_and_ash",
|
|
2742
|
+
pageId: "neblina",
|
|
2743
|
+
team: "world",
|
|
2744
|
+
budget: { particles: 120, lights: 1 },
|
|
2745
|
+
loop: 0,
|
|
2746
|
+
view: { eye: [3, 1.8, 7.5], target: [-3, 1.2, -1] },
|
|
2747
|
+
setup: [
|
|
2748
|
+
cue("fog", { density: 0.075 }),
|
|
2749
|
+
cue("lamp_cone", { visible: true }),
|
|
2750
|
+
cue("zombie_visible", { index: -1, visible: false }),
|
|
2751
|
+
repeat(
|
|
2752
|
+
SPOTS_X.length,
|
|
2753
|
+
set("turn", rnd(-0.6, 0.6)),
|
|
2754
|
+
behavior("walkers", "place", { index: INDEX, x: pick(SPOTS_X, INDEX), z: pick(SPOTS_Z, INDEX), facing: variable("turn") })
|
|
2755
|
+
)
|
|
2756
|
+
],
|
|
2757
|
+
timeline: [],
|
|
2758
|
+
tick: [
|
|
2759
|
+
emit("fog", "normal", 5, { p: [rnd(-14, 10), rnd(0.2, 1.1), rnd(-3, 8)], v: [rnd(0.15, 0.35), 0, rnd(-0.05, 0.05)], sp: 0, life: [9, 13], size: [3, 5], grow: 1.4, c0: 8227488, a: 0.13, fi: 0.35 }),
|
|
2760
|
+
emit("ash", "normal", 14, { p: [rnd(-10, 8), rnd(4, 6), rnd(-3, 7)], v: [rnd(0.1, 0.4), -0.35, rnd(-0.1, 0.1)], sp: [0.05, 0.15], life: [8, 12], size: [0.025, 0.04], c0: 10525328, a: 0.75, fi: 0.1, gnd: 1 })
|
|
2761
|
+
]
|
|
2762
|
+
};
|
|
2763
|
+
var RAIN_CAPACITY = 4e3;
|
|
2764
|
+
var FALL_SPEED = 15;
|
|
2765
|
+
var WIND_PER_FALL = 0.07;
|
|
2766
|
+
var STREAK_SLANT = 0.04;
|
|
2767
|
+
var STREAK_LENGTH = 0.6;
|
|
2768
|
+
var BOX_X = [-15, 15];
|
|
2769
|
+
var BOX_Z = [-6, 16];
|
|
2770
|
+
var START_HEIGHT = [0, 16];
|
|
2771
|
+
var REENTRY_HEIGHT = [14, 17];
|
|
2772
|
+
var SPLASH_CHANCE = 0.35;
|
|
2773
|
+
var SPLASH_RANGE = 12;
|
|
2774
|
+
var SPRITE_CHANCE = 0.5;
|
|
2775
|
+
var UP9 = [0, 1, 0];
|
|
2776
|
+
var WORKSHOP_PUDDLES = [
|
|
2777
|
+
[-1.5, 2.2, 1.6, 0.9],
|
|
2778
|
+
[3, 3.6, 1.1, 0.7],
|
|
2779
|
+
[-6, 3.2, 1.3, 0.8],
|
|
2780
|
+
[1.4, -2.2, 0.9, 0.5]
|
|
2781
|
+
];
|
|
2782
|
+
var inPuddle = (puddles, x, z) => puddles.some((p) => ((x - p[0]) / p[2]) ** 2 + ((z - p[1]) / p[3]) ** 2 < 1);
|
|
2783
|
+
var RainField = class {
|
|
2784
|
+
constructor(engine) {
|
|
2785
|
+
__publicField2(this, "engine", engine);
|
|
2786
|
+
__publicField2(this, "positions", new Float32Array(RAIN_CAPACITY * 6));
|
|
2787
|
+
__publicField2(this, "count", 0);
|
|
2788
|
+
__publicField2(this, "wind", 1);
|
|
2789
|
+
__publicField2(this, "on", false);
|
|
2790
|
+
__publicField2(this, "centerX", 0);
|
|
2791
|
+
__publicField2(this, "centerZ", 0);
|
|
2792
|
+
__publicField2(this, "puddles", WORKSHOP_PUDDLES);
|
|
2793
|
+
__publicField2(this, "puddleAt");
|
|
2794
|
+
}
|
|
2795
|
+
/** `initRain` (W321): `count` streaks (thinned by the quality), each drawn at a random place in the box. */
|
|
2796
|
+
init(count, wind) {
|
|
2797
|
+
const { random } = this.engine;
|
|
2798
|
+
this.count = Math.min(RAIN_CAPACITY, Math.round(count * this.engine.context.quality.mult));
|
|
2799
|
+
this.wind = wind;
|
|
2800
|
+
this.on = true;
|
|
2801
|
+
for (let index = 0; index < this.count; index++) {
|
|
2802
|
+
const offset = index * 6;
|
|
2803
|
+
const x = random.between(BOX_X[0], BOX_X[1]);
|
|
2804
|
+
const y = random.between(START_HEIGHT[0], START_HEIGHT[1]);
|
|
2805
|
+
const z = random.between(BOX_Z[0], BOX_Z[1]);
|
|
2806
|
+
this.set(offset, x, y, z);
|
|
2807
|
+
}
|
|
2808
|
+
}
|
|
2809
|
+
/**
|
|
2810
|
+
* What a game does with the field every frame: the box follows the camera (`centerX`, `centerZ`), the streaks thin or thicken to `count` (a new streak
|
|
2811
|
+
* starts at a random place of the box, as `init` draws it) and the wind slants them. The golden never calls it.
|
|
2812
|
+
*/
|
|
2813
|
+
drive(count, wind, centerX, centerZ) {
|
|
2814
|
+
const { random } = this.engine;
|
|
2815
|
+
const target = Math.max(0, Math.min(RAIN_CAPACITY, Math.round(count * this.engine.context.quality.mult)));
|
|
2816
|
+
this.wind = wind;
|
|
2817
|
+
this.centerX = centerX;
|
|
2818
|
+
this.centerZ = centerZ;
|
|
2819
|
+
this.on = target > 0;
|
|
2820
|
+
for (let index = this.count; index < target; index++) {
|
|
2821
|
+
this.set(index * 6, random.between(BOX_X[0], BOX_X[1]) + centerX, random.between(START_HEIGHT[0], START_HEIGHT[1]), random.between(BOX_Z[0], BOX_Z[1]) + centerZ);
|
|
2822
|
+
}
|
|
2823
|
+
this.count = target;
|
|
2824
|
+
}
|
|
2825
|
+
/** `updateRain` (W322-329). `camera` is where the eye is; `splash` lets the drops that land leave a splash. */
|
|
2826
|
+
update(dt, splash, camera2) {
|
|
2827
|
+
if (!this.on) return;
|
|
2828
|
+
const { random, context } = this.engine;
|
|
2829
|
+
const positions = this.positions;
|
|
2830
|
+
const fall = FALL_SPEED * dt;
|
|
2831
|
+
const slant = this.wind * fall * WIND_PER_FALL;
|
|
2832
|
+
const reach = SPLASH_RANGE / (1 + context.quality.level);
|
|
2833
|
+
for (let index = 0; index < this.count; index++) {
|
|
2834
|
+
const o = index * 6;
|
|
2835
|
+
positions[o] += slant;
|
|
2836
|
+
positions[o + 3] += slant;
|
|
2837
|
+
positions[o + 1] -= fall;
|
|
2838
|
+
positions[o + 4] -= fall;
|
|
2839
|
+
const ground = context.groundAt(positions[o], positions[o + 2]);
|
|
2840
|
+
if (positions[o + 4] < ground) {
|
|
2841
|
+
const x = positions[o];
|
|
2842
|
+
const z = positions[o + 2];
|
|
2843
|
+
if (splash && random.next() < SPLASH_CHANCE) {
|
|
2844
|
+
const distance = Math.hypot(x - camera2[0], z - camera2[2]);
|
|
2845
|
+
if (distance < reach) {
|
|
2846
|
+
if (random.next() < SPRITE_CHANCE) {
|
|
2847
|
+
this.engine.spawn("normal", { p: [x, ground + 0.01, z], dir: UP9, cone: 0.6, sp: [0.6, 1.3], life: [0.18, 0.3], size: 0.035, c0: 12110044, a: 0.6, g: 9.8, fi: 0 });
|
|
2848
|
+
}
|
|
2849
|
+
if (this.puddleAt ? this.puddleAt(x, z) : inPuddle(this.puddles, x, z)) {
|
|
2850
|
+
this.engine.ring([[x, ground + 0.012, z], 0.01, random.between(0.12, 0.25), random.between(0.4, 0.6), 6978192]);
|
|
2851
|
+
}
|
|
2852
|
+
}
|
|
2853
|
+
}
|
|
2854
|
+
const nx = random.between(BOX_X[0], BOX_X[1]) + this.centerX;
|
|
2855
|
+
const ny = random.between(REENTRY_HEIGHT[0], REENTRY_HEIGHT[1]);
|
|
2856
|
+
const nz = random.between(BOX_Z[0], BOX_Z[1]) + this.centerZ;
|
|
2857
|
+
this.set(o, nx, ny, nz);
|
|
2858
|
+
}
|
|
2859
|
+
}
|
|
2860
|
+
}
|
|
2861
|
+
/** `rain.visible = false; RN.on = false` (W440): the field stops; the streaks stay where they were. */
|
|
2862
|
+
clear() {
|
|
2863
|
+
this.on = false;
|
|
2864
|
+
}
|
|
2865
|
+
set(offset, x, y, z) {
|
|
2866
|
+
const positions = this.positions;
|
|
2867
|
+
positions[offset] = x;
|
|
2868
|
+
positions[offset + 1] = y;
|
|
2869
|
+
positions[offset + 2] = z;
|
|
2870
|
+
positions[offset + 3] = x + this.wind * STREAK_SLANT;
|
|
2871
|
+
positions[offset + 4] = y - STREAK_LENGTH;
|
|
2872
|
+
positions[offset + 5] = z;
|
|
2873
|
+
}
|
|
2874
|
+
};
|
|
2875
|
+
var DROPS = [900, 2200, 4e3];
|
|
2876
|
+
var SLANT = [0.3, 1.2, 4.5];
|
|
2877
|
+
var STORM = 2;
|
|
2878
|
+
var FLASH_STEPS = ite(lt(variable("flash"), 0.08), 1, ite(lt(variable("flash"), 0.16), 0.2, ite(lt(variable("flash"), 0.26), 0.8, 0)));
|
|
2879
|
+
var RAIN_AND_PUDDLES = {
|
|
2880
|
+
id: "rain_and_puddles",
|
|
2881
|
+
pageId: "chuva",
|
|
2882
|
+
team: "world",
|
|
2883
|
+
params: { id: "intensity", options: ["drizzle", "rain", "storm"], default: 1 },
|
|
2884
|
+
budget: { particles: 4e3, decals: 4 },
|
|
2885
|
+
loop: 0,
|
|
2886
|
+
view: { eye: [2, 2, 7], target: [-1, 0.6, 1] },
|
|
2887
|
+
setup: [
|
|
2888
|
+
cue("lamp_cone", { visible: true }),
|
|
2889
|
+
...WORKSHOP_PUDDLES.map(([x, z, radiusX, radiusZ]) => decal(x, 0, z, radiusX * 2, 790550, { grow: 0, life: 1e6, ar: radiusZ / radiusX }))
|
|
2890
|
+
],
|
|
2891
|
+
timeline: [
|
|
2892
|
+
behavior("rain", "init", { count: ite(eq(PARAM, 0), DROPS[0], ite(eq(PARAM, 1), DROPS[1], DROPS[2])), wind: ite(eq(PARAM, 0), SLANT[0], ite(eq(PARAM, 1), SLANT[1], SLANT[2])) }),
|
|
2893
|
+
set("nextStrike", rnd(2, 4)),
|
|
2894
|
+
set("flash", -1)
|
|
2895
|
+
],
|
|
2896
|
+
tick: [
|
|
2897
|
+
behavior("rain", "update", { dt: DELTA, splash: gt(PARAM, 0) }),
|
|
2898
|
+
when(eq(PARAM, STORM), [
|
|
2899
|
+
when(gt(TIME, variable("nextStrike")), [set("nextStrike", add(TIME, rnd(3.5, 6))), set("flash", 0)]),
|
|
2900
|
+
when(ge(variable("flash"), 0), [
|
|
2901
|
+
set("flash", add(variable("flash"), DELTA)),
|
|
2902
|
+
set("light", FLASH_STEPS),
|
|
2903
|
+
cue("lightning", { intensity: variable("light") }),
|
|
2904
|
+
screen({ max: { white: mul(variable("light"), 0.12) } }),
|
|
2905
|
+
when(gt(variable("flash"), 0.4), [set("flash", -1), cue("lightning", { intensity: 0 })])
|
|
2906
|
+
]),
|
|
2907
|
+
emit("sheet", "normal", 2.5, { p: [-12, 2.5, rnd(-1, 8)], box: [0, 2, 0], v: [7, -0.5, 0], sp: 0, life: [3, 4], size: [3, 5], grow: 1.3, c0: 9083568, a: 0.06, fi: 0.3 })
|
|
2908
|
+
])
|
|
2909
|
+
]
|
|
2910
|
+
};
|
|
2911
|
+
var CAR_ORIGIN2 = [5.6, 0, 0.8];
|
|
2912
|
+
var CAR_ROTATION2 = [0, -0.4, 0];
|
|
2913
|
+
var carPoint = (x, y, z) => localToWorld(CAR_ORIGIN2, CAR_ROTATION2, [x, y, z]);
|
|
2914
|
+
var carDirection = (from, to) => normalized([to[0] - from[0], to[1] - from[1], to[2] - from[2]]);
|
|
2915
|
+
var BEAM_FROM = carPoint(0, 0.74, 2.15);
|
|
2916
|
+
var BEAM_DIRECTION = carDirection(BEAM_FROM, carPoint(0, 0.74, 3.15));
|
|
2917
|
+
var BEAM_SIDE = [BEAM_DIRECTION[2], 0, -BEAM_DIRECTION[0]];
|
|
2918
|
+
var WALKERS = 6;
|
|
2919
|
+
var WALK_SPEED2 = 0.7;
|
|
2920
|
+
var DROPS2 = 1800;
|
|
2921
|
+
var SLANT2 = 0.8;
|
|
2922
|
+
var startWalking = [
|
|
2923
|
+
set("spot", query("car", "point", rnd(-2, 2), 0, rnd(8, 18))),
|
|
2924
|
+
set("goal", query("car", "point", rnd(-0.6, 0.6), 0, 2.6)),
|
|
2925
|
+
behavior("walkers", "place", { index: INDEX, x: pick(variable("spot"), 0), z: pick(variable("spot"), 2), facing: 0 }),
|
|
2926
|
+
behavior("walkers", "walk", { index: INDEX, to: variable("goal"), speed: WALK_SPEED2 })
|
|
2927
|
+
];
|
|
2928
|
+
var HEADLIGHTS_IN_RAIN = {
|
|
2929
|
+
id: "headlights_in_rain",
|
|
2930
|
+
pageId: "farol",
|
|
2931
|
+
team: "vehicles",
|
|
2932
|
+
budget: { particles: 600, lights: 2 },
|
|
2933
|
+
loop: 0,
|
|
2934
|
+
view: { eye: [-2.5, 2, 5.5], target: [4, 1, 6] },
|
|
2935
|
+
setup: [
|
|
2936
|
+
cue("fog", { density: 0.05 }),
|
|
2937
|
+
cue("headlights", { on: true, intensity: 2.4, color: 16773584 }),
|
|
2938
|
+
behavior("rain", "init", { count: DROPS2, wind: SLANT2 }),
|
|
2939
|
+
repeat(WALKERS, ...startWalking)
|
|
2940
|
+
],
|
|
2941
|
+
timeline: [],
|
|
2942
|
+
tick: [
|
|
2943
|
+
behavior("rain", "update", { dt: DELTA, splash: true }),
|
|
2944
|
+
emit(
|
|
2945
|
+
"lit",
|
|
2946
|
+
"streak",
|
|
2947
|
+
600,
|
|
2948
|
+
local(
|
|
2949
|
+
"depth",
|
|
2950
|
+
rnd(1, 13),
|
|
2951
|
+
local(
|
|
2952
|
+
"spread",
|
|
2953
|
+
mul(variable("depth"), 0.33, sqrt(rand())),
|
|
2954
|
+
local(
|
|
2955
|
+
"turn",
|
|
2956
|
+
rnd(0, 6.283),
|
|
2957
|
+
local("base", vadd(BEAM_FROM, vscale(BEAM_DIRECTION, variable("depth")), vscale(BEAM_SIDE, mul(cos(variable("turn")), variable("spread")))), {
|
|
2958
|
+
p: vwith(variable("base"), 1, add(vy(variable("base")), mul(sin(variable("turn")), variable("spread"), 0.6))),
|
|
2959
|
+
v: [0.8, -14, 0],
|
|
2960
|
+
sp: 0,
|
|
2961
|
+
life: 0.06,
|
|
2962
|
+
len: 0.035,
|
|
2963
|
+
c0: 13622512,
|
|
2964
|
+
a: 0.9
|
|
2965
|
+
})
|
|
2966
|
+
)
|
|
2967
|
+
)
|
|
2968
|
+
)
|
|
2969
|
+
),
|
|
2970
|
+
repeat(WALKERS, when(not(query("walkers", "is_walking", INDEX)), startWalking))
|
|
2971
|
+
]
|
|
2972
|
+
};
|
|
2735
2973
|
var YAW = -Math.PI / 2;
|
|
2736
2974
|
var COS = Math.cos(YAW);
|
|
2737
2975
|
var SIN = Math.sin(YAW);
|
|
@@ -2759,10 +2997,6 @@ var GameDestructionThree = (() => {
|
|
|
2759
2997
|
fireLight(0, [vx(variable("contact")), 0.34, vz(variable("contact"))], 1.6, mul(TIME, 3))
|
|
2760
2998
|
]
|
|
2761
2999
|
};
|
|
2762
|
-
var CAR_ORIGIN2 = [5.6, 0, 0.8];
|
|
2763
|
-
var CAR_ROTATION2 = [0, -0.4, 0];
|
|
2764
|
-
var carPoint = (x, y, z) => localToWorld(CAR_ORIGIN2, CAR_ROTATION2, [x, y, z]);
|
|
2765
|
-
var carDirection = (from, to) => normalized([to[0] - from[0], to[1] - from[1], to[2] - from[2]]);
|
|
2766
3000
|
var HOOD = carPoint(0, 1.02, 1.4);
|
|
2767
3001
|
var EXHAUST = carPoint(0.5, 0.3, -2.2);
|
|
2768
3002
|
var EXHAUST_DIRECTION = carDirection(EXHAUST, carPoint(0.5, 0.3, -3));
|
|
@@ -2796,7 +3030,7 @@ var GameDestructionThree = (() => {
|
|
|
2796
3030
|
], [fireLightOff(0)])
|
|
2797
3031
|
]
|
|
2798
3032
|
};
|
|
2799
|
-
var
|
|
3033
|
+
var UP10 = [0, 1, 0];
|
|
2800
3034
|
var doorVelocity = (side) => {
|
|
2801
3035
|
const out = carPoint(side * 4, 3, 0.3);
|
|
2802
3036
|
const centre = carPoint(0, 0, 0.3);
|
|
@@ -2806,7 +3040,7 @@ var GameDestructionThree = (() => {
|
|
|
2806
3040
|
call2("explode", vadd(query("car", "position"), [0, 0.6, 0]), 1.8, 2759188),
|
|
2807
3041
|
cue("car_burnt"),
|
|
2808
3042
|
behavior("car", "launch", { rise: 4.5, spin: 0.9 }),
|
|
2809
|
-
repeat(scaled(30), debris({ p: vadd(query("car", "position"), [0, 1.3, 0]), dir:
|
|
3043
|
+
repeat(scaled(30), debris({ p: vadd(query("car", "position"), [0, 1.3, 0]), dir: UP10, cone: 1.3, sp: [2, 6], size: [0.06, 6e-3, 0.06], c: 11061464, life: 20 })),
|
|
2810
3044
|
debris({ p: carPoint(0, 1, 1.4), v: [rnd(-1, 1), 9, rnd(-1, 1)], sp: 0, size: [1.6, 0.06, 1.2], c: 3808536, spin: 6, life: 20, bounce: 0.2 }),
|
|
2811
3045
|
...[-1, 1].map((side) => debris({ p: carPoint(side * 0.95, 0.7, 0.3), v: doorVelocity(side), sp: 0, size: [0.06, 0.7, 1.1], c: 3808536, spin: 5, life: 20, bounce: 0.2 })),
|
|
2812
3046
|
debris({ p: carPoint(0.95, 0.38, 1.35), v: [3, 4, 2], sp: 0, size: [0.3, 0.76, 0.76], c: 1118481, spin: 8, life: 20, bounce: 0.4 })
|
|
@@ -2976,7 +3210,7 @@ var GameDestructionThree = (() => {
|
|
|
2976
3210
|
])
|
|
2977
3211
|
]
|
|
2978
3212
|
};
|
|
2979
|
-
var
|
|
3213
|
+
var WALKERS2 = 6;
|
|
2980
3214
|
var NEAR = 9;
|
|
2981
3215
|
var RANGE = 7;
|
|
2982
3216
|
var RESTING_BPM = 70;
|
|
@@ -2992,7 +3226,7 @@ var GameDestructionThree = (() => {
|
|
|
2992
3226
|
setup: [
|
|
2993
3227
|
cue("zombie_visible", { index: -1, visible: false }),
|
|
2994
3228
|
repeat(
|
|
2995
|
-
|
|
3229
|
+
WALKERS2,
|
|
2996
3230
|
set("startX", rnd(-4, 4)),
|
|
2997
3231
|
set("startZ", sub(rnd(-4, -2), mul(INDEX, 0.6))),
|
|
2998
3232
|
behavior("walkers", "place", { index: INDEX, x: variable("startX"), z: variable("startZ"), facing: 0 }),
|
|
@@ -3002,7 +3236,7 @@ var GameDestructionThree = (() => {
|
|
|
3002
3236
|
timeline: [],
|
|
3003
3237
|
tick: [
|
|
3004
3238
|
set("nearest", 99),
|
|
3005
|
-
repeat(
|
|
3239
|
+
repeat(WALKERS2, set("nearest", min(variable("nearest"), vdist(walkerPoint, CAMERA_POSITION)))),
|
|
3006
3240
|
set("fear", clamp(div(sub(NEAR, variable("nearest")), RANGE), 0, 1)),
|
|
3007
3241
|
set("bpm", add(RESTING_BPM, mul(BPM_RISE, variable("fear")))),
|
|
3008
3242
|
when(lt(mod(div(mul(TIME, variable("bpm")), 60), 1), div(mul(DELTA, variable("bpm")), 60)), [screen({ set: { beat: add(0.4, mul(0.6, variable("fear"))) } })]),
|
|
@@ -3069,7 +3303,7 @@ var GameDestructionThree = (() => {
|
|
|
3069
3303
|
]
|
|
3070
3304
|
};
|
|
3071
3305
|
var FACING4 = [0, 0, 1];
|
|
3072
|
-
var
|
|
3306
|
+
var UP11 = [0, 1, 0];
|
|
3073
3307
|
var ORIGIN = [0, 0, 0];
|
|
3074
3308
|
var FORWARD4 = [0, 0, -1];
|
|
3075
3309
|
var IMPACT_MATERIALS = ["concrete", "metal", "wood", "glass", "flesh", "water"];
|
|
@@ -3199,12 +3433,157 @@ var GameDestructionThree = (() => {
|
|
|
3199
3433
|
team: "destruction",
|
|
3200
3434
|
budget: { particles: 20, debris: 8 },
|
|
3201
3435
|
loop: 2,
|
|
3202
|
-
timeline: [call2("chips", ORIGIN,
|
|
3436
|
+
timeline: [call2("chips", ORIGIN, UP11, 8, 0.9), call2("rust_at", ORIGIN, 6)]
|
|
3203
3437
|
}
|
|
3204
3438
|
];
|
|
3205
|
-
var
|
|
3439
|
+
var PI = Math.PI;
|
|
3440
|
+
var SMOKE = { color: 9079430, width: 10, height: 8, gravity: -0.08, drag: 2.2, growth: 2.1 };
|
|
3441
|
+
var FLASH_SECONDS = 0.055;
|
|
3442
|
+
var FLASH_RAMP = [0.6, 0.9];
|
|
3443
|
+
var FLASH_OPACITY = 0.95;
|
|
3444
|
+
var FLAME_COLORS = [16742946, 16760896, 13121050, 16773296];
|
|
3445
|
+
var FLAME_ADDITIVE = 3;
|
|
3446
|
+
var ORIGIN2 = [0, 0, 0];
|
|
3447
|
+
var SIZE = variable("size");
|
|
3448
|
+
var wide = (width) => mul(sub(rand(), 0.5), width);
|
|
3449
|
+
var puff2 = (point, velocity, world, radius, life, opacity) => mesh({
|
|
3450
|
+
shape: "sphere",
|
|
3451
|
+
p: point,
|
|
3452
|
+
v: velocity,
|
|
3453
|
+
wv: world,
|
|
3454
|
+
r: radius,
|
|
3455
|
+
seg: SMOKE.width,
|
|
3456
|
+
seg2: SMOKE.height,
|
|
3457
|
+
life,
|
|
3458
|
+
c0: SMOKE.color,
|
|
3459
|
+
a: opacity,
|
|
3460
|
+
fade: true,
|
|
3461
|
+
lit: true,
|
|
3462
|
+
g: SMOKE.gravity,
|
|
3463
|
+
drag: SMOKE.drag,
|
|
3464
|
+
grow: SMOKE.growth
|
|
3465
|
+
});
|
|
3466
|
+
var flameBit = (point, velocity, world, radius, life) => [
|
|
3467
|
+
set("bitPoint", point),
|
|
3468
|
+
set("bitVelocity", velocity),
|
|
3469
|
+
set("bitWorld", world),
|
|
3470
|
+
set("bitRadius", radius),
|
|
3471
|
+
set("bitLife", life),
|
|
3472
|
+
set("bitColour", floor(mul(rand(), FLAME_COLORS.length))),
|
|
3473
|
+
mesh({
|
|
3474
|
+
shape: "icosahedron",
|
|
3475
|
+
p: variable("bitPoint"),
|
|
3476
|
+
v: variable("bitVelocity"),
|
|
3477
|
+
wv: variable("bitWorld"),
|
|
3478
|
+
r: variable("bitRadius"),
|
|
3479
|
+
seg: 1,
|
|
3480
|
+
rot: [mul(rand(), 3), mul(rand(), 3), 0],
|
|
3481
|
+
spin: [3, 4, 2],
|
|
3482
|
+
life: variable("bitLife"),
|
|
3483
|
+
c0: pick(FLAME_COLORS, variable("bitColour")),
|
|
3484
|
+
add: eq(variable("bitColour"), FLAME_ADDITIVE),
|
|
3485
|
+
a: 0.9,
|
|
3486
|
+
fade: true,
|
|
3487
|
+
g: -1.4,
|
|
3488
|
+
drag: 1.4,
|
|
3489
|
+
grow: 2.2
|
|
3490
|
+
})
|
|
3491
|
+
];
|
|
3492
|
+
var flashPiece = (shape, radius, height, width, at3, rot, color) => mesh({ shape, r: radius, ...height === void 0 ? {} : { h: height }, seg: width, seg2: shape === "sphere" ? 8 : 1, p: ORIGIN2, at: at3, rot, roll: variable("roll"), ramp: FLASH_RAMP, life: FLASH_SECONDS, c0: color, a: FLASH_OPACITY, add: true });
|
|
3493
|
+
var MUZZLE_FLASH2 = {
|
|
3494
|
+
id: "viewmodel_muzzle_flash",
|
|
3495
|
+
pageId: "event:viewmodel_muzzle_flash",
|
|
3496
|
+
team: "weapons",
|
|
3497
|
+
budget: { particles: 12, lights: 1 },
|
|
3498
|
+
loop: 0.1,
|
|
3499
|
+
timeline: [
|
|
3500
|
+
set("angles", []),
|
|
3501
|
+
repeat(4, append("angles", add(div(mul(INDEX, PI), 2), mul(rand(), 0.6)))),
|
|
3502
|
+
set("roll", mul(rand(), PI)),
|
|
3503
|
+
flash(ORIGIN2, 16756832, mul(4, SIZE), FLASH_SECONDS, mul(2, SIZE), true, true),
|
|
3504
|
+
flashPiece("cone_open", mul(0.013, SIZE), mul(0.085, SIZE), 10, [mul(0.042, SIZE), 0, 0], [0, 0, -PI / 2], 16757575),
|
|
3505
|
+
repeat(
|
|
3506
|
+
4,
|
|
3507
|
+
set("angle", pick(variable("angles"), INDEX)),
|
|
3508
|
+
flashPiece(
|
|
3509
|
+
"cone",
|
|
3510
|
+
mul(5e-3, SIZE),
|
|
3511
|
+
mul(0.04, SIZE),
|
|
3512
|
+
6,
|
|
3513
|
+
[mul(0.012, SIZE), mul(cos(variable("angle")), 0.016, SIZE), mul(sin(variable("angle")), 0.016, SIZE)],
|
|
3514
|
+
[variable("angle"), 0, -PI / 2],
|
|
3515
|
+
16757575
|
|
3516
|
+
)
|
|
3517
|
+
),
|
|
3518
|
+
flashPiece("sphere", mul(0.016, SIZE), void 0, 12, [mul(8e-3, SIZE), 0, 0], [0, 0, 0], 16773568),
|
|
3519
|
+
repeat(
|
|
3520
|
+
6,
|
|
3521
|
+
puff2(
|
|
3522
|
+
ORIGIN2,
|
|
3523
|
+
[add(0.15, mul(rand(), 0.35)), add(0.03, mul(rand(), 0.12)), mul(sub(rand(), 0.5), 0.14)],
|
|
3524
|
+
[0, 0, 0],
|
|
3525
|
+
mul(0.013, SIZE),
|
|
3526
|
+
add(1.3, mul(rand(), 0.6)),
|
|
3527
|
+
0.45
|
|
3528
|
+
)
|
|
3529
|
+
)
|
|
3530
|
+
]
|
|
3531
|
+
};
|
|
3532
|
+
var SMOKE_PUFF = {
|
|
3533
|
+
id: "weapon_smoke_puff",
|
|
3534
|
+
pageId: "event:weapon_smoke_puff",
|
|
3535
|
+
team: "weapons",
|
|
3536
|
+
budget: { particles: 1 },
|
|
3537
|
+
loop: 0.1,
|
|
3538
|
+
timeline: [puff2(ORIGIN2, void 0, [variable("vx"), variable("vy"), variable("vz")], variable("radius"), variable("life"), variable("opacity"))]
|
|
3539
|
+
};
|
|
3540
|
+
var BACKBLAST = {
|
|
3541
|
+
id: "launcher_backblast",
|
|
3542
|
+
pageId: "event:launcher_backblast",
|
|
3543
|
+
team: "weapons",
|
|
3544
|
+
budget: { particles: 40 },
|
|
3545
|
+
loop: 0.1,
|
|
3546
|
+
timeline: [
|
|
3547
|
+
repeat(26, puff2(ORIGIN2, [neg(add(1.5, mul(rand(), 3))), 0, 0], [wide(1.4), wide(0.8), wide(1.4)], add(0.03, mul(rand(), 0.03)), add(1.8, mul(rand(), 1.4)), 0.5)),
|
|
3548
|
+
repeat(14, ...flameBit(ORIGIN2, [neg(add(2, mul(rand(), 2))), 0, 0], [wide(1), wide(0.6), wide(1)], 0.02, 0.25))
|
|
3549
|
+
]
|
|
3550
|
+
};
|
|
3551
|
+
var FLAME_JET = {
|
|
3552
|
+
id: "flame_jet",
|
|
3553
|
+
pageId: "event:flame_jet",
|
|
3554
|
+
team: "weapons",
|
|
3555
|
+
budget: { particles: 30 },
|
|
3556
|
+
loop: 0.1,
|
|
3557
|
+
timeline: [
|
|
3558
|
+
repeat(
|
|
3559
|
+
floor(mul(420, variable("dt"), variable("scale"))),
|
|
3560
|
+
set("speed", mul(add(2.2, mul(rand(), 1.1)), variable("scale"))),
|
|
3561
|
+
...flameBit(
|
|
3562
|
+
[mul(rand(), variable("speed"), min(variable("dt"), 0.3)), 0, 0],
|
|
3563
|
+
[variable("speed"), 0, 0],
|
|
3564
|
+
[wide(0.35), mul(sub(rand(), 0.3), 0.3), wide(0.35)],
|
|
3565
|
+
add(0.02, mul(rand(), 0.022)),
|
|
3566
|
+
add(0.4, mul(rand(), 0.35))
|
|
3567
|
+
)
|
|
3568
|
+
),
|
|
3569
|
+
when(lt(rand(), 0.5), [
|
|
3570
|
+
puff2([add(mul(1.1, variable("scale")), mul(rand(), 0.4)), 0, 0], void 0, [mul(vx(DIRECTION), 0.6), 0.35, mul(vz(DIRECTION), 0.6)], 0.03, 1.6, 0.4)
|
|
3571
|
+
])
|
|
3572
|
+
]
|
|
3573
|
+
};
|
|
3574
|
+
var VIEWMODEL_EFFECTS = [MUZZLE_FLASH2, SMOKE_PUFF, BACKBLAST, FLAME_JET];
|
|
3575
|
+
var aliasOf = (base, id, changes) => ({ ...base, id, pageId: `vehicle:${id}`, anchor: CAR_ORIGIN2, ...changes });
|
|
3576
|
+
var VEHICLE_EFFECTS = [
|
|
3577
|
+
/** The engine on fire: `engine_smoke` at its worst condition (black smoke, flames in the hood, a light). */
|
|
3578
|
+
aliasOf(ENGINE_SMOKE, "vehicle_fire", { params: { id: "condition", options: ["100", "60", "30", "10"], default: 3 }, loop: 12 }),
|
|
3579
|
+
/** The exhaust of a car under way: `engine_smoke` in the best condition, for half a second so a moving car asks again. */
|
|
3580
|
+
aliasOf(ENGINE_SMOKE, "vehicle_exhaust", { params: { id: "condition", options: ["100", "60", "30", "10"], default: 0 }, loop: 0.5 }),
|
|
3581
|
+
/** A hole in the tank: the page's own petrol leak (drips, pool, sparks, fire running to the tank). */
|
|
3582
|
+
aliasOf(FUEL_LEAK, "vehicle_leak", {})
|
|
3583
|
+
];
|
|
3584
|
+
var ALL_EFFECTS = [BLOOD_HIT, HEADSHOT, DISMEMBER, BLOATER_CLOUD, SCREAMER_SHRIEK, CORPSE_DECAY, REANIMATION, EYES_IN_FOG, MUZZLE_FLASH, IMPACT_BY_MATERIAL, PENETRATION, CASINGS_AND_MAGAZINE, MOLOTOV, GRENADE, EXPLOSIVE_BARREL, SHOPFRONT_GLASS, DOOR_STAGES, BUILDING_COLLAPSE, BLOCK_WALL, METAL_DOOR_EFFECT, IRON_RAILING, WOODEN_FENCE, HIT_POINT_BREAKAGE, PRESSURE_CYLINDERS, BUILDING_FIRE, RAIN_AND_PUDDLES, FOG_AND_ASH, SCRAPING_SPARKS, ENGINE_SMOKE, FUEL_LEAK, CAR_EXPLOSION, WINDSHIELD, HEADLIGHTS_IN_RAIN, DAMAGE_AND_BITE, INFECTION_PHASES, PANIC, BLOATER_BLINDNESS, CAMPFIRE, COUGH_AND_BREATH];
|
|
3206
3585
|
var WORKSHOP_EFFECTS = Object.fromEntries(ALL_EFFECTS.map((effect) => [effect.id, effect]));
|
|
3207
|
-
var GAME_EFFECTS = { ...WORKSHOP_EFFECTS, ...Object.fromEntries(EVENT_EFFECTS.map((effect) => [effect.id, effect])) };
|
|
3586
|
+
var GAME_EFFECTS = { ...WORKSHOP_EFFECTS, ...Object.fromEntries([...EVENT_EFFECTS, ...VIEWMODEL_EFFECTS, ...VEHICLE_EFFECTS].map((effect) => [effect.id, effect])) };
|
|
3208
3587
|
var LEHMER_MULTIPLIER = 16807;
|
|
3209
3588
|
var LEHMER_MODULUS = 2147483647;
|
|
3210
3589
|
var HASH_MIX = 2654435761;
|
|
@@ -3300,7 +3679,7 @@ var GameDestructionThree = (() => {
|
|
|
3300
3679
|
}
|
|
3301
3680
|
var COLUMNS = 6;
|
|
3302
3681
|
var ROWS = 5;
|
|
3303
|
-
var
|
|
3682
|
+
var ORIGIN3 = [-2.2, 0, 2.6];
|
|
3304
3683
|
var BLOCK_SIZE = [0.5, 0.44, 0.25];
|
|
3305
3684
|
var OBJECT_ID_DRAWS2 = 4;
|
|
3306
3685
|
var FLOOR2 = 0.13;
|
|
@@ -3343,7 +3722,7 @@ var GameDestructionThree = (() => {
|
|
|
3343
3722
|
const chipScale = random.between(0.8, 1.3) * scale;
|
|
3344
3723
|
for (let draw = 0; draw < OBJECT_ID_DRAWS2; draw++) random.next();
|
|
3345
3724
|
best.holes.push({ x: offsetX, y: offsetY, scale, chipTurn, chipScale });
|
|
3346
|
-
impact(host.engine, "concrete", [
|
|
3725
|
+
impact(host.engine, "concrete", [ORIGIN3[0] + x, y, ORIGIN3[2] + 0.13], [0, 0, 1], 0.8);
|
|
3347
3726
|
} else if (action === "collapse") {
|
|
3348
3727
|
const { x, y } = args;
|
|
3349
3728
|
for (const block of blocks) {
|
|
@@ -3393,7 +3772,7 @@ var GameDestructionThree = (() => {
|
|
|
3393
3772
|
}
|
|
3394
3773
|
};
|
|
3395
3774
|
}
|
|
3396
|
-
var
|
|
3775
|
+
var ORIGIN4 = [5.6, 0, 0.8];
|
|
3397
3776
|
var MAX_TILT = 0.25;
|
|
3398
3777
|
function createCarBehavior() {
|
|
3399
3778
|
let y = 0;
|
|
@@ -3425,8 +3804,13 @@ var GameDestructionThree = (() => {
|
|
|
3425
3804
|
}
|
|
3426
3805
|
}
|
|
3427
3806
|
},
|
|
3428
|
-
query(_host, name) {
|
|
3429
|
-
if (name === "position") return [
|
|
3807
|
+
query(_host, name, args) {
|
|
3808
|
+
if (name === "position") return [ORIGIN4[0], y, ORIGIN4[2]];
|
|
3809
|
+
if (name === "point") {
|
|
3810
|
+
const [x, py, z] = args;
|
|
3811
|
+
const point = carPoint(x, py, z);
|
|
3812
|
+
return [point[0], point[1] + y, point[2]];
|
|
3813
|
+
}
|
|
3430
3814
|
if (name === "roll") return roll;
|
|
3431
3815
|
throw new Error(`car: unknown query ${name}`);
|
|
3432
3816
|
},
|
|
@@ -3626,6 +4010,29 @@ var GameDestructionThree = (() => {
|
|
|
3626
4010
|
}
|
|
3627
4011
|
};
|
|
3628
4012
|
}
|
|
4013
|
+
function createRainBehavior() {
|
|
4014
|
+
return {
|
|
4015
|
+
reset() {
|
|
4016
|
+
},
|
|
4017
|
+
act(host, action, args) {
|
|
4018
|
+
const { engine, camera: camera2 } = host;
|
|
4019
|
+
if (action === "init") {
|
|
4020
|
+
const { count, wind } = args;
|
|
4021
|
+
engine.rain.init(count, wind);
|
|
4022
|
+
} else if (action === "update") {
|
|
4023
|
+
const { dt, splash } = args;
|
|
4024
|
+
engine.rain.update(dt, splash, camera2.position);
|
|
4025
|
+
}
|
|
4026
|
+
},
|
|
4027
|
+
query(host, name) {
|
|
4028
|
+
if (name === "count") return host.engine.rain.count;
|
|
4029
|
+
if (name === "on") return host.engine.rain.on;
|
|
4030
|
+
throw new Error(`rain: unknown query ${name}`);
|
|
4031
|
+
},
|
|
4032
|
+
update() {
|
|
4033
|
+
}
|
|
4034
|
+
};
|
|
4035
|
+
}
|
|
3629
4036
|
var WALKER_COUNT = 10;
|
|
3630
4037
|
var ARRIVAL_DISTANCE = 0.05;
|
|
3631
4038
|
var SWAY_AMPLITUDE = 0.04;
|
|
@@ -3691,7 +4098,8 @@ var GameDestructionThree = (() => {
|
|
|
3691
4098
|
blocks: () => createBlocksBehavior(),
|
|
3692
4099
|
plate: () => createPlateBehavior(),
|
|
3693
4100
|
cylinder: () => createCylinderBehavior(),
|
|
3694
|
-
car: () => createCarBehavior()
|
|
4101
|
+
car: () => createCarBehavior(),
|
|
4102
|
+
rain: () => createRainBehavior()
|
|
3695
4103
|
};
|
|
3696
4104
|
var NOOP = () => {
|
|
3697
4105
|
};
|
|
@@ -3762,6 +4170,8 @@ var GameDestructionThree = (() => {
|
|
|
3762
4170
|
return Math.abs(asNumber(first));
|
|
3763
4171
|
case "sqrt":
|
|
3764
4172
|
return Math.sqrt(asNumber(first));
|
|
4173
|
+
case "exp":
|
|
4174
|
+
return Math.exp(asNumber(first));
|
|
3765
4175
|
case "sin":
|
|
3766
4176
|
return Math.sin(asNumber(first));
|
|
3767
4177
|
case "cos":
|
|
@@ -3880,7 +4290,7 @@ var GameDestructionThree = (() => {
|
|
|
3880
4290
|
return evaluateCall(value.$, args.map((entry) => resolve(entry, context)));
|
|
3881
4291
|
}
|
|
3882
4292
|
}
|
|
3883
|
-
var
|
|
4293
|
+
var UP12 = [0, 1, 0];
|
|
3884
4294
|
var ZERO = [0, 0, 0];
|
|
3885
4295
|
var FULL_TURN_DRAWN = 6.283;
|
|
3886
4296
|
function scaledSizes(range, factor) {
|
|
@@ -3893,7 +4303,7 @@ var GameDestructionThree = (() => {
|
|
|
3893
4303
|
p: centre,
|
|
3894
4304
|
r: radius,
|
|
3895
4305
|
flat: true,
|
|
3896
|
-
dir: options.dir ??
|
|
4306
|
+
dir: options.dir ?? UP12,
|
|
3897
4307
|
cone: 0.35,
|
|
3898
4308
|
sp: [0.4, 1.4],
|
|
3899
4309
|
v: wind,
|
|
@@ -3910,7 +4320,7 @@ var GameDestructionThree = (() => {
|
|
|
3910
4320
|
p: centre,
|
|
3911
4321
|
r: radius * 0.6,
|
|
3912
4322
|
flat: true,
|
|
3913
|
-
dir:
|
|
4323
|
+
dir: UP12,
|
|
3914
4324
|
cone: 0.3,
|
|
3915
4325
|
sp: [0.3, 0.8],
|
|
3916
4326
|
life: [0.2, 0.4],
|
|
@@ -3925,14 +4335,14 @@ var GameDestructionThree = (() => {
|
|
|
3925
4335
|
if (engine.quality < 2) {
|
|
3926
4336
|
engine.emit(`${key}e`, "streak", 10 * factor, dt, () => {
|
|
3927
4337
|
const jitter = plus(wind, engine.random.between(-0.4, 0.4), 0, engine.random.between(-0.4, 0.4));
|
|
3928
|
-
return { p: centre, box: [radius, 0, radius], dir:
|
|
4338
|
+
return { p: centre, box: [radius, 0, radius], dir: UP12, cone: 0.5, sp: [1.5, 3.5], v: jitter, life: [0.8, 1.8], len: 0.03, c0: 16756816, c1: 6295552, g: -0.6, drag: 0.4 };
|
|
3929
4339
|
});
|
|
3930
4340
|
}
|
|
3931
4341
|
if (options.noSmoke) return;
|
|
3932
4342
|
engine.emit(`${key}s`, "normal", (options.smoke || 14) * factor, dt, () => ({
|
|
3933
4343
|
p: plus(centre, 0, 0.8 * sqrtFactor, 0),
|
|
3934
4344
|
r: radius * 0.7,
|
|
3935
|
-
dir:
|
|
4345
|
+
dir: UP12,
|
|
3936
4346
|
cone: 0.35,
|
|
3937
4347
|
sp: [0.6, 1.4],
|
|
3938
4348
|
v: wind,
|
|
@@ -3972,15 +4382,15 @@ var GameDestructionThree = (() => {
|
|
|
3972
4382
|
engine.screen.shake += 0.7 * scale;
|
|
3973
4383
|
engine.screen.white += 0.18 * scale;
|
|
3974
4384
|
engine.burst("add", 55 * scale, { p: point, r: 0.3 * scale, sp: [2, 7 * scale], drag: 4, life: [0.25, 0.6], size: [0.7 * scale, 1.4 * scale], grow: 1.7, c0: 16773296, c1: 10103304, fi: 0.04 });
|
|
3975
|
-
engine.burst("add", 28 * scale, { p: plus(point, 0, 0.3, 0), r: 0.3, dir:
|
|
4385
|
+
engine.burst("add", 28 * scale, { p: plus(point, 0, 0.3, 0), r: 0.3, dir: UP12, cone: 0.7, sp: [2, 5 * scale], drag: 1.5, life: [0.6, 1.1], size: [0.6 * scale, 1 * scale], grow: 1.3, c0: 16760928, c1: 5902853, g: -2, fi: 0.05 });
|
|
3976
4386
|
engine.ring([plus(point, 0, 0.05, 0), 0.3, 7 * scale, 0.55, 16767136]);
|
|
3977
4387
|
const toCamera = normalized([cameraPosition[0] - point[0], cameraPosition[1] - point[1], cameraPosition[2] - point[2]]);
|
|
3978
4388
|
engine.ring([plus(point, 0, 1, 0), 0.3, 5 * scale, 0.35, 16773328, toCamera]);
|
|
3979
|
-
engine.burst("normal", 32 * scale, { p: plus(point, 0, 0.6, 0), r: 0.8 * scale, dir:
|
|
4389
|
+
engine.burst("normal", 32 * scale, { p: plus(point, 0, 0.6, 0), r: 0.8 * scale, dir: UP12, cone: 1.1, sp: [1, 3], drag: 1.2, life: [3, 6], size: [1 * scale, 1.8 * scale], grow: 2.6, c0: 2828068, c1: 987155, a: 0.6, fi: 0.18, g: -0.35 });
|
|
3980
4390
|
ringOfDust(engine, point, scale);
|
|
3981
|
-
if (engine.quality < 2) engine.burst("streak", 44 * scale, { p: point, dir:
|
|
4391
|
+
if (engine.quality < 2) engine.burst("streak", 44 * scale, { p: point, dir: UP12, cone: 1.45, sp: [10, 26], life: [0.3, 0.7], len: 0.03, c0: 16760944, c1: 8396800, g: 9.8, gnd: 2 });
|
|
3982
4392
|
for (let index = 0; index < engine.scaled(16 * scale); index++) {
|
|
3983
|
-
engine.debrisPiece({ p: point, dir:
|
|
4393
|
+
engine.debrisPiece({ p: point, dir: UP12, cone: 1.2, sp: [3, 9], size: [0.12, 0.06, 0.1], k: [0.6, 1.6], c: chipColor || 2762274, life: 9 });
|
|
3984
4394
|
}
|
|
3985
4395
|
engine.decal([point[0], engine.context.groundAt(point[0], point[2]), point[2], 3 * scale, 657930, { grow: 0.15, life: 60 }]);
|
|
3986
4396
|
}
|
|
@@ -4123,6 +4533,7 @@ var GameDestructionThree = (() => {
|
|
|
4123
4533
|
if (!def) return;
|
|
4124
4534
|
this.schedule.clear();
|
|
4125
4535
|
this.variables.clear();
|
|
4536
|
+
for (const [name, value] of Object.entries(this.setup.values ?? {})) this.variables.set(name, value);
|
|
4126
4537
|
for (const behavior2 of this.deps.behaviors()) behavior2.reset(this.host);
|
|
4127
4538
|
this.time = 0;
|
|
4128
4539
|
this.within(() => {
|
|
@@ -4181,6 +4592,10 @@ var GameDestructionThree = (() => {
|
|
|
4181
4592
|
return engine.spawn(step.system, this.value(step.spawn));
|
|
4182
4593
|
case "emit":
|
|
4183
4594
|
return engine.emit(step.key, step.system, this.value(step.rate), this.dt, () => this.value(step.spawn));
|
|
4595
|
+
case "mesh": {
|
|
4596
|
+
engine.mesh(this.value(step.spawn));
|
|
4597
|
+
return;
|
|
4598
|
+
}
|
|
4184
4599
|
case "debris":
|
|
4185
4600
|
return engine.debrisPiece(this.value(step.spawn));
|
|
4186
4601
|
case "decal":
|
|
@@ -4262,7 +4677,7 @@ var GameDestructionThree = (() => {
|
|
|
4262
4677
|
this.index = previous;
|
|
4263
4678
|
}
|
|
4264
4679
|
};
|
|
4265
|
-
var
|
|
4680
|
+
var ORIGIN5 = [0, 0, 0];
|
|
4266
4681
|
var DEFAULT_HEADING = [0, 0, -1];
|
|
4267
4682
|
var DEFAULT_MAX_INSTANCES = 48;
|
|
4268
4683
|
var ENDLESS_SECONDS = 60;
|
|
@@ -4307,7 +4722,7 @@ var GameDestructionThree = (() => {
|
|
|
4307
4722
|
}
|
|
4308
4723
|
function placementOf(entry) {
|
|
4309
4724
|
const origin = entry.follow ? [entry.origin[0] + positionOf2(entry.follow)[0], entry.origin[1] + positionOf2(entry.follow)[1], entry.origin[2] + positionOf2(entry.follow)[2]] : entry.origin;
|
|
4310
|
-
return { origin, anchor: entry.anchor, yaw: entry.yaw };
|
|
4725
|
+
return { origin, anchor: entry.anchor, yaw: entry.yaw, ...entry.orientation ? { orientation: entry.orientation } : {} };
|
|
4311
4726
|
}
|
|
4312
4727
|
function drawing(entry, action) {
|
|
4313
4728
|
const context = engine.context;
|
|
@@ -4331,8 +4746,9 @@ var GameDestructionThree = (() => {
|
|
|
4331
4746
|
random: playOptions.seed !== void 0 ? streamOf(playOptions.seed) : void 0,
|
|
4332
4747
|
follow: playOptions.follow,
|
|
4333
4748
|
origin: point,
|
|
4334
|
-
anchor: def.anchor ??
|
|
4749
|
+
anchor: def.anchor ?? ORIGIN5,
|
|
4335
4750
|
yaw: yawOf(heading, playOptions.direction),
|
|
4751
|
+
orientation: playOptions.orientation,
|
|
4336
4752
|
seconds: playOptions.seconds ?? (def.loop && def.loop > 0 ? def.loop : ENDLESS_SECONDS)
|
|
4337
4753
|
};
|
|
4338
4754
|
playing.push(entry);
|
|
@@ -4341,7 +4757,8 @@ var GameDestructionThree = (() => {
|
|
|
4341
4757
|
() => instance.begin(def, paramIndex(def, playOptions.param), {
|
|
4342
4758
|
placement: placementOf(entry),
|
|
4343
4759
|
...playOptions.direction ? { direction: playOptions.direction } : {},
|
|
4344
|
-
...playOptions.normal ? { normal: playOptions.normal } : {}
|
|
4760
|
+
...playOptions.normal ? { normal: playOptions.normal } : {},
|
|
4761
|
+
...playOptions.values ? { values: playOptions.values } : {}
|
|
4345
4762
|
})
|
|
4346
4763
|
);
|
|
4347
4764
|
return entry.handle;
|
|
@@ -4601,15 +5018,15 @@ var GameDestructionThree = (() => {
|
|
|
4601
5018
|
return shock;
|
|
4602
5019
|
}
|
|
4603
5020
|
function pushPuffs(puffs, shock, reach, dt, age) {
|
|
4604
|
-
for (const
|
|
4605
|
-
if (
|
|
4606
|
-
const dx =
|
|
4607
|
-
const dz =
|
|
5021
|
+
for (const puff3 of puffs) {
|
|
5022
|
+
if (puff3.ring || puff3.t > PUSH_AGE_LIMIT) continue;
|
|
5023
|
+
const dx = puff3.x - shock.x;
|
|
5024
|
+
const dz = puff3.z - shock.z;
|
|
4608
5025
|
const distance = Math.hypot(dx, dz) + 1e-3;
|
|
4609
|
-
if (Math.abs(distance - reach) < PUSH_BAND &&
|
|
5026
|
+
if (Math.abs(distance - reach) < PUSH_BAND && puff3.y < PUSH_CEILING) {
|
|
4610
5027
|
const strength = 4 * dt * (1 - age);
|
|
4611
|
-
|
|
4612
|
-
|
|
5028
|
+
puff3.vx += dx / distance * strength * 6;
|
|
5029
|
+
puff3.vz += dz / distance * strength * 6;
|
|
4613
5030
|
}
|
|
4614
5031
|
}
|
|
4615
5032
|
}
|
|
@@ -4909,10 +5326,10 @@ var GameDestructionThree = (() => {
|
|
|
4909
5326
|
const life = random.between(ring2.life * 0.75, ring2.life);
|
|
4910
5327
|
const h0 = random.between(1, 1.25);
|
|
4911
5328
|
const hl = random.between(0.9, 1.6);
|
|
4912
|
-
const
|
|
4913
|
-
|
|
4914
|
-
|
|
4915
|
-
|
|
5329
|
+
const puff3 = addPuff(core, random, { x, y, z, s0: spec.radius * 0.2, s1, sg: spec.radius * 0.06, gk: 3, life, h0, hl, color, kind: 0 });
|
|
5330
|
+
puff3.ring = ring2;
|
|
5331
|
+
puff3.ph = random.next() * Math.PI * 2;
|
|
5332
|
+
puff3.th = random.next() * Math.PI * 2;
|
|
4916
5333
|
}
|
|
4917
5334
|
const stemCount = Math.round((spec.stem || 18) * Math.max(lod, 0.4));
|
|
4918
5335
|
for (let index = 0; index < stemCount; index++) {
|
|
@@ -5713,7 +6130,7 @@ var GameDestructionThree = (() => {
|
|
|
5713
6130
|
};
|
|
5714
6131
|
var TWO_PI_ROUNDED = 6.2832;
|
|
5715
6132
|
var WIDE_CONE = 3.1;
|
|
5716
|
-
var
|
|
6133
|
+
var UP13 = [0, 1, 0];
|
|
5717
6134
|
function drawRange(random, range) {
|
|
5718
6135
|
if (Array.isArray(range)) return random.between(range[0], range[1]);
|
|
5719
6136
|
return range || 0;
|
|
@@ -5741,7 +6158,7 @@ var GameDestructionThree = (() => {
|
|
|
5741
6158
|
}
|
|
5742
6159
|
function coneDirection(random, direction, cone, out) {
|
|
5743
6160
|
if (cone >= WIDE_CONE) return randomUnit(random, out);
|
|
5744
|
-
const [dx, dy, dz] = direction ??
|
|
6161
|
+
const [dx, dy, dz] = direction ?? UP13;
|
|
5745
6162
|
const cosTilt = 1 - random.next() * (1 - Math.cos(cone));
|
|
5746
6163
|
const sinTilt = Math.sqrt(1 - cosTilt * cosTilt);
|
|
5747
6164
|
const phase = random.next() * TWO_PI_ROUNDED;
|
|
@@ -5861,12 +6278,12 @@ var GameDestructionThree = (() => {
|
|
|
5861
6278
|
}
|
|
5862
6279
|
};
|
|
5863
6280
|
var CAPACITY2 = 400;
|
|
5864
|
-
var
|
|
6281
|
+
var UP14 = [0, 1, 0];
|
|
5865
6282
|
var DEFAULT_LIFE2 = 60;
|
|
5866
6283
|
var DEFAULT_GROW = 1.2;
|
|
5867
6284
|
var EVAPORATION = { fuel: [6, 5], water: [40, 20] };
|
|
5868
6285
|
function createDecal() {
|
|
5869
|
-
return { on: false, x: 0, y: 0, z: 0, sx: 0, sy: 0, t: 0, life: 0, grow: 0, color: 0, normal:
|
|
6286
|
+
return { on: false, x: 0, y: 0, z: 0, sx: 0, sy: 0, t: 0, life: 0, grow: 0, color: 0, normal: UP14, fluid: void 0, dryColor: -1, dryAt: 0, dryTime: 0 };
|
|
5870
6287
|
}
|
|
5871
6288
|
var DecalPool = class {
|
|
5872
6289
|
constructor(context) {
|
|
@@ -5879,7 +6296,7 @@ var GameDestructionThree = (() => {
|
|
|
5879
6296
|
const random = this.context.random;
|
|
5880
6297
|
const index = this.next++ % CAPACITY2;
|
|
5881
6298
|
const decal2 = this.decals[index];
|
|
5882
|
-
const normal = options.n ??
|
|
6299
|
+
const normal = options.n ?? UP14;
|
|
5883
6300
|
random.between(0, 6.28);
|
|
5884
6301
|
const offset = 4e-3 + index % 40 * 4e-4;
|
|
5885
6302
|
decal2.on = true;
|
|
@@ -5920,6 +6337,94 @@ var GameDestructionThree = (() => {
|
|
|
5920
6337
|
}
|
|
5921
6338
|
}
|
|
5922
6339
|
};
|
|
6340
|
+
var CAPACITY3 = 400;
|
|
6341
|
+
var IDENTITY = [0, 0, 0, 1];
|
|
6342
|
+
function multiply(a, b) {
|
|
6343
|
+
const [ax, ay, az, aw] = a;
|
|
6344
|
+
const [bx, by, bz, bw] = b;
|
|
6345
|
+
return [aw * bx + ax * bw + ay * bz - az * by, aw * by - ax * bz + ay * bw + az * bx, aw * bz + ax * by - ay * bx + az * bw, aw * bw - ax * bx - ay * by - az * bz];
|
|
6346
|
+
}
|
|
6347
|
+
var aboutX = (angle) => [Math.sin(angle / 2), 0, 0, Math.cos(angle / 2)];
|
|
6348
|
+
var MeshPool = class {
|
|
6349
|
+
constructor(capacity = CAPACITY3) {
|
|
6350
|
+
__publicField2(this, "capacity", capacity);
|
|
6351
|
+
__publicField2(this, "particles", []);
|
|
6352
|
+
__publicField2(this, "serial", 0);
|
|
6353
|
+
}
|
|
6354
|
+
get count() {
|
|
6355
|
+
return this.particles.length;
|
|
6356
|
+
}
|
|
6357
|
+
spawn(options, frame = IDENTITY) {
|
|
6358
|
+
const velocity = options.v ?? [0, 0, 0];
|
|
6359
|
+
const world = options.wv ?? [0, 0, 0];
|
|
6360
|
+
const particle = {
|
|
6361
|
+
id: ++this.serial,
|
|
6362
|
+
shape: options.shape,
|
|
6363
|
+
radius: options.r,
|
|
6364
|
+
height: options.h ?? 0,
|
|
6365
|
+
segments: options.seg ?? 0,
|
|
6366
|
+
segments2: options.seg2 ?? 0,
|
|
6367
|
+
color: options.c0,
|
|
6368
|
+
additive: options.add === true,
|
|
6369
|
+
lit: options.lit === true,
|
|
6370
|
+
x: options.p[0],
|
|
6371
|
+
y: options.p[1],
|
|
6372
|
+
z: options.p[2],
|
|
6373
|
+
frame: options.roll ? multiply(frame, aboutX(options.roll)) : frame,
|
|
6374
|
+
at: options.at ?? [0, 0, 0],
|
|
6375
|
+
rx: options.rot?.[0] ?? 0,
|
|
6376
|
+
ry: options.rot?.[1] ?? 0,
|
|
6377
|
+
rz: options.rot?.[2] ?? 0,
|
|
6378
|
+
scale: 1,
|
|
6379
|
+
opacity: options.a,
|
|
6380
|
+
age: 0,
|
|
6381
|
+
life: options.life,
|
|
6382
|
+
vx: velocity[0] + world[0],
|
|
6383
|
+
vy: velocity[1] + world[1],
|
|
6384
|
+
vz: velocity[2] + world[2],
|
|
6385
|
+
spin: options.spin ?? [0, 0, 0],
|
|
6386
|
+
gravity: options.g ?? 0,
|
|
6387
|
+
drag: options.drag ?? 0,
|
|
6388
|
+
grow: options.grow ?? 0,
|
|
6389
|
+
ramp: options.ramp,
|
|
6390
|
+
fade: options.fade === true,
|
|
6391
|
+
startOpacity: options.a
|
|
6392
|
+
};
|
|
6393
|
+
this.particles.push(particle);
|
|
6394
|
+
if (this.particles.length > this.capacity) this.particles.shift();
|
|
6395
|
+
return particle;
|
|
6396
|
+
}
|
|
6397
|
+
update(dt) {
|
|
6398
|
+
const live = this.particles;
|
|
6399
|
+
for (let index = 0; index < live.length; index++) {
|
|
6400
|
+
const particle = live[index];
|
|
6401
|
+
particle.age += dt;
|
|
6402
|
+
if (particle.ramp ? particle.age >= particle.life : particle.age > particle.life) {
|
|
6403
|
+
live.splice(index--, 1);
|
|
6404
|
+
continue;
|
|
6405
|
+
}
|
|
6406
|
+
if (particle.fade) particle.opacity = Math.max(0, particle.startOpacity * (1 - particle.age / particle.life));
|
|
6407
|
+
particle.vy -= particle.gravity * dt;
|
|
6408
|
+
if (particle.drag) {
|
|
6409
|
+
const keep = Math.max(0, 1 - particle.drag * dt);
|
|
6410
|
+
particle.vx *= keep;
|
|
6411
|
+
particle.vy *= keep;
|
|
6412
|
+
particle.vz *= keep;
|
|
6413
|
+
}
|
|
6414
|
+
particle.x += particle.vx * dt;
|
|
6415
|
+
particle.y += particle.vy * dt;
|
|
6416
|
+
particle.z += particle.vz * dt;
|
|
6417
|
+
particle.rx += particle.spin[0] * dt;
|
|
6418
|
+
particle.ry += particle.spin[1] * dt;
|
|
6419
|
+
particle.rz += particle.spin[2] * dt;
|
|
6420
|
+
if (particle.grow) particle.scale *= 1 + particle.grow * dt;
|
|
6421
|
+
if (particle.ramp) particle.scale = particle.ramp[0] + Math.min(1, particle.age / particle.life) * particle.ramp[1];
|
|
6422
|
+
}
|
|
6423
|
+
}
|
|
6424
|
+
clear() {
|
|
6425
|
+
this.particles.length = 0;
|
|
6426
|
+
}
|
|
6427
|
+
};
|
|
5923
6428
|
var DEFAULT_FADE_IN = 0.1;
|
|
5924
6429
|
var FLOATS_PER_VECTOR = 3;
|
|
5925
6430
|
var BYTE_MAX2 = 255;
|
|
@@ -6209,11 +6714,11 @@ var GameDestructionThree = (() => {
|
|
|
6209
6714
|
};
|
|
6210
6715
|
var RING_CAPACITY = 120;
|
|
6211
6716
|
var LIGHT_CAPACITY = 4;
|
|
6212
|
-
var
|
|
6717
|
+
var UP15 = [0, 1, 0];
|
|
6213
6718
|
var DEFAULT_LIGHT_DISTANCE = 14;
|
|
6214
6719
|
var WaveRingPool = class {
|
|
6215
6720
|
constructor() {
|
|
6216
|
-
__publicField2(this, "rings", Array.from({ length: RING_CAPACITY }, () => ({ on: false, point:
|
|
6721
|
+
__publicField2(this, "rings", Array.from({ length: RING_CAPACITY }, () => ({ on: false, point: UP15, from: 0, to: 0, t: 0, duration: 1, color: 0, normal: UP15, hold: 0 })));
|
|
6217
6722
|
__publicField2(this, "count", 0);
|
|
6218
6723
|
__publicField2(this, "next", 0);
|
|
6219
6724
|
}
|
|
@@ -6226,7 +6731,7 @@ var GameDestructionThree = (() => {
|
|
|
6226
6731
|
ring2.t = 0;
|
|
6227
6732
|
ring2.duration = duration;
|
|
6228
6733
|
ring2.color = color;
|
|
6229
|
-
ring2.normal = normal ??
|
|
6734
|
+
ring2.normal = normal ?? UP15;
|
|
6230
6735
|
ring2.hold = hold || 0;
|
|
6231
6736
|
}
|
|
6232
6737
|
clear() {
|
|
@@ -6246,7 +6751,7 @@ var GameDestructionThree = (() => {
|
|
|
6246
6751
|
var FlashLightPool = class {
|
|
6247
6752
|
constructor(context) {
|
|
6248
6753
|
__publicField2(this, "context", context);
|
|
6249
|
-
__publicField2(this, "lights", Array.from({ length: LIGHT_CAPACITY }, () => ({ x: 0, y: 0, z: 0, color: 16760944, distance: DEFAULT_LIGHT_DISTANCE, peak: 0, duration: 1, t: 0, intensity: 0 })));
|
|
6754
|
+
__publicField2(this, "lights", Array.from({ length: LIGHT_CAPACITY }, () => ({ x: 0, y: 0, z: 0, color: 16760944, distance: DEFAULT_LIGHT_DISTANCE, peak: 0, duration: 1, t: 0, intensity: 0, steady: false })));
|
|
6250
6755
|
__publicField2(this, "fire", [
|
|
6251
6756
|
{ x: 0, y: 0, z: 0, intensity: 0 },
|
|
6252
6757
|
{ x: 0, y: 0, z: 0, intensity: 0 }
|
|
@@ -6256,7 +6761,7 @@ var GameDestructionThree = (() => {
|
|
|
6256
6761
|
get lit() {
|
|
6257
6762
|
return this.lights.filter((light) => light.intensity > 0).length;
|
|
6258
6763
|
}
|
|
6259
|
-
flash(point, color, intensity, duration, distance, force) {
|
|
6764
|
+
flash(point, color, intensity, duration, distance, force, steady) {
|
|
6260
6765
|
const { level } = this.context.quality;
|
|
6261
6766
|
if (level >= 1 && !force) return;
|
|
6262
6767
|
if (level >= 2 && force !== "boom") return;
|
|
@@ -6269,6 +6774,7 @@ var GameDestructionThree = (() => {
|
|
|
6269
6774
|
light.peak = intensity;
|
|
6270
6775
|
light.duration = duration;
|
|
6271
6776
|
light.t = 0;
|
|
6777
|
+
light.steady = steady === true;
|
|
6272
6778
|
light.intensity = intensity;
|
|
6273
6779
|
}
|
|
6274
6780
|
clear() {
|
|
@@ -6280,7 +6786,7 @@ var GameDestructionThree = (() => {
|
|
|
6280
6786
|
if (light.intensity <= 0) continue;
|
|
6281
6787
|
light.t += dt;
|
|
6282
6788
|
const age = light.t / light.duration;
|
|
6283
|
-
light.intensity = age >= 1 ? 0 : light.peak * (1 - age) * (1 - age);
|
|
6789
|
+
light.intensity = age >= 1 ? 0 : light.steady ? light.peak : light.peak * (1 - age) * (1 - age);
|
|
6284
6790
|
}
|
|
6285
6791
|
}
|
|
6286
6792
|
};
|
|
@@ -6288,6 +6794,14 @@ var GameDestructionThree = (() => {
|
|
|
6288
6794
|
var FIRE_FLICKER_SWAY = 0.25;
|
|
6289
6795
|
var FIRE_FLICKER_JITTER = 0.08;
|
|
6290
6796
|
var LENS_FADE = 0.16;
|
|
6797
|
+
function rotate(q, v) {
|
|
6798
|
+
const [qx, qy, qz, qw] = q;
|
|
6799
|
+
const ix = qw * v[0] + qy * v[2] - qz * v[1];
|
|
6800
|
+
const iy = qw * v[1] + qz * v[0] - qx * v[2];
|
|
6801
|
+
const iz = qw * v[2] + qx * v[1] - qy * v[0];
|
|
6802
|
+
const iw = -qx * v[0] - qy * v[1] - qz * v[2];
|
|
6803
|
+
return [ix * qw + iw * -qx + iy * -qz - iz * -qy, iy * qw + iw * -qy + iz * -qx - ix * -qz, iz * qw + iw * -qz + ix * -qy - iy * -qx];
|
|
6804
|
+
}
|
|
6291
6805
|
function workshopGround(x, z) {
|
|
6292
6806
|
return z < -2.9 && z > -4.5 && Math.abs(x) < 13 ? 0.12 : 0;
|
|
6293
6807
|
}
|
|
@@ -6301,6 +6815,8 @@ var GameDestructionThree = (() => {
|
|
|
6301
6815
|
__publicField2(this, "decals");
|
|
6302
6816
|
__publicField2(this, "rings", new WaveRingPool());
|
|
6303
6817
|
__publicField2(this, "lights");
|
|
6818
|
+
__publicField2(this, "rain", new RainField(this));
|
|
6819
|
+
__publicField2(this, "meshes", new MeshPool());
|
|
6304
6820
|
__publicField2(this, "screen", createScreenState());
|
|
6305
6821
|
__publicField2(this, "lens", []);
|
|
6306
6822
|
__publicField2(this, "post", {});
|
|
@@ -6333,7 +6849,11 @@ var GameDestructionThree = (() => {
|
|
|
6333
6849
|
place(point) {
|
|
6334
6850
|
const placement = this.placement;
|
|
6335
6851
|
if (!placement) return point;
|
|
6336
|
-
const { anchor, origin, yaw } = placement;
|
|
6852
|
+
const { anchor, origin, yaw, orientation } = placement;
|
|
6853
|
+
if (orientation) {
|
|
6854
|
+
const turned = rotate(orientation, [point[0] - anchor[0], point[1] - anchor[1], point[2] - anchor[2]]);
|
|
6855
|
+
return [origin[0] + turned[0], origin[1] + turned[1], origin[2] + turned[2]];
|
|
6856
|
+
}
|
|
6337
6857
|
const x = point[0] - anchor[0];
|
|
6338
6858
|
const z = point[2] - anchor[2];
|
|
6339
6859
|
const cos2 = Math.cos(yaw);
|
|
@@ -6344,6 +6864,7 @@ var GameDestructionThree = (() => {
|
|
|
6344
6864
|
turn(vector) {
|
|
6345
6865
|
const placement = this.placement;
|
|
6346
6866
|
if (!placement) return vector;
|
|
6867
|
+
if (placement.orientation) return rotate(placement.orientation, vector);
|
|
6347
6868
|
const cos2 = Math.cos(placement.yaw);
|
|
6348
6869
|
const sin2 = Math.sin(placement.yaw);
|
|
6349
6870
|
return [cos2 * vector[0] + sin2 * vector[2], vector[1], -sin2 * vector[0] + cos2 * vector[2]];
|
|
@@ -6372,6 +6893,14 @@ var GameDestructionThree = (() => {
|
|
|
6372
6893
|
}
|
|
6373
6894
|
this.accumulators.set(key, carried);
|
|
6374
6895
|
}
|
|
6896
|
+
/** A solid particle (a cone, a sphere): the group sits at `p` turned by the placement, `v` is turned with it and `wv` is not. */
|
|
6897
|
+
mesh(recipe) {
|
|
6898
|
+
const placement = this.placement;
|
|
6899
|
+
const options = placement ? { ...recipe, p: this.place(recipe.p), ...recipe.v ? { v: this.turn(recipe.v) } : {} } : recipe;
|
|
6900
|
+
this.context.trace?.("mesh", [options]);
|
|
6901
|
+
const grouped = recipe.at !== void 0 || recipe.roll !== void 0;
|
|
6902
|
+
return this.meshes.spawn(options, placement && grouped ? placement.orientation ?? [0, Math.sin(placement.yaw / 2), 0, Math.cos(placement.yaw / 2)] : void 0);
|
|
6903
|
+
}
|
|
6375
6904
|
debrisPiece(recipe) {
|
|
6376
6905
|
const options = this.placed(recipe);
|
|
6377
6906
|
this.context.trace?.("debris", [options]);
|
|
@@ -6392,10 +6921,11 @@ var GameDestructionThree = (() => {
|
|
|
6392
6921
|
this.context.trace?.("ring", args);
|
|
6393
6922
|
this.rings.add(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
|
|
6394
6923
|
}
|
|
6924
|
+
/** `steady` (a seventh number): the light holds its intensity for its duration and goes out, where the Workshop's fades with the square of its age. */
|
|
6395
6925
|
flash(recipe) {
|
|
6396
|
-
const args = this.placement ? [this.place(recipe[0]), recipe[1], recipe[2], recipe[3], recipe[4], recipe[5]] : recipe;
|
|
6397
|
-
this.context.trace?.("flash", args);
|
|
6398
|
-
this.lights.flash(args[0], args[1], args[2], args[3], args[4], args[5]);
|
|
6926
|
+
const args = this.placement ? [this.place(recipe[0]), recipe[1], recipe[2], recipe[3], recipe[4], recipe[5], recipe[6]] : recipe;
|
|
6927
|
+
this.context.trace?.("flash", args.slice(0, 6));
|
|
6928
|
+
this.lights.flash(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
|
|
6399
6929
|
}
|
|
6400
6930
|
/** `fireLight` (W400): sways with the clock and flickers with one draw. */
|
|
6401
6931
|
fireLight(slot, recipe, intensity, time) {
|
|
@@ -6420,6 +6950,7 @@ var GameDestructionThree = (() => {
|
|
|
6420
6950
|
this.debris.update(dt);
|
|
6421
6951
|
this.decals.update(dt);
|
|
6422
6952
|
this.rings.update(dt);
|
|
6953
|
+
this.meshes.update(dt);
|
|
6423
6954
|
this.lights.update(dt);
|
|
6424
6955
|
updateScreen(this.screen, dt);
|
|
6425
6956
|
for (let index = this.lens.length - 1; index >= 0; index--) {
|
|
@@ -6436,7 +6967,9 @@ var GameDestructionThree = (() => {
|
|
|
6436
6967
|
this.debris.clear();
|
|
6437
6968
|
this.decals.clear();
|
|
6438
6969
|
this.rings.clear();
|
|
6970
|
+
this.meshes.clear();
|
|
6439
6971
|
this.lights.clear();
|
|
6972
|
+
this.rain.clear();
|
|
6440
6973
|
this.accumulators.clear();
|
|
6441
6974
|
resetScreenState(this.screen);
|
|
6442
6975
|
this.lens.length = 0;
|
|
@@ -6582,16 +7115,16 @@ var GameDestructionThree = (() => {
|
|
|
6582
7115
|
},
|
|
6583
7116
|
push(point, radius, speed) {
|
|
6584
7117
|
spriteSystem.push(point, radius, speed);
|
|
6585
|
-
for (const
|
|
6586
|
-
const dx =
|
|
6587
|
-
const dy =
|
|
6588
|
-
const dz =
|
|
7118
|
+
for (const puff3 of core.puffs.items) {
|
|
7119
|
+
const dx = puff3.x - point[0];
|
|
7120
|
+
const dy = puff3.y - point[1];
|
|
7121
|
+
const dz = puff3.z - point[2];
|
|
6589
7122
|
const distance = Math.sqrt(dx * dx + dy * dy + dz * dz);
|
|
6590
7123
|
if (distance >= radius) continue;
|
|
6591
7124
|
const strength = speed * (1 - distance / radius) / (distance + 1e-3);
|
|
6592
|
-
|
|
6593
|
-
|
|
6594
|
-
|
|
7125
|
+
puff3.vx += dx * strength;
|
|
7126
|
+
puff3.vy += dy * strength;
|
|
7127
|
+
puff3.vz += dz * strength;
|
|
6595
7128
|
}
|
|
6596
7129
|
},
|
|
6597
7130
|
stop(handle) {
|
|
@@ -6608,6 +7141,12 @@ var GameDestructionThree = (() => {
|
|
|
6608
7141
|
camera2.y = position[1];
|
|
6609
7142
|
camera2.z = position[2];
|
|
6610
7143
|
},
|
|
7144
|
+
setWind(next) {
|
|
7145
|
+
wind.x = next[0];
|
|
7146
|
+
wind.y = next[1];
|
|
7147
|
+
wind.z = next[2];
|
|
7148
|
+
},
|
|
7149
|
+
wind: () => [wind.x, wind.y, wind.z],
|
|
6611
7150
|
forceLod(scale) {
|
|
6612
7151
|
core.clock.forcedLod = scale;
|
|
6613
7152
|
},
|
|
@@ -6805,11 +7344,11 @@ void main(){
|
|
|
6805
7344
|
geometry.setAttribute("aC", attributes[2]);
|
|
6806
7345
|
geometry.instanceCount = 0;
|
|
6807
7346
|
const material = new THREE.ShaderMaterial({ uniforms, vertexShader: PUFF_VERTEX, fragmentShader: PUFF_FRAGMENT });
|
|
6808
|
-
const
|
|
6809
|
-
|
|
6810
|
-
|
|
7347
|
+
const mesh2 = new THREE.Mesh(geometry, material);
|
|
7348
|
+
mesh2.name = "vfx-puffs";
|
|
7349
|
+
mesh2.frustumCulled = false;
|
|
6811
7350
|
return {
|
|
6812
|
-
mesh,
|
|
7351
|
+
mesh: mesh2,
|
|
6813
7352
|
sync() {
|
|
6814
7353
|
let n = 0;
|
|
6815
7354
|
for (const p of pool.items) {
|
|
@@ -6850,12 +7389,12 @@ void main(){
|
|
|
6850
7389
|
geometry.setAttribute("aE", attributes[2]);
|
|
6851
7390
|
geometry.instanceCount = 0;
|
|
6852
7391
|
const material = new THREE.ShaderMaterial({ transparent: true, depthWrite: false, blending: THREE.AdditiveBlending, vertexShader: SPARK_VERTEX, fragmentShader: SPARK_FRAGMENT });
|
|
6853
|
-
const
|
|
6854
|
-
|
|
6855
|
-
|
|
6856
|
-
|
|
7392
|
+
const mesh2 = new THREE.Mesh(geometry, material);
|
|
7393
|
+
mesh2.name = "vfx-sparks";
|
|
7394
|
+
mesh2.frustumCulled = false;
|
|
7395
|
+
mesh2.renderOrder = 5;
|
|
6857
7396
|
return {
|
|
6858
|
-
mesh,
|
|
7397
|
+
mesh: mesh2,
|
|
6859
7398
|
sync() {
|
|
6860
7399
|
let n = 0;
|
|
6861
7400
|
for (const s of pool.items) {
|
|
@@ -6893,12 +7432,12 @@ void main(){
|
|
|
6893
7432
|
geometry.setAttribute("aC", attributes[1]);
|
|
6894
7433
|
geometry.instanceCount = 0;
|
|
6895
7434
|
const material = new THREE.ShaderMaterial({ transparent: true, depthWrite: false, blending: THREE.AdditiveBlending, vertexShader: GLOW_VERTEX, fragmentShader: GLOW_FRAGMENT });
|
|
6896
|
-
const
|
|
6897
|
-
|
|
6898
|
-
|
|
6899
|
-
|
|
7435
|
+
const mesh2 = new THREE.Mesh(geometry, material);
|
|
7436
|
+
mesh2.name = "vfx-glows";
|
|
7437
|
+
mesh2.frustumCulled = false;
|
|
7438
|
+
mesh2.renderOrder = 6;
|
|
6900
7439
|
return {
|
|
6901
|
-
mesh,
|
|
7440
|
+
mesh: mesh2,
|
|
6902
7441
|
sync() {
|
|
6903
7442
|
let n = 0;
|
|
6904
7443
|
for (const g of pool.items) {
|
|
@@ -6927,14 +7466,14 @@ void main(){
|
|
|
6927
7466
|
const rockMaterial = new THREE.MeshStandardMaterial({ color: 16777215, roughness: 0.85, flatShading: true });
|
|
6928
7467
|
const plateMaterial = rockMaterial.clone();
|
|
6929
7468
|
const make = (geometry, material) => {
|
|
6930
|
-
const
|
|
6931
|
-
|
|
6932
|
-
|
|
6933
|
-
|
|
6934
|
-
|
|
6935
|
-
|
|
6936
|
-
|
|
6937
|
-
return
|
|
7469
|
+
const mesh2 = new THREE.InstancedMesh(geometry, material, capacity);
|
|
7470
|
+
mesh2.instanceMatrix.setUsage(THREE.DynamicDrawUsage);
|
|
7471
|
+
mesh2.castShadow = true;
|
|
7472
|
+
mesh2.receiveShadow = true;
|
|
7473
|
+
mesh2.frustumCulled = false;
|
|
7474
|
+
mesh2.count = 0;
|
|
7475
|
+
mesh2.setColorAt(0, new THREE.Color(1, 1, 1));
|
|
7476
|
+
return mesh2;
|
|
6938
7477
|
};
|
|
6939
7478
|
const rocks = make(shapes.rock, rockMaterial);
|
|
6940
7479
|
const plates = make(shapes.plate, plateMaterial);
|
|
@@ -6953,20 +7492,20 @@ void main(){
|
|
|
6953
7492
|
euler.set(chunk.rx, chunk.ry, chunk.rz);
|
|
6954
7493
|
quaternion.setFromEuler(euler);
|
|
6955
7494
|
matrix.compose(position.set(chunk.x, chunk.y, chunk.z), quaternion, scale.set(chunk.sx, chunk.sy, chunk.sz));
|
|
6956
|
-
const
|
|
7495
|
+
const mesh2 = chunk.plate ? plates : rocks;
|
|
6957
7496
|
const index = chunk.plate ? plateCount++ : rockCount++;
|
|
6958
|
-
|
|
7497
|
+
mesh2.setMatrixAt(index, matrix);
|
|
6959
7498
|
const color = colorOf2(chunk);
|
|
6960
|
-
const colors =
|
|
7499
|
+
const colors = mesh2.instanceColor.array;
|
|
6961
7500
|
colors[index * 3] = color[0];
|
|
6962
7501
|
colors[index * 3 + 1] = color[1];
|
|
6963
7502
|
colors[index * 3 + 2] = color[2];
|
|
6964
7503
|
}
|
|
6965
7504
|
rocks.count = rockCount;
|
|
6966
7505
|
plates.count = plateCount;
|
|
6967
|
-
for (const
|
|
6968
|
-
|
|
6969
|
-
|
|
7506
|
+
for (const mesh2 of [rocks, plates]) {
|
|
7507
|
+
mesh2.instanceMatrix.needsUpdate = true;
|
|
7508
|
+
mesh2.instanceColor.needsUpdate = true;
|
|
6970
7509
|
}
|
|
6971
7510
|
return rockCount + plateCount;
|
|
6972
7511
|
},
|
|
@@ -7150,28 +7689,28 @@ void main(){
|
|
|
7150
7689
|
position.setXYZ(index, worldX, (options.ground?.heightAt(worldX, worldZ) ?? 0) + mark.lift, worldZ);
|
|
7151
7690
|
}
|
|
7152
7691
|
geometry.computeVertexNormals();
|
|
7153
|
-
const
|
|
7154
|
-
|
|
7155
|
-
return
|
|
7692
|
+
const mesh2 = new THREE.Mesh(geometry, material);
|
|
7693
|
+
mesh2.receiveShadow = true;
|
|
7694
|
+
return mesh2;
|
|
7156
7695
|
}
|
|
7157
7696
|
function addRock(mark) {
|
|
7158
|
-
const
|
|
7159
|
-
|
|
7160
|
-
|
|
7161
|
-
|
|
7162
|
-
|
|
7163
|
-
|
|
7164
|
-
return
|
|
7697
|
+
const mesh2 = new THREE.Mesh(mark.plate ? options.plateGeometry : options.rockGeometry, rockMaterial(mark.color));
|
|
7698
|
+
mesh2.position.set(mark.x, mark.y, mark.z);
|
|
7699
|
+
mesh2.scale.set(mark.scale[0], mark.scale[1], mark.scale[2]);
|
|
7700
|
+
mesh2.rotation.set(mark.rotation[0], mark.rotation[1], mark.rotation[2]);
|
|
7701
|
+
mesh2.castShadow = true;
|
|
7702
|
+
mesh2.receiveShadow = true;
|
|
7703
|
+
return mesh2;
|
|
7165
7704
|
}
|
|
7166
7705
|
function addBlood(mark) {
|
|
7167
|
-
const
|
|
7168
|
-
|
|
7169
|
-
|
|
7170
|
-
|
|
7171
|
-
|
|
7172
|
-
|
|
7173
|
-
blood.push({ mesh, scaleX: mark.scaleX, scaleZ: mark.scaleZ, age: 0 });
|
|
7174
|
-
return
|
|
7706
|
+
const mesh2 = new THREE.Mesh(bloodGeometry, bloodMaterial);
|
|
7707
|
+
mesh2.position.set(mark.x, mark.y, mark.z);
|
|
7708
|
+
mesh2.scale.set(mark.scaleX, 1, mark.scaleZ);
|
|
7709
|
+
mesh2.rotation.y = mark.rotation;
|
|
7710
|
+
mesh2.receiveShadow = true;
|
|
7711
|
+
mesh2.scale.multiplyScalar(0.05);
|
|
7712
|
+
blood.push({ mesh: mesh2, scaleX: mark.scaleX, scaleZ: mark.scaleZ, age: 0 });
|
|
7713
|
+
return mesh2;
|
|
7175
7714
|
}
|
|
7176
7715
|
function build(mark) {
|
|
7177
7716
|
if (mark.kind === "scorch") return conform(mark, scorchMaterials[mark.variant]);
|
|
@@ -7382,6 +7921,73 @@ void main() {
|
|
|
7382
7921
|
}
|
|
7383
7922
|
};
|
|
7384
7923
|
}
|
|
7924
|
+
var SPHERE_DEFAULT_WIDTH = 8;
|
|
7925
|
+
var SPHERE_DEFAULT_HEIGHT = 6;
|
|
7926
|
+
function geometryOf(THREE, particle) {
|
|
7927
|
+
switch (particle.shape) {
|
|
7928
|
+
case "cone":
|
|
7929
|
+
return new THREE.ConeGeometry(particle.radius, particle.height, particle.segments || void 0, particle.segments2 || 1, false);
|
|
7930
|
+
case "cone_open":
|
|
7931
|
+
return new THREE.ConeGeometry(particle.radius, particle.height, particle.segments || void 0, particle.segments2 || 1, true);
|
|
7932
|
+
case "sphere":
|
|
7933
|
+
return new THREE.SphereGeometry(particle.radius, particle.segments || SPHERE_DEFAULT_WIDTH, particle.segments2 || SPHERE_DEFAULT_HEIGHT);
|
|
7934
|
+
case "icosahedron":
|
|
7935
|
+
return new THREE.IcosahedronGeometry(particle.radius, particle.segments);
|
|
7936
|
+
}
|
|
7937
|
+
}
|
|
7938
|
+
function materialOf(THREE, particle) {
|
|
7939
|
+
if (particle.lit) return new THREE.MeshStandardMaterial({ color: particle.color, roughness: 1, metalness: 0, transparent: true, opacity: particle.opacity, depthWrite: false });
|
|
7940
|
+
return new THREE.MeshBasicMaterial({ color: particle.color, transparent: true, opacity: particle.opacity, depthWrite: false, ...particle.additive ? { blending: THREE.AdditiveBlending } : {} });
|
|
7941
|
+
}
|
|
7942
|
+
function createMeshLayer(THREE, pool) {
|
|
7943
|
+
const group = new THREE.Group();
|
|
7944
|
+
group.name = "workshop-meshes";
|
|
7945
|
+
const drawn = /* @__PURE__ */ new Map();
|
|
7946
|
+
const frame = new THREE.Quaternion();
|
|
7947
|
+
const euler = new THREE.Euler();
|
|
7948
|
+
const turn = new THREE.Quaternion();
|
|
7949
|
+
const offset = new THREE.Vector3();
|
|
7950
|
+
function release(mesh2) {
|
|
7951
|
+
mesh2.removeFromParent();
|
|
7952
|
+
mesh2.geometry.dispose();
|
|
7953
|
+
mesh2.material.dispose();
|
|
7954
|
+
}
|
|
7955
|
+
return {
|
|
7956
|
+
group,
|
|
7957
|
+
sync() {
|
|
7958
|
+
const live = /* @__PURE__ */ new Set();
|
|
7959
|
+
for (const particle of pool.particles) {
|
|
7960
|
+
live.add(particle.id);
|
|
7961
|
+
let mesh2 = drawn.get(particle.id);
|
|
7962
|
+
if (!mesh2) {
|
|
7963
|
+
mesh2 = new THREE.Mesh(geometryOf(THREE, particle), materialOf(THREE, particle));
|
|
7964
|
+
mesh2.frustumCulled = false;
|
|
7965
|
+
mesh2.renderOrder = particle.additive ? 5 : 3;
|
|
7966
|
+
drawn.set(particle.id, mesh2);
|
|
7967
|
+
group.add(mesh2);
|
|
7968
|
+
}
|
|
7969
|
+
frame.set(particle.frame[0], particle.frame[1], particle.frame[2], particle.frame[3]);
|
|
7970
|
+
offset.set(particle.at[0], particle.at[1], particle.at[2]).multiplyScalar(particle.scale).applyQuaternion(frame);
|
|
7971
|
+
mesh2.position.set(particle.x + offset.x, particle.y + offset.y, particle.z + offset.z);
|
|
7972
|
+
turn.setFromEuler(euler.set(particle.rx, particle.ry, particle.rz));
|
|
7973
|
+
mesh2.quaternion.copy(frame).multiply(turn);
|
|
7974
|
+
mesh2.scale.setScalar(particle.scale);
|
|
7975
|
+
mesh2.material.opacity = particle.opacity;
|
|
7976
|
+
}
|
|
7977
|
+
for (const [id, mesh2] of drawn) {
|
|
7978
|
+
if (live.has(id)) continue;
|
|
7979
|
+
release(mesh2);
|
|
7980
|
+
drawn.delete(id);
|
|
7981
|
+
}
|
|
7982
|
+
return pool.count;
|
|
7983
|
+
},
|
|
7984
|
+
dispose() {
|
|
7985
|
+
for (const mesh2 of drawn.values()) release(mesh2);
|
|
7986
|
+
drawn.clear();
|
|
7987
|
+
group.removeFromParent();
|
|
7988
|
+
}
|
|
7989
|
+
};
|
|
7990
|
+
}
|
|
7385
7991
|
var WORKSHOP_SPRITE_VERTEX = `attribute float size;attribute float alpha;attribute vec3 pcol;varying vec3 vC;varying float vA;uniform float uScale;
|
|
7386
7992
|
void main(){vC=pcol;vA=alpha;vec4 mv=modelViewMatrix*vec4(position,1.);gl_PointSize=clamp(size*uScale/-mv.z,1.,512.);gl_Position=projectionMatrix*mv;}`;
|
|
7387
7993
|
var WORKSHOP_SPRITE_FRAGMENT = `uniform float uSoft;varying vec3 vC;varying float vA;
|
|
@@ -7457,13 +8063,37 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
7457
8063
|
}
|
|
7458
8064
|
};
|
|
7459
8065
|
}
|
|
8066
|
+
function rainLayer(THREE, rain) {
|
|
8067
|
+
const geometry = new THREE.BufferGeometry();
|
|
8068
|
+
const position = new THREE.BufferAttribute(rain.positions, 3).setUsage(THREE.DynamicDrawUsage);
|
|
8069
|
+
geometry.setAttribute("position", position);
|
|
8070
|
+
geometry.setDrawRange(0, 0);
|
|
8071
|
+
const material = new THREE.LineBasicMaterial({ color: 10466255, transparent: true, opacity: 0.35, depthWrite: false });
|
|
8072
|
+
const lines = new THREE.LineSegments(geometry, material);
|
|
8073
|
+
lines.frustumCulled = false;
|
|
8074
|
+
lines.name = "workshop-rain";
|
|
8075
|
+
return {
|
|
8076
|
+
object: lines,
|
|
8077
|
+
sync() {
|
|
8078
|
+
const drawn = rain.on && rain.count > 0;
|
|
8079
|
+
lines.visible = drawn;
|
|
8080
|
+
geometry.setDrawRange(0, drawn ? rain.count * 2 : 0);
|
|
8081
|
+
position.needsUpdate = true;
|
|
8082
|
+
return drawn;
|
|
8083
|
+
},
|
|
8084
|
+
dispose() {
|
|
8085
|
+
geometry.dispose();
|
|
8086
|
+
material.dispose();
|
|
8087
|
+
}
|
|
8088
|
+
};
|
|
8089
|
+
}
|
|
7460
8090
|
function debrisLayer(THREE, pool) {
|
|
7461
8091
|
const geometry = new THREE.BoxGeometry(1, 1, 1);
|
|
7462
8092
|
const material = new THREE.MeshStandardMaterial({ color: 16777215, roughness: 0.45, metalness: 0.25, flatShading: true });
|
|
7463
|
-
const
|
|
7464
|
-
|
|
7465
|
-
|
|
7466
|
-
|
|
8093
|
+
const mesh2 = new THREE.InstancedMesh(geometry, material, DEBRIS_CAPACITY);
|
|
8094
|
+
mesh2.instanceMatrix.setUsage(THREE.DynamicDrawUsage);
|
|
8095
|
+
mesh2.frustumCulled = false;
|
|
8096
|
+
mesh2.name = "workshop-debris";
|
|
7467
8097
|
const euler = new THREE.Euler();
|
|
7468
8098
|
const quaternion = new THREE.Quaternion();
|
|
7469
8099
|
const position = new THREE.Vector3();
|
|
@@ -7471,16 +8101,16 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
7471
8101
|
const matrix = new THREE.Matrix4();
|
|
7472
8102
|
const colour = new THREE.Color();
|
|
7473
8103
|
const hidden = new THREE.Matrix4().makeScale(0, 0, 0);
|
|
7474
|
-
for (let index = 0; index < DEBRIS_CAPACITY; index++)
|
|
7475
|
-
|
|
8104
|
+
for (let index = 0; index < DEBRIS_CAPACITY; index++) mesh2.setMatrixAt(index, hidden);
|
|
8105
|
+
mesh2.setColorAt(0, colour.setHex(16777215));
|
|
7476
8106
|
return {
|
|
7477
|
-
object:
|
|
8107
|
+
object: mesh2,
|
|
7478
8108
|
sync() {
|
|
7479
8109
|
let drawn = false;
|
|
7480
8110
|
for (let index = 0; index < DEBRIS_CAPACITY; index++) {
|
|
7481
8111
|
const piece = pool.pieces[index];
|
|
7482
8112
|
if (!piece.on) {
|
|
7483
|
-
|
|
8113
|
+
mesh2.setMatrixAt(index, hidden);
|
|
7484
8114
|
continue;
|
|
7485
8115
|
}
|
|
7486
8116
|
drawn = true;
|
|
@@ -7488,11 +8118,11 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
7488
8118
|
euler.set(piece.rx, piece.ry, piece.rz);
|
|
7489
8119
|
quaternion.setFromEuler(euler);
|
|
7490
8120
|
matrix.compose(position.set(piece.x, piece.y, piece.z), quaternion, scale.set(piece.sx * shrink, piece.sy * shrink, piece.sz * shrink));
|
|
7491
|
-
|
|
7492
|
-
|
|
8121
|
+
mesh2.setMatrixAt(index, matrix);
|
|
8122
|
+
mesh2.setColorAt(index, colour.setHex(piece.color));
|
|
7493
8123
|
}
|
|
7494
|
-
|
|
7495
|
-
if (
|
|
8124
|
+
mesh2.instanceMatrix.needsUpdate = true;
|
|
8125
|
+
if (mesh2.instanceColor) mesh2.instanceColor.needsUpdate = true;
|
|
7496
8126
|
return drawn;
|
|
7497
8127
|
},
|
|
7498
8128
|
dispose() {
|
|
@@ -7549,11 +8179,11 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
7549
8179
|
const dryMesh = new THREE.InstancedMesh(geometry, dry, DECAL_CAPACITY);
|
|
7550
8180
|
const group = new THREE.Group();
|
|
7551
8181
|
group.name = "workshop-decals";
|
|
7552
|
-
for (const
|
|
7553
|
-
|
|
7554
|
-
|
|
7555
|
-
|
|
7556
|
-
group.add(
|
|
8182
|
+
for (const mesh2 of [wetMesh, dryMesh]) {
|
|
8183
|
+
mesh2.frustumCulled = false;
|
|
8184
|
+
mesh2.renderOrder = 1;
|
|
8185
|
+
mesh2.instanceMatrix.setUsage(THREE.DynamicDrawUsage);
|
|
8186
|
+
group.add(mesh2);
|
|
7557
8187
|
}
|
|
7558
8188
|
const hidden = new THREE.Matrix4().makeScale(0, 0, 0);
|
|
7559
8189
|
const colour = new THREE.Color();
|
|
@@ -7590,13 +8220,13 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
7590
8220
|
quaternion.multiply(turn.setFromAxisAngle(forward, index * 2.399963));
|
|
7591
8221
|
const offset = 4e-3 + index % 40 * 4e-4;
|
|
7592
8222
|
matrix.compose(position.set(decal2.x + normal.x * offset, decal2.y + normal.y * offset, decal2.z + normal.z * offset), quaternion, scale.set(look.sx, look.sy, 1));
|
|
7593
|
-
const
|
|
7594
|
-
|
|
7595
|
-
|
|
8223
|
+
const mesh2 = look.dried ? dryMesh : wetMesh;
|
|
8224
|
+
mesh2.setMatrixAt(index, matrix);
|
|
8225
|
+
mesh2.setColorAt(index, colour);
|
|
7596
8226
|
}
|
|
7597
|
-
for (const
|
|
7598
|
-
|
|
7599
|
-
if (
|
|
8227
|
+
for (const mesh2 of [wetMesh, dryMesh]) {
|
|
8228
|
+
mesh2.instanceMatrix.needsUpdate = true;
|
|
8229
|
+
if (mesh2.instanceColor) mesh2.instanceColor.needsUpdate = true;
|
|
7600
8230
|
}
|
|
7601
8231
|
return drawn;
|
|
7602
8232
|
},
|
|
@@ -7610,10 +8240,10 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
7610
8240
|
function ringLayer(THREE, pool) {
|
|
7611
8241
|
const geometry = new THREE.RingGeometry(0.86, 1, 40);
|
|
7612
8242
|
const material = new THREE.MeshBasicMaterial({ color: 16777215, transparent: true, blending: THREE.AdditiveBlending, depthWrite: false, side: THREE.DoubleSide });
|
|
7613
|
-
const
|
|
7614
|
-
|
|
7615
|
-
|
|
7616
|
-
|
|
8243
|
+
const mesh2 = new THREE.InstancedMesh(geometry, material, RING_CAPACITY3);
|
|
8244
|
+
mesh2.frustumCulled = false;
|
|
8245
|
+
mesh2.instanceMatrix.setUsage(THREE.DynamicDrawUsage);
|
|
8246
|
+
mesh2.name = "workshop-rings";
|
|
7617
8247
|
const hidden = new THREE.Matrix4().makeScale(0, 0, 0);
|
|
7618
8248
|
const colour = new THREE.Color();
|
|
7619
8249
|
const normal = new THREE.Vector3();
|
|
@@ -7622,16 +8252,16 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
7622
8252
|
const position = new THREE.Vector3();
|
|
7623
8253
|
const scale = new THREE.Vector3();
|
|
7624
8254
|
const matrix = new THREE.Matrix4();
|
|
7625
|
-
|
|
7626
|
-
for (let index = 0; index < RING_CAPACITY3; index++)
|
|
8255
|
+
mesh2.setColorAt(0, colour.setHex(0));
|
|
8256
|
+
for (let index = 0; index < RING_CAPACITY3; index++) mesh2.setMatrixAt(index, hidden);
|
|
7627
8257
|
return {
|
|
7628
|
-
object:
|
|
8258
|
+
object: mesh2,
|
|
7629
8259
|
sync() {
|
|
7630
8260
|
let drawn = false;
|
|
7631
8261
|
for (let index = 0; index < RING_CAPACITY3; index++) {
|
|
7632
8262
|
const ring2 = pool.rings[index];
|
|
7633
8263
|
if (!ring2.on) {
|
|
7634
|
-
|
|
8264
|
+
mesh2.setMatrixAt(index, hidden);
|
|
7635
8265
|
continue;
|
|
7636
8266
|
}
|
|
7637
8267
|
drawn = true;
|
|
@@ -7639,11 +8269,11 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
7639
8269
|
const radius = ring2.from + (ring2.to - ring2.from) * (1 - Math.pow(1 - k, 2));
|
|
7640
8270
|
quaternion.setFromUnitVectors(forward, normal.set(ring2.normal[0], ring2.normal[1], ring2.normal[2]));
|
|
7641
8271
|
matrix.compose(position.set(ring2.point[0], ring2.point[1], ring2.point[2]), quaternion, scale.set(radius, radius, 1));
|
|
7642
|
-
|
|
7643
|
-
|
|
8272
|
+
mesh2.setMatrixAt(index, matrix);
|
|
8273
|
+
mesh2.setColorAt(index, colour.setHex(ring2.color).multiplyScalar(ring2.hold ? ring2.hold : 1 - k));
|
|
7644
8274
|
}
|
|
7645
|
-
|
|
7646
|
-
if (
|
|
8275
|
+
mesh2.instanceMatrix.needsUpdate = true;
|
|
8276
|
+
if (mesh2.instanceColor) mesh2.instanceColor.needsUpdate = true;
|
|
7647
8277
|
return drawn;
|
|
7648
8278
|
},
|
|
7649
8279
|
dispose() {
|
|
@@ -7659,11 +8289,14 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
7659
8289
|
spriteLayer(THREE, engine.add, true, 1, pointScale),
|
|
7660
8290
|
spriteLayer(THREE, engine.normal, false, 0.55, pointScale),
|
|
7661
8291
|
streakLayer(THREE, engine.streaks),
|
|
8292
|
+
rainLayer(THREE, engine.rain),
|
|
7662
8293
|
debrisLayer(THREE, engine.debris),
|
|
7663
8294
|
decalLayer(THREE, engine.decals),
|
|
7664
8295
|
ringLayer(THREE, engine.rings)
|
|
7665
8296
|
];
|
|
7666
8297
|
for (const layer2 of layers) group.add(layer2.object);
|
|
8298
|
+
const meshes = createMeshLayer(THREE, engine.meshes);
|
|
8299
|
+
group.add(meshes.group);
|
|
7667
8300
|
const flashLights = engine.lights.lights.map(() => new THREE.PointLight(16760944, 0, 14));
|
|
7668
8301
|
const fireLights = engine.lights.fire.map(() => new THREE.PointLight(FIRE_LIGHT_COLOR, 0, FIRE_LIGHT_DISTANCE));
|
|
7669
8302
|
for (const light of [...flashLights, ...fireLights]) group.add(light);
|
|
@@ -7672,6 +8305,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
7672
8305
|
sync() {
|
|
7673
8306
|
let drawCalls = 0;
|
|
7674
8307
|
for (const layer2 of layers) if (layer2.sync()) drawCalls++;
|
|
8308
|
+
drawCalls += meshes.sync();
|
|
7675
8309
|
engine.lights.lights.forEach((source, index) => {
|
|
7676
8310
|
const light = flashLights[index];
|
|
7677
8311
|
light.position.set(source.x, source.y, source.z);
|
|
@@ -7688,6 +8322,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
7688
8322
|
},
|
|
7689
8323
|
dispose() {
|
|
7690
8324
|
for (const layer2 of layers) layer2.dispose();
|
|
8325
|
+
meshes.dispose();
|
|
7691
8326
|
group.clear();
|
|
7692
8327
|
}
|
|
7693
8328
|
};
|
|
@@ -7803,8 +8438,10 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
7803
8438
|
return world.play(request.effect, request.point, {
|
|
7804
8439
|
...request.direction ? { direction: request.direction } : {},
|
|
7805
8440
|
...request.normal ? { normal: request.normal } : {},
|
|
8441
|
+
...request.orientation ? { orientation: request.orientation } : {},
|
|
7806
8442
|
...request.seed !== void 0 ? { seed: request.seed } : {},
|
|
7807
|
-
...request.param !== void 0 ? { param: request.param } : {}
|
|
8443
|
+
...request.param !== void 0 ? { param: request.param } : {},
|
|
8444
|
+
...request.values ? { values: request.values } : {}
|
|
7808
8445
|
});
|
|
7809
8446
|
},
|
|
7810
8447
|
stop: (handle) => world.stop(handle),
|
|
@@ -7965,11 +8602,11 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
7965
8602
|
* Bullet holes that stay on a fragment (`Fragment.marks`): dark discs that are children of its mesh, so they fall, spin and settle with it. The mesh is
|
|
7966
8603
|
* a unit box scaled to the fragment, so each disc is scaled back; exact for a mark on a face, which is where a bullet hole is.
|
|
7967
8604
|
*/
|
|
7968
|
-
addMarks(
|
|
8605
|
+
addMarks(mesh2, f) {
|
|
7969
8606
|
if (!f.marks?.length) return;
|
|
7970
8607
|
this.markGeometry ?? (this.markGeometry = new this.THREE.CircleGeometry(1, 10));
|
|
7971
8608
|
this.markMaterial ?? (this.markMaterial = new this.THREE.MeshBasicMaterial({ color: 723465, depthWrite: false, polygonOffset: true, polygonOffsetFactor: -4, polygonOffsetUnits: -4 }));
|
|
7972
|
-
const sc =
|
|
8609
|
+
const sc = mesh2.scale;
|
|
7973
8610
|
for (const mark of f.marks) {
|
|
7974
8611
|
const disc = new this.THREE.Mesh(this.markGeometry, this.markMaterial);
|
|
7975
8612
|
const radius = Math.max(4e-3, mark.diameter) * 0.6;
|
|
@@ -7977,22 +8614,22 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
7977
8614
|
disc.position.set(mark.point[0] / sc.x + n.x * 2e-3 / sc.x, mark.point[1] / sc.y + n.y * 2e-3 / sc.y, mark.point[2] / sc.z + n.z * 2e-3 / sc.z);
|
|
7978
8615
|
disc.quaternion.setFromUnitVectors(this.w.set(0, 0, 1), n);
|
|
7979
8616
|
disc.scale.set(radius / sc.x, radius / sc.y, radius / sc.z);
|
|
7980
|
-
|
|
8617
|
+
mesh2.add(disc);
|
|
7981
8618
|
}
|
|
7982
8619
|
}
|
|
7983
8620
|
/** Create the mesh of a fragment and start its motion. `maxAllowed` is the live budget. */
|
|
7984
8621
|
spawn(f, material, home, maxAllowed) {
|
|
7985
8622
|
const geo = f.shape === "shard" ? this.shardGeometry(hashString(f.id)) : this.box;
|
|
7986
|
-
const
|
|
7987
|
-
|
|
7988
|
-
|
|
8623
|
+
const mesh2 = new this.THREE.Mesh(geo, material);
|
|
8624
|
+
mesh2.position.set(f.center[0], f.center[1], f.center[2]);
|
|
8625
|
+
mesh2.quaternion.set(f.rotation[0], f.rotation[1], f.rotation[2], f.rotation[3]).normalize();
|
|
7989
8626
|
const sz = f.size;
|
|
7990
8627
|
const sc = new this.THREE.Vector3(Math.max(5e-3, sz[0]), Math.max(5e-3, sz[1]), Math.max(3e-3, sz[2]));
|
|
7991
|
-
|
|
7992
|
-
|
|
7993
|
-
this.o.scene.add(
|
|
8628
|
+
mesh2.scale.copy(sc);
|
|
8629
|
+
mesh2.castShadow = true;
|
|
8630
|
+
this.o.scene.add(mesh2);
|
|
7994
8631
|
const live = {
|
|
7995
|
-
mesh,
|
|
8632
|
+
mesh: mesh2,
|
|
7996
8633
|
home,
|
|
7997
8634
|
vel: new this.THREE.Vector3(f.velocity[0], f.velocity[1], f.velocity[2]),
|
|
7998
8635
|
ang: new this.THREE.Vector3(f.angularVelocity[0], f.angularVelocity[1], f.angularVelocity[2]),
|
|
@@ -8013,8 +8650,8 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
8013
8650
|
alive--;
|
|
8014
8651
|
}
|
|
8015
8652
|
}
|
|
8016
|
-
this.addMarks(
|
|
8017
|
-
return
|
|
8653
|
+
this.addMarks(mesh2, f);
|
|
8654
|
+
return mesh2;
|
|
8018
8655
|
}
|
|
8019
8656
|
/** Add velocity to every fragment within `radius` of a point (blasts). */
|
|
8020
8657
|
blast(point, radius, speed) {
|
|
@@ -8053,24 +8690,24 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
8053
8690
|
}
|
|
8054
8691
|
}
|
|
8055
8692
|
step(f, dt, g) {
|
|
8056
|
-
const
|
|
8693
|
+
const mesh2 = f.mesh;
|
|
8057
8694
|
f.vel.y -= g * dt;
|
|
8058
|
-
|
|
8695
|
+
mesh2.position.addScaledVector(f.vel, dt);
|
|
8059
8696
|
const w = f.ang.length();
|
|
8060
8697
|
if (w > 1e-5) {
|
|
8061
8698
|
this.dq.setFromAxisAngle(this.v.copy(f.ang).multiplyScalar(1 / w), w * dt);
|
|
8062
|
-
|
|
8699
|
+
mesh2.quaternion.premultiply(this.dq).normalize();
|
|
8063
8700
|
}
|
|
8064
|
-
this.m.makeRotationFromQuaternion(
|
|
8701
|
+
this.m.makeRotationFromQuaternion(mesh2.quaternion);
|
|
8065
8702
|
const e = this.m.elements;
|
|
8066
8703
|
const h = f.half;
|
|
8067
8704
|
const sc = f.dying ? f.fade : 1;
|
|
8068
8705
|
const ext = (Math.abs(e[1]) * h.x + Math.abs(e[5]) * h.y + Math.abs(e[9]) * h.z) * sc;
|
|
8069
|
-
const gy = this.o.groundAt(
|
|
8706
|
+
const gy = this.o.groundAt(mesh2.position.x, mesh2.position.z);
|
|
8070
8707
|
let contact = false;
|
|
8071
|
-
if (
|
|
8708
|
+
if (mesh2.position.y - ext < gy) {
|
|
8072
8709
|
contact = true;
|
|
8073
|
-
|
|
8710
|
+
mesh2.position.y = gy + ext;
|
|
8074
8711
|
if (f.vel.y < -0.6) {
|
|
8075
8712
|
f.vel.y = -f.vel.y * 0.25;
|
|
8076
8713
|
f.vel.x *= 0.7;
|
|
@@ -8103,8 +8740,8 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
8103
8740
|
}
|
|
8104
8741
|
/** Tip the fragment towards lying on its flattest face. */
|
|
8105
8742
|
settle(f, dt) {
|
|
8106
|
-
const
|
|
8107
|
-
this.m.makeRotationFromQuaternion(
|
|
8743
|
+
const mesh2 = f.mesh;
|
|
8744
|
+
this.m.makeRotationFromQuaternion(mesh2.quaternion);
|
|
8108
8745
|
const e = this.m.elements;
|
|
8109
8746
|
const up = [e[1], e[5], e[9]];
|
|
8110
8747
|
const half = [f.half.x, f.half.y, f.half.z];
|
|
@@ -8119,8 +8756,8 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
8119
8756
|
this.v.set(e[axis2 * 4], e[axis2 * 4 + 1], e[axis2 * 4 + 2]).multiplyScalar(sign);
|
|
8120
8757
|
this.w.set(0, 1, 0);
|
|
8121
8758
|
this.dq.setFromUnitVectors(this.v, this.w);
|
|
8122
|
-
this.q.copy(this.dq).multiply(
|
|
8123
|
-
|
|
8759
|
+
this.q.copy(this.dq).multiply(mesh2.quaternion);
|
|
8760
|
+
mesh2.quaternion.slerp(this.q, clamp6(dt * 7, 0, 1));
|
|
8124
8761
|
}
|
|
8125
8762
|
/** Remove the fragments of one object (after `restore`). */
|
|
8126
8763
|
removeHome(home) {
|
|
@@ -8192,13 +8829,13 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
8192
8829
|
}
|
|
8193
8830
|
}
|
|
8194
8831
|
while (this.spots.length >= this.cap) this.remove(this.spots[0]);
|
|
8195
|
-
const
|
|
8832
|
+
const mesh2 = new this.THREE.Mesh(this.geometry, this.material(kind, color));
|
|
8196
8833
|
const y = this.groundAt(x, z) + 4e-3 + this.spots.length % 8 * 4e-4;
|
|
8197
|
-
|
|
8198
|
-
|
|
8199
|
-
|
|
8200
|
-
this.scene.add(
|
|
8201
|
-
this.spots.push({ mesh, kind, home, x, z, radius: 1e-3, target: Math.min(MAX_RADIUS, radius) });
|
|
8834
|
+
mesh2.position.set(x, y, z);
|
|
8835
|
+
mesh2.scale.setScalar(1e-3);
|
|
8836
|
+
mesh2.renderOrder = 1;
|
|
8837
|
+
this.scene.add(mesh2);
|
|
8838
|
+
this.spots.push({ mesh: mesh2, kind, home, x, z, radius: 1e-3, target: Math.min(MAX_RADIUS, radius) });
|
|
8202
8839
|
}
|
|
8203
8840
|
remove(s) {
|
|
8204
8841
|
const i = this.spots.indexOf(s);
|
|
@@ -8578,7 +9215,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
8578
9215
|
/** Bars drawn now, over every part. */
|
|
8579
9216
|
get count() {
|
|
8580
9217
|
let n = 0;
|
|
8581
|
-
for (const
|
|
9218
|
+
for (const mesh2 of this.cages.values()) n += mesh2.count;
|
|
8582
9219
|
return n;
|
|
8583
9220
|
}
|
|
8584
9221
|
/** Meshes of the live cages (tests and picking). */
|
|
@@ -8589,25 +9226,25 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
8589
9226
|
set(key, bars) {
|
|
8590
9227
|
this.remove(key);
|
|
8591
9228
|
if (bars.length === 0) return;
|
|
8592
|
-
const
|
|
9229
|
+
const mesh2 = new this.THREE.InstancedMesh(this.geometry, this.material, bars.length);
|
|
8593
9230
|
bars.forEach(([a, b], i) => {
|
|
8594
9231
|
this.dir.set(b[0] - a[0], b[1] - a[1], b[2] - a[2]);
|
|
8595
9232
|
const length = this.dir.length();
|
|
8596
9233
|
this.mid.set((a[0] + b[0]) / 2, (a[1] + b[1]) / 2, (a[2] + b[2]) / 2);
|
|
8597
9234
|
this.q.setFromUnitVectors(this.up, length > 1e-9 ? this.dir.divideScalar(length) : this.up);
|
|
8598
9235
|
this.m.compose(this.mid, this.q, this.scale.set(1, Math.max(length, 1e-4), 1));
|
|
8599
|
-
|
|
9236
|
+
mesh2.setMatrixAt(i, this.m);
|
|
8600
9237
|
});
|
|
8601
|
-
|
|
8602
|
-
|
|
8603
|
-
this.scene.add(
|
|
8604
|
-
this.cages.set(key,
|
|
9238
|
+
mesh2.instanceMatrix.needsUpdate = true;
|
|
9239
|
+
mesh2.castShadow = true;
|
|
9240
|
+
this.scene.add(mesh2);
|
|
9241
|
+
this.cages.set(key, mesh2);
|
|
8605
9242
|
}
|
|
8606
9243
|
remove(key) {
|
|
8607
|
-
const
|
|
8608
|
-
if (!
|
|
8609
|
-
this.scene.remove(
|
|
8610
|
-
|
|
9244
|
+
const mesh2 = this.cages.get(key);
|
|
9245
|
+
if (!mesh2) return;
|
|
9246
|
+
this.scene.remove(mesh2);
|
|
9247
|
+
mesh2.dispose();
|
|
8611
9248
|
this.cages.delete(key);
|
|
8612
9249
|
}
|
|
8613
9250
|
/** Remove the cages of every part of `object` (keys are `object|part`). */
|
|
@@ -8626,9 +9263,9 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
8626
9263
|
|
|
8627
9264
|
// ../game-destruction/dist/index.js
|
|
8628
9265
|
var EPS = 1e-9;
|
|
8629
|
-
var
|
|
9266
|
+
var IDENTITY2 = [0, 0, 0, 1];
|
|
8630
9267
|
var quat = {
|
|
8631
|
-
identity: () => [
|
|
9268
|
+
identity: () => [IDENTITY2[0], IDENTITY2[1], IDENTITY2[2], IDENTITY2[3]],
|
|
8632
9269
|
/** Hamilton product `a * b` (apply `b` first, then `a`). */
|
|
8633
9270
|
mul: (a, b) => [
|
|
8634
9271
|
a[3] * b[0] + a[0] * b[3] + a[1] * b[2] - a[2] * b[1],
|
|
@@ -9951,25 +10588,25 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
9951
10588
|
/**
|
|
9952
10589
|
* @param range vertex range `[v0, v1)` of a merged mesh this part is drawn by (see `MeshRange`); `hosts` caches the shared state per mesh for one `bind`.
|
|
9953
10590
|
*/
|
|
9954
|
-
makeMeshVis(
|
|
10591
|
+
makeMeshVis(mesh2, home, range, hosts) {
|
|
9955
10592
|
let host = null;
|
|
9956
10593
|
if (range) {
|
|
9957
|
-
host = hosts?.get(
|
|
10594
|
+
host = hosts?.get(mesh2) ?? null;
|
|
9958
10595
|
if (!host) {
|
|
9959
|
-
host = { mesh, origGeometry:
|
|
9960
|
-
hosts?.set(
|
|
10596
|
+
host = { mesh: mesh2, origGeometry: mesh2.geometry, origMaterial: mesh2.material, ownGeo: false, work: null, ownMat: false, sharers: [] };
|
|
10597
|
+
hosts?.set(mesh2, host);
|
|
9961
10598
|
}
|
|
9962
10599
|
}
|
|
9963
10600
|
const mv = {
|
|
9964
|
-
mesh,
|
|
10601
|
+
mesh: mesh2,
|
|
9965
10602
|
home,
|
|
9966
|
-
origGeometry:
|
|
9967
|
-
origMaterial:
|
|
9968
|
-
origVisible:
|
|
9969
|
-
origParent:
|
|
9970
|
-
origPosition:
|
|
9971
|
-
origQuaternion:
|
|
9972
|
-
origScale:
|
|
10603
|
+
origGeometry: mesh2.geometry,
|
|
10604
|
+
origMaterial: mesh2.material,
|
|
10605
|
+
origVisible: mesh2.visible,
|
|
10606
|
+
origParent: mesh2.parent,
|
|
10607
|
+
origPosition: mesh2.position.clone(),
|
|
10608
|
+
origQuaternion: mesh2.quaternion.clone(),
|
|
10609
|
+
origScale: mesh2.scale.clone(),
|
|
9973
10610
|
ownMat: false,
|
|
9974
10611
|
ownGeo: false,
|
|
9975
10612
|
work: null,
|
|
@@ -10094,15 +10731,15 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
10094
10731
|
* Returns false when nothing was changed (too far, low quality on a heavy mesh, or no editable positions).
|
|
10095
10732
|
*/
|
|
10096
10733
|
applyDent(mv, worldPoint, worldNormal, dent) {
|
|
10097
|
-
const
|
|
10734
|
+
const mesh2 = mv.mesh;
|
|
10098
10735
|
if (this.lowQuality && this.vertexCount(mv) > 2e4) return false;
|
|
10099
|
-
|
|
10100
|
-
const s =
|
|
10101
|
-
const lp =
|
|
10102
|
-
const ln = this.b.copy(worldNormal).transformDirection(this.m4.copy(
|
|
10736
|
+
mesh2.updateWorldMatrix(true, false);
|
|
10737
|
+
const s = mesh2.matrixWorld.getMaxScaleOnAxis() || 1;
|
|
10738
|
+
const lp = mesh2.worldToLocal(this.a.copy(worldPoint));
|
|
10739
|
+
const ln = this.b.copy(worldNormal).transformDirection(this.m4.copy(mesh2.matrixWorld).invert()).normalize();
|
|
10103
10740
|
const r = dent.radius / s;
|
|
10104
10741
|
const depth = dent.depth / s;
|
|
10105
|
-
const geo =
|
|
10742
|
+
const geo = mesh2.geometry;
|
|
10106
10743
|
let bb;
|
|
10107
10744
|
if (mv.host) bb = this.localBox(mv, this.lbox);
|
|
10108
10745
|
else {
|
|
@@ -10112,7 +10749,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
10112
10749
|
if (bb && !bb.isEmpty() && bb.distanceToPoint(lp) > r) return false;
|
|
10113
10750
|
if (!this.ownGeometry(mv)) return false;
|
|
10114
10751
|
const work = mv.host ? mv.host.work : mv.work;
|
|
10115
|
-
const pos = positionAttr(
|
|
10752
|
+
const pos = positionAttr(mesh2.geometry);
|
|
10116
10753
|
const r2 = r * r;
|
|
10117
10754
|
let touched = false;
|
|
10118
10755
|
const px = lp.x;
|
|
@@ -10178,11 +10815,11 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
10178
10815
|
// Decals
|
|
10179
10816
|
// ------------------------------------------------------------------------------------------------------------------------------------
|
|
10180
10817
|
/** Decal pose in mesh space: position and a rotation taking +Z to the surface normal. */
|
|
10181
|
-
decalPose(
|
|
10182
|
-
|
|
10183
|
-
const s =
|
|
10184
|
-
const ln = worldNormal.clone().transformDirection(this.m4.copy(
|
|
10185
|
-
const pos =
|
|
10818
|
+
decalPose(mesh2, worldPoint, worldNormal, lift) {
|
|
10819
|
+
mesh2.updateWorldMatrix(true, false);
|
|
10820
|
+
const s = mesh2.matrixWorld.getMaxScaleOnAxis() || 1;
|
|
10821
|
+
const ln = worldNormal.clone().transformDirection(this.m4.copy(mesh2.matrixWorld).invert()).normalize();
|
|
10822
|
+
const pos = mesh2.worldToLocal(worldPoint.clone()).addScaledVector(ln, lift / s);
|
|
10186
10823
|
const quat2 = new this.THREE.Quaternion().setFromUnitVectors(new this.THREE.Vector3(0, 0, 1), ln);
|
|
10187
10824
|
return { s, pos, quat: quat2 };
|
|
10188
10825
|
}
|
|
@@ -10318,7 +10955,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
10318
10955
|
if (Math.abs(m - pv.meltApplied) < 0.01) return;
|
|
10319
10956
|
pv.meltApplied = m;
|
|
10320
10957
|
for (const mv of pv.meshes) {
|
|
10321
|
-
const
|
|
10958
|
+
const mesh2 = mv.mesh;
|
|
10322
10959
|
if (mv.host) {
|
|
10323
10960
|
mv.meltApplied = m;
|
|
10324
10961
|
mv.touched = true;
|
|
@@ -10326,27 +10963,27 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
10326
10963
|
continue;
|
|
10327
10964
|
}
|
|
10328
10965
|
if (mv.meltApplied === 0 && m > 0) {
|
|
10329
|
-
|
|
10330
|
-
mv.bottomY = this.box.setFromObject(
|
|
10966
|
+
mesh2.updateWorldMatrix(true, false);
|
|
10967
|
+
mv.bottomY = this.box.setFromObject(mesh2).min.y;
|
|
10331
10968
|
}
|
|
10332
10969
|
mv.meltApplied = m;
|
|
10333
10970
|
mv.moved = true;
|
|
10334
10971
|
const sy = lerp5(1, 0.25, m);
|
|
10335
10972
|
const sxz = 1 + 0.18 * m;
|
|
10336
|
-
|
|
10337
|
-
|
|
10338
|
-
|
|
10339
|
-
const bottom = this.box.setFromObject(
|
|
10973
|
+
mesh2.scale.set(mv.origScale.x * sxz, mv.origScale.y * sy, mv.origScale.z * sxz);
|
|
10974
|
+
mesh2.position.copy(mv.origPosition);
|
|
10975
|
+
mesh2.updateWorldMatrix(true, false);
|
|
10976
|
+
const bottom = this.box.setFromObject(mesh2).min.y;
|
|
10340
10977
|
const dy = mv.bottomY - bottom;
|
|
10341
|
-
if (Math.abs(dy) > 1e-6 &&
|
|
10342
|
-
|
|
10343
|
-
const inv = this.m4.copy(
|
|
10978
|
+
if (Math.abs(dy) > 1e-6 && mesh2.parent) {
|
|
10979
|
+
mesh2.parent.updateWorldMatrix(true, false);
|
|
10980
|
+
const inv = this.m4.copy(mesh2.parent.matrixWorld).invert();
|
|
10344
10981
|
this.a.set(0, dy, 0).applyMatrix4(inv);
|
|
10345
10982
|
this.b.set(0, 0, 0).applyMatrix4(inv);
|
|
10346
|
-
|
|
10983
|
+
mesh2.position.copy(mv.origPosition).add(this.a.sub(this.b));
|
|
10347
10984
|
}
|
|
10348
10985
|
if (!(this.lowQuality && this.vertexCount(mv) > 2e4) && this.ownGeometry(mv)) {
|
|
10349
|
-
this.writePositions(mv, positionAttr(
|
|
10986
|
+
this.writePositions(mv, positionAttr(mesh2.geometry));
|
|
10350
10987
|
}
|
|
10351
10988
|
}
|
|
10352
10989
|
}
|
|
@@ -10424,10 +11061,10 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
10424
11061
|
const sy = lerp5(1, 0.25, melt);
|
|
10425
11062
|
const sxz = 1 + 0.18 * melt;
|
|
10426
11063
|
for (let i = range[0] * 3, v = 0; i < range[1] * 3; i += 3, v++) {
|
|
10427
|
-
const
|
|
11064
|
+
const noise = (Math.imul(v + 1, 2654435761) >>> 0) % 1e3 / 1e3;
|
|
10428
11065
|
arr[i] = cx + (work[i] - cx) * sxz;
|
|
10429
11066
|
arr[i + 2] = cz + (work[i + 2] - cz) * sxz;
|
|
10430
|
-
arr[i + 1] = Math.max(minY, minY + (work[i + 1] - minY) * sy -
|
|
11067
|
+
arr[i + 1] = Math.max(minY, minY + (work[i + 1] - minY) * sy - noise * melt * h * 0.04);
|
|
10431
11068
|
}
|
|
10432
11069
|
}
|
|
10433
11070
|
/** The colour attribute of the host's current geometry (created white when there is none) with vertex colours switched on in its material. */
|
|
@@ -10619,30 +11256,30 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
10619
11256
|
this.restoreRanged(mv);
|
|
10620
11257
|
return;
|
|
10621
11258
|
}
|
|
10622
|
-
const
|
|
11259
|
+
const mesh2 = mv.mesh;
|
|
10623
11260
|
for (const d of mv.decals) this.disposeDecal(d);
|
|
10624
11261
|
mv.decals.length = 0;
|
|
10625
11262
|
if (mv.ownGeo) {
|
|
10626
|
-
|
|
10627
|
-
|
|
11263
|
+
mesh2.geometry.dispose();
|
|
11264
|
+
mesh2.geometry = mv.origGeometry;
|
|
10628
11265
|
mv.ownGeo = false;
|
|
10629
11266
|
mv.work = null;
|
|
10630
11267
|
}
|
|
10631
11268
|
if (mv.ownMat) {
|
|
10632
|
-
for (const m of materialsOf(
|
|
10633
|
-
|
|
11269
|
+
for (const m of materialsOf(mesh2.material)) m.dispose();
|
|
11270
|
+
mesh2.material = mv.origMaterial;
|
|
10634
11271
|
mv.ownMat = false;
|
|
10635
11272
|
mv.baseColors = null;
|
|
10636
11273
|
}
|
|
10637
|
-
|
|
10638
|
-
if (mv.origParent &&
|
|
10639
|
-
mv.origParent.add(
|
|
11274
|
+
mesh2.visible = mv.origVisible;
|
|
11275
|
+
if (mv.origParent && mesh2.parent !== mv.origParent) {
|
|
11276
|
+
mv.origParent.add(mesh2);
|
|
10640
11277
|
mv.moved = true;
|
|
10641
11278
|
}
|
|
10642
11279
|
if (mv.moved) {
|
|
10643
|
-
|
|
10644
|
-
|
|
10645
|
-
|
|
11280
|
+
mesh2.position.copy(mv.origPosition);
|
|
11281
|
+
mesh2.quaternion.copy(mv.origQuaternion);
|
|
11282
|
+
mesh2.scale.copy(mv.origScale);
|
|
10646
11283
|
mv.moved = false;
|
|
10647
11284
|
}
|
|
10648
11285
|
mv.meltApplied = 0;
|
|
@@ -11780,6 +12417,56 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
11780
12417
|
};
|
|
11781
12418
|
}
|
|
11782
12419
|
var GAME_SFX_BANK = { id: "game_sfx", sounds: [...GAME_SFX_CLASSES, GAME_SFX_FALLBACK].map((row) => noiseClassRecipe(row)) };
|
|
12420
|
+
var ATTACK = 2e-3;
|
|
12421
|
+
function lengthOf(d, attack) {
|
|
12422
|
+
if (typeof d === "number") return attack + d;
|
|
12423
|
+
if (Array.isArray(d)) return [attack + d[0], attack + d[1]];
|
|
12424
|
+
return { ...d, add: (d.add ?? 0) + attack };
|
|
12425
|
+
}
|
|
12426
|
+
var envelope = (attack) => [
|
|
12427
|
+
[0, 1e-4, "set", "fixed"],
|
|
12428
|
+
[attack, 1, "exp"],
|
|
12429
|
+
["1d", 1e-4, "exp", "fixed"]
|
|
12430
|
+
];
|
|
12431
|
+
function sceneNoise(o) {
|
|
12432
|
+
const a = o.a ?? ATTACK;
|
|
12433
|
+
const over = typeof o.d === "number" ? o.d : 0;
|
|
12434
|
+
return {
|
|
12435
|
+
filters: {
|
|
12436
|
+
mode: "serial",
|
|
12437
|
+
bank: [{ type: o.type ?? "lowpass", frequency: o.f2 === void 0 ? { set: o.f } : { set: o.f, to: o.f2, curve: "exp", over }, q: o.q ?? 0.7 }]
|
|
12438
|
+
},
|
|
12439
|
+
duration: lengthOf(o.d, a),
|
|
12440
|
+
gain: o.vol,
|
|
12441
|
+
...o.delay === void 0 ? {} : { at: o.delay },
|
|
12442
|
+
...o.wet === void 0 ? {} : { wet: o.wet },
|
|
12443
|
+
source: { kind: "noise", offset: "random", offsetScale: 1.5, loop: true },
|
|
12444
|
+
envelope: envelope(a)
|
|
12445
|
+
};
|
|
12446
|
+
}
|
|
12447
|
+
function sceneTone(o) {
|
|
12448
|
+
return {
|
|
12449
|
+
source: { kind: "osc", wave: o.wave ?? "sine", frequency: { from: o.f, to: o.f2 ?? "from", curve: "exp", over: "duration" } },
|
|
12450
|
+
duration: lengthOf(o.d, ATTACK),
|
|
12451
|
+
gain: o.vol,
|
|
12452
|
+
...o.delay === void 0 ? {} : { at: o.delay },
|
|
12453
|
+
...o.wet === void 0 ? {} : { wet: o.wet },
|
|
12454
|
+
envelope: envelope(ATTACK)
|
|
12455
|
+
};
|
|
12456
|
+
}
|
|
12457
|
+
var sceneMany = (count, make) => Array.from({ length: count }, make);
|
|
12458
|
+
function sceneRecipe(id, layers, line, options = {}) {
|
|
12459
|
+
return {
|
|
12460
|
+
id,
|
|
12461
|
+
bus: options.bus ?? "world",
|
|
12462
|
+
pan: true,
|
|
12463
|
+
layers,
|
|
12464
|
+
falloff: DISTANCE_CURVES.art_scene,
|
|
12465
|
+
...options.vars ? { vars: options.vars } : {},
|
|
12466
|
+
...options.group ? { group: options.group } : {},
|
|
12467
|
+
sources: [`cena:${line}`]
|
|
12468
|
+
};
|
|
12469
|
+
}
|
|
11783
12470
|
var BENCH_BANK = {
|
|
11784
12471
|
id: "audio_bench",
|
|
11785
12472
|
sounds: [
|
|
@@ -11827,88 +12514,42 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
11827
12514
|
};
|
|
11828
12515
|
|
|
11829
12516
|
// src/audio/recipes.ts
|
|
11830
|
-
var
|
|
11831
|
-
var lengthOf = (d, attack) => {
|
|
11832
|
-
if (typeof d === "number") return attack + d;
|
|
11833
|
-
if (Array.isArray(d)) return [attack + d[0], attack + d[1]];
|
|
11834
|
-
return { ...d, add: (d.add ?? 0) + attack };
|
|
11835
|
-
};
|
|
11836
|
-
var envelope = (attack) => [
|
|
11837
|
-
[0, 1e-4, "set", "fixed"],
|
|
11838
|
-
[attack, 1, "exp"],
|
|
11839
|
-
["1d", 1e-4, "exp", "fixed"]
|
|
11840
|
-
];
|
|
11841
|
-
function noise(o) {
|
|
11842
|
-
const a = o.a ?? ATTACK;
|
|
11843
|
-
const over = typeof o.d === "number" ? o.d : 0;
|
|
11844
|
-
return {
|
|
11845
|
-
filters: {
|
|
11846
|
-
mode: "serial",
|
|
11847
|
-
bank: [{ type: o.type ?? "lowpass", frequency: o.f2 === void 0 ? { set: o.f } : { set: o.f, to: o.f2, curve: "exp", over }, q: o.q ?? 0.7 }]
|
|
11848
|
-
},
|
|
11849
|
-
duration: lengthOf(o.d, a),
|
|
11850
|
-
gain: o.vol,
|
|
11851
|
-
...o.delay === void 0 ? {} : { at: o.delay },
|
|
11852
|
-
...o.wet === void 0 ? {} : { wet: o.wet },
|
|
11853
|
-
source: { kind: "noise", offset: "random", offsetScale: 1.5, loop: true },
|
|
11854
|
-
envelope: envelope(a)
|
|
11855
|
-
};
|
|
11856
|
-
}
|
|
11857
|
-
function tone(o) {
|
|
11858
|
-
return {
|
|
11859
|
-
source: { kind: "osc", wave: o.wave ?? "sine", frequency: { from: o.f, to: o.f2 ?? "from", curve: "exp", over: "duration" } },
|
|
11860
|
-
duration: lengthOf(o.d, ATTACK),
|
|
11861
|
-
gain: o.vol,
|
|
11862
|
-
...o.delay === void 0 ? {} : { at: o.delay },
|
|
11863
|
-
...o.wet === void 0 ? {} : { wet: o.wet },
|
|
11864
|
-
envelope: envelope(ATTACK)
|
|
11865
|
-
};
|
|
11866
|
-
}
|
|
11867
|
-
var many = (count, make) => Array.from({ length: count }, make);
|
|
11868
|
-
var scene = (id, layers, line, vars) => ({
|
|
11869
|
-
id,
|
|
11870
|
-
bus: "world",
|
|
11871
|
-
pan: true,
|
|
11872
|
-
layers,
|
|
11873
|
-
falloff: DISTANCE_CURVES.art_scene,
|
|
11874
|
-
...vars ? { vars } : {},
|
|
11875
|
-
sources: [`cena:${line}`]
|
|
11876
|
-
});
|
|
12517
|
+
var scene = (id, layers, line, vars) => sceneRecipe(id, layers, line, vars ? { vars } : {});
|
|
11877
12518
|
var boomLayers = (big) => [
|
|
11878
|
-
|
|
11879
|
-
|
|
11880
|
-
|
|
11881
|
-
...big ? [
|
|
11882
|
-
...
|
|
12519
|
+
sceneNoise({ f: 1200, f2: 120, d: 1.8, vol: 2, wet: 1.2 }),
|
|
12520
|
+
sceneTone({ f: 65, f2: 24, d: 1, vol: 1.8 }),
|
|
12521
|
+
sceneNoise({ type: "highpass", f: 1500, d: 0.2, vol: 0.8 }),
|
|
12522
|
+
...big ? [sceneNoise({ f: 500, f2: 90, a: 0.2, d: 2.4, vol: 1.2, wet: 1, delay: 0.15 })] : [],
|
|
12523
|
+
...sceneMany(8, () => sceneTone({ f: [2600, 5600], d: 0.05, vol: 0.08, delay: [0.4, 1.6] }))
|
|
11883
12524
|
];
|
|
11884
12525
|
var SCENE_SOUNDS = [
|
|
11885
12526
|
scene(
|
|
11886
12527
|
"glass_shatter",
|
|
11887
|
-
[
|
|
12528
|
+
[sceneNoise({ type: "highpass", f: 2800, d: 0.45, vol: 0.9, wet: 0.5 }), ...sceneMany(12, () => sceneTone({ f: [3e3, 7500], d: [0.06, 0.14], vol: 0.18, delay: [0, 0.55] }))],
|
|
11888
12529
|
"L1359 glass"
|
|
11889
12530
|
),
|
|
11890
12531
|
scene(
|
|
11891
12532
|
"wood_hit",
|
|
11892
|
-
[
|
|
12533
|
+
[sceneNoise({ type: "bandpass", f: 850, q: 1, d: 0.25, vol: 0.9, wet: 0.3 }), sceneTone({ f: 210, f2: 90, d: 0.1, vol: 0.6 }), sceneNoise({ type: "highpass", f: 2e3, d: 0.04, vol: 0.5 })],
|
|
11893
12534
|
"L1360 wood"
|
|
11894
12535
|
),
|
|
11895
|
-
scene("thunk", [
|
|
11896
|
-
scene("ping", [
|
|
11897
|
-
scene("clang", [
|
|
11898
|
-
scene("chip", [
|
|
12536
|
+
scene("thunk", [sceneNoise({ type: "bandpass", f: 700, q: 2, d: 0.07, vol: 0.4 })], "L1361 thunk"),
|
|
12537
|
+
scene("ping", [sceneTone({ f: [2600, 3500], f2: 1400, d: 0.14, vol: 0.18, wet: 0.3 })], "L1362 ping"),
|
|
12538
|
+
scene("clang", [sceneTone({ f: [520, 720], f2: 480, d: 0.5, vol: 0.35, wet: 0.4 }), sceneTone({ f: 1370, f2: 1300, d: 0.3, vol: 0.15 }), sceneNoise({ type: "highpass", f: 2e3, d: 0.05, vol: 0.5 })], "L1363 clang"),
|
|
12539
|
+
scene("chip", [sceneNoise({ type: "bandpass", f: 1600, q: 1.2, d: 0.06, vol: 0.5 })], "L1364 chip"),
|
|
11899
12540
|
scene(
|
|
11900
12541
|
"crumble",
|
|
11901
|
-
[
|
|
12542
|
+
[sceneNoise({ f: 900, f2: 200, d: 0.6, vol: 0.9, wet: 0.3 }), ...sceneMany(5, () => sceneNoise({ type: "bandpass", f: [500, 1400], q: 2, d: 0.05, vol: 0.4, delay: [0.1, 0.5] }))],
|
|
11902
12543
|
"L1365 crumble"
|
|
11903
12544
|
),
|
|
11904
12545
|
// `thud(x, z, v)`: `v` is the `scale` param (default 1)
|
|
11905
|
-
scene("thud", [
|
|
12546
|
+
scene("thud", [sceneTone({ f: 75, f2: 38, d: 0.22, vol: { param: "scale", scale: 0.6 } }), sceneNoise({ f: 420, d: 0.16, vol: { param: "scale", scale: 0.45 } })], "L1358 thud", { scale: 1 }),
|
|
11906
12547
|
// `hiss(x, z, d)`: `seconds` is the param `d` (default 1.2)
|
|
11907
|
-
scene("hiss", [
|
|
12548
|
+
scene("hiss", [sceneNoise({ type: "highpass", f: 3500, a: 0.05, d: { param: "seconds" }, vol: 0.35 })], "L1366 hiss", { seconds: 1.2 }),
|
|
11908
12549
|
scene("boom", boomLayers(false), "L1367 boom"),
|
|
11909
12550
|
scene("boom_big", boomLayers(true), "L1367 boom (big)"),
|
|
11910
|
-
scene("burst", [
|
|
11911
|
-
scene("crack", [
|
|
12551
|
+
scene("burst", [sceneNoise({ f: 700, f2: 120, d: 0.7, vol: 1.4, wet: 0.5 }), sceneNoise({ type: "highpass", f: 3e3, a: 0.05, d: 1.2, vol: 0.4, delay: 0.1 })], "L1357 burst"),
|
|
12552
|
+
scene("crack", [sceneNoise({ type: "highpass", f: 1800, d: 0.05, vol: 0.8 }), sceneTone({ f: 420, f2: 180, d: 0.06, vol: 0.4 })], "L1354 crack")
|
|
11912
12553
|
];
|
|
11913
12554
|
var EXPLOSION_BOOM = {
|
|
11914
12555
|
id: "explosion_boom",
|