@adatechnology/game-destruction 0.3.2 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -1
- package/dist/index.d.ts +26 -3
- package/dist/index.global.js +82 -7
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +82 -7
- package/dist/index.js.map +1 -1
- package/package.json +4 -3
package/dist/index.js
CHANGED
|
@@ -1,3 +1,22 @@
|
|
|
1
|
+
// src/chain.ts
|
|
2
|
+
var FIRE_PRIME_C = 300;
|
|
3
|
+
var drawChainDelay = (delay, random) => {
|
|
4
|
+
if (typeof delay === "number") return delay;
|
|
5
|
+
const [min, max] = delay;
|
|
6
|
+
return min + random() * (max - min);
|
|
7
|
+
};
|
|
8
|
+
var chainDelayOf = (spec, trigger) => spec.explodes?.chain?.[trigger];
|
|
9
|
+
var shotDamageFractionOf = (spec) => spec.explodes?.chain?.shotDamageFraction ?? 0;
|
|
10
|
+
var explosivePart = (explosive, part, options = {}) => ({
|
|
11
|
+
...part,
|
|
12
|
+
explodes: {
|
|
13
|
+
energy: explosive.energy,
|
|
14
|
+
radius: explosive.injuryRadius,
|
|
15
|
+
...options.atC !== void 0 ? { atC: options.atC } : {},
|
|
16
|
+
...explosive.chain ? { chain: { ...explosive.chain } } : {}
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
|
|
1
20
|
// src/math.ts
|
|
2
21
|
var EPS = 1e-9;
|
|
3
22
|
var vec = {
|
|
@@ -1441,6 +1460,8 @@ var createDestruction = (options = {}) => {
|
|
|
1441
1460
|
const listeners = /* @__PURE__ */ new Map();
|
|
1442
1461
|
let cur = [];
|
|
1443
1462
|
const blasts = [];
|
|
1463
|
+
const primed = /* @__PURE__ */ new Map();
|
|
1464
|
+
let orderCounter = 0;
|
|
1444
1465
|
const impls = /* @__PURE__ */ new Map();
|
|
1445
1466
|
const taken = (id) => objects.has(id) || impls.has(id);
|
|
1446
1467
|
const emit = (e) => {
|
|
@@ -1454,6 +1475,9 @@ var createDestruction = (options = {}) => {
|
|
|
1454
1475
|
const base = (o, source) => source === void 0 ? { object: o.id, time } : { object: o.id, time, source };
|
|
1455
1476
|
const pendingCollapse = /* @__PURE__ */ new Map();
|
|
1456
1477
|
let runDepth = 0;
|
|
1478
|
+
const drainBlasts = () => {
|
|
1479
|
+
for (let blast = blasts.shift(); blast; blast = blasts.shift()) blastWorld(blast.point, blast.energy, blast.radius, blast.source);
|
|
1480
|
+
};
|
|
1457
1481
|
const run = (fn) => {
|
|
1458
1482
|
const prev = cur;
|
|
1459
1483
|
const mine = [];
|
|
@@ -1461,11 +1485,7 @@ var createDestruction = (options = {}) => {
|
|
|
1461
1485
|
runDepth++;
|
|
1462
1486
|
try {
|
|
1463
1487
|
const value = fn();
|
|
1464
|
-
|
|
1465
|
-
while (blasts.length && guard++ < 64) {
|
|
1466
|
-
const b = blasts.shift();
|
|
1467
|
-
blastWorld(b.point, b.energy, b.radius, b.source);
|
|
1468
|
-
}
|
|
1488
|
+
drainBlasts();
|
|
1469
1489
|
if (runDepth === 1) flushCollapse();
|
|
1470
1490
|
return { value, events: mine };
|
|
1471
1491
|
} finally {
|
|
@@ -1525,7 +1545,8 @@ var createDestruction = (options = {}) => {
|
|
|
1525
1545
|
maxStress: 0,
|
|
1526
1546
|
collapsed: new Set(carry?.collapsed ?? []),
|
|
1527
1547
|
unsup: [],
|
|
1528
|
-
anyAnchor: false
|
|
1548
|
+
anyAnchor: false,
|
|
1549
|
+
order: ++orderCounter
|
|
1529
1550
|
};
|
|
1530
1551
|
for (const ps of spec.parts) {
|
|
1531
1552
|
if (o.byId.has(ps.id)) throw new Error(`duplicate part id "${ps.id}"`);
|
|
@@ -1572,6 +1593,7 @@ var createDestruction = (options = {}) => {
|
|
|
1572
1593
|
cap: ps.structure ? partCapacity(ps, mat) : 0
|
|
1573
1594
|
};
|
|
1574
1595
|
if (p.structural) o.hasStructure = true;
|
|
1596
|
+
if (p.rt.chainDue !== void 0 && !isLost(p)) primed.set(p, o);
|
|
1575
1597
|
o.idx.set(ps.id, o.parts.length);
|
|
1576
1598
|
o.parts.push(p);
|
|
1577
1599
|
o.byId.set(ps.id, p);
|
|
@@ -2009,15 +2031,29 @@ var createDestruction = (options = {}) => {
|
|
|
2009
2031
|
}
|
|
2010
2032
|
partLost(o, p, src);
|
|
2011
2033
|
};
|
|
2034
|
+
const prime = (o, p, trigger, src) => {
|
|
2035
|
+
const spec = chainDelayOf(p.spec, trigger);
|
|
2036
|
+
if (spec === void 0 || isLost(p) || p.rt.chainDue !== void 0) return;
|
|
2037
|
+
const delay = drawChainDelay(spec, rnd);
|
|
2038
|
+
p.rt.chainDue = time + delay;
|
|
2039
|
+
primed.set(p, o);
|
|
2040
|
+
o.active = true;
|
|
2041
|
+
emit({ ...base(o, src), type: "primed", part: p.spec.id, point: partXf(o, p).c, trigger, delay });
|
|
2042
|
+
};
|
|
2043
|
+
const CHAIN_TRIGGER_OF = { ballistic: "shot", explosive: "explosion" };
|
|
2012
2044
|
const applyDamage = (o, p, amount, type, origin, dir, fragEnergy, cap, src) => {
|
|
2013
2045
|
if (isLost(p) || amount <= 0) return 0;
|
|
2014
2046
|
const prev = p.st.hp;
|
|
2015
2047
|
p.st.hp -= amount;
|
|
2016
2048
|
markDamaged(p);
|
|
2049
|
+
const trigger = CHAIN_TRIGGER_OF[type];
|
|
2050
|
+
const chained = trigger !== void 0 && chainDelayOf(p.spec, trigger) !== void 0;
|
|
2051
|
+
if (chained && p.st.hp <= 0 && p.rt.chainDue === void 0) p.st.hp = Math.min(prev, 1);
|
|
2017
2052
|
if (p.st.hp <= 0 && p.mat.fracture === "none" && !p.spec.explodes) p.st.hp = Math.min(prev, 1);
|
|
2018
2053
|
const done = prev - p.st.hp;
|
|
2019
2054
|
if (done > 0) emit({ ...base(o, src), type: "damage", part: p.spec.id, amount: done, hp: Math.max(0, p.st.hp), damageType: type });
|
|
2020
2055
|
if (p.st.hp <= 0) failPart(o, p, origin, dir, fragEnergy, cap, src);
|
|
2056
|
+
else if (chained && (trigger === "explosion" || 1 - p.st.hp / p.st.maxHp >= shotDamageFractionOf(p.spec))) prime(o, p, trigger, src);
|
|
2021
2057
|
return done;
|
|
2022
2058
|
};
|
|
2023
2059
|
const ballistic = (o, p, entry, n, d, E, caliber, pathLen, src) => {
|
|
@@ -2318,7 +2354,9 @@ var createDestruction = (options = {}) => {
|
|
|
2318
2354
|
if (isLost(p)) continue;
|
|
2319
2355
|
checkIgnite(o, p);
|
|
2320
2356
|
const ex = p.spec.explodes;
|
|
2321
|
-
if (ex &&
|
|
2357
|
+
if (ex && chainDelayOf(p.spec, "fire") !== void 0) {
|
|
2358
|
+
if (s.temperature >= (ex.atC ?? FIRE_PRIME_C)) prime(o, p, "fire");
|
|
2359
|
+
} else if (ex && ex.atC !== void 0 && s.temperature >= ex.atC) {
|
|
2322
2360
|
failPart(o, p, null, null, 0, 40);
|
|
2323
2361
|
continue;
|
|
2324
2362
|
}
|
|
@@ -2330,6 +2368,10 @@ var createDestruction = (options = {}) => {
|
|
|
2330
2368
|
s.liters = Math.max(0, (s.liters ?? 0) - rate * dt);
|
|
2331
2369
|
hot = true;
|
|
2332
2370
|
if (FLAMMABLE_FLUIDS.includes(cont.fluid) && s.temperature >= 350 && !p.rt.jet) {
|
|
2371
|
+
if (ex && chainDelayOf(p.spec, "fire") !== void 0) {
|
|
2372
|
+
prime(o, p, "fire");
|
|
2373
|
+
continue;
|
|
2374
|
+
}
|
|
2333
2375
|
if (ex) {
|
|
2334
2376
|
failPart(o, p, null, null, 0, 40);
|
|
2335
2377
|
continue;
|
|
@@ -2413,6 +2455,34 @@ var createDestruction = (options = {}) => {
|
|
|
2413
2455
|
}
|
|
2414
2456
|
}
|
|
2415
2457
|
};
|
|
2458
|
+
const nextPrimed = (until) => {
|
|
2459
|
+
let best = null;
|
|
2460
|
+
for (const [p, o] of primed) {
|
|
2461
|
+
if (objects.get(o.id) !== o || isLost(p)) {
|
|
2462
|
+
primed.delete(p);
|
|
2463
|
+
continue;
|
|
2464
|
+
}
|
|
2465
|
+
const due = p.rt.chainDue;
|
|
2466
|
+
if (due > until) continue;
|
|
2467
|
+
if (!best) best = { o, p };
|
|
2468
|
+
else {
|
|
2469
|
+
const bestDue = best.p.rt.chainDue;
|
|
2470
|
+
if (due < bestDue || due === bestDue && (o.order < best.o.order || o.order === best.o.order && (o.idx.get(p.spec.id) ?? 0) < (best.o.idx.get(best.p.spec.id) ?? 0))) best = { o, p };
|
|
2471
|
+
}
|
|
2472
|
+
}
|
|
2473
|
+
return best;
|
|
2474
|
+
};
|
|
2475
|
+
const detonatePrimed = (until) => {
|
|
2476
|
+
const end = time;
|
|
2477
|
+
for (let next = nextPrimed(until); next; next = nextPrimed(until)) {
|
|
2478
|
+
primed.delete(next.p);
|
|
2479
|
+
time = Math.max(0, Math.min(end, next.p.rt.chainDue));
|
|
2480
|
+
next.p.rt.chainDue = void 0;
|
|
2481
|
+
failPart(next.o, next.p, null, null, 0, 40);
|
|
2482
|
+
drainBlasts();
|
|
2483
|
+
}
|
|
2484
|
+
time = end;
|
|
2485
|
+
};
|
|
2416
2486
|
const withCollapses = (r) => {
|
|
2417
2487
|
const last = r.value[r.value.length - 1];
|
|
2418
2488
|
if (!last) return r.value;
|
|
@@ -2663,6 +2733,7 @@ var createDestruction = (options = {}) => {
|
|
|
2663
2733
|
const sources = [];
|
|
2664
2734
|
for (const o of [...objects.values()]) if (o.active) stepObject(o, dt, sources);
|
|
2665
2735
|
if (sources.length) spread(sources, dt);
|
|
2736
|
+
detonatePrimed(time);
|
|
2666
2737
|
for (const im of [...impls.values()]) {
|
|
2667
2738
|
if (!im.impl.update) continue;
|
|
2668
2739
|
for (const e of im.impl.update(dt) ?? []) emit(e.time === void 0 ? { ...e, time } : e);
|
|
@@ -2956,6 +3027,7 @@ var locales = {
|
|
|
2956
3027
|
drip: "dripping",
|
|
2957
3028
|
leak: "leak",
|
|
2958
3029
|
explode: "exploded",
|
|
3030
|
+
primed: "about to explode",
|
|
2959
3031
|
stress: "overload",
|
|
2960
3032
|
collapse: "collapsed",
|
|
2961
3033
|
destroyed: "destroyed"
|
|
@@ -3037,6 +3109,7 @@ var locales = {
|
|
|
3037
3109
|
drip: "pingando",
|
|
3038
3110
|
leak: "vazamento",
|
|
3039
3111
|
explode: "explodiu",
|
|
3112
|
+
primed: "prestes a explodir",
|
|
3040
3113
|
stress: "sobrecarga",
|
|
3041
3114
|
collapse: "desabou",
|
|
3042
3115
|
destroyed: "destru\xEDdo"
|
|
@@ -3055,6 +3128,7 @@ var checkDestructible = (impl, options = {}) => {
|
|
|
3055
3128
|
return check(impl, contractOptions);
|
|
3056
3129
|
};
|
|
3057
3130
|
export {
|
|
3131
|
+
FIRE_PRIME_C,
|
|
3058
3132
|
IMPACT_CONTRACT,
|
|
3059
3133
|
JOINT_BY_MATERIALS,
|
|
3060
3134
|
JOINT_DEFAULTS,
|
|
@@ -3063,6 +3137,7 @@ export {
|
|
|
3063
3137
|
checkDestructible,
|
|
3064
3138
|
checkHit,
|
|
3065
3139
|
createDestruction,
|
|
3140
|
+
explosivePart,
|
|
3066
3141
|
fragility,
|
|
3067
3142
|
guessMaterial,
|
|
3068
3143
|
inferJoints,
|