@adatechnology/game-destruction-three 0.12.0 → 0.12.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.global.js +303 -66
- package/dist/index.global.js.map +1 -1
- package/package.json +6 -6
package/dist/index.global.js
CHANGED
|
@@ -1357,11 +1357,231 @@ var GameDestructionThree = (() => {
|
|
|
1357
1357
|
glow.outIntensity = glow.i * Math.pow(1 - age, glow.curve) * flicker;
|
|
1358
1358
|
}
|
|
1359
1359
|
}
|
|
1360
|
+
var LEHMER_MULTIPLIER = 16807;
|
|
1361
|
+
var LEHMER_MODULUS = 2147483647;
|
|
1362
|
+
var HASH_MIX = 2654435761;
|
|
1363
|
+
function normalizeLehmerSeed(seed) {
|
|
1364
|
+
const whole = Math.floor(Math.abs(seed)) % (LEHMER_MODULUS - 1);
|
|
1365
|
+
return whole === 0 ? 1 : whole;
|
|
1366
|
+
}
|
|
1367
|
+
function lehmer(seed) {
|
|
1368
|
+
let state = normalizeLehmerSeed(seed);
|
|
1369
|
+
const next = () => {
|
|
1370
|
+
state = state * LEHMER_MULTIPLIER % LEHMER_MODULUS;
|
|
1371
|
+
return (state - 1) / (LEHMER_MODULUS - 1);
|
|
1372
|
+
};
|
|
1373
|
+
return {
|
|
1374
|
+
next,
|
|
1375
|
+
between: (min2, max2) => min2 + (max2 - min2) * next(),
|
|
1376
|
+
direction(out) {
|
|
1377
|
+
const up = next() * 2 - 1;
|
|
1378
|
+
const angle = next() * Math.PI * 2;
|
|
1379
|
+
const ring2 = Math.sqrt(1 - up * up);
|
|
1380
|
+
out.x = ring2 * Math.cos(angle);
|
|
1381
|
+
out.y = up;
|
|
1382
|
+
out.z = ring2 * Math.sin(angle);
|
|
1383
|
+
return out;
|
|
1384
|
+
},
|
|
1385
|
+
get state() {
|
|
1386
|
+
return state;
|
|
1387
|
+
}
|
|
1388
|
+
};
|
|
1389
|
+
}
|
|
1390
|
+
function mixEventSeed(eventSeed) {
|
|
1391
|
+
let mixed = Math.imul((eventSeed | 0) ^ HASH_MIX, 2246822507);
|
|
1392
|
+
mixed ^= mixed >>> 13;
|
|
1393
|
+
mixed = Math.imul(mixed, 3266489909);
|
|
1394
|
+
mixed ^= mixed >>> 16;
|
|
1395
|
+
return (mixed >>> 0) % (LEHMER_MODULUS - 1) + 1;
|
|
1396
|
+
}
|
|
1397
|
+
function streamFor(eventSeed) {
|
|
1398
|
+
return lehmer(mixEventSeed(eventSeed));
|
|
1399
|
+
}
|
|
1400
|
+
var SKIN = 5e-3;
|
|
1401
|
+
var MAX_PAD = 0.45;
|
|
1402
|
+
function rotation(q) {
|
|
1403
|
+
const [x, y, z, w] = q ?? [0, 0, 0, 1];
|
|
1404
|
+
const n = Math.hypot(x, y, z, w) || 1;
|
|
1405
|
+
const qx = x / n;
|
|
1406
|
+
const qy = y / n;
|
|
1407
|
+
const qz = z / n;
|
|
1408
|
+
const qw = w / n;
|
|
1409
|
+
return new Float64Array([
|
|
1410
|
+
1 - 2 * (qy * qy + qz * qz),
|
|
1411
|
+
2 * (qx * qy - qz * qw),
|
|
1412
|
+
2 * (qx * qz + qy * qw),
|
|
1413
|
+
2 * (qx * qy + qz * qw),
|
|
1414
|
+
1 - 2 * (qx * qx + qz * qz),
|
|
1415
|
+
2 * (qy * qz - qx * qw),
|
|
1416
|
+
2 * (qx * qz - qy * qw),
|
|
1417
|
+
2 * (qy * qz + qx * qw),
|
|
1418
|
+
1 - 2 * (qx * qx + qy * qy)
|
|
1419
|
+
]);
|
|
1420
|
+
}
|
|
1421
|
+
var Enclosures = class {
|
|
1422
|
+
constructor(seed = 20973) {
|
|
1423
|
+
__publicField2(this, "spaces", /* @__PURE__ */ new Map());
|
|
1424
|
+
__publicField2(this, "list", []);
|
|
1425
|
+
__publicField2(this, "random");
|
|
1426
|
+
__publicField2(this, "out", { x: 0, y: 0, z: 0, nx: 0, ny: 0, nz: 0 });
|
|
1427
|
+
__publicField2(this, "l0", new Float64Array(3));
|
|
1428
|
+
__publicField2(this, "l1", new Float64Array(3));
|
|
1429
|
+
__publicField2(this, "q", new Float64Array(3));
|
|
1430
|
+
this.random = lehmer(seed);
|
|
1431
|
+
}
|
|
1432
|
+
get empty() {
|
|
1433
|
+
return this.list.length === 0;
|
|
1434
|
+
}
|
|
1435
|
+
get size() {
|
|
1436
|
+
return this.list.length;
|
|
1437
|
+
}
|
|
1438
|
+
/** Declares, moves or (with `null`) ends the space `id`. */
|
|
1439
|
+
set(id, enclosure) {
|
|
1440
|
+
if (!enclosure) {
|
|
1441
|
+
if (this.spaces.delete(id)) this.list = [...this.spaces.values()];
|
|
1442
|
+
return;
|
|
1443
|
+
}
|
|
1444
|
+
const [hx, hy, hz] = enclosure.halfSize;
|
|
1445
|
+
const space = {
|
|
1446
|
+
cx: enclosure.center[0],
|
|
1447
|
+
cy: enclosure.center[1],
|
|
1448
|
+
cz: enclosure.center[2],
|
|
1449
|
+
hx: Math.abs(hx),
|
|
1450
|
+
hy: Math.abs(hy),
|
|
1451
|
+
hz: Math.abs(hz),
|
|
1452
|
+
r: rotation(enclosure.orientation),
|
|
1453
|
+
radius: Math.hypot(hx, hy, hz),
|
|
1454
|
+
openings: enclosure.openings ?? [],
|
|
1455
|
+
leak: Math.max(0, enclosure.leak ?? 0)
|
|
1456
|
+
};
|
|
1457
|
+
const old = this.spaces.get(id);
|
|
1458
|
+
this.spaces.set(id, space);
|
|
1459
|
+
const at3 = old ? this.list.indexOf(old) : -1;
|
|
1460
|
+
if (at3 >= 0) this.list[at3] = space;
|
|
1461
|
+
else this.list.push(space);
|
|
1462
|
+
}
|
|
1463
|
+
get(id) {
|
|
1464
|
+
const s = this.spaces.get(id);
|
|
1465
|
+
if (!s) return void 0;
|
|
1466
|
+
return { center: [s.cx, s.cy, s.cz], halfSize: [s.hx, s.hy, s.hz], openings: s.openings, leak: s.leak };
|
|
1467
|
+
}
|
|
1468
|
+
ids() {
|
|
1469
|
+
return [...this.spaces.keys()];
|
|
1470
|
+
}
|
|
1471
|
+
clear() {
|
|
1472
|
+
this.spaces.clear();
|
|
1473
|
+
this.list = [];
|
|
1474
|
+
}
|
|
1475
|
+
/** Whether a point is inside any space (on the inside of its walls). */
|
|
1476
|
+
inside(x, y, z) {
|
|
1477
|
+
for (const s of this.list) {
|
|
1478
|
+
this.toLocal(s, x, y, z, this.l0);
|
|
1479
|
+
if (Math.abs(this.l0[0]) <= s.hx && Math.abs(this.l0[1]) <= s.hy && Math.abs(this.l0[2]) <= s.hz) return true;
|
|
1480
|
+
}
|
|
1481
|
+
return false;
|
|
1482
|
+
}
|
|
1483
|
+
toLocal(s, x, y, z, out) {
|
|
1484
|
+
const dx = x - s.cx;
|
|
1485
|
+
const dy = y - s.cy;
|
|
1486
|
+
const dz = z - s.cz;
|
|
1487
|
+
const r = s.r;
|
|
1488
|
+
out[0] = r[0] * dx + r[3] * dy + r[6] * dz;
|
|
1489
|
+
out[1] = r[1] * dx + r[4] * dy + r[7] * dz;
|
|
1490
|
+
out[2] = r[2] * dx + r[5] * dy + r[8] * dz;
|
|
1491
|
+
}
|
|
1492
|
+
/** Passes at `rate` per second. */
|
|
1493
|
+
chance(rate, dt) {
|
|
1494
|
+
return rate > 0 && this.random.next() < 1 - Math.exp(-rate * dt);
|
|
1495
|
+
}
|
|
1496
|
+
/** The opening the wall point `q` (local) is in lets it through now. */
|
|
1497
|
+
through(s, q, dt) {
|
|
1498
|
+
for (const o of s.openings) {
|
|
1499
|
+
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;
|
|
1500
|
+
if (o.rate === void 0 || this.chance(o.rate, dt)) return true;
|
|
1501
|
+
}
|
|
1502
|
+
return this.chance(s.leak, dt);
|
|
1503
|
+
}
|
|
1504
|
+
confine(x0, y0, z0, x1, y1, z1, pad, dt) {
|
|
1505
|
+
const list = this.list;
|
|
1506
|
+
if (list.length === 0) return false;
|
|
1507
|
+
const p = Math.min(Math.max(0, pad), MAX_PAD);
|
|
1508
|
+
const l0 = this.l0;
|
|
1509
|
+
const l1 = this.l1;
|
|
1510
|
+
const q = this.q;
|
|
1511
|
+
for (const s of list) {
|
|
1512
|
+
const reach = s.radius + p + 0.05;
|
|
1513
|
+
const dx = x1 - s.cx;
|
|
1514
|
+
const dy = y1 - s.cy;
|
|
1515
|
+
const dz = z1 - s.cz;
|
|
1516
|
+
if (dx * dx + dy * dy + dz * dz > reach * reach) {
|
|
1517
|
+
const ex = x0 - s.cx;
|
|
1518
|
+
const ey = y0 - s.cy;
|
|
1519
|
+
const ez = z0 - s.cz;
|
|
1520
|
+
if (ex * ex + ey * ey + ez * ez > reach * reach) continue;
|
|
1521
|
+
}
|
|
1522
|
+
this.toLocal(s, x0, y0, z0, l0);
|
|
1523
|
+
this.toLocal(s, x1, y1, z1, l1);
|
|
1524
|
+
const h = [s.hx, s.hy, s.hz];
|
|
1525
|
+
const in0 = Math.abs(l0[0]) <= s.hx && Math.abs(l0[1]) <= s.hy && Math.abs(l0[2]) <= s.hz;
|
|
1526
|
+
let axis2 = 0;
|
|
1527
|
+
let sign = 1;
|
|
1528
|
+
if (in0) {
|
|
1529
|
+
if (Math.abs(l1[0]) <= s.hx && Math.abs(l1[1]) <= s.hy && Math.abs(l1[2]) <= s.hz) continue;
|
|
1530
|
+
for (let a = 0; a < 3; a++) q[a] = Math.min(h[a], Math.max(-h[a], l1[a]));
|
|
1531
|
+
if (this.through(s, q, dt)) continue;
|
|
1532
|
+
let worst = -Infinity;
|
|
1533
|
+
for (let a = 0; a < 3; a++) {
|
|
1534
|
+
const over = Math.abs(l1[a]) - h[a];
|
|
1535
|
+
if (over > worst) {
|
|
1536
|
+
worst = over;
|
|
1537
|
+
axis2 = a;
|
|
1538
|
+
}
|
|
1539
|
+
}
|
|
1540
|
+
sign = l1[axis2] < 0 ? -1 : 1;
|
|
1541
|
+
for (let a = 0; a < 3; a++) l1[a] = Math.min(h[a] - SKIN, Math.max(-(h[a] - SKIN), l1[a]));
|
|
1542
|
+
sign = -sign;
|
|
1543
|
+
} else {
|
|
1544
|
+
const padded0 = Math.abs(l0[0]) <= s.hx + p && Math.abs(l0[1]) <= s.hy + p && Math.abs(l0[2]) <= s.hz + p;
|
|
1545
|
+
const bound = padded0 ? 0 : p;
|
|
1546
|
+
if (!(Math.abs(l1[0]) <= s.hx + bound && Math.abs(l1[1]) <= s.hy + bound && Math.abs(l1[2]) <= s.hz + bound)) continue;
|
|
1547
|
+
for (let a = 0; a < 3; a++) q[a] = Math.min(h[a], Math.max(-h[a], l1[a]));
|
|
1548
|
+
if (this.through(s, q, dt)) continue;
|
|
1549
|
+
let worst = -Infinity;
|
|
1550
|
+
for (let a = 0; a < 3; a++) {
|
|
1551
|
+
const over = Math.abs(l0[a]) - (h[a] + bound);
|
|
1552
|
+
if (over > worst) {
|
|
1553
|
+
worst = over;
|
|
1554
|
+
axis2 = a;
|
|
1555
|
+
}
|
|
1556
|
+
}
|
|
1557
|
+
sign = l0[axis2] < 0 ? -1 : 1;
|
|
1558
|
+
l1[axis2] = sign * (h[axis2] + bound + SKIN);
|
|
1559
|
+
}
|
|
1560
|
+
const r = s.r;
|
|
1561
|
+
const out = this.out;
|
|
1562
|
+
out.x = s.cx + r[0] * l1[0] + r[1] * l1[1] + r[2] * l1[2];
|
|
1563
|
+
out.y = s.cy + r[3] * l1[0] + r[4] * l1[1] + r[5] * l1[2];
|
|
1564
|
+
out.z = s.cz + r[6] * l1[0] + r[7] * l1[1] + r[8] * l1[2];
|
|
1565
|
+
out.nx = r[axis2] * sign;
|
|
1566
|
+
out.ny = r[3 + axis2] * sign;
|
|
1567
|
+
out.nz = r[6 + axis2] * sign;
|
|
1568
|
+
return true;
|
|
1569
|
+
}
|
|
1570
|
+
return false;
|
|
1571
|
+
}
|
|
1572
|
+
};
|
|
1573
|
+
function slideAlong(out, vx2, vy2, vz2) {
|
|
1574
|
+
const into = vx2 * out.nx + vy2 * out.ny + vz2 * out.nz;
|
|
1575
|
+
if (into >= 0) return [vx2, vy2, vz2];
|
|
1576
|
+
return [vx2 - into * out.nx, vy2 - into * out.ny, vz2 - into * out.nz];
|
|
1577
|
+
}
|
|
1360
1578
|
var FLOOR_FRACTION = 0.4;
|
|
1361
1579
|
var FLOOR_BOUNCE = -0.2;
|
|
1362
1580
|
var ARRIVAL_FRAME = 30;
|
|
1363
1581
|
var ARRIVAL_BASE = 0.3;
|
|
1364
1582
|
var GROWTH_CAP_SECONDS = 3.5;
|
|
1583
|
+
var CARRIED_KINDS = [true, true, false, true, false];
|
|
1584
|
+
var PAD_OF_SIZE = 0.35;
|
|
1365
1585
|
function createPuffPool(capacity) {
|
|
1366
1586
|
const placeholder = { next: () => 0, between: (min2) => min2, direction: (out) => out, state: 0 };
|
|
1367
1587
|
return new OrderedPool(capacity, () => ({
|
|
@@ -1456,13 +1676,24 @@ var GameDestructionThree = (() => {
|
|
|
1456
1676
|
if (puff3.vy < 0) puff3.vy *= FLOOR_BOUNCE;
|
|
1457
1677
|
}
|
|
1458
1678
|
}
|
|
1459
|
-
function updatePuffs(pool, dt, wind) {
|
|
1679
|
+
function updatePuffs(pool, dt, wind, confiner) {
|
|
1460
1680
|
pool.compact(ageOrKeep2, dt);
|
|
1681
|
+
const confining = confiner !== void 0 && !confiner.empty;
|
|
1461
1682
|
for (const puff3 of pool.items) {
|
|
1462
1683
|
const age = puff3.t / puff3.life;
|
|
1463
1684
|
const heat = puff3.h0 > 0 ? puff3.h0 * Math.pow(Math.max(0, 1 - puff3.t / puff3.hl), 1.25) : 0;
|
|
1685
|
+
const x0 = puff3.x;
|
|
1686
|
+
const y0 = puff3.y;
|
|
1687
|
+
const z0 = puff3.z;
|
|
1464
1688
|
if (puff3.ring) moveOnRing(puff3, puff3.ring, wind);
|
|
1465
1689
|
else moveFree(puff3, dt, age, heat, wind);
|
|
1690
|
+
if (confining && CARRIED_KINDS[puff3.kind] && confiner.confine(x0, y0, z0, puff3.x, puff3.y, puff3.z, puff3.size * PAD_OF_SIZE, dt)) {
|
|
1691
|
+
const out = confiner.out;
|
|
1692
|
+
puff3.x = out.x;
|
|
1693
|
+
puff3.y = out.y;
|
|
1694
|
+
puff3.z = out.z;
|
|
1695
|
+
[puff3.vx, puff3.vy, puff3.vz] = slideAlong(out, puff3.vx, puff3.vy, puff3.vz);
|
|
1696
|
+
}
|
|
1466
1697
|
const size = puff3.s0 + (puff3.s1 - puff3.s0) * (1 - Math.exp(-puff3.t * puff3.gk)) + puff3.sg * Math.min(puff3.t, GROWTH_CAP_SECONDS);
|
|
1467
1698
|
puff3.size = size * Math.min(1, puff3.t * ARRIVAL_FRAME + ARRIVAL_BASE);
|
|
1468
1699
|
puff3.age = age;
|
|
@@ -1988,10 +2219,10 @@ var GameDestructionThree = (() => {
|
|
|
1988
2219
|
])
|
|
1989
2220
|
]
|
|
1990
2221
|
};
|
|
1991
|
-
function localToWorld(translation,
|
|
2222
|
+
function localToWorld(translation, rotation2, local2) {
|
|
1992
2223
|
const [x, y, z] = local2;
|
|
1993
|
-
const [a, c, e] = [Math.cos(
|
|
1994
|
-
const [b, d, f] = [Math.sin(
|
|
2224
|
+
const [a, c, e] = [Math.cos(rotation2[0]), Math.cos(rotation2[1]), Math.cos(rotation2[2])];
|
|
2225
|
+
const [b, d, f] = [Math.sin(rotation2[0]), Math.sin(rotation2[1]), Math.sin(rotation2[2])];
|
|
1995
2226
|
const [ae, af, be, bf] = [a * e, a * f, b * e, b * f];
|
|
1996
2227
|
return [
|
|
1997
2228
|
c * e * x + -c * f * y + d * z + translation[0],
|
|
@@ -3654,46 +3885,6 @@ var GameDestructionThree = (() => {
|
|
|
3654
3885
|
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];
|
|
3655
3886
|
var WORKSHOP_EFFECTS = Object.fromEntries(ALL_EFFECTS.map((effect) => [effect.id, effect]));
|
|
3656
3887
|
var GAME_EFFECTS = { ...WORKSHOP_EFFECTS, ...Object.fromEntries([...EVENT_EFFECTS, ...VIEWMODEL_EFFECTS, ...VEHICLE_EFFECTS].map((effect) => [effect.id, effect])) };
|
|
3657
|
-
var LEHMER_MULTIPLIER = 16807;
|
|
3658
|
-
var LEHMER_MODULUS = 2147483647;
|
|
3659
|
-
var HASH_MIX = 2654435761;
|
|
3660
|
-
function normalizeLehmerSeed(seed) {
|
|
3661
|
-
const whole = Math.floor(Math.abs(seed)) % (LEHMER_MODULUS - 1);
|
|
3662
|
-
return whole === 0 ? 1 : whole;
|
|
3663
|
-
}
|
|
3664
|
-
function lehmer(seed) {
|
|
3665
|
-
let state = normalizeLehmerSeed(seed);
|
|
3666
|
-
const next = () => {
|
|
3667
|
-
state = state * LEHMER_MULTIPLIER % LEHMER_MODULUS;
|
|
3668
|
-
return (state - 1) / (LEHMER_MODULUS - 1);
|
|
3669
|
-
};
|
|
3670
|
-
return {
|
|
3671
|
-
next,
|
|
3672
|
-
between: (min2, max2) => min2 + (max2 - min2) * next(),
|
|
3673
|
-
direction(out) {
|
|
3674
|
-
const up = next() * 2 - 1;
|
|
3675
|
-
const angle = next() * Math.PI * 2;
|
|
3676
|
-
const ring2 = Math.sqrt(1 - up * up);
|
|
3677
|
-
out.x = ring2 * Math.cos(angle);
|
|
3678
|
-
out.y = up;
|
|
3679
|
-
out.z = ring2 * Math.sin(angle);
|
|
3680
|
-
return out;
|
|
3681
|
-
},
|
|
3682
|
-
get state() {
|
|
3683
|
-
return state;
|
|
3684
|
-
}
|
|
3685
|
-
};
|
|
3686
|
-
}
|
|
3687
|
-
function mixEventSeed(eventSeed) {
|
|
3688
|
-
let mixed = Math.imul((eventSeed | 0) ^ HASH_MIX, 2246822507);
|
|
3689
|
-
mixed ^= mixed >>> 13;
|
|
3690
|
-
mixed = Math.imul(mixed, 3266489909);
|
|
3691
|
-
mixed ^= mixed >>> 16;
|
|
3692
|
-
return (mixed >>> 0) % (LEHMER_MODULUS - 1) + 1;
|
|
3693
|
-
}
|
|
3694
|
-
function streamFor(eventSeed) {
|
|
3695
|
-
return lehmer(mixEventSeed(eventSeed));
|
|
3696
|
-
}
|
|
3697
3888
|
var TABLE = {
|
|
3698
3889
|
concrete: { dust: 9078138, chip: 7236195, spark: 2 },
|
|
3699
3890
|
metal: { dust: 0, chip: 0, spark: 18 },
|
|
@@ -4997,8 +5188,8 @@ var GameDestructionThree = (() => {
|
|
|
4997
5188
|
function addScorch(store, random, x, z, radius) {
|
|
4998
5189
|
const variant = Math.floor(random.next() * SCORCH_VARIANTS);
|
|
4999
5190
|
const lift = 0.03 + nextLift(store) * 1e-3;
|
|
5000
|
-
const
|
|
5001
|
-
store.add({ kind: "scorch", x, z, radius, variant, lift, rotation });
|
|
5191
|
+
const rotation2 = random.next() * 6;
|
|
5192
|
+
store.add({ kind: "scorch", x, z, radius, variant, lift, rotation: rotation2 });
|
|
5002
5193
|
}
|
|
5003
5194
|
function addRimRocks(store, ground, random, x, z, radius) {
|
|
5004
5195
|
const count = Math.round(6 + radius * 7);
|
|
@@ -5027,8 +5218,8 @@ var GameDestructionThree = (() => {
|
|
|
5027
5218
|
function addCrater(store, ground, random, spec) {
|
|
5028
5219
|
ground?.dent(random, spec.x, spec.z, spec.radius, spec.depth);
|
|
5029
5220
|
if (!spec.marks) return;
|
|
5030
|
-
const
|
|
5031
|
-
store.add({ kind: "dirt", x: spec.x, z: spec.z, radius: spec.radius * 1.02, lift: 0.045, rotation });
|
|
5221
|
+
const rotation2 = random.next() * 6;
|
|
5222
|
+
store.add({ kind: "dirt", x: spec.x, z: spec.z, radius: spec.radius * 1.02, lift: 0.045, rotation: rotation2 });
|
|
5032
5223
|
addRimRocks(store, ground, random, spec.x, spec.z, spec.radius);
|
|
5033
5224
|
}
|
|
5034
5225
|
function addBloodSplat(store, ground, random, spec) {
|
|
@@ -5584,6 +5775,7 @@ var GameDestructionThree = (() => {
|
|
|
5584
5775
|
state.gas = Math.max(0, state.gas - dt / DECAY.gasSeconds);
|
|
5585
5776
|
state.beat *= Math.exp(-DECAY.beat * dt);
|
|
5586
5777
|
}
|
|
5778
|
+
var PAD_OF_SIZE2 = 0.35;
|
|
5587
5779
|
var clamp4 = (v, lo, hi) => v < lo ? lo : v > hi ? hi : v;
|
|
5588
5780
|
var lerp4 = (a, b, t) => a + (b - a) * t;
|
|
5589
5781
|
function rgb(hex) {
|
|
@@ -5743,9 +5935,20 @@ var GameDestructionThree = (() => {
|
|
|
5743
5935
|
vy2 *= k;
|
|
5744
5936
|
vz2 *= k;
|
|
5745
5937
|
}
|
|
5746
|
-
|
|
5938
|
+
let x = this.position[i3] + vx2 * dt;
|
|
5747
5939
|
let y = this.position[i3 + 1] + vy2 * dt;
|
|
5748
|
-
|
|
5940
|
+
let z = this.position[i3 + 2] + vz2 * dt;
|
|
5941
|
+
const confiner = host.confiner;
|
|
5942
|
+
if (def.carried && confiner && !confiner.empty) {
|
|
5943
|
+
const pad = this.size0[i] * lerp4(1, def.grow, t) * PAD_OF_SIZE2;
|
|
5944
|
+
if (confiner.confine(this.position[i3], this.position[i3 + 1], this.position[i3 + 2], x, y, z, pad, dt)) {
|
|
5945
|
+
const out = confiner.out;
|
|
5946
|
+
x = out.x;
|
|
5947
|
+
y = out.y;
|
|
5948
|
+
z = out.z;
|
|
5949
|
+
[vx2, vy2, vz2] = slideAlong(out, vx2, vy2, vz2);
|
|
5950
|
+
}
|
|
5951
|
+
}
|
|
5749
5952
|
if (def.ground !== "none") {
|
|
5750
5953
|
const own = this.floor[i];
|
|
5751
5954
|
const gy = Number.isNaN(own) ? host.groundAt(x, z) + 5e-3 : own;
|
|
@@ -5831,7 +6034,8 @@ var GameDestructionThree = (() => {
|
|
|
5831
6034
|
alpha: 0.35,
|
|
5832
6035
|
fadeIn: 0.15,
|
|
5833
6036
|
cone: 0.6,
|
|
5834
|
-
ground: "none"
|
|
6037
|
+
ground: "none",
|
|
6038
|
+
carried: true
|
|
5835
6039
|
},
|
|
5836
6040
|
sparks: {
|
|
5837
6041
|
id: "sparks",
|
|
@@ -5875,7 +6079,8 @@ var GameDestructionThree = (() => {
|
|
|
5875
6079
|
alpha: 0.4,
|
|
5876
6080
|
fadeIn: 0.1,
|
|
5877
6081
|
cone: 0.4,
|
|
5878
|
-
ground: "none"
|
|
6082
|
+
ground: "none",
|
|
6083
|
+
carried: true
|
|
5879
6084
|
},
|
|
5880
6085
|
shards: {
|
|
5881
6086
|
id: "shards",
|
|
@@ -6033,7 +6238,8 @@ var GameDestructionThree = (() => {
|
|
|
6033
6238
|
fadeIn: 0.1,
|
|
6034
6239
|
cone: 0.5,
|
|
6035
6240
|
ground: "stop",
|
|
6036
|
-
flutter: 0.6
|
|
6241
|
+
flutter: 0.6,
|
|
6242
|
+
carried: true
|
|
6037
6243
|
},
|
|
6038
6244
|
steam: {
|
|
6039
6245
|
id: "steam",
|
|
@@ -6055,7 +6261,8 @@ var GameDestructionThree = (() => {
|
|
|
6055
6261
|
alpha: 0.35,
|
|
6056
6262
|
fadeIn: 0.15,
|
|
6057
6263
|
cone: 0.6,
|
|
6058
|
-
ground: "none"
|
|
6264
|
+
ground: "none",
|
|
6265
|
+
carried: true
|
|
6059
6266
|
},
|
|
6060
6267
|
flash: {
|
|
6061
6268
|
id: "flash",
|
|
@@ -6188,7 +6395,8 @@ var GameDestructionThree = (() => {
|
|
|
6188
6395
|
const host = {
|
|
6189
6396
|
groundAt: this.options.groundAt,
|
|
6190
6397
|
gravity: this.options.gravity,
|
|
6191
|
-
land: (owner, x, y, z, color, tag) => this.listeners.get(owner)?.(x, y, z, color, tag)
|
|
6398
|
+
land: (owner, x, y, z, color, tag) => this.listeners.get(owner)?.(x, y, z, color, tag),
|
|
6399
|
+
...this.options.confiner ? { confiner: this.options.confiner } : {}
|
|
6192
6400
|
};
|
|
6193
6401
|
if (this.additive.live > 0 || this.additive.drawCount > 0) this.additive.update(dt, host);
|
|
6194
6402
|
if (this.normal.live > 0 || this.normal.drawCount > 0) this.normal.update(dt, host);
|
|
@@ -6394,8 +6602,8 @@ var GameDestructionThree = (() => {
|
|
|
6394
6602
|
* 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
|
|
6395
6603
|
* world axes). The surface they were on is gone (a brick came out of a wall with its bullet holes). Returns how many went.
|
|
6396
6604
|
*/
|
|
6397
|
-
clearInside(center, half,
|
|
6398
|
-
const qx = -
|
|
6605
|
+
clearInside(center, half, rotation2 = [0, 0, 0, 1]) {
|
|
6606
|
+
const qx = -rotation2[0], qy = -rotation2[1], qz = -rotation2[2], qw = rotation2[3];
|
|
6399
6607
|
let gone = 0;
|
|
6400
6608
|
for (const decal2 of this.decals) {
|
|
6401
6609
|
if (!decal2.on) continue;
|
|
@@ -6516,10 +6724,14 @@ var GameDestructionThree = (() => {
|
|
|
6516
6724
|
var DEFAULT_FADE_IN = 0.1;
|
|
6517
6725
|
var FLOATS_PER_VECTOR = 3;
|
|
6518
6726
|
var BYTE_MAX2 = 255;
|
|
6727
|
+
var CARRIED_GRAVITY = 3;
|
|
6728
|
+
var PAD_OF_SIZE3 = 0.35;
|
|
6519
6729
|
var SpritePool = class {
|
|
6520
|
-
|
|
6730
|
+
/** `carried`: the normal-blend pool (smoke, dust, steam), whose light sprites go round the closed spaces; the additive one (flames, sparks) does not. */
|
|
6731
|
+
constructor(capacity, context, carried = false) {
|
|
6521
6732
|
__publicField2(this, "capacity", capacity);
|
|
6522
6733
|
__publicField2(this, "context", context);
|
|
6734
|
+
__publicField2(this, "carried", carried);
|
|
6523
6735
|
__publicField2(this, "count", 0);
|
|
6524
6736
|
__publicField2(this, "position");
|
|
6525
6737
|
__publicField2(this, "velocity");
|
|
@@ -6619,6 +6831,7 @@ var GameDestructionThree = (() => {
|
|
|
6619
6831
|
}
|
|
6620
6832
|
update(dt, leaveDecal) {
|
|
6621
6833
|
const { position, velocity } = this;
|
|
6834
|
+
const confiner = this.context.confiner;
|
|
6622
6835
|
for (let index = this.count - 1; index >= 0; index--) {
|
|
6623
6836
|
this.life[index] -= dt;
|
|
6624
6837
|
if (this.life[index] <= 0) {
|
|
@@ -6632,9 +6845,25 @@ var GameDestructionThree = (() => {
|
|
|
6632
6845
|
velocity[offset] *= factor;
|
|
6633
6846
|
velocity[offset + 1] *= factor;
|
|
6634
6847
|
velocity[offset + 2] *= factor;
|
|
6848
|
+
const x0 = position[offset];
|
|
6849
|
+
const y0 = position[offset + 1];
|
|
6850
|
+
const z0 = position[offset + 2];
|
|
6635
6851
|
position[offset] += velocity[offset] * dt;
|
|
6636
6852
|
position[offset + 1] += velocity[offset + 1] * dt;
|
|
6637
6853
|
position[offset + 2] += velocity[offset + 2] * dt;
|
|
6854
|
+
if (this.carried && confiner && !confiner.empty && Math.abs(this.gravity[index]) < CARRIED_GRAVITY) {
|
|
6855
|
+
const size = this.startSize[index] * (1 + (this.growth[index] - 1) * age);
|
|
6856
|
+
if (confiner.confine(x0, y0, z0, position[offset], position[offset + 1], position[offset + 2], size * PAD_OF_SIZE3, dt)) {
|
|
6857
|
+
const out = confiner.out;
|
|
6858
|
+
position[offset] = out.x;
|
|
6859
|
+
position[offset + 1] = out.y;
|
|
6860
|
+
position[offset + 2] = out.z;
|
|
6861
|
+
const [vx2, vy2, vz2] = slideAlong(out, velocity[offset], velocity[offset + 1], velocity[offset + 2]);
|
|
6862
|
+
velocity[offset] = vx2;
|
|
6863
|
+
velocity[offset + 1] = vy2;
|
|
6864
|
+
velocity[offset + 2] = vz2;
|
|
6865
|
+
}
|
|
6866
|
+
}
|
|
6638
6867
|
const mode = this.groundMode[index];
|
|
6639
6868
|
if (mode) {
|
|
6640
6869
|
const groundHeight = this.context.groundAt(position[offset], position[offset + 2]);
|
|
@@ -6911,9 +7140,9 @@ var GameDestructionThree = (() => {
|
|
|
6911
7140
|
__publicField2(this, "placement");
|
|
6912
7141
|
__publicField2(this, "accumulators", /* @__PURE__ */ new Map());
|
|
6913
7142
|
const profile = options.profile ?? PROFILES.high;
|
|
6914
|
-
this.context = { random: options.random, groundAt: options.groundAt ?? workshopGround, quality: { level: 0, mult: 1 }, trace: options.trace };
|
|
7143
|
+
this.context = { random: options.random, groundAt: options.groundAt ?? workshopGround, quality: { level: 0, mult: 1 }, trace: options.trace, ...options.confiner ? { confiner: options.confiner } : {} };
|
|
6915
7144
|
this.add = new SpritePool(profile.sprites.add, this.context);
|
|
6916
|
-
this.normal = new SpritePool(profile.sprites.normal, this.context);
|
|
7145
|
+
this.normal = new SpritePool(profile.sprites.normal, this.context, true);
|
|
6917
7146
|
this.streaks = new StreakPool(profile.streaks, this.context);
|
|
6918
7147
|
this.debris = new DebrisPool(this.context);
|
|
6919
7148
|
this.decals = new DecalPool(this.context);
|
|
@@ -7101,12 +7330,14 @@ var GameDestructionThree = (() => {
|
|
|
7101
7330
|
const groundAt = options.groundAt ?? (ground ? (x, z) => ground.heightAt(x, z) : () => 0);
|
|
7102
7331
|
const handles = { next: 0, events: 0 };
|
|
7103
7332
|
const low = options.profile === "low";
|
|
7333
|
+
const enclosures = new Enclosures(20973 + (options.seed ?? 0));
|
|
7104
7334
|
const spriteSystem = new SpriteKindSystem({
|
|
7105
7335
|
capacity: options.sprites?.capacity ?? (low ? 1250 : 2500),
|
|
7106
7336
|
density: options.sprites?.density ?? (low ? 0.6 : 1),
|
|
7107
7337
|
seed: 2654435761 + (options.seed ?? 0),
|
|
7108
7338
|
groundAt,
|
|
7109
7339
|
gravity: options.gravity ?? DEFAULT_GRAVITY,
|
|
7340
|
+
confiner: enclosures,
|
|
7110
7341
|
...options.sprites?.kinds ? { kinds: options.sprites.kinds } : {}
|
|
7111
7342
|
});
|
|
7112
7343
|
const core = {
|
|
@@ -7156,7 +7387,7 @@ var GameDestructionThree = (() => {
|
|
|
7156
7387
|
return [camera2.x, camera2.y, camera2.z];
|
|
7157
7388
|
}, forward: (local2) => [local2[0] ?? 0, local2[1] ?? 0, local2[2] ?? 0] };
|
|
7158
7389
|
function workshop() {
|
|
7159
|
-
return engine ?? (engine = new WorkshopEngine({ random: sharedRandom, profile, groundAt }));
|
|
7390
|
+
return engine ?? (engine = new WorkshopEngine({ random: sharedRandom, profile, groundAt, confiner: enclosures }));
|
|
7160
7391
|
}
|
|
7161
7392
|
function effectPlayer() {
|
|
7162
7393
|
return player ?? (player = createEffectPlayer({ engine: workshop(), effects, view }));
|
|
@@ -7215,6 +7446,10 @@ var GameDestructionThree = (() => {
|
|
|
7215
7446
|
puff3.vz += dz * strength;
|
|
7216
7447
|
}
|
|
7217
7448
|
},
|
|
7449
|
+
enclose(id, enclosure) {
|
|
7450
|
+
enclosures.set(id, enclosure);
|
|
7451
|
+
},
|
|
7452
|
+
enclosures: () => enclosures,
|
|
7218
7453
|
stop(handle) {
|
|
7219
7454
|
player?.stop(handle);
|
|
7220
7455
|
const fires = core.fires;
|
|
@@ -7242,7 +7477,7 @@ var GameDestructionThree = (() => {
|
|
|
7242
7477
|
core.clock.time += dt;
|
|
7243
7478
|
core.schedule.update(core.clock.time);
|
|
7244
7479
|
updateRings(core.rings, dt);
|
|
7245
|
-
updatePuffs(core.puffs, dt, wind);
|
|
7480
|
+
updatePuffs(core.puffs, dt, wind, enclosures);
|
|
7246
7481
|
updateSparks(core.sparks, { dt, groundAt });
|
|
7247
7482
|
updateGlows(core.glows, dt);
|
|
7248
7483
|
updateShocks(core.shocks, core.puffs.items, dt);
|
|
@@ -8642,6 +8877,8 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
8642
8877
|
});
|
|
8643
8878
|
},
|
|
8644
8879
|
stop: (handle) => world.stop(handle),
|
|
8880
|
+
// a module's closed space (a shut car's cabin): the world's smoke, dust and steam go round it
|
|
8881
|
+
enclose: (id, enclosure) => world.enclose(id, enclosure),
|
|
8645
8882
|
configure(settings) {
|
|
8646
8883
|
const band = settings.lod_band;
|
|
8647
8884
|
if (typeof band === "string" && band in LOD_BANDS) world.forceLod(LOD_BANDS[band] ?? null);
|
|
@@ -11922,8 +12159,8 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
11922
12159
|
* Takes away the decals of a mesh that sit inside a box (world `center`, `half` extents along the axes of the world `rotation`): the surface they
|
|
11923
12160
|
* marked is gone (a unit came out of the wall with its bullet holes and spalls).
|
|
11924
12161
|
*/
|
|
11925
|
-
clearDecals(mv, center, half,
|
|
11926
|
-
const inv =
|
|
12162
|
+
clearDecals(mv, center, half, rotation2) {
|
|
12163
|
+
const inv = rotation2.clone().invert();
|
|
11927
12164
|
const p = new this.THREE.Vector3();
|
|
11928
12165
|
for (let i = mv.decals.length - 1; i >= 0; i--) {
|
|
11929
12166
|
const d = mv.decals[i];
|
|
@@ -13364,8 +13601,8 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
13364
13601
|
const T = this.THREE;
|
|
13365
13602
|
const center = new T.Vector3(ev.center[0], ev.center[1], ev.center[2]);
|
|
13366
13603
|
const half = new T.Vector3(ev.size[0] / 2 + CHIP_DECAL_EDGE, ev.size[1] / 2 + CHIP_DECAL_EDGE, ev.size[2] / 2 + CHIP_DECAL_EDGE);
|
|
13367
|
-
const
|
|
13368
|
-
for (const part of this.bounds.get(ev.object)?.parts.values() ?? []) for (const mv of part.meshes) this.visuals.clearDecals(mv, center, half,
|
|
13604
|
+
const rotation2 = new T.Quaternion(ev.rotation[0], ev.rotation[1], ev.rotation[2], ev.rotation[3]);
|
|
13605
|
+
for (const part of this.bounds.get(ev.object)?.parts.values() ?? []) for (const mv of part.meshes) this.visuals.clearDecals(mv, center, half, rotation2);
|
|
13369
13606
|
this.vfx.peekWorkshop()?.decals.clearInside(ev.center, [half.x, half.y, half.z], ev.rotation);
|
|
13370
13607
|
this.vfx.burst("dust", ev.center, [0, 1, 0], 8, 0.8, { color });
|
|
13371
13608
|
this.sound(impactKey(def), ev.center, 0.7);
|