@adatechnology/game-destruction 0.19.0 → 0.20.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.js CHANGED
@@ -2955,7 +2955,7 @@ var fragility = (ductility, thickness) => {
2955
2955
  };
2956
2956
 
2957
2957
  // src/world.ts
2958
- import { ignitionChance, resolveIgnitionRules, sparkTargetFactor } from "@adatechnology/game-contracts";
2958
+ import { bodyImpulse, DEFAULT_BLAST_IMPULSE, ignitionChance, resolveIgnitionRules, sideOnOverpressure, sparkTargetFactor } from "@adatechnology/game-contracts";
2959
2959
  var THIN_SHEET_DISHING = 5e-3;
2960
2960
  var SWEEP_BACK = 0.01;
2961
2961
  function sweepOrigins(box, d, spacing) {
@@ -2997,9 +2997,15 @@ var BREACH_BLAST_FACTOR = 6;
2997
2997
  var BREACH_AREA = 0.25;
2998
2998
  var BREACH_BLAST_REACH = 0.12;
2999
2999
  var MEMBER_CUT_REACH = 0.5;
3000
+ var FAR_MEMBER_HP_FLOOR = 0.25;
3000
3001
  var BLAST_REFERENCE_RESISTANCE = 200 * 1900 * 0.13;
3001
3002
  var BLAST_EDGE_RAGGED = 0.3;
3002
3003
  var BLAST_EDGE_LOOSE = 1.35;
3004
+ var PANEL_PRESSURE = 7e4;
3005
+ var PANEL_IMPULSE = 150;
3006
+ var PANEL_PI = 6e6;
3007
+ var PANEL_POINTS = [[0, 0], [-0.3, 0], [0.3, 0], [0, -0.3], [0, 0.3]];
3008
+ var PANEL_POINTS_LOADED = 4;
3003
3009
  var BLAST_EDGE_WEAR = 0.6;
3004
3010
  var RESIDUAL_CAPACITY = 0.15;
3005
3011
  var SEVER_BAND = 0.1;
@@ -4593,7 +4599,7 @@ var createDestruction = (options = {}) => {
4593
4599
  return BREACH_BLAST_REACH * Math.cbrt(Math.max(0, energy) / 1e3) * clamp2(Math.cbrt(BLAST_REFERENCE_RESISTANCE / resistance), 0.3, 2);
4594
4600
  };
4595
4601
  const blastUnits = (o, p, wp, energy, dist, src) => {
4596
- var _a, _b;
4602
+ var _a;
4597
4603
  if (!p.staged || p.st.stripped || isLost(p) || chipEnergy <= 0) return false;
4598
4604
  const reach = blastReachOf(p, energy);
4599
4605
  if (dist >= reach) return false;
@@ -4623,6 +4629,62 @@ var createDestruction = (options = {}) => {
4623
4629
  }
4624
4630
  }
4625
4631
  if (out.length === 0) return false;
4632
+ return knockOutUnits(o, p, wp, energy, out, src);
4633
+ };
4634
+ const blastPanel = (o, p, point, energy, src) => {
4635
+ var _a;
4636
+ if (!p.staged || p.st.stripped || isLost(p) || !p.spec.units || p.spec.units.mortar === p.spec.material || p.spec.reinforcement) return false;
4637
+ const [u, v] = planeAxes(p.thin);
4638
+ const lp = toLocal(p.pos, p.q, objLocal(o, point));
4639
+ const half = p.dims[u] / 2;
4640
+ const posts = [];
4641
+ for (const m of o.parts) {
4642
+ if (m === p || !m.spec.reinforcement || isLost(m) || m.spec.shape.kind !== "box") continue;
4643
+ const mp = toLocal(p.pos, p.q, m.pos);
4644
+ if (Math.abs(mp[p.thin]) > p.dims[p.thin] + 0.15 || Math.abs(mp[u]) > half + 0.15 || m.dims[v] < p.dims[v] * 0.5) continue;
4645
+ posts.push(mp[u]);
4646
+ }
4647
+ let from = -half, to = half;
4648
+ for (const x of posts) {
4649
+ if (x <= lp[u] && x > from) from = x;
4650
+ if (x >= lp[u] && x < to) to = x;
4651
+ }
4652
+ if (to - from < 0.2) return false;
4653
+ const tnt = energy * DEFAULT_BLAST_IMPULSE.tntPerJoule;
4654
+ const centre = objLocal(o, point);
4655
+ const span = to - from, height = p.dims[v];
4656
+ let loaded = 0;
4657
+ for (const [fu, fv] of PANEL_POINTS) {
4658
+ const at = [0, 0, 0];
4659
+ at[u] = (from + to) / 2 + fu * span;
4660
+ at[v] = fv * height;
4661
+ at[p.thin] = Math.sign(lp[p.thin]) * p.dims[p.thin] / 2;
4662
+ const r = vec.distance(toWorld(p.pos, p.q, at), centre);
4663
+ const side = sideOnOverpressure(tnt, r);
4664
+ const reflected = 2 * side + 6 * side * side / (side + 7 * 101325);
4665
+ const impulse = bodyImpulse(tnt, r);
4666
+ if (reflected > PANEL_PRESSURE && impulse > PANEL_IMPULSE && (reflected - PANEL_PRESSURE) * (impulse - PANEL_IMPULSE) >= PANEL_PI) loaded++;
4667
+ }
4668
+ if (loaded < PANEL_POINTS_LOADED) return false;
4669
+ const grid = gridOf(p);
4670
+ const worn = (_a = p.rt).chips ?? (_a.chips = {});
4671
+ const out = [];
4672
+ for (let i = 0; i < grid.length; i++) {
4673
+ const cell = grid[i];
4674
+ if (worn[i] === -1) continue;
4675
+ if (cell.center[u] - cell.size[u] / 2 >= from - 1e-6 && cell.center[u] + cell.size[u] / 2 <= to + 1e-6) out.push(i);
4676
+ }
4677
+ if (out.length === 0) return false;
4678
+ for (const i of out) worn[i] = -1;
4679
+ return knockOutUnits(o, p, point, energy, out, src);
4680
+ };
4681
+ const knockOutUnits = (o, p, wp, energy, out, src) => {
4682
+ var _a, _b;
4683
+ const [u, v] = planeAxes(p.thin);
4684
+ const op = p.st.opening ? toLocal(p.pos, p.q, p.st.opening.center) : null;
4685
+ const grid = gridOf(p);
4686
+ const worn = (_a = p.rt).chips ?? (_a.chips = {});
4687
+ for (const i of out) worn[i] = -1;
4626
4688
  const loose = unsupportedCells(grid, p.thin, p.dims, (i) => worn[i] !== -1 && !(op && p.st.opening && Math.hypot(grid[i].center[u] - op[u], grid[i].center[v] - op[v]) <= p.st.opening.radius));
4627
4689
  for (const i of loose) worn[i] = -1;
4628
4690
  const blown = out.map((i) => grid[i]), fallen = loose.map((i) => grid[i]);
@@ -5105,12 +5167,15 @@ var createDestruction = (options = {}) => {
5105
5167
  return reach;
5106
5168
  }
5107
5169
  if (Ein > 20 && p.layers.length > 0) spallOuter(o, p, wp, faceOf(o, p, wn), wn, clamp2(0.05 + Math.sqrt(Ein) * 2e-3, 0.05, 0.4), src);
5108
- const dealt = applyDamage(o, p, amount, "explosive", point, null, Ein * 0.3, 40, src);
5170
+ const breachReach = BREACH_BLAST_REACH * Math.cbrt(Math.max(0, energy) / 1e3);
5171
+ const farMember = Boolean(p.spec.reinforcement && p.spec.units) && dist > MEMBER_CUT_REACH * breachReach;
5172
+ const dealt = farMember ? applyDamage(o, p, Math.min(amount, Math.max(0, p.st.hp - p.st.maxHp * FAR_MEMBER_HP_FLOOR)), "explosive", null, null, Ein * 0.3, 40, src) : applyDamage(o, p, amount, "explosive", point, null, Ein * 0.3, 40, src);
5109
5173
  res.damage += dealt;
5110
5174
  if (p.bend && flexure.enabled) bendByBlast(o, p, point, energy, radius, reach, src);
5111
- const breachReach = BREACH_BLAST_REACH * Math.cbrt(Math.max(0, energy) / 1e3);
5112
- if (p.spec.units && p.spec.units.mortar !== p.spec.material) blastUnits(o, p, wp, energy, dist, src);
5113
- else if (p.spec.reinforcement && p.spec.units && dist > MEMBER_CUT_REACH * breachReach) blastUnits(o, p, wp, energy, dist, src);
5175
+ if (p.spec.units && p.spec.units.mortar !== p.spec.material) {
5176
+ blastPanel(o, p, point, energy, src);
5177
+ if (!isLost(p)) blastUnits(o, p, wp, energy, dist, src);
5178
+ } else if (farMember) blastUnits(o, p, wp, energy, dist, src);
5114
5179
  else if (dist <= breachReach) addBreach(o, p, wp, breachAreaOf(p, dealt, true), Ein, null, src);
5115
5180
  return reach;
5116
5181
  };