@adatechnology/game-destruction 0.10.0 → 0.12.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 +39 -1
- package/dist/index.global.js +398 -34
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +398 -34
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -376,7 +376,9 @@ var severAt = (inp, root, at, gap) => {
|
|
|
376
376
|
const band = { c: [root.c[0], root.c[1], root.c[2]], s: [dims[0], dims[1], dims[2]] };
|
|
377
377
|
band.c[L] = (lo + hi) / 2;
|
|
378
378
|
band.s[L] = Math.max(hi - lo, 0.01);
|
|
379
|
-
|
|
379
|
+
if (inp.style === "snap") {
|
|
380
|
+
for (const b of bsp(band, Math.max(3, Math.min(6, inp.maxFragments - out.length)), [0, 1, 2], inp.rnd)) out.push({ center: b.c, size: b.s, q: quat.identity(), shape: "chunk", weight: b.s[0] * b.s[1] * b.s[2] });
|
|
381
|
+
} else for (const p of splinterBox(inp, band, Math.max(3, inp.maxFragments - out.length))) out.push(p);
|
|
380
382
|
return out;
|
|
381
383
|
};
|
|
382
384
|
var tearStack = (inp, root, t, u, v, n, sheet) => {
|
|
@@ -407,6 +409,7 @@ var planFragments = (inp) => {
|
|
|
407
409
|
const t = sorted[0];
|
|
408
410
|
const [u, v] = [sorted[1], sorted[2]].sort((a, b) => a - b);
|
|
409
411
|
if (style === "snap") {
|
|
412
|
+
if (inp.cut) return severAt(inp, root, inp.cut.at, inp.cut.gap);
|
|
410
413
|
const n2 = Math.min(maxFragments, 2 + Math.floor(rnd() * 3));
|
|
411
414
|
for (const b of bsp(root, n2, [0, 1, 2], rnd)) out.push({ center: b.c, size: b.s, q: idq, shape: "slab", weight: b.s[0] * b.s[1] * b.s[2] });
|
|
412
415
|
return out;
|
|
@@ -586,6 +589,27 @@ var rebarBars = (dims, thin, spacing) => {
|
|
|
586
589
|
for (const x of spread(dims[u], COVER, spacing, MAX_BARS_PER_DIRECTION)) out.push(bar(v, dims[v] / 2 - 0.02, [[u, x], [thin, 0]]));
|
|
587
590
|
return out;
|
|
588
591
|
};
|
|
592
|
+
var clipBarsToBox = (bars, u, v, center, size) => {
|
|
593
|
+
const out = [];
|
|
594
|
+
for (const [a, b] of bars) {
|
|
595
|
+
const axis = a[u] !== b[u] ? u : v;
|
|
596
|
+
const other = axis === u ? v : u;
|
|
597
|
+
if (Math.abs(a[other] - center[other]) > size[other] / 2) continue;
|
|
598
|
+
const lo = Math.max(Math.min(a[axis], b[axis]), center[axis] - size[axis] / 2), hi = Math.min(Math.max(a[axis], b[axis]), center[axis] + size[axis] / 2);
|
|
599
|
+
if (hi - lo < 1e-6) continue;
|
|
600
|
+
const p = [a[0], a[1], a[2]], q = [b[0], b[1], b[2]];
|
|
601
|
+
p[axis] = lo;
|
|
602
|
+
q[axis] = hi;
|
|
603
|
+
out.push([p, q]);
|
|
604
|
+
}
|
|
605
|
+
return out;
|
|
606
|
+
};
|
|
607
|
+
var bendBar = ([a, b], thin, bow, i) => {
|
|
608
|
+
const length = Math.hypot(b[0] - a[0], b[1] - a[1], b[2] - a[2]);
|
|
609
|
+
const m = [(a[0] + b[0]) / 2, (a[1] + b[1]) / 2, (a[2] + b[2]) / 2];
|
|
610
|
+
m[thin] += (i % 2 === 0 ? 1 : -1) * bow * length;
|
|
611
|
+
return [[a, m], [m, b]];
|
|
612
|
+
};
|
|
589
613
|
var clipBarsToDisc = (bars, u, v, center, radius) => {
|
|
590
614
|
const out = [];
|
|
591
615
|
for (const [a, b] of bars) {
|
|
@@ -1563,14 +1587,21 @@ var materials_default = [
|
|
|
1563
1587
|
smoke: "grey"
|
|
1564
1588
|
},
|
|
1565
1589
|
visual: {
|
|
1566
|
-
charColor: 1709072
|
|
1590
|
+
charColor: 1709072,
|
|
1591
|
+
innerColor: 14730131
|
|
1567
1592
|
},
|
|
1568
1593
|
tags: [
|
|
1569
1594
|
"wood",
|
|
1570
1595
|
"organic",
|
|
1571
1596
|
"flammable"
|
|
1572
1597
|
],
|
|
1573
|
-
compressive: 1e5
|
|
1598
|
+
compressive: 1e5,
|
|
1599
|
+
hits: {
|
|
1600
|
+
blunt: {
|
|
1601
|
+
tear: "splinters",
|
|
1602
|
+
tearJoules: 60
|
|
1603
|
+
}
|
|
1604
|
+
}
|
|
1574
1605
|
},
|
|
1575
1606
|
{
|
|
1576
1607
|
id: "wood_hard",
|
|
@@ -1600,14 +1631,21 @@ var materials_default = [
|
|
|
1600
1631
|
smoke: "grey"
|
|
1601
1632
|
},
|
|
1602
1633
|
visual: {
|
|
1603
|
-
charColor: 1709072
|
|
1634
|
+
charColor: 1709072,
|
|
1635
|
+
innerColor: 13213802
|
|
1604
1636
|
},
|
|
1605
1637
|
tags: [
|
|
1606
1638
|
"wood",
|
|
1607
1639
|
"organic",
|
|
1608
1640
|
"flammable"
|
|
1609
1641
|
],
|
|
1610
|
-
compressive: 15e4
|
|
1642
|
+
compressive: 15e4,
|
|
1643
|
+
hits: {
|
|
1644
|
+
blunt: {
|
|
1645
|
+
tear: "splinters",
|
|
1646
|
+
tearJoules: 150
|
|
1647
|
+
}
|
|
1648
|
+
}
|
|
1611
1649
|
},
|
|
1612
1650
|
{
|
|
1613
1651
|
id: "plywood",
|
|
@@ -1637,14 +1675,24 @@ var materials_default = [
|
|
|
1637
1675
|
smoke: "grey"
|
|
1638
1676
|
},
|
|
1639
1677
|
visual: {
|
|
1640
|
-
charColor: 1709072
|
|
1678
|
+
charColor: 1709072,
|
|
1679
|
+
innerColor: 14862234
|
|
1641
1680
|
},
|
|
1642
1681
|
tags: [
|
|
1643
1682
|
"wood",
|
|
1644
1683
|
"organic",
|
|
1645
1684
|
"flammable"
|
|
1646
1685
|
],
|
|
1647
|
-
compressive: 6e4
|
|
1686
|
+
compressive: 6e4,
|
|
1687
|
+
hits: {
|
|
1688
|
+
ballistic: {
|
|
1689
|
+
tear: "splinters"
|
|
1690
|
+
},
|
|
1691
|
+
blunt: {
|
|
1692
|
+
tear: "splinters",
|
|
1693
|
+
tearJoules: 80
|
|
1694
|
+
}
|
|
1695
|
+
}
|
|
1648
1696
|
},
|
|
1649
1697
|
{
|
|
1650
1698
|
id: "mdf",
|
|
@@ -1671,14 +1719,25 @@ var materials_default = [
|
|
|
1671
1719
|
smoke: "grey"
|
|
1672
1720
|
},
|
|
1673
1721
|
visual: {
|
|
1674
|
-
charColor: 1709072
|
|
1722
|
+
charColor: 1709072,
|
|
1723
|
+
innerColor: 12096362
|
|
1675
1724
|
},
|
|
1676
1725
|
tags: [
|
|
1677
1726
|
"wood",
|
|
1678
1727
|
"organic",
|
|
1679
1728
|
"flammable"
|
|
1680
1729
|
],
|
|
1681
|
-
compressive: 3e4
|
|
1730
|
+
compressive: 3e4,
|
|
1731
|
+
hits: {
|
|
1732
|
+
ballistic: {
|
|
1733
|
+
tear: "lumps",
|
|
1734
|
+
tearJoules: 120
|
|
1735
|
+
},
|
|
1736
|
+
blunt: {
|
|
1737
|
+
tear: "lumps",
|
|
1738
|
+
tearJoules: 20
|
|
1739
|
+
}
|
|
1740
|
+
}
|
|
1682
1741
|
},
|
|
1683
1742
|
{
|
|
1684
1743
|
id: "glass",
|
|
@@ -1792,8 +1851,20 @@ var materials_default = [
|
|
|
1792
1851
|
damageScale: {
|
|
1793
1852
|
explosive: 1.2
|
|
1794
1853
|
},
|
|
1854
|
+
hits: {
|
|
1855
|
+
ballistic: {
|
|
1856
|
+
unitJoules: 500,
|
|
1857
|
+
floor: 900,
|
|
1858
|
+
crater: true
|
|
1859
|
+
},
|
|
1860
|
+
blunt: {
|
|
1861
|
+
unitJoules: 1500,
|
|
1862
|
+
floor: 60
|
|
1863
|
+
}
|
|
1864
|
+
},
|
|
1795
1865
|
hitDebris: "chips",
|
|
1796
1866
|
breakDebris: "dust",
|
|
1867
|
+
visual: { innerColor: 10197652 },
|
|
1797
1868
|
thermal: {
|
|
1798
1869
|
conductivity: 0.15,
|
|
1799
1870
|
heatCapacity: 2.5
|
|
@@ -1824,6 +1895,7 @@ var materials_default = [
|
|
|
1824
1895
|
],
|
|
1825
1896
|
hitDebris: "chips",
|
|
1826
1897
|
breakDebris: "dust",
|
|
1898
|
+
visual: { innerColor: 12085567 },
|
|
1827
1899
|
thermal: {
|
|
1828
1900
|
conductivity: 0.15,
|
|
1829
1901
|
heatCapacity: 2.5
|
|
@@ -1854,6 +1926,7 @@ var materials_default = [
|
|
|
1854
1926
|
],
|
|
1855
1927
|
hitDebris: "dust",
|
|
1856
1928
|
breakDebris: "dust",
|
|
1929
|
+
visual: { innerColor: 14999507 },
|
|
1857
1930
|
thermal: {
|
|
1858
1931
|
conductivity: 0.1,
|
|
1859
1932
|
heatCapacity: 1.5
|
|
@@ -1879,6 +1952,7 @@ var materials_default = [
|
|
|
1879
1952
|
],
|
|
1880
1953
|
hitDebris: "chips",
|
|
1881
1954
|
breakDebris: "dust",
|
|
1955
|
+
visual: { innerColor: 9407364 },
|
|
1882
1956
|
thermal: {
|
|
1883
1957
|
conductivity: 0.2,
|
|
1884
1958
|
heatCapacity: 2.5
|
|
@@ -2160,7 +2234,8 @@ var materials_default = [
|
|
|
2160
2234
|
smoke: "white"
|
|
2161
2235
|
},
|
|
2162
2236
|
visual: {
|
|
2163
|
-
charColor: 1709072
|
|
2237
|
+
charColor: 1709072,
|
|
2238
|
+
innerColor: 14207126
|
|
2164
2239
|
},
|
|
2165
2240
|
tags: [
|
|
2166
2241
|
"plant",
|
|
@@ -2168,7 +2243,12 @@ var materials_default = [
|
|
|
2168
2243
|
"organic",
|
|
2169
2244
|
"flammable"
|
|
2170
2245
|
],
|
|
2171
|
-
compressive: 6e4
|
|
2246
|
+
compressive: 6e4,
|
|
2247
|
+
hits: {
|
|
2248
|
+
blunt: {
|
|
2249
|
+
tear: "none"
|
|
2250
|
+
}
|
|
2251
|
+
}
|
|
2172
2252
|
},
|
|
2173
2253
|
{
|
|
2174
2254
|
id: "cactus",
|
|
@@ -2283,6 +2363,130 @@ var materials_default = [
|
|
|
2283
2363
|
"masonry"
|
|
2284
2364
|
],
|
|
2285
2365
|
compressive: 2e4
|
|
2366
|
+
},
|
|
2367
|
+
{
|
|
2368
|
+
id: "asphalt",
|
|
2369
|
+
density: 2350,
|
|
2370
|
+
hpPerKg: 10,
|
|
2371
|
+
penetration: 14,
|
|
2372
|
+
penetrationClass: "concrete",
|
|
2373
|
+
penetrationScale: 0.8,
|
|
2374
|
+
ductility: 0.1,
|
|
2375
|
+
fracture: "crumble",
|
|
2376
|
+
fragmentSize: [
|
|
2377
|
+
0.03,
|
|
2378
|
+
0.15
|
|
2379
|
+
],
|
|
2380
|
+
hitDebris: "chips",
|
|
2381
|
+
breakDebris: "dust",
|
|
2382
|
+
thermal: {
|
|
2383
|
+
conductivity: 0.1,
|
|
2384
|
+
heatCapacity: 2,
|
|
2385
|
+
ignitionC: 400,
|
|
2386
|
+
burnRate: 2e-3,
|
|
2387
|
+
smoke: "black"
|
|
2388
|
+
},
|
|
2389
|
+
tags: [
|
|
2390
|
+
"masonry",
|
|
2391
|
+
"brittle"
|
|
2392
|
+
],
|
|
2393
|
+
compressive: 3e4
|
|
2394
|
+
},
|
|
2395
|
+
{
|
|
2396
|
+
id: "sand",
|
|
2397
|
+
density: 1600,
|
|
2398
|
+
hpPerKg: 2,
|
|
2399
|
+
penetration: 6,
|
|
2400
|
+
ductility: 0.4,
|
|
2401
|
+
fracture: "crumble",
|
|
2402
|
+
fragmentSize: [
|
|
2403
|
+
0.01,
|
|
2404
|
+
0.04
|
|
2405
|
+
],
|
|
2406
|
+
hitDebris: "dust",
|
|
2407
|
+
breakDebris: "dust",
|
|
2408
|
+
thermal: {
|
|
2409
|
+
conductivity: 0.1,
|
|
2410
|
+
heatCapacity: 2
|
|
2411
|
+
},
|
|
2412
|
+
tags: [
|
|
2413
|
+
"soil"
|
|
2414
|
+
],
|
|
2415
|
+
compressive: 1e4
|
|
2416
|
+
},
|
|
2417
|
+
{
|
|
2418
|
+
id: "gravel",
|
|
2419
|
+
density: 1800,
|
|
2420
|
+
hpPerKg: 3,
|
|
2421
|
+
penetration: 8,
|
|
2422
|
+
ductility: 0.3,
|
|
2423
|
+
fracture: "crumble",
|
|
2424
|
+
fragmentSize: [
|
|
2425
|
+
0.02,
|
|
2426
|
+
0.06
|
|
2427
|
+
],
|
|
2428
|
+
hitDebris: "chips",
|
|
2429
|
+
breakDebris: "dust",
|
|
2430
|
+
thermal: {
|
|
2431
|
+
conductivity: 0.1,
|
|
2432
|
+
heatCapacity: 2
|
|
2433
|
+
},
|
|
2434
|
+
tags: [
|
|
2435
|
+
"soil",
|
|
2436
|
+
"masonry"
|
|
2437
|
+
],
|
|
2438
|
+
compressive: 2e4
|
|
2439
|
+
},
|
|
2440
|
+
{
|
|
2441
|
+
id: "turf",
|
|
2442
|
+
density: 900,
|
|
2443
|
+
hpPerKg: 3,
|
|
2444
|
+
penetration: 4,
|
|
2445
|
+
ductility: 0.5,
|
|
2446
|
+
fracture: "crumble",
|
|
2447
|
+
fragmentSize: [
|
|
2448
|
+
0.03,
|
|
2449
|
+
0.1
|
|
2450
|
+
],
|
|
2451
|
+
hitDebris: "dust",
|
|
2452
|
+
breakDebris: "dust",
|
|
2453
|
+
thermal: {
|
|
2454
|
+
conductivity: 0.1,
|
|
2455
|
+
heatCapacity: 1.5,
|
|
2456
|
+
ignitionC: 250,
|
|
2457
|
+
burnRate: 0.03,
|
|
2458
|
+
smoke: "white"
|
|
2459
|
+
},
|
|
2460
|
+
tags: [
|
|
2461
|
+
"soil",
|
|
2462
|
+
"organic"
|
|
2463
|
+
],
|
|
2464
|
+
compressive: 15e3
|
|
2465
|
+
},
|
|
2466
|
+
{
|
|
2467
|
+
id: "mortar",
|
|
2468
|
+
density: 1900,
|
|
2469
|
+
hpPerKg: 10,
|
|
2470
|
+
penetration: 12,
|
|
2471
|
+
penetrationClass: "concrete",
|
|
2472
|
+
penetrationScale: 1.2,
|
|
2473
|
+
ductility: 0.03,
|
|
2474
|
+
fracture: "crumble",
|
|
2475
|
+
fragmentSize: [
|
|
2476
|
+
0.02,
|
|
2477
|
+
0.08
|
|
2478
|
+
],
|
|
2479
|
+
hitDebris: "chips",
|
|
2480
|
+
breakDebris: "dust",
|
|
2481
|
+
thermal: {
|
|
2482
|
+
conductivity: 0.15,
|
|
2483
|
+
heatCapacity: 2.5
|
|
2484
|
+
},
|
|
2485
|
+
tags: [
|
|
2486
|
+
"masonry",
|
|
2487
|
+
"brittle"
|
|
2488
|
+
],
|
|
2489
|
+
compressive: 1e5
|
|
2286
2490
|
}
|
|
2287
2491
|
];
|
|
2288
2492
|
|
|
@@ -2468,6 +2672,32 @@ var fragility = (ductility, thickness) => {
|
|
|
2468
2672
|
// src/world.ts
|
|
2469
2673
|
import { ignitionChance, resolveIgnitionRules, sparkTargetFactor } from "@adatechnology/game-contracts";
|
|
2470
2674
|
var THIN_SHEET_DISHING = 5e-3;
|
|
2675
|
+
var SWEEP_BACK = 0.01;
|
|
2676
|
+
function sweepOrigins(box, d, spacing) {
|
|
2677
|
+
const origins = [];
|
|
2678
|
+
const line = (from, to) => {
|
|
2679
|
+
const n = Math.max(1, Math.ceil((to - from) / spacing));
|
|
2680
|
+
return Array.from({ length: n + 1 }, (_, i) => from + (to - from) * i / n);
|
|
2681
|
+
};
|
|
2682
|
+
for (const axis of [0, 1, 2]) {
|
|
2683
|
+
if (Math.abs(d[axis]) < 1e-3) continue;
|
|
2684
|
+
const lead = d[axis] > 0 ? box.max[axis] - SWEEP_BACK : box.min[axis] + SWEEP_BACK;
|
|
2685
|
+
const u = (axis + 1) % 3;
|
|
2686
|
+
const v = (axis + 2) % 3;
|
|
2687
|
+
for (const a of line(box.min[u], box.max[u])) {
|
|
2688
|
+
for (const b of line(box.min[v], box.max[v])) {
|
|
2689
|
+
const point = [0, 0, 0];
|
|
2690
|
+
point[axis] = lead;
|
|
2691
|
+
point[u] = a;
|
|
2692
|
+
point[v] = b;
|
|
2693
|
+
origins.push(point);
|
|
2694
|
+
}
|
|
2695
|
+
}
|
|
2696
|
+
}
|
|
2697
|
+
return origins;
|
|
2698
|
+
}
|
|
2699
|
+
var THIN_SHEET_CRUSH = 5e-4;
|
|
2700
|
+
var THIN_SHEET_CONTACT = 0.025;
|
|
2471
2701
|
var DMG_PER_J = 0.02;
|
|
2472
2702
|
var BLAST_COUPLING = 0.1;
|
|
2473
2703
|
var SHELTER_DEFAULTS = { k: 2800, brokenTransmission: 0.5, minPath: 5e-3 };
|
|
@@ -2484,11 +2714,15 @@ var RESIDUAL_CAPACITY = 0.15;
|
|
|
2484
2714
|
var SEVER_BAND = 0.1;
|
|
2485
2715
|
var SEVER_ASPECT = 3;
|
|
2486
2716
|
var SEVER_BALLISTIC = 2;
|
|
2717
|
+
var TEAR_JOULES = 150;
|
|
2718
|
+
var tears = 0;
|
|
2487
2719
|
var SUPPORT_TOLERANCE = 0.05;
|
|
2488
2720
|
var UNIT_FRAGMENT_FACTOR = 4;
|
|
2489
2721
|
var BREACH_GRID_CAP = 4096;
|
|
2490
2722
|
var CHIP_ENERGY = 200;
|
|
2491
2723
|
var CHIP_SPLASH = 0.5;
|
|
2724
|
+
var BAR_BOW = 0.08;
|
|
2725
|
+
var BULLET_JOINT_SPAN = 0.3;
|
|
2492
2726
|
var CUT_SLICE = 1;
|
|
2493
2727
|
var cutFactorOf = (shape) => clamp2(Math.max(...shapeDims(shape)) / CUT_SLICE, 1, 50);
|
|
2494
2728
|
var clamp2 = (v, a, b) => Math.max(a, Math.min(b, v));
|
|
@@ -2498,8 +2732,24 @@ var penetrationOf = (mat, table) => {
|
|
|
2498
2732
|
return v === void 0 ? void 0 : v * (mat.penetrationScale ?? 1);
|
|
2499
2733
|
};
|
|
2500
2734
|
var capacityScale = (p) => {
|
|
2501
|
-
|
|
2502
|
-
|
|
2735
|
+
const residual = p.spec.reinforcement?.residualCapacity ?? RESIDUAL_CAPACITY;
|
|
2736
|
+
if (p.st.stripped) return residual;
|
|
2737
|
+
const kept = Math.min(p.rt.removed ? 1 - p.rt.removed / p.mass0 : 1, 1 - sectionLoss(p));
|
|
2738
|
+
return Math.max(p.spec.reinforcement ? residual : 0.05, kept);
|
|
2739
|
+
};
|
|
2740
|
+
var sectionLoss = (p) => {
|
|
2741
|
+
const cells = p.st.chipped;
|
|
2742
|
+
if (!cells?.length) return 0;
|
|
2743
|
+
const [u, v] = planeAxes(p.thin);
|
|
2744
|
+
const along = p.dims[u] >= p.dims[v] ? u : v;
|
|
2745
|
+
const across = along === u ? v : u;
|
|
2746
|
+
let worst = 0;
|
|
2747
|
+
for (const c of cells) {
|
|
2748
|
+
let gone = 0;
|
|
2749
|
+
for (const d of cells) if (Math.abs(d.center[along] - c.center[along]) < d.size[along] / 2 + 1e-6) gone += d.size[across];
|
|
2750
|
+
worst = Math.max(worst, gone / Math.max(p.dims[across], 1e-6));
|
|
2751
|
+
}
|
|
2752
|
+
return Math.min(1, worst);
|
|
2503
2753
|
};
|
|
2504
2754
|
var isLost = (p) => p.st.status === "broken" || p.st.status === "melted" || p.st.status === "ashes";
|
|
2505
2755
|
var clone = (v) => structuredClone(v);
|
|
@@ -3599,7 +3849,7 @@ var createDestruction = (options = {}) => {
|
|
|
3599
3849
|
emit({ ...base(o, src), type: "crack", part: p.spec.id, crack, worldPoint: wp });
|
|
3600
3850
|
setStage(o, p, 1, {}, src);
|
|
3601
3851
|
};
|
|
3602
|
-
const debris = (o, p, kind, point, normal, count, speed, src) => emit({ ...base(o, src), type: "debris", part: p.spec.id, kind, point, normal, count, speed });
|
|
3852
|
+
const debris = (o, p, kind, point, normal, count, speed, src, material) => emit({ ...base(o, src), type: "debris", part: p.spec.id, kind, point, normal, count, speed, ...material && material !== p.spec.material ? { material } : {} });
|
|
3603
3853
|
const holeRate = (hole, pressurized) => (pressurized ? 0.5 : 0.1) * (hole.diameter / 9e-3);
|
|
3604
3854
|
const detachEvents = (o, opened, by, src) => {
|
|
3605
3855
|
for (const j of opened) emit({ ...base(o, src), type: "detach", joint: j.spec.id, parts: [j.spec.a, j.spec.b], by, groups: o.st.groups.map((g) => [...g]) });
|
|
@@ -3640,7 +3890,13 @@ var createDestruction = (options = {}) => {
|
|
|
3640
3890
|
const small = pa.dims[0] * pa.dims[1] * pa.dims[2] <= pb.dims[0] * pb.dims[1] * pb.dims[2] ? pa : pb;
|
|
3641
3891
|
return Math.max(0.06, 0.5 * Math.min(small.dims[0], small.dims[1], small.dims[2]));
|
|
3642
3892
|
};
|
|
3643
|
-
const
|
|
3893
|
+
const jointLength = (o, j) => {
|
|
3894
|
+
const A = partWorldAabb(o, o.parts[j.ia]), B = partWorldAabb(o, o.parts[j.ib]);
|
|
3895
|
+
let len = 0;
|
|
3896
|
+
for (let k = 0; k < 3; k++) len = Math.max(len, Math.min(A.max[k], B.max[k]) - Math.max(A.min[k], B.min[k]));
|
|
3897
|
+
return len;
|
|
3898
|
+
};
|
|
3899
|
+
const wearJoints = (o, p, amount, near, radius = 0.06, src, split = false, span) => {
|
|
3644
3900
|
if (amount <= 0) return;
|
|
3645
3901
|
const mine = (o.byPart.get(p.spec.id) ?? []).filter((j) => !j.st.open);
|
|
3646
3902
|
if (split && mine.length) amount /= mine.length;
|
|
@@ -3648,7 +3904,7 @@ var createDestruction = (options = {}) => {
|
|
|
3648
3904
|
if (j.st.open) continue;
|
|
3649
3905
|
if (j.spec.kind === "rebar" && (isReinforced(o.parts[j.ia].spec) || isReinforced(o.parts[j.ib].spec))) continue;
|
|
3650
3906
|
if (near && jointReach(o, j, near) > Math.max(radius, jointReachLimit(o, j))) continue;
|
|
3651
|
-
j.st.hp -= amount;
|
|
3907
|
+
j.st.hp -= span === void 0 ? amount : amount * Math.min(1, span / Math.max(jointLength(o, j), 1e-6));
|
|
3652
3908
|
if (j.st.hp <= 0) {
|
|
3653
3909
|
j.st.hp = 0;
|
|
3654
3910
|
j.st.open = true;
|
|
@@ -3677,7 +3933,13 @@ var createDestruction = (options = {}) => {
|
|
|
3677
3933
|
if (spalls.length > MAX_SPALLS) spalls.shift();
|
|
3678
3934
|
markDamaged(p);
|
|
3679
3935
|
emit({ ...base(o, src), type: "spall", part: p.spec.id, layer: layer.index, point: wp, area: Math.PI * radius * radius });
|
|
3680
|
-
debris(o, p, layer.mat.hitDebris, wp, normal, 5, 2, src);
|
|
3936
|
+
debris(o, p, layer.mat.hitDebris, wp, normal, 5, 2, src, layer.mat.id);
|
|
3937
|
+
setStage(o, p, 1, {}, src);
|
|
3938
|
+
};
|
|
3939
|
+
const crater = (o, p, wp, normal, radius, src) => {
|
|
3940
|
+
markDamaged(p);
|
|
3941
|
+
emit({ ...base(o, src), type: "spall", part: p.spec.id, layer: -1, point: wp, area: Math.PI * radius * radius });
|
|
3942
|
+
debris(o, p, p.mat.breakDebris, wp, normal, 6, 1.5, src);
|
|
3681
3943
|
setStage(o, p, 1, {}, src);
|
|
3682
3944
|
};
|
|
3683
3945
|
const insideOpening = (o, p, objectPoint) => {
|
|
@@ -3756,9 +4018,13 @@ var createDestruction = (options = {}) => {
|
|
|
3756
4018
|
const lp = toLocal(p.pos, p.q, objectPoint);
|
|
3757
4019
|
return cells.some((c) => Math.abs(lp[u] - c.center[u]) <= c.size[u] / 2 && Math.abs(lp[v] - c.center[v]) <= c.size[v] / 2);
|
|
3758
4020
|
};
|
|
3759
|
-
const chipUnits = (o, p, wp,
|
|
4021
|
+
const chipUnits = (o, p, kind, wp, hitEnergy, dir, radius, src) => {
|
|
3760
4022
|
var _a, _b;
|
|
3761
|
-
if (!p.spec.units ||
|
|
4023
|
+
if (!p.spec.units || !p.staged || chipEnergy <= 0 || p.st.stripped || isLost(p) || (p.st.stage ?? 0) >= 2) return;
|
|
4024
|
+
const rule = p.mat.hits?.[kind];
|
|
4025
|
+
const perKg = rule?.unitJoules ?? chipEnergy;
|
|
4026
|
+
const energy = hitEnergy - (rule?.floor ?? 0);
|
|
4027
|
+
if (perKg <= 0 || energy <= 0) return;
|
|
3762
4028
|
const [u, v] = planeAxes(p.thin);
|
|
3763
4029
|
const lp = toLocal(p.pos, p.q, objLocal(o, wp));
|
|
3764
4030
|
const grid = gridOf(p);
|
|
@@ -3772,7 +4038,7 @@ var createDestruction = (options = {}) => {
|
|
|
3772
4038
|
const share = gap === 0 ? 1 : CHIP_SPLASH * (1 - gap / radius);
|
|
3773
4039
|
const total = (worn[i] ?? 0) + energy * share;
|
|
3774
4040
|
const mass = p.mat.density * cell.size[0] * cell.size[1] * cell.size[2];
|
|
3775
|
-
if (total <
|
|
4041
|
+
if (total < perKg * mass) {
|
|
3776
4042
|
worn[i] = total;
|
|
3777
4043
|
continue;
|
|
3778
4044
|
}
|
|
@@ -3797,7 +4063,32 @@ var createDestruction = (options = {}) => {
|
|
|
3797
4063
|
emit({ ...base(o, src), type: "chip", part: p.spec.id, center, size: [cell.size[0], cell.size[1], cell.size[2]], rotation: q, fragments });
|
|
3798
4064
|
debris(o, p, p.mat.breakDebris, center, vec.scale(dir ?? [0, 1, 0], -1), 6, 2, src);
|
|
3799
4065
|
}
|
|
4066
|
+
if (p.spec.reinforcement) exposeRebar(o, p, src);
|
|
3800
4067
|
for (const cell of out) addBreach(o, p, toWorld(c, q, cell.center), cell.size[u] * cell.size[v], energy, dir, src);
|
|
4068
|
+
if (p.structural && !isLost(p)) {
|
|
4069
|
+
solveStructure(o);
|
|
4070
|
+
collapseCheck(o, src);
|
|
4071
|
+
}
|
|
4072
|
+
};
|
|
4073
|
+
const exposeRebar = (o, p, src) => {
|
|
4074
|
+
const r = p.spec.reinforcement;
|
|
4075
|
+
if (!r) return;
|
|
4076
|
+
const [u, v] = planeAxes(p.thin);
|
|
4077
|
+
const all = rebarBars(p.dims, p.thin, r.spacing);
|
|
4078
|
+
let bars;
|
|
4079
|
+
if (p.st.stripped) bars = all;
|
|
4080
|
+
else {
|
|
4081
|
+
bars = [];
|
|
4082
|
+
for (const cell of p.st.chipped ?? []) bars.push(...clipBarsToBox(all, u, v, cell.center, cell.size));
|
|
4083
|
+
const op = p.st.opening;
|
|
4084
|
+
if (op) {
|
|
4085
|
+
const lc = toLocal(p.pos, p.q, op.center);
|
|
4086
|
+
bars.push(...clipBarsToDisc(all, u, v, [lc[u], lc[v]], op.radius + 0.05));
|
|
4087
|
+
}
|
|
4088
|
+
}
|
|
4089
|
+
const bow = clamp2(((p.st.stress ?? 0) - 1) / 0.5, 0, 1);
|
|
4090
|
+
if (bow > 0) bars = bars.flatMap((bar2, i) => bendBar(bar2, p.thin, bow * BAR_BOW, i));
|
|
4091
|
+
emit({ ...base(o, src), type: "expose", part: p.spec.id, bars: worldBars(o, p, bars) });
|
|
3801
4092
|
};
|
|
3802
4093
|
const openBreach = (o, p, center, total, energy, dir, src) => {
|
|
3803
4094
|
const [u, v] = planeAxes(p.thin);
|
|
@@ -3825,10 +4116,7 @@ var createDestruction = (options = {}) => {
|
|
|
3825
4116
|
setStage(o, p, 2, { opening: { center: worldCenter, radius }, fragments }, src);
|
|
3826
4117
|
debris(o, p, p.mat.breakDebris, worldCenter, vec.scale(dir ?? [0, 1, 0], -1), 14, 3, src);
|
|
3827
4118
|
const reinforcement = p.spec.reinforcement;
|
|
3828
|
-
if (reinforcement)
|
|
3829
|
-
const bars = worldBars(o, p, clipBarsToDisc(rebarBars(p.dims, p.thin, reinforcement.spacing), u, v, [lc[u], lc[v]], radius + 0.05));
|
|
3830
|
-
if (bars.length > 0) emit({ ...base(o, src), type: "expose", part: p.spec.id, bars });
|
|
3831
|
-
}
|
|
4119
|
+
if (reinforcement) exposeRebar(o, p, src);
|
|
3832
4120
|
if (p.structural) solveStructure(o);
|
|
3833
4121
|
};
|
|
3834
4122
|
const stripPart = (o, p, reinforcement, src) => {
|
|
@@ -3840,8 +4128,8 @@ var createDestruction = (options = {}) => {
|
|
|
3840
4128
|
p.st.burning = false;
|
|
3841
4129
|
p.rt.jet = false;
|
|
3842
4130
|
markDamaged(p);
|
|
3843
|
-
emit({ ...base(o, src), type: "expose", part: p.spec.id, bars: worldBars(o, p, bars) });
|
|
3844
4131
|
solveStructure(o);
|
|
4132
|
+
exposeRebar(o, p, src);
|
|
3845
4133
|
collapseCheck(o, src);
|
|
3846
4134
|
};
|
|
3847
4135
|
const unitFragmentPlan = (p, cap) => {
|
|
@@ -3895,7 +4183,7 @@ var createDestruction = (options = {}) => {
|
|
|
3895
4183
|
const grain = p.spec.grain ? AXIS[p.spec.grain] : void 0;
|
|
3896
4184
|
const hitLocal = toLocal(c, q, hitW);
|
|
3897
4185
|
const unitPlan = p.spec.units ? unitFragmentPlan(p, maxFragments * UNIT_FRAGMENT_FACTOR) : [];
|
|
3898
|
-
const axis = style === "splinter" ? severAxis(p) : -1;
|
|
4186
|
+
const axis = style === "splinter" || style === "snap" ? severAxis(p) : -1;
|
|
3899
4187
|
const cutAt = axis < 0 ? void 0 : p.rt.cutAt ?? (origin ? hitLocal[axis] : void 0);
|
|
3900
4188
|
const plan = unitPlan.length > 0 ? unitPlan : planFragments({
|
|
3901
4189
|
style,
|
|
@@ -3967,7 +4255,7 @@ var createDestruction = (options = {}) => {
|
|
|
3967
4255
|
};
|
|
3968
4256
|
const CHAIN_TRIGGER_OF = { ballistic: "shot", explosive: "explosion" };
|
|
3969
4257
|
const severAxis = (p) => {
|
|
3970
|
-
if (p.mat.fracture !== "splinter" || p.spec.shape.kind !== "box") return -1;
|
|
4258
|
+
if (p.mat.fracture !== "splinter" && p.mat.fracture !== "snap" || p.spec.shape.kind !== "box") return -1;
|
|
3971
4259
|
const d = p.dims;
|
|
3972
4260
|
const order = [0, 1, 2].sort((a, b) => d[b] - d[a]);
|
|
3973
4261
|
return d[order[0]] >= SEVER_ASPECT * d[order[1]] && d[order[0]] >= 3 * SEVER_BAND ? order[0] : -1;
|
|
@@ -4028,6 +4316,49 @@ var createDestruction = (options = {}) => {
|
|
|
4028
4316
|
}
|
|
4029
4317
|
}
|
|
4030
4318
|
};
|
|
4319
|
+
const tearOf = (mat, kind) => {
|
|
4320
|
+
const h = mat.hits?.[kind];
|
|
4321
|
+
const tear = h?.tear ?? (kind === "ballistic" && mat.penetrationClass === "wood" ? "splinters" : "none");
|
|
4322
|
+
return { tear, joules: h?.tearJoules ?? TEAR_JOULES };
|
|
4323
|
+
};
|
|
4324
|
+
const tearAt = (o, p, kind, entry, exit, d, E, scale, src) => {
|
|
4325
|
+
const { tear, joules } = tearOf(p.mat, kind);
|
|
4326
|
+
if (tear === "none") return;
|
|
4327
|
+
const shot = kind === "ballistic";
|
|
4328
|
+
const n = shot ? exit ? clamp2(Math.round(E / joules), 1, 7) : 1 : clamp2(Math.floor(E / joules), 0, 5);
|
|
4329
|
+
if (n === 0) return;
|
|
4330
|
+
const fibre = tear === "lumps";
|
|
4331
|
+
const { q } = partXf(o, p);
|
|
4332
|
+
const along = (p.spec.grain ? AXIS[p.spec.grain] : void 0) ?? [0, 1, 2].sort((a, b) => p.dims[b] - p.dims[a])[0];
|
|
4333
|
+
const fragments = [];
|
|
4334
|
+
for (let i = 0; i < n; i++) {
|
|
4335
|
+
const back = !exit || i % 3 === 2;
|
|
4336
|
+
const len = scale * (fibre ? 1.2 + 1.2 * rnd() : 3 + 4 * rnd()), w = scale * (0.8 + 0.8 * rnd()), t = scale * (fibre ? 0.7 + 0.6 * rnd() : 0.4 + 0.4 * rnd());
|
|
4337
|
+
const size = [w, w, w];
|
|
4338
|
+
size[along] = len;
|
|
4339
|
+
size[(along + 1) % 3] = w;
|
|
4340
|
+
size[(along + 2) % 3] = t;
|
|
4341
|
+
const spread3 = [(rnd() - 0.5) * 0.8, (rnd() - 0.2) * 0.8, (rnd() - 0.5) * 0.8];
|
|
4342
|
+
const speed = shot ? back ? 1.5 + 2 * rnd() : 2 + 4 * rnd() : 0.8 + 1.2 * rnd();
|
|
4343
|
+
const v = vec.scale(vec.normalize(vec.add(back ? vec.scale(d, -1) : d, spread3)), speed);
|
|
4344
|
+
const mass = size[0] * size[1] * size[2] * p.mat.density;
|
|
4345
|
+
fragments.push({
|
|
4346
|
+
id: `${p.spec.id}#t${tears++}-${i}`,
|
|
4347
|
+
part: p.spec.id,
|
|
4348
|
+
material: p.spec.material,
|
|
4349
|
+
shape: fibre ? "chunk" : "splinter",
|
|
4350
|
+
center: back || !exit ? vec.madd(entry, d, -0.01) : vec.madd(exit, d, 0.01),
|
|
4351
|
+
size,
|
|
4352
|
+
rotation: q,
|
|
4353
|
+
velocity: v,
|
|
4354
|
+
inner: true,
|
|
4355
|
+
angularVelocity: [(rnd() - 0.5) * 30, (rnd() - 0.5) * 30, (rnd() - 0.5) * 30],
|
|
4356
|
+
mass
|
|
4357
|
+
});
|
|
4358
|
+
}
|
|
4359
|
+
const patch = [scale * 4, scale * 4, scale * 4];
|
|
4360
|
+
emit({ ...base(o, src), type: "chip", part: p.spec.id, center: exit ?? entry, size: patch, rotation: q, fragments });
|
|
4361
|
+
};
|
|
4031
4362
|
const ballistic = (o, p, entry, n, d, E, caliber, pathLen, src, round = {}) => {
|
|
4032
4363
|
const mat = p.mat;
|
|
4033
4364
|
const piercing = round.piercing ?? 1;
|
|
@@ -4056,6 +4387,7 @@ var createDestruction = (options = {}) => {
|
|
|
4056
4387
|
return { penetrated: false, exitEnergy: 0, damage: dmg2 };
|
|
4057
4388
|
}
|
|
4058
4389
|
if (p.layers.length > 0) spallOuter(o, p, entry, face, n, Math.max(0.03, caliber / 1e3 * 4), src);
|
|
4390
|
+
else if (mat.hits?.ballistic?.crater) crater(o, p, entry, n, clamp2(0.02 + Math.sqrt(E) * 15e-4, 0.02, 0.15), src);
|
|
4059
4391
|
const brittle = mat.ductility < 0.3;
|
|
4060
4392
|
const ratio = Ep / Math.max(thr, 1e-6);
|
|
4061
4393
|
const crackLen = clamp2(0.03 + ratio * 0.2, 0.03, 0.8);
|
|
@@ -4088,9 +4420,11 @@ var createDestruction = (options = {}) => {
|
|
|
4088
4420
|
if (mat.fracture !== "shatter") addHole(o, p, entry, n, caliber / 1e3, false, void 0, src);
|
|
4089
4421
|
} else addHole(o, p, entry, n, caliber / 1e3, false, void 0, src);
|
|
4090
4422
|
debris(o, p, mat.hitDebris, entry, n, clamp2(Math.round(E / 60) + 2, 2, 14), clamp2(Math.sqrt(E) / 6, 1, 8), src);
|
|
4091
|
-
wearJoints(o, p, (penetrated ? thr : E) * 0.02, void 0, 0, src, true);
|
|
4092
|
-
const
|
|
4093
|
-
|
|
4423
|
+
wearJoints(o, p, (penetrated ? thr : E) * 0.02, void 0, 0, src, true, BULLET_JOINT_SPAN);
|
|
4424
|
+
const absorbed = penetrated && mat.ductility >= 0.5 && mat.fracture !== "tear" ? Math.min(E, thr) : E;
|
|
4425
|
+
const dmg = applyDamage(o, p, absorbed * DMG_PER_J * scale, "ballistic", entry, d, absorbed * 0.1, 12, src);
|
|
4426
|
+
if (!isLost(p)) tearAt(o, p, "ballistic", entry, penetrated ? exitPoint : void 0, d, E, caliber / 1e3, src);
|
|
4427
|
+
chipUnits(o, p, "ballistic", entry, penetrated ? Math.min(E, Math.max(thr, E * 0.5)) : E, d, Math.max(0.05, caliber / 1e3 * 8), src);
|
|
4094
4428
|
return { penetrated, exitEnergy: penetrated ? penMm !== void 0 ? E * (1 - thr / Ep) : E - thr / (hard ? piercing : 1) : 0, exitPoint, damage: dmg };
|
|
4095
4429
|
};
|
|
4096
4430
|
const melee = (o, p, kind, E, point, n, d, contactR, src) => {
|
|
@@ -4098,14 +4432,20 @@ var createDestruction = (options = {}) => {
|
|
|
4098
4432
|
const thrMm = mat.penetration * p.thickness * 1e3;
|
|
4099
4433
|
const fragile = kind === "blunt" ? fragility(mat.ductility, p.thickness) : 1;
|
|
4100
4434
|
const Ec = E * fragile;
|
|
4435
|
+
const sheet = mat.ductility >= 0.5 && p.thickness <= THIN_SHEET_CRUSH;
|
|
4436
|
+
const fold = sheet ? Math.min(4, Math.sqrt(1e-3 / p.thickness)) : 1;
|
|
4437
|
+
const patch = sheet ? Math.min(contactR, THIN_SHEET_CONTACT) : contactR;
|
|
4101
4438
|
if (E > 0) {
|
|
4102
4439
|
if (kind === "blunt") {
|
|
4103
|
-
if (mat.ductility >= 0.5) addDent(o, p, point, n, Math.max(
|
|
4440
|
+
if (mat.ductility >= 0.5) addDent(o, p, point, n, Math.max(patch, 0.015), clamp2(E * 1e-4 * fold, 1e-3, sheet ? Math.min(0.06, Math.min(...p.dims) * 0.45) : 0.06), src);
|
|
4104
4441
|
else if (mat.ductility < 0.3) {
|
|
4105
4442
|
if (Ec >= 5) addCrack(o, p, point, n, clamp2(0.04 + Math.min(Ec, E * 6) * 8e-4, 0.04, 0.6), src);
|
|
4106
4443
|
} else if (E >= thrMm * 0.2) addDent(o, p, point, n, Math.max(contactR, 0.015), clamp2(E * 6e-5, 1e-3, 0.04), src);
|
|
4107
4444
|
} else if (mat.fracture === "tear") {
|
|
4108
4445
|
addHole(o, p, point, n, clamp2(0.02 + E * 5e-4, 0.02, 0.3), true, void 0, src);
|
|
4446
|
+
} else if (mat.ductility >= 0.3 && E >= thrMm) {
|
|
4447
|
+
addHole(o, p, point, n, clamp2(contactR, 0.01, 0.08), true, void 0, src);
|
|
4448
|
+
if (sheet) addDent(o, p, point, n, Math.max(patch * 0.6, 0.01), clamp2(E * 4e-5 * fold, 5e-4, 0.02), src);
|
|
4109
4449
|
} else if (mat.ductility >= 0.5) {
|
|
4110
4450
|
addDent(o, p, point, n, Math.max(contactR, 0.01), clamp2(E * 4e-5, 5e-4, 0.02), src);
|
|
4111
4451
|
}
|
|
@@ -4118,7 +4458,8 @@ var createDestruction = (options = {}) => {
|
|
|
4118
4458
|
const scale = mat.damageScale?.[kind] ?? 1;
|
|
4119
4459
|
const done = applyDamage(o, p, Ec * DMG_PER_J * scale * (kind === "slash" ? p.cutFactor : 1), kind, point, d, E * 0.1, 12, src);
|
|
4120
4460
|
addBreach(o, p, point, breachAreaOf(p, done, false), E, d, src);
|
|
4121
|
-
if (kind === "blunt") chipUnits(o, p, point, E, d, Math.max(contactR, 0.03), src);
|
|
4461
|
+
if (kind === "blunt") chipUnits(o, p, "blunt", point, E, d, Math.max(contactR, 0.03), src);
|
|
4462
|
+
if (E > 0 && !isLost(p)) tearAt(o, p, kind, point, void 0, d, E, clamp2(contactR * 0.2, 6e-3, 0.02), src);
|
|
4122
4463
|
return done;
|
|
4123
4464
|
};
|
|
4124
4465
|
const blastPart = (o, p, point, energy, radius, src, res, reachAt) => {
|
|
@@ -4697,6 +5038,7 @@ var createDestruction = (options = {}) => {
|
|
|
4697
5038
|
if (p.rt.stressT <= 0) {
|
|
4698
5039
|
p.rt.stressT = 0.5;
|
|
4699
5040
|
emit({ ...base(o), type: "stress", part: p.spec.id, stress, load: p.st.load ?? 0 });
|
|
5041
|
+
if (p.spec.reinforcement && (p.st.stripped || p.st.chipped?.length || p.st.opening)) exposeRebar(o, p);
|
|
4700
5042
|
}
|
|
4701
5043
|
applyDamage(o, p, overloadRate(stress) * p.st.maxHp * dt, "blunt", null, null, 5, 3);
|
|
4702
5044
|
} else if (stress > 0.8 && p.mat.ductility < 0.3 && p.rt.stressT <= 0 && p.st.cracks.length < 6) {
|
|
@@ -4913,6 +5255,18 @@ var createDestruction = (options = {}) => {
|
|
|
4913
5255
|
const r = raycastInternal(origin, direction, maxDistance);
|
|
4914
5256
|
return r ? { object: r.object, part: r.part, point: r.point, normal: r.normal, distance: r.distance } : null;
|
|
4915
5257
|
},
|
|
5258
|
+
sweepBox(box, direction, distance, options2 = {}) {
|
|
5259
|
+
const d = vec.normalize(direction);
|
|
5260
|
+
const ignored = options2.ignore === void 0 ? void 0 : objects.get(options2.ignore);
|
|
5261
|
+
const ignore = ignored ? new Set(ignored.parts.map((p) => `${ignored.id}\0${p.spec.id}`)) : void 0;
|
|
5262
|
+
let best = null;
|
|
5263
|
+
for (const origin of sweepOrigins(box, d, options2.spacing ?? 0.2)) {
|
|
5264
|
+
const r = raycastInternal(origin, d, distance + SWEEP_BACK, ignore);
|
|
5265
|
+
if (!r || best && r.distance >= best.distance) continue;
|
|
5266
|
+
best = { object: r.object, part: r.part, point: r.point, normal: r.normal, distance: Math.max(0, r.distance - SWEEP_BACK) };
|
|
5267
|
+
}
|
|
5268
|
+
return best;
|
|
5269
|
+
},
|
|
4916
5270
|
shoot(origin, direction, energy, caliber, source, round) {
|
|
4917
5271
|
const extras = typeof round === "number" ? { piercing: round } : round ?? {};
|
|
4918
5272
|
return withCollapses(run(() => {
|
|
@@ -5557,7 +5911,12 @@ var locales = {
|
|
|
5557
5911
|
cactus: "cactus",
|
|
5558
5912
|
flesh_fruit: "fruit",
|
|
5559
5913
|
wax: "wax",
|
|
5560
|
-
soil: "soil"
|
|
5914
|
+
soil: "soil",
|
|
5915
|
+
asphalt: "asphalt",
|
|
5916
|
+
sand: "sand",
|
|
5917
|
+
gravel: "gravel",
|
|
5918
|
+
turf: "turf",
|
|
5919
|
+
mortar: "mortar"
|
|
5561
5920
|
},
|
|
5562
5921
|
partStatus: { intact: "intact", damaged: "damaged", collapsed: "collapsed", broken: "broken", melted: "melted", ashes: "ashes" },
|
|
5563
5922
|
jointKinds: {
|
|
@@ -5648,7 +6007,12 @@ var locales = {
|
|
|
5648
6007
|
cactus: "cacto",
|
|
5649
6008
|
flesh_fruit: "fruta",
|
|
5650
6009
|
wax: "cera",
|
|
5651
|
-
soil: "terra"
|
|
6010
|
+
soil: "terra",
|
|
6011
|
+
asphalt: "asfalto",
|
|
6012
|
+
sand: "areia",
|
|
6013
|
+
gravel: "brita",
|
|
6014
|
+
turf: "grama",
|
|
6015
|
+
mortar: "argamassa"
|
|
5652
6016
|
},
|
|
5653
6017
|
partStatus: { intact: "intacto", damaged: "danificado", collapsed: "desabado", broken: "quebrado", melted: "derretido", ashes: "cinzas" },
|
|
5654
6018
|
jointKinds: {
|