@adatechnology/game-vfx-three 0.1.3 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.global.js +907 -215
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +101 -1
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.global.js
CHANGED
|
@@ -1374,77 +1374,77 @@ var GameVfxThree = (() => {
|
|
|
1374
1374
|
}));
|
|
1375
1375
|
}
|
|
1376
1376
|
function spawnPuff(pool, random, init) {
|
|
1377
|
-
const
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
return
|
|
1407
|
-
}
|
|
1408
|
-
function ageOrKeep2(
|
|
1409
|
-
|
|
1410
|
-
return
|
|
1411
|
-
}
|
|
1412
|
-
function moveOnRing(
|
|
1377
|
+
const puff3 = pool.acquire();
|
|
1378
|
+
puff3.x = init.x ?? 0;
|
|
1379
|
+
puff3.y = init.y ?? 0;
|
|
1380
|
+
puff3.z = init.z ?? 0;
|
|
1381
|
+
puff3.vx = init.vx ?? 0;
|
|
1382
|
+
puff3.vy = init.vy ?? 0;
|
|
1383
|
+
puff3.vz = init.vz ?? 0;
|
|
1384
|
+
puff3.s0 = init.s0 ?? 0.2;
|
|
1385
|
+
puff3.s1 = init.s1 ?? 1;
|
|
1386
|
+
puff3.sg = init.sg ?? 0.1;
|
|
1387
|
+
puff3.gk = init.gk ?? 6;
|
|
1388
|
+
puff3.life = init.life ?? 3;
|
|
1389
|
+
puff3.t = 0;
|
|
1390
|
+
puff3.h0 = init.h0 ?? 0;
|
|
1391
|
+
puff3.hl = init.hl ?? 0.4;
|
|
1392
|
+
puff3.drag = init.drag ?? 3;
|
|
1393
|
+
puff3.buoy = init.buoy ?? 0.5;
|
|
1394
|
+
puff3.grav = init.grav ?? 0;
|
|
1395
|
+
puff3.kind = init.kind ?? 0;
|
|
1396
|
+
puff3.seed = random.next();
|
|
1397
|
+
puff3.wind = init.wind ?? 1;
|
|
1398
|
+
puff3.color = init.color ?? SMOKE_COLORS.grey;
|
|
1399
|
+
puff3.ring = init.ring ?? null;
|
|
1400
|
+
puff3.ph = init.ph ?? 0;
|
|
1401
|
+
puff3.th = init.th ?? 0;
|
|
1402
|
+
puff3.rng = random;
|
|
1403
|
+
puff3.age = 0;
|
|
1404
|
+
puff3.heat = 0;
|
|
1405
|
+
puff3.size = 0;
|
|
1406
|
+
return puff3;
|
|
1407
|
+
}
|
|
1408
|
+
function ageOrKeep2(puff3, dt) {
|
|
1409
|
+
puff3.t += dt;
|
|
1410
|
+
return puff3.t < puff3.life;
|
|
1411
|
+
}
|
|
1412
|
+
function moveOnRing(puff3, ring2, wind) {
|
|
1413
1413
|
const ringTime = ring2.t;
|
|
1414
1414
|
const centerY = ring2.y0 + ring2.rise * (1 - Math.exp(-ringTime * ring2.rk));
|
|
1415
1415
|
const majorRadius = ring2.R0 + (ring2.R1 - ring2.R0) * (1 - Math.exp(-ringTime * 1.6));
|
|
1416
|
-
const theta =
|
|
1416
|
+
const theta = puff3.th + ringTime * ring2.roll;
|
|
1417
1417
|
const minorRadius = ring2.r * (0.8 + 0.4 * Math.min(1, ringTime));
|
|
1418
1418
|
const radius = majorRadius + minorRadius * Math.cos(theta);
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
}
|
|
1423
|
-
function moveFree(
|
|
1424
|
-
const damping = Math.exp(-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
if (
|
|
1433
|
-
|
|
1434
|
-
if (
|
|
1419
|
+
puff3.x = ring2.x + Math.cos(puff3.ph) * radius + wind.x * ringTime * 0.6;
|
|
1420
|
+
puff3.z = ring2.z + Math.sin(puff3.ph) * radius + wind.z * ringTime * 0.6;
|
|
1421
|
+
puff3.y = centerY + minorRadius * Math.sin(theta);
|
|
1422
|
+
}
|
|
1423
|
+
function moveFree(puff3, dt, age, heat, wind) {
|
|
1424
|
+
const damping = Math.exp(-puff3.drag * dt);
|
|
1425
|
+
puff3.vx *= damping;
|
|
1426
|
+
puff3.vy *= damping;
|
|
1427
|
+
puff3.vz *= damping;
|
|
1428
|
+
puff3.vy += (puff3.buoy * (heat > 0 ? 1.6 : 1) - puff3.grav) * dt;
|
|
1429
|
+
puff3.x += (puff3.vx + wind.x * puff3.wind * age) * dt;
|
|
1430
|
+
puff3.y += puff3.vy * dt;
|
|
1431
|
+
puff3.z += (puff3.vz + wind.z * puff3.wind * age) * dt;
|
|
1432
|
+
if (puff3.y < puff3.s0 * FLOOR_FRACTION) {
|
|
1433
|
+
puff3.y = puff3.s0 * FLOOR_FRACTION;
|
|
1434
|
+
if (puff3.vy < 0) puff3.vy *= FLOOR_BOUNCE;
|
|
1435
1435
|
}
|
|
1436
1436
|
}
|
|
1437
1437
|
function updatePuffs(pool, dt, wind) {
|
|
1438
1438
|
pool.compact(ageOrKeep2, dt);
|
|
1439
|
-
for (const
|
|
1440
|
-
const age =
|
|
1441
|
-
const heat =
|
|
1442
|
-
if (
|
|
1443
|
-
else moveFree(
|
|
1444
|
-
const size =
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1439
|
+
for (const puff3 of pool.items) {
|
|
1440
|
+
const age = puff3.t / puff3.life;
|
|
1441
|
+
const heat = puff3.h0 > 0 ? puff3.h0 * Math.pow(Math.max(0, 1 - puff3.t / puff3.hl), 1.25) : 0;
|
|
1442
|
+
if (puff3.ring) moveOnRing(puff3, puff3.ring, wind);
|
|
1443
|
+
else moveFree(puff3, dt, age, heat, wind);
|
|
1444
|
+
const size = puff3.s0 + (puff3.s1 - puff3.s0) * (1 - Math.exp(-puff3.t * puff3.gk)) + puff3.sg * Math.min(puff3.t, GROWTH_CAP_SECONDS);
|
|
1445
|
+
puff3.size = size * Math.min(1, puff3.t * ARRIVAL_FRAME + ARRIVAL_BASE);
|
|
1446
|
+
puff3.age = age;
|
|
1447
|
+
puff3.heat = heat;
|
|
1448
1448
|
}
|
|
1449
1449
|
}
|
|
1450
1450
|
var GROUND_LIFT = 0.02;
|
|
@@ -1501,9 +1501,9 @@ var GameVfxThree = (() => {
|
|
|
1501
1501
|
var HOT_GLOW_COLOR = [1, 0.45, 0.12];
|
|
1502
1502
|
function addPuff(core, random, init) {
|
|
1503
1503
|
core.spawned.puffs++;
|
|
1504
|
-
const
|
|
1505
|
-
core.trace?.puff?.(
|
|
1506
|
-
return
|
|
1504
|
+
const puff3 = spawnPuff(core.puffs, random, init);
|
|
1505
|
+
core.trace?.puff?.(puff3);
|
|
1506
|
+
return puff3;
|
|
1507
1507
|
}
|
|
1508
1508
|
function addSpark(core, init) {
|
|
1509
1509
|
core.spawned.sparks++;
|
|
@@ -1685,6 +1685,7 @@ var GameVfxThree = (() => {
|
|
|
1685
1685
|
var neg = call("neg");
|
|
1686
1686
|
var abs = call("abs");
|
|
1687
1687
|
var sqrt = call("sqrt");
|
|
1688
|
+
var exp = call("exp");
|
|
1688
1689
|
var sin = call("sin");
|
|
1689
1690
|
var cos = call("cos");
|
|
1690
1691
|
var atan2 = call("atan2");
|
|
@@ -1730,10 +1731,12 @@ var GameVfxThree = (() => {
|
|
|
1730
1731
|
var INDEX = { $: "index" };
|
|
1731
1732
|
var QUALITY = { $: "quality" };
|
|
1732
1733
|
var FRESH = { $: "fresh" };
|
|
1734
|
+
var DIRECTION = { $: "direction" };
|
|
1733
1735
|
var CAMERA_POSITION = { $: "cameraPosition" };
|
|
1734
1736
|
var burst = (system, count, spawn2) => ({ op: "burst", system, count, spawn: spawn2 });
|
|
1735
1737
|
var spawn = (system, options) => ({ op: "spawn", system, spawn: options });
|
|
1736
1738
|
var emit = (key, system, rate, options) => ({ op: "emit", key, system, rate, spawn: options });
|
|
1739
|
+
var mesh = (options) => ({ op: "mesh", spawn: options });
|
|
1737
1740
|
var debris = (options) => ({ op: "debris", spawn: options });
|
|
1738
1741
|
var decal = (...args) => ({ op: "decal", args });
|
|
1739
1742
|
var ring = (...args) => ({ op: "ring", args });
|
|
@@ -2745,6 +2748,241 @@ var GameVfxThree = (() => {
|
|
|
2745
2748
|
)
|
|
2746
2749
|
]
|
|
2747
2750
|
};
|
|
2751
|
+
var SPOTS_X = [-3, 1, 5];
|
|
2752
|
+
var SPOTS_Z = [-1, -2.4, 0.4];
|
|
2753
|
+
var FOG_AND_ASH = {
|
|
2754
|
+
id: "fog_and_ash",
|
|
2755
|
+
pageId: "neblina",
|
|
2756
|
+
team: "world",
|
|
2757
|
+
budget: { particles: 120, lights: 1 },
|
|
2758
|
+
loop: 0,
|
|
2759
|
+
view: { eye: [3, 1.8, 7.5], target: [-3, 1.2, -1] },
|
|
2760
|
+
setup: [
|
|
2761
|
+
cue("fog", { density: 0.075 }),
|
|
2762
|
+
cue("lamp_cone", { visible: true }),
|
|
2763
|
+
cue("zombie_visible", { index: -1, visible: false }),
|
|
2764
|
+
repeat(
|
|
2765
|
+
SPOTS_X.length,
|
|
2766
|
+
set("turn", rnd(-0.6, 0.6)),
|
|
2767
|
+
behavior("walkers", "place", { index: INDEX, x: pick(SPOTS_X, INDEX), z: pick(SPOTS_Z, INDEX), facing: variable("turn") })
|
|
2768
|
+
)
|
|
2769
|
+
],
|
|
2770
|
+
timeline: [],
|
|
2771
|
+
tick: [
|
|
2772
|
+
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 }),
|
|
2773
|
+
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 })
|
|
2774
|
+
]
|
|
2775
|
+
};
|
|
2776
|
+
var RAIN_CAPACITY = 4e3;
|
|
2777
|
+
var FALL_SPEED = 15;
|
|
2778
|
+
var WIND_PER_FALL = 0.07;
|
|
2779
|
+
var STREAK_SLANT = 0.04;
|
|
2780
|
+
var STREAK_LENGTH = 0.6;
|
|
2781
|
+
var BOX_X = [-15, 15];
|
|
2782
|
+
var BOX_Z = [-6, 16];
|
|
2783
|
+
var START_HEIGHT = [0, 16];
|
|
2784
|
+
var REENTRY_HEIGHT = [14, 17];
|
|
2785
|
+
var SPLASH_CHANCE = 0.35;
|
|
2786
|
+
var SPLASH_RANGE = 12;
|
|
2787
|
+
var SPRITE_CHANCE = 0.5;
|
|
2788
|
+
var UP9 = [0, 1, 0];
|
|
2789
|
+
var WORKSHOP_PUDDLES = [
|
|
2790
|
+
[-1.5, 2.2, 1.6, 0.9],
|
|
2791
|
+
[3, 3.6, 1.1, 0.7],
|
|
2792
|
+
[-6, 3.2, 1.3, 0.8],
|
|
2793
|
+
[1.4, -2.2, 0.9, 0.5]
|
|
2794
|
+
];
|
|
2795
|
+
var inPuddle = (puddles, x, z) => puddles.some((p) => ((x - p[0]) / p[2]) ** 2 + ((z - p[1]) / p[3]) ** 2 < 1);
|
|
2796
|
+
var RainField = class {
|
|
2797
|
+
constructor(engine) {
|
|
2798
|
+
__publicField(this, "engine", engine);
|
|
2799
|
+
__publicField(this, "positions", new Float32Array(RAIN_CAPACITY * 6));
|
|
2800
|
+
__publicField(this, "count", 0);
|
|
2801
|
+
__publicField(this, "wind", 1);
|
|
2802
|
+
__publicField(this, "on", false);
|
|
2803
|
+
__publicField(this, "centerX", 0);
|
|
2804
|
+
__publicField(this, "centerZ", 0);
|
|
2805
|
+
__publicField(this, "puddles", WORKSHOP_PUDDLES);
|
|
2806
|
+
__publicField(this, "puddleAt");
|
|
2807
|
+
}
|
|
2808
|
+
/** `initRain` (W321): `count` streaks (thinned by the quality), each drawn at a random place in the box. */
|
|
2809
|
+
init(count, wind) {
|
|
2810
|
+
const { random } = this.engine;
|
|
2811
|
+
this.count = Math.min(RAIN_CAPACITY, Math.round(count * this.engine.context.quality.mult));
|
|
2812
|
+
this.wind = wind;
|
|
2813
|
+
this.on = true;
|
|
2814
|
+
for (let index = 0; index < this.count; index++) {
|
|
2815
|
+
const offset = index * 6;
|
|
2816
|
+
const x = random.between(BOX_X[0], BOX_X[1]);
|
|
2817
|
+
const y = random.between(START_HEIGHT[0], START_HEIGHT[1]);
|
|
2818
|
+
const z = random.between(BOX_Z[0], BOX_Z[1]);
|
|
2819
|
+
this.set(offset, x, y, z);
|
|
2820
|
+
}
|
|
2821
|
+
}
|
|
2822
|
+
/**
|
|
2823
|
+
* 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
|
|
2824
|
+
* starts at a random place of the box, as `init` draws it) and the wind slants them. The golden never calls it.
|
|
2825
|
+
*/
|
|
2826
|
+
drive(count, wind, centerX, centerZ) {
|
|
2827
|
+
const { random } = this.engine;
|
|
2828
|
+
const target = Math.max(0, Math.min(RAIN_CAPACITY, Math.round(count * this.engine.context.quality.mult)));
|
|
2829
|
+
this.wind = wind;
|
|
2830
|
+
this.centerX = centerX;
|
|
2831
|
+
this.centerZ = centerZ;
|
|
2832
|
+
this.on = target > 0;
|
|
2833
|
+
for (let index = this.count; index < target; index++) {
|
|
2834
|
+
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);
|
|
2835
|
+
}
|
|
2836
|
+
this.count = target;
|
|
2837
|
+
}
|
|
2838
|
+
/** `updateRain` (W322-329). `camera` is where the eye is; `splash` lets the drops that land leave a splash. */
|
|
2839
|
+
update(dt, splash, camera2) {
|
|
2840
|
+
if (!this.on) return;
|
|
2841
|
+
const { random, context } = this.engine;
|
|
2842
|
+
const positions = this.positions;
|
|
2843
|
+
const fall = FALL_SPEED * dt;
|
|
2844
|
+
const slant = this.wind * fall * WIND_PER_FALL;
|
|
2845
|
+
const reach = SPLASH_RANGE / (1 + context.quality.level);
|
|
2846
|
+
for (let index = 0; index < this.count; index++) {
|
|
2847
|
+
const o = index * 6;
|
|
2848
|
+
positions[o] += slant;
|
|
2849
|
+
positions[o + 3] += slant;
|
|
2850
|
+
positions[o + 1] -= fall;
|
|
2851
|
+
positions[o + 4] -= fall;
|
|
2852
|
+
const ground = context.groundAt(positions[o], positions[o + 2]);
|
|
2853
|
+
if (positions[o + 4] < ground) {
|
|
2854
|
+
const x = positions[o];
|
|
2855
|
+
const z = positions[o + 2];
|
|
2856
|
+
if (splash && random.next() < SPLASH_CHANCE) {
|
|
2857
|
+
const distance = Math.hypot(x - camera2[0], z - camera2[2]);
|
|
2858
|
+
if (distance < reach) {
|
|
2859
|
+
if (random.next() < SPRITE_CHANCE) {
|
|
2860
|
+
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 });
|
|
2861
|
+
}
|
|
2862
|
+
if (this.puddleAt ? this.puddleAt(x, z) : inPuddle(this.puddles, x, z)) {
|
|
2863
|
+
this.engine.ring([[x, ground + 0.012, z], 0.01, random.between(0.12, 0.25), random.between(0.4, 0.6), 6978192]);
|
|
2864
|
+
}
|
|
2865
|
+
}
|
|
2866
|
+
}
|
|
2867
|
+
const nx = random.between(BOX_X[0], BOX_X[1]) + this.centerX;
|
|
2868
|
+
const ny = random.between(REENTRY_HEIGHT[0], REENTRY_HEIGHT[1]);
|
|
2869
|
+
const nz = random.between(BOX_Z[0], BOX_Z[1]) + this.centerZ;
|
|
2870
|
+
this.set(o, nx, ny, nz);
|
|
2871
|
+
}
|
|
2872
|
+
}
|
|
2873
|
+
}
|
|
2874
|
+
/** `rain.visible = false; RN.on = false` (W440): the field stops; the streaks stay where they were. */
|
|
2875
|
+
clear() {
|
|
2876
|
+
this.on = false;
|
|
2877
|
+
}
|
|
2878
|
+
set(offset, x, y, z) {
|
|
2879
|
+
const positions = this.positions;
|
|
2880
|
+
positions[offset] = x;
|
|
2881
|
+
positions[offset + 1] = y;
|
|
2882
|
+
positions[offset + 2] = z;
|
|
2883
|
+
positions[offset + 3] = x + this.wind * STREAK_SLANT;
|
|
2884
|
+
positions[offset + 4] = y - STREAK_LENGTH;
|
|
2885
|
+
positions[offset + 5] = z;
|
|
2886
|
+
}
|
|
2887
|
+
};
|
|
2888
|
+
var DROPS = [900, 2200, 4e3];
|
|
2889
|
+
var SLANT = [0.3, 1.2, 4.5];
|
|
2890
|
+
var STORM = 2;
|
|
2891
|
+
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)));
|
|
2892
|
+
var RAIN_AND_PUDDLES = {
|
|
2893
|
+
id: "rain_and_puddles",
|
|
2894
|
+
pageId: "chuva",
|
|
2895
|
+
team: "world",
|
|
2896
|
+
params: { id: "intensity", options: ["drizzle", "rain", "storm"], default: 1 },
|
|
2897
|
+
budget: { particles: 4e3, decals: 4 },
|
|
2898
|
+
loop: 0,
|
|
2899
|
+
view: { eye: [2, 2, 7], target: [-1, 0.6, 1] },
|
|
2900
|
+
setup: [
|
|
2901
|
+
cue("lamp_cone", { visible: true }),
|
|
2902
|
+
...WORKSHOP_PUDDLES.map(([x, z, radiusX, radiusZ]) => decal(x, 0, z, radiusX * 2, 790550, { grow: 0, life: 1e6, ar: radiusZ / radiusX }))
|
|
2903
|
+
],
|
|
2904
|
+
timeline: [
|
|
2905
|
+
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])) }),
|
|
2906
|
+
set("nextStrike", rnd(2, 4)),
|
|
2907
|
+
set("flash", -1)
|
|
2908
|
+
],
|
|
2909
|
+
tick: [
|
|
2910
|
+
behavior("rain", "update", { dt: DELTA, splash: gt(PARAM, 0) }),
|
|
2911
|
+
when(eq(PARAM, STORM), [
|
|
2912
|
+
when(gt(TIME, variable("nextStrike")), [set("nextStrike", add(TIME, rnd(3.5, 6))), set("flash", 0)]),
|
|
2913
|
+
when(ge(variable("flash"), 0), [
|
|
2914
|
+
set("flash", add(variable("flash"), DELTA)),
|
|
2915
|
+
set("light", FLASH_STEPS),
|
|
2916
|
+
cue("lightning", { intensity: variable("light") }),
|
|
2917
|
+
screen({ max: { white: mul(variable("light"), 0.12) } }),
|
|
2918
|
+
when(gt(variable("flash"), 0.4), [set("flash", -1), cue("lightning", { intensity: 0 })])
|
|
2919
|
+
]),
|
|
2920
|
+
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 })
|
|
2921
|
+
])
|
|
2922
|
+
]
|
|
2923
|
+
};
|
|
2924
|
+
var CAR_ORIGIN2 = [5.6, 0, 0.8];
|
|
2925
|
+
var CAR_ROTATION2 = [0, -0.4, 0];
|
|
2926
|
+
var carPoint = (x, y, z) => localToWorld(CAR_ORIGIN2, CAR_ROTATION2, [x, y, z]);
|
|
2927
|
+
var carDirection = (from, to) => normalized([to[0] - from[0], to[1] - from[1], to[2] - from[2]]);
|
|
2928
|
+
var BEAM_FROM = carPoint(0, 0.74, 2.15);
|
|
2929
|
+
var BEAM_DIRECTION = carDirection(BEAM_FROM, carPoint(0, 0.74, 3.15));
|
|
2930
|
+
var BEAM_SIDE = [BEAM_DIRECTION[2], 0, -BEAM_DIRECTION[0]];
|
|
2931
|
+
var WALKERS = 6;
|
|
2932
|
+
var WALK_SPEED2 = 0.7;
|
|
2933
|
+
var DROPS2 = 1800;
|
|
2934
|
+
var SLANT2 = 0.8;
|
|
2935
|
+
var startWalking = [
|
|
2936
|
+
set("spot", query("car", "point", rnd(-2, 2), 0, rnd(8, 18))),
|
|
2937
|
+
set("goal", query("car", "point", rnd(-0.6, 0.6), 0, 2.6)),
|
|
2938
|
+
behavior("walkers", "place", { index: INDEX, x: pick(variable("spot"), 0), z: pick(variable("spot"), 2), facing: 0 }),
|
|
2939
|
+
behavior("walkers", "walk", { index: INDEX, to: variable("goal"), speed: WALK_SPEED2 })
|
|
2940
|
+
];
|
|
2941
|
+
var HEADLIGHTS_IN_RAIN = {
|
|
2942
|
+
id: "headlights_in_rain",
|
|
2943
|
+
pageId: "farol",
|
|
2944
|
+
team: "vehicles",
|
|
2945
|
+
budget: { particles: 600, lights: 2 },
|
|
2946
|
+
loop: 0,
|
|
2947
|
+
view: { eye: [-2.5, 2, 5.5], target: [4, 1, 6] },
|
|
2948
|
+
setup: [
|
|
2949
|
+
cue("fog", { density: 0.05 }),
|
|
2950
|
+
cue("headlights", { on: true, intensity: 2.4, color: 16773584 }),
|
|
2951
|
+
behavior("rain", "init", { count: DROPS2, wind: SLANT2 }),
|
|
2952
|
+
repeat(WALKERS, ...startWalking)
|
|
2953
|
+
],
|
|
2954
|
+
timeline: [],
|
|
2955
|
+
tick: [
|
|
2956
|
+
behavior("rain", "update", { dt: DELTA, splash: true }),
|
|
2957
|
+
emit(
|
|
2958
|
+
"lit",
|
|
2959
|
+
"streak",
|
|
2960
|
+
600,
|
|
2961
|
+
local(
|
|
2962
|
+
"depth",
|
|
2963
|
+
rnd(1, 13),
|
|
2964
|
+
local(
|
|
2965
|
+
"spread",
|
|
2966
|
+
mul(variable("depth"), 0.33, sqrt(rand())),
|
|
2967
|
+
local(
|
|
2968
|
+
"turn",
|
|
2969
|
+
rnd(0, 6.283),
|
|
2970
|
+
local("base", vadd(BEAM_FROM, vscale(BEAM_DIRECTION, variable("depth")), vscale(BEAM_SIDE, mul(cos(variable("turn")), variable("spread")))), {
|
|
2971
|
+
p: vwith(variable("base"), 1, add(vy(variable("base")), mul(sin(variable("turn")), variable("spread"), 0.6))),
|
|
2972
|
+
v: [0.8, -14, 0],
|
|
2973
|
+
sp: 0,
|
|
2974
|
+
life: 0.06,
|
|
2975
|
+
len: 0.035,
|
|
2976
|
+
c0: 13622512,
|
|
2977
|
+
a: 0.9
|
|
2978
|
+
})
|
|
2979
|
+
)
|
|
2980
|
+
)
|
|
2981
|
+
)
|
|
2982
|
+
),
|
|
2983
|
+
repeat(WALKERS, when(not(query("walkers", "is_walking", INDEX)), startWalking))
|
|
2984
|
+
]
|
|
2985
|
+
};
|
|
2748
2986
|
var YAW = -Math.PI / 2;
|
|
2749
2987
|
var COS = Math.cos(YAW);
|
|
2750
2988
|
var SIN = Math.sin(YAW);
|
|
@@ -2772,10 +3010,6 @@ var GameVfxThree = (() => {
|
|
|
2772
3010
|
fireLight(0, [vx(variable("contact")), 0.34, vz(variable("contact"))], 1.6, mul(TIME, 3))
|
|
2773
3011
|
]
|
|
2774
3012
|
};
|
|
2775
|
-
var CAR_ORIGIN2 = [5.6, 0, 0.8];
|
|
2776
|
-
var CAR_ROTATION2 = [0, -0.4, 0];
|
|
2777
|
-
var carPoint = (x, y, z) => localToWorld(CAR_ORIGIN2, CAR_ROTATION2, [x, y, z]);
|
|
2778
|
-
var carDirection = (from, to) => normalized([to[0] - from[0], to[1] - from[1], to[2] - from[2]]);
|
|
2779
3013
|
var HOOD = carPoint(0, 1.02, 1.4);
|
|
2780
3014
|
var EXHAUST = carPoint(0.5, 0.3, -2.2);
|
|
2781
3015
|
var EXHAUST_DIRECTION = carDirection(EXHAUST, carPoint(0.5, 0.3, -3));
|
|
@@ -2809,7 +3043,7 @@ var GameVfxThree = (() => {
|
|
|
2809
3043
|
], [fireLightOff(0)])
|
|
2810
3044
|
]
|
|
2811
3045
|
};
|
|
2812
|
-
var
|
|
3046
|
+
var UP10 = [0, 1, 0];
|
|
2813
3047
|
var doorVelocity = (side) => {
|
|
2814
3048
|
const out = carPoint(side * 4, 3, 0.3);
|
|
2815
3049
|
const centre = carPoint(0, 0, 0.3);
|
|
@@ -2819,7 +3053,7 @@ var GameVfxThree = (() => {
|
|
|
2819
3053
|
call2("explode", vadd(query("car", "position"), [0, 0.6, 0]), 1.8, 2759188),
|
|
2820
3054
|
cue("car_burnt"),
|
|
2821
3055
|
behavior("car", "launch", { rise: 4.5, spin: 0.9 }),
|
|
2822
|
-
repeat(scaled(30), debris({ p: vadd(query("car", "position"), [0, 1.3, 0]), dir:
|
|
3056
|
+
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 })),
|
|
2823
3057
|
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 }),
|
|
2824
3058
|
...[-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 })),
|
|
2825
3059
|
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 })
|
|
@@ -2989,7 +3223,7 @@ var GameVfxThree = (() => {
|
|
|
2989
3223
|
])
|
|
2990
3224
|
]
|
|
2991
3225
|
};
|
|
2992
|
-
var
|
|
3226
|
+
var WALKERS2 = 6;
|
|
2993
3227
|
var NEAR = 9;
|
|
2994
3228
|
var RANGE = 7;
|
|
2995
3229
|
var RESTING_BPM = 70;
|
|
@@ -3005,7 +3239,7 @@ var GameVfxThree = (() => {
|
|
|
3005
3239
|
setup: [
|
|
3006
3240
|
cue("zombie_visible", { index: -1, visible: false }),
|
|
3007
3241
|
repeat(
|
|
3008
|
-
|
|
3242
|
+
WALKERS2,
|
|
3009
3243
|
set("startX", rnd(-4, 4)),
|
|
3010
3244
|
set("startZ", sub(rnd(-4, -2), mul(INDEX, 0.6))),
|
|
3011
3245
|
behavior("walkers", "place", { index: INDEX, x: variable("startX"), z: variable("startZ"), facing: 0 }),
|
|
@@ -3015,7 +3249,7 @@ var GameVfxThree = (() => {
|
|
|
3015
3249
|
timeline: [],
|
|
3016
3250
|
tick: [
|
|
3017
3251
|
set("nearest", 99),
|
|
3018
|
-
repeat(
|
|
3252
|
+
repeat(WALKERS2, set("nearest", min(variable("nearest"), vdist(walkerPoint, CAMERA_POSITION)))),
|
|
3019
3253
|
set("fear", clamp(div(sub(NEAR, variable("nearest")), RANGE), 0, 1)),
|
|
3020
3254
|
set("bpm", add(RESTING_BPM, mul(BPM_RISE, variable("fear")))),
|
|
3021
3255
|
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"))) } })]),
|
|
@@ -3082,7 +3316,7 @@ var GameVfxThree = (() => {
|
|
|
3082
3316
|
]
|
|
3083
3317
|
};
|
|
3084
3318
|
var FACING4 = [0, 0, 1];
|
|
3085
|
-
var
|
|
3319
|
+
var UP11 = [0, 1, 0];
|
|
3086
3320
|
var ORIGIN = [0, 0, 0];
|
|
3087
3321
|
var FORWARD4 = [0, 0, -1];
|
|
3088
3322
|
var IMPACT_MATERIALS = ["concrete", "metal", "wood", "glass", "flesh", "water"];
|
|
@@ -3212,12 +3446,148 @@ var GameVfxThree = (() => {
|
|
|
3212
3446
|
team: "destruction",
|
|
3213
3447
|
budget: { particles: 20, debris: 8 },
|
|
3214
3448
|
loop: 2,
|
|
3215
|
-
timeline: [call2("chips", ORIGIN,
|
|
3449
|
+
timeline: [call2("chips", ORIGIN, UP11, 8, 0.9), call2("rust_at", ORIGIN, 6)]
|
|
3216
3450
|
}
|
|
3217
3451
|
];
|
|
3218
|
-
var
|
|
3452
|
+
var PI = Math.PI;
|
|
3453
|
+
var SMOKE = { color: 9079430, width: 10, height: 8, gravity: -0.08, drag: 2.2, growth: 2.1 };
|
|
3454
|
+
var FLASH_SECONDS = 0.055;
|
|
3455
|
+
var FLASH_RAMP = [0.6, 0.9];
|
|
3456
|
+
var FLASH_OPACITY = 0.95;
|
|
3457
|
+
var FLAME_COLORS = [16742946, 16760896, 13121050, 16773296];
|
|
3458
|
+
var FLAME_ADDITIVE = 3;
|
|
3459
|
+
var ORIGIN2 = [0, 0, 0];
|
|
3460
|
+
var SIZE = variable("size");
|
|
3461
|
+
var wide = (width) => mul(sub(rand(), 0.5), width);
|
|
3462
|
+
var puff2 = (point, velocity, world, radius, life, opacity) => mesh({
|
|
3463
|
+
shape: "sphere",
|
|
3464
|
+
p: point,
|
|
3465
|
+
v: velocity,
|
|
3466
|
+
wv: world,
|
|
3467
|
+
r: radius,
|
|
3468
|
+
seg: SMOKE.width,
|
|
3469
|
+
seg2: SMOKE.height,
|
|
3470
|
+
life,
|
|
3471
|
+
c0: SMOKE.color,
|
|
3472
|
+
a: opacity,
|
|
3473
|
+
fade: true,
|
|
3474
|
+
lit: true,
|
|
3475
|
+
g: SMOKE.gravity,
|
|
3476
|
+
drag: SMOKE.drag,
|
|
3477
|
+
grow: SMOKE.growth
|
|
3478
|
+
});
|
|
3479
|
+
var flameBit = (point, velocity, world, radius, life) => [
|
|
3480
|
+
set("bitPoint", point),
|
|
3481
|
+
set("bitVelocity", velocity),
|
|
3482
|
+
set("bitWorld", world),
|
|
3483
|
+
set("bitRadius", radius),
|
|
3484
|
+
set("bitLife", life),
|
|
3485
|
+
set("bitColour", floor(mul(rand(), FLAME_COLORS.length))),
|
|
3486
|
+
mesh({
|
|
3487
|
+
shape: "icosahedron",
|
|
3488
|
+
p: variable("bitPoint"),
|
|
3489
|
+
v: variable("bitVelocity"),
|
|
3490
|
+
wv: variable("bitWorld"),
|
|
3491
|
+
r: variable("bitRadius"),
|
|
3492
|
+
seg: 1,
|
|
3493
|
+
rot: [mul(rand(), 3), mul(rand(), 3), 0],
|
|
3494
|
+
spin: [3, 4, 2],
|
|
3495
|
+
life: variable("bitLife"),
|
|
3496
|
+
c0: pick(FLAME_COLORS, variable("bitColour")),
|
|
3497
|
+
add: eq(variable("bitColour"), FLAME_ADDITIVE),
|
|
3498
|
+
a: 0.9,
|
|
3499
|
+
fade: true,
|
|
3500
|
+
g: -1.4,
|
|
3501
|
+
drag: 1.4,
|
|
3502
|
+
grow: 2.2
|
|
3503
|
+
})
|
|
3504
|
+
];
|
|
3505
|
+
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 });
|
|
3506
|
+
var MUZZLE_FLASH2 = {
|
|
3507
|
+
id: "viewmodel_muzzle_flash",
|
|
3508
|
+
pageId: "event:viewmodel_muzzle_flash",
|
|
3509
|
+
team: "weapons",
|
|
3510
|
+
budget: { particles: 12, lights: 1 },
|
|
3511
|
+
loop: 0.1,
|
|
3512
|
+
timeline: [
|
|
3513
|
+
set("angles", []),
|
|
3514
|
+
repeat(4, append("angles", add(div(mul(INDEX, PI), 2), mul(rand(), 0.6)))),
|
|
3515
|
+
set("roll", mul(rand(), PI)),
|
|
3516
|
+
flash(ORIGIN2, 16756832, mul(4, SIZE), FLASH_SECONDS, mul(2, SIZE), true, true),
|
|
3517
|
+
flashPiece("cone_open", mul(0.013, SIZE), mul(0.085, SIZE), 10, [mul(0.042, SIZE), 0, 0], [0, 0, -PI / 2], 16757575),
|
|
3518
|
+
repeat(
|
|
3519
|
+
4,
|
|
3520
|
+
set("angle", pick(variable("angles"), INDEX)),
|
|
3521
|
+
flashPiece(
|
|
3522
|
+
"cone",
|
|
3523
|
+
mul(5e-3, SIZE),
|
|
3524
|
+
mul(0.04, SIZE),
|
|
3525
|
+
6,
|
|
3526
|
+
[mul(0.012, SIZE), mul(cos(variable("angle")), 0.016, SIZE), mul(sin(variable("angle")), 0.016, SIZE)],
|
|
3527
|
+
[variable("angle"), 0, -PI / 2],
|
|
3528
|
+
16757575
|
|
3529
|
+
)
|
|
3530
|
+
),
|
|
3531
|
+
flashPiece("sphere", mul(0.016, SIZE), void 0, 12, [mul(8e-3, SIZE), 0, 0], [0, 0, 0], 16773568),
|
|
3532
|
+
repeat(
|
|
3533
|
+
6,
|
|
3534
|
+
puff2(
|
|
3535
|
+
ORIGIN2,
|
|
3536
|
+
[add(0.15, mul(rand(), 0.35)), add(0.03, mul(rand(), 0.12)), mul(sub(rand(), 0.5), 0.14)],
|
|
3537
|
+
[0, 0, 0],
|
|
3538
|
+
mul(0.013, SIZE),
|
|
3539
|
+
add(1.3, mul(rand(), 0.6)),
|
|
3540
|
+
0.45
|
|
3541
|
+
)
|
|
3542
|
+
)
|
|
3543
|
+
]
|
|
3544
|
+
};
|
|
3545
|
+
var SMOKE_PUFF = {
|
|
3546
|
+
id: "weapon_smoke_puff",
|
|
3547
|
+
pageId: "event:weapon_smoke_puff",
|
|
3548
|
+
team: "weapons",
|
|
3549
|
+
budget: { particles: 1 },
|
|
3550
|
+
loop: 0.1,
|
|
3551
|
+
timeline: [puff2(ORIGIN2, void 0, [variable("vx"), variable("vy"), variable("vz")], variable("radius"), variable("life"), variable("opacity"))]
|
|
3552
|
+
};
|
|
3553
|
+
var BACKBLAST = {
|
|
3554
|
+
id: "launcher_backblast",
|
|
3555
|
+
pageId: "event:launcher_backblast",
|
|
3556
|
+
team: "weapons",
|
|
3557
|
+
budget: { particles: 40 },
|
|
3558
|
+
loop: 0.1,
|
|
3559
|
+
timeline: [
|
|
3560
|
+
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)),
|
|
3561
|
+
repeat(14, ...flameBit(ORIGIN2, [neg(add(2, mul(rand(), 2))), 0, 0], [wide(1), wide(0.6), wide(1)], 0.02, 0.25))
|
|
3562
|
+
]
|
|
3563
|
+
};
|
|
3564
|
+
var FLAME_JET = {
|
|
3565
|
+
id: "flame_jet",
|
|
3566
|
+
pageId: "event:flame_jet",
|
|
3567
|
+
team: "weapons",
|
|
3568
|
+
budget: { particles: 30 },
|
|
3569
|
+
loop: 0.1,
|
|
3570
|
+
timeline: [
|
|
3571
|
+
repeat(
|
|
3572
|
+
floor(mul(420, variable("dt"), variable("scale"))),
|
|
3573
|
+
set("speed", mul(add(2.2, mul(rand(), 1.1)), variable("scale"))),
|
|
3574
|
+
...flameBit(
|
|
3575
|
+
[mul(rand(), variable("speed"), min(variable("dt"), 0.3)), 0, 0],
|
|
3576
|
+
[variable("speed"), 0, 0],
|
|
3577
|
+
[wide(0.35), mul(sub(rand(), 0.3), 0.3), wide(0.35)],
|
|
3578
|
+
add(0.02, mul(rand(), 0.022)),
|
|
3579
|
+
add(0.4, mul(rand(), 0.35))
|
|
3580
|
+
)
|
|
3581
|
+
),
|
|
3582
|
+
when(lt(rand(), 0.5), [
|
|
3583
|
+
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)
|
|
3584
|
+
])
|
|
3585
|
+
]
|
|
3586
|
+
};
|
|
3587
|
+
var VIEWMODEL_EFFECTS = [MUZZLE_FLASH2, SMOKE_PUFF, BACKBLAST, FLAME_JET];
|
|
3588
|
+
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];
|
|
3219
3589
|
var WORKSHOP_EFFECTS = Object.fromEntries(ALL_EFFECTS.map((effect) => [effect.id, effect]));
|
|
3220
|
-
var GAME_EFFECTS = { ...WORKSHOP_EFFECTS, ...Object.fromEntries(EVENT_EFFECTS.map((effect) => [effect.id, effect])) };
|
|
3590
|
+
var GAME_EFFECTS = { ...WORKSHOP_EFFECTS, ...Object.fromEntries([...EVENT_EFFECTS, ...VIEWMODEL_EFFECTS].map((effect) => [effect.id, effect])) };
|
|
3221
3591
|
var LEHMER_MULTIPLIER = 16807;
|
|
3222
3592
|
var LEHMER_MODULUS = 2147483647;
|
|
3223
3593
|
var HASH_MIX = 2654435761;
|
|
@@ -3313,7 +3683,7 @@ var GameVfxThree = (() => {
|
|
|
3313
3683
|
}
|
|
3314
3684
|
var COLUMNS = 6;
|
|
3315
3685
|
var ROWS = 5;
|
|
3316
|
-
var
|
|
3686
|
+
var ORIGIN3 = [-2.2, 0, 2.6];
|
|
3317
3687
|
var BLOCK_SIZE = [0.5, 0.44, 0.25];
|
|
3318
3688
|
var OBJECT_ID_DRAWS2 = 4;
|
|
3319
3689
|
var FLOOR2 = 0.13;
|
|
@@ -3356,7 +3726,7 @@ var GameVfxThree = (() => {
|
|
|
3356
3726
|
const chipScale = random.between(0.8, 1.3) * scale;
|
|
3357
3727
|
for (let draw = 0; draw < OBJECT_ID_DRAWS2; draw++) random.next();
|
|
3358
3728
|
best.holes.push({ x: offsetX, y: offsetY, scale, chipTurn, chipScale });
|
|
3359
|
-
impact(host.engine, "concrete", [
|
|
3729
|
+
impact(host.engine, "concrete", [ORIGIN3[0] + x, y, ORIGIN3[2] + 0.13], [0, 0, 1], 0.8);
|
|
3360
3730
|
} else if (action === "collapse") {
|
|
3361
3731
|
const { x, y } = args;
|
|
3362
3732
|
for (const block of blocks) {
|
|
@@ -3406,7 +3776,7 @@ var GameVfxThree = (() => {
|
|
|
3406
3776
|
}
|
|
3407
3777
|
};
|
|
3408
3778
|
}
|
|
3409
|
-
var
|
|
3779
|
+
var ORIGIN4 = [5.6, 0, 0.8];
|
|
3410
3780
|
var MAX_TILT = 0.25;
|
|
3411
3781
|
function createCarBehavior() {
|
|
3412
3782
|
let y = 0;
|
|
@@ -3438,8 +3808,13 @@ var GameVfxThree = (() => {
|
|
|
3438
3808
|
}
|
|
3439
3809
|
}
|
|
3440
3810
|
},
|
|
3441
|
-
query(_host, name) {
|
|
3442
|
-
if (name === "position") return [
|
|
3811
|
+
query(_host, name, args) {
|
|
3812
|
+
if (name === "position") return [ORIGIN4[0], y, ORIGIN4[2]];
|
|
3813
|
+
if (name === "point") {
|
|
3814
|
+
const [x, py, z] = args;
|
|
3815
|
+
const point = carPoint(x, py, z);
|
|
3816
|
+
return [point[0], point[1] + y, point[2]];
|
|
3817
|
+
}
|
|
3443
3818
|
if (name === "roll") return roll;
|
|
3444
3819
|
throw new Error(`car: unknown query ${name}`);
|
|
3445
3820
|
},
|
|
@@ -3639,6 +4014,29 @@ var GameVfxThree = (() => {
|
|
|
3639
4014
|
}
|
|
3640
4015
|
};
|
|
3641
4016
|
}
|
|
4017
|
+
function createRainBehavior() {
|
|
4018
|
+
return {
|
|
4019
|
+
reset() {
|
|
4020
|
+
},
|
|
4021
|
+
act(host, action, args) {
|
|
4022
|
+
const { engine, camera: camera2 } = host;
|
|
4023
|
+
if (action === "init") {
|
|
4024
|
+
const { count, wind } = args;
|
|
4025
|
+
engine.rain.init(count, wind);
|
|
4026
|
+
} else if (action === "update") {
|
|
4027
|
+
const { dt, splash } = args;
|
|
4028
|
+
engine.rain.update(dt, splash, camera2.position);
|
|
4029
|
+
}
|
|
4030
|
+
},
|
|
4031
|
+
query(host, name) {
|
|
4032
|
+
if (name === "count") return host.engine.rain.count;
|
|
4033
|
+
if (name === "on") return host.engine.rain.on;
|
|
4034
|
+
throw new Error(`rain: unknown query ${name}`);
|
|
4035
|
+
},
|
|
4036
|
+
update() {
|
|
4037
|
+
}
|
|
4038
|
+
};
|
|
4039
|
+
}
|
|
3642
4040
|
var WALKER_COUNT = 10;
|
|
3643
4041
|
var ARRIVAL_DISTANCE = 0.05;
|
|
3644
4042
|
var SWAY_AMPLITUDE = 0.04;
|
|
@@ -3704,7 +4102,8 @@ var GameVfxThree = (() => {
|
|
|
3704
4102
|
blocks: () => createBlocksBehavior(),
|
|
3705
4103
|
plate: () => createPlateBehavior(),
|
|
3706
4104
|
cylinder: () => createCylinderBehavior(),
|
|
3707
|
-
car: () => createCarBehavior()
|
|
4105
|
+
car: () => createCarBehavior(),
|
|
4106
|
+
rain: () => createRainBehavior()
|
|
3708
4107
|
};
|
|
3709
4108
|
var NOOP = () => {
|
|
3710
4109
|
};
|
|
@@ -3775,6 +4174,8 @@ var GameVfxThree = (() => {
|
|
|
3775
4174
|
return Math.abs(asNumber(first));
|
|
3776
4175
|
case "sqrt":
|
|
3777
4176
|
return Math.sqrt(asNumber(first));
|
|
4177
|
+
case "exp":
|
|
4178
|
+
return Math.exp(asNumber(first));
|
|
3778
4179
|
case "sin":
|
|
3779
4180
|
return Math.sin(asNumber(first));
|
|
3780
4181
|
case "cos":
|
|
@@ -3893,7 +4294,7 @@ var GameVfxThree = (() => {
|
|
|
3893
4294
|
return evaluateCall(value.$, args.map((entry) => resolve(entry, context)));
|
|
3894
4295
|
}
|
|
3895
4296
|
}
|
|
3896
|
-
var
|
|
4297
|
+
var UP12 = [0, 1, 0];
|
|
3897
4298
|
var ZERO = [0, 0, 0];
|
|
3898
4299
|
var FULL_TURN_DRAWN = 6.283;
|
|
3899
4300
|
function scaledSizes(range, factor) {
|
|
@@ -3906,7 +4307,7 @@ var GameVfxThree = (() => {
|
|
|
3906
4307
|
p: centre,
|
|
3907
4308
|
r: radius,
|
|
3908
4309
|
flat: true,
|
|
3909
|
-
dir: options.dir ??
|
|
4310
|
+
dir: options.dir ?? UP12,
|
|
3910
4311
|
cone: 0.35,
|
|
3911
4312
|
sp: [0.4, 1.4],
|
|
3912
4313
|
v: wind,
|
|
@@ -3923,7 +4324,7 @@ var GameVfxThree = (() => {
|
|
|
3923
4324
|
p: centre,
|
|
3924
4325
|
r: radius * 0.6,
|
|
3925
4326
|
flat: true,
|
|
3926
|
-
dir:
|
|
4327
|
+
dir: UP12,
|
|
3927
4328
|
cone: 0.3,
|
|
3928
4329
|
sp: [0.3, 0.8],
|
|
3929
4330
|
life: [0.2, 0.4],
|
|
@@ -3938,14 +4339,14 @@ var GameVfxThree = (() => {
|
|
|
3938
4339
|
if (engine.quality < 2) {
|
|
3939
4340
|
engine.emit(`${key}e`, "streak", 10 * factor, dt, () => {
|
|
3940
4341
|
const jitter = plus(wind, engine.random.between(-0.4, 0.4), 0, engine.random.between(-0.4, 0.4));
|
|
3941
|
-
return { p: centre, box: [radius, 0, radius], dir:
|
|
4342
|
+
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 };
|
|
3942
4343
|
});
|
|
3943
4344
|
}
|
|
3944
4345
|
if (options.noSmoke) return;
|
|
3945
4346
|
engine.emit(`${key}s`, "normal", (options.smoke || 14) * factor, dt, () => ({
|
|
3946
4347
|
p: plus(centre, 0, 0.8 * sqrtFactor, 0),
|
|
3947
4348
|
r: radius * 0.7,
|
|
3948
|
-
dir:
|
|
4349
|
+
dir: UP12,
|
|
3949
4350
|
cone: 0.35,
|
|
3950
4351
|
sp: [0.6, 1.4],
|
|
3951
4352
|
v: wind,
|
|
@@ -3985,15 +4386,15 @@ var GameVfxThree = (() => {
|
|
|
3985
4386
|
engine.screen.shake += 0.7 * scale;
|
|
3986
4387
|
engine.screen.white += 0.18 * scale;
|
|
3987
4388
|
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 });
|
|
3988
|
-
engine.burst("add", 28 * scale, { p: plus(point, 0, 0.3, 0), r: 0.3, dir:
|
|
4389
|
+
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 });
|
|
3989
4390
|
engine.ring([plus(point, 0, 0.05, 0), 0.3, 7 * scale, 0.55, 16767136]);
|
|
3990
4391
|
const toCamera = normalized([cameraPosition[0] - point[0], cameraPosition[1] - point[1], cameraPosition[2] - point[2]]);
|
|
3991
4392
|
engine.ring([plus(point, 0, 1, 0), 0.3, 5 * scale, 0.35, 16773328, toCamera]);
|
|
3992
|
-
engine.burst("normal", 32 * scale, { p: plus(point, 0, 0.6, 0), r: 0.8 * scale, dir:
|
|
4393
|
+
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 });
|
|
3993
4394
|
ringOfDust(engine, point, scale);
|
|
3994
|
-
if (engine.quality < 2) engine.burst("streak", 44 * scale, { p: point, dir:
|
|
4395
|
+
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 });
|
|
3995
4396
|
for (let index = 0; index < engine.scaled(16 * scale); index++) {
|
|
3996
|
-
engine.debrisPiece({ p: point, dir:
|
|
4397
|
+
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 });
|
|
3997
4398
|
}
|
|
3998
4399
|
engine.decal([point[0], engine.context.groundAt(point[0], point[2]), point[2], 3 * scale, 657930, { grow: 0.15, life: 60 }]);
|
|
3999
4400
|
}
|
|
@@ -4136,6 +4537,7 @@ var GameVfxThree = (() => {
|
|
|
4136
4537
|
if (!def) return;
|
|
4137
4538
|
this.schedule.clear();
|
|
4138
4539
|
this.variables.clear();
|
|
4540
|
+
for (const [name, value] of Object.entries(this.setup.values ?? {})) this.variables.set(name, value);
|
|
4139
4541
|
for (const behavior2 of this.deps.behaviors()) behavior2.reset(this.host);
|
|
4140
4542
|
this.time = 0;
|
|
4141
4543
|
this.within(() => {
|
|
@@ -4194,6 +4596,10 @@ var GameVfxThree = (() => {
|
|
|
4194
4596
|
return engine.spawn(step.system, this.value(step.spawn));
|
|
4195
4597
|
case "emit":
|
|
4196
4598
|
return engine.emit(step.key, step.system, this.value(step.rate), this.dt, () => this.value(step.spawn));
|
|
4599
|
+
case "mesh": {
|
|
4600
|
+
engine.mesh(this.value(step.spawn));
|
|
4601
|
+
return;
|
|
4602
|
+
}
|
|
4197
4603
|
case "debris":
|
|
4198
4604
|
return engine.debrisPiece(this.value(step.spawn));
|
|
4199
4605
|
case "decal":
|
|
@@ -4275,7 +4681,7 @@ var GameVfxThree = (() => {
|
|
|
4275
4681
|
this.index = previous;
|
|
4276
4682
|
}
|
|
4277
4683
|
};
|
|
4278
|
-
var
|
|
4684
|
+
var ORIGIN5 = [0, 0, 0];
|
|
4279
4685
|
var DEFAULT_HEADING = [0, 0, -1];
|
|
4280
4686
|
var DEFAULT_MAX_INSTANCES = 48;
|
|
4281
4687
|
var ENDLESS_SECONDS = 60;
|
|
@@ -4320,7 +4726,7 @@ var GameVfxThree = (() => {
|
|
|
4320
4726
|
}
|
|
4321
4727
|
function placementOf(entry) {
|
|
4322
4728
|
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;
|
|
4323
|
-
return { origin, anchor: entry.anchor, yaw: entry.yaw };
|
|
4729
|
+
return { origin, anchor: entry.anchor, yaw: entry.yaw, ...entry.orientation ? { orientation: entry.orientation } : {} };
|
|
4324
4730
|
}
|
|
4325
4731
|
function drawing(entry, action) {
|
|
4326
4732
|
const context = engine.context;
|
|
@@ -4344,8 +4750,9 @@ var GameVfxThree = (() => {
|
|
|
4344
4750
|
random: playOptions.seed !== void 0 ? streamOf(playOptions.seed) : void 0,
|
|
4345
4751
|
follow: playOptions.follow,
|
|
4346
4752
|
origin: point,
|
|
4347
|
-
anchor: def.anchor ??
|
|
4753
|
+
anchor: def.anchor ?? ORIGIN5,
|
|
4348
4754
|
yaw: yawOf(heading, playOptions.direction),
|
|
4755
|
+
orientation: playOptions.orientation,
|
|
4349
4756
|
seconds: playOptions.seconds ?? (def.loop && def.loop > 0 ? def.loop : ENDLESS_SECONDS)
|
|
4350
4757
|
};
|
|
4351
4758
|
playing.push(entry);
|
|
@@ -4354,7 +4761,8 @@ var GameVfxThree = (() => {
|
|
|
4354
4761
|
() => instance.begin(def, paramIndex(def, playOptions.param), {
|
|
4355
4762
|
placement: placementOf(entry),
|
|
4356
4763
|
...playOptions.direction ? { direction: playOptions.direction } : {},
|
|
4357
|
-
...playOptions.normal ? { normal: playOptions.normal } : {}
|
|
4764
|
+
...playOptions.normal ? { normal: playOptions.normal } : {},
|
|
4765
|
+
...playOptions.values ? { values: playOptions.values } : {}
|
|
4358
4766
|
})
|
|
4359
4767
|
);
|
|
4360
4768
|
return entry.handle;
|
|
@@ -4614,15 +5022,15 @@ var GameVfxThree = (() => {
|
|
|
4614
5022
|
return shock;
|
|
4615
5023
|
}
|
|
4616
5024
|
function pushPuffs(puffs, shock, reach, dt, age) {
|
|
4617
|
-
for (const
|
|
4618
|
-
if (
|
|
4619
|
-
const dx =
|
|
4620
|
-
const dz =
|
|
5025
|
+
for (const puff3 of puffs) {
|
|
5026
|
+
if (puff3.ring || puff3.t > PUSH_AGE_LIMIT) continue;
|
|
5027
|
+
const dx = puff3.x - shock.x;
|
|
5028
|
+
const dz = puff3.z - shock.z;
|
|
4621
5029
|
const distance = Math.hypot(dx, dz) + 1e-3;
|
|
4622
|
-
if (Math.abs(distance - reach) < PUSH_BAND &&
|
|
5030
|
+
if (Math.abs(distance - reach) < PUSH_BAND && puff3.y < PUSH_CEILING) {
|
|
4623
5031
|
const strength = 4 * dt * (1 - age);
|
|
4624
|
-
|
|
4625
|
-
|
|
5032
|
+
puff3.vx += dx / distance * strength * 6;
|
|
5033
|
+
puff3.vz += dz / distance * strength * 6;
|
|
4626
5034
|
}
|
|
4627
5035
|
}
|
|
4628
5036
|
}
|
|
@@ -4922,10 +5330,10 @@ var GameVfxThree = (() => {
|
|
|
4922
5330
|
const life = random.between(ring2.life * 0.75, ring2.life);
|
|
4923
5331
|
const h0 = random.between(1, 1.25);
|
|
4924
5332
|
const hl = random.between(0.9, 1.6);
|
|
4925
|
-
const
|
|
4926
|
-
|
|
4927
|
-
|
|
4928
|
-
|
|
5333
|
+
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 });
|
|
5334
|
+
puff3.ring = ring2;
|
|
5335
|
+
puff3.ph = random.next() * Math.PI * 2;
|
|
5336
|
+
puff3.th = random.next() * Math.PI * 2;
|
|
4929
5337
|
}
|
|
4930
5338
|
const stemCount = Math.round((spec.stem || 18) * Math.max(lod, 0.4));
|
|
4931
5339
|
for (let index = 0; index < stemCount; index++) {
|
|
@@ -5726,7 +6134,7 @@ var GameVfxThree = (() => {
|
|
|
5726
6134
|
};
|
|
5727
6135
|
var TWO_PI_ROUNDED = 6.2832;
|
|
5728
6136
|
var WIDE_CONE = 3.1;
|
|
5729
|
-
var
|
|
6137
|
+
var UP13 = [0, 1, 0];
|
|
5730
6138
|
function drawRange(random, range) {
|
|
5731
6139
|
if (Array.isArray(range)) return random.between(range[0], range[1]);
|
|
5732
6140
|
return range || 0;
|
|
@@ -5754,7 +6162,7 @@ var GameVfxThree = (() => {
|
|
|
5754
6162
|
}
|
|
5755
6163
|
function coneDirection(random, direction, cone, out) {
|
|
5756
6164
|
if (cone >= WIDE_CONE) return randomUnit(random, out);
|
|
5757
|
-
const [dx, dy, dz] = direction ??
|
|
6165
|
+
const [dx, dy, dz] = direction ?? UP13;
|
|
5758
6166
|
const cosTilt = 1 - random.next() * (1 - Math.cos(cone));
|
|
5759
6167
|
const sinTilt = Math.sqrt(1 - cosTilt * cosTilt);
|
|
5760
6168
|
const phase = random.next() * TWO_PI_ROUNDED;
|
|
@@ -5874,12 +6282,12 @@ var GameVfxThree = (() => {
|
|
|
5874
6282
|
}
|
|
5875
6283
|
};
|
|
5876
6284
|
var CAPACITY2 = 400;
|
|
5877
|
-
var
|
|
6285
|
+
var UP14 = [0, 1, 0];
|
|
5878
6286
|
var DEFAULT_LIFE2 = 60;
|
|
5879
6287
|
var DEFAULT_GROW = 1.2;
|
|
5880
6288
|
var EVAPORATION = { fuel: [6, 5], water: [40, 20] };
|
|
5881
6289
|
function createDecal() {
|
|
5882
|
-
return { on: false, x: 0, y: 0, z: 0, sx: 0, sy: 0, t: 0, life: 0, grow: 0, color: 0, normal:
|
|
6290
|
+
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 };
|
|
5883
6291
|
}
|
|
5884
6292
|
var DecalPool = class {
|
|
5885
6293
|
constructor(context) {
|
|
@@ -5892,7 +6300,7 @@ var GameVfxThree = (() => {
|
|
|
5892
6300
|
const random = this.context.random;
|
|
5893
6301
|
const index = this.next++ % CAPACITY2;
|
|
5894
6302
|
const decal2 = this.decals[index];
|
|
5895
|
-
const normal = options.n ??
|
|
6303
|
+
const normal = options.n ?? UP14;
|
|
5896
6304
|
random.between(0, 6.28);
|
|
5897
6305
|
const offset = 4e-3 + index % 40 * 4e-4;
|
|
5898
6306
|
decal2.on = true;
|
|
@@ -5933,6 +6341,94 @@ var GameVfxThree = (() => {
|
|
|
5933
6341
|
}
|
|
5934
6342
|
}
|
|
5935
6343
|
};
|
|
6344
|
+
var CAPACITY3 = 400;
|
|
6345
|
+
var IDENTITY = [0, 0, 0, 1];
|
|
6346
|
+
function multiply(a, b) {
|
|
6347
|
+
const [ax, ay, az, aw] = a;
|
|
6348
|
+
const [bx, by, bz, bw] = b;
|
|
6349
|
+
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];
|
|
6350
|
+
}
|
|
6351
|
+
var aboutX = (angle) => [Math.sin(angle / 2), 0, 0, Math.cos(angle / 2)];
|
|
6352
|
+
var MeshPool = class {
|
|
6353
|
+
constructor(capacity = CAPACITY3) {
|
|
6354
|
+
__publicField(this, "capacity", capacity);
|
|
6355
|
+
__publicField(this, "particles", []);
|
|
6356
|
+
__publicField(this, "serial", 0);
|
|
6357
|
+
}
|
|
6358
|
+
get count() {
|
|
6359
|
+
return this.particles.length;
|
|
6360
|
+
}
|
|
6361
|
+
spawn(options, frame = IDENTITY) {
|
|
6362
|
+
const velocity = options.v ?? [0, 0, 0];
|
|
6363
|
+
const world = options.wv ?? [0, 0, 0];
|
|
6364
|
+
const particle = {
|
|
6365
|
+
id: ++this.serial,
|
|
6366
|
+
shape: options.shape,
|
|
6367
|
+
radius: options.r,
|
|
6368
|
+
height: options.h ?? 0,
|
|
6369
|
+
segments: options.seg ?? 0,
|
|
6370
|
+
segments2: options.seg2 ?? 0,
|
|
6371
|
+
color: options.c0,
|
|
6372
|
+
additive: options.add === true,
|
|
6373
|
+
lit: options.lit === true,
|
|
6374
|
+
x: options.p[0],
|
|
6375
|
+
y: options.p[1],
|
|
6376
|
+
z: options.p[2],
|
|
6377
|
+
frame: options.roll ? multiply(frame, aboutX(options.roll)) : frame,
|
|
6378
|
+
at: options.at ?? [0, 0, 0],
|
|
6379
|
+
rx: options.rot?.[0] ?? 0,
|
|
6380
|
+
ry: options.rot?.[1] ?? 0,
|
|
6381
|
+
rz: options.rot?.[2] ?? 0,
|
|
6382
|
+
scale: 1,
|
|
6383
|
+
opacity: options.a,
|
|
6384
|
+
age: 0,
|
|
6385
|
+
life: options.life,
|
|
6386
|
+
vx: velocity[0] + world[0],
|
|
6387
|
+
vy: velocity[1] + world[1],
|
|
6388
|
+
vz: velocity[2] + world[2],
|
|
6389
|
+
spin: options.spin ?? [0, 0, 0],
|
|
6390
|
+
gravity: options.g ?? 0,
|
|
6391
|
+
drag: options.drag ?? 0,
|
|
6392
|
+
grow: options.grow ?? 0,
|
|
6393
|
+
ramp: options.ramp,
|
|
6394
|
+
fade: options.fade === true,
|
|
6395
|
+
startOpacity: options.a
|
|
6396
|
+
};
|
|
6397
|
+
this.particles.push(particle);
|
|
6398
|
+
if (this.particles.length > this.capacity) this.particles.shift();
|
|
6399
|
+
return particle;
|
|
6400
|
+
}
|
|
6401
|
+
update(dt) {
|
|
6402
|
+
const live = this.particles;
|
|
6403
|
+
for (let index = 0; index < live.length; index++) {
|
|
6404
|
+
const particle = live[index];
|
|
6405
|
+
particle.age += dt;
|
|
6406
|
+
if (particle.ramp ? particle.age >= particle.life : particle.age > particle.life) {
|
|
6407
|
+
live.splice(index--, 1);
|
|
6408
|
+
continue;
|
|
6409
|
+
}
|
|
6410
|
+
if (particle.fade) particle.opacity = Math.max(0, particle.startOpacity * (1 - particle.age / particle.life));
|
|
6411
|
+
particle.vy -= particle.gravity * dt;
|
|
6412
|
+
if (particle.drag) {
|
|
6413
|
+
const keep = Math.max(0, 1 - particle.drag * dt);
|
|
6414
|
+
particle.vx *= keep;
|
|
6415
|
+
particle.vy *= keep;
|
|
6416
|
+
particle.vz *= keep;
|
|
6417
|
+
}
|
|
6418
|
+
particle.x += particle.vx * dt;
|
|
6419
|
+
particle.y += particle.vy * dt;
|
|
6420
|
+
particle.z += particle.vz * dt;
|
|
6421
|
+
particle.rx += particle.spin[0] * dt;
|
|
6422
|
+
particle.ry += particle.spin[1] * dt;
|
|
6423
|
+
particle.rz += particle.spin[2] * dt;
|
|
6424
|
+
if (particle.grow) particle.scale *= 1 + particle.grow * dt;
|
|
6425
|
+
if (particle.ramp) particle.scale = particle.ramp[0] + Math.min(1, particle.age / particle.life) * particle.ramp[1];
|
|
6426
|
+
}
|
|
6427
|
+
}
|
|
6428
|
+
clear() {
|
|
6429
|
+
this.particles.length = 0;
|
|
6430
|
+
}
|
|
6431
|
+
};
|
|
5936
6432
|
var DEFAULT_FADE_IN = 0.1;
|
|
5937
6433
|
var FLOATS_PER_VECTOR = 3;
|
|
5938
6434
|
var BYTE_MAX2 = 255;
|
|
@@ -6222,11 +6718,11 @@ var GameVfxThree = (() => {
|
|
|
6222
6718
|
};
|
|
6223
6719
|
var RING_CAPACITY = 120;
|
|
6224
6720
|
var LIGHT_CAPACITY = 4;
|
|
6225
|
-
var
|
|
6721
|
+
var UP15 = [0, 1, 0];
|
|
6226
6722
|
var DEFAULT_LIGHT_DISTANCE = 14;
|
|
6227
6723
|
var WaveRingPool = class {
|
|
6228
6724
|
constructor() {
|
|
6229
|
-
__publicField(this, "rings", Array.from({ length: RING_CAPACITY }, () => ({ on: false, point:
|
|
6725
|
+
__publicField(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 })));
|
|
6230
6726
|
__publicField(this, "count", 0);
|
|
6231
6727
|
__publicField(this, "next", 0);
|
|
6232
6728
|
}
|
|
@@ -6239,7 +6735,7 @@ var GameVfxThree = (() => {
|
|
|
6239
6735
|
ring2.t = 0;
|
|
6240
6736
|
ring2.duration = duration;
|
|
6241
6737
|
ring2.color = color;
|
|
6242
|
-
ring2.normal = normal ??
|
|
6738
|
+
ring2.normal = normal ?? UP15;
|
|
6243
6739
|
ring2.hold = hold || 0;
|
|
6244
6740
|
}
|
|
6245
6741
|
clear() {
|
|
@@ -6259,7 +6755,7 @@ var GameVfxThree = (() => {
|
|
|
6259
6755
|
var FlashLightPool = class {
|
|
6260
6756
|
constructor(context) {
|
|
6261
6757
|
__publicField(this, "context", context);
|
|
6262
|
-
__publicField(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 })));
|
|
6758
|
+
__publicField(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 })));
|
|
6263
6759
|
__publicField(this, "fire", [
|
|
6264
6760
|
{ x: 0, y: 0, z: 0, intensity: 0 },
|
|
6265
6761
|
{ x: 0, y: 0, z: 0, intensity: 0 }
|
|
@@ -6269,7 +6765,7 @@ var GameVfxThree = (() => {
|
|
|
6269
6765
|
get lit() {
|
|
6270
6766
|
return this.lights.filter((light) => light.intensity > 0).length;
|
|
6271
6767
|
}
|
|
6272
|
-
flash(point, color, intensity, duration, distance, force) {
|
|
6768
|
+
flash(point, color, intensity, duration, distance, force, steady) {
|
|
6273
6769
|
const { level } = this.context.quality;
|
|
6274
6770
|
if (level >= 1 && !force) return;
|
|
6275
6771
|
if (level >= 2 && force !== "boom") return;
|
|
@@ -6282,6 +6778,7 @@ var GameVfxThree = (() => {
|
|
|
6282
6778
|
light.peak = intensity;
|
|
6283
6779
|
light.duration = duration;
|
|
6284
6780
|
light.t = 0;
|
|
6781
|
+
light.steady = steady === true;
|
|
6285
6782
|
light.intensity = intensity;
|
|
6286
6783
|
}
|
|
6287
6784
|
clear() {
|
|
@@ -6293,7 +6790,7 @@ var GameVfxThree = (() => {
|
|
|
6293
6790
|
if (light.intensity <= 0) continue;
|
|
6294
6791
|
light.t += dt;
|
|
6295
6792
|
const age = light.t / light.duration;
|
|
6296
|
-
light.intensity = age >= 1 ? 0 : light.peak * (1 - age) * (1 - age);
|
|
6793
|
+
light.intensity = age >= 1 ? 0 : light.steady ? light.peak : light.peak * (1 - age) * (1 - age);
|
|
6297
6794
|
}
|
|
6298
6795
|
}
|
|
6299
6796
|
};
|
|
@@ -6301,6 +6798,14 @@ var GameVfxThree = (() => {
|
|
|
6301
6798
|
var FIRE_FLICKER_SWAY = 0.25;
|
|
6302
6799
|
var FIRE_FLICKER_JITTER = 0.08;
|
|
6303
6800
|
var LENS_FADE = 0.16;
|
|
6801
|
+
function rotate(q, v) {
|
|
6802
|
+
const [qx, qy, qz, qw] = q;
|
|
6803
|
+
const ix = qw * v[0] + qy * v[2] - qz * v[1];
|
|
6804
|
+
const iy = qw * v[1] + qz * v[0] - qx * v[2];
|
|
6805
|
+
const iz = qw * v[2] + qx * v[1] - qy * v[0];
|
|
6806
|
+
const iw = -qx * v[0] - qy * v[1] - qz * v[2];
|
|
6807
|
+
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];
|
|
6808
|
+
}
|
|
6304
6809
|
function workshopGround(x, z) {
|
|
6305
6810
|
return z < -2.9 && z > -4.5 && Math.abs(x) < 13 ? 0.12 : 0;
|
|
6306
6811
|
}
|
|
@@ -6314,6 +6819,8 @@ var GameVfxThree = (() => {
|
|
|
6314
6819
|
__publicField(this, "decals");
|
|
6315
6820
|
__publicField(this, "rings", new WaveRingPool());
|
|
6316
6821
|
__publicField(this, "lights");
|
|
6822
|
+
__publicField(this, "rain", new RainField(this));
|
|
6823
|
+
__publicField(this, "meshes", new MeshPool());
|
|
6317
6824
|
__publicField(this, "screen", createScreenState());
|
|
6318
6825
|
__publicField(this, "lens", []);
|
|
6319
6826
|
__publicField(this, "post", {});
|
|
@@ -6346,7 +6853,11 @@ var GameVfxThree = (() => {
|
|
|
6346
6853
|
place(point) {
|
|
6347
6854
|
const placement = this.placement;
|
|
6348
6855
|
if (!placement) return point;
|
|
6349
|
-
const { anchor, origin, yaw } = placement;
|
|
6856
|
+
const { anchor, origin, yaw, orientation } = placement;
|
|
6857
|
+
if (orientation) {
|
|
6858
|
+
const turned = rotate(orientation, [point[0] - anchor[0], point[1] - anchor[1], point[2] - anchor[2]]);
|
|
6859
|
+
return [origin[0] + turned[0], origin[1] + turned[1], origin[2] + turned[2]];
|
|
6860
|
+
}
|
|
6350
6861
|
const x = point[0] - anchor[0];
|
|
6351
6862
|
const z = point[2] - anchor[2];
|
|
6352
6863
|
const cos2 = Math.cos(yaw);
|
|
@@ -6357,6 +6868,7 @@ var GameVfxThree = (() => {
|
|
|
6357
6868
|
turn(vector) {
|
|
6358
6869
|
const placement = this.placement;
|
|
6359
6870
|
if (!placement) return vector;
|
|
6871
|
+
if (placement.orientation) return rotate(placement.orientation, vector);
|
|
6360
6872
|
const cos2 = Math.cos(placement.yaw);
|
|
6361
6873
|
const sin2 = Math.sin(placement.yaw);
|
|
6362
6874
|
return [cos2 * vector[0] + sin2 * vector[2], vector[1], -sin2 * vector[0] + cos2 * vector[2]];
|
|
@@ -6385,6 +6897,14 @@ var GameVfxThree = (() => {
|
|
|
6385
6897
|
}
|
|
6386
6898
|
this.accumulators.set(key, carried);
|
|
6387
6899
|
}
|
|
6900
|
+
/** 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. */
|
|
6901
|
+
mesh(recipe) {
|
|
6902
|
+
const placement = this.placement;
|
|
6903
|
+
const options = placement ? { ...recipe, p: this.place(recipe.p), ...recipe.v ? { v: this.turn(recipe.v) } : {} } : recipe;
|
|
6904
|
+
this.context.trace?.("mesh", [options]);
|
|
6905
|
+
const grouped = recipe.at !== void 0 || recipe.roll !== void 0;
|
|
6906
|
+
return this.meshes.spawn(options, placement && grouped ? placement.orientation ?? [0, Math.sin(placement.yaw / 2), 0, Math.cos(placement.yaw / 2)] : void 0);
|
|
6907
|
+
}
|
|
6388
6908
|
debrisPiece(recipe) {
|
|
6389
6909
|
const options = this.placed(recipe);
|
|
6390
6910
|
this.context.trace?.("debris", [options]);
|
|
@@ -6405,10 +6925,11 @@ var GameVfxThree = (() => {
|
|
|
6405
6925
|
this.context.trace?.("ring", args);
|
|
6406
6926
|
this.rings.add(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
|
|
6407
6927
|
}
|
|
6928
|
+
/** `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. */
|
|
6408
6929
|
flash(recipe) {
|
|
6409
|
-
const args = this.placement ? [this.place(recipe[0]), recipe[1], recipe[2], recipe[3], recipe[4], recipe[5]] : recipe;
|
|
6410
|
-
this.context.trace?.("flash", args);
|
|
6411
|
-
this.lights.flash(args[0], args[1], args[2], args[3], args[4], args[5]);
|
|
6930
|
+
const args = this.placement ? [this.place(recipe[0]), recipe[1], recipe[2], recipe[3], recipe[4], recipe[5], recipe[6]] : recipe;
|
|
6931
|
+
this.context.trace?.("flash", args.slice(0, 6));
|
|
6932
|
+
this.lights.flash(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
|
|
6412
6933
|
}
|
|
6413
6934
|
/** `fireLight` (W400): sways with the clock and flickers with one draw. */
|
|
6414
6935
|
fireLight(slot, recipe, intensity, time) {
|
|
@@ -6433,6 +6954,7 @@ var GameVfxThree = (() => {
|
|
|
6433
6954
|
this.debris.update(dt);
|
|
6434
6955
|
this.decals.update(dt);
|
|
6435
6956
|
this.rings.update(dt);
|
|
6957
|
+
this.meshes.update(dt);
|
|
6436
6958
|
this.lights.update(dt);
|
|
6437
6959
|
updateScreen(this.screen, dt);
|
|
6438
6960
|
for (let index = this.lens.length - 1; index >= 0; index--) {
|
|
@@ -6449,7 +6971,9 @@ var GameVfxThree = (() => {
|
|
|
6449
6971
|
this.debris.clear();
|
|
6450
6972
|
this.decals.clear();
|
|
6451
6973
|
this.rings.clear();
|
|
6974
|
+
this.meshes.clear();
|
|
6452
6975
|
this.lights.clear();
|
|
6976
|
+
this.rain.clear();
|
|
6453
6977
|
this.accumulators.clear();
|
|
6454
6978
|
resetScreenState(this.screen);
|
|
6455
6979
|
this.lens.length = 0;
|
|
@@ -6595,16 +7119,16 @@ var GameVfxThree = (() => {
|
|
|
6595
7119
|
},
|
|
6596
7120
|
push(point, radius, speed) {
|
|
6597
7121
|
spriteSystem.push(point, radius, speed);
|
|
6598
|
-
for (const
|
|
6599
|
-
const dx =
|
|
6600
|
-
const dy =
|
|
6601
|
-
const dz =
|
|
7122
|
+
for (const puff3 of core.puffs.items) {
|
|
7123
|
+
const dx = puff3.x - point[0];
|
|
7124
|
+
const dy = puff3.y - point[1];
|
|
7125
|
+
const dz = puff3.z - point[2];
|
|
6602
7126
|
const distance = Math.sqrt(dx * dx + dy * dy + dz * dz);
|
|
6603
7127
|
if (distance >= radius) continue;
|
|
6604
7128
|
const strength = speed * (1 - distance / radius) / (distance + 1e-3);
|
|
6605
|
-
|
|
6606
|
-
|
|
6607
|
-
|
|
7129
|
+
puff3.vx += dx * strength;
|
|
7130
|
+
puff3.vy += dy * strength;
|
|
7131
|
+
puff3.vz += dz * strength;
|
|
6608
7132
|
}
|
|
6609
7133
|
},
|
|
6610
7134
|
stop(handle) {
|
|
@@ -6621,6 +7145,12 @@ var GameVfxThree = (() => {
|
|
|
6621
7145
|
camera2.y = position[1];
|
|
6622
7146
|
camera2.z = position[2];
|
|
6623
7147
|
},
|
|
7148
|
+
setWind(next) {
|
|
7149
|
+
wind.x = next[0];
|
|
7150
|
+
wind.y = next[1];
|
|
7151
|
+
wind.z = next[2];
|
|
7152
|
+
},
|
|
7153
|
+
wind: () => [wind.x, wind.y, wind.z],
|
|
6624
7154
|
forceLod(scale) {
|
|
6625
7155
|
core.clock.forcedLod = scale;
|
|
6626
7156
|
},
|
|
@@ -6950,6 +7480,27 @@ var GameVfxThree = (() => {
|
|
|
6950
7480
|
budget: "Up to 600 particles per building and 2 fire lights. Beyond 80 m only the smoke column and the glow of the windows remain, which become a landmark.",
|
|
6951
7481
|
network: "A fire entity on the server per building, with a spread state."
|
|
6952
7482
|
},
|
|
7483
|
+
rain_and_puddles: {
|
|
7484
|
+
name: "Rain, splashes and puddles",
|
|
7485
|
+
short: "Drops with wind, splashes and rings only near the camera, lightning in the storm.",
|
|
7486
|
+
cost: "\u2264 4,000 drops",
|
|
7487
|
+
costNote: "splash up to 12 m",
|
|
7488
|
+
paramLabel: "Intensity",
|
|
7489
|
+
when: "The weather of the world. Rain raises the background noise and masks footsteps (it can be used for stealth).",
|
|
7490
|
+
look: "A fine drizzle, almost vertical. Rain with splashes on the asphalt and rings in the puddles, which are dark and mirror-like. A storm with drops slanted by the wind, sheets of water passing and a double flash of lightning that lights the scene for 0.2 s and reveals the horde.",
|
|
7491
|
+
budget: "Up to 4,000 drops tied to the camera in a 30 m box. Splashes and rings only within 12 m and only on what the camera sees.",
|
|
7492
|
+
network: "The server sends the weather and the lightning seed, so everyone sees the same flash."
|
|
7493
|
+
},
|
|
7494
|
+
fog_and_ash: {
|
|
7495
|
+
name: "Fog and ash",
|
|
7496
|
+
short: "Low layered mist, ash falling and the lamp post with its cone of light.",
|
|
7497
|
+
cost: "\u2264 120 sprites",
|
|
7498
|
+
costNote: "1 cone of light",
|
|
7499
|
+
when: "Before dawn, near the river and in burnt zones (ash). It cuts the sight of the zombies and of the player.",
|
|
7500
|
+
look: "The engine fog plus a layer of low mist that moves slowly, fine ash falling in a spiral and the beam of the lamp posts in view. Zombie silhouettes show before their details.",
|
|
7501
|
+
budget: "Up to 60 large mist sprites (half resolution) and 60 of ash. The lamp cone is an additive mesh, not real volumetric light.",
|
|
7502
|
+
network: "The weather comes from the server. The density is local, by zone."
|
|
7503
|
+
},
|
|
6953
7504
|
scraping_sparks: {
|
|
6954
7505
|
name: "Scraping sparks",
|
|
6955
7506
|
short: "A bumper dragging on the asphalt: a river of bouncing sparks and a mark on the ground.",
|
|
@@ -7001,6 +7552,16 @@ var GameVfxThree = (() => {
|
|
|
7001
7552
|
budget: "Texture only: a crack mask with 4 stages and a blood decal on the glass. Glass dust: 6 particles per blow.",
|
|
7002
7553
|
network: "The server sends the glass health. Blood on the glass is local."
|
|
7003
7554
|
},
|
|
7555
|
+
headlights_in_rain: {
|
|
7556
|
+
name: "Headlights in the rain",
|
|
7557
|
+
short: "A visible beam, drops lit inside the cone and the horde walking into the light.",
|
|
7558
|
+
cost: "\u2264 600 lit drops",
|
|
7559
|
+
costNote: "2 spots, no shadow",
|
|
7560
|
+
when: "Headlights on at night, with rain or fog.",
|
|
7561
|
+
look: "Two cones of light in the air, rain drops that shine only inside the beam and zombie silhouettes that light up when they enter the light. Outside the cone the rain almost disappears.",
|
|
7562
|
+
budget: "2 spotlights without shadow, 2 additive cones and up to 600 extra drops only inside the cone. Headlights of cars beyond 40 m stay as a cone only, with no real light.",
|
|
7563
|
+
network: "The state of the headlights is already replicated with the car."
|
|
7564
|
+
},
|
|
7004
7565
|
damage_and_bite: {
|
|
7005
7566
|
name: "Damage and bite",
|
|
7006
7567
|
short: "A red edge on the side of the blow, blood on the lens and the pulse of the bite.",
|
|
@@ -7318,6 +7879,27 @@ var GameVfxThree = (() => {
|
|
|
7318
7879
|
budget: "At\xE9 600 part\xEDculas por pr\xE9dio e 2 luzes de fogo. Al\xE9m de 80 m fica s\xF3 a coluna de fuma\xE7a e o brilho das janelas, que viram ponto de refer\xEAncia.",
|
|
7319
7880
|
network: "Entidade de fogo no servidor por pr\xE9dio, com estado de espalhar."
|
|
7320
7881
|
},
|
|
7882
|
+
rain_and_puddles: {
|
|
7883
|
+
name: "Chuva, respingos e po\xE7as",
|
|
7884
|
+
short: "Gotas com vento, respingos e an\xE9is s\xF3 perto da c\xE2mera, rel\xE2mpago no temporal.",
|
|
7885
|
+
cost: "\u2264 4.000 gotas",
|
|
7886
|
+
costNote: "respingo at\xE9 12 m",
|
|
7887
|
+
paramLabel: "Intensidade",
|
|
7888
|
+
when: "Clima do mundo. Chuva aumenta o ru\xEDdo de fundo e mascara passos (d\xE1 para usar na furtividade).",
|
|
7889
|
+
look: "Garoa fina quase vertical. Chuva com respingos no asfalto e an\xE9is nas po\xE7as, que ficam escuras e espelhadas. Temporal com gotas inclinadas pelo vento, cortinas de \xE1gua passando e rel\xE2mpago duplo que clareia a cena por 0,2 s e revela a horda.",
|
|
7890
|
+
budget: "At\xE9 4.000 gotas presas \xE0 c\xE2mera numa caixa de 30 m. Respingos e an\xE9is s\xF3 a menos de 12 m e s\xF3 em cima do que a c\xE2mera v\xEA.",
|
|
7891
|
+
network: "O servidor manda o clima e a semente do rel\xE2mpago, para todos verem o mesmo clar\xE3o."
|
|
7892
|
+
},
|
|
7893
|
+
fog_and_ash: {
|
|
7894
|
+
name: "Neblina e cinzas",
|
|
7895
|
+
short: "N\xE9voa rasteira em camadas, cinza caindo e o poste com cone de luz.",
|
|
7896
|
+
cost: "\u2264 120 sprites",
|
|
7897
|
+
costNote: "1 cone de luz",
|
|
7898
|
+
when: "Madrugada, perto de rio e em zonas queimadas (cinza). Reduz a vis\xE3o dos zumbis e do jogador.",
|
|
7899
|
+
look: "Neblina do motor mais uma camada de n\xE9voa baixa que se move devagar, cinza fina caindo em espiral e o feixe dos postes vis\xEDvel. Silhuetas de zumbis aparecem antes dos detalhes.",
|
|
7900
|
+
budget: "At\xE9 60 sprites grandes de n\xE9voa (meia resolu\xE7\xE3o) e 60 de cinza. O cone do poste \xE9 uma malha aditiva, n\xE3o luz volum\xE9trica real.",
|
|
7901
|
+
network: "Clima vem do servidor. Densidade \xE9 local por zona."
|
|
7902
|
+
},
|
|
7321
7903
|
scraping_sparks: {
|
|
7322
7904
|
name: "Fa\xEDscas de raspagem",
|
|
7323
7905
|
short: "Para-choque arrastando no asfalto: rio de fa\xEDscas que quicam e marca no ch\xE3o.",
|
|
@@ -7369,6 +7951,16 @@ var GameVfxThree = (() => {
|
|
|
7369
7951
|
budget: "S\xF3 textura: uma m\xE1scara de rachadura com 4 est\xE1gios e um decal de sangue no vidro. P\xF3 de vidro: 6 part\xEDculas por golpe.",
|
|
7370
7952
|
network: "O servidor manda a vida do vidro. Sangue no vidro \xE9 local."
|
|
7371
7953
|
},
|
|
7954
|
+
headlights_in_rain: {
|
|
7955
|
+
name: "Far\xF3is na chuva",
|
|
7956
|
+
short: "Feixe vis\xEDvel, gotas acesas dentro do cone e a horda entrando na luz.",
|
|
7957
|
+
cost: "\u2264 600 gotas acesas",
|
|
7958
|
+
costNote: "2 spots sem sombra",
|
|
7959
|
+
when: "Far\xF3is ligados \xE0 noite, com chuva ou neblina.",
|
|
7960
|
+
look: "Dois cones de luz vis\xEDveis no ar, gotas de chuva que brilham s\xF3 dentro do feixe e silhuetas de zumbi que acendem quando entram na luz. Fora do cone, a chuva quase some.",
|
|
7961
|
+
budget: "2 spotlights sem sombra, 2 cones aditivos e at\xE9 600 gotas extras s\xF3 dentro do cone. Far\xF3is de carros a mais de 40 m ficam s\xF3 como cone, sem luz real.",
|
|
7962
|
+
network: "Estado do farol j\xE1 \xE9 replicado com o carro."
|
|
7963
|
+
},
|
|
7372
7964
|
damage_and_bite: {
|
|
7373
7965
|
name: "Dano e mordida",
|
|
7374
7966
|
short: "Borda vermelha do lado do golpe, sangue na lente e o pulso da mordida.",
|
|
@@ -7559,11 +8151,11 @@ void main(){
|
|
|
7559
8151
|
geometry.setAttribute("aC", attributes[2]);
|
|
7560
8152
|
geometry.instanceCount = 0;
|
|
7561
8153
|
const material = new THREE.ShaderMaterial({ uniforms, vertexShader: PUFF_VERTEX, fragmentShader: PUFF_FRAGMENT });
|
|
7562
|
-
const
|
|
7563
|
-
|
|
7564
|
-
|
|
8154
|
+
const mesh2 = new THREE.Mesh(geometry, material);
|
|
8155
|
+
mesh2.name = "vfx-puffs";
|
|
8156
|
+
mesh2.frustumCulled = false;
|
|
7565
8157
|
return {
|
|
7566
|
-
mesh,
|
|
8158
|
+
mesh: mesh2,
|
|
7567
8159
|
sync() {
|
|
7568
8160
|
let n = 0;
|
|
7569
8161
|
for (const p of pool.items) {
|
|
@@ -7604,12 +8196,12 @@ void main(){
|
|
|
7604
8196
|
geometry.setAttribute("aE", attributes[2]);
|
|
7605
8197
|
geometry.instanceCount = 0;
|
|
7606
8198
|
const material = new THREE.ShaderMaterial({ transparent: true, depthWrite: false, blending: THREE.AdditiveBlending, vertexShader: SPARK_VERTEX, fragmentShader: SPARK_FRAGMENT });
|
|
7607
|
-
const
|
|
7608
|
-
|
|
7609
|
-
|
|
7610
|
-
|
|
8199
|
+
const mesh2 = new THREE.Mesh(geometry, material);
|
|
8200
|
+
mesh2.name = "vfx-sparks";
|
|
8201
|
+
mesh2.frustumCulled = false;
|
|
8202
|
+
mesh2.renderOrder = 5;
|
|
7611
8203
|
return {
|
|
7612
|
-
mesh,
|
|
8204
|
+
mesh: mesh2,
|
|
7613
8205
|
sync() {
|
|
7614
8206
|
let n = 0;
|
|
7615
8207
|
for (const s of pool.items) {
|
|
@@ -7647,12 +8239,12 @@ void main(){
|
|
|
7647
8239
|
geometry.setAttribute("aC", attributes[1]);
|
|
7648
8240
|
geometry.instanceCount = 0;
|
|
7649
8241
|
const material = new THREE.ShaderMaterial({ transparent: true, depthWrite: false, blending: THREE.AdditiveBlending, vertexShader: GLOW_VERTEX, fragmentShader: GLOW_FRAGMENT });
|
|
7650
|
-
const
|
|
7651
|
-
|
|
7652
|
-
|
|
7653
|
-
|
|
8242
|
+
const mesh2 = new THREE.Mesh(geometry, material);
|
|
8243
|
+
mesh2.name = "vfx-glows";
|
|
8244
|
+
mesh2.frustumCulled = false;
|
|
8245
|
+
mesh2.renderOrder = 6;
|
|
7654
8246
|
return {
|
|
7655
|
-
mesh,
|
|
8247
|
+
mesh: mesh2,
|
|
7656
8248
|
sync() {
|
|
7657
8249
|
let n = 0;
|
|
7658
8250
|
for (const g of pool.items) {
|
|
@@ -7681,14 +8273,14 @@ void main(){
|
|
|
7681
8273
|
const rockMaterial = new THREE.MeshStandardMaterial({ color: 16777215, roughness: 0.85, flatShading: true });
|
|
7682
8274
|
const plateMaterial = rockMaterial.clone();
|
|
7683
8275
|
const make = (geometry, material) => {
|
|
7684
|
-
const
|
|
7685
|
-
|
|
7686
|
-
|
|
7687
|
-
|
|
7688
|
-
|
|
7689
|
-
|
|
7690
|
-
|
|
7691
|
-
return
|
|
8276
|
+
const mesh2 = new THREE.InstancedMesh(geometry, material, capacity);
|
|
8277
|
+
mesh2.instanceMatrix.setUsage(THREE.DynamicDrawUsage);
|
|
8278
|
+
mesh2.castShadow = true;
|
|
8279
|
+
mesh2.receiveShadow = true;
|
|
8280
|
+
mesh2.frustumCulled = false;
|
|
8281
|
+
mesh2.count = 0;
|
|
8282
|
+
mesh2.setColorAt(0, new THREE.Color(1, 1, 1));
|
|
8283
|
+
return mesh2;
|
|
7692
8284
|
};
|
|
7693
8285
|
const rocks = make(shapes.rock, rockMaterial);
|
|
7694
8286
|
const plates = make(shapes.plate, plateMaterial);
|
|
@@ -7707,20 +8299,20 @@ void main(){
|
|
|
7707
8299
|
euler.set(chunk.rx, chunk.ry, chunk.rz);
|
|
7708
8300
|
quaternion.setFromEuler(euler);
|
|
7709
8301
|
matrix.compose(position.set(chunk.x, chunk.y, chunk.z), quaternion, scale.set(chunk.sx, chunk.sy, chunk.sz));
|
|
7710
|
-
const
|
|
8302
|
+
const mesh2 = chunk.plate ? plates : rocks;
|
|
7711
8303
|
const index = chunk.plate ? plateCount++ : rockCount++;
|
|
7712
|
-
|
|
8304
|
+
mesh2.setMatrixAt(index, matrix);
|
|
7713
8305
|
const color = colorOf(chunk);
|
|
7714
|
-
const colors =
|
|
8306
|
+
const colors = mesh2.instanceColor.array;
|
|
7715
8307
|
colors[index * 3] = color[0];
|
|
7716
8308
|
colors[index * 3 + 1] = color[1];
|
|
7717
8309
|
colors[index * 3 + 2] = color[2];
|
|
7718
8310
|
}
|
|
7719
8311
|
rocks.count = rockCount;
|
|
7720
8312
|
plates.count = plateCount;
|
|
7721
|
-
for (const
|
|
7722
|
-
|
|
7723
|
-
|
|
8313
|
+
for (const mesh2 of [rocks, plates]) {
|
|
8314
|
+
mesh2.instanceMatrix.needsUpdate = true;
|
|
8315
|
+
mesh2.instanceColor.needsUpdate = true;
|
|
7724
8316
|
}
|
|
7725
8317
|
return rockCount + plateCount;
|
|
7726
8318
|
},
|
|
@@ -7910,28 +8502,28 @@ void main(){
|
|
|
7910
8502
|
position.setXYZ(index, worldX, (options.ground?.heightAt(worldX, worldZ) ?? 0) + mark.lift, worldZ);
|
|
7911
8503
|
}
|
|
7912
8504
|
geometry.computeVertexNormals();
|
|
7913
|
-
const
|
|
7914
|
-
|
|
7915
|
-
return
|
|
8505
|
+
const mesh2 = new THREE.Mesh(geometry, material);
|
|
8506
|
+
mesh2.receiveShadow = true;
|
|
8507
|
+
return mesh2;
|
|
7916
8508
|
}
|
|
7917
8509
|
function addRock(mark) {
|
|
7918
|
-
const
|
|
7919
|
-
|
|
7920
|
-
|
|
7921
|
-
|
|
7922
|
-
|
|
7923
|
-
|
|
7924
|
-
return
|
|
8510
|
+
const mesh2 = new THREE.Mesh(mark.plate ? options.plateGeometry : options.rockGeometry, rockMaterial(mark.color));
|
|
8511
|
+
mesh2.position.set(mark.x, mark.y, mark.z);
|
|
8512
|
+
mesh2.scale.set(mark.scale[0], mark.scale[1], mark.scale[2]);
|
|
8513
|
+
mesh2.rotation.set(mark.rotation[0], mark.rotation[1], mark.rotation[2]);
|
|
8514
|
+
mesh2.castShadow = true;
|
|
8515
|
+
mesh2.receiveShadow = true;
|
|
8516
|
+
return mesh2;
|
|
7925
8517
|
}
|
|
7926
8518
|
function addBlood(mark) {
|
|
7927
|
-
const
|
|
7928
|
-
|
|
7929
|
-
|
|
7930
|
-
|
|
7931
|
-
|
|
7932
|
-
|
|
7933
|
-
blood.push({ mesh, scaleX: mark.scaleX, scaleZ: mark.scaleZ, age: 0 });
|
|
7934
|
-
return
|
|
8519
|
+
const mesh2 = new THREE.Mesh(bloodGeometry, bloodMaterial);
|
|
8520
|
+
mesh2.position.set(mark.x, mark.y, mark.z);
|
|
8521
|
+
mesh2.scale.set(mark.scaleX, 1, mark.scaleZ);
|
|
8522
|
+
mesh2.rotation.y = mark.rotation;
|
|
8523
|
+
mesh2.receiveShadow = true;
|
|
8524
|
+
mesh2.scale.multiplyScalar(0.05);
|
|
8525
|
+
blood.push({ mesh: mesh2, scaleX: mark.scaleX, scaleZ: mark.scaleZ, age: 0 });
|
|
8526
|
+
return mesh2;
|
|
7935
8527
|
}
|
|
7936
8528
|
function build(mark) {
|
|
7937
8529
|
if (mark.kind === "scorch") return conform(mark, scorchMaterials[mark.variant]);
|
|
@@ -8153,6 +8745,75 @@ void main() {
|
|
|
8153
8745
|
};
|
|
8154
8746
|
}
|
|
8155
8747
|
|
|
8748
|
+
// src/mesh-layer.ts
|
|
8749
|
+
var SPHERE_DEFAULT_WIDTH = 8;
|
|
8750
|
+
var SPHERE_DEFAULT_HEIGHT = 6;
|
|
8751
|
+
function geometryOf(THREE, particle) {
|
|
8752
|
+
switch (particle.shape) {
|
|
8753
|
+
case "cone":
|
|
8754
|
+
return new THREE.ConeGeometry(particle.radius, particle.height, particle.segments || void 0, particle.segments2 || 1, false);
|
|
8755
|
+
case "cone_open":
|
|
8756
|
+
return new THREE.ConeGeometry(particle.radius, particle.height, particle.segments || void 0, particle.segments2 || 1, true);
|
|
8757
|
+
case "sphere":
|
|
8758
|
+
return new THREE.SphereGeometry(particle.radius, particle.segments || SPHERE_DEFAULT_WIDTH, particle.segments2 || SPHERE_DEFAULT_HEIGHT);
|
|
8759
|
+
case "icosahedron":
|
|
8760
|
+
return new THREE.IcosahedronGeometry(particle.radius, particle.segments);
|
|
8761
|
+
}
|
|
8762
|
+
}
|
|
8763
|
+
function materialOf(THREE, particle) {
|
|
8764
|
+
if (particle.lit) return new THREE.MeshStandardMaterial({ color: particle.color, roughness: 1, metalness: 0, transparent: true, opacity: particle.opacity, depthWrite: false });
|
|
8765
|
+
return new THREE.MeshBasicMaterial({ color: particle.color, transparent: true, opacity: particle.opacity, depthWrite: false, ...particle.additive ? { blending: THREE.AdditiveBlending } : {} });
|
|
8766
|
+
}
|
|
8767
|
+
function createMeshLayer(THREE, pool) {
|
|
8768
|
+
const group = new THREE.Group();
|
|
8769
|
+
group.name = "workshop-meshes";
|
|
8770
|
+
const drawn = /* @__PURE__ */ new Map();
|
|
8771
|
+
const frame = new THREE.Quaternion();
|
|
8772
|
+
const euler = new THREE.Euler();
|
|
8773
|
+
const turn = new THREE.Quaternion();
|
|
8774
|
+
const offset = new THREE.Vector3();
|
|
8775
|
+
function release(mesh2) {
|
|
8776
|
+
mesh2.removeFromParent();
|
|
8777
|
+
mesh2.geometry.dispose();
|
|
8778
|
+
mesh2.material.dispose();
|
|
8779
|
+
}
|
|
8780
|
+
return {
|
|
8781
|
+
group,
|
|
8782
|
+
sync() {
|
|
8783
|
+
const live = /* @__PURE__ */ new Set();
|
|
8784
|
+
for (const particle of pool.particles) {
|
|
8785
|
+
live.add(particle.id);
|
|
8786
|
+
let mesh2 = drawn.get(particle.id);
|
|
8787
|
+
if (!mesh2) {
|
|
8788
|
+
mesh2 = new THREE.Mesh(geometryOf(THREE, particle), materialOf(THREE, particle));
|
|
8789
|
+
mesh2.frustumCulled = false;
|
|
8790
|
+
mesh2.renderOrder = particle.additive ? 5 : 3;
|
|
8791
|
+
drawn.set(particle.id, mesh2);
|
|
8792
|
+
group.add(mesh2);
|
|
8793
|
+
}
|
|
8794
|
+
frame.set(particle.frame[0], particle.frame[1], particle.frame[2], particle.frame[3]);
|
|
8795
|
+
offset.set(particle.at[0], particle.at[1], particle.at[2]).multiplyScalar(particle.scale).applyQuaternion(frame);
|
|
8796
|
+
mesh2.position.set(particle.x + offset.x, particle.y + offset.y, particle.z + offset.z);
|
|
8797
|
+
turn.setFromEuler(euler.set(particle.rx, particle.ry, particle.rz));
|
|
8798
|
+
mesh2.quaternion.copy(frame).multiply(turn);
|
|
8799
|
+
mesh2.scale.setScalar(particle.scale);
|
|
8800
|
+
mesh2.material.opacity = particle.opacity;
|
|
8801
|
+
}
|
|
8802
|
+
for (const [id, mesh2] of drawn) {
|
|
8803
|
+
if (live.has(id)) continue;
|
|
8804
|
+
release(mesh2);
|
|
8805
|
+
drawn.delete(id);
|
|
8806
|
+
}
|
|
8807
|
+
return pool.count;
|
|
8808
|
+
},
|
|
8809
|
+
dispose() {
|
|
8810
|
+
for (const mesh2 of drawn.values()) release(mesh2);
|
|
8811
|
+
drawn.clear();
|
|
8812
|
+
group.removeFromParent();
|
|
8813
|
+
}
|
|
8814
|
+
};
|
|
8815
|
+
}
|
|
8816
|
+
|
|
8156
8817
|
// src/shaders/workshop-sprite.ts
|
|
8157
8818
|
var WORKSHOP_SPRITE_VERTEX = `attribute float size;attribute float alpha;attribute vec3 pcol;varying vec3 vC;varying float vA;uniform float uScale;
|
|
8158
8819
|
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;}`;
|
|
@@ -8231,13 +8892,37 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
8231
8892
|
}
|
|
8232
8893
|
};
|
|
8233
8894
|
}
|
|
8895
|
+
function rainLayer(THREE, rain) {
|
|
8896
|
+
const geometry = new THREE.BufferGeometry();
|
|
8897
|
+
const position = new THREE.BufferAttribute(rain.positions, 3).setUsage(THREE.DynamicDrawUsage);
|
|
8898
|
+
geometry.setAttribute("position", position);
|
|
8899
|
+
geometry.setDrawRange(0, 0);
|
|
8900
|
+
const material = new THREE.LineBasicMaterial({ color: 10466255, transparent: true, opacity: 0.35, depthWrite: false });
|
|
8901
|
+
const lines = new THREE.LineSegments(geometry, material);
|
|
8902
|
+
lines.frustumCulled = false;
|
|
8903
|
+
lines.name = "workshop-rain";
|
|
8904
|
+
return {
|
|
8905
|
+
object: lines,
|
|
8906
|
+
sync() {
|
|
8907
|
+
const drawn = rain.on && rain.count > 0;
|
|
8908
|
+
lines.visible = drawn;
|
|
8909
|
+
geometry.setDrawRange(0, drawn ? rain.count * 2 : 0);
|
|
8910
|
+
position.needsUpdate = true;
|
|
8911
|
+
return drawn;
|
|
8912
|
+
},
|
|
8913
|
+
dispose() {
|
|
8914
|
+
geometry.dispose();
|
|
8915
|
+
material.dispose();
|
|
8916
|
+
}
|
|
8917
|
+
};
|
|
8918
|
+
}
|
|
8234
8919
|
function debrisLayer(THREE, pool) {
|
|
8235
8920
|
const geometry = new THREE.BoxGeometry(1, 1, 1);
|
|
8236
8921
|
const material = new THREE.MeshStandardMaterial({ color: 16777215, roughness: 0.45, metalness: 0.25, flatShading: true });
|
|
8237
|
-
const
|
|
8238
|
-
|
|
8239
|
-
|
|
8240
|
-
|
|
8922
|
+
const mesh2 = new THREE.InstancedMesh(geometry, material, DEBRIS_CAPACITY);
|
|
8923
|
+
mesh2.instanceMatrix.setUsage(THREE.DynamicDrawUsage);
|
|
8924
|
+
mesh2.frustumCulled = false;
|
|
8925
|
+
mesh2.name = "workshop-debris";
|
|
8241
8926
|
const euler = new THREE.Euler();
|
|
8242
8927
|
const quaternion = new THREE.Quaternion();
|
|
8243
8928
|
const position = new THREE.Vector3();
|
|
@@ -8245,16 +8930,16 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
8245
8930
|
const matrix = new THREE.Matrix4();
|
|
8246
8931
|
const colour = new THREE.Color();
|
|
8247
8932
|
const hidden = new THREE.Matrix4().makeScale(0, 0, 0);
|
|
8248
|
-
for (let index = 0; index < DEBRIS_CAPACITY; index++)
|
|
8249
|
-
|
|
8933
|
+
for (let index = 0; index < DEBRIS_CAPACITY; index++) mesh2.setMatrixAt(index, hidden);
|
|
8934
|
+
mesh2.setColorAt(0, colour.setHex(16777215));
|
|
8250
8935
|
return {
|
|
8251
|
-
object:
|
|
8936
|
+
object: mesh2,
|
|
8252
8937
|
sync() {
|
|
8253
8938
|
let drawn = false;
|
|
8254
8939
|
for (let index = 0; index < DEBRIS_CAPACITY; index++) {
|
|
8255
8940
|
const piece = pool.pieces[index];
|
|
8256
8941
|
if (!piece.on) {
|
|
8257
|
-
|
|
8942
|
+
mesh2.setMatrixAt(index, hidden);
|
|
8258
8943
|
continue;
|
|
8259
8944
|
}
|
|
8260
8945
|
drawn = true;
|
|
@@ -8262,11 +8947,11 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
8262
8947
|
euler.set(piece.rx, piece.ry, piece.rz);
|
|
8263
8948
|
quaternion.setFromEuler(euler);
|
|
8264
8949
|
matrix.compose(position.set(piece.x, piece.y, piece.z), quaternion, scale.set(piece.sx * shrink, piece.sy * shrink, piece.sz * shrink));
|
|
8265
|
-
|
|
8266
|
-
|
|
8950
|
+
mesh2.setMatrixAt(index, matrix);
|
|
8951
|
+
mesh2.setColorAt(index, colour.setHex(piece.color));
|
|
8267
8952
|
}
|
|
8268
|
-
|
|
8269
|
-
if (
|
|
8953
|
+
mesh2.instanceMatrix.needsUpdate = true;
|
|
8954
|
+
if (mesh2.instanceColor) mesh2.instanceColor.needsUpdate = true;
|
|
8270
8955
|
return drawn;
|
|
8271
8956
|
},
|
|
8272
8957
|
dispose() {
|
|
@@ -8323,11 +9008,11 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
8323
9008
|
const dryMesh = new THREE.InstancedMesh(geometry, dry, DECAL_CAPACITY);
|
|
8324
9009
|
const group = new THREE.Group();
|
|
8325
9010
|
group.name = "workshop-decals";
|
|
8326
|
-
for (const
|
|
8327
|
-
|
|
8328
|
-
|
|
8329
|
-
|
|
8330
|
-
group.add(
|
|
9011
|
+
for (const mesh2 of [wetMesh, dryMesh]) {
|
|
9012
|
+
mesh2.frustumCulled = false;
|
|
9013
|
+
mesh2.renderOrder = 1;
|
|
9014
|
+
mesh2.instanceMatrix.setUsage(THREE.DynamicDrawUsage);
|
|
9015
|
+
group.add(mesh2);
|
|
8331
9016
|
}
|
|
8332
9017
|
const hidden = new THREE.Matrix4().makeScale(0, 0, 0);
|
|
8333
9018
|
const colour = new THREE.Color();
|
|
@@ -8364,13 +9049,13 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
8364
9049
|
quaternion.multiply(turn.setFromAxisAngle(forward, index * 2.399963));
|
|
8365
9050
|
const offset = 4e-3 + index % 40 * 4e-4;
|
|
8366
9051
|
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));
|
|
8367
|
-
const
|
|
8368
|
-
|
|
8369
|
-
|
|
9052
|
+
const mesh2 = look.dried ? dryMesh : wetMesh;
|
|
9053
|
+
mesh2.setMatrixAt(index, matrix);
|
|
9054
|
+
mesh2.setColorAt(index, colour);
|
|
8370
9055
|
}
|
|
8371
|
-
for (const
|
|
8372
|
-
|
|
8373
|
-
if (
|
|
9056
|
+
for (const mesh2 of [wetMesh, dryMesh]) {
|
|
9057
|
+
mesh2.instanceMatrix.needsUpdate = true;
|
|
9058
|
+
if (mesh2.instanceColor) mesh2.instanceColor.needsUpdate = true;
|
|
8374
9059
|
}
|
|
8375
9060
|
return drawn;
|
|
8376
9061
|
},
|
|
@@ -8384,10 +9069,10 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
8384
9069
|
function ringLayer(THREE, pool) {
|
|
8385
9070
|
const geometry = new THREE.RingGeometry(0.86, 1, 40);
|
|
8386
9071
|
const material = new THREE.MeshBasicMaterial({ color: 16777215, transparent: true, blending: THREE.AdditiveBlending, depthWrite: false, side: THREE.DoubleSide });
|
|
8387
|
-
const
|
|
8388
|
-
|
|
8389
|
-
|
|
8390
|
-
|
|
9072
|
+
const mesh2 = new THREE.InstancedMesh(geometry, material, RING_CAPACITY3);
|
|
9073
|
+
mesh2.frustumCulled = false;
|
|
9074
|
+
mesh2.instanceMatrix.setUsage(THREE.DynamicDrawUsage);
|
|
9075
|
+
mesh2.name = "workshop-rings";
|
|
8391
9076
|
const hidden = new THREE.Matrix4().makeScale(0, 0, 0);
|
|
8392
9077
|
const colour = new THREE.Color();
|
|
8393
9078
|
const normal = new THREE.Vector3();
|
|
@@ -8396,16 +9081,16 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
8396
9081
|
const position = new THREE.Vector3();
|
|
8397
9082
|
const scale = new THREE.Vector3();
|
|
8398
9083
|
const matrix = new THREE.Matrix4();
|
|
8399
|
-
|
|
8400
|
-
for (let index = 0; index < RING_CAPACITY3; index++)
|
|
9084
|
+
mesh2.setColorAt(0, colour.setHex(0));
|
|
9085
|
+
for (let index = 0; index < RING_CAPACITY3; index++) mesh2.setMatrixAt(index, hidden);
|
|
8401
9086
|
return {
|
|
8402
|
-
object:
|
|
9087
|
+
object: mesh2,
|
|
8403
9088
|
sync() {
|
|
8404
9089
|
let drawn = false;
|
|
8405
9090
|
for (let index = 0; index < RING_CAPACITY3; index++) {
|
|
8406
9091
|
const ring2 = pool.rings[index];
|
|
8407
9092
|
if (!ring2.on) {
|
|
8408
|
-
|
|
9093
|
+
mesh2.setMatrixAt(index, hidden);
|
|
8409
9094
|
continue;
|
|
8410
9095
|
}
|
|
8411
9096
|
drawn = true;
|
|
@@ -8413,11 +9098,11 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
8413
9098
|
const radius = ring2.from + (ring2.to - ring2.from) * (1 - Math.pow(1 - k, 2));
|
|
8414
9099
|
quaternion.setFromUnitVectors(forward, normal.set(ring2.normal[0], ring2.normal[1], ring2.normal[2]));
|
|
8415
9100
|
matrix.compose(position.set(ring2.point[0], ring2.point[1], ring2.point[2]), quaternion, scale.set(radius, radius, 1));
|
|
8416
|
-
|
|
8417
|
-
|
|
9101
|
+
mesh2.setMatrixAt(index, matrix);
|
|
9102
|
+
mesh2.setColorAt(index, colour.setHex(ring2.color).multiplyScalar(ring2.hold ? ring2.hold : 1 - k));
|
|
8418
9103
|
}
|
|
8419
|
-
|
|
8420
|
-
if (
|
|
9104
|
+
mesh2.instanceMatrix.needsUpdate = true;
|
|
9105
|
+
if (mesh2.instanceColor) mesh2.instanceColor.needsUpdate = true;
|
|
8421
9106
|
return drawn;
|
|
8422
9107
|
},
|
|
8423
9108
|
dispose() {
|
|
@@ -8433,11 +9118,14 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
8433
9118
|
spriteLayer(THREE, engine.add, true, 1, pointScale),
|
|
8434
9119
|
spriteLayer(THREE, engine.normal, false, 0.55, pointScale),
|
|
8435
9120
|
streakLayer(THREE, engine.streaks),
|
|
9121
|
+
rainLayer(THREE, engine.rain),
|
|
8436
9122
|
debrisLayer(THREE, engine.debris),
|
|
8437
9123
|
decalLayer(THREE, engine.decals),
|
|
8438
9124
|
ringLayer(THREE, engine.rings)
|
|
8439
9125
|
];
|
|
8440
9126
|
for (const layer2 of layers) group.add(layer2.object);
|
|
9127
|
+
const meshes = createMeshLayer(THREE, engine.meshes);
|
|
9128
|
+
group.add(meshes.group);
|
|
8441
9129
|
const flashLights = engine.lights.lights.map(() => new THREE.PointLight(16760944, 0, 14));
|
|
8442
9130
|
const fireLights = engine.lights.fire.map(() => new THREE.PointLight(FIRE_LIGHT_COLOR, 0, FIRE_LIGHT_DISTANCE));
|
|
8443
9131
|
for (const light of [...flashLights, ...fireLights]) group.add(light);
|
|
@@ -8446,6 +9134,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
8446
9134
|
sync() {
|
|
8447
9135
|
let drawCalls = 0;
|
|
8448
9136
|
for (const layer2 of layers) if (layer2.sync()) drawCalls++;
|
|
9137
|
+
drawCalls += meshes.sync();
|
|
8449
9138
|
engine.lights.lights.forEach((source, index) => {
|
|
8450
9139
|
const light = flashLights[index];
|
|
8451
9140
|
light.position.set(source.x, source.y, source.z);
|
|
@@ -8462,6 +9151,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
8462
9151
|
},
|
|
8463
9152
|
dispose() {
|
|
8464
9153
|
for (const layer2 of layers) layer2.dispose();
|
|
9154
|
+
meshes.dispose();
|
|
8465
9155
|
group.clear();
|
|
8466
9156
|
}
|
|
8467
9157
|
};
|
|
@@ -8580,8 +9270,10 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
8580
9270
|
return world.play(request.effect, request.point, {
|
|
8581
9271
|
...request.direction ? { direction: request.direction } : {},
|
|
8582
9272
|
...request.normal ? { normal: request.normal } : {},
|
|
9273
|
+
...request.orientation ? { orientation: request.orientation } : {},
|
|
8583
9274
|
...request.seed !== void 0 ? { seed: request.seed } : {},
|
|
8584
|
-
...request.param !== void 0 ? { param: request.param } : {}
|
|
9275
|
+
...request.param !== void 0 ? { param: request.param } : {},
|
|
9276
|
+
...request.values ? { values: request.values } : {}
|
|
8585
9277
|
});
|
|
8586
9278
|
},
|
|
8587
9279
|
stop: (handle) => world.stop(handle),
|
|
@@ -9002,8 +9694,8 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
9002
9694
|
const uv = geometry.attributes.uv;
|
|
9003
9695
|
for (let index = 0; index < position.count; index++) uv.setXY(index, position.getX(index) / metres, position.getZ(index) / metres);
|
|
9004
9696
|
const material = options.material ?? new THREE.MeshStandardMaterial({ color: 2829359, roughness: 0.93, flatShading: true });
|
|
9005
|
-
const
|
|
9006
|
-
|
|
9697
|
+
const mesh2 = new THREE.Mesh(geometry, material);
|
|
9698
|
+
mesh2.receiveShadow = true;
|
|
9007
9699
|
let version = -1;
|
|
9008
9700
|
function sync() {
|
|
9009
9701
|
if (field.version === version) return false;
|
|
@@ -9014,7 +9706,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
9014
9706
|
return true;
|
|
9015
9707
|
}
|
|
9016
9708
|
return {
|
|
9017
|
-
mesh,
|
|
9709
|
+
mesh: mesh2,
|
|
9018
9710
|
sync,
|
|
9019
9711
|
dispose() {
|
|
9020
9712
|
geometry.dispose();
|