@adatechnology/game-floorplan-structure 2.1.2 → 2.1.4

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.
@@ -5572,23 +5572,42 @@ var GameFloorplanStructure = (() => {
5572
5572
  const v = table[mat.penetrationClass ?? mat.id] ?? table[mat.id];
5573
5573
  return v === void 0 ? void 0 : v * (mat.penetrationScale ?? 1);
5574
5574
  };
5575
- var capacityScale = (p) => {
5575
+ var BURIED_BLAST_REACH = 0.5;
5576
+ var GIVE_AT_CUT_HP = 0.5;
5577
+ var capacityScale = (p, borne, through) => {
5576
5578
  const residual = p.spec.reinforcement?.residualCapacity ?? RESIDUAL_CAPACITY;
5577
5579
  if (p.st.stripped) return residual;
5578
- const kept = Math.min(p.rt.removed ? 1 - p.rt.removed / p.mass0 : 1, 1 - sectionLoss(p));
5580
+ const kept = Math.min(p.rt.removed ? 1 - p.rt.removed / p.mass0 : 1, sectionKept(p, residual, borne, through));
5579
5581
  return Math.max(p.spec.reinforcement ? residual : 0.05, kept);
5580
5582
  };
5581
- var sectionLoss = (p) => {
5583
+ var sectionKept = (p, residual, borne, through) => {
5584
+ let kept = 1;
5585
+ forEachSection(p, borne, (c, along, gone) => {
5586
+ const share = through?.(c.center, along) ?? 1;
5587
+ if (share <= 0) return;
5588
+ kept = Math.min(kept, Math.max(p.spec.reinforcement ? residual : 0, 1 - gone) / share);
5589
+ });
5590
+ return kept;
5591
+ };
5592
+ var sectionLoss = (p, borne) => {
5593
+ let worst = 0;
5594
+ forEachSection(p, borne, (_c, _along, gone) => {
5595
+ worst = Math.max(worst, gone);
5596
+ });
5597
+ return Math.min(1, worst);
5598
+ };
5599
+ var forEachSection = (p, borne, visit) => {
5582
5600
  const cells = p.st.chipped;
5583
- if (!cells?.length) return 0;
5601
+ if (!cells?.length) return;
5584
5602
  const [u, v] = planeAxes(p.thin);
5585
5603
  const role = p.spec.structure?.role;
5586
5604
  const up = rotateVec(p.q, [0, 0, 0].map((_, k) => k === v ? 1 : 0));
5587
5605
  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;
5588
5606
  const along = (role === "wall" || role === "partition" || role === "column") && upright >= 0 ? upright : p.dims[u] >= p.dims[v] ? u : v;
5589
5607
  const across = along === u ? v : u;
5590
- let worst = 0;
5608
+ const lying = along !== upright || upright < 0;
5591
5609
  for (const c of cells) {
5610
+ if (lying && borne?.(c.center, along)) continue;
5592
5611
  const spans = [];
5593
5612
  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]);
5594
5613
  spans.sort((a, b) => a[0] - b[0]);
@@ -5598,9 +5617,8 @@ var GameFloorplanStructure = (() => {
5598
5617
  gone += b - Math.max(a, end);
5599
5618
  end = b;
5600
5619
  }
5601
- worst = Math.max(worst, gone / Math.max(p.dims[across], 1e-6));
5620
+ visit(c, along, Math.min(1, gone / Math.max(p.dims[across], 1e-6)));
5602
5621
  }
5603
- return Math.min(1, worst);
5604
5622
  };
5605
5623
  var isLost = (p) => p.st.status === "broken" || p.st.status === "melted" || p.st.status === "ashes";
5606
5624
  var clone = (v) => structuredClone(v);
@@ -5911,6 +5929,26 @@ var GameFloorplanStructure = (() => {
5911
5929
  byTouching.set(support, { version: poseVersion, box: box2 });
5912
5930
  return box2;
5913
5931
  };
5932
+ const throughOf = (p) => {
5933
+ const load = p.st.load ?? 0;
5934
+ if (load <= 0) return void 0;
5935
+ const above = Math.max(0, load - p.st.mass);
5936
+ const up = rotateVec(p.q, [0, 1, 0]);
5937
+ return (local, along) => {
5938
+ const axis = [0, 0, 0];
5939
+ axis[along] = 1;
5940
+ const sign = Math.sign(rotateVec(p.q, axis)[1]);
5941
+ if (Math.abs(up[1]) < 0.7 && Math.abs(rotateVec(p.q, axis)[1]) < 0.7) return 1;
5942
+ const half = p.dims[along] / 2;
5943
+ const share = clamp22((half - sign * local[along]) / Math.max(p.dims[along], 1e-6), 0, 1);
5944
+ return (above + p.st.mass * share) / load;
5945
+ };
5946
+ };
5947
+ const borneOn = (p, supports) => {
5948
+ if (supports.length === 0) return void 0;
5949
+ const boxes = supports.map((support) => contactBox(p, support));
5950
+ return (local, along) => boxes.some(([lo, hi]) => local[along] >= lo[along] - SUPPORT_TOLERANCE && local[along] <= hi[along] + SUPPORT_TOLERANCE);
5951
+ };
5914
5952
  const measureContact = (p, support) => {
5915
5953
  const A = aabbOf(p.spec.shape, p.pos, p.q), B = aabbOf(support.spec.shape, support.pos, support.q);
5916
5954
  const lo = [0, 0, 0], hi = [0, 0, 0];
@@ -6118,7 +6156,7 @@ var GameFloorplanStructure = (() => {
6118
6156
  o.unsup[i] = o.anyAnchor && !isLost(p) && !p.orphan;
6119
6157
  continue;
6120
6158
  }
6121
- p.st.stress = p.st.load * structureSafety / (p.cap * capacityScale(p));
6159
+ p.st.stress = p.st.load * structureSafety / (p.cap * capacityScale(p, borneOn(p, (lowerOf.get(i) ?? []).map((k) => parts[k])), throughOf(p)));
6122
6160
  if (p.bend) {
6123
6161
  p.bendLoad = p.st.mass + bending[i];
6124
6162
  const bent = restFlexure(o, p, lowerOf.get(i) ?? []);
@@ -7208,6 +7246,27 @@ var GameFloorplanStructure = (() => {
7208
7246
  debris(o, p, p.mat.breakDebris, center, [0, -1, 0], 6, 1, src);
7209
7247
  return loose.length;
7210
7248
  };
7249
+ const giveAtCut = (o, p, src) => {
7250
+ if (!p.spec.reinforcement || !p.spec.units || !p.st.chipped?.length || sectionLoss(p) <= 0) return false;
7251
+ const opened = [];
7252
+ for (const j of o.byPart.get(p.spec.id) ?? []) {
7253
+ if (j.st.open) continue;
7254
+ const onIt = j.bears === "a_on_b" && j.spec.b === p.spec.id || j.bears === "b_on_a" && j.spec.a === p.spec.id;
7255
+ if (!onIt) continue;
7256
+ j.st.open = true;
7257
+ j.st.openedBy = "break";
7258
+ opened.push(j);
7259
+ }
7260
+ if (opened.length === 0) return false;
7261
+ p.st.hp = Math.max(p.st.hp, p.st.maxHp * GIVE_AT_CUT_HP);
7262
+ markDamaged(p);
7263
+ solveStructure(o);
7264
+ recomputeGroups(o);
7265
+ detachEvents(o, opened, "break", src);
7266
+ exposeRebar(o, p, src);
7267
+ collapseCheck(o, src);
7268
+ return true;
7269
+ };
7211
7270
  const stripPart = (o, p, reinforcement, src) => {
7212
7271
  const bars = rebarBars(p.dims, p.thin, reinforcement.spacing);
7213
7272
  p.st.stripped = true;
@@ -7265,6 +7324,7 @@ var GameFloorplanStructure = (() => {
7265
7324
  hingeDrop(o, p, src);
7266
7325
  return;
7267
7326
  }
7327
+ if (!force && giveAtCut(o, p, src)) return;
7268
7328
  const ex = p.spec.explodes;
7269
7329
  const style = force ?? (p.snap ? "snap" : p.mat.fracture === "none" ? "snap" : p.mat.fracture);
7270
7330
  const { c, q } = partXf(o, p);
@@ -7611,7 +7671,9 @@ var GameFloorplanStructure = (() => {
7611
7671
  const dx = local[0] - p.pos[0];
7612
7672
  const dy = local[1] - p.pos[1];
7613
7673
  const dz = local[2] - p.pos[2];
7614
- if (dx * dx + dy * dy + dz * dz < reach * reach) near.push(p);
7674
+ if (dx * dx + dy * dy + dz * dz >= reach * reach) continue;
7675
+ if (p.spec.anchored && p.spec.structure?.role === "foundation" && distToPart(o, p, point) > BURIED_BLAST_REACH) continue;
7676
+ near.push(p);
7615
7677
  }
7616
7678
  blastProbe.partsTested += o.parts.length;
7617
7679
  blastProbe.partsNear += near.length;