@adatechnology/game-floorplan-structure 1.2.1 → 1.2.3
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 +212 -46
- package/dist/index.global.js.map +1 -1
- package/package.json +5 -5
package/dist/index.global.js
CHANGED
|
@@ -2755,6 +2755,62 @@ var GameFloorplanStructure = (() => {
|
|
|
2755
2755
|
return angle === 0 ? q : quat.mul(q, quat.fromAxisAngle([0, 0, 1], angle));
|
|
2756
2756
|
};
|
|
2757
2757
|
var clamp3 = (v, a, b) => Math.max(a, Math.min(b, v));
|
|
2758
|
+
var splinterBox = (inp, box2, limit = inp.maxFragments) => {
|
|
2759
|
+
const { rnd } = inp;
|
|
2760
|
+
const dims = box2.s;
|
|
2761
|
+
const [fmin, fmax] = inp.fragmentSize;
|
|
2762
|
+
const g = inp.grain ?? [0, 1, 2].sort((a2, b2) => dims[b2] - dims[a2])[0];
|
|
2763
|
+
const [a, b] = [0, 1, 2].filter((i) => i !== g);
|
|
2764
|
+
const w = Math.max(fmin * 1.5, 0.01);
|
|
2765
|
+
const c = clamp3(Math.round(dims[a] * dims[b] / (w * w)), 3, Math.max(3, Math.floor(limit / 2)));
|
|
2766
|
+
const maxLen = fmax * 4;
|
|
2767
|
+
const cells = bsp(box2, c, [a, b], rnd);
|
|
2768
|
+
const pieces = [];
|
|
2769
|
+
for (const cell of cells) {
|
|
2770
|
+
const extra = rnd() < 0.4 ? 1 : 0;
|
|
2771
|
+
const k = Math.max(1, Math.ceil(dims[g] / maxLen)) + extra;
|
|
2772
|
+
for (const p of bsp(cell, k, [g], rnd)) pieces.push(p);
|
|
2773
|
+
}
|
|
2774
|
+
return pieces.slice(0, limit).map((p) => ({ center: p.c, size: [p.s[g], p.s[a], p.s[b]], q: frame(g, a, b), shape: "splinter", weight: p.s[0] * p.s[1] * p.s[2] }));
|
|
2775
|
+
};
|
|
2776
|
+
var severAt = (inp, root, at2, gap) => {
|
|
2777
|
+
const dims = root.s;
|
|
2778
|
+
const L = [0, 1, 2].sort((x, y) => dims[y] - dims[x])[0];
|
|
2779
|
+
const half = dims[L] / 2;
|
|
2780
|
+
const lo = clamp3(at2 - gap / 2, -half, half), hi = clamp3(at2 + gap / 2, -half, half);
|
|
2781
|
+
const out = [];
|
|
2782
|
+
const stub = (from, to) => {
|
|
2783
|
+
if (to - from < 0.02) return;
|
|
2784
|
+
const c = [root.c[0], root.c[1], root.c[2]], sz = [dims[0], dims[1], dims[2]];
|
|
2785
|
+
c[L] = (from + to) / 2;
|
|
2786
|
+
sz[L] = to - from;
|
|
2787
|
+
out.push({ center: c, size: sz, q: quat.identity(), shape: "slab", weight: sz[0] * sz[1] * sz[2] });
|
|
2788
|
+
};
|
|
2789
|
+
stub(-half, lo);
|
|
2790
|
+
stub(hi, half);
|
|
2791
|
+
const band = { c: [root.c[0], root.c[1], root.c[2]], s: [dims[0], dims[1], dims[2]] };
|
|
2792
|
+
band.c[L] = (lo + hi) / 2;
|
|
2793
|
+
band.s[L] = Math.max(hi - lo, 0.01);
|
|
2794
|
+
for (const p of splinterBox(inp, band, Math.max(3, inp.maxFragments - out.length))) out.push(p);
|
|
2795
|
+
return out;
|
|
2796
|
+
};
|
|
2797
|
+
var tearStack = (inp, root, t, u, v, n, sheet) => {
|
|
2798
|
+
const { dims, rnd, maxFragments } = inp;
|
|
2799
|
+
const layers = clamp3(Math.ceil(dims[t] / STACK_LAYER), 2, 4);
|
|
2800
|
+
const per = clamp3(n, 3, Math.max(3, Math.floor(maxFragments / layers)));
|
|
2801
|
+
const out = [];
|
|
2802
|
+
for (let k = 0; k < layers; k++) {
|
|
2803
|
+
const off = -dims[t] / 2 + (k + 0.5) * dims[t] / layers;
|
|
2804
|
+
for (const b of bsp(root, per, [u, v], rnd)) {
|
|
2805
|
+
if (out.length >= maxFragments) return out;
|
|
2806
|
+
const c = [b.c[0], b.c[1], b.c[2]];
|
|
2807
|
+
c[t] = off;
|
|
2808
|
+
out.push({ center: c, size: [b.s[u], b.s[v], sheet], q: frame(u, v, t, (rnd() - 0.5) * 0.8), shape: "scrap", weight: b.s[u] * b.s[v], inner: out.length % 4 !== 0 });
|
|
2809
|
+
}
|
|
2810
|
+
}
|
|
2811
|
+
return out;
|
|
2812
|
+
};
|
|
2813
|
+
var STACK_LAYER = 0.012;
|
|
2758
2814
|
var planFragments = (inp) => {
|
|
2759
2815
|
const { style, dims, rnd, maxFragments } = inp;
|
|
2760
2816
|
const [fmin, fmax] = inp.fragmentSize;
|
|
@@ -2776,27 +2832,14 @@ var GameFloorplanStructure = (() => {
|
|
|
2776
2832
|
return out;
|
|
2777
2833
|
}
|
|
2778
2834
|
if (style === "splinter") {
|
|
2779
|
-
|
|
2780
|
-
const
|
|
2781
|
-
const w = Math.max(fmin * 1.5, 0.01);
|
|
2782
|
-
const c = clamp3(Math.round(dims[a] * dims[b] / (w * w)), 3, Math.max(3, Math.floor(maxFragments / 2)));
|
|
2783
|
-
const maxLen = fmax * 4;
|
|
2784
|
-
const cells = bsp(root, c, [a, b], rnd);
|
|
2785
|
-
const pieces = [];
|
|
2786
|
-
for (const cell of cells) {
|
|
2787
|
-
let list = [cell];
|
|
2788
|
-
const extra = rnd() < 0.4 ? 1 : 0;
|
|
2789
|
-
const k = Math.max(1, Math.ceil(dims[g] / maxLen)) + extra;
|
|
2790
|
-
list = bsp(cell, k, [g], rnd);
|
|
2791
|
-
for (const p of list) pieces.push(p);
|
|
2792
|
-
}
|
|
2793
|
-
for (const p of pieces.slice(0, maxFragments)) {
|
|
2794
|
-
out.push({ center: p.c, size: [p.s[g], p.s[a], p.s[b]], q: frame(g, a, b), shape: "splinter", weight: p.s[0] * p.s[1] * p.s[2] });
|
|
2795
|
-
}
|
|
2835
|
+
if (inp.cut) return severAt(inp, root, inp.cut.at, inp.cut.gap);
|
|
2836
|
+
for (const p of splinterBox(inp, root)) out.push(p);
|
|
2796
2837
|
return out;
|
|
2797
2838
|
}
|
|
2798
2839
|
if (style === "tear") {
|
|
2799
2840
|
const n2 = clamp3(Math.round(dims[u] * dims[v] / (mean * mean)), 3, maxFragments);
|
|
2841
|
+
const sheet = inp.sheet ?? 0;
|
|
2842
|
+
if (sheet > 0 && dims[t] > sheet * 4) return tearStack(inp, root, t, u, v, n2, sheet);
|
|
2800
2843
|
const th2 = Math.min(inp.thickness, dims[t]);
|
|
2801
2844
|
for (const b of bsp(root, n2, [u, v], rnd)) {
|
|
2802
2845
|
out.push({ center: [b.c[0], b.c[1], b.c[2]], size: [b.s[u], b.s[v], th2], q: frame(u, v, t), shape: "scrap", weight: b.s[u] * b.s[v] });
|
|
@@ -4379,6 +4422,7 @@ var GameFloorplanStructure = (() => {
|
|
|
4379
4422
|
0.03,
|
|
4380
4423
|
0.15
|
|
4381
4424
|
],
|
|
4425
|
+
sheet: 1e-3,
|
|
4382
4426
|
damageScale: {
|
|
4383
4427
|
slash: 3
|
|
4384
4428
|
},
|
|
@@ -4394,7 +4438,8 @@ var GameFloorplanStructure = (() => {
|
|
|
4394
4438
|
smoke: "grey"
|
|
4395
4439
|
},
|
|
4396
4440
|
visual: {
|
|
4397
|
-
charColor: 1709072
|
|
4441
|
+
charColor: 1709072,
|
|
4442
|
+
innerColor: 15524048
|
|
4398
4443
|
},
|
|
4399
4444
|
tags: [
|
|
4400
4445
|
"fabric",
|
|
@@ -4776,9 +4821,14 @@ var GameFloorplanStructure = (() => {
|
|
|
4776
4821
|
var BREACH_AREA = 0.25;
|
|
4777
4822
|
var BREACH_BLAST_REACH = 0.12;
|
|
4778
4823
|
var RESIDUAL_CAPACITY = 0.15;
|
|
4824
|
+
var SEVER_BAND = 0.1;
|
|
4825
|
+
var SEVER_ASPECT = 3;
|
|
4826
|
+
var SEVER_BALLISTIC = 2;
|
|
4779
4827
|
var SUPPORT_TOLERANCE = 0.05;
|
|
4780
4828
|
var UNIT_FRAGMENT_FACTOR = 4;
|
|
4781
4829
|
var BREACH_GRID_CAP = 4096;
|
|
4830
|
+
var CHIP_ENERGY = 200;
|
|
4831
|
+
var CHIP_SPLASH = 0.5;
|
|
4782
4832
|
var CUT_SLICE = 1;
|
|
4783
4833
|
var cutFactorOf = (shape) => clamp22(Math.max(...shapeDims(shape)) / CUT_SLICE, 1, 50);
|
|
4784
4834
|
var clamp22 = (v, a, b) => Math.max(a, Math.min(b, v));
|
|
@@ -4822,6 +4872,7 @@ var GameFloorplanStructure = (() => {
|
|
|
4822
4872
|
let windCfg = windOpts ? resolveWind(windOpts) : null;
|
|
4823
4873
|
const ignitionRules = resolveIgnitionRules(options.ignition);
|
|
4824
4874
|
const breachBlastFactor = options.breach?.blastFactor ?? BREACH_BLAST_FACTOR;
|
|
4875
|
+
const chipEnergy = options.breach?.chipEnergy ?? CHIP_ENERGY;
|
|
4825
4876
|
const rng = createRng(options.seed ?? 1);
|
|
4826
4877
|
const rnd = () => rng.next();
|
|
4827
4878
|
let time = 0;
|
|
@@ -5195,41 +5246,68 @@ var GameFloorplanStructure = (() => {
|
|
|
5195
5246
|
markDamaged(p);
|
|
5196
5247
|
if (p.rt.hinge >= flexure.failRotationDeg * Math.PI / 180) hingeDrop(o, p, src);
|
|
5197
5248
|
};
|
|
5249
|
+
const freeSpan = (p, supports) => {
|
|
5250
|
+
if (supports.length === 0) return Infinity;
|
|
5251
|
+
const d = p.dims;
|
|
5252
|
+
const L = [0, 1, 2].sort((a, b) => d[b] - d[a])[0];
|
|
5253
|
+
const spans = supports.map((k) => contactBox(p, k)).map(([lo, hi]) => [lo[L], hi[L]]);
|
|
5254
|
+
let far = 0;
|
|
5255
|
+
for (let i = 0; i <= 16; i++) {
|
|
5256
|
+
const x = (i / 16 - 0.5) * d[L];
|
|
5257
|
+
let near = Infinity;
|
|
5258
|
+
for (const [lo, hi] of spans) near = Math.min(near, Math.max(lo - x, x - hi, 0));
|
|
5259
|
+
far = Math.max(far, near);
|
|
5260
|
+
}
|
|
5261
|
+
return 2 * far;
|
|
5262
|
+
};
|
|
5198
5263
|
const solveStructure = (o) => {
|
|
5199
5264
|
o.maxStress = 0;
|
|
5200
5265
|
if (!o.hasStructure) return;
|
|
5201
5266
|
const parts = o.parts;
|
|
5202
5267
|
const n = parts.length;
|
|
5203
5268
|
const dist = new Array(n).fill(-1);
|
|
5204
|
-
const queue = [];
|
|
5205
5269
|
const ok = (i) => parts[i].structural && !isLost(parts[i]);
|
|
5206
5270
|
const isPartition = (i) => parts[i].spec.structure?.role === "partition";
|
|
5207
|
-
|
|
5208
|
-
|
|
5209
|
-
|
|
5210
|
-
|
|
5211
|
-
|
|
5212
|
-
|
|
5213
|
-
if (
|
|
5214
|
-
|
|
5215
|
-
|
|
5216
|
-
const r = j.ia === s ? j.ib : j.ia;
|
|
5217
|
-
if (dist[r] >= 0 || !ok(r) || restsOn(o, j, r) !== s) continue;
|
|
5218
|
-
dist[r] = dist[s] + 1;
|
|
5219
|
-
queue.push(r);
|
|
5271
|
+
const out = /* @__PURE__ */ new Set();
|
|
5272
|
+
let queue = [];
|
|
5273
|
+
let lowerOf = /* @__PURE__ */ new Map();
|
|
5274
|
+
for (; ; ) {
|
|
5275
|
+
dist.fill(-1);
|
|
5276
|
+
queue = [];
|
|
5277
|
+
for (let i = 0; i < n; i++) if (ok(i) && !out.has(i) && parts[i].anchored) {
|
|
5278
|
+
dist[i] = 0;
|
|
5279
|
+
queue.push(i);
|
|
5220
5280
|
}
|
|
5221
|
-
|
|
5222
|
-
|
|
5223
|
-
|
|
5224
|
-
|
|
5225
|
-
|
|
5226
|
-
|
|
5227
|
-
|
|
5228
|
-
|
|
5229
|
-
|
|
5281
|
+
for (let h = 0; h < queue.length; h++) {
|
|
5282
|
+
const s = queue[h];
|
|
5283
|
+
if (isPartition(s)) continue;
|
|
5284
|
+
for (const j of o.byPart.get(parts[s].spec.id)) {
|
|
5285
|
+
if (j.st.open || !j.bears) continue;
|
|
5286
|
+
const r = j.ia === s ? j.ib : j.ia;
|
|
5287
|
+
if (dist[r] >= 0 || !ok(r) || out.has(r) || restsOn(o, j, r) !== s) continue;
|
|
5288
|
+
dist[r] = dist[s] + 1;
|
|
5289
|
+
queue.push(r);
|
|
5290
|
+
}
|
|
5291
|
+
}
|
|
5292
|
+
lowerOf = /* @__PURE__ */ new Map();
|
|
5293
|
+
let dropped = false;
|
|
5294
|
+
for (const i of queue) {
|
|
5295
|
+
const lower = [];
|
|
5296
|
+
for (const j of o.byPart.get(parts[i].spec.id)) {
|
|
5297
|
+
if (j.st.open || !j.bears) continue;
|
|
5298
|
+
const k = restsOn(o, j, i);
|
|
5299
|
+
if (k >= 0 && dist[k] >= 0 && dist[k] < dist[i] && !isPartition(k)) lower.push(k);
|
|
5300
|
+
}
|
|
5301
|
+
lowerOf.set(i, lower);
|
|
5302
|
+
const max = parts[i].spec.structure?.maxSpan;
|
|
5303
|
+
if (max !== void 0 && !parts[i].anchored && freeSpan(parts[i], lower.map((k) => parts[k])) > max) {
|
|
5304
|
+
out.add(i);
|
|
5305
|
+
dropped = true;
|
|
5306
|
+
}
|
|
5230
5307
|
}
|
|
5231
|
-
|
|
5308
|
+
if (!dropped) break;
|
|
5232
5309
|
}
|
|
5310
|
+
const incoming = new Array(n).fill(0);
|
|
5233
5311
|
const bending = new Array(n).fill(0);
|
|
5234
5312
|
const through = parts.map(() => []);
|
|
5235
5313
|
const pass = (k, at2, mass) => {
|
|
@@ -5741,6 +5819,7 @@ var GameFloorplanStructure = (() => {
|
|
|
5741
5819
|
const r = rayPart(o, p, origin, d);
|
|
5742
5820
|
if (!r || r.t0 < 0 || r.t0 > maxDist) continue;
|
|
5743
5821
|
if (p.st.opening && insideOpening(o, p, vec.madd(origin, d, r.t0))) continue;
|
|
5822
|
+
if (p.st.chipped && insideChip(p, objLocal(o, vec.madd(origin, d, r.t0)))) continue;
|
|
5744
5823
|
if (!best || r.t0 < best.distance) best = { object: o.id, part: p.spec.id, point: vec.madd(origin, d, r.t0), normal: r.n, distance: r.t0, pathLen: r.t1 - r.t0 };
|
|
5745
5824
|
}
|
|
5746
5825
|
}
|
|
@@ -6004,6 +6083,62 @@ var GameFloorplanStructure = (() => {
|
|
|
6004
6083
|
if (total < (p.spec.breach?.area ?? BREACH_AREA)) return;
|
|
6005
6084
|
openBreach(o, p, [sum[0] / total, sum[1] / total, sum[2] / total], total, energy, dir, src);
|
|
6006
6085
|
};
|
|
6086
|
+
const unitGrids = /* @__PURE__ */ new WeakMap();
|
|
6087
|
+
const gridOf = (p) => {
|
|
6088
|
+
let grid = unitGrids.get(p);
|
|
6089
|
+
if (!grid) unitGrids.set(p, grid = unitGrid(p.dims, p.thin, unitsOf2(p), BREACH_GRID_CAP));
|
|
6090
|
+
return grid;
|
|
6091
|
+
};
|
|
6092
|
+
const insideChip = (p, objectPoint) => {
|
|
6093
|
+
const cells = p.st.chipped;
|
|
6094
|
+
if (!cells?.length) return false;
|
|
6095
|
+
const [u, v] = planeAxes(p.thin);
|
|
6096
|
+
const lp = toLocal(p.pos, p.q, objectPoint);
|
|
6097
|
+
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);
|
|
6098
|
+
};
|
|
6099
|
+
const chipUnits = (o, p, wp, energy, dir, radius, src) => {
|
|
6100
|
+
var _a, _b;
|
|
6101
|
+
if (!p.spec.units || p.spec.reinforcement || !p.staged || chipEnergy <= 0 || energy <= 0 || p.st.stripped || isLost(p) || (p.st.stage ?? 0) >= 2) return;
|
|
6102
|
+
const [u, v] = planeAxes(p.thin);
|
|
6103
|
+
const lp = toLocal(p.pos, p.q, objLocal(o, wp));
|
|
6104
|
+
const grid = gridOf(p);
|
|
6105
|
+
const worn = (_a = p.rt).chips ?? (_a.chips = {});
|
|
6106
|
+
const out = [];
|
|
6107
|
+
for (let i = 0; i < grid.length; i++) {
|
|
6108
|
+
const cell = grid[i];
|
|
6109
|
+
if (worn[i] === -1) continue;
|
|
6110
|
+
const gap = Math.hypot(Math.max(0, Math.abs(lp[u] - cell.center[u]) - cell.size[u] / 2), Math.max(0, Math.abs(lp[v] - cell.center[v]) - cell.size[v] / 2));
|
|
6111
|
+
if (gap > radius) continue;
|
|
6112
|
+
const share = gap === 0 ? 1 : CHIP_SPLASH * (1 - gap / radius);
|
|
6113
|
+
const total = (worn[i] ?? 0) + energy * share;
|
|
6114
|
+
const mass = p.mat.density * cell.size[0] * cell.size[1] * cell.size[2];
|
|
6115
|
+
if (total < chipEnergy * mass) {
|
|
6116
|
+
worn[i] = total;
|
|
6117
|
+
continue;
|
|
6118
|
+
}
|
|
6119
|
+
worn[i] = -1;
|
|
6120
|
+
out.push(cell);
|
|
6121
|
+
}
|
|
6122
|
+
if (out.length === 0) return;
|
|
6123
|
+
const { c, q } = partXf(o, p);
|
|
6124
|
+
const chipped = (_b = p.st).chipped ?? (_b.chipped = []);
|
|
6125
|
+
const holes = localHolesOf(p);
|
|
6126
|
+
for (const cell of out) {
|
|
6127
|
+
const mass = Math.min(p.st.mass, p.mat.density * cell.size[0] * cell.size[1] * cell.size[2]);
|
|
6128
|
+
const center = toWorld(c, q, cell.center);
|
|
6129
|
+
const speed = clamp22(Math.sqrt(2 * energy * 0.05 / Math.max(mass, 0.05)), 0.5, 6);
|
|
6130
|
+
const fragments = cellFragments(o, p, [cell], wp, dir, speed, mass, `c${chipped.length}_`);
|
|
6131
|
+
p.st.holes = p.st.holes.filter((_, k) => marksInBox(cell.center, cell.size, void 0, [holes[k]]).length === 0);
|
|
6132
|
+
chipped.push({ center: [cell.center[0], cell.center[1], cell.center[2]], size: [cell.size[0], cell.size[1], cell.size[2]] });
|
|
6133
|
+
p.st.mass = Math.max(0, p.st.mass - mass);
|
|
6134
|
+
p.rt.removed = (p.rt.removed ?? 0) + mass;
|
|
6135
|
+
markDamaged(p);
|
|
6136
|
+
setStage(o, p, 1, {}, src);
|
|
6137
|
+
emit({ ...base(o, src), type: "chip", part: p.spec.id, center, size: [cell.size[0], cell.size[1], cell.size[2]], rotation: q, fragments });
|
|
6138
|
+
debris(o, p, p.mat.breakDebris, center, vec.scale(dir ?? [0, 1, 0], -1), 6, 2, src);
|
|
6139
|
+
}
|
|
6140
|
+
for (const cell of out) addBreach(o, p, toWorld(c, q, cell.center), cell.size[u] * cell.size[v], energy, dir, src);
|
|
6141
|
+
};
|
|
6007
6142
|
const openBreach = (o, p, center, total, energy, dir, src) => {
|
|
6008
6143
|
const [u, v] = planeAxes(p.thin);
|
|
6009
6144
|
const radius = clamp22(Math.sqrt(total / Math.PI), Math.sqrt((p.spec.breach?.area ?? BREACH_AREA) / Math.PI), breachRadius);
|
|
@@ -6015,7 +6150,8 @@ var GameFloorplanStructure = (() => {
|
|
|
6015
6150
|
failPart(o, p, worldCenter, dir, energy, 12, src);
|
|
6016
6151
|
return;
|
|
6017
6152
|
}
|
|
6018
|
-
const
|
|
6153
|
+
const worn = p.rt.chips;
|
|
6154
|
+
const cells = cellsWithin(gridOf(p).filter((_, i) => worn?.[i] !== -1), p.thin, lc, radius);
|
|
6019
6155
|
const removed = p.st.mass * cells.reduce((sum, cell) => sum + cell.size[u] * cell.size[v], 0) / (p.dims[u] * p.dims[v]);
|
|
6020
6156
|
const speed = clamp22(Math.sqrt(2 * energy * 0.1 / Math.max(removed, 0.05)), 0.5, 8);
|
|
6021
6157
|
const fragments = cellFragments(o, p, cells, worldCenter, dir, speed, removed, "b");
|
|
@@ -6099,6 +6235,8 @@ var GameFloorplanStructure = (() => {
|
|
|
6099
6235
|
const grain = p.spec.grain ? AXIS[p.spec.grain] : void 0;
|
|
6100
6236
|
const hitLocal = toLocal(c, q, hitW);
|
|
6101
6237
|
const unitPlan = p.spec.units ? unitFragmentPlan(p, maxFragments * UNIT_FRAGMENT_FACTOR) : [];
|
|
6238
|
+
const axis = style === "splinter" ? severAxis(p) : -1;
|
|
6239
|
+
const cutAt2 = axis < 0 ? void 0 : p.rt.cutAt ?? (origin ? hitLocal[axis] : void 0);
|
|
6102
6240
|
const plan = unitPlan.length > 0 ? unitPlan : planFragments({
|
|
6103
6241
|
style,
|
|
6104
6242
|
dims: p.dims,
|
|
@@ -6107,7 +6245,9 @@ var GameFloorplanStructure = (() => {
|
|
|
6107
6245
|
hit: hitLocal,
|
|
6108
6246
|
fragmentSize: p.mat.fragmentSize ?? [0.04, 0.2],
|
|
6109
6247
|
maxFragments,
|
|
6110
|
-
rnd
|
|
6248
|
+
rnd,
|
|
6249
|
+
sheet: p.mat.sheet,
|
|
6250
|
+
...cutAt2 !== void 0 ? { cut: { at: cutAt2, gap: SEVER_BAND } } : {}
|
|
6111
6251
|
});
|
|
6112
6252
|
const holes = p.st.holes.length > 0 ? localHolesOf(p) : [];
|
|
6113
6253
|
const mass = p.st.mass;
|
|
@@ -6131,7 +6271,8 @@ var GameFloorplanStructure = (() => {
|
|
|
6131
6271
|
velocity: [dv[0] * k, dv[1] * k + 0.5 * rnd(), dv[2] * k],
|
|
6132
6272
|
angularVelocity: [(rnd() - 0.5) * 12, (rnd() - 0.5) * 12, (rnd() - 0.5) * 12],
|
|
6133
6273
|
mass: mass * f.weight / totW,
|
|
6134
|
-
...marks.length > 0 ? { marks } : {}
|
|
6274
|
+
...marks.length > 0 ? { marks } : {},
|
|
6275
|
+
...f.inner ? { inner: true } : {}
|
|
6135
6276
|
};
|
|
6136
6277
|
});
|
|
6137
6278
|
const reinforcement = p.spec.reinforcement;
|
|
@@ -6165,10 +6306,33 @@ var GameFloorplanStructure = (() => {
|
|
|
6165
6306
|
emit({ ...base(o, src), type: "primed", part: p.spec.id, point: partXf(o, p).c, trigger, delay });
|
|
6166
6307
|
};
|
|
6167
6308
|
const CHAIN_TRIGGER_OF = { ballistic: "shot", explosive: "explosion" };
|
|
6309
|
+
const severAxis = (p) => {
|
|
6310
|
+
if (p.mat.fracture !== "splinter" || p.spec.shape.kind !== "box") return -1;
|
|
6311
|
+
const d = p.dims;
|
|
6312
|
+
const order = [0, 1, 2].sort((a, b) => d[b] - d[a]);
|
|
6313
|
+
return d[order[0]] >= SEVER_ASPECT * d[order[1]] && d[order[0]] >= 3 * SEVER_BAND ? order[0] : -1;
|
|
6314
|
+
};
|
|
6315
|
+
const bandOf = (o, p, axis, origin) => {
|
|
6316
|
+
const { c, q } = partXf(o, p);
|
|
6317
|
+
const along = toLocal(c, q, origin)[axis];
|
|
6318
|
+
const L = p.dims[axis];
|
|
6319
|
+
return clamp22(Math.floor((along + L / 2) / SEVER_BAND), 0, Math.ceil(L / SEVER_BAND) - 1);
|
|
6320
|
+
};
|
|
6168
6321
|
const applyDamage = (o, p, amount, type, origin, dir, fragEnergy, cap, src) => {
|
|
6322
|
+
var _a;
|
|
6169
6323
|
if (isLost(p) || amount <= 0) return 0;
|
|
6170
6324
|
const prev = p.st.hp;
|
|
6171
6325
|
p.st.hp -= amount;
|
|
6326
|
+
const axis = origin && type !== "fire" && type !== "heat" ? severAxis(p) : -1;
|
|
6327
|
+
if (axis >= 0 && p.st.hp > 0) {
|
|
6328
|
+
const band = bandOf(o, p, axis, origin);
|
|
6329
|
+
const cuts = (_a = p.rt).cuts ?? (_a.cuts = {});
|
|
6330
|
+
cuts[band] = (cuts[band] ?? 0) + amount * (type === "ballistic" ? SEVER_BALLISTIC : 1);
|
|
6331
|
+
if (cuts[band] >= p.st.maxHp * SEVER_BAND / p.dims[axis]) {
|
|
6332
|
+
p.rt.cutAt = -p.dims[axis] / 2 + (band + 0.5) * SEVER_BAND;
|
|
6333
|
+
p.st.hp = 0;
|
|
6334
|
+
}
|
|
6335
|
+
}
|
|
6172
6336
|
markDamaged(p);
|
|
6173
6337
|
const trigger = CHAIN_TRIGGER_OF[type];
|
|
6174
6338
|
const chained = trigger !== void 0 && chainDelayOf(p.spec, trigger) !== void 0;
|
|
@@ -6207,7 +6371,7 @@ var GameFloorplanStructure = (() => {
|
|
|
6207
6371
|
const ballistic = (o, p, entry2, n, d, E, caliber, pathLen, src, round3 = {}) => {
|
|
6208
6372
|
const mat = p.mat;
|
|
6209
6373
|
const piercing = round3.piercing ?? 1;
|
|
6210
|
-
if (p.st.stripped || p.st.opening && insideOpening(o, p, objLocal(o, entry2))) {
|
|
6374
|
+
if (p.st.stripped || p.st.opening && insideOpening(o, p, objLocal(o, entry2)) || insideChip(p, objLocal(o, entry2))) {
|
|
6211
6375
|
return { penetrated: true, exitEnergy: E, exitPoint: vec.madd(entry2, d, Math.min(pathLen, p.thickness)), damage: 0 };
|
|
6212
6376
|
}
|
|
6213
6377
|
const sin = Math.min(1, Math.abs(vec.dot(d, n)));
|
|
@@ -6266,6 +6430,7 @@ var GameFloorplanStructure = (() => {
|
|
|
6266
6430
|
debris(o, p, mat.hitDebris, entry2, n, clamp22(Math.round(E / 60) + 2, 2, 14), clamp22(Math.sqrt(E) / 6, 1, 8), src);
|
|
6267
6431
|
wearJoints(o, p, (penetrated ? thr : E) * 0.02, void 0, 0, src, true);
|
|
6268
6432
|
const dmg = applyDamage(o, p, E * DMG_PER_J * scale, "ballistic", entry2, d, E * 0.1, 12, src);
|
|
6433
|
+
chipUnits(o, p, entry2, penetrated ? Math.min(E, Math.max(thr, E * 0.5)) : E, d, Math.max(0.05, caliber / 1e3 * 8), src);
|
|
6269
6434
|
return { penetrated, exitEnergy: penetrated ? penMm !== void 0 ? E * (1 - thr / Ep) : E - thr / (hard ? piercing : 1) : 0, exitPoint, damage: dmg };
|
|
6270
6435
|
};
|
|
6271
6436
|
const melee = (o, p, kind, E, point, n, d, contactR, src) => {
|
|
@@ -6293,6 +6458,7 @@ var GameFloorplanStructure = (() => {
|
|
|
6293
6458
|
const scale = mat.damageScale?.[kind] ?? 1;
|
|
6294
6459
|
const done = applyDamage(o, p, Ec * DMG_PER_J * scale * (kind === "slash" ? p.cutFactor : 1), kind, point, d, E * 0.1, 12, src);
|
|
6295
6460
|
addBreach(o, p, point, breachAreaOf(p, done, false), E, d, src);
|
|
6461
|
+
if (kind === "blunt") chipUnits(o, p, point, E, d, Math.max(contactR, 0.03), src);
|
|
6296
6462
|
return done;
|
|
6297
6463
|
};
|
|
6298
6464
|
const blastPart = (o, p, point, energy, radius, src, res, reachAt) => {
|