@adatechnology/game-floorplan-structure 1.3.0 → 1.3.2
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 +159 -23
- package/dist/index.global.js.map +1 -1
- package/package.json +6 -7
package/dist/index.global.js
CHANGED
|
@@ -4217,6 +4217,7 @@ var GameFloorplanStructure = (() => {
|
|
|
4217
4217
|
},
|
|
4218
4218
|
hitDebris: "chips",
|
|
4219
4219
|
breakDebris: "dust",
|
|
4220
|
+
visual: { innerColor: 10197652 },
|
|
4220
4221
|
thermal: {
|
|
4221
4222
|
conductivity: 0.15,
|
|
4222
4223
|
heatCapacity: 2.5
|
|
@@ -4247,6 +4248,7 @@ var GameFloorplanStructure = (() => {
|
|
|
4247
4248
|
],
|
|
4248
4249
|
hitDebris: "chips",
|
|
4249
4250
|
breakDebris: "dust",
|
|
4251
|
+
visual: { innerColor: 12085567 },
|
|
4250
4252
|
thermal: {
|
|
4251
4253
|
conductivity: 0.15,
|
|
4252
4254
|
heatCapacity: 2.5
|
|
@@ -4277,6 +4279,7 @@ var GameFloorplanStructure = (() => {
|
|
|
4277
4279
|
],
|
|
4278
4280
|
hitDebris: "dust",
|
|
4279
4281
|
breakDebris: "dust",
|
|
4282
|
+
visual: { innerColor: 14999507 },
|
|
4280
4283
|
thermal: {
|
|
4281
4284
|
conductivity: 0.1,
|
|
4282
4285
|
heatCapacity: 1.5
|
|
@@ -4302,6 +4305,7 @@ var GameFloorplanStructure = (() => {
|
|
|
4302
4305
|
],
|
|
4303
4306
|
hitDebris: "chips",
|
|
4304
4307
|
breakDebris: "dust",
|
|
4308
|
+
visual: { innerColor: 9407364 },
|
|
4305
4309
|
thermal: {
|
|
4306
4310
|
conductivity: 0.2,
|
|
4307
4311
|
heatCapacity: 2.5
|
|
@@ -5043,6 +5047,7 @@ var GameFloorplanStructure = (() => {
|
|
|
5043
5047
|
var FLAMMABLE_FLUIDS = ["gas", "fuel"];
|
|
5044
5048
|
var VENT_DIAMETER = 8e-3;
|
|
5045
5049
|
var FLAME_LIGHTS_LEAK_C = 470;
|
|
5050
|
+
var RESTING_HOLD_COS = Math.cos(Math.PI / 6);
|
|
5046
5051
|
var BREACH_RADIUS = 0.55;
|
|
5047
5052
|
var BREACH_BLAST_FACTOR = 6;
|
|
5048
5053
|
var BREACH_AREA = 0.25;
|
|
@@ -5058,7 +5063,9 @@ var GameFloorplanStructure = (() => {
|
|
|
5058
5063
|
var BREACH_GRID_CAP = 4096;
|
|
5059
5064
|
var CHIP_ENERGY = 200;
|
|
5060
5065
|
var CHIP_SPLASH = 0.5;
|
|
5066
|
+
var CRATER_SPENT = 0.6;
|
|
5061
5067
|
var BAR_BOW = 0.08;
|
|
5068
|
+
var BULLET_JOINT_SPAN = 0.3;
|
|
5062
5069
|
var CUT_SLICE = 1;
|
|
5063
5070
|
var cutFactorOf = (shape) => clamp22(Math.max(...shapeDims(shape)) / CUT_SLICE, 1, 50);
|
|
5064
5071
|
var clamp22 = (v, a, b) => Math.max(a, Math.min(b, v));
|
|
@@ -5077,12 +5084,22 @@ var GameFloorplanStructure = (() => {
|
|
|
5077
5084
|
const cells = p.st.chipped;
|
|
5078
5085
|
if (!cells?.length) return 0;
|
|
5079
5086
|
const [u, v] = planeAxes(p.thin);
|
|
5080
|
-
const
|
|
5087
|
+
const role = p.spec.structure?.role;
|
|
5088
|
+
const up = rotateVec(p.q, [0, 0, 0].map((_, k) => k === v ? 1 : 0));
|
|
5089
|
+
const upright = Math.abs(up[1]) > 0.7 ? v : Math.abs(rotateVec(p.q, [0, 0, 0].map((_, k) => k === u ? 1 : 0))[1]) > 0.7 ? u : -1;
|
|
5090
|
+
const along = (role === "wall" || role === "partition" || role === "column") && upright >= 0 ? upright : p.dims[u] >= p.dims[v] ? u : v;
|
|
5081
5091
|
const across = along === u ? v : u;
|
|
5082
5092
|
let worst = 0;
|
|
5083
5093
|
for (const c of cells) {
|
|
5084
|
-
|
|
5085
|
-
for (const d of cells) if (Math.abs(d.center[along] - c.center[along]) < d.size[along] / 2 + 1e-6)
|
|
5094
|
+
const spans = [];
|
|
5095
|
+
for (const d of cells) if (Math.abs(d.center[along] - c.center[along]) < d.size[along] / 2 + 1e-6) spans.push([d.center[across] - d.size[across] / 2, d.center[across] + d.size[across] / 2]);
|
|
5096
|
+
spans.sort((a, b) => a[0] - b[0]);
|
|
5097
|
+
let gone = 0, end = -Infinity;
|
|
5098
|
+
for (const [a, b] of spans) {
|
|
5099
|
+
if (b <= end) continue;
|
|
5100
|
+
gone += b - Math.max(a, end);
|
|
5101
|
+
end = b;
|
|
5102
|
+
}
|
|
5086
5103
|
worst = Math.max(worst, gone / Math.max(p.dims[across], 1e-6));
|
|
5087
5104
|
}
|
|
5088
5105
|
return Math.min(1, worst);
|
|
@@ -5378,7 +5395,18 @@ var GameFloorplanStructure = (() => {
|
|
|
5378
5395
|
if (k < 0 || j.spec.kind !== "tie") return k;
|
|
5379
5396
|
return partXf(o, o.parts[k]).c[1] > partXf(o, o.parts[r]).c[1] + 1e-6 ? k : -1;
|
|
5380
5397
|
};
|
|
5398
|
+
let poseVersion = 0;
|
|
5399
|
+
const contactMemo = /* @__PURE__ */ new WeakMap();
|
|
5381
5400
|
const contactBox = (p, support) => {
|
|
5401
|
+
let byTouching = contactMemo.get(p);
|
|
5402
|
+
if (!byTouching) contactMemo.set(p, byTouching = /* @__PURE__ */ new Map());
|
|
5403
|
+
const known = byTouching.get(support);
|
|
5404
|
+
if (known && known.version === poseVersion) return known.box;
|
|
5405
|
+
const box2 = measureContact(p, support);
|
|
5406
|
+
byTouching.set(support, { version: poseVersion, box: box2 });
|
|
5407
|
+
return box2;
|
|
5408
|
+
};
|
|
5409
|
+
const measureContact = (p, support) => {
|
|
5382
5410
|
const A = aabbOf(p.spec.shape, p.pos, p.q), B = aabbOf(support.spec.shape, support.pos, support.q);
|
|
5383
5411
|
const lo = [0, 0, 0], hi = [0, 0, 0];
|
|
5384
5412
|
for (let k = 0; k < 3; k++) {
|
|
@@ -6173,7 +6201,7 @@ var GameFloorplanStructure = (() => {
|
|
|
6173
6201
|
p.st.holes.push(hole);
|
|
6174
6202
|
if (p.st.holes.length > maxHoles) p.st.holes.shift();
|
|
6175
6203
|
markDamaged(p);
|
|
6176
|
-
emit({ ...base(o, src), type: "hole", part: p.spec.id, hole, worldPoint: wp, ...exit ? { exitPoint: exit } : {} });
|
|
6204
|
+
emit({ ...base(o, src), type: "hole", part: p.spec.id, hole, worldPoint: wp, ...exit ? { exitPoint: exit } : {}, ...p.spec.powder ? { powder: { ...p.spec.powder } } : {} });
|
|
6177
6205
|
setStage(o, p, 1, {}, src);
|
|
6178
6206
|
return hole;
|
|
6179
6207
|
};
|
|
@@ -6185,11 +6213,27 @@ var GameFloorplanStructure = (() => {
|
|
|
6185
6213
|
emit({ ...base(o, src), type: "crack", part: p.spec.id, crack, worldPoint: wp });
|
|
6186
6214
|
setStage(o, p, 1, {}, src);
|
|
6187
6215
|
};
|
|
6188
|
-
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 });
|
|
6216
|
+
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 } : {} });
|
|
6189
6217
|
const holeRate = (hole, pressurized) => (pressurized ? 0.5 : 0.1) * (hole.diameter / 9e-3);
|
|
6190
6218
|
const detachEvents = (o, opened, by, src) => {
|
|
6191
6219
|
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]) });
|
|
6192
6220
|
};
|
|
6221
|
+
const slideOffResting = (o, rotation) => {
|
|
6222
|
+
const upY = 1 - 2 * (rotation[0] * rotation[0] + rotation[2] * rotation[2]);
|
|
6223
|
+
if (upY >= RESTING_HOLD_COS) return;
|
|
6224
|
+
const opened = o.joints.filter((j) => j.spec.kind === "resting" && !j.st.open);
|
|
6225
|
+
if (opened.length === 0) return;
|
|
6226
|
+
run(() => {
|
|
6227
|
+
for (const j of opened) {
|
|
6228
|
+
j.st.open = true;
|
|
6229
|
+
j.st.openedBy = "break";
|
|
6230
|
+
}
|
|
6231
|
+
solveStructure(o);
|
|
6232
|
+
recomputeGroups(o);
|
|
6233
|
+
detachEvents(o, opened, "break");
|
|
6234
|
+
collapseCheck(o);
|
|
6235
|
+
});
|
|
6236
|
+
};
|
|
6193
6237
|
const checkDestroyed = (o, src) => {
|
|
6194
6238
|
if (!o.st.destroyed && o.parts.length > 0 && o.parts.every(isLost)) {
|
|
6195
6239
|
o.st.destroyed = true;
|
|
@@ -6226,7 +6270,13 @@ var GameFloorplanStructure = (() => {
|
|
|
6226
6270
|
const small = pa.dims[0] * pa.dims[1] * pa.dims[2] <= pb.dims[0] * pb.dims[1] * pb.dims[2] ? pa : pb;
|
|
6227
6271
|
return Math.max(0.06, 0.5 * Math.min(small.dims[0], small.dims[1], small.dims[2]));
|
|
6228
6272
|
};
|
|
6229
|
-
const
|
|
6273
|
+
const jointLength = (o, j) => {
|
|
6274
|
+
const A = partWorldAabb(o, o.parts[j.ia]), B = partWorldAabb(o, o.parts[j.ib]);
|
|
6275
|
+
let len = 0;
|
|
6276
|
+
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]));
|
|
6277
|
+
return len;
|
|
6278
|
+
};
|
|
6279
|
+
const wearJoints = (o, p, amount, near, radius = 0.06, src, split = false, span) => {
|
|
6230
6280
|
if (amount <= 0) return;
|
|
6231
6281
|
const mine = (o.byPart.get(p.spec.id) ?? []).filter((j) => !j.st.open);
|
|
6232
6282
|
if (split && mine.length) amount /= mine.length;
|
|
@@ -6234,7 +6284,7 @@ var GameFloorplanStructure = (() => {
|
|
|
6234
6284
|
if (j.st.open) continue;
|
|
6235
6285
|
if (j.spec.kind === "rebar" && (isReinforced(o.parts[j.ia].spec) || isReinforced(o.parts[j.ib].spec))) continue;
|
|
6236
6286
|
if (near && jointReach(o, j, near) > Math.max(radius, jointReachLimit(o, j))) continue;
|
|
6237
|
-
j.st.hp -= amount;
|
|
6287
|
+
j.st.hp -= span === void 0 ? amount : amount * Math.min(1, span / Math.max(jointLength(o, j), 1e-6));
|
|
6238
6288
|
if (j.st.hp <= 0) {
|
|
6239
6289
|
j.st.hp = 0;
|
|
6240
6290
|
j.st.open = true;
|
|
@@ -6263,7 +6313,7 @@ var GameFloorplanStructure = (() => {
|
|
|
6263
6313
|
if (spalls.length > MAX_SPALLS) spalls.shift();
|
|
6264
6314
|
markDamaged(p);
|
|
6265
6315
|
emit({ ...base(o, src), type: "spall", part: p.spec.id, layer: layer.index, point: wp, area: Math.PI * radius * radius });
|
|
6266
|
-
debris(o, p, layer.mat.hitDebris, wp, normal, 5, 2, src);
|
|
6316
|
+
debris(o, p, layer.mat.hitDebris, wp, normal, 5, 2, src, layer.mat.id);
|
|
6267
6317
|
setStage(o, p, 1, {}, src);
|
|
6268
6318
|
};
|
|
6269
6319
|
const crater = (o, p, wp, normal, radius, src) => {
|
|
@@ -6284,7 +6334,7 @@ var GameFloorplanStructure = (() => {
|
|
|
6284
6334
|
const localHolesOf = (p) => p.st.holes.map((h) => ({ point: toLocal(p.pos, p.q, h.point), normal: rotateVec(quat.conjugate(p.q), h.normal), diameter: h.diameter }));
|
|
6285
6335
|
const unitsOf2 = (p) => p.spec.units ?? { size: [p.mat.fragmentSize?.[1] ?? 0.2, p.mat.fragmentSize?.[1] ?? 0.2, p.thickness], bond: "stack" };
|
|
6286
6336
|
const FRAGMENT_SHAPE = { shatter: "shard", splinter: "splinter", tear: "scrap" };
|
|
6287
|
-
const cellFragments = (o, p, cells, hitW, dir, speed, mass, tag) => {
|
|
6337
|
+
const cellFragments = (o, p, cells, hitW, dir, speed, mass, tag, inner2 = false) => {
|
|
6288
6338
|
const { c, q } = partXf(o, p);
|
|
6289
6339
|
const holes = p.st.holes.length > 0 ? localHolesOf(p) : [];
|
|
6290
6340
|
const [u, v] = planeAxes(p.thin);
|
|
@@ -6308,7 +6358,8 @@ var GameFloorplanStructure = (() => {
|
|
|
6308
6358
|
velocity: [dv[0] * k, dv[1] * k + 0.5 * rnd(), dv[2] * k],
|
|
6309
6359
|
angularVelocity: [(rnd() - 0.5) * 8, (rnd() - 0.5) * 8, (rnd() - 0.5) * 8],
|
|
6310
6360
|
mass: mass * faceArea(cell) / total,
|
|
6311
|
-
...marks.length > 0 ? { marks } : {}
|
|
6361
|
+
...marks.length > 0 ? { marks } : {},
|
|
6362
|
+
...inner2 ? { inner: inner2 } : {}
|
|
6312
6363
|
};
|
|
6313
6364
|
});
|
|
6314
6365
|
};
|
|
@@ -6349,7 +6400,7 @@ var GameFloorplanStructure = (() => {
|
|
|
6349
6400
|
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);
|
|
6350
6401
|
};
|
|
6351
6402
|
const chipUnits = (o, p, kind, wp, hitEnergy, dir, radius, src) => {
|
|
6352
|
-
var _a, _b;
|
|
6403
|
+
var _a, _b, _c;
|
|
6353
6404
|
if (!p.spec.units || !p.staged || chipEnergy <= 0 || p.st.stripped || isLost(p) || (p.st.stage ?? 0) >= 2) return;
|
|
6354
6405
|
const rule = p.mat.hits?.[kind];
|
|
6355
6406
|
const perKg = rule?.unitJoules ?? chipEnergy;
|
|
@@ -6359,7 +6410,9 @@ var GameFloorplanStructure = (() => {
|
|
|
6359
6410
|
const lp = toLocal(p.pos, p.q, objLocal(o, wp));
|
|
6360
6411
|
const grid = gridOf(p);
|
|
6361
6412
|
const worn = (_a = p.rt).chips ?? (_a.chips = {});
|
|
6413
|
+
const cut = (_b = p.rt).craters ?? (_b.craters = {});
|
|
6362
6414
|
const out = [];
|
|
6415
|
+
const shot = kind === "ballistic";
|
|
6363
6416
|
for (let i = 0; i < grid.length; i++) {
|
|
6364
6417
|
const cell = grid[i];
|
|
6365
6418
|
if (worn[i] === -1) continue;
|
|
@@ -6372,18 +6425,39 @@ var GameFloorplanStructure = (() => {
|
|
|
6372
6425
|
worn[i] = total;
|
|
6373
6426
|
continue;
|
|
6374
6427
|
}
|
|
6375
|
-
|
|
6376
|
-
|
|
6428
|
+
if (!shot) {
|
|
6429
|
+
worn[i] = -1;
|
|
6430
|
+
out.push(cell);
|
|
6431
|
+
continue;
|
|
6432
|
+
}
|
|
6433
|
+
const size = [cell.size[0], cell.size[1], cell.size[2]];
|
|
6434
|
+
const center = [cell.center[0], cell.center[1], cell.center[2]];
|
|
6435
|
+
for (const a of [u, v]) {
|
|
6436
|
+
const w = Math.min(cell.size[a], craterAcross(hitEnergy) * (0.85 + 0.3 * rnd()));
|
|
6437
|
+
const lo = cell.center[a] - cell.size[a] / 2 + w / 2, hi = cell.center[a] + cell.size[a] / 2 - w / 2;
|
|
6438
|
+
size[a] = w;
|
|
6439
|
+
center[a] = clamp22(lp[a], lo, hi);
|
|
6440
|
+
}
|
|
6441
|
+
const taken2 = (cut[i] ?? 0) + size[u] * size[v];
|
|
6442
|
+
if (taken2 >= cell.size[u] * cell.size[v] * CRATER_SPENT) {
|
|
6443
|
+
worn[i] = -1;
|
|
6444
|
+
out.push({ ...cell, crater: true });
|
|
6445
|
+
continue;
|
|
6446
|
+
}
|
|
6447
|
+
worn[i] = 0;
|
|
6448
|
+
cut[i] = taken2;
|
|
6449
|
+
out.push({ center, size, crater: true });
|
|
6377
6450
|
}
|
|
6378
6451
|
if (out.length === 0) return;
|
|
6379
6452
|
const { c, q } = partXf(o, p);
|
|
6380
|
-
const chipped = (
|
|
6453
|
+
const chipped = (_c = p.st).chipped ?? (_c.chipped = []);
|
|
6381
6454
|
const holes = localHolesOf(p);
|
|
6382
6455
|
for (const cell of out) {
|
|
6383
6456
|
const mass = Math.min(p.st.mass, p.mat.density * cell.size[0] * cell.size[1] * cell.size[2]);
|
|
6384
6457
|
const center = toWorld(c, q, cell.center);
|
|
6385
6458
|
const speed = clamp22(Math.sqrt(2 * energy * 0.05 / Math.max(mass, 0.05)), 0.5, 6);
|
|
6386
|
-
const
|
|
6459
|
+
const tag = `c${chipped.length}_`;
|
|
6460
|
+
const fragments = cell.crater ? craterFragments(o, p, cell, dir, speed, mass, tag) : cellFragments(o, p, [cell], wp, dir, speed, mass, tag, true);
|
|
6387
6461
|
p.st.holes = p.st.holes.filter((_, k) => marksInBox(cell.center, cell.size, void 0, [holes[k]]).length === 0);
|
|
6388
6462
|
chipped.push({ center: [cell.center[0], cell.center[1], cell.center[2]], size: [cell.size[0], cell.size[1], cell.size[2]] });
|
|
6389
6463
|
p.st.mass = Math.max(0, p.st.mass - mass);
|
|
@@ -6400,6 +6474,44 @@ var GameFloorplanStructure = (() => {
|
|
|
6400
6474
|
collapseCheck(o, src);
|
|
6401
6475
|
}
|
|
6402
6476
|
};
|
|
6477
|
+
const craterAcross = (energy) => clamp22(0.03 + 12e-4 * Math.sqrt(Math.max(0, energy)), 0.03, 0.14);
|
|
6478
|
+
const craterFragments = (o, p, cell, dir, speed, mass, tag) => {
|
|
6479
|
+
const { c, q } = partXf(o, p);
|
|
6480
|
+
const [u, v] = planeAxes(p.thin);
|
|
6481
|
+
const d = dir ?? rotateVec(q, [p.thin === 0 ? 1 : 0, p.thin === 1 ? 1 : 0, p.thin === 2 ? 1 : 0]);
|
|
6482
|
+
const exitSign = Math.sign(rotateVec(quat.conjugate(q), d)[p.thin]) || 1;
|
|
6483
|
+
const bit = Math.max(0.01, Math.min(cell.size[u], cell.size[v]) / 3);
|
|
6484
|
+
const n = clamp22(Math.round(cell.size[u] * cell.size[v] / (bit * bit * 3)), 4, 10) + Math.floor(rnd() * 3);
|
|
6485
|
+
const out = [];
|
|
6486
|
+
for (let i = 0; i < n; i++) {
|
|
6487
|
+
const back = i % 3 === 2;
|
|
6488
|
+
const lc = [cell.center[0], cell.center[1], cell.center[2]];
|
|
6489
|
+
lc[u] += (rnd() - 0.5) * cell.size[u] * 0.7;
|
|
6490
|
+
lc[v] += (rnd() - 0.5) * cell.size[v] * 0.7;
|
|
6491
|
+
lc[p.thin] += (back ? -exitSign : exitSign) * (p.thickness / 2 + 0.01);
|
|
6492
|
+
const size = [0, 0, 0];
|
|
6493
|
+
size[u] = bit * (0.6 + 0.8 * rnd());
|
|
6494
|
+
size[v] = bit * (0.5 + 0.7 * rnd());
|
|
6495
|
+
size[p.thin] = bit * (0.4 + 0.6 * rnd());
|
|
6496
|
+
const spread3 = [(rnd() - 0.5) * 0.9, (rnd() - 0.3) * 0.9, (rnd() - 0.5) * 0.9];
|
|
6497
|
+
const k = speed * (back ? 0.4 + 0.4 * rnd() : 0.7 + 0.8 * rnd());
|
|
6498
|
+
const vdir = vec.normalize(vec.add(back ? vec.scale(d, -1) : d, spread3));
|
|
6499
|
+
out.push({
|
|
6500
|
+
id: `${p.spec.id}#${tag}${i}`,
|
|
6501
|
+
part: p.spec.id,
|
|
6502
|
+
material: p.spec.material,
|
|
6503
|
+
shape: "chunk",
|
|
6504
|
+
center: toWorld(c, q, lc),
|
|
6505
|
+
size,
|
|
6506
|
+
rotation: q,
|
|
6507
|
+
velocity: [vdir[0] * k, vdir[1] * k + 0.5 * rnd(), vdir[2] * k],
|
|
6508
|
+
angularVelocity: [(rnd() - 0.5) * 20, (rnd() - 0.5) * 20, (rnd() - 0.5) * 20],
|
|
6509
|
+
mass: mass / n,
|
|
6510
|
+
inner: true
|
|
6511
|
+
});
|
|
6512
|
+
}
|
|
6513
|
+
return out;
|
|
6514
|
+
};
|
|
6403
6515
|
const exposeRebar = (o, p, src) => {
|
|
6404
6516
|
const r = p.spec.reinforcement;
|
|
6405
6517
|
if (!r) return;
|
|
@@ -6687,7 +6799,7 @@ var GameFloorplanStructure = (() => {
|
|
|
6687
6799
|
});
|
|
6688
6800
|
}
|
|
6689
6801
|
const patch = [scale * 4, scale * 4, scale * 4];
|
|
6690
|
-
emit({ ...base(o, src), type: "chip", part: p.spec.id, center: exit ?? entry2, size: patch, rotation: q, fragments });
|
|
6802
|
+
emit({ ...base(o, src), type: "chip", part: p.spec.id, center: exit ?? entry2, size: patch, rotation: q, fragments, torn: true });
|
|
6691
6803
|
};
|
|
6692
6804
|
const ballistic = (o, p, entry2, n, d, E, caliber, pathLen, src, round3 = {}) => {
|
|
6693
6805
|
const mat = p.mat;
|
|
@@ -6746,12 +6858,13 @@ var GameFloorplanStructure = (() => {
|
|
|
6746
6858
|
} else if (mat.ductility >= 0.5) {
|
|
6747
6859
|
addDent(o, p, entry2, n, Math.max(caliber * 3 / 1e3, 0.012), clamp22(Math.min(Math.max(p.thickness * 3, 3e-3), ratio * 0.01), 1e-3, 0.05), src);
|
|
6748
6860
|
} else if (brittle) {
|
|
6749
|
-
addCrack(o, p, entry2, n, crackLen, src);
|
|
6861
|
+
if (!p.spec.units) addCrack(o, p, entry2, n, crackLen, src);
|
|
6750
6862
|
if (mat.fracture !== "shatter") addHole(o, p, entry2, n, caliber / 1e3, false, void 0, src);
|
|
6751
6863
|
} else addHole(o, p, entry2, n, caliber / 1e3, false, void 0, src);
|
|
6752
6864
|
debris(o, p, mat.hitDebris, entry2, n, clamp22(Math.round(E / 60) + 2, 2, 14), clamp22(Math.sqrt(E) / 6, 1, 8), src);
|
|
6753
|
-
wearJoints(o, p, (penetrated ? thr : E) * 0.02, void 0, 0, src, true);
|
|
6754
|
-
const
|
|
6865
|
+
wearJoints(o, p, (penetrated ? thr : E) * 0.02, void 0, 0, src, true, BULLET_JOINT_SPAN);
|
|
6866
|
+
const hollowTear = mat.fracture === "tear" && p.spec.fill !== void 0 && p.spec.fill < 0.5;
|
|
6867
|
+
const absorbed = penetrated && (mat.ductility >= 0.5 && mat.fracture !== "tear" || hollowTear) ? Math.min(E, thr) : E;
|
|
6755
6868
|
const dmg = applyDamage(o, p, absorbed * DMG_PER_J * scale, "ballistic", entry2, d, absorbed * 0.1, 12, src);
|
|
6756
6869
|
if (!isLost(p)) tearAt(o, p, "ballistic", entry2, penetrated ? exitPoint : void 0, d, E, caliber / 1e3, src);
|
|
6757
6870
|
chipUnits(o, p, "ballistic", entry2, penetrated ? Math.min(E, Math.max(thr, E * 0.5)) : E, d, Math.max(0.05, caliber / 1e3 * 8), src);
|
|
@@ -6836,10 +6949,25 @@ var GameFloorplanStructure = (() => {
|
|
|
6836
6949
|
if (dist <= BREACH_BLAST_REACH * Math.cbrt(Math.max(0, energy) / 1e3)) addBreach(o, p, wp, breachAreaOf(p, dealt, true), Ein, null, src);
|
|
6837
6950
|
return reach;
|
|
6838
6951
|
};
|
|
6952
|
+
const blastProbe = { partsTested: 0, partsNear: 0 };
|
|
6953
|
+
const blastCandidates = (o, point, radius) => {
|
|
6954
|
+
const local = toLocal(o.st.position, o.st.rotation, point);
|
|
6955
|
+
const near = [];
|
|
6956
|
+
for (const p of o.parts) {
|
|
6957
|
+
const reach = radius + p.bound;
|
|
6958
|
+
const dx = local[0] - p.pos[0];
|
|
6959
|
+
const dy = local[1] - p.pos[1];
|
|
6960
|
+
const dz = local[2] - p.pos[2];
|
|
6961
|
+
if (dx * dx + dy * dy + dz * dz < reach * reach) near.push(p);
|
|
6962
|
+
}
|
|
6963
|
+
blastProbe.partsTested += o.parts.length;
|
|
6964
|
+
blastProbe.partsNear += near.length;
|
|
6965
|
+
return near;
|
|
6966
|
+
};
|
|
6839
6967
|
const blastObject = (o, point, energy, radius, src) => {
|
|
6840
6968
|
const start = cur.length;
|
|
6841
6969
|
const res = { object: o.id, damage: 0, penetrated: false, exitEnergy: 0, events: [] };
|
|
6842
|
-
for (const p of o
|
|
6970
|
+
for (const p of blastCandidates(o, point, radius)) blastPart(o, p, point, energy, radius, src, res);
|
|
6843
6971
|
res.events = cur.slice(start);
|
|
6844
6972
|
return res;
|
|
6845
6973
|
};
|
|
@@ -6963,7 +7091,7 @@ var GameFloorplanStructure = (() => {
|
|
|
6963
7091
|
let order = 0;
|
|
6964
7092
|
for (const o of inRange) {
|
|
6965
7093
|
if (only && only !== o) continue;
|
|
6966
|
-
for (const p of o
|
|
7094
|
+
for (const p of blastCandidates(o, point, radius)) {
|
|
6967
7095
|
if (isLost(p)) continue;
|
|
6968
7096
|
const dist = distToPart(o, p, point);
|
|
6969
7097
|
if (dist < radius) items.push({ dist, order: order++, o, p });
|
|
@@ -7510,6 +7638,7 @@ var GameFloorplanStructure = (() => {
|
|
|
7510
7638
|
const p = getPart(o, partId);
|
|
7511
7639
|
p.pos = [position[0], position[1], position[2]];
|
|
7512
7640
|
p.q = q;
|
|
7641
|
+
poseVersion++;
|
|
7513
7642
|
updateBound(o);
|
|
7514
7643
|
},
|
|
7515
7644
|
remove(id) {
|
|
@@ -7528,6 +7657,7 @@ var GameFloorplanStructure = (() => {
|
|
|
7528
7657
|
const o = getObj(id);
|
|
7529
7658
|
o.base = { pos: [position[0], position[1], position[2]], rot: [rotation[0], rotation[1], rotation[2], rotation[3]] };
|
|
7530
7659
|
applySoilPose(o);
|
|
7660
|
+
slideOffResting(o, rotation);
|
|
7531
7661
|
},
|
|
7532
7662
|
splitGroup(id, group, newId) {
|
|
7533
7663
|
if (impls.has(id)) throw new Error(`object "${id}" is a registered DestructibleImpl and cannot be split; its module owns its pieces`);
|
|
@@ -7551,7 +7681,7 @@ var GameFloorplanStructure = (() => {
|
|
|
7551
7681
|
if (o.spec.name !== void 0) s.name = o.spec.name;
|
|
7552
7682
|
if (o.spec.tags) s.tags = [...o.spec.tags];
|
|
7553
7683
|
if (o.spec.soil !== void 0) s.soil = o.spec.soil;
|
|
7554
|
-
return
|
|
7684
|
+
return s;
|
|
7555
7685
|
};
|
|
7556
7686
|
const inNew = (pid) => moved.has(pid);
|
|
7557
7687
|
const inOld = (pid) => !moved.has(pid);
|
|
@@ -7578,7 +7708,12 @@ var GameFloorplanStructure = (() => {
|
|
|
7578
7708
|
const p = getPart(o, partId);
|
|
7579
7709
|
return whole(() => doHit(o, h, p));
|
|
7580
7710
|
},
|
|
7711
|
+
blastProbe() {
|
|
7712
|
+
return { ...blastProbe };
|
|
7713
|
+
},
|
|
7581
7714
|
explode(point, energy, radius, source, blast) {
|
|
7715
|
+
blastProbe.partsTested = 0;
|
|
7716
|
+
blastProbe.partsNear = 0;
|
|
7582
7717
|
return withCollapses(run(() => blastWorld(point, energy, radius, source, blast)));
|
|
7583
7718
|
},
|
|
7584
7719
|
raycast(origin, direction, maxDistance = Infinity) {
|
|
@@ -7588,7 +7723,8 @@ var GameFloorplanStructure = (() => {
|
|
|
7588
7723
|
sweepBox(box2, direction, distance2, options2 = {}) {
|
|
7589
7724
|
const d = vec.normalize(direction);
|
|
7590
7725
|
const ignored = options2.ignore === void 0 ? void 0 : objects.get(options2.ignore);
|
|
7591
|
-
const
|
|
7726
|
+
const hosted = options2.ignore === void 0 || ignored ? void 0 : impls.get(options2.ignore);
|
|
7727
|
+
const ignore = ignored ? new Set(ignored.parts.map((p) => `${ignored.id}\0${p.spec.id}`)) : hosted ? new Set(hosted.impl.describe().parts.map((p) => `${hosted.impl.id}\0${p.id}`)) : void 0;
|
|
7592
7728
|
let best = null;
|
|
7593
7729
|
for (const origin of sweepOrigins(box2, d, options2.spacing ?? 0.2)) {
|
|
7594
7730
|
const r = raycastInternal(origin, d, distance2 + SWEEP_BACK, ignore);
|