@adatechnology/game-fluids-three 0.2.3 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +14 -0
- package/dist/index.global.js +909 -233
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +29 -2
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.global.js
CHANGED
|
@@ -1364,77 +1364,77 @@ var GameFluidsThree = (() => {
|
|
|
1364
1364
|
}));
|
|
1365
1365
|
}
|
|
1366
1366
|
function spawnPuff(pool, random, init) {
|
|
1367
|
-
const
|
|
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
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
return
|
|
1397
|
-
}
|
|
1398
|
-
function ageOrKeep2(
|
|
1399
|
-
|
|
1400
|
-
return
|
|
1401
|
-
}
|
|
1402
|
-
function moveOnRing(
|
|
1367
|
+
const puff3 = pool.acquire();
|
|
1368
|
+
puff3.x = init.x ?? 0;
|
|
1369
|
+
puff3.y = init.y ?? 0;
|
|
1370
|
+
puff3.z = init.z ?? 0;
|
|
1371
|
+
puff3.vx = init.vx ?? 0;
|
|
1372
|
+
puff3.vy = init.vy ?? 0;
|
|
1373
|
+
puff3.vz = init.vz ?? 0;
|
|
1374
|
+
puff3.s0 = init.s0 ?? 0.2;
|
|
1375
|
+
puff3.s1 = init.s1 ?? 1;
|
|
1376
|
+
puff3.sg = init.sg ?? 0.1;
|
|
1377
|
+
puff3.gk = init.gk ?? 6;
|
|
1378
|
+
puff3.life = init.life ?? 3;
|
|
1379
|
+
puff3.t = 0;
|
|
1380
|
+
puff3.h0 = init.h0 ?? 0;
|
|
1381
|
+
puff3.hl = init.hl ?? 0.4;
|
|
1382
|
+
puff3.drag = init.drag ?? 3;
|
|
1383
|
+
puff3.buoy = init.buoy ?? 0.5;
|
|
1384
|
+
puff3.grav = init.grav ?? 0;
|
|
1385
|
+
puff3.kind = init.kind ?? 0;
|
|
1386
|
+
puff3.seed = random.next();
|
|
1387
|
+
puff3.wind = init.wind ?? 1;
|
|
1388
|
+
puff3.color = init.color ?? SMOKE_COLORS.grey;
|
|
1389
|
+
puff3.ring = init.ring ?? null;
|
|
1390
|
+
puff3.ph = init.ph ?? 0;
|
|
1391
|
+
puff3.th = init.th ?? 0;
|
|
1392
|
+
puff3.rng = random;
|
|
1393
|
+
puff3.age = 0;
|
|
1394
|
+
puff3.heat = 0;
|
|
1395
|
+
puff3.size = 0;
|
|
1396
|
+
return puff3;
|
|
1397
|
+
}
|
|
1398
|
+
function ageOrKeep2(puff3, dt) {
|
|
1399
|
+
puff3.t += dt;
|
|
1400
|
+
return puff3.t < puff3.life;
|
|
1401
|
+
}
|
|
1402
|
+
function moveOnRing(puff3, ring2, wind) {
|
|
1403
1403
|
const ringTime = ring2.t;
|
|
1404
1404
|
const centerY = ring2.y0 + ring2.rise * (1 - Math.exp(-ringTime * ring2.rk));
|
|
1405
1405
|
const majorRadius = ring2.R0 + (ring2.R1 - ring2.R0) * (1 - Math.exp(-ringTime * 1.6));
|
|
1406
|
-
const theta =
|
|
1406
|
+
const theta = puff3.th + ringTime * ring2.roll;
|
|
1407
1407
|
const minorRadius = ring2.r * (0.8 + 0.4 * Math.min(1, ringTime));
|
|
1408
1408
|
const radius = majorRadius + minorRadius * Math.cos(theta);
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
}
|
|
1413
|
-
function moveFree(
|
|
1414
|
-
const damping = Math.exp(-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
if (
|
|
1423
|
-
|
|
1424
|
-
if (
|
|
1409
|
+
puff3.x = ring2.x + Math.cos(puff3.ph) * radius + wind.x * ringTime * 0.6;
|
|
1410
|
+
puff3.z = ring2.z + Math.sin(puff3.ph) * radius + wind.z * ringTime * 0.6;
|
|
1411
|
+
puff3.y = centerY + minorRadius * Math.sin(theta);
|
|
1412
|
+
}
|
|
1413
|
+
function moveFree(puff3, dt, age, heat, wind) {
|
|
1414
|
+
const damping = Math.exp(-puff3.drag * dt);
|
|
1415
|
+
puff3.vx *= damping;
|
|
1416
|
+
puff3.vy *= damping;
|
|
1417
|
+
puff3.vz *= damping;
|
|
1418
|
+
puff3.vy += (puff3.buoy * (heat > 0 ? 1.6 : 1) - puff3.grav) * dt;
|
|
1419
|
+
puff3.x += (puff3.vx + wind.x * puff3.wind * age) * dt;
|
|
1420
|
+
puff3.y += puff3.vy * dt;
|
|
1421
|
+
puff3.z += (puff3.vz + wind.z * puff3.wind * age) * dt;
|
|
1422
|
+
if (puff3.y < puff3.s0 * FLOOR_FRACTION) {
|
|
1423
|
+
puff3.y = puff3.s0 * FLOOR_FRACTION;
|
|
1424
|
+
if (puff3.vy < 0) puff3.vy *= FLOOR_BOUNCE;
|
|
1425
1425
|
}
|
|
1426
1426
|
}
|
|
1427
1427
|
function updatePuffs(pool, dt, wind) {
|
|
1428
1428
|
pool.compact(ageOrKeep2, dt);
|
|
1429
|
-
for (const
|
|
1430
|
-
const age =
|
|
1431
|
-
const heat =
|
|
1432
|
-
if (
|
|
1433
|
-
else moveFree(
|
|
1434
|
-
const size =
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1429
|
+
for (const puff3 of pool.items) {
|
|
1430
|
+
const age = puff3.t / puff3.life;
|
|
1431
|
+
const heat = puff3.h0 > 0 ? puff3.h0 * Math.pow(Math.max(0, 1 - puff3.t / puff3.hl), 1.25) : 0;
|
|
1432
|
+
if (puff3.ring) moveOnRing(puff3, puff3.ring, wind);
|
|
1433
|
+
else moveFree(puff3, dt, age, heat, wind);
|
|
1434
|
+
const size = puff3.s0 + (puff3.s1 - puff3.s0) * (1 - Math.exp(-puff3.t * puff3.gk)) + puff3.sg * Math.min(puff3.t, GROWTH_CAP_SECONDS);
|
|
1435
|
+
puff3.size = size * Math.min(1, puff3.t * ARRIVAL_FRAME + ARRIVAL_BASE);
|
|
1436
|
+
puff3.age = age;
|
|
1437
|
+
puff3.heat = heat;
|
|
1438
1438
|
}
|
|
1439
1439
|
}
|
|
1440
1440
|
var GROUND_LIFT = 0.02;
|
|
@@ -1491,9 +1491,9 @@ var GameFluidsThree = (() => {
|
|
|
1491
1491
|
var HOT_GLOW_COLOR = [1, 0.45, 0.12];
|
|
1492
1492
|
function addPuff(core, random, init) {
|
|
1493
1493
|
core.spawned.puffs++;
|
|
1494
|
-
const
|
|
1495
|
-
core.trace?.puff?.(
|
|
1496
|
-
return
|
|
1494
|
+
const puff3 = spawnPuff(core.puffs, random, init);
|
|
1495
|
+
core.trace?.puff?.(puff3);
|
|
1496
|
+
return puff3;
|
|
1497
1497
|
}
|
|
1498
1498
|
function addSpark(core, init) {
|
|
1499
1499
|
core.spawned.sparks++;
|
|
@@ -1675,6 +1675,7 @@ var GameFluidsThree = (() => {
|
|
|
1675
1675
|
var neg = call("neg");
|
|
1676
1676
|
var abs = call("abs");
|
|
1677
1677
|
var sqrt = call("sqrt");
|
|
1678
|
+
var exp = call("exp");
|
|
1678
1679
|
var sin = call("sin");
|
|
1679
1680
|
var cos = call("cos");
|
|
1680
1681
|
var atan2 = call("atan2");
|
|
@@ -1720,10 +1721,12 @@ var GameFluidsThree = (() => {
|
|
|
1720
1721
|
var INDEX = { $: "index" };
|
|
1721
1722
|
var QUALITY = { $: "quality" };
|
|
1722
1723
|
var FRESH = { $: "fresh" };
|
|
1724
|
+
var DIRECTION = { $: "direction" };
|
|
1723
1725
|
var CAMERA_POSITION = { $: "cameraPosition" };
|
|
1724
1726
|
var burst = (system, count, spawn2) => ({ op: "burst", system, count, spawn: spawn2 });
|
|
1725
1727
|
var spawn = (system, options) => ({ op: "spawn", system, spawn: options });
|
|
1726
1728
|
var emit = (key, system, rate, options) => ({ op: "emit", key, system, rate, spawn: options });
|
|
1729
|
+
var mesh = (options) => ({ op: "mesh", spawn: options });
|
|
1727
1730
|
var debris = (options) => ({ op: "debris", spawn: options });
|
|
1728
1731
|
var decal = (...args) => ({ op: "decal", args });
|
|
1729
1732
|
var ring = (...args) => ({ op: "ring", args });
|
|
@@ -2735,6 +2738,241 @@ var GameFluidsThree = (() => {
|
|
|
2735
2738
|
)
|
|
2736
2739
|
]
|
|
2737
2740
|
};
|
|
2741
|
+
var SPOTS_X = [-3, 1, 5];
|
|
2742
|
+
var SPOTS_Z = [-1, -2.4, 0.4];
|
|
2743
|
+
var FOG_AND_ASH = {
|
|
2744
|
+
id: "fog_and_ash",
|
|
2745
|
+
pageId: "neblina",
|
|
2746
|
+
team: "world",
|
|
2747
|
+
budget: { particles: 120, lights: 1 },
|
|
2748
|
+
loop: 0,
|
|
2749
|
+
view: { eye: [3, 1.8, 7.5], target: [-3, 1.2, -1] },
|
|
2750
|
+
setup: [
|
|
2751
|
+
cue("fog", { density: 0.075 }),
|
|
2752
|
+
cue("lamp_cone", { visible: true }),
|
|
2753
|
+
cue("zombie_visible", { index: -1, visible: false }),
|
|
2754
|
+
repeat(
|
|
2755
|
+
SPOTS_X.length,
|
|
2756
|
+
set("turn", rnd(-0.6, 0.6)),
|
|
2757
|
+
behavior("walkers", "place", { index: INDEX, x: pick(SPOTS_X, INDEX), z: pick(SPOTS_Z, INDEX), facing: variable("turn") })
|
|
2758
|
+
)
|
|
2759
|
+
],
|
|
2760
|
+
timeline: [],
|
|
2761
|
+
tick: [
|
|
2762
|
+
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 }),
|
|
2763
|
+
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 })
|
|
2764
|
+
]
|
|
2765
|
+
};
|
|
2766
|
+
var RAIN_CAPACITY = 4e3;
|
|
2767
|
+
var FALL_SPEED = 15;
|
|
2768
|
+
var WIND_PER_FALL = 0.07;
|
|
2769
|
+
var STREAK_SLANT = 0.04;
|
|
2770
|
+
var STREAK_LENGTH = 0.6;
|
|
2771
|
+
var BOX_X = [-15, 15];
|
|
2772
|
+
var BOX_Z = [-6, 16];
|
|
2773
|
+
var START_HEIGHT = [0, 16];
|
|
2774
|
+
var REENTRY_HEIGHT = [14, 17];
|
|
2775
|
+
var SPLASH_CHANCE = 0.35;
|
|
2776
|
+
var SPLASH_RANGE = 12;
|
|
2777
|
+
var SPRITE_CHANCE = 0.5;
|
|
2778
|
+
var UP9 = [0, 1, 0];
|
|
2779
|
+
var WORKSHOP_PUDDLES = [
|
|
2780
|
+
[-1.5, 2.2, 1.6, 0.9],
|
|
2781
|
+
[3, 3.6, 1.1, 0.7],
|
|
2782
|
+
[-6, 3.2, 1.3, 0.8],
|
|
2783
|
+
[1.4, -2.2, 0.9, 0.5]
|
|
2784
|
+
];
|
|
2785
|
+
var inPuddle = (puddles, x, z) => puddles.some((p) => ((x - p[0]) / p[2]) ** 2 + ((z - p[1]) / p[3]) ** 2 < 1);
|
|
2786
|
+
var RainField = class {
|
|
2787
|
+
constructor(engine) {
|
|
2788
|
+
__publicField2(this, "engine", engine);
|
|
2789
|
+
__publicField2(this, "positions", new Float32Array(RAIN_CAPACITY * 6));
|
|
2790
|
+
__publicField2(this, "count", 0);
|
|
2791
|
+
__publicField2(this, "wind", 1);
|
|
2792
|
+
__publicField2(this, "on", false);
|
|
2793
|
+
__publicField2(this, "centerX", 0);
|
|
2794
|
+
__publicField2(this, "centerZ", 0);
|
|
2795
|
+
__publicField2(this, "puddles", WORKSHOP_PUDDLES);
|
|
2796
|
+
__publicField2(this, "puddleAt");
|
|
2797
|
+
}
|
|
2798
|
+
/** `initRain` (W321): `count` streaks (thinned by the quality), each drawn at a random place in the box. */
|
|
2799
|
+
init(count, wind) {
|
|
2800
|
+
const { random } = this.engine;
|
|
2801
|
+
this.count = Math.min(RAIN_CAPACITY, Math.round(count * this.engine.context.quality.mult));
|
|
2802
|
+
this.wind = wind;
|
|
2803
|
+
this.on = true;
|
|
2804
|
+
for (let index = 0; index < this.count; index++) {
|
|
2805
|
+
const offset = index * 6;
|
|
2806
|
+
const x = random.between(BOX_X[0], BOX_X[1]);
|
|
2807
|
+
const y = random.between(START_HEIGHT[0], START_HEIGHT[1]);
|
|
2808
|
+
const z = random.between(BOX_Z[0], BOX_Z[1]);
|
|
2809
|
+
this.set(offset, x, y, z);
|
|
2810
|
+
}
|
|
2811
|
+
}
|
|
2812
|
+
/**
|
|
2813
|
+
* 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
|
|
2814
|
+
* starts at a random place of the box, as `init` draws it) and the wind slants them. The golden never calls it.
|
|
2815
|
+
*/
|
|
2816
|
+
drive(count, wind, centerX, centerZ) {
|
|
2817
|
+
const { random } = this.engine;
|
|
2818
|
+
const target = Math.max(0, Math.min(RAIN_CAPACITY, Math.round(count * this.engine.context.quality.mult)));
|
|
2819
|
+
this.wind = wind;
|
|
2820
|
+
this.centerX = centerX;
|
|
2821
|
+
this.centerZ = centerZ;
|
|
2822
|
+
this.on = target > 0;
|
|
2823
|
+
for (let index = this.count; index < target; index++) {
|
|
2824
|
+
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);
|
|
2825
|
+
}
|
|
2826
|
+
this.count = target;
|
|
2827
|
+
}
|
|
2828
|
+
/** `updateRain` (W322-329). `camera` is where the eye is; `splash` lets the drops that land leave a splash. */
|
|
2829
|
+
update(dt, splash, camera2) {
|
|
2830
|
+
if (!this.on) return;
|
|
2831
|
+
const { random, context } = this.engine;
|
|
2832
|
+
const positions = this.positions;
|
|
2833
|
+
const fall = FALL_SPEED * dt;
|
|
2834
|
+
const slant = this.wind * fall * WIND_PER_FALL;
|
|
2835
|
+
const reach = SPLASH_RANGE / (1 + context.quality.level);
|
|
2836
|
+
for (let index = 0; index < this.count; index++) {
|
|
2837
|
+
const o = index * 6;
|
|
2838
|
+
positions[o] += slant;
|
|
2839
|
+
positions[o + 3] += slant;
|
|
2840
|
+
positions[o + 1] -= fall;
|
|
2841
|
+
positions[o + 4] -= fall;
|
|
2842
|
+
const ground = context.groundAt(positions[o], positions[o + 2]);
|
|
2843
|
+
if (positions[o + 4] < ground) {
|
|
2844
|
+
const x = positions[o];
|
|
2845
|
+
const z = positions[o + 2];
|
|
2846
|
+
if (splash && random.next() < SPLASH_CHANCE) {
|
|
2847
|
+
const distance2 = Math.hypot(x - camera2[0], z - camera2[2]);
|
|
2848
|
+
if (distance2 < reach) {
|
|
2849
|
+
if (random.next() < SPRITE_CHANCE) {
|
|
2850
|
+
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 });
|
|
2851
|
+
}
|
|
2852
|
+
if (this.puddleAt ? this.puddleAt(x, z) : inPuddle(this.puddles, x, z)) {
|
|
2853
|
+
this.engine.ring([[x, ground + 0.012, z], 0.01, random.between(0.12, 0.25), random.between(0.4, 0.6), 6978192]);
|
|
2854
|
+
}
|
|
2855
|
+
}
|
|
2856
|
+
}
|
|
2857
|
+
const nx = random.between(BOX_X[0], BOX_X[1]) + this.centerX;
|
|
2858
|
+
const ny = random.between(REENTRY_HEIGHT[0], REENTRY_HEIGHT[1]);
|
|
2859
|
+
const nz = random.between(BOX_Z[0], BOX_Z[1]) + this.centerZ;
|
|
2860
|
+
this.set(o, nx, ny, nz);
|
|
2861
|
+
}
|
|
2862
|
+
}
|
|
2863
|
+
}
|
|
2864
|
+
/** `rain.visible = false; RN.on = false` (W440): the field stops; the streaks stay where they were. */
|
|
2865
|
+
clear() {
|
|
2866
|
+
this.on = false;
|
|
2867
|
+
}
|
|
2868
|
+
set(offset, x, y, z) {
|
|
2869
|
+
const positions = this.positions;
|
|
2870
|
+
positions[offset] = x;
|
|
2871
|
+
positions[offset + 1] = y;
|
|
2872
|
+
positions[offset + 2] = z;
|
|
2873
|
+
positions[offset + 3] = x + this.wind * STREAK_SLANT;
|
|
2874
|
+
positions[offset + 4] = y - STREAK_LENGTH;
|
|
2875
|
+
positions[offset + 5] = z;
|
|
2876
|
+
}
|
|
2877
|
+
};
|
|
2878
|
+
var DROPS = [900, 2200, 4e3];
|
|
2879
|
+
var SLANT = [0.3, 1.2, 4.5];
|
|
2880
|
+
var STORM = 2;
|
|
2881
|
+
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)));
|
|
2882
|
+
var RAIN_AND_PUDDLES = {
|
|
2883
|
+
id: "rain_and_puddles",
|
|
2884
|
+
pageId: "chuva",
|
|
2885
|
+
team: "world",
|
|
2886
|
+
params: { id: "intensity", options: ["drizzle", "rain", "storm"], default: 1 },
|
|
2887
|
+
budget: { particles: 4e3, decals: 4 },
|
|
2888
|
+
loop: 0,
|
|
2889
|
+
view: { eye: [2, 2, 7], target: [-1, 0.6, 1] },
|
|
2890
|
+
setup: [
|
|
2891
|
+
cue("lamp_cone", { visible: true }),
|
|
2892
|
+
...WORKSHOP_PUDDLES.map(([x, z, radiusX, radiusZ]) => decal(x, 0, z, radiusX * 2, 790550, { grow: 0, life: 1e6, ar: radiusZ / radiusX }))
|
|
2893
|
+
],
|
|
2894
|
+
timeline: [
|
|
2895
|
+
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])) }),
|
|
2896
|
+
set("nextStrike", rnd(2, 4)),
|
|
2897
|
+
set("flash", -1)
|
|
2898
|
+
],
|
|
2899
|
+
tick: [
|
|
2900
|
+
behavior("rain", "update", { dt: DELTA, splash: gt(PARAM, 0) }),
|
|
2901
|
+
when(eq(PARAM, STORM), [
|
|
2902
|
+
when(gt(TIME, variable("nextStrike")), [set("nextStrike", add(TIME, rnd(3.5, 6))), set("flash", 0)]),
|
|
2903
|
+
when(ge(variable("flash"), 0), [
|
|
2904
|
+
set("flash", add(variable("flash"), DELTA)),
|
|
2905
|
+
set("light", FLASH_STEPS),
|
|
2906
|
+
cue("lightning", { intensity: variable("light") }),
|
|
2907
|
+
screen({ max: { white: mul(variable("light"), 0.12) } }),
|
|
2908
|
+
when(gt(variable("flash"), 0.4), [set("flash", -1), cue("lightning", { intensity: 0 })])
|
|
2909
|
+
]),
|
|
2910
|
+
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 })
|
|
2911
|
+
])
|
|
2912
|
+
]
|
|
2913
|
+
};
|
|
2914
|
+
var CAR_ORIGIN2 = [5.6, 0, 0.8];
|
|
2915
|
+
var CAR_ROTATION2 = [0, -0.4, 0];
|
|
2916
|
+
var carPoint = (x, y, z) => localToWorld(CAR_ORIGIN2, CAR_ROTATION2, [x, y, z]);
|
|
2917
|
+
var carDirection = (from, to) => normalized([to[0] - from[0], to[1] - from[1], to[2] - from[2]]);
|
|
2918
|
+
var BEAM_FROM = carPoint(0, 0.74, 2.15);
|
|
2919
|
+
var BEAM_DIRECTION = carDirection(BEAM_FROM, carPoint(0, 0.74, 3.15));
|
|
2920
|
+
var BEAM_SIDE = [BEAM_DIRECTION[2], 0, -BEAM_DIRECTION[0]];
|
|
2921
|
+
var WALKERS = 6;
|
|
2922
|
+
var WALK_SPEED2 = 0.7;
|
|
2923
|
+
var DROPS2 = 1800;
|
|
2924
|
+
var SLANT2 = 0.8;
|
|
2925
|
+
var startWalking = [
|
|
2926
|
+
set("spot", query("car", "point", rnd(-2, 2), 0, rnd(8, 18))),
|
|
2927
|
+
set("goal", query("car", "point", rnd(-0.6, 0.6), 0, 2.6)),
|
|
2928
|
+
behavior("walkers", "place", { index: INDEX, x: pick(variable("spot"), 0), z: pick(variable("spot"), 2), facing: 0 }),
|
|
2929
|
+
behavior("walkers", "walk", { index: INDEX, to: variable("goal"), speed: WALK_SPEED2 })
|
|
2930
|
+
];
|
|
2931
|
+
var HEADLIGHTS_IN_RAIN = {
|
|
2932
|
+
id: "headlights_in_rain",
|
|
2933
|
+
pageId: "farol",
|
|
2934
|
+
team: "vehicles",
|
|
2935
|
+
budget: { particles: 600, lights: 2 },
|
|
2936
|
+
loop: 0,
|
|
2937
|
+
view: { eye: [-2.5, 2, 5.5], target: [4, 1, 6] },
|
|
2938
|
+
setup: [
|
|
2939
|
+
cue("fog", { density: 0.05 }),
|
|
2940
|
+
cue("headlights", { on: true, intensity: 2.4, color: 16773584 }),
|
|
2941
|
+
behavior("rain", "init", { count: DROPS2, wind: SLANT2 }),
|
|
2942
|
+
repeat(WALKERS, ...startWalking)
|
|
2943
|
+
],
|
|
2944
|
+
timeline: [],
|
|
2945
|
+
tick: [
|
|
2946
|
+
behavior("rain", "update", { dt: DELTA, splash: true }),
|
|
2947
|
+
emit(
|
|
2948
|
+
"lit",
|
|
2949
|
+
"streak",
|
|
2950
|
+
600,
|
|
2951
|
+
local(
|
|
2952
|
+
"depth",
|
|
2953
|
+
rnd(1, 13),
|
|
2954
|
+
local(
|
|
2955
|
+
"spread",
|
|
2956
|
+
mul(variable("depth"), 0.33, sqrt(rand())),
|
|
2957
|
+
local(
|
|
2958
|
+
"turn",
|
|
2959
|
+
rnd(0, 6.283),
|
|
2960
|
+
local("base", vadd(BEAM_FROM, vscale(BEAM_DIRECTION, variable("depth")), vscale(BEAM_SIDE, mul(cos(variable("turn")), variable("spread")))), {
|
|
2961
|
+
p: vwith(variable("base"), 1, add(vy(variable("base")), mul(sin(variable("turn")), variable("spread"), 0.6))),
|
|
2962
|
+
v: [0.8, -14, 0],
|
|
2963
|
+
sp: 0,
|
|
2964
|
+
life: 0.06,
|
|
2965
|
+
len: 0.035,
|
|
2966
|
+
c0: 13622512,
|
|
2967
|
+
a: 0.9
|
|
2968
|
+
})
|
|
2969
|
+
)
|
|
2970
|
+
)
|
|
2971
|
+
)
|
|
2972
|
+
),
|
|
2973
|
+
repeat(WALKERS, when(not(query("walkers", "is_walking", INDEX)), startWalking))
|
|
2974
|
+
]
|
|
2975
|
+
};
|
|
2738
2976
|
var YAW = -Math.PI / 2;
|
|
2739
2977
|
var COS = Math.cos(YAW);
|
|
2740
2978
|
var SIN = Math.sin(YAW);
|
|
@@ -2762,10 +3000,6 @@ var GameFluidsThree = (() => {
|
|
|
2762
3000
|
fireLight(0, [vx(variable("contact")), 0.34, vz(variable("contact"))], 1.6, mul(TIME, 3))
|
|
2763
3001
|
]
|
|
2764
3002
|
};
|
|
2765
|
-
var CAR_ORIGIN2 = [5.6, 0, 0.8];
|
|
2766
|
-
var CAR_ROTATION2 = [0, -0.4, 0];
|
|
2767
|
-
var carPoint = (x, y, z) => localToWorld(CAR_ORIGIN2, CAR_ROTATION2, [x, y, z]);
|
|
2768
|
-
var carDirection = (from, to) => normalized([to[0] - from[0], to[1] - from[1], to[2] - from[2]]);
|
|
2769
3003
|
var HOOD = carPoint(0, 1.02, 1.4);
|
|
2770
3004
|
var EXHAUST = carPoint(0.5, 0.3, -2.2);
|
|
2771
3005
|
var EXHAUST_DIRECTION = carDirection(EXHAUST, carPoint(0.5, 0.3, -3));
|
|
@@ -2799,7 +3033,7 @@ var GameFluidsThree = (() => {
|
|
|
2799
3033
|
], [fireLightOff(0)])
|
|
2800
3034
|
]
|
|
2801
3035
|
};
|
|
2802
|
-
var
|
|
3036
|
+
var UP10 = [0, 1, 0];
|
|
2803
3037
|
var doorVelocity = (side) => {
|
|
2804
3038
|
const out = carPoint(side * 4, 3, 0.3);
|
|
2805
3039
|
const centre = carPoint(0, 0, 0.3);
|
|
@@ -2809,7 +3043,7 @@ var GameFluidsThree = (() => {
|
|
|
2809
3043
|
call2("explode", vadd(query("car", "position"), [0, 0.6, 0]), 1.8, 2759188),
|
|
2810
3044
|
cue("car_burnt"),
|
|
2811
3045
|
behavior("car", "launch", { rise: 4.5, spin: 0.9 }),
|
|
2812
|
-
repeat(scaled(30), debris({ p: vadd(query("car", "position"), [0, 1.3, 0]), dir:
|
|
3046
|
+
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 })),
|
|
2813
3047
|
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 }),
|
|
2814
3048
|
...[-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 })),
|
|
2815
3049
|
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 })
|
|
@@ -2979,7 +3213,7 @@ var GameFluidsThree = (() => {
|
|
|
2979
3213
|
])
|
|
2980
3214
|
]
|
|
2981
3215
|
};
|
|
2982
|
-
var
|
|
3216
|
+
var WALKERS2 = 6;
|
|
2983
3217
|
var NEAR = 9;
|
|
2984
3218
|
var RANGE = 7;
|
|
2985
3219
|
var RESTING_BPM = 70;
|
|
@@ -2995,7 +3229,7 @@ var GameFluidsThree = (() => {
|
|
|
2995
3229
|
setup: [
|
|
2996
3230
|
cue("zombie_visible", { index: -1, visible: false }),
|
|
2997
3231
|
repeat(
|
|
2998
|
-
|
|
3232
|
+
WALKERS2,
|
|
2999
3233
|
set("startX", rnd(-4, 4)),
|
|
3000
3234
|
set("startZ", sub(rnd(-4, -2), mul(INDEX, 0.6))),
|
|
3001
3235
|
behavior("walkers", "place", { index: INDEX, x: variable("startX"), z: variable("startZ"), facing: 0 }),
|
|
@@ -3005,7 +3239,7 @@ var GameFluidsThree = (() => {
|
|
|
3005
3239
|
timeline: [],
|
|
3006
3240
|
tick: [
|
|
3007
3241
|
set("nearest", 99),
|
|
3008
|
-
repeat(
|
|
3242
|
+
repeat(WALKERS2, set("nearest", min(variable("nearest"), vdist(walkerPoint, CAMERA_POSITION)))),
|
|
3009
3243
|
set("fear", clamp(div(sub(NEAR, variable("nearest")), RANGE), 0, 1)),
|
|
3010
3244
|
set("bpm", add(RESTING_BPM, mul(BPM_RISE, variable("fear")))),
|
|
3011
3245
|
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"))) } })]),
|
|
@@ -3072,7 +3306,7 @@ var GameFluidsThree = (() => {
|
|
|
3072
3306
|
]
|
|
3073
3307
|
};
|
|
3074
3308
|
var FACING4 = [0, 0, 1];
|
|
3075
|
-
var
|
|
3309
|
+
var UP11 = [0, 1, 0];
|
|
3076
3310
|
var ORIGIN = [0, 0, 0];
|
|
3077
3311
|
var FORWARD4 = [0, 0, -1];
|
|
3078
3312
|
var IMPACT_MATERIALS = ["concrete", "metal", "wood", "glass", "flesh", "water"];
|
|
@@ -3202,12 +3436,148 @@ var GameFluidsThree = (() => {
|
|
|
3202
3436
|
team: "destruction",
|
|
3203
3437
|
budget: { particles: 20, debris: 8 },
|
|
3204
3438
|
loop: 2,
|
|
3205
|
-
timeline: [call2("chips", ORIGIN,
|
|
3439
|
+
timeline: [call2("chips", ORIGIN, UP11, 8, 0.9), call2("rust_at", ORIGIN, 6)]
|
|
3206
3440
|
}
|
|
3207
3441
|
];
|
|
3208
|
-
var
|
|
3442
|
+
var PI = Math.PI;
|
|
3443
|
+
var SMOKE = { color: 9079430, width: 10, height: 8, gravity: -0.08, drag: 2.2, growth: 2.1 };
|
|
3444
|
+
var FLASH_SECONDS = 0.055;
|
|
3445
|
+
var FLASH_RAMP = [0.6, 0.9];
|
|
3446
|
+
var FLASH_OPACITY = 0.95;
|
|
3447
|
+
var FLAME_COLORS = [16742946, 16760896, 13121050, 16773296];
|
|
3448
|
+
var FLAME_ADDITIVE = 3;
|
|
3449
|
+
var ORIGIN2 = [0, 0, 0];
|
|
3450
|
+
var SIZE = variable("size");
|
|
3451
|
+
var wide = (width) => mul(sub(rand(), 0.5), width);
|
|
3452
|
+
var puff2 = (point, velocity, world, radius, life, opacity) => mesh({
|
|
3453
|
+
shape: "sphere",
|
|
3454
|
+
p: point,
|
|
3455
|
+
v: velocity,
|
|
3456
|
+
wv: world,
|
|
3457
|
+
r: radius,
|
|
3458
|
+
seg: SMOKE.width,
|
|
3459
|
+
seg2: SMOKE.height,
|
|
3460
|
+
life,
|
|
3461
|
+
c0: SMOKE.color,
|
|
3462
|
+
a: opacity,
|
|
3463
|
+
fade: true,
|
|
3464
|
+
lit: true,
|
|
3465
|
+
g: SMOKE.gravity,
|
|
3466
|
+
drag: SMOKE.drag,
|
|
3467
|
+
grow: SMOKE.growth
|
|
3468
|
+
});
|
|
3469
|
+
var flameBit = (point, velocity, world, radius, life) => [
|
|
3470
|
+
set("bitPoint", point),
|
|
3471
|
+
set("bitVelocity", velocity),
|
|
3472
|
+
set("bitWorld", world),
|
|
3473
|
+
set("bitRadius", radius),
|
|
3474
|
+
set("bitLife", life),
|
|
3475
|
+
set("bitColour", floor(mul(rand(), FLAME_COLORS.length))),
|
|
3476
|
+
mesh({
|
|
3477
|
+
shape: "icosahedron",
|
|
3478
|
+
p: variable("bitPoint"),
|
|
3479
|
+
v: variable("bitVelocity"),
|
|
3480
|
+
wv: variable("bitWorld"),
|
|
3481
|
+
r: variable("bitRadius"),
|
|
3482
|
+
seg: 1,
|
|
3483
|
+
rot: [mul(rand(), 3), mul(rand(), 3), 0],
|
|
3484
|
+
spin: [3, 4, 2],
|
|
3485
|
+
life: variable("bitLife"),
|
|
3486
|
+
c0: pick(FLAME_COLORS, variable("bitColour")),
|
|
3487
|
+
add: eq(variable("bitColour"), FLAME_ADDITIVE),
|
|
3488
|
+
a: 0.9,
|
|
3489
|
+
fade: true,
|
|
3490
|
+
g: -1.4,
|
|
3491
|
+
drag: 1.4,
|
|
3492
|
+
grow: 2.2
|
|
3493
|
+
})
|
|
3494
|
+
];
|
|
3495
|
+
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 });
|
|
3496
|
+
var MUZZLE_FLASH2 = {
|
|
3497
|
+
id: "viewmodel_muzzle_flash",
|
|
3498
|
+
pageId: "event:viewmodel_muzzle_flash",
|
|
3499
|
+
team: "weapons",
|
|
3500
|
+
budget: { particles: 12, lights: 1 },
|
|
3501
|
+
loop: 0.1,
|
|
3502
|
+
timeline: [
|
|
3503
|
+
set("angles", []),
|
|
3504
|
+
repeat(4, append("angles", add(div(mul(INDEX, PI), 2), mul(rand(), 0.6)))),
|
|
3505
|
+
set("roll", mul(rand(), PI)),
|
|
3506
|
+
flash(ORIGIN2, 16756832, mul(4, SIZE), FLASH_SECONDS, mul(2, SIZE), true, true),
|
|
3507
|
+
flashPiece("cone_open", mul(0.013, SIZE), mul(0.085, SIZE), 10, [mul(0.042, SIZE), 0, 0], [0, 0, -PI / 2], 16757575),
|
|
3508
|
+
repeat(
|
|
3509
|
+
4,
|
|
3510
|
+
set("angle", pick(variable("angles"), INDEX)),
|
|
3511
|
+
flashPiece(
|
|
3512
|
+
"cone",
|
|
3513
|
+
mul(5e-3, SIZE),
|
|
3514
|
+
mul(0.04, SIZE),
|
|
3515
|
+
6,
|
|
3516
|
+
[mul(0.012, SIZE), mul(cos(variable("angle")), 0.016, SIZE), mul(sin(variable("angle")), 0.016, SIZE)],
|
|
3517
|
+
[variable("angle"), 0, -PI / 2],
|
|
3518
|
+
16757575
|
|
3519
|
+
)
|
|
3520
|
+
),
|
|
3521
|
+
flashPiece("sphere", mul(0.016, SIZE), void 0, 12, [mul(8e-3, SIZE), 0, 0], [0, 0, 0], 16773568),
|
|
3522
|
+
repeat(
|
|
3523
|
+
6,
|
|
3524
|
+
puff2(
|
|
3525
|
+
ORIGIN2,
|
|
3526
|
+
[add(0.15, mul(rand(), 0.35)), add(0.03, mul(rand(), 0.12)), mul(sub(rand(), 0.5), 0.14)],
|
|
3527
|
+
[0, 0, 0],
|
|
3528
|
+
mul(0.013, SIZE),
|
|
3529
|
+
add(1.3, mul(rand(), 0.6)),
|
|
3530
|
+
0.45
|
|
3531
|
+
)
|
|
3532
|
+
)
|
|
3533
|
+
]
|
|
3534
|
+
};
|
|
3535
|
+
var SMOKE_PUFF = {
|
|
3536
|
+
id: "weapon_smoke_puff",
|
|
3537
|
+
pageId: "event:weapon_smoke_puff",
|
|
3538
|
+
team: "weapons",
|
|
3539
|
+
budget: { particles: 1 },
|
|
3540
|
+
loop: 0.1,
|
|
3541
|
+
timeline: [puff2(ORIGIN2, void 0, [variable("vx"), variable("vy"), variable("vz")], variable("radius"), variable("life"), variable("opacity"))]
|
|
3542
|
+
};
|
|
3543
|
+
var BACKBLAST = {
|
|
3544
|
+
id: "launcher_backblast",
|
|
3545
|
+
pageId: "event:launcher_backblast",
|
|
3546
|
+
team: "weapons",
|
|
3547
|
+
budget: { particles: 40 },
|
|
3548
|
+
loop: 0.1,
|
|
3549
|
+
timeline: [
|
|
3550
|
+
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)),
|
|
3551
|
+
repeat(14, ...flameBit(ORIGIN2, [neg(add(2, mul(rand(), 2))), 0, 0], [wide(1), wide(0.6), wide(1)], 0.02, 0.25))
|
|
3552
|
+
]
|
|
3553
|
+
};
|
|
3554
|
+
var FLAME_JET = {
|
|
3555
|
+
id: "flame_jet",
|
|
3556
|
+
pageId: "event:flame_jet",
|
|
3557
|
+
team: "weapons",
|
|
3558
|
+
budget: { particles: 30 },
|
|
3559
|
+
loop: 0.1,
|
|
3560
|
+
timeline: [
|
|
3561
|
+
repeat(
|
|
3562
|
+
floor(mul(420, variable("dt"), variable("scale"))),
|
|
3563
|
+
set("speed", mul(add(2.2, mul(rand(), 1.1)), variable("scale"))),
|
|
3564
|
+
...flameBit(
|
|
3565
|
+
[mul(rand(), variable("speed"), min(variable("dt"), 0.3)), 0, 0],
|
|
3566
|
+
[variable("speed"), 0, 0],
|
|
3567
|
+
[wide(0.35), mul(sub(rand(), 0.3), 0.3), wide(0.35)],
|
|
3568
|
+
add(0.02, mul(rand(), 0.022)),
|
|
3569
|
+
add(0.4, mul(rand(), 0.35))
|
|
3570
|
+
)
|
|
3571
|
+
),
|
|
3572
|
+
when(lt(rand(), 0.5), [
|
|
3573
|
+
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)
|
|
3574
|
+
])
|
|
3575
|
+
]
|
|
3576
|
+
};
|
|
3577
|
+
var VIEWMODEL_EFFECTS = [MUZZLE_FLASH2, SMOKE_PUFF, BACKBLAST, FLAME_JET];
|
|
3578
|
+
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];
|
|
3209
3579
|
var WORKSHOP_EFFECTS = Object.fromEntries(ALL_EFFECTS.map((effect) => [effect.id, effect]));
|
|
3210
|
-
var GAME_EFFECTS = { ...WORKSHOP_EFFECTS, ...Object.fromEntries(EVENT_EFFECTS.map((effect) => [effect.id, effect])) };
|
|
3580
|
+
var GAME_EFFECTS = { ...WORKSHOP_EFFECTS, ...Object.fromEntries([...EVENT_EFFECTS, ...VIEWMODEL_EFFECTS].map((effect) => [effect.id, effect])) };
|
|
3211
3581
|
var LEHMER_MULTIPLIER = 16807;
|
|
3212
3582
|
var LEHMER_MODULUS = 2147483647;
|
|
3213
3583
|
var HASH_MIX = 2654435761;
|
|
@@ -3303,7 +3673,7 @@ var GameFluidsThree = (() => {
|
|
|
3303
3673
|
}
|
|
3304
3674
|
var COLUMNS = 6;
|
|
3305
3675
|
var ROWS = 5;
|
|
3306
|
-
var
|
|
3676
|
+
var ORIGIN3 = [-2.2, 0, 2.6];
|
|
3307
3677
|
var BLOCK_SIZE = [0.5, 0.44, 0.25];
|
|
3308
3678
|
var OBJECT_ID_DRAWS2 = 4;
|
|
3309
3679
|
var FLOOR2 = 0.13;
|
|
@@ -3346,7 +3716,7 @@ var GameFluidsThree = (() => {
|
|
|
3346
3716
|
const chipScale = random.between(0.8, 1.3) * scale2;
|
|
3347
3717
|
for (let draw = 0; draw < OBJECT_ID_DRAWS2; draw++) random.next();
|
|
3348
3718
|
best.holes.push({ x: offsetX, y: offsetY, scale: scale2, chipTurn, chipScale });
|
|
3349
|
-
impact(host.engine, "concrete", [
|
|
3719
|
+
impact(host.engine, "concrete", [ORIGIN3[0] + x, y, ORIGIN3[2] + 0.13], [0, 0, 1], 0.8);
|
|
3350
3720
|
} else if (action === "collapse") {
|
|
3351
3721
|
const { x, y } = args;
|
|
3352
3722
|
for (const block of blocks) {
|
|
@@ -3396,7 +3766,7 @@ var GameFluidsThree = (() => {
|
|
|
3396
3766
|
}
|
|
3397
3767
|
};
|
|
3398
3768
|
}
|
|
3399
|
-
var
|
|
3769
|
+
var ORIGIN4 = [5.6, 0, 0.8];
|
|
3400
3770
|
var MAX_TILT = 0.25;
|
|
3401
3771
|
function createCarBehavior() {
|
|
3402
3772
|
let y = 0;
|
|
@@ -3428,8 +3798,13 @@ var GameFluidsThree = (() => {
|
|
|
3428
3798
|
}
|
|
3429
3799
|
}
|
|
3430
3800
|
},
|
|
3431
|
-
query(_host, name) {
|
|
3432
|
-
if (name === "position") return [
|
|
3801
|
+
query(_host, name, args) {
|
|
3802
|
+
if (name === "position") return [ORIGIN4[0], y, ORIGIN4[2]];
|
|
3803
|
+
if (name === "point") {
|
|
3804
|
+
const [x, py, z] = args;
|
|
3805
|
+
const point = carPoint(x, py, z);
|
|
3806
|
+
return [point[0], point[1] + y, point[2]];
|
|
3807
|
+
}
|
|
3433
3808
|
if (name === "roll") return roll;
|
|
3434
3809
|
throw new Error(`car: unknown query ${name}`);
|
|
3435
3810
|
},
|
|
@@ -3629,6 +4004,29 @@ var GameFluidsThree = (() => {
|
|
|
3629
4004
|
}
|
|
3630
4005
|
};
|
|
3631
4006
|
}
|
|
4007
|
+
function createRainBehavior() {
|
|
4008
|
+
return {
|
|
4009
|
+
reset() {
|
|
4010
|
+
},
|
|
4011
|
+
act(host, action, args) {
|
|
4012
|
+
const { engine, camera: camera2 } = host;
|
|
4013
|
+
if (action === "init") {
|
|
4014
|
+
const { count, wind } = args;
|
|
4015
|
+
engine.rain.init(count, wind);
|
|
4016
|
+
} else if (action === "update") {
|
|
4017
|
+
const { dt, splash } = args;
|
|
4018
|
+
engine.rain.update(dt, splash, camera2.position);
|
|
4019
|
+
}
|
|
4020
|
+
},
|
|
4021
|
+
query(host, name) {
|
|
4022
|
+
if (name === "count") return host.engine.rain.count;
|
|
4023
|
+
if (name === "on") return host.engine.rain.on;
|
|
4024
|
+
throw new Error(`rain: unknown query ${name}`);
|
|
4025
|
+
},
|
|
4026
|
+
update() {
|
|
4027
|
+
}
|
|
4028
|
+
};
|
|
4029
|
+
}
|
|
3632
4030
|
var WALKER_COUNT = 10;
|
|
3633
4031
|
var ARRIVAL_DISTANCE = 0.05;
|
|
3634
4032
|
var SWAY_AMPLITUDE = 0.04;
|
|
@@ -3694,7 +4092,8 @@ var GameFluidsThree = (() => {
|
|
|
3694
4092
|
blocks: () => createBlocksBehavior(),
|
|
3695
4093
|
plate: () => createPlateBehavior(),
|
|
3696
4094
|
cylinder: () => createCylinderBehavior(),
|
|
3697
|
-
car: () => createCarBehavior()
|
|
4095
|
+
car: () => createCarBehavior(),
|
|
4096
|
+
rain: () => createRainBehavior()
|
|
3698
4097
|
};
|
|
3699
4098
|
var NOOP = () => {
|
|
3700
4099
|
};
|
|
@@ -3765,6 +4164,8 @@ var GameFluidsThree = (() => {
|
|
|
3765
4164
|
return Math.abs(asNumber(first));
|
|
3766
4165
|
case "sqrt":
|
|
3767
4166
|
return Math.sqrt(asNumber(first));
|
|
4167
|
+
case "exp":
|
|
4168
|
+
return Math.exp(asNumber(first));
|
|
3768
4169
|
case "sin":
|
|
3769
4170
|
return Math.sin(asNumber(first));
|
|
3770
4171
|
case "cos":
|
|
@@ -3883,7 +4284,7 @@ var GameFluidsThree = (() => {
|
|
|
3883
4284
|
return evaluateCall(value.$, args.map((entry) => resolve(entry, context)));
|
|
3884
4285
|
}
|
|
3885
4286
|
}
|
|
3886
|
-
var
|
|
4287
|
+
var UP12 = [0, 1, 0];
|
|
3887
4288
|
var ZERO = [0, 0, 0];
|
|
3888
4289
|
var FULL_TURN_DRAWN = 6.283;
|
|
3889
4290
|
function scaledSizes(range2, factor) {
|
|
@@ -3896,7 +4297,7 @@ var GameFluidsThree = (() => {
|
|
|
3896
4297
|
p: centre,
|
|
3897
4298
|
r: radius,
|
|
3898
4299
|
flat: true,
|
|
3899
|
-
dir: options.dir ??
|
|
4300
|
+
dir: options.dir ?? UP12,
|
|
3900
4301
|
cone: 0.35,
|
|
3901
4302
|
sp: [0.4, 1.4],
|
|
3902
4303
|
v: wind,
|
|
@@ -3913,7 +4314,7 @@ var GameFluidsThree = (() => {
|
|
|
3913
4314
|
p: centre,
|
|
3914
4315
|
r: radius * 0.6,
|
|
3915
4316
|
flat: true,
|
|
3916
|
-
dir:
|
|
4317
|
+
dir: UP12,
|
|
3917
4318
|
cone: 0.3,
|
|
3918
4319
|
sp: [0.3, 0.8],
|
|
3919
4320
|
life: [0.2, 0.4],
|
|
@@ -3928,14 +4329,14 @@ var GameFluidsThree = (() => {
|
|
|
3928
4329
|
if (engine.quality < 2) {
|
|
3929
4330
|
engine.emit(`${key}e`, "streak", 10 * factor, dt, () => {
|
|
3930
4331
|
const jitter = plus(wind, engine.random.between(-0.4, 0.4), 0, engine.random.between(-0.4, 0.4));
|
|
3931
|
-
return { p: centre, box: [radius, 0, radius], dir:
|
|
4332
|
+
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 };
|
|
3932
4333
|
});
|
|
3933
4334
|
}
|
|
3934
4335
|
if (options.noSmoke) return;
|
|
3935
4336
|
engine.emit(`${key}s`, "normal", (options.smoke || 14) * factor, dt, () => ({
|
|
3936
4337
|
p: plus(centre, 0, 0.8 * sqrtFactor, 0),
|
|
3937
4338
|
r: radius * 0.7,
|
|
3938
|
-
dir:
|
|
4339
|
+
dir: UP12,
|
|
3939
4340
|
cone: 0.35,
|
|
3940
4341
|
sp: [0.6, 1.4],
|
|
3941
4342
|
v: wind,
|
|
@@ -3975,15 +4376,15 @@ var GameFluidsThree = (() => {
|
|
|
3975
4376
|
engine.screen.shake += 0.7 * scale2;
|
|
3976
4377
|
engine.screen.white += 0.18 * scale2;
|
|
3977
4378
|
engine.burst("add", 55 * scale2, { p: point, r: 0.3 * scale2, sp: [2, 7 * scale2], drag: 4, life: [0.25, 0.6], size: [0.7 * scale2, 1.4 * scale2], grow: 1.7, c0: 16773296, c1: 10103304, fi: 0.04 });
|
|
3978
|
-
engine.burst("add", 28 * scale2, { p: plus(point, 0, 0.3, 0), r: 0.3, dir:
|
|
4379
|
+
engine.burst("add", 28 * scale2, { p: plus(point, 0, 0.3, 0), r: 0.3, dir: UP12, cone: 0.7, sp: [2, 5 * scale2], drag: 1.5, life: [0.6, 1.1], size: [0.6 * scale2, 1 * scale2], grow: 1.3, c0: 16760928, c1: 5902853, g: -2, fi: 0.05 });
|
|
3979
4380
|
engine.ring([plus(point, 0, 0.05, 0), 0.3, 7 * scale2, 0.55, 16767136]);
|
|
3980
4381
|
const toCamera = normalized([cameraPosition[0] - point[0], cameraPosition[1] - point[1], cameraPosition[2] - point[2]]);
|
|
3981
4382
|
engine.ring([plus(point, 0, 1, 0), 0.3, 5 * scale2, 0.35, 16773328, toCamera]);
|
|
3982
|
-
engine.burst("normal", 32 * scale2, { p: plus(point, 0, 0.6, 0), r: 0.8 * scale2, dir:
|
|
4383
|
+
engine.burst("normal", 32 * scale2, { p: plus(point, 0, 0.6, 0), r: 0.8 * scale2, dir: UP12, cone: 1.1, sp: [1, 3], drag: 1.2, life: [3, 6], size: [1 * scale2, 1.8 * scale2], grow: 2.6, c0: 2828068, c1: 987155, a: 0.6, fi: 0.18, g: -0.35 });
|
|
3983
4384
|
ringOfDust(engine, point, scale2);
|
|
3984
|
-
if (engine.quality < 2) engine.burst("streak", 44 * scale2, { p: point, dir:
|
|
4385
|
+
if (engine.quality < 2) engine.burst("streak", 44 * scale2, { 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 });
|
|
3985
4386
|
for (let index = 0; index < engine.scaled(16 * scale2); index++) {
|
|
3986
|
-
engine.debrisPiece({ p: point, dir:
|
|
4387
|
+
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 });
|
|
3987
4388
|
}
|
|
3988
4389
|
engine.decal([point[0], engine.context.groundAt(point[0], point[2]), point[2], 3 * scale2, 657930, { grow: 0.15, life: 60 }]);
|
|
3989
4390
|
}
|
|
@@ -4126,6 +4527,7 @@ var GameFluidsThree = (() => {
|
|
|
4126
4527
|
if (!def) return;
|
|
4127
4528
|
this.schedule.clear();
|
|
4128
4529
|
this.variables.clear();
|
|
4530
|
+
for (const [name, value] of Object.entries(this.setup.values ?? {})) this.variables.set(name, value);
|
|
4129
4531
|
for (const behavior2 of this.deps.behaviors()) behavior2.reset(this.host);
|
|
4130
4532
|
this.time = 0;
|
|
4131
4533
|
this.within(() => {
|
|
@@ -4184,6 +4586,10 @@ var GameFluidsThree = (() => {
|
|
|
4184
4586
|
return engine.spawn(step.system, this.value(step.spawn));
|
|
4185
4587
|
case "emit":
|
|
4186
4588
|
return engine.emit(step.key, step.system, this.value(step.rate), this.dt, () => this.value(step.spawn));
|
|
4589
|
+
case "mesh": {
|
|
4590
|
+
engine.mesh(this.value(step.spawn));
|
|
4591
|
+
return;
|
|
4592
|
+
}
|
|
4187
4593
|
case "debris":
|
|
4188
4594
|
return engine.debrisPiece(this.value(step.spawn));
|
|
4189
4595
|
case "decal":
|
|
@@ -4265,7 +4671,7 @@ var GameFluidsThree = (() => {
|
|
|
4265
4671
|
this.index = previous;
|
|
4266
4672
|
}
|
|
4267
4673
|
};
|
|
4268
|
-
var
|
|
4674
|
+
var ORIGIN5 = [0, 0, 0];
|
|
4269
4675
|
var DEFAULT_HEADING = [0, 0, -1];
|
|
4270
4676
|
var DEFAULT_MAX_INSTANCES = 48;
|
|
4271
4677
|
var ENDLESS_SECONDS = 60;
|
|
@@ -4310,7 +4716,7 @@ var GameFluidsThree = (() => {
|
|
|
4310
4716
|
}
|
|
4311
4717
|
function placementOf(entry) {
|
|
4312
4718
|
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;
|
|
4313
|
-
return { origin, anchor: entry.anchor, yaw: entry.yaw };
|
|
4719
|
+
return { origin, anchor: entry.anchor, yaw: entry.yaw, ...entry.orientation ? { orientation: entry.orientation } : {} };
|
|
4314
4720
|
}
|
|
4315
4721
|
function drawing(entry, action) {
|
|
4316
4722
|
const context = engine.context;
|
|
@@ -4334,8 +4740,9 @@ var GameFluidsThree = (() => {
|
|
|
4334
4740
|
random: playOptions.seed !== void 0 ? streamOf(playOptions.seed) : void 0,
|
|
4335
4741
|
follow: playOptions.follow,
|
|
4336
4742
|
origin: point,
|
|
4337
|
-
anchor: def.anchor ??
|
|
4743
|
+
anchor: def.anchor ?? ORIGIN5,
|
|
4338
4744
|
yaw: yawOf(heading, playOptions.direction),
|
|
4745
|
+
orientation: playOptions.orientation,
|
|
4339
4746
|
seconds: playOptions.seconds ?? (def.loop && def.loop > 0 ? def.loop : ENDLESS_SECONDS)
|
|
4340
4747
|
};
|
|
4341
4748
|
playing.push(entry);
|
|
@@ -4344,7 +4751,8 @@ var GameFluidsThree = (() => {
|
|
|
4344
4751
|
() => instance.begin(def, paramIndex(def, playOptions.param), {
|
|
4345
4752
|
placement: placementOf(entry),
|
|
4346
4753
|
...playOptions.direction ? { direction: playOptions.direction } : {},
|
|
4347
|
-
...playOptions.normal ? { normal: playOptions.normal } : {}
|
|
4754
|
+
...playOptions.normal ? { normal: playOptions.normal } : {},
|
|
4755
|
+
...playOptions.values ? { values: playOptions.values } : {}
|
|
4348
4756
|
})
|
|
4349
4757
|
);
|
|
4350
4758
|
return entry.handle;
|
|
@@ -4604,15 +5012,15 @@ var GameFluidsThree = (() => {
|
|
|
4604
5012
|
return shock;
|
|
4605
5013
|
}
|
|
4606
5014
|
function pushPuffs(puffs, shock, reach, dt, age) {
|
|
4607
|
-
for (const
|
|
4608
|
-
if (
|
|
4609
|
-
const dx =
|
|
4610
|
-
const dz =
|
|
5015
|
+
for (const puff3 of puffs) {
|
|
5016
|
+
if (puff3.ring || puff3.t > PUSH_AGE_LIMIT) continue;
|
|
5017
|
+
const dx = puff3.x - shock.x;
|
|
5018
|
+
const dz = puff3.z - shock.z;
|
|
4611
5019
|
const distance2 = Math.hypot(dx, dz) + 1e-3;
|
|
4612
|
-
if (Math.abs(distance2 - reach) < PUSH_BAND &&
|
|
5020
|
+
if (Math.abs(distance2 - reach) < PUSH_BAND && puff3.y < PUSH_CEILING) {
|
|
4613
5021
|
const strength = 4 * dt * (1 - age);
|
|
4614
|
-
|
|
4615
|
-
|
|
5022
|
+
puff3.vx += dx / distance2 * strength * 6;
|
|
5023
|
+
puff3.vz += dz / distance2 * strength * 6;
|
|
4616
5024
|
}
|
|
4617
5025
|
}
|
|
4618
5026
|
}
|
|
@@ -4912,10 +5320,10 @@ var GameFluidsThree = (() => {
|
|
|
4912
5320
|
const life = random.between(ring2.life * 0.75, ring2.life);
|
|
4913
5321
|
const h0 = random.between(1, 1.25);
|
|
4914
5322
|
const hl = random.between(0.9, 1.6);
|
|
4915
|
-
const
|
|
4916
|
-
|
|
4917
|
-
|
|
4918
|
-
|
|
5323
|
+
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 });
|
|
5324
|
+
puff3.ring = ring2;
|
|
5325
|
+
puff3.ph = random.next() * Math.PI * 2;
|
|
5326
|
+
puff3.th = random.next() * Math.PI * 2;
|
|
4919
5327
|
}
|
|
4920
5328
|
const stemCount = Math.round((spec.stem || 18) * Math.max(lod, 0.4));
|
|
4921
5329
|
for (let index = 0; index < stemCount; index++) {
|
|
@@ -5716,7 +6124,7 @@ var GameFluidsThree = (() => {
|
|
|
5716
6124
|
};
|
|
5717
6125
|
var TWO_PI_ROUNDED = 6.2832;
|
|
5718
6126
|
var WIDE_CONE = 3.1;
|
|
5719
|
-
var
|
|
6127
|
+
var UP13 = [0, 1, 0];
|
|
5720
6128
|
function drawRange(random, range2) {
|
|
5721
6129
|
if (Array.isArray(range2)) return random.between(range2[0], range2[1]);
|
|
5722
6130
|
return range2 || 0;
|
|
@@ -5744,7 +6152,7 @@ var GameFluidsThree = (() => {
|
|
|
5744
6152
|
}
|
|
5745
6153
|
function coneDirection(random, direction, cone, out) {
|
|
5746
6154
|
if (cone >= WIDE_CONE) return randomUnit(random, out);
|
|
5747
|
-
const [dx, dy, dz] = direction ??
|
|
6155
|
+
const [dx, dy, dz] = direction ?? UP13;
|
|
5748
6156
|
const cosTilt = 1 - random.next() * (1 - Math.cos(cone));
|
|
5749
6157
|
const sinTilt = Math.sqrt(1 - cosTilt * cosTilt);
|
|
5750
6158
|
const phase = random.next() * TWO_PI_ROUNDED;
|
|
@@ -5864,12 +6272,12 @@ var GameFluidsThree = (() => {
|
|
|
5864
6272
|
}
|
|
5865
6273
|
};
|
|
5866
6274
|
var CAPACITY2 = 400;
|
|
5867
|
-
var
|
|
6275
|
+
var UP14 = [0, 1, 0];
|
|
5868
6276
|
var DEFAULT_LIFE2 = 60;
|
|
5869
6277
|
var DEFAULT_GROW = 1.2;
|
|
5870
6278
|
var EVAPORATION = { fuel: [6, 5], water: [40, 20] };
|
|
5871
6279
|
function createDecal() {
|
|
5872
|
-
return { on: false, x: 0, y: 0, z: 0, sx: 0, sy: 0, t: 0, life: 0, grow: 0, color: 0, normal:
|
|
6280
|
+
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 };
|
|
5873
6281
|
}
|
|
5874
6282
|
var DecalPool = class {
|
|
5875
6283
|
constructor(context) {
|
|
@@ -5882,7 +6290,7 @@ var GameFluidsThree = (() => {
|
|
|
5882
6290
|
const random = this.context.random;
|
|
5883
6291
|
const index = this.next++ % CAPACITY2;
|
|
5884
6292
|
const decal2 = this.decals[index];
|
|
5885
|
-
const normal = options.n ??
|
|
6293
|
+
const normal = options.n ?? UP14;
|
|
5886
6294
|
random.between(0, 6.28);
|
|
5887
6295
|
const offset = 4e-3 + index % 40 * 4e-4;
|
|
5888
6296
|
decal2.on = true;
|
|
@@ -5923,6 +6331,94 @@ var GameFluidsThree = (() => {
|
|
|
5923
6331
|
}
|
|
5924
6332
|
}
|
|
5925
6333
|
};
|
|
6334
|
+
var CAPACITY3 = 400;
|
|
6335
|
+
var IDENTITY = [0, 0, 0, 1];
|
|
6336
|
+
function multiply(a, b) {
|
|
6337
|
+
const [ax, ay, az, aw] = a;
|
|
6338
|
+
const [bx, by, bz, bw] = b;
|
|
6339
|
+
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];
|
|
6340
|
+
}
|
|
6341
|
+
var aboutX = (angle) => [Math.sin(angle / 2), 0, 0, Math.cos(angle / 2)];
|
|
6342
|
+
var MeshPool = class {
|
|
6343
|
+
constructor(capacity = CAPACITY3) {
|
|
6344
|
+
__publicField2(this, "capacity", capacity);
|
|
6345
|
+
__publicField2(this, "particles", []);
|
|
6346
|
+
__publicField2(this, "serial", 0);
|
|
6347
|
+
}
|
|
6348
|
+
get count() {
|
|
6349
|
+
return this.particles.length;
|
|
6350
|
+
}
|
|
6351
|
+
spawn(options, frame = IDENTITY) {
|
|
6352
|
+
const velocity = options.v ?? [0, 0, 0];
|
|
6353
|
+
const world = options.wv ?? [0, 0, 0];
|
|
6354
|
+
const particle = {
|
|
6355
|
+
id: ++this.serial,
|
|
6356
|
+
shape: options.shape,
|
|
6357
|
+
radius: options.r,
|
|
6358
|
+
height: options.h ?? 0,
|
|
6359
|
+
segments: options.seg ?? 0,
|
|
6360
|
+
segments2: options.seg2 ?? 0,
|
|
6361
|
+
color: options.c0,
|
|
6362
|
+
additive: options.add === true,
|
|
6363
|
+
lit: options.lit === true,
|
|
6364
|
+
x: options.p[0],
|
|
6365
|
+
y: options.p[1],
|
|
6366
|
+
z: options.p[2],
|
|
6367
|
+
frame: options.roll ? multiply(frame, aboutX(options.roll)) : frame,
|
|
6368
|
+
at: options.at ?? [0, 0, 0],
|
|
6369
|
+
rx: options.rot?.[0] ?? 0,
|
|
6370
|
+
ry: options.rot?.[1] ?? 0,
|
|
6371
|
+
rz: options.rot?.[2] ?? 0,
|
|
6372
|
+
scale: 1,
|
|
6373
|
+
opacity: options.a,
|
|
6374
|
+
age: 0,
|
|
6375
|
+
life: options.life,
|
|
6376
|
+
vx: velocity[0] + world[0],
|
|
6377
|
+
vy: velocity[1] + world[1],
|
|
6378
|
+
vz: velocity[2] + world[2],
|
|
6379
|
+
spin: options.spin ?? [0, 0, 0],
|
|
6380
|
+
gravity: options.g ?? 0,
|
|
6381
|
+
drag: options.drag ?? 0,
|
|
6382
|
+
grow: options.grow ?? 0,
|
|
6383
|
+
ramp: options.ramp,
|
|
6384
|
+
fade: options.fade === true,
|
|
6385
|
+
startOpacity: options.a
|
|
6386
|
+
};
|
|
6387
|
+
this.particles.push(particle);
|
|
6388
|
+
if (this.particles.length > this.capacity) this.particles.shift();
|
|
6389
|
+
return particle;
|
|
6390
|
+
}
|
|
6391
|
+
update(dt) {
|
|
6392
|
+
const live = this.particles;
|
|
6393
|
+
for (let index = 0; index < live.length; index++) {
|
|
6394
|
+
const particle = live[index];
|
|
6395
|
+
particle.age += dt;
|
|
6396
|
+
if (particle.ramp ? particle.age >= particle.life : particle.age > particle.life) {
|
|
6397
|
+
live.splice(index--, 1);
|
|
6398
|
+
continue;
|
|
6399
|
+
}
|
|
6400
|
+
if (particle.fade) particle.opacity = Math.max(0, particle.startOpacity * (1 - particle.age / particle.life));
|
|
6401
|
+
particle.vy -= particle.gravity * dt;
|
|
6402
|
+
if (particle.drag) {
|
|
6403
|
+
const keep = Math.max(0, 1 - particle.drag * dt);
|
|
6404
|
+
particle.vx *= keep;
|
|
6405
|
+
particle.vy *= keep;
|
|
6406
|
+
particle.vz *= keep;
|
|
6407
|
+
}
|
|
6408
|
+
particle.x += particle.vx * dt;
|
|
6409
|
+
particle.y += particle.vy * dt;
|
|
6410
|
+
particle.z += particle.vz * dt;
|
|
6411
|
+
particle.rx += particle.spin[0] * dt;
|
|
6412
|
+
particle.ry += particle.spin[1] * dt;
|
|
6413
|
+
particle.rz += particle.spin[2] * dt;
|
|
6414
|
+
if (particle.grow) particle.scale *= 1 + particle.grow * dt;
|
|
6415
|
+
if (particle.ramp) particle.scale = particle.ramp[0] + Math.min(1, particle.age / particle.life) * particle.ramp[1];
|
|
6416
|
+
}
|
|
6417
|
+
}
|
|
6418
|
+
clear() {
|
|
6419
|
+
this.particles.length = 0;
|
|
6420
|
+
}
|
|
6421
|
+
};
|
|
5926
6422
|
var DEFAULT_FADE_IN = 0.1;
|
|
5927
6423
|
var FLOATS_PER_VECTOR = 3;
|
|
5928
6424
|
var BYTE_MAX2 = 255;
|
|
@@ -6212,11 +6708,11 @@ var GameFluidsThree = (() => {
|
|
|
6212
6708
|
};
|
|
6213
6709
|
var RING_CAPACITY = 120;
|
|
6214
6710
|
var LIGHT_CAPACITY = 4;
|
|
6215
|
-
var
|
|
6711
|
+
var UP15 = [0, 1, 0];
|
|
6216
6712
|
var DEFAULT_LIGHT_DISTANCE = 14;
|
|
6217
6713
|
var WaveRingPool = class {
|
|
6218
6714
|
constructor() {
|
|
6219
|
-
__publicField2(this, "rings", Array.from({ length: RING_CAPACITY }, () => ({ on: false, point:
|
|
6715
|
+
__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 })));
|
|
6220
6716
|
__publicField2(this, "count", 0);
|
|
6221
6717
|
__publicField2(this, "next", 0);
|
|
6222
6718
|
}
|
|
@@ -6229,7 +6725,7 @@ var GameFluidsThree = (() => {
|
|
|
6229
6725
|
ring2.t = 0;
|
|
6230
6726
|
ring2.duration = duration;
|
|
6231
6727
|
ring2.color = color;
|
|
6232
|
-
ring2.normal = normal ??
|
|
6728
|
+
ring2.normal = normal ?? UP15;
|
|
6233
6729
|
ring2.hold = hold || 0;
|
|
6234
6730
|
}
|
|
6235
6731
|
clear() {
|
|
@@ -6249,7 +6745,7 @@ var GameFluidsThree = (() => {
|
|
|
6249
6745
|
var FlashLightPool = class {
|
|
6250
6746
|
constructor(context) {
|
|
6251
6747
|
__publicField2(this, "context", context);
|
|
6252
|
-
__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 })));
|
|
6748
|
+
__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 })));
|
|
6253
6749
|
__publicField2(this, "fire", [
|
|
6254
6750
|
{ x: 0, y: 0, z: 0, intensity: 0 },
|
|
6255
6751
|
{ x: 0, y: 0, z: 0, intensity: 0 }
|
|
@@ -6259,7 +6755,7 @@ var GameFluidsThree = (() => {
|
|
|
6259
6755
|
get lit() {
|
|
6260
6756
|
return this.lights.filter((light) => light.intensity > 0).length;
|
|
6261
6757
|
}
|
|
6262
|
-
flash(point, color, intensity, duration, distance2, force) {
|
|
6758
|
+
flash(point, color, intensity, duration, distance2, force, steady) {
|
|
6263
6759
|
const { level } = this.context.quality;
|
|
6264
6760
|
if (level >= 1 && !force) return;
|
|
6265
6761
|
if (level >= 2 && force !== "boom") return;
|
|
@@ -6272,6 +6768,7 @@ var GameFluidsThree = (() => {
|
|
|
6272
6768
|
light.peak = intensity;
|
|
6273
6769
|
light.duration = duration;
|
|
6274
6770
|
light.t = 0;
|
|
6771
|
+
light.steady = steady === true;
|
|
6275
6772
|
light.intensity = intensity;
|
|
6276
6773
|
}
|
|
6277
6774
|
clear() {
|
|
@@ -6283,7 +6780,7 @@ var GameFluidsThree = (() => {
|
|
|
6283
6780
|
if (light.intensity <= 0) continue;
|
|
6284
6781
|
light.t += dt;
|
|
6285
6782
|
const age = light.t / light.duration;
|
|
6286
|
-
light.intensity = age >= 1 ? 0 : light.peak * (1 - age) * (1 - age);
|
|
6783
|
+
light.intensity = age >= 1 ? 0 : light.steady ? light.peak : light.peak * (1 - age) * (1 - age);
|
|
6287
6784
|
}
|
|
6288
6785
|
}
|
|
6289
6786
|
};
|
|
@@ -6291,6 +6788,14 @@ var GameFluidsThree = (() => {
|
|
|
6291
6788
|
var FIRE_FLICKER_SWAY = 0.25;
|
|
6292
6789
|
var FIRE_FLICKER_JITTER = 0.08;
|
|
6293
6790
|
var LENS_FADE = 0.16;
|
|
6791
|
+
function rotate(q, v) {
|
|
6792
|
+
const [qx, qy, qz, qw] = q;
|
|
6793
|
+
const ix = qw * v[0] + qy * v[2] - qz * v[1];
|
|
6794
|
+
const iy = qw * v[1] + qz * v[0] - qx * v[2];
|
|
6795
|
+
const iz = qw * v[2] + qx * v[1] - qy * v[0];
|
|
6796
|
+
const iw = -qx * v[0] - qy * v[1] - qz * v[2];
|
|
6797
|
+
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];
|
|
6798
|
+
}
|
|
6294
6799
|
function workshopGround(x, z) {
|
|
6295
6800
|
return z < -2.9 && z > -4.5 && Math.abs(x) < 13 ? 0.12 : 0;
|
|
6296
6801
|
}
|
|
@@ -6304,6 +6809,8 @@ var GameFluidsThree = (() => {
|
|
|
6304
6809
|
__publicField2(this, "decals");
|
|
6305
6810
|
__publicField2(this, "rings", new WaveRingPool());
|
|
6306
6811
|
__publicField2(this, "lights");
|
|
6812
|
+
__publicField2(this, "rain", new RainField(this));
|
|
6813
|
+
__publicField2(this, "meshes", new MeshPool());
|
|
6307
6814
|
__publicField2(this, "screen", createScreenState());
|
|
6308
6815
|
__publicField2(this, "lens", []);
|
|
6309
6816
|
__publicField2(this, "post", {});
|
|
@@ -6336,7 +6843,11 @@ var GameFluidsThree = (() => {
|
|
|
6336
6843
|
place(point) {
|
|
6337
6844
|
const placement = this.placement;
|
|
6338
6845
|
if (!placement) return point;
|
|
6339
|
-
const { anchor, origin, yaw } = placement;
|
|
6846
|
+
const { anchor, origin, yaw, orientation } = placement;
|
|
6847
|
+
if (orientation) {
|
|
6848
|
+
const turned = rotate(orientation, [point[0] - anchor[0], point[1] - anchor[1], point[2] - anchor[2]]);
|
|
6849
|
+
return [origin[0] + turned[0], origin[1] + turned[1], origin[2] + turned[2]];
|
|
6850
|
+
}
|
|
6340
6851
|
const x = point[0] - anchor[0];
|
|
6341
6852
|
const z = point[2] - anchor[2];
|
|
6342
6853
|
const cos2 = Math.cos(yaw);
|
|
@@ -6347,6 +6858,7 @@ var GameFluidsThree = (() => {
|
|
|
6347
6858
|
turn(vector) {
|
|
6348
6859
|
const placement = this.placement;
|
|
6349
6860
|
if (!placement) return vector;
|
|
6861
|
+
if (placement.orientation) return rotate(placement.orientation, vector);
|
|
6350
6862
|
const cos2 = Math.cos(placement.yaw);
|
|
6351
6863
|
const sin2 = Math.sin(placement.yaw);
|
|
6352
6864
|
return [cos2 * vector[0] + sin2 * vector[2], vector[1], -sin2 * vector[0] + cos2 * vector[2]];
|
|
@@ -6375,6 +6887,14 @@ var GameFluidsThree = (() => {
|
|
|
6375
6887
|
}
|
|
6376
6888
|
this.accumulators.set(key, carried);
|
|
6377
6889
|
}
|
|
6890
|
+
/** 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. */
|
|
6891
|
+
mesh(recipe) {
|
|
6892
|
+
const placement = this.placement;
|
|
6893
|
+
const options = placement ? { ...recipe, p: this.place(recipe.p), ...recipe.v ? { v: this.turn(recipe.v) } : {} } : recipe;
|
|
6894
|
+
this.context.trace?.("mesh", [options]);
|
|
6895
|
+
const grouped = recipe.at !== void 0 || recipe.roll !== void 0;
|
|
6896
|
+
return this.meshes.spawn(options, placement && grouped ? placement.orientation ?? [0, Math.sin(placement.yaw / 2), 0, Math.cos(placement.yaw / 2)] : void 0);
|
|
6897
|
+
}
|
|
6378
6898
|
debrisPiece(recipe) {
|
|
6379
6899
|
const options = this.placed(recipe);
|
|
6380
6900
|
this.context.trace?.("debris", [options]);
|
|
@@ -6395,10 +6915,11 @@ var GameFluidsThree = (() => {
|
|
|
6395
6915
|
this.context.trace?.("ring", args);
|
|
6396
6916
|
this.rings.add(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
|
|
6397
6917
|
}
|
|
6918
|
+
/** `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. */
|
|
6398
6919
|
flash(recipe) {
|
|
6399
|
-
const args = this.placement ? [this.place(recipe[0]), recipe[1], recipe[2], recipe[3], recipe[4], recipe[5]] : recipe;
|
|
6400
|
-
this.context.trace?.("flash", args);
|
|
6401
|
-
this.lights.flash(args[0], args[1], args[2], args[3], args[4], args[5]);
|
|
6920
|
+
const args = this.placement ? [this.place(recipe[0]), recipe[1], recipe[2], recipe[3], recipe[4], recipe[5], recipe[6]] : recipe;
|
|
6921
|
+
this.context.trace?.("flash", args.slice(0, 6));
|
|
6922
|
+
this.lights.flash(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
|
|
6402
6923
|
}
|
|
6403
6924
|
/** `fireLight` (W400): sways with the clock and flickers with one draw. */
|
|
6404
6925
|
fireLight(slot, recipe, intensity, time) {
|
|
@@ -6423,6 +6944,7 @@ var GameFluidsThree = (() => {
|
|
|
6423
6944
|
this.debris.update(dt);
|
|
6424
6945
|
this.decals.update(dt);
|
|
6425
6946
|
this.rings.update(dt);
|
|
6947
|
+
this.meshes.update(dt);
|
|
6426
6948
|
this.lights.update(dt);
|
|
6427
6949
|
updateScreen(this.screen, dt);
|
|
6428
6950
|
for (let index = this.lens.length - 1; index >= 0; index--) {
|
|
@@ -6439,7 +6961,9 @@ var GameFluidsThree = (() => {
|
|
|
6439
6961
|
this.debris.clear();
|
|
6440
6962
|
this.decals.clear();
|
|
6441
6963
|
this.rings.clear();
|
|
6964
|
+
this.meshes.clear();
|
|
6442
6965
|
this.lights.clear();
|
|
6966
|
+
this.rain.clear();
|
|
6443
6967
|
this.accumulators.clear();
|
|
6444
6968
|
resetScreenState(this.screen);
|
|
6445
6969
|
this.lens.length = 0;
|
|
@@ -6585,16 +7109,16 @@ var GameFluidsThree = (() => {
|
|
|
6585
7109
|
},
|
|
6586
7110
|
push(point, radius, speed) {
|
|
6587
7111
|
spriteSystem.push(point, radius, speed);
|
|
6588
|
-
for (const
|
|
6589
|
-
const dx =
|
|
6590
|
-
const dy =
|
|
6591
|
-
const dz =
|
|
7112
|
+
for (const puff3 of core.puffs.items) {
|
|
7113
|
+
const dx = puff3.x - point[0];
|
|
7114
|
+
const dy = puff3.y - point[1];
|
|
7115
|
+
const dz = puff3.z - point[2];
|
|
6592
7116
|
const distance2 = Math.sqrt(dx * dx + dy * dy + dz * dz);
|
|
6593
7117
|
if (distance2 >= radius) continue;
|
|
6594
7118
|
const strength = speed * (1 - distance2 / radius) / (distance2 + 1e-3);
|
|
6595
|
-
|
|
6596
|
-
|
|
6597
|
-
|
|
7119
|
+
puff3.vx += dx * strength;
|
|
7120
|
+
puff3.vy += dy * strength;
|
|
7121
|
+
puff3.vz += dz * strength;
|
|
6598
7122
|
}
|
|
6599
7123
|
},
|
|
6600
7124
|
stop(handle) {
|
|
@@ -6611,6 +7135,12 @@ var GameFluidsThree = (() => {
|
|
|
6611
7135
|
camera2.y = position[1];
|
|
6612
7136
|
camera2.z = position[2];
|
|
6613
7137
|
},
|
|
7138
|
+
setWind(next) {
|
|
7139
|
+
wind.x = next[0];
|
|
7140
|
+
wind.y = next[1];
|
|
7141
|
+
wind.z = next[2];
|
|
7142
|
+
},
|
|
7143
|
+
wind: () => [wind.x, wind.y, wind.z],
|
|
6614
7144
|
forceLod(scale2) {
|
|
6615
7145
|
core.clock.forcedLod = scale2;
|
|
6616
7146
|
},
|
|
@@ -6792,11 +7322,11 @@ void main(){
|
|
|
6792
7322
|
geometry.setAttribute("aC", attributes[2]);
|
|
6793
7323
|
geometry.instanceCount = 0;
|
|
6794
7324
|
const material = new THREE.ShaderMaterial({ uniforms, vertexShader: PUFF_VERTEX, fragmentShader: PUFF_FRAGMENT });
|
|
6795
|
-
const
|
|
6796
|
-
|
|
6797
|
-
|
|
7325
|
+
const mesh2 = new THREE.Mesh(geometry, material);
|
|
7326
|
+
mesh2.name = "vfx-puffs";
|
|
7327
|
+
mesh2.frustumCulled = false;
|
|
6798
7328
|
return {
|
|
6799
|
-
mesh,
|
|
7329
|
+
mesh: mesh2,
|
|
6800
7330
|
sync() {
|
|
6801
7331
|
let n = 0;
|
|
6802
7332
|
for (const p of pool.items) {
|
|
@@ -6837,12 +7367,12 @@ void main(){
|
|
|
6837
7367
|
geometry.setAttribute("aE", attributes[2]);
|
|
6838
7368
|
geometry.instanceCount = 0;
|
|
6839
7369
|
const material = new THREE.ShaderMaterial({ transparent: true, depthWrite: false, blending: THREE.AdditiveBlending, vertexShader: SPARK_VERTEX, fragmentShader: SPARK_FRAGMENT });
|
|
6840
|
-
const
|
|
6841
|
-
|
|
6842
|
-
|
|
6843
|
-
|
|
7370
|
+
const mesh2 = new THREE.Mesh(geometry, material);
|
|
7371
|
+
mesh2.name = "vfx-sparks";
|
|
7372
|
+
mesh2.frustumCulled = false;
|
|
7373
|
+
mesh2.renderOrder = 5;
|
|
6844
7374
|
return {
|
|
6845
|
-
mesh,
|
|
7375
|
+
mesh: mesh2,
|
|
6846
7376
|
sync() {
|
|
6847
7377
|
let n = 0;
|
|
6848
7378
|
for (const s of pool.items) {
|
|
@@ -6880,12 +7410,12 @@ void main(){
|
|
|
6880
7410
|
geometry.setAttribute("aC", attributes[1]);
|
|
6881
7411
|
geometry.instanceCount = 0;
|
|
6882
7412
|
const material = new THREE.ShaderMaterial({ transparent: true, depthWrite: false, blending: THREE.AdditiveBlending, vertexShader: GLOW_VERTEX, fragmentShader: GLOW_FRAGMENT });
|
|
6883
|
-
const
|
|
6884
|
-
|
|
6885
|
-
|
|
6886
|
-
|
|
7413
|
+
const mesh2 = new THREE.Mesh(geometry, material);
|
|
7414
|
+
mesh2.name = "vfx-glows";
|
|
7415
|
+
mesh2.frustumCulled = false;
|
|
7416
|
+
mesh2.renderOrder = 6;
|
|
6887
7417
|
return {
|
|
6888
|
-
mesh,
|
|
7418
|
+
mesh: mesh2,
|
|
6889
7419
|
sync() {
|
|
6890
7420
|
let n = 0;
|
|
6891
7421
|
for (const g of pool.items) {
|
|
@@ -6914,14 +7444,14 @@ void main(){
|
|
|
6914
7444
|
const rockMaterial = new THREE.MeshStandardMaterial({ color: 16777215, roughness: 0.85, flatShading: true });
|
|
6915
7445
|
const plateMaterial = rockMaterial.clone();
|
|
6916
7446
|
const make = (geometry, material) => {
|
|
6917
|
-
const
|
|
6918
|
-
|
|
6919
|
-
|
|
6920
|
-
|
|
6921
|
-
|
|
6922
|
-
|
|
6923
|
-
|
|
6924
|
-
return
|
|
7447
|
+
const mesh2 = new THREE.InstancedMesh(geometry, material, capacity);
|
|
7448
|
+
mesh2.instanceMatrix.setUsage(THREE.DynamicDrawUsage);
|
|
7449
|
+
mesh2.castShadow = true;
|
|
7450
|
+
mesh2.receiveShadow = true;
|
|
7451
|
+
mesh2.frustumCulled = false;
|
|
7452
|
+
mesh2.count = 0;
|
|
7453
|
+
mesh2.setColorAt(0, new THREE.Color(1, 1, 1));
|
|
7454
|
+
return mesh2;
|
|
6925
7455
|
};
|
|
6926
7456
|
const rocks = make(shapes.rock, rockMaterial);
|
|
6927
7457
|
const plates = make(shapes.plate, plateMaterial);
|
|
@@ -6940,20 +7470,20 @@ void main(){
|
|
|
6940
7470
|
euler.set(chunk.rx, chunk.ry, chunk.rz);
|
|
6941
7471
|
quaternion.setFromEuler(euler);
|
|
6942
7472
|
matrix.compose(position.set(chunk.x, chunk.y, chunk.z), quaternion, scale2.set(chunk.sx, chunk.sy, chunk.sz));
|
|
6943
|
-
const
|
|
7473
|
+
const mesh2 = chunk.plate ? plates : rocks;
|
|
6944
7474
|
const index = chunk.plate ? plateCount++ : rockCount++;
|
|
6945
|
-
|
|
7475
|
+
mesh2.setMatrixAt(index, matrix);
|
|
6946
7476
|
const color = colorOf(chunk);
|
|
6947
|
-
const colors =
|
|
7477
|
+
const colors = mesh2.instanceColor.array;
|
|
6948
7478
|
colors[index * 3] = color[0];
|
|
6949
7479
|
colors[index * 3 + 1] = color[1];
|
|
6950
7480
|
colors[index * 3 + 2] = color[2];
|
|
6951
7481
|
}
|
|
6952
7482
|
rocks.count = rockCount;
|
|
6953
7483
|
plates.count = plateCount;
|
|
6954
|
-
for (const
|
|
6955
|
-
|
|
6956
|
-
|
|
7484
|
+
for (const mesh2 of [rocks, plates]) {
|
|
7485
|
+
mesh2.instanceMatrix.needsUpdate = true;
|
|
7486
|
+
mesh2.instanceColor.needsUpdate = true;
|
|
6957
7487
|
}
|
|
6958
7488
|
return rockCount + plateCount;
|
|
6959
7489
|
},
|
|
@@ -7137,28 +7667,28 @@ void main(){
|
|
|
7137
7667
|
position.setXYZ(index, worldX, (options.ground?.heightAt(worldX, worldZ) ?? 0) + mark.lift, worldZ);
|
|
7138
7668
|
}
|
|
7139
7669
|
geometry.computeVertexNormals();
|
|
7140
|
-
const
|
|
7141
|
-
|
|
7142
|
-
return
|
|
7670
|
+
const mesh2 = new THREE.Mesh(geometry, material);
|
|
7671
|
+
mesh2.receiveShadow = true;
|
|
7672
|
+
return mesh2;
|
|
7143
7673
|
}
|
|
7144
7674
|
function addRock(mark) {
|
|
7145
|
-
const
|
|
7146
|
-
|
|
7147
|
-
|
|
7148
|
-
|
|
7149
|
-
|
|
7150
|
-
|
|
7151
|
-
return
|
|
7675
|
+
const mesh2 = new THREE.Mesh(mark.plate ? options.plateGeometry : options.rockGeometry, rockMaterial(mark.color));
|
|
7676
|
+
mesh2.position.set(mark.x, mark.y, mark.z);
|
|
7677
|
+
mesh2.scale.set(mark.scale[0], mark.scale[1], mark.scale[2]);
|
|
7678
|
+
mesh2.rotation.set(mark.rotation[0], mark.rotation[1], mark.rotation[2]);
|
|
7679
|
+
mesh2.castShadow = true;
|
|
7680
|
+
mesh2.receiveShadow = true;
|
|
7681
|
+
return mesh2;
|
|
7152
7682
|
}
|
|
7153
7683
|
function addBlood(mark) {
|
|
7154
|
-
const
|
|
7155
|
-
|
|
7156
|
-
|
|
7157
|
-
|
|
7158
|
-
|
|
7159
|
-
|
|
7160
|
-
blood.push({ mesh, scaleX: mark.scaleX, scaleZ: mark.scaleZ, age: 0 });
|
|
7161
|
-
return
|
|
7684
|
+
const mesh2 = new THREE.Mesh(bloodGeometry, bloodMaterial);
|
|
7685
|
+
mesh2.position.set(mark.x, mark.y, mark.z);
|
|
7686
|
+
mesh2.scale.set(mark.scaleX, 1, mark.scaleZ);
|
|
7687
|
+
mesh2.rotation.y = mark.rotation;
|
|
7688
|
+
mesh2.receiveShadow = true;
|
|
7689
|
+
mesh2.scale.multiplyScalar(0.05);
|
|
7690
|
+
blood.push({ mesh: mesh2, scaleX: mark.scaleX, scaleZ: mark.scaleZ, age: 0 });
|
|
7691
|
+
return mesh2;
|
|
7162
7692
|
}
|
|
7163
7693
|
function build(mark) {
|
|
7164
7694
|
if (mark.kind === "scorch") return conform(mark, scorchMaterials[mark.variant]);
|
|
@@ -7369,6 +7899,73 @@ void main() {
|
|
|
7369
7899
|
}
|
|
7370
7900
|
};
|
|
7371
7901
|
}
|
|
7902
|
+
var SPHERE_DEFAULT_WIDTH = 8;
|
|
7903
|
+
var SPHERE_DEFAULT_HEIGHT = 6;
|
|
7904
|
+
function geometryOf(THREE, particle) {
|
|
7905
|
+
switch (particle.shape) {
|
|
7906
|
+
case "cone":
|
|
7907
|
+
return new THREE.ConeGeometry(particle.radius, particle.height, particle.segments || void 0, particle.segments2 || 1, false);
|
|
7908
|
+
case "cone_open":
|
|
7909
|
+
return new THREE.ConeGeometry(particle.radius, particle.height, particle.segments || void 0, particle.segments2 || 1, true);
|
|
7910
|
+
case "sphere":
|
|
7911
|
+
return new THREE.SphereGeometry(particle.radius, particle.segments || SPHERE_DEFAULT_WIDTH, particle.segments2 || SPHERE_DEFAULT_HEIGHT);
|
|
7912
|
+
case "icosahedron":
|
|
7913
|
+
return new THREE.IcosahedronGeometry(particle.radius, particle.segments);
|
|
7914
|
+
}
|
|
7915
|
+
}
|
|
7916
|
+
function materialOf(THREE, particle) {
|
|
7917
|
+
if (particle.lit) return new THREE.MeshStandardMaterial({ color: particle.color, roughness: 1, metalness: 0, transparent: true, opacity: particle.opacity, depthWrite: false });
|
|
7918
|
+
return new THREE.MeshBasicMaterial({ color: particle.color, transparent: true, opacity: particle.opacity, depthWrite: false, ...particle.additive ? { blending: THREE.AdditiveBlending } : {} });
|
|
7919
|
+
}
|
|
7920
|
+
function createMeshLayer(THREE, pool) {
|
|
7921
|
+
const group = new THREE.Group();
|
|
7922
|
+
group.name = "workshop-meshes";
|
|
7923
|
+
const drawn = /* @__PURE__ */ new Map();
|
|
7924
|
+
const frame = new THREE.Quaternion();
|
|
7925
|
+
const euler = new THREE.Euler();
|
|
7926
|
+
const turn = new THREE.Quaternion();
|
|
7927
|
+
const offset = new THREE.Vector3();
|
|
7928
|
+
function release(mesh2) {
|
|
7929
|
+
mesh2.removeFromParent();
|
|
7930
|
+
mesh2.geometry.dispose();
|
|
7931
|
+
mesh2.material.dispose();
|
|
7932
|
+
}
|
|
7933
|
+
return {
|
|
7934
|
+
group,
|
|
7935
|
+
sync() {
|
|
7936
|
+
const live = /* @__PURE__ */ new Set();
|
|
7937
|
+
for (const particle of pool.particles) {
|
|
7938
|
+
live.add(particle.id);
|
|
7939
|
+
let mesh2 = drawn.get(particle.id);
|
|
7940
|
+
if (!mesh2) {
|
|
7941
|
+
mesh2 = new THREE.Mesh(geometryOf(THREE, particle), materialOf(THREE, particle));
|
|
7942
|
+
mesh2.frustumCulled = false;
|
|
7943
|
+
mesh2.renderOrder = particle.additive ? 5 : 3;
|
|
7944
|
+
drawn.set(particle.id, mesh2);
|
|
7945
|
+
group.add(mesh2);
|
|
7946
|
+
}
|
|
7947
|
+
frame.set(particle.frame[0], particle.frame[1], particle.frame[2], particle.frame[3]);
|
|
7948
|
+
offset.set(particle.at[0], particle.at[1], particle.at[2]).multiplyScalar(particle.scale).applyQuaternion(frame);
|
|
7949
|
+
mesh2.position.set(particle.x + offset.x, particle.y + offset.y, particle.z + offset.z);
|
|
7950
|
+
turn.setFromEuler(euler.set(particle.rx, particle.ry, particle.rz));
|
|
7951
|
+
mesh2.quaternion.copy(frame).multiply(turn);
|
|
7952
|
+
mesh2.scale.setScalar(particle.scale);
|
|
7953
|
+
mesh2.material.opacity = particle.opacity;
|
|
7954
|
+
}
|
|
7955
|
+
for (const [id, mesh2] of drawn) {
|
|
7956
|
+
if (live.has(id)) continue;
|
|
7957
|
+
release(mesh2);
|
|
7958
|
+
drawn.delete(id);
|
|
7959
|
+
}
|
|
7960
|
+
return pool.count;
|
|
7961
|
+
},
|
|
7962
|
+
dispose() {
|
|
7963
|
+
for (const mesh2 of drawn.values()) release(mesh2);
|
|
7964
|
+
drawn.clear();
|
|
7965
|
+
group.removeFromParent();
|
|
7966
|
+
}
|
|
7967
|
+
};
|
|
7968
|
+
}
|
|
7372
7969
|
var WORKSHOP_SPRITE_VERTEX = `attribute float size;attribute float alpha;attribute vec3 pcol;varying vec3 vC;varying float vA;uniform float uScale;
|
|
7373
7970
|
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;}`;
|
|
7374
7971
|
var WORKSHOP_SPRITE_FRAGMENT = `uniform float uSoft;varying vec3 vC;varying float vA;
|
|
@@ -7444,13 +8041,37 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
7444
8041
|
}
|
|
7445
8042
|
};
|
|
7446
8043
|
}
|
|
8044
|
+
function rainLayer(THREE, rain) {
|
|
8045
|
+
const geometry = new THREE.BufferGeometry();
|
|
8046
|
+
const position = new THREE.BufferAttribute(rain.positions, 3).setUsage(THREE.DynamicDrawUsage);
|
|
8047
|
+
geometry.setAttribute("position", position);
|
|
8048
|
+
geometry.setDrawRange(0, 0);
|
|
8049
|
+
const material = new THREE.LineBasicMaterial({ color: 10466255, transparent: true, opacity: 0.35, depthWrite: false });
|
|
8050
|
+
const lines = new THREE.LineSegments(geometry, material);
|
|
8051
|
+
lines.frustumCulled = false;
|
|
8052
|
+
lines.name = "workshop-rain";
|
|
8053
|
+
return {
|
|
8054
|
+
object: lines,
|
|
8055
|
+
sync() {
|
|
8056
|
+
const drawn = rain.on && rain.count > 0;
|
|
8057
|
+
lines.visible = drawn;
|
|
8058
|
+
geometry.setDrawRange(0, drawn ? rain.count * 2 : 0);
|
|
8059
|
+
position.needsUpdate = true;
|
|
8060
|
+
return drawn;
|
|
8061
|
+
},
|
|
8062
|
+
dispose() {
|
|
8063
|
+
geometry.dispose();
|
|
8064
|
+
material.dispose();
|
|
8065
|
+
}
|
|
8066
|
+
};
|
|
8067
|
+
}
|
|
7447
8068
|
function debrisLayer(THREE, pool) {
|
|
7448
8069
|
const geometry = new THREE.BoxGeometry(1, 1, 1);
|
|
7449
8070
|
const material = new THREE.MeshStandardMaterial({ color: 16777215, roughness: 0.45, metalness: 0.25, flatShading: true });
|
|
7450
|
-
const
|
|
7451
|
-
|
|
7452
|
-
|
|
7453
|
-
|
|
8071
|
+
const mesh2 = new THREE.InstancedMesh(geometry, material, DEBRIS_CAPACITY);
|
|
8072
|
+
mesh2.instanceMatrix.setUsage(THREE.DynamicDrawUsage);
|
|
8073
|
+
mesh2.frustumCulled = false;
|
|
8074
|
+
mesh2.name = "workshop-debris";
|
|
7454
8075
|
const euler = new THREE.Euler();
|
|
7455
8076
|
const quaternion = new THREE.Quaternion();
|
|
7456
8077
|
const position = new THREE.Vector3();
|
|
@@ -7458,16 +8079,16 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
7458
8079
|
const matrix = new THREE.Matrix4();
|
|
7459
8080
|
const colour = new THREE.Color();
|
|
7460
8081
|
const hidden = new THREE.Matrix4().makeScale(0, 0, 0);
|
|
7461
|
-
for (let index = 0; index < DEBRIS_CAPACITY; index++)
|
|
7462
|
-
|
|
8082
|
+
for (let index = 0; index < DEBRIS_CAPACITY; index++) mesh2.setMatrixAt(index, hidden);
|
|
8083
|
+
mesh2.setColorAt(0, colour.setHex(16777215));
|
|
7463
8084
|
return {
|
|
7464
|
-
object:
|
|
8085
|
+
object: mesh2,
|
|
7465
8086
|
sync() {
|
|
7466
8087
|
let drawn = false;
|
|
7467
8088
|
for (let index = 0; index < DEBRIS_CAPACITY; index++) {
|
|
7468
8089
|
const piece = pool.pieces[index];
|
|
7469
8090
|
if (!piece.on) {
|
|
7470
|
-
|
|
8091
|
+
mesh2.setMatrixAt(index, hidden);
|
|
7471
8092
|
continue;
|
|
7472
8093
|
}
|
|
7473
8094
|
drawn = true;
|
|
@@ -7475,11 +8096,11 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
7475
8096
|
euler.set(piece.rx, piece.ry, piece.rz);
|
|
7476
8097
|
quaternion.setFromEuler(euler);
|
|
7477
8098
|
matrix.compose(position.set(piece.x, piece.y, piece.z), quaternion, scale2.set(piece.sx * shrink, piece.sy * shrink, piece.sz * shrink));
|
|
7478
|
-
|
|
7479
|
-
|
|
8099
|
+
mesh2.setMatrixAt(index, matrix);
|
|
8100
|
+
mesh2.setColorAt(index, colour.setHex(piece.color));
|
|
7480
8101
|
}
|
|
7481
|
-
|
|
7482
|
-
if (
|
|
8102
|
+
mesh2.instanceMatrix.needsUpdate = true;
|
|
8103
|
+
if (mesh2.instanceColor) mesh2.instanceColor.needsUpdate = true;
|
|
7483
8104
|
return drawn;
|
|
7484
8105
|
},
|
|
7485
8106
|
dispose() {
|
|
@@ -7536,11 +8157,11 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
7536
8157
|
const dryMesh = new THREE.InstancedMesh(geometry, dry, DECAL_CAPACITY);
|
|
7537
8158
|
const group = new THREE.Group();
|
|
7538
8159
|
group.name = "workshop-decals";
|
|
7539
|
-
for (const
|
|
7540
|
-
|
|
7541
|
-
|
|
7542
|
-
|
|
7543
|
-
group.add(
|
|
8160
|
+
for (const mesh2 of [wetMesh, dryMesh]) {
|
|
8161
|
+
mesh2.frustumCulled = false;
|
|
8162
|
+
mesh2.renderOrder = 1;
|
|
8163
|
+
mesh2.instanceMatrix.setUsage(THREE.DynamicDrawUsage);
|
|
8164
|
+
group.add(mesh2);
|
|
7544
8165
|
}
|
|
7545
8166
|
const hidden = new THREE.Matrix4().makeScale(0, 0, 0);
|
|
7546
8167
|
const colour = new THREE.Color();
|
|
@@ -7577,13 +8198,13 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
7577
8198
|
quaternion.multiply(turn.setFromAxisAngle(forward, index * 2.399963));
|
|
7578
8199
|
const offset = 4e-3 + index % 40 * 4e-4;
|
|
7579
8200
|
matrix.compose(position.set(decal2.x + normal.x * offset, decal2.y + normal.y * offset, decal2.z + normal.z * offset), quaternion, scale2.set(look.sx, look.sy, 1));
|
|
7580
|
-
const
|
|
7581
|
-
|
|
7582
|
-
|
|
8201
|
+
const mesh2 = look.dried ? dryMesh : wetMesh;
|
|
8202
|
+
mesh2.setMatrixAt(index, matrix);
|
|
8203
|
+
mesh2.setColorAt(index, colour);
|
|
7583
8204
|
}
|
|
7584
|
-
for (const
|
|
7585
|
-
|
|
7586
|
-
if (
|
|
8205
|
+
for (const mesh2 of [wetMesh, dryMesh]) {
|
|
8206
|
+
mesh2.instanceMatrix.needsUpdate = true;
|
|
8207
|
+
if (mesh2.instanceColor) mesh2.instanceColor.needsUpdate = true;
|
|
7587
8208
|
}
|
|
7588
8209
|
return drawn;
|
|
7589
8210
|
},
|
|
@@ -7597,10 +8218,10 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
7597
8218
|
function ringLayer(THREE, pool) {
|
|
7598
8219
|
const geometry = new THREE.RingGeometry(0.86, 1, 40);
|
|
7599
8220
|
const material = new THREE.MeshBasicMaterial({ color: 16777215, transparent: true, blending: THREE.AdditiveBlending, depthWrite: false, side: THREE.DoubleSide });
|
|
7600
|
-
const
|
|
7601
|
-
|
|
7602
|
-
|
|
7603
|
-
|
|
8221
|
+
const mesh2 = new THREE.InstancedMesh(geometry, material, RING_CAPACITY3);
|
|
8222
|
+
mesh2.frustumCulled = false;
|
|
8223
|
+
mesh2.instanceMatrix.setUsage(THREE.DynamicDrawUsage);
|
|
8224
|
+
mesh2.name = "workshop-rings";
|
|
7604
8225
|
const hidden = new THREE.Matrix4().makeScale(0, 0, 0);
|
|
7605
8226
|
const colour = new THREE.Color();
|
|
7606
8227
|
const normal = new THREE.Vector3();
|
|
@@ -7609,16 +8230,16 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
7609
8230
|
const position = new THREE.Vector3();
|
|
7610
8231
|
const scale2 = new THREE.Vector3();
|
|
7611
8232
|
const matrix = new THREE.Matrix4();
|
|
7612
|
-
|
|
7613
|
-
for (let index = 0; index < RING_CAPACITY3; index++)
|
|
8233
|
+
mesh2.setColorAt(0, colour.setHex(0));
|
|
8234
|
+
for (let index = 0; index < RING_CAPACITY3; index++) mesh2.setMatrixAt(index, hidden);
|
|
7614
8235
|
return {
|
|
7615
|
-
object:
|
|
8236
|
+
object: mesh2,
|
|
7616
8237
|
sync() {
|
|
7617
8238
|
let drawn = false;
|
|
7618
8239
|
for (let index = 0; index < RING_CAPACITY3; index++) {
|
|
7619
8240
|
const ring2 = pool.rings[index];
|
|
7620
8241
|
if (!ring2.on) {
|
|
7621
|
-
|
|
8242
|
+
mesh2.setMatrixAt(index, hidden);
|
|
7622
8243
|
continue;
|
|
7623
8244
|
}
|
|
7624
8245
|
drawn = true;
|
|
@@ -7626,11 +8247,11 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
7626
8247
|
const radius = ring2.from + (ring2.to - ring2.from) * (1 - Math.pow(1 - k, 2));
|
|
7627
8248
|
quaternion.setFromUnitVectors(forward, normal.set(ring2.normal[0], ring2.normal[1], ring2.normal[2]));
|
|
7628
8249
|
matrix.compose(position.set(ring2.point[0], ring2.point[1], ring2.point[2]), quaternion, scale2.set(radius, radius, 1));
|
|
7629
|
-
|
|
7630
|
-
|
|
8250
|
+
mesh2.setMatrixAt(index, matrix);
|
|
8251
|
+
mesh2.setColorAt(index, colour.setHex(ring2.color).multiplyScalar(ring2.hold ? ring2.hold : 1 - k));
|
|
7631
8252
|
}
|
|
7632
|
-
|
|
7633
|
-
if (
|
|
8253
|
+
mesh2.instanceMatrix.needsUpdate = true;
|
|
8254
|
+
if (mesh2.instanceColor) mesh2.instanceColor.needsUpdate = true;
|
|
7634
8255
|
return drawn;
|
|
7635
8256
|
},
|
|
7636
8257
|
dispose() {
|
|
@@ -7646,11 +8267,14 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
7646
8267
|
spriteLayer(THREE, engine.add, true, 1, pointScale),
|
|
7647
8268
|
spriteLayer(THREE, engine.normal, false, 0.55, pointScale),
|
|
7648
8269
|
streakLayer(THREE, engine.streaks),
|
|
8270
|
+
rainLayer(THREE, engine.rain),
|
|
7649
8271
|
debrisLayer(THREE, engine.debris),
|
|
7650
8272
|
decalLayer(THREE, engine.decals),
|
|
7651
8273
|
ringLayer(THREE, engine.rings)
|
|
7652
8274
|
];
|
|
7653
8275
|
for (const layer2 of layers) group.add(layer2.object);
|
|
8276
|
+
const meshes = createMeshLayer(THREE, engine.meshes);
|
|
8277
|
+
group.add(meshes.group);
|
|
7654
8278
|
const flashLights = engine.lights.lights.map(() => new THREE.PointLight(16760944, 0, 14));
|
|
7655
8279
|
const fireLights = engine.lights.fire.map(() => new THREE.PointLight(FIRE_LIGHT_COLOR, 0, FIRE_LIGHT_DISTANCE));
|
|
7656
8280
|
for (const light of [...flashLights, ...fireLights]) group.add(light);
|
|
@@ -7659,6 +8283,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
7659
8283
|
sync() {
|
|
7660
8284
|
let drawCalls = 0;
|
|
7661
8285
|
for (const layer2 of layers) if (layer2.sync()) drawCalls++;
|
|
8286
|
+
drawCalls += meshes.sync();
|
|
7662
8287
|
engine.lights.lights.forEach((source, index) => {
|
|
7663
8288
|
const light = flashLights[index];
|
|
7664
8289
|
light.position.set(source.x, source.y, source.z);
|
|
@@ -7675,6 +8300,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
7675
8300
|
},
|
|
7676
8301
|
dispose() {
|
|
7677
8302
|
for (const layer2 of layers) layer2.dispose();
|
|
8303
|
+
meshes.dispose();
|
|
7678
8304
|
group.clear();
|
|
7679
8305
|
}
|
|
7680
8306
|
};
|
|
@@ -7790,8 +8416,10 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
7790
8416
|
return world.play(request.effect, request.point, {
|
|
7791
8417
|
...request.direction ? { direction: request.direction } : {},
|
|
7792
8418
|
...request.normal ? { normal: request.normal } : {},
|
|
8419
|
+
...request.orientation ? { orientation: request.orientation } : {},
|
|
7793
8420
|
...request.seed !== void 0 ? { seed: request.seed } : {},
|
|
7794
|
-
...request.param !== void 0 ? { param: request.param } : {}
|
|
8421
|
+
...request.param !== void 0 ? { param: request.param } : {},
|
|
8422
|
+
...request.values ? { values: request.values } : {}
|
|
7795
8423
|
});
|
|
7796
8424
|
},
|
|
7797
8425
|
stop: (handle) => world.stop(handle),
|
|
@@ -8605,7 +9233,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
8605
9233
|
if (lastRow < 0) return;
|
|
8606
9234
|
const profile = profileOf2();
|
|
8607
9235
|
const rainScale = 1 - options.weather().rain;
|
|
8608
|
-
const seconds = dryingSeconds * rainScale;
|
|
9236
|
+
const seconds = dryingSeconds * rainScale * (options.weather().drying ?? 1);
|
|
8609
9237
|
for (let row = firstRow; row <= lastRow; row++) {
|
|
8610
9238
|
const offset = row * width;
|
|
8611
9239
|
for (let column = firstColumn; column <= lastColumn; column++) {
|
|
@@ -8729,6 +9357,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
8729
9357
|
}
|
|
8730
9358
|
var DEFAULT_STEP_RATE = 180;
|
|
8731
9359
|
var DEFAULT_MAX_STEPS = 6;
|
|
9360
|
+
var WASH_BELOW_DRYNESS = 0.5;
|
|
8732
9361
|
function createFilm(options) {
|
|
8733
9362
|
const { layout, random } = options;
|
|
8734
9363
|
const cellCount = layout.width * layout.height;
|
|
@@ -8739,7 +9368,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
8739
9368
|
dryness: new Float32Array(cellCount),
|
|
8740
9369
|
dampness: new Float32Array(cellCount)
|
|
8741
9370
|
};
|
|
8742
|
-
let weatherState = { rain: 0 };
|
|
9371
|
+
let weatherState = { rain: 0, drying: 1 };
|
|
8743
9372
|
let currentProfile = options.profile;
|
|
8744
9373
|
const context = { field, random, profile: () => currentProfile };
|
|
8745
9374
|
const drops = createDropPool(layout, context);
|
|
@@ -8777,9 +9406,29 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
8777
9406
|
simulator.advance({ dt, dryingSeconds });
|
|
8778
9407
|
},
|
|
8779
9408
|
setWeather(weather) {
|
|
8780
|
-
weatherState = {
|
|
9409
|
+
weatherState = {
|
|
9410
|
+
rain: Math.min(1, Math.max(0, weather.rain ?? weatherState.rain)),
|
|
9411
|
+
drying: Math.max(0, weather.drying ?? weatherState.drying ?? 1)
|
|
9412
|
+
};
|
|
8781
9413
|
},
|
|
8782
9414
|
weather: () => ({ ...weatherState }),
|
|
9415
|
+
wash(maxDryness = WASH_BELOW_DRYNESS) {
|
|
9416
|
+
simulator.refreshBounds();
|
|
9417
|
+
const { firstRow, lastRow, firstColumn, lastColumn } = simulator.bounds;
|
|
9418
|
+
let cleared = 0;
|
|
9419
|
+
for (let row = firstRow; row <= lastRow; row++) {
|
|
9420
|
+
for (let column = firstColumn; column <= lastColumn; column++) {
|
|
9421
|
+
const index = row * layout.width + column;
|
|
9422
|
+
if (field.thickness[index] > 0 && field.dryness[index] < maxDryness) {
|
|
9423
|
+
field.thickness[index] = 0;
|
|
9424
|
+
field.dryness[index] = 0;
|
|
9425
|
+
field.dampness[index] = 0;
|
|
9426
|
+
cleared++;
|
|
9427
|
+
}
|
|
9428
|
+
}
|
|
9429
|
+
}
|
|
9430
|
+
return cleared;
|
|
9431
|
+
},
|
|
8783
9432
|
clear() {
|
|
8784
9433
|
field.thickness.fill(0);
|
|
8785
9434
|
field.dryness.fill(0);
|
|
@@ -9292,11 +9941,11 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
9292
9941
|
const index = [];
|
|
9293
9942
|
for (let i = 0; i < this.ring; i++) index.push(0, 1 + i, 1 + (i + 1) % this.ring);
|
|
9294
9943
|
geometry.setIndex(index);
|
|
9295
|
-
const
|
|
9296
|
-
|
|
9297
|
-
|
|
9298
|
-
|
|
9299
|
-
return { mesh, position, color };
|
|
9944
|
+
const mesh2 = new T.Mesh(geometry);
|
|
9945
|
+
mesh2.name = name;
|
|
9946
|
+
mesh2.frustumCulled = false;
|
|
9947
|
+
mesh2.renderOrder = order;
|
|
9948
|
+
return { mesh: mesh2, position, color };
|
|
9300
9949
|
}
|
|
9301
9950
|
assign(def, materials) {
|
|
9302
9951
|
this.outer.mesh.material = materials.stainFilm(def);
|
|
@@ -10036,12 +10685,12 @@ void main(){
|
|
|
10036
10685
|
this.group = new THREE.Group();
|
|
10037
10686
|
this.group.name = "film_grid";
|
|
10038
10687
|
for (const region of layout.regions) {
|
|
10039
|
-
const
|
|
10040
|
-
|
|
10041
|
-
|
|
10042
|
-
|
|
10043
|
-
this.strips.push(
|
|
10044
|
-
this.group.add(
|
|
10688
|
+
const mesh2 = new THREE.Mesh(createStripGeometry(THREE, layout, region), this.material.material);
|
|
10689
|
+
mesh2.frustumCulled = false;
|
|
10690
|
+
mesh2.renderOrder = 3;
|
|
10691
|
+
mesh2.name = `film_${region.id}`;
|
|
10692
|
+
this.strips.push(mesh2);
|
|
10693
|
+
this.group.add(mesh2);
|
|
10045
10694
|
}
|
|
10046
10695
|
this.dropsView = createFilmDrops(THREE, layout.rules.dropCapacity, profile);
|
|
10047
10696
|
this.group.add(this.dropsView.drops, this.dropsView.bead);
|
|
@@ -10086,6 +10735,19 @@ void main(){
|
|
|
10086
10735
|
this.pending = this.union(this.pending, rect);
|
|
10087
10736
|
return this.takePending();
|
|
10088
10737
|
}
|
|
10738
|
+
/** Clears the cells less than `maxDryness` dry and sends the rectangle that held them up with the next update. Returns how many it cleared. */
|
|
10739
|
+
wash(maxDryness) {
|
|
10740
|
+
const cleared = this.film.wash(maxDryness);
|
|
10741
|
+
if (cleared > 0) {
|
|
10742
|
+
const bounds = this.film.simulator.bounds;
|
|
10743
|
+
if (bounds.lastRow >= 0) {
|
|
10744
|
+
const rect = { firstRow: bounds.firstRow, lastRow: bounds.lastRow, firstColumn: bounds.firstColumn, lastColumn: bounds.lastColumn };
|
|
10745
|
+
this.encode(rect);
|
|
10746
|
+
this.pending = this.union(this.pending, rect);
|
|
10747
|
+
}
|
|
10748
|
+
}
|
|
10749
|
+
return cleared;
|
|
10750
|
+
}
|
|
10089
10751
|
takePending() {
|
|
10090
10752
|
const rect = this.pending;
|
|
10091
10753
|
this.pending = null;
|
|
@@ -10141,7 +10803,7 @@ void main(){
|
|
|
10141
10803
|
return { firstRow: Math.min(a.firstRow, b.firstRow), lastRow: Math.max(a.lastRow, b.lastRow), firstColumn: Math.min(a.firstColumn, b.firstColumn), lastColumn: Math.max(a.lastColumn, b.lastColumn) };
|
|
10142
10804
|
}
|
|
10143
10805
|
dispose() {
|
|
10144
|
-
for (const
|
|
10806
|
+
for (const mesh2 of this.strips) mesh2.geometry.dispose();
|
|
10145
10807
|
this.material.dispose();
|
|
10146
10808
|
this.dropsView.dispose();
|
|
10147
10809
|
this.texture.dispose();
|
|
@@ -10157,11 +10819,12 @@ void main(){
|
|
|
10157
10819
|
var DEFAULT_GRID_METRES = 2;
|
|
10158
10820
|
var DEFAULT_CELL2 = 0.0125;
|
|
10159
10821
|
var BAKE_RANGE_FACTOR = 1.25;
|
|
10822
|
+
var DEFAULT_WASHABLE = ["blood", "old_blood"];
|
|
10160
10823
|
var EDGE_MARGIN = 0.35;
|
|
10161
10824
|
var FLOOR_REACH = 0.3;
|
|
10162
10825
|
var DROP_HEIGHT = 2.5;
|
|
10163
10826
|
var DEFAULT_DROP_RADIUS = 3;
|
|
10164
|
-
var
|
|
10827
|
+
var FALL_SPEED2 = 2;
|
|
10165
10828
|
var VISIBLE_THICKNESS3 = 0.035;
|
|
10166
10829
|
var DEFAULT_HALF = 50;
|
|
10167
10830
|
var FREE_AFTER_EMPTY = 2;
|
|
@@ -10182,6 +10845,7 @@ void main(){
|
|
|
10182
10845
|
__publicField(this, "staging", /* @__PURE__ */ new Map());
|
|
10183
10846
|
__publicField(this, "now");
|
|
10184
10847
|
__publicField(this, "rain", 0);
|
|
10848
|
+
__publicField(this, "drying", 1);
|
|
10185
10849
|
__publicField(this, "time", 0);
|
|
10186
10850
|
__publicField(this, "bakedCount", 0);
|
|
10187
10851
|
__publicField(this, "last", { grids: 0, drops: 0, wetCells: 0, simMs: 0, starved: 0, baked: 0, uploadedTexels: 0 });
|
|
@@ -10201,13 +10865,24 @@ void main(){
|
|
|
10201
10865
|
}
|
|
10202
10866
|
setWeather(weather) {
|
|
10203
10867
|
this.rain = Math.min(1, Math.max(0, weather.rain));
|
|
10204
|
-
|
|
10868
|
+
if (weather.drying !== void 0) this.drying = Math.max(0, weather.drying);
|
|
10869
|
+
for (const grid of this.grids) grid.film.setWeather({ rain: this.rain, drying: this.drying });
|
|
10870
|
+
}
|
|
10871
|
+
/**
|
|
10872
|
+
* Rain washes the fresh stain away (the visor's `ZG.wipe` with mode "chuva"): in the grids of the washable liquids (default blood and old blood), the
|
|
10873
|
+
* cells that are less than `maxDryness` dry (default 0.5) are cleared. Returns how many cells it cleared.
|
|
10874
|
+
*/
|
|
10875
|
+
wash(maxDryness) {
|
|
10876
|
+
const washable = this.options.washable ?? DEFAULT_WASHABLE;
|
|
10877
|
+
let cleared = 0;
|
|
10878
|
+
for (const grid of this.grids) if (washable.includes(grid.profile.id)) cleared += grid.wash(maxDryness);
|
|
10879
|
+
return cleared;
|
|
10205
10880
|
}
|
|
10206
10881
|
/** Throws a drop of a liquid: it lands in the grid under it (made on the spot) and leaves the impact splash. Null when it is out of range or has no surface. */
|
|
10207
10882
|
launch(request) {
|
|
10208
10883
|
const grid = this.gridFor(request.fluid, request.point, request.surfaces, request.tint);
|
|
10209
10884
|
if (!grid) return null;
|
|
10210
|
-
const velocity = request.velocity ?? [0, -
|
|
10885
|
+
const velocity = request.velocity ?? [0, -FALL_SPEED2, 0];
|
|
10211
10886
|
grid.film.launch(request.point, velocity, request.radius ?? DEFAULT_DROP_RADIUS);
|
|
10212
10887
|
return grid;
|
|
10213
10888
|
}
|
|
@@ -10232,7 +10907,7 @@ void main(){
|
|
|
10232
10907
|
const layout = layoutFromSurfaces({ ...found, center: point, columns: this.columns(), rows: this.columns(), cellSize: this.options.cellSize ?? DEFAULT_CELL2 });
|
|
10233
10908
|
if (this.grids.length >= (this.options.maxGrids ?? DEFAULT_MAX_GRIDS)) this.evict(point);
|
|
10234
10909
|
const grid = new FilmGrid(this.THREE, { layout, profile, random: this.options.random, center: point, ...tint ? { tint } : {}, ...this.options.base === void 0 ? {} : { base: this.options.base } });
|
|
10235
|
-
grid.film.setWeather({ rain: this.rain });
|
|
10910
|
+
grid.film.setWeather({ rain: this.rain, drying: this.drying });
|
|
10236
10911
|
this.grids.push(grid);
|
|
10237
10912
|
this.group.add(grid.group);
|
|
10238
10913
|
return grid;
|
|
@@ -10309,7 +10984,7 @@ void main(){
|
|
|
10309
10984
|
/** Whether `point` is over the grid, away from its edge, so a splash there does not fall off the strip. */
|
|
10310
10985
|
covers(grid, point) {
|
|
10311
10986
|
const layout = grid.film.layout;
|
|
10312
|
-
const
|
|
10987
|
+
const wide2 = layout.width * layout.cellSize;
|
|
10313
10988
|
for (const region of layout.regions) {
|
|
10314
10989
|
const local2 = [point[0] - region.origin[0], point[1] - region.origin[1], point[2] - region.origin[2]];
|
|
10315
10990
|
const above2 = local2[0] * region.normal[0] + local2[1] * region.normal[1] + local2[2] * region.normal[2];
|
|
@@ -10317,7 +10992,7 @@ void main(){
|
|
|
10317
10992
|
const sideways = local2[0] * region.columnAxis[0] + local2[1] * region.columnAxis[1] + local2[2] * region.columnAxis[2];
|
|
10318
10993
|
const down = local2[0] * region.rowAxis[0] + local2[1] * region.rowAxis[1] + local2[2] * region.rowAxis[2];
|
|
10319
10994
|
const length2 = region.rowCount * layout.cellSize;
|
|
10320
|
-
if (sideways > EDGE_MARGIN && sideways <
|
|
10995
|
+
if (sideways > EDGE_MARGIN && sideways < wide2 - EDGE_MARGIN && down > EDGE_MARGIN && down < length2 - EDGE_MARGIN) return true;
|
|
10321
10996
|
}
|
|
10322
10997
|
return false;
|
|
10323
10998
|
}
|
|
@@ -10470,6 +11145,7 @@ void main(){
|
|
|
10470
11145
|
return landed;
|
|
10471
11146
|
},
|
|
10472
11147
|
setWeather: (weather) => manager.setWeather(weather),
|
|
11148
|
+
wash: (maxDryness) => manager.wash(maxDryness),
|
|
10473
11149
|
update(dt) {
|
|
10474
11150
|
if (leaks.size === 0) return;
|
|
10475
11151
|
const streams = new Map(fluids.streams().map((stream) => [stream.id, stream]));
|