@adatechnology/game-vfx-three 0.3.6 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-ALDCQ5RH.js +1904 -0
- package/dist/chunk-ALDCQ5RH.js.map +1 -0
- package/dist/index.d.ts +9 -32
- package/dist/index.global.js +502 -95
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +21 -1790
- package/dist/index.js.map +1 -1
- package/dist/testing.d.ts +33 -0
- package/dist/testing.js +11 -0
- package/dist/testing.js.map +1 -0
- package/package.json +8 -3
package/dist/index.global.js
CHANGED
|
@@ -45,6 +45,19 @@ var GameVfxThree = (() => {
|
|
|
45
45
|
});
|
|
46
46
|
|
|
47
47
|
// ../game-contracts/dist/index.js
|
|
48
|
+
var DEFAULT_COST_ALLOCATION_BYTES = 1024 * 1024;
|
|
49
|
+
var DEFERRED_QUEUE_ID = {
|
|
50
|
+
DESTRUCTION_EVENTS: "destruction.events",
|
|
51
|
+
BREACH_PAINT: "floorplan.breach-paint",
|
|
52
|
+
AUDIO_VOICES: "audio.voices",
|
|
53
|
+
VEHICLE_CREASE: "vehicles.crease"
|
|
54
|
+
};
|
|
55
|
+
var DEFERRED_PRIORITY = {
|
|
56
|
+
[DEFERRED_QUEUE_ID.DESTRUCTION_EVENTS]: { priority: 300, phase: "present" },
|
|
57
|
+
[DEFERRED_QUEUE_ID.BREACH_PAINT]: { priority: 250, phase: "present" },
|
|
58
|
+
[DEFERRED_QUEUE_ID.AUDIO_VOICES]: { priority: 200, phase: "idle", reserveMs: 1 },
|
|
59
|
+
[DEFERRED_QUEUE_ID.VEHICLE_CREASE]: { priority: 100, phase: "idle" }
|
|
60
|
+
};
|
|
48
61
|
var KIT_ORIGIN_KEY = "kitOrigin";
|
|
49
62
|
function markKitOrigin(object, origin) {
|
|
50
63
|
const node = object;
|
|
@@ -52,6 +65,42 @@ var GameVfxThree = (() => {
|
|
|
52
65
|
node.userData[KIT_ORIGIN_KEY] = { ...origin };
|
|
53
66
|
return object;
|
|
54
67
|
}
|
|
68
|
+
var SURFACE_IDS = ["concrete", "asphalt", "wood", "tile", "dirt", "grass", "gravel", "sand", "metal", "water", "glass", "carpet"];
|
|
69
|
+
var GAIT_IDS = ["walk", "run"];
|
|
70
|
+
var LANDING_IDS = ["light", "heavy"];
|
|
71
|
+
var BODY_SOUND_IDS = [
|
|
72
|
+
"jump",
|
|
73
|
+
"cloth_rustle",
|
|
74
|
+
"body_fall",
|
|
75
|
+
"fall_damage",
|
|
76
|
+
"player_hurt",
|
|
77
|
+
"player_breath_run",
|
|
78
|
+
"player_death",
|
|
79
|
+
"bite",
|
|
80
|
+
"grab",
|
|
81
|
+
"punch_swing",
|
|
82
|
+
"punch_hit_body",
|
|
83
|
+
"punch_hit_face",
|
|
84
|
+
"punch_hit_object",
|
|
85
|
+
"kick_swing",
|
|
86
|
+
"kick_hit",
|
|
87
|
+
"kick_hit_object",
|
|
88
|
+
"shove_two_hands",
|
|
89
|
+
"knife_swing",
|
|
90
|
+
"knife_stab",
|
|
91
|
+
"knife_slash",
|
|
92
|
+
"knife_hit_object",
|
|
93
|
+
"blunt_swing",
|
|
94
|
+
"blunt_hit",
|
|
95
|
+
"blunt_hit_object",
|
|
96
|
+
"axe_swing",
|
|
97
|
+
"axe_chop",
|
|
98
|
+
"axe_hit_object"
|
|
99
|
+
];
|
|
100
|
+
var footstepSoundId = (surface, gait) => `footstep_${surface}_${gait}`;
|
|
101
|
+
var FOOTSTEP_SOUND_IDS = SURFACE_IDS.flatMap((surface) => GAIT_IDS.map((gait) => footstepSoundId(surface, gait)));
|
|
102
|
+
var LAND_SOUND_IDS = SURFACE_IDS.flatMap((surface) => LANDING_IDS.map((landing) => `land_${surface}_${landing}`));
|
|
103
|
+
var BODY_FOLEY_IDS = [...FOOTSTEP_SOUND_IDS, ...LAND_SOUND_IDS, ...BODY_SOUND_IDS];
|
|
55
104
|
|
|
56
105
|
// ../game-vfx/dist/index.js
|
|
57
106
|
var __defProp2 = Object.defineProperty;
|
|
@@ -1344,11 +1393,231 @@ var GameVfxThree = (() => {
|
|
|
1344
1393
|
glow.outIntensity = glow.i * Math.pow(1 - age, glow.curve) * flicker;
|
|
1345
1394
|
}
|
|
1346
1395
|
}
|
|
1396
|
+
var LEHMER_MULTIPLIER = 16807;
|
|
1397
|
+
var LEHMER_MODULUS = 2147483647;
|
|
1398
|
+
var HASH_MIX = 2654435761;
|
|
1399
|
+
function normalizeLehmerSeed(seed) {
|
|
1400
|
+
const whole = Math.floor(Math.abs(seed)) % (LEHMER_MODULUS - 1);
|
|
1401
|
+
return whole === 0 ? 1 : whole;
|
|
1402
|
+
}
|
|
1403
|
+
function lehmer(seed) {
|
|
1404
|
+
let state = normalizeLehmerSeed(seed);
|
|
1405
|
+
const next = () => {
|
|
1406
|
+
state = state * LEHMER_MULTIPLIER % LEHMER_MODULUS;
|
|
1407
|
+
return (state - 1) / (LEHMER_MODULUS - 1);
|
|
1408
|
+
};
|
|
1409
|
+
return {
|
|
1410
|
+
next,
|
|
1411
|
+
between: (min2, max2) => min2 + (max2 - min2) * next(),
|
|
1412
|
+
direction(out) {
|
|
1413
|
+
const up = next() * 2 - 1;
|
|
1414
|
+
const angle = next() * Math.PI * 2;
|
|
1415
|
+
const ring2 = Math.sqrt(1 - up * up);
|
|
1416
|
+
out.x = ring2 * Math.cos(angle);
|
|
1417
|
+
out.y = up;
|
|
1418
|
+
out.z = ring2 * Math.sin(angle);
|
|
1419
|
+
return out;
|
|
1420
|
+
},
|
|
1421
|
+
get state() {
|
|
1422
|
+
return state;
|
|
1423
|
+
}
|
|
1424
|
+
};
|
|
1425
|
+
}
|
|
1426
|
+
function mixEventSeed(eventSeed) {
|
|
1427
|
+
let mixed = Math.imul((eventSeed | 0) ^ HASH_MIX, 2246822507);
|
|
1428
|
+
mixed ^= mixed >>> 13;
|
|
1429
|
+
mixed = Math.imul(mixed, 3266489909);
|
|
1430
|
+
mixed ^= mixed >>> 16;
|
|
1431
|
+
return (mixed >>> 0) % (LEHMER_MODULUS - 1) + 1;
|
|
1432
|
+
}
|
|
1433
|
+
function streamFor(eventSeed) {
|
|
1434
|
+
return lehmer(mixEventSeed(eventSeed));
|
|
1435
|
+
}
|
|
1436
|
+
var SKIN = 5e-3;
|
|
1437
|
+
var MAX_PAD = 0.45;
|
|
1438
|
+
function rotation(q) {
|
|
1439
|
+
const [x, y, z, w] = q ?? [0, 0, 0, 1];
|
|
1440
|
+
const n = Math.hypot(x, y, z, w) || 1;
|
|
1441
|
+
const qx = x / n;
|
|
1442
|
+
const qy = y / n;
|
|
1443
|
+
const qz = z / n;
|
|
1444
|
+
const qw = w / n;
|
|
1445
|
+
return new Float64Array([
|
|
1446
|
+
1 - 2 * (qy * qy + qz * qz),
|
|
1447
|
+
2 * (qx * qy - qz * qw),
|
|
1448
|
+
2 * (qx * qz + qy * qw),
|
|
1449
|
+
2 * (qx * qy + qz * qw),
|
|
1450
|
+
1 - 2 * (qx * qx + qz * qz),
|
|
1451
|
+
2 * (qy * qz - qx * qw),
|
|
1452
|
+
2 * (qx * qz - qy * qw),
|
|
1453
|
+
2 * (qy * qz + qx * qw),
|
|
1454
|
+
1 - 2 * (qx * qx + qy * qy)
|
|
1455
|
+
]);
|
|
1456
|
+
}
|
|
1457
|
+
var Enclosures = class {
|
|
1458
|
+
constructor(seed = 20973) {
|
|
1459
|
+
__publicField(this, "spaces", /* @__PURE__ */ new Map());
|
|
1460
|
+
__publicField(this, "list", []);
|
|
1461
|
+
__publicField(this, "random");
|
|
1462
|
+
__publicField(this, "out", { x: 0, y: 0, z: 0, nx: 0, ny: 0, nz: 0 });
|
|
1463
|
+
__publicField(this, "l0", new Float64Array(3));
|
|
1464
|
+
__publicField(this, "l1", new Float64Array(3));
|
|
1465
|
+
__publicField(this, "q", new Float64Array(3));
|
|
1466
|
+
this.random = lehmer(seed);
|
|
1467
|
+
}
|
|
1468
|
+
get empty() {
|
|
1469
|
+
return this.list.length === 0;
|
|
1470
|
+
}
|
|
1471
|
+
get size() {
|
|
1472
|
+
return this.list.length;
|
|
1473
|
+
}
|
|
1474
|
+
/** Declares, moves or (with `null`) ends the space `id`. */
|
|
1475
|
+
set(id, enclosure) {
|
|
1476
|
+
if (!enclosure) {
|
|
1477
|
+
if (this.spaces.delete(id)) this.list = [...this.spaces.values()];
|
|
1478
|
+
return;
|
|
1479
|
+
}
|
|
1480
|
+
const [hx, hy, hz] = enclosure.halfSize;
|
|
1481
|
+
const space = {
|
|
1482
|
+
cx: enclosure.center[0],
|
|
1483
|
+
cy: enclosure.center[1],
|
|
1484
|
+
cz: enclosure.center[2],
|
|
1485
|
+
hx: Math.abs(hx),
|
|
1486
|
+
hy: Math.abs(hy),
|
|
1487
|
+
hz: Math.abs(hz),
|
|
1488
|
+
r: rotation(enclosure.orientation),
|
|
1489
|
+
radius: Math.hypot(hx, hy, hz),
|
|
1490
|
+
openings: enclosure.openings ?? [],
|
|
1491
|
+
leak: Math.max(0, enclosure.leak ?? 0)
|
|
1492
|
+
};
|
|
1493
|
+
const old = this.spaces.get(id);
|
|
1494
|
+
this.spaces.set(id, space);
|
|
1495
|
+
const at3 = old ? this.list.indexOf(old) : -1;
|
|
1496
|
+
if (at3 >= 0) this.list[at3] = space;
|
|
1497
|
+
else this.list.push(space);
|
|
1498
|
+
}
|
|
1499
|
+
get(id) {
|
|
1500
|
+
const s = this.spaces.get(id);
|
|
1501
|
+
if (!s) return void 0;
|
|
1502
|
+
return { center: [s.cx, s.cy, s.cz], halfSize: [s.hx, s.hy, s.hz], openings: s.openings, leak: s.leak };
|
|
1503
|
+
}
|
|
1504
|
+
ids() {
|
|
1505
|
+
return [...this.spaces.keys()];
|
|
1506
|
+
}
|
|
1507
|
+
clear() {
|
|
1508
|
+
this.spaces.clear();
|
|
1509
|
+
this.list = [];
|
|
1510
|
+
}
|
|
1511
|
+
/** Whether a point is inside any space (on the inside of its walls). */
|
|
1512
|
+
inside(x, y, z) {
|
|
1513
|
+
for (const s of this.list) {
|
|
1514
|
+
this.toLocal(s, x, y, z, this.l0);
|
|
1515
|
+
if (Math.abs(this.l0[0]) <= s.hx && Math.abs(this.l0[1]) <= s.hy && Math.abs(this.l0[2]) <= s.hz) return true;
|
|
1516
|
+
}
|
|
1517
|
+
return false;
|
|
1518
|
+
}
|
|
1519
|
+
toLocal(s, x, y, z, out) {
|
|
1520
|
+
const dx = x - s.cx;
|
|
1521
|
+
const dy = y - s.cy;
|
|
1522
|
+
const dz = z - s.cz;
|
|
1523
|
+
const r = s.r;
|
|
1524
|
+
out[0] = r[0] * dx + r[3] * dy + r[6] * dz;
|
|
1525
|
+
out[1] = r[1] * dx + r[4] * dy + r[7] * dz;
|
|
1526
|
+
out[2] = r[2] * dx + r[5] * dy + r[8] * dz;
|
|
1527
|
+
}
|
|
1528
|
+
/** Passes at `rate` per second. */
|
|
1529
|
+
chance(rate, dt) {
|
|
1530
|
+
return rate > 0 && this.random.next() < 1 - Math.exp(-rate * dt);
|
|
1531
|
+
}
|
|
1532
|
+
/** The opening the wall point `q` (local) is in lets it through now. */
|
|
1533
|
+
through(s, q, dt) {
|
|
1534
|
+
for (const o of s.openings) {
|
|
1535
|
+
if (Math.abs(q[0] - o.center[0]) > o.halfSize[0] || Math.abs(q[1] - o.center[1]) > o.halfSize[1] || Math.abs(q[2] - o.center[2]) > o.halfSize[2]) continue;
|
|
1536
|
+
if (o.rate === void 0 || this.chance(o.rate, dt)) return true;
|
|
1537
|
+
}
|
|
1538
|
+
return this.chance(s.leak, dt);
|
|
1539
|
+
}
|
|
1540
|
+
confine(x0, y0, z0, x1, y1, z1, pad, dt) {
|
|
1541
|
+
const list = this.list;
|
|
1542
|
+
if (list.length === 0) return false;
|
|
1543
|
+
const p = Math.min(Math.max(0, pad), MAX_PAD);
|
|
1544
|
+
const l0 = this.l0;
|
|
1545
|
+
const l1 = this.l1;
|
|
1546
|
+
const q = this.q;
|
|
1547
|
+
for (const s of list) {
|
|
1548
|
+
const reach = s.radius + p + 0.05;
|
|
1549
|
+
const dx = x1 - s.cx;
|
|
1550
|
+
const dy = y1 - s.cy;
|
|
1551
|
+
const dz = z1 - s.cz;
|
|
1552
|
+
if (dx * dx + dy * dy + dz * dz > reach * reach) {
|
|
1553
|
+
const ex = x0 - s.cx;
|
|
1554
|
+
const ey = y0 - s.cy;
|
|
1555
|
+
const ez = z0 - s.cz;
|
|
1556
|
+
if (ex * ex + ey * ey + ez * ez > reach * reach) continue;
|
|
1557
|
+
}
|
|
1558
|
+
this.toLocal(s, x0, y0, z0, l0);
|
|
1559
|
+
this.toLocal(s, x1, y1, z1, l1);
|
|
1560
|
+
const h = [s.hx, s.hy, s.hz];
|
|
1561
|
+
const in0 = Math.abs(l0[0]) <= s.hx && Math.abs(l0[1]) <= s.hy && Math.abs(l0[2]) <= s.hz;
|
|
1562
|
+
let axis2 = 0;
|
|
1563
|
+
let sign = 1;
|
|
1564
|
+
if (in0) {
|
|
1565
|
+
if (Math.abs(l1[0]) <= s.hx && Math.abs(l1[1]) <= s.hy && Math.abs(l1[2]) <= s.hz) continue;
|
|
1566
|
+
for (let a = 0; a < 3; a++) q[a] = Math.min(h[a], Math.max(-h[a], l1[a]));
|
|
1567
|
+
if (this.through(s, q, dt)) continue;
|
|
1568
|
+
let worst = -Infinity;
|
|
1569
|
+
for (let a = 0; a < 3; a++) {
|
|
1570
|
+
const over = Math.abs(l1[a]) - h[a];
|
|
1571
|
+
if (over > worst) {
|
|
1572
|
+
worst = over;
|
|
1573
|
+
axis2 = a;
|
|
1574
|
+
}
|
|
1575
|
+
}
|
|
1576
|
+
sign = l1[axis2] < 0 ? -1 : 1;
|
|
1577
|
+
for (let a = 0; a < 3; a++) l1[a] = Math.min(h[a] - SKIN, Math.max(-(h[a] - SKIN), l1[a]));
|
|
1578
|
+
sign = -sign;
|
|
1579
|
+
} else {
|
|
1580
|
+
const padded0 = Math.abs(l0[0]) <= s.hx + p && Math.abs(l0[1]) <= s.hy + p && Math.abs(l0[2]) <= s.hz + p;
|
|
1581
|
+
const bound = padded0 ? 0 : p;
|
|
1582
|
+
if (!(Math.abs(l1[0]) <= s.hx + bound && Math.abs(l1[1]) <= s.hy + bound && Math.abs(l1[2]) <= s.hz + bound)) continue;
|
|
1583
|
+
for (let a = 0; a < 3; a++) q[a] = Math.min(h[a], Math.max(-h[a], l1[a]));
|
|
1584
|
+
if (this.through(s, q, dt)) continue;
|
|
1585
|
+
let worst = -Infinity;
|
|
1586
|
+
for (let a = 0; a < 3; a++) {
|
|
1587
|
+
const over = Math.abs(l0[a]) - (h[a] + bound);
|
|
1588
|
+
if (over > worst) {
|
|
1589
|
+
worst = over;
|
|
1590
|
+
axis2 = a;
|
|
1591
|
+
}
|
|
1592
|
+
}
|
|
1593
|
+
sign = l0[axis2] < 0 ? -1 : 1;
|
|
1594
|
+
l1[axis2] = sign * (h[axis2] + bound + SKIN);
|
|
1595
|
+
}
|
|
1596
|
+
const r = s.r;
|
|
1597
|
+
const out = this.out;
|
|
1598
|
+
out.x = s.cx + r[0] * l1[0] + r[1] * l1[1] + r[2] * l1[2];
|
|
1599
|
+
out.y = s.cy + r[3] * l1[0] + r[4] * l1[1] + r[5] * l1[2];
|
|
1600
|
+
out.z = s.cz + r[6] * l1[0] + r[7] * l1[1] + r[8] * l1[2];
|
|
1601
|
+
out.nx = r[axis2] * sign;
|
|
1602
|
+
out.ny = r[3 + axis2] * sign;
|
|
1603
|
+
out.nz = r[6 + axis2] * sign;
|
|
1604
|
+
return true;
|
|
1605
|
+
}
|
|
1606
|
+
return false;
|
|
1607
|
+
}
|
|
1608
|
+
};
|
|
1609
|
+
function slideAlong(out, vx2, vy2, vz2) {
|
|
1610
|
+
const into = vx2 * out.nx + vy2 * out.ny + vz2 * out.nz;
|
|
1611
|
+
if (into >= 0) return [vx2, vy2, vz2];
|
|
1612
|
+
return [vx2 - into * out.nx, vy2 - into * out.ny, vz2 - into * out.nz];
|
|
1613
|
+
}
|
|
1347
1614
|
var FLOOR_FRACTION = 0.4;
|
|
1348
1615
|
var FLOOR_BOUNCE = -0.2;
|
|
1349
1616
|
var ARRIVAL_FRAME = 30;
|
|
1350
1617
|
var ARRIVAL_BASE = 0.3;
|
|
1351
1618
|
var GROWTH_CAP_SECONDS = 3.5;
|
|
1619
|
+
var CARRIED_KINDS = [true, true, false, true, false];
|
|
1620
|
+
var PAD_OF_SIZE = 0.35;
|
|
1352
1621
|
function createPuffPool(capacity) {
|
|
1353
1622
|
const placeholder = { next: () => 0, between: (min2) => min2, direction: (out) => out, state: 0 };
|
|
1354
1623
|
return new OrderedPool(capacity, () => ({
|
|
@@ -1443,13 +1712,24 @@ var GameVfxThree = (() => {
|
|
|
1443
1712
|
if (puff3.vy < 0) puff3.vy *= FLOOR_BOUNCE;
|
|
1444
1713
|
}
|
|
1445
1714
|
}
|
|
1446
|
-
function updatePuffs(pool, dt, wind) {
|
|
1715
|
+
function updatePuffs(pool, dt, wind, confiner) {
|
|
1447
1716
|
pool.compact(ageOrKeep2, dt);
|
|
1717
|
+
const confining = confiner !== void 0 && !confiner.empty;
|
|
1448
1718
|
for (const puff3 of pool.items) {
|
|
1449
1719
|
const age = puff3.t / puff3.life;
|
|
1450
1720
|
const heat = puff3.h0 > 0 ? puff3.h0 * Math.pow(Math.max(0, 1 - puff3.t / puff3.hl), 1.25) : 0;
|
|
1721
|
+
const x0 = puff3.x;
|
|
1722
|
+
const y0 = puff3.y;
|
|
1723
|
+
const z0 = puff3.z;
|
|
1451
1724
|
if (puff3.ring) moveOnRing(puff3, puff3.ring, wind);
|
|
1452
1725
|
else moveFree(puff3, dt, age, heat, wind);
|
|
1726
|
+
if (confining && CARRIED_KINDS[puff3.kind] && confiner.confine(x0, y0, z0, puff3.x, puff3.y, puff3.z, puff3.size * PAD_OF_SIZE, dt)) {
|
|
1727
|
+
const out = confiner.out;
|
|
1728
|
+
puff3.x = out.x;
|
|
1729
|
+
puff3.y = out.y;
|
|
1730
|
+
puff3.z = out.z;
|
|
1731
|
+
[puff3.vx, puff3.vy, puff3.vz] = slideAlong(out, puff3.vx, puff3.vy, puff3.vz);
|
|
1732
|
+
}
|
|
1453
1733
|
const size = puff3.s0 + (puff3.s1 - puff3.s0) * (1 - Math.exp(-puff3.t * puff3.gk)) + puff3.sg * Math.min(puff3.t, GROWTH_CAP_SECONDS);
|
|
1454
1734
|
puff3.size = size * Math.min(1, puff3.t * ARRIVAL_FRAME + ARRIVAL_BASE);
|
|
1455
1735
|
puff3.age = age;
|
|
@@ -1975,10 +2255,10 @@ var GameVfxThree = (() => {
|
|
|
1975
2255
|
])
|
|
1976
2256
|
]
|
|
1977
2257
|
};
|
|
1978
|
-
function localToWorld(translation,
|
|
2258
|
+
function localToWorld(translation, rotation2, local2) {
|
|
1979
2259
|
const [x, y, z] = local2;
|
|
1980
|
-
const [a, c, e] = [Math.cos(
|
|
1981
|
-
const [b, d, f] = [Math.sin(
|
|
2260
|
+
const [a, c, e] = [Math.cos(rotation2[0]), Math.cos(rotation2[1]), Math.cos(rotation2[2])];
|
|
2261
|
+
const [b, d, f] = [Math.sin(rotation2[0]), Math.sin(rotation2[1]), Math.sin(rotation2[2])];
|
|
1982
2262
|
const [ae, af, be, bf] = [a * e, a * f, b * e, b * f];
|
|
1983
2263
|
return [
|
|
1984
2264
|
c * e * x + -c * f * y + d * z + translation[0],
|
|
@@ -2320,22 +2600,22 @@ var GameVfxThree = (() => {
|
|
|
2320
2600
|
)
|
|
2321
2601
|
]
|
|
2322
2602
|
};
|
|
2323
|
-
function normalized(
|
|
2324
|
-
const length = Math.sqrt(
|
|
2603
|
+
function normalized(vector2) {
|
|
2604
|
+
const length = Math.sqrt(vector2[0] * vector2[0] + vector2[1] * vector2[1] + vector2[2] * vector2[2]) || 1;
|
|
2325
2605
|
const inverse = 1 / length;
|
|
2326
|
-
return [
|
|
2606
|
+
return [vector2[0] * inverse, vector2[1] * inverse, vector2[2] * inverse];
|
|
2327
2607
|
}
|
|
2328
|
-
function plus(
|
|
2329
|
-
return [
|
|
2608
|
+
function plus(vector2, x, y, z) {
|
|
2609
|
+
return [vector2[0] + x, vector2[1] + y, vector2[2] + z];
|
|
2330
2610
|
}
|
|
2331
|
-
function scaledBy(
|
|
2332
|
-
return [
|
|
2611
|
+
function scaledBy(vector2, factor) {
|
|
2612
|
+
return [vector2[0] * factor, vector2[1] * factor, vector2[2] * factor];
|
|
2333
2613
|
}
|
|
2334
|
-
function plusScaled(
|
|
2335
|
-
return [
|
|
2614
|
+
function plusScaled(vector2, direction, factor) {
|
|
2615
|
+
return [vector2[0] + direction[0] * factor, vector2[1] + direction[1] * factor, vector2[2] + direction[2] * factor];
|
|
2336
2616
|
}
|
|
2337
|
-
function negated(
|
|
2338
|
-
return [-
|
|
2617
|
+
function negated(vector2) {
|
|
2618
|
+
return [-vector2[0], -vector2[1], -vector2[2]];
|
|
2339
2619
|
}
|
|
2340
2620
|
var FRAME_DUST = normalized([0, -0.3, 1]);
|
|
2341
2621
|
var SPLINTER_DIRECTION = normalized([0, 0.3, 1]);
|
|
@@ -3638,49 +3918,32 @@ var GameVfxThree = (() => {
|
|
|
3638
3918
|
/** The leak caught fire (an incendiary or tracer round, a spark, a fire near): the page's whole sequence, the fire running along the pool to the tank and the blast. */
|
|
3639
3919
|
aliasOf(FUEL_LEAK, "vehicle_leak_ignited", {})
|
|
3640
3920
|
];
|
|
3921
|
+
var vector = [variable("vx"), variable("vy"), variable("vz")];
|
|
3922
|
+
var range = (name) => [variable(name), variable(name)];
|
|
3923
|
+
var singleParticle = (id, system) => ({
|
|
3924
|
+
id,
|
|
3925
|
+
pageId: `particle:${id}`,
|
|
3926
|
+
team: "world",
|
|
3927
|
+
budget: { particles: 1, lights: 0 },
|
|
3928
|
+
loop: 1e-3,
|
|
3929
|
+
timeline: [
|
|
3930
|
+
spawn(system, {
|
|
3931
|
+
p: [0, 0, 0],
|
|
3932
|
+
v: vector,
|
|
3933
|
+
life: range("life"),
|
|
3934
|
+
size: range("size"),
|
|
3935
|
+
grow: variable("grow"),
|
|
3936
|
+
c0: variable("color"),
|
|
3937
|
+
a: variable("alpha"),
|
|
3938
|
+
g: variable("gravity"),
|
|
3939
|
+
drag: variable("drag")
|
|
3940
|
+
})
|
|
3941
|
+
]
|
|
3942
|
+
});
|
|
3943
|
+
var SINGLE_PARTICLE_EFFECTS = [singleParticle("particle_puff", "normal"), singleParticle("particle_glow", "add"), singleParticle("particle_streak", "streak")];
|
|
3641
3944
|
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];
|
|
3642
3945
|
var WORKSHOP_EFFECTS = Object.fromEntries(ALL_EFFECTS.map((effect) => [effect.id, effect]));
|
|
3643
|
-
var GAME_EFFECTS = { ...WORKSHOP_EFFECTS, ...Object.fromEntries([...EVENT_EFFECTS, ...VIEWMODEL_EFFECTS, ...VEHICLE_EFFECTS].map((effect) => [effect.id, effect])) };
|
|
3644
|
-
var LEHMER_MULTIPLIER = 16807;
|
|
3645
|
-
var LEHMER_MODULUS = 2147483647;
|
|
3646
|
-
var HASH_MIX = 2654435761;
|
|
3647
|
-
function normalizeLehmerSeed(seed) {
|
|
3648
|
-
const whole = Math.floor(Math.abs(seed)) % (LEHMER_MODULUS - 1);
|
|
3649
|
-
return whole === 0 ? 1 : whole;
|
|
3650
|
-
}
|
|
3651
|
-
function lehmer(seed) {
|
|
3652
|
-
let state = normalizeLehmerSeed(seed);
|
|
3653
|
-
const next = () => {
|
|
3654
|
-
state = state * LEHMER_MULTIPLIER % LEHMER_MODULUS;
|
|
3655
|
-
return (state - 1) / (LEHMER_MODULUS - 1);
|
|
3656
|
-
};
|
|
3657
|
-
return {
|
|
3658
|
-
next,
|
|
3659
|
-
between: (min2, max2) => min2 + (max2 - min2) * next(),
|
|
3660
|
-
direction(out) {
|
|
3661
|
-
const up = next() * 2 - 1;
|
|
3662
|
-
const angle = next() * Math.PI * 2;
|
|
3663
|
-
const ring2 = Math.sqrt(1 - up * up);
|
|
3664
|
-
out.x = ring2 * Math.cos(angle);
|
|
3665
|
-
out.y = up;
|
|
3666
|
-
out.z = ring2 * Math.sin(angle);
|
|
3667
|
-
return out;
|
|
3668
|
-
},
|
|
3669
|
-
get state() {
|
|
3670
|
-
return state;
|
|
3671
|
-
}
|
|
3672
|
-
};
|
|
3673
|
-
}
|
|
3674
|
-
function mixEventSeed(eventSeed) {
|
|
3675
|
-
let mixed = Math.imul((eventSeed | 0) ^ HASH_MIX, 2246822507);
|
|
3676
|
-
mixed ^= mixed >>> 13;
|
|
3677
|
-
mixed = Math.imul(mixed, 3266489909);
|
|
3678
|
-
mixed ^= mixed >>> 16;
|
|
3679
|
-
return (mixed >>> 0) % (LEHMER_MODULUS - 1) + 1;
|
|
3680
|
-
}
|
|
3681
|
-
function streamFor(eventSeed) {
|
|
3682
|
-
return lehmer(mixEventSeed(eventSeed));
|
|
3683
|
-
}
|
|
3946
|
+
var GAME_EFFECTS = { ...WORKSHOP_EFFECTS, ...Object.fromEntries([...EVENT_EFFECTS, ...VIEWMODEL_EFFECTS, ...VEHICLE_EFFECTS, ...SINGLE_PARTICLE_EFFECTS].map((effect) => [effect.id, effect])) };
|
|
3684
3947
|
var TABLE = {
|
|
3685
3948
|
concrete: { dust: 9078138, chip: 7236195, spark: 2 },
|
|
3686
3949
|
metal: { dust: 0, chip: 0, spark: 18 },
|
|
@@ -4350,8 +4613,8 @@ var GameVfxThree = (() => {
|
|
|
4350
4613
|
var UP12 = [0, 1, 0];
|
|
4351
4614
|
var ZERO = [0, 0, 0];
|
|
4352
4615
|
var FULL_TURN_DRAWN = 6.283;
|
|
4353
|
-
function scaledSizes(
|
|
4354
|
-
return [
|
|
4616
|
+
function scaledSizes(range2, factor) {
|
|
4617
|
+
return [range2[0] * Math.sqrt(factor), range2[1] * Math.sqrt(factor)];
|
|
4355
4618
|
}
|
|
4356
4619
|
function fireEmit(engine, key, dt, centre, radius, factor, options = {}) {
|
|
4357
4620
|
const wind = options.wind ?? ZERO;
|
|
@@ -4984,8 +5247,8 @@ var GameVfxThree = (() => {
|
|
|
4984
5247
|
function addScorch(store, random, x, z, radius) {
|
|
4985
5248
|
const variant = Math.floor(random.next() * SCORCH_VARIANTS);
|
|
4986
5249
|
const lift = 0.03 + nextLift(store) * 1e-3;
|
|
4987
|
-
const
|
|
4988
|
-
store.add({ kind: "scorch", x, z, radius, variant, lift, rotation });
|
|
5250
|
+
const rotation2 = random.next() * 6;
|
|
5251
|
+
store.add({ kind: "scorch", x, z, radius, variant, lift, rotation: rotation2 });
|
|
4989
5252
|
}
|
|
4990
5253
|
function addRimRocks(store, ground, random, x, z, radius) {
|
|
4991
5254
|
const count = Math.round(6 + radius * 7);
|
|
@@ -5014,8 +5277,8 @@ var GameVfxThree = (() => {
|
|
|
5014
5277
|
function addCrater(store, ground, random, spec) {
|
|
5015
5278
|
ground?.dent(random, spec.x, spec.z, spec.radius, spec.depth);
|
|
5016
5279
|
if (!spec.marks) return;
|
|
5017
|
-
const
|
|
5018
|
-
store.add({ kind: "dirt", x: spec.x, z: spec.z, radius: spec.radius * 1.02, lift: 0.045, rotation });
|
|
5280
|
+
const rotation2 = random.next() * 6;
|
|
5281
|
+
store.add({ kind: "dirt", x: spec.x, z: spec.z, radius: spec.radius * 1.02, lift: 0.045, rotation: rotation2 });
|
|
5019
5282
|
addRimRocks(store, ground, random, spec.x, spec.z, spec.radius);
|
|
5020
5283
|
}
|
|
5021
5284
|
function addBloodSplat(store, ground, random, spec) {
|
|
@@ -5571,6 +5834,7 @@ var GameVfxThree = (() => {
|
|
|
5571
5834
|
state.gas = Math.max(0, state.gas - dt / DECAY.gasSeconds);
|
|
5572
5835
|
state.beat *= Math.exp(-DECAY.beat * dt);
|
|
5573
5836
|
}
|
|
5837
|
+
var PAD_OF_SIZE2 = 0.35;
|
|
5574
5838
|
var clamp4 = (v, lo, hi) => v < lo ? lo : v > hi ? hi : v;
|
|
5575
5839
|
var lerp4 = (a, b, t) => a + (b - a) * t;
|
|
5576
5840
|
function rgb(hex) {
|
|
@@ -5730,9 +5994,20 @@ var GameVfxThree = (() => {
|
|
|
5730
5994
|
vy2 *= k;
|
|
5731
5995
|
vz2 *= k;
|
|
5732
5996
|
}
|
|
5733
|
-
|
|
5997
|
+
let x = this.position[i3] + vx2 * dt;
|
|
5734
5998
|
let y = this.position[i3 + 1] + vy2 * dt;
|
|
5735
|
-
|
|
5999
|
+
let z = this.position[i3 + 2] + vz2 * dt;
|
|
6000
|
+
const confiner = host.confiner;
|
|
6001
|
+
if (def.carried && confiner && !confiner.empty) {
|
|
6002
|
+
const pad = this.size0[i] * lerp4(1, def.grow, t) * PAD_OF_SIZE2;
|
|
6003
|
+
if (confiner.confine(this.position[i3], this.position[i3 + 1], this.position[i3 + 2], x, y, z, pad, dt)) {
|
|
6004
|
+
const out = confiner.out;
|
|
6005
|
+
x = out.x;
|
|
6006
|
+
y = out.y;
|
|
6007
|
+
z = out.z;
|
|
6008
|
+
[vx2, vy2, vz2] = slideAlong(out, vx2, vy2, vz2);
|
|
6009
|
+
}
|
|
6010
|
+
}
|
|
5736
6011
|
if (def.ground !== "none") {
|
|
5737
6012
|
const own = this.floor[i];
|
|
5738
6013
|
const gy = Number.isNaN(own) ? host.groundAt(x, z) + 5e-3 : own;
|
|
@@ -5818,7 +6093,8 @@ var GameVfxThree = (() => {
|
|
|
5818
6093
|
alpha: 0.35,
|
|
5819
6094
|
fadeIn: 0.15,
|
|
5820
6095
|
cone: 0.6,
|
|
5821
|
-
ground: "none"
|
|
6096
|
+
ground: "none",
|
|
6097
|
+
carried: true
|
|
5822
6098
|
},
|
|
5823
6099
|
sparks: {
|
|
5824
6100
|
id: "sparks",
|
|
@@ -5862,7 +6138,8 @@ var GameVfxThree = (() => {
|
|
|
5862
6138
|
alpha: 0.4,
|
|
5863
6139
|
fadeIn: 0.1,
|
|
5864
6140
|
cone: 0.4,
|
|
5865
|
-
ground: "none"
|
|
6141
|
+
ground: "none",
|
|
6142
|
+
carried: true
|
|
5866
6143
|
},
|
|
5867
6144
|
shards: {
|
|
5868
6145
|
id: "shards",
|
|
@@ -6020,7 +6297,8 @@ var GameVfxThree = (() => {
|
|
|
6020
6297
|
fadeIn: 0.1,
|
|
6021
6298
|
cone: 0.5,
|
|
6022
6299
|
ground: "stop",
|
|
6023
|
-
flutter: 0.6
|
|
6300
|
+
flutter: 0.6,
|
|
6301
|
+
carried: true
|
|
6024
6302
|
},
|
|
6025
6303
|
steam: {
|
|
6026
6304
|
id: "steam",
|
|
@@ -6042,7 +6320,8 @@ var GameVfxThree = (() => {
|
|
|
6042
6320
|
alpha: 0.35,
|
|
6043
6321
|
fadeIn: 0.15,
|
|
6044
6322
|
cone: 0.6,
|
|
6045
|
-
ground: "none"
|
|
6323
|
+
ground: "none",
|
|
6324
|
+
carried: true
|
|
6046
6325
|
},
|
|
6047
6326
|
flash: {
|
|
6048
6327
|
id: "flash",
|
|
@@ -6175,7 +6454,8 @@ var GameVfxThree = (() => {
|
|
|
6175
6454
|
const host = {
|
|
6176
6455
|
groundAt: this.options.groundAt,
|
|
6177
6456
|
gravity: this.options.gravity,
|
|
6178
|
-
land: (owner, x, y, z, color, tag) => this.listeners.get(owner)?.(x, y, z, color, tag)
|
|
6457
|
+
land: (owner, x, y, z, color, tag) => this.listeners.get(owner)?.(x, y, z, color, tag),
|
|
6458
|
+
...this.options.confiner ? { confiner: this.options.confiner } : {}
|
|
6179
6459
|
};
|
|
6180
6460
|
if (this.additive.live > 0 || this.additive.drawCount > 0) this.additive.update(dt, host);
|
|
6181
6461
|
if (this.normal.live > 0 || this.normal.drawCount > 0) this.normal.update(dt, host);
|
|
@@ -6188,9 +6468,9 @@ var GameVfxThree = (() => {
|
|
|
6188
6468
|
var TWO_PI_ROUNDED = 6.2832;
|
|
6189
6469
|
var WIDE_CONE = 3.1;
|
|
6190
6470
|
var UP13 = [0, 1, 0];
|
|
6191
|
-
function drawRange(random,
|
|
6192
|
-
if (Array.isArray(
|
|
6193
|
-
return
|
|
6471
|
+
function drawRange(random, range2) {
|
|
6472
|
+
if (Array.isArray(range2)) return random.between(range2[0], range2[1]);
|
|
6473
|
+
return range2 || 0;
|
|
6194
6474
|
}
|
|
6195
6475
|
function randomUnit(random, out) {
|
|
6196
6476
|
const up = random.next() * 2 - 1;
|
|
@@ -6381,8 +6661,8 @@ var GameVfxThree = (() => {
|
|
|
6381
6661
|
* Takes away the marks inside a box: world `center`, `half` extents along the axes of the world `rotation` (a quaternion, x y z w; none means the
|
|
6382
6662
|
* world axes). The surface they were on is gone (a brick came out of a wall with its bullet holes). Returns how many went.
|
|
6383
6663
|
*/
|
|
6384
|
-
clearInside(center, half,
|
|
6385
|
-
const qx = -
|
|
6664
|
+
clearInside(center, half, rotation2 = [0, 0, 0, 1]) {
|
|
6665
|
+
const qx = -rotation2[0], qy = -rotation2[1], qz = -rotation2[2], qw = rotation2[3];
|
|
6386
6666
|
let gone = 0;
|
|
6387
6667
|
for (const decal2 of this.decals) {
|
|
6388
6668
|
if (!decal2.on) continue;
|
|
@@ -6503,10 +6783,14 @@ var GameVfxThree = (() => {
|
|
|
6503
6783
|
var DEFAULT_FADE_IN = 0.1;
|
|
6504
6784
|
var FLOATS_PER_VECTOR = 3;
|
|
6505
6785
|
var BYTE_MAX2 = 255;
|
|
6786
|
+
var CARRIED_GRAVITY = 3;
|
|
6787
|
+
var PAD_OF_SIZE3 = 0.35;
|
|
6506
6788
|
var SpritePool = class {
|
|
6507
|
-
|
|
6789
|
+
/** `carried`: the normal-blend pool (smoke, dust, steam), whose light sprites go round the closed spaces; the additive one (flames, sparks) does not. */
|
|
6790
|
+
constructor(capacity, context, carried = false) {
|
|
6508
6791
|
__publicField(this, "capacity", capacity);
|
|
6509
6792
|
__publicField(this, "context", context);
|
|
6793
|
+
__publicField(this, "carried", carried);
|
|
6510
6794
|
__publicField(this, "count", 0);
|
|
6511
6795
|
__publicField(this, "position");
|
|
6512
6796
|
__publicField(this, "velocity");
|
|
@@ -6606,6 +6890,7 @@ var GameVfxThree = (() => {
|
|
|
6606
6890
|
}
|
|
6607
6891
|
update(dt, leaveDecal) {
|
|
6608
6892
|
const { position, velocity } = this;
|
|
6893
|
+
const confiner = this.context.confiner;
|
|
6609
6894
|
for (let index = this.count - 1; index >= 0; index--) {
|
|
6610
6895
|
this.life[index] -= dt;
|
|
6611
6896
|
if (this.life[index] <= 0) {
|
|
@@ -6619,9 +6904,25 @@ var GameVfxThree = (() => {
|
|
|
6619
6904
|
velocity[offset] *= factor;
|
|
6620
6905
|
velocity[offset + 1] *= factor;
|
|
6621
6906
|
velocity[offset + 2] *= factor;
|
|
6907
|
+
const x0 = position[offset];
|
|
6908
|
+
const y0 = position[offset + 1];
|
|
6909
|
+
const z0 = position[offset + 2];
|
|
6622
6910
|
position[offset] += velocity[offset] * dt;
|
|
6623
6911
|
position[offset + 1] += velocity[offset + 1] * dt;
|
|
6624
6912
|
position[offset + 2] += velocity[offset + 2] * dt;
|
|
6913
|
+
if (this.carried && confiner && !confiner.empty && Math.abs(this.gravity[index]) < CARRIED_GRAVITY) {
|
|
6914
|
+
const size = this.startSize[index] * (1 + (this.growth[index] - 1) * age);
|
|
6915
|
+
if (confiner.confine(x0, y0, z0, position[offset], position[offset + 1], position[offset + 2], size * PAD_OF_SIZE3, dt)) {
|
|
6916
|
+
const out = confiner.out;
|
|
6917
|
+
position[offset] = out.x;
|
|
6918
|
+
position[offset + 1] = out.y;
|
|
6919
|
+
position[offset + 2] = out.z;
|
|
6920
|
+
const [vx2, vy2, vz2] = slideAlong(out, velocity[offset], velocity[offset + 1], velocity[offset + 2]);
|
|
6921
|
+
velocity[offset] = vx2;
|
|
6922
|
+
velocity[offset + 1] = vy2;
|
|
6923
|
+
velocity[offset + 2] = vz2;
|
|
6924
|
+
}
|
|
6925
|
+
}
|
|
6625
6926
|
const mode = this.groundMode[index];
|
|
6626
6927
|
if (mode) {
|
|
6627
6928
|
const groundHeight = this.context.groundAt(position[offset], position[offset + 2]);
|
|
@@ -6898,9 +7199,9 @@ var GameVfxThree = (() => {
|
|
|
6898
7199
|
__publicField(this, "placement");
|
|
6899
7200
|
__publicField(this, "accumulators", /* @__PURE__ */ new Map());
|
|
6900
7201
|
const profile = options.profile ?? PROFILES.high;
|
|
6901
|
-
this.context = { random: options.random, groundAt: options.groundAt ?? workshopGround, quality: { level: 0, mult: 1 }, trace: options.trace };
|
|
7202
|
+
this.context = { random: options.random, groundAt: options.groundAt ?? workshopGround, quality: { level: 0, mult: 1 }, trace: options.trace, ...options.confiner ? { confiner: options.confiner } : {} };
|
|
6902
7203
|
this.add = new SpritePool(profile.sprites.add, this.context);
|
|
6903
|
-
this.normal = new SpritePool(profile.sprites.normal, this.context);
|
|
7204
|
+
this.normal = new SpritePool(profile.sprites.normal, this.context, true);
|
|
6904
7205
|
this.streaks = new StreakPool(profile.streaks, this.context);
|
|
6905
7206
|
this.debris = new DebrisPool(this.context);
|
|
6906
7207
|
this.decals = new DecalPool(this.context);
|
|
@@ -6936,13 +7237,13 @@ var GameVfxThree = (() => {
|
|
|
6936
7237
|
return [origin[0] + cos2 * x + sin2 * z, origin[1] + point[1] - anchor[1], origin[2] - sin2 * x + cos2 * z];
|
|
6937
7238
|
}
|
|
6938
7239
|
/** A direction or velocity of the recipe's space in the world. */
|
|
6939
|
-
turn(
|
|
7240
|
+
turn(vector2) {
|
|
6940
7241
|
const placement = this.placement;
|
|
6941
|
-
if (!placement) return
|
|
6942
|
-
if (placement.orientation) return rotate(placement.orientation,
|
|
7242
|
+
if (!placement) return vector2;
|
|
7243
|
+
if (placement.orientation) return rotate(placement.orientation, vector2);
|
|
6943
7244
|
const cos2 = Math.cos(placement.yaw);
|
|
6944
7245
|
const sin2 = Math.sin(placement.yaw);
|
|
6945
|
-
return [cos2 *
|
|
7246
|
+
return [cos2 * vector2[0] + sin2 * vector2[2], vector2[1], -sin2 * vector2[0] + cos2 * vector2[2]];
|
|
6946
7247
|
}
|
|
6947
7248
|
placed(options) {
|
|
6948
7249
|
if (!this.placement) return options;
|
|
@@ -7088,12 +7389,14 @@ var GameVfxThree = (() => {
|
|
|
7088
7389
|
const groundAt = options.groundAt ?? (ground ? (x, z) => ground.heightAt(x, z) : () => 0);
|
|
7089
7390
|
const handles = { next: 0, events: 0 };
|
|
7090
7391
|
const low = options.profile === "low";
|
|
7392
|
+
const enclosures = new Enclosures(20973 + (options.seed ?? 0));
|
|
7091
7393
|
const spriteSystem = new SpriteKindSystem({
|
|
7092
7394
|
capacity: options.sprites?.capacity ?? (low ? 1250 : 2500),
|
|
7093
7395
|
density: options.sprites?.density ?? (low ? 0.6 : 1),
|
|
7094
7396
|
seed: 2654435761 + (options.seed ?? 0),
|
|
7095
7397
|
groundAt,
|
|
7096
7398
|
gravity: options.gravity ?? DEFAULT_GRAVITY,
|
|
7399
|
+
confiner: enclosures,
|
|
7097
7400
|
...options.sprites?.kinds ? { kinds: options.sprites.kinds } : {}
|
|
7098
7401
|
});
|
|
7099
7402
|
const core = {
|
|
@@ -7143,7 +7446,7 @@ var GameVfxThree = (() => {
|
|
|
7143
7446
|
return [camera2.x, camera2.y, camera2.z];
|
|
7144
7447
|
}, forward: (local2) => [local2[0] ?? 0, local2[1] ?? 0, local2[2] ?? 0] };
|
|
7145
7448
|
function workshop() {
|
|
7146
|
-
return engine ?? (engine = new WorkshopEngine({ random: sharedRandom, profile, groundAt }));
|
|
7449
|
+
return engine ?? (engine = new WorkshopEngine({ random: sharedRandom, profile, groundAt, confiner: enclosures }));
|
|
7147
7450
|
}
|
|
7148
7451
|
function effectPlayer() {
|
|
7149
7452
|
return player ?? (player = createEffectPlayer({ engine: workshop(), effects, view }));
|
|
@@ -7202,6 +7505,10 @@ var GameVfxThree = (() => {
|
|
|
7202
7505
|
puff3.vz += dz * strength;
|
|
7203
7506
|
}
|
|
7204
7507
|
},
|
|
7508
|
+
enclose(id, enclosure) {
|
|
7509
|
+
enclosures.set(id, enclosure);
|
|
7510
|
+
},
|
|
7511
|
+
enclosures: () => enclosures,
|
|
7205
7512
|
stop(handle) {
|
|
7206
7513
|
player?.stop(handle);
|
|
7207
7514
|
const fires = core.fires;
|
|
@@ -7229,7 +7536,7 @@ var GameVfxThree = (() => {
|
|
|
7229
7536
|
core.clock.time += dt;
|
|
7230
7537
|
core.schedule.update(core.clock.time);
|
|
7231
7538
|
updateRings(core.rings, dt);
|
|
7232
|
-
updatePuffs(core.puffs, dt, wind);
|
|
7539
|
+
updatePuffs(core.puffs, dt, wind, enclosures);
|
|
7233
7540
|
updateSparks(core.sparks, { dt, groundAt });
|
|
7234
7541
|
updateGlows(core.glows, dt);
|
|
7235
7542
|
updateShocks(core.shocks, core.puffs.items, dt);
|
|
@@ -8396,9 +8703,42 @@ void main(){
|
|
|
8396
8703
|
};
|
|
8397
8704
|
}
|
|
8398
8705
|
|
|
8706
|
+
// ../game-render-three/dist/index.js
|
|
8707
|
+
var DEFAULT_ANGLE = Math.PI / 3;
|
|
8708
|
+
var LIGHT_PRIORITY = {
|
|
8709
|
+
blast: 900,
|
|
8710
|
+
rocket: 800,
|
|
8711
|
+
muzzle: 750,
|
|
8712
|
+
fire: 600,
|
|
8713
|
+
flare: 500,
|
|
8714
|
+
headlight: 400,
|
|
8715
|
+
weaponLight: 400,
|
|
8716
|
+
lamp: 200,
|
|
8717
|
+
street: 150
|
|
8718
|
+
};
|
|
8719
|
+
var EFFECT_STEP_SECONDS = 1 / 50;
|
|
8720
|
+
|
|
8399
8721
|
// src/lights.ts
|
|
8400
|
-
|
|
8722
|
+
var LIGHT_ON_THRESHOLD = 0.05;
|
|
8723
|
+
var FIRE_COLOR = 16742954;
|
|
8724
|
+
var FIRE_DECAY = 2;
|
|
8725
|
+
var BLAST_DECAY = 2;
|
|
8726
|
+
function followEntry(budget, handles, index, entry, request) {
|
|
8727
|
+
const handle = handles[index] ?? null;
|
|
8728
|
+
if (entry.intensity <= LIGHT_ON_THRESHOLD) {
|
|
8729
|
+
handle?.release({ fadeMs: 0 });
|
|
8730
|
+
handles[index] = null;
|
|
8731
|
+
return;
|
|
8732
|
+
}
|
|
8733
|
+
if (handle?.alive) {
|
|
8734
|
+
handle.update({ color: request.color, intensity: request.intensity, distance: request.distance, position: request.position });
|
|
8735
|
+
return;
|
|
8736
|
+
}
|
|
8737
|
+
handles[index] = budget.acquire(request);
|
|
8738
|
+
}
|
|
8739
|
+
function createLightLayer(THREE, pool, scale, budget) {
|
|
8401
8740
|
const group = new THREE.Group();
|
|
8741
|
+
if (budget) return createBudgetedLightLayer(group, pool, scale, budget);
|
|
8402
8742
|
const blast = pool.blast.map(() => {
|
|
8403
8743
|
const light = new THREE.PointLight(16752720, 0, 30, 2);
|
|
8404
8744
|
light.position.set(0, -50, 0);
|
|
@@ -8437,6 +8777,30 @@ void main(){
|
|
|
8437
8777
|
}
|
|
8438
8778
|
};
|
|
8439
8779
|
}
|
|
8780
|
+
function createBudgetedLightLayer(group, pool, scale, budget) {
|
|
8781
|
+
const blast = pool.blast.map(() => null);
|
|
8782
|
+
const fire = pool.fire.map(() => null);
|
|
8783
|
+
return {
|
|
8784
|
+
group,
|
|
8785
|
+
sync() {
|
|
8786
|
+
let lit = 0;
|
|
8787
|
+
pool.blast.forEach((entry, index) => {
|
|
8788
|
+
const request = { owner: "vfx.blast", priority: LIGHT_PRIORITY.blast, urgent: true, color: entry.color, intensity: entry.intensity * scale, distance: entry.distance, decay: BLAST_DECAY, position: [entry.x, entry.y, entry.z] };
|
|
8789
|
+
followEntry(budget, blast, index, entry, request);
|
|
8790
|
+
if (entry.intensity > LIGHT_ON_THRESHOLD) lit++;
|
|
8791
|
+
});
|
|
8792
|
+
pool.fire.forEach((entry, index) => {
|
|
8793
|
+
const request = { owner: "vfx.fire", priority: LIGHT_PRIORITY.fire, color: FIRE_COLOR, intensity: entry.intensity * scale, distance: entry.distance, decay: FIRE_DECAY, position: [entry.x, entry.y, entry.z] };
|
|
8794
|
+
followEntry(budget, fire, index, entry, request);
|
|
8795
|
+
if (entry.intensity > LIGHT_ON_THRESHOLD) lit++;
|
|
8796
|
+
});
|
|
8797
|
+
return lit;
|
|
8798
|
+
},
|
|
8799
|
+
dispose() {
|
|
8800
|
+
for (const handle of [...blast, ...fire]) handle?.release({ fadeMs: 0 });
|
|
8801
|
+
}
|
|
8802
|
+
};
|
|
8803
|
+
}
|
|
8440
8804
|
|
|
8441
8805
|
// src/canvas.ts
|
|
8442
8806
|
var SCORCH_SEED = 5;
|
|
@@ -8574,6 +8938,7 @@ void main(){
|
|
|
8574
8938
|
group.add(mesh2);
|
|
8575
8939
|
return mesh2;
|
|
8576
8940
|
}
|
|
8941
|
+
let probeGeometry;
|
|
8577
8942
|
const groundMarks = [];
|
|
8578
8943
|
const spareGeometries = [];
|
|
8579
8944
|
const blood = [];
|
|
@@ -8679,6 +9044,15 @@ void main(){
|
|
|
8679
9044
|
rockMesh();
|
|
8680
9045
|
plateMesh();
|
|
8681
9046
|
},
|
|
9047
|
+
probes() {
|
|
9048
|
+
probeGeometry ?? (probeGeometry = new THREE.PlaneGeometry(1e-3, 1e-3).rotateX(-Math.PI / 2));
|
|
9049
|
+
return [...scorchMaterials, dirtMaterial].map((material) => {
|
|
9050
|
+
const mesh2 = new THREE.Mesh(probeGeometry, material);
|
|
9051
|
+
mesh2.receiveShadow = true;
|
|
9052
|
+
mesh2.frustumCulled = false;
|
|
9053
|
+
return mesh2;
|
|
9054
|
+
});
|
|
9055
|
+
},
|
|
8682
9056
|
update(dt) {
|
|
8683
9057
|
for (let index = 0; index < blood.length; index++) {
|
|
8684
9058
|
const drawn = blood[index];
|
|
@@ -8691,6 +9065,7 @@ void main(){
|
|
|
8691
9065
|
dispose() {
|
|
8692
9066
|
clearMarks();
|
|
8693
9067
|
for (const mesh2 of [instanced.blood, instanced.rock, instanced.plate]) mesh2?.dispose();
|
|
9068
|
+
probeGeometry?.dispose();
|
|
8694
9069
|
for (const item of owned) item.dispose();
|
|
8695
9070
|
}
|
|
8696
9071
|
};
|
|
@@ -9282,7 +9657,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
9282
9657
|
}
|
|
9283
9658
|
};
|
|
9284
9659
|
}
|
|
9285
|
-
function createWorkshopLayers(THREE, engine, pointScale, lightScale) {
|
|
9660
|
+
function createWorkshopLayers(THREE, engine, pointScale, lightScale, budget) {
|
|
9286
9661
|
const group = new THREE.Group();
|
|
9287
9662
|
group.name = "workshop";
|
|
9288
9663
|
const layers = [
|
|
@@ -9297,15 +9672,30 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
9297
9672
|
for (const layer2 of layers) group.add(layer2.object);
|
|
9298
9673
|
const meshes = createMeshLayer(THREE, engine.meshes);
|
|
9299
9674
|
group.add(meshes.group);
|
|
9300
|
-
const
|
|
9301
|
-
const fireLights = engine.lights.fire.map(() => new THREE.PointLight(FIRE_LIGHT_COLOR, 0, FIRE_LIGHT_DISTANCE));
|
|
9302
|
-
for (const light of [...flashLights, ...fireLights]) group.add(light);
|
|
9675
|
+
const lights = budget ? budgetedLights(engine, lightScale, budget) : legacyLights(THREE, engine, lightScale, group);
|
|
9303
9676
|
return {
|
|
9304
9677
|
group,
|
|
9305
9678
|
sync() {
|
|
9306
9679
|
let drawCalls = 0;
|
|
9307
9680
|
for (const layer2 of layers) if (layer2.sync()) drawCalls++;
|
|
9308
9681
|
drawCalls += meshes.sync();
|
|
9682
|
+
lights.sync();
|
|
9683
|
+
return drawCalls;
|
|
9684
|
+
},
|
|
9685
|
+
dispose() {
|
|
9686
|
+
for (const layer2 of layers) layer2.dispose();
|
|
9687
|
+
meshes.dispose();
|
|
9688
|
+
lights.dispose();
|
|
9689
|
+
group.clear();
|
|
9690
|
+
}
|
|
9691
|
+
};
|
|
9692
|
+
}
|
|
9693
|
+
function legacyLights(THREE, engine, lightScale, group) {
|
|
9694
|
+
const flashLights = engine.lights.lights.map(() => new THREE.PointLight(16760944, 0, 14));
|
|
9695
|
+
const fireLights = engine.lights.fire.map(() => new THREE.PointLight(FIRE_LIGHT_COLOR, 0, FIRE_LIGHT_DISTANCE));
|
|
9696
|
+
for (const light of [...flashLights, ...fireLights]) group.add(light);
|
|
9697
|
+
return {
|
|
9698
|
+
sync() {
|
|
9309
9699
|
engine.lights.lights.forEach((source, index) => {
|
|
9310
9700
|
const light = flashLights[index];
|
|
9311
9701
|
light.position.set(source.x, source.y, source.z);
|
|
@@ -9318,12 +9708,27 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
9318
9708
|
light.position.set(source.x, source.y, source.z);
|
|
9319
9709
|
light.intensity = source.intensity * lightScale;
|
|
9320
9710
|
});
|
|
9321
|
-
return drawCalls;
|
|
9322
9711
|
},
|
|
9323
9712
|
dispose() {
|
|
9324
|
-
|
|
9325
|
-
|
|
9326
|
-
|
|
9713
|
+
}
|
|
9714
|
+
};
|
|
9715
|
+
}
|
|
9716
|
+
function budgetedLights(engine, lightScale, budget) {
|
|
9717
|
+
const flash2 = engine.lights.lights.map(() => null);
|
|
9718
|
+
const fire = engine.lights.fire.map(() => null);
|
|
9719
|
+
return {
|
|
9720
|
+
sync() {
|
|
9721
|
+
engine.lights.lights.forEach((source, index) => {
|
|
9722
|
+
const request = { owner: "vfx.workshop", priority: LIGHT_PRIORITY.blast, urgent: true, color: source.color, intensity: source.intensity * lightScale, distance: source.distance, position: [source.x, source.y, source.z] };
|
|
9723
|
+
followEntry(budget, flash2, index, source, request);
|
|
9724
|
+
});
|
|
9725
|
+
engine.lights.fire.forEach((source, index) => {
|
|
9726
|
+
const request = { owner: "vfx.workshop", priority: LIGHT_PRIORITY.fire, color: FIRE_LIGHT_COLOR, intensity: source.intensity * lightScale, distance: FIRE_LIGHT_DISTANCE, position: [source.x, source.y, source.z] };
|
|
9727
|
+
followEntry(budget, fire, index, source, request);
|
|
9728
|
+
});
|
|
9729
|
+
},
|
|
9730
|
+
dispose() {
|
|
9731
|
+
for (const handle of [...flash2, ...fire]) handle?.release({ fadeMs: 0 });
|
|
9327
9732
|
}
|
|
9328
9733
|
};
|
|
9329
9734
|
}
|
|
@@ -9384,7 +9789,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
9384
9789
|
const chunks = createChunkLayer(THREE, pools.chunks, { rock: rockGeometry, plate: plateGeometry }, colorOfChunk);
|
|
9385
9790
|
const shocks = createShockLayer(THREE, pools.shocks);
|
|
9386
9791
|
const sprites = createSpriteLayer(THREE, world.sprites(), options.pointScale ?? 700);
|
|
9387
|
-
const lights = createLightLayer(THREE, pools.lights, options.lightScale ?? Math.PI);
|
|
9792
|
+
const lights = createLightLayer(THREE, pools.lights, options.lightScale ?? Math.PI, options.lights);
|
|
9388
9793
|
const marks = createMarkLayer(THREE, { ground: pools.ground, createCanvas: options.createCanvas, rockGeometry, plateGeometry, ...options.markLimits });
|
|
9389
9794
|
root.add(puffs.mesh, sparks.mesh, glows.mesh, chunks.rocks, chunks.plates, shocks.group, lights.group, sprites.additive, sprites.normal, marks.group);
|
|
9390
9795
|
const stopMarks = world.onMarks((event) => marks.handle(event));
|
|
@@ -9417,7 +9822,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
9417
9822
|
workshopLayers?.dispose();
|
|
9418
9823
|
if (workshopLayers) root.remove(workshopLayers.group);
|
|
9419
9824
|
workshopEngine = engine;
|
|
9420
|
-
workshopLayers = createWorkshopLayers(THREE, engine, options.pointScale ?? 700, 1);
|
|
9825
|
+
workshopLayers = createWorkshopLayers(THREE, engine, options.pointScale ?? 700, 1, options.lights);
|
|
9421
9826
|
root.add(workshopLayers.group);
|
|
9422
9827
|
applyLayers();
|
|
9423
9828
|
}
|
|
@@ -9457,6 +9862,8 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
9457
9862
|
});
|
|
9458
9863
|
},
|
|
9459
9864
|
stop: (handle) => world.stop(handle),
|
|
9865
|
+
// a module's closed space (a shut car's cabin): the world's smoke, dust and steam go round it
|
|
9866
|
+
enclose: (id, enclosure) => world.enclose(id, enclosure),
|
|
9460
9867
|
configure(settings) {
|
|
9461
9868
|
const band = settings.lod_band;
|
|
9462
9869
|
if (typeof band === "string" && band in LOD_BANDS) world.forceLod(LOD_BANDS[band] ?? null);
|
|
@@ -9488,7 +9895,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
9488
9895
|
const meshes = createMeshLayerProbes(THREE);
|
|
9489
9896
|
for (const mesh2 of meshes) mesh2.frustumCulled = false;
|
|
9490
9897
|
const group = new THREE.Group();
|
|
9491
|
-
group.add(...meshes);
|
|
9898
|
+
group.add(...meshes, ...marks.probes());
|
|
9492
9899
|
anchors = { meshes, group };
|
|
9493
9900
|
return { group, dispose: () => {
|
|
9494
9901
|
} };
|