@adatechnology/game-destruction-three 0.8.2 → 0.10.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
@@ -45,6 +45,9 @@ function mixHex(a, b, t) {
45
45
  }
46
46
 
47
47
  // src/fragments.ts
48
+ var SHEET_MAX = 4e-3;
49
+ var SHEET_AIR = 2.5;
50
+ var SHEET_SWAY = 3;
48
51
  var FragmentSystem = class {
49
52
  constructor(THREE, o) {
50
53
  __publicField(this, "THREE", THREE);
@@ -150,7 +153,8 @@ var FragmentSystem = class {
150
153
  asleep: false,
151
154
  rest: 0,
152
155
  fade: 1,
153
- dying: false
156
+ dying: false,
157
+ air: f.shape === "scrap" && sz[2] <= SHEET_MAX ? SHEET_AIR : 0
154
158
  };
155
159
  this.list.push(live);
156
160
  let alive = this.list.reduce((n, l) => n + (l.dying ? 0 : 1), 0);
@@ -234,6 +238,7 @@ var FragmentSystem = class {
234
238
  }
235
239
  } else {
236
240
  f.ang.multiplyScalar(Math.exp(-0.15 * dt));
241
+ if (f.air > 0) this.flutter(f, dt);
237
242
  }
238
243
  if (contact && f.vel.lengthSq() < 4) this.settle(f, dt);
239
244
  const slow = f.vel.lengthSq() < 0.012 && f.ang.lengthSq() < 0.2;
@@ -248,6 +253,14 @@ var FragmentSystem = class {
248
253
  f.still = 0;
249
254
  }
250
255
  }
256
+ /** A sheet in the air: drag slows it to a slow fall, and it sways and turns over as it goes. */
257
+ flutter(f, dt) {
258
+ f.vel.multiplyScalar(Math.exp(-f.air * dt));
259
+ f.vel.x += (this.rng() - 0.5) * SHEET_SWAY * dt;
260
+ f.vel.z += (this.rng() - 0.5) * SHEET_SWAY * dt;
261
+ f.ang.x += (this.rng() - 0.5) * SHEET_SWAY * 4 * dt;
262
+ f.ang.z += (this.rng() - 0.5) * SHEET_SWAY * 4 * dt;
263
+ }
251
264
  /** Tip the fragment towards lying on its flattest face. */
252
265
  settle(f, dt) {
253
266
  const mesh = f.mesh;
@@ -957,6 +970,9 @@ function specFromObject3D(THREE, root, options = {}) {
957
970
  return { spec, parts: meshesOf };
958
971
  }
959
972
 
973
+ // src/renderer.ts
974
+ import { kitOriginOf } from "@adatechnology/game-contracts";
975
+
960
976
  // src/heat.ts
961
977
  var STOPS = [
962
978
  [450, 0],
@@ -1927,6 +1943,7 @@ var Visuals = class {
1927
1943
 
1928
1944
  // src/renderer.ts
1929
1945
  var rendererCount = 0;
1946
+ var COLLAPSE_CLOUD_KG = 1e3;
1930
1947
  var IMPACT_TAGS = ["metal", "glass", "wood"];
1931
1948
  var GLOW_FROM_C = 430;
1932
1949
  var QUEUE_CAP = 4e3;
@@ -2390,10 +2407,14 @@ var Renderer = class {
2390
2407
  case "settle":
2391
2408
  this.onSettle(ev.object);
2392
2409
  break;
2393
- case "collapse":
2410
+ case "collapse": {
2411
+ const root = this.bounds.get(ev.object)?.root;
2412
+ const furniture = !!root && kitOriginOf(root)?.kind === "furniture";
2394
2413
  this.splitLoose(ev.object);
2395
- this.playEvent({ kind: "collapse" }, this.rootPoint(ev.object));
2414
+ if (!furniture || ev.mass >= COLLAPSE_CLOUD_KG) this.playEvent({ kind: "collapse" }, this.rootPoint(ev.object));
2415
+ else this.vfx.burst("dust", this.rootPoint(ev.object), [0, 1, 0], clamp(Math.round(ev.mass / 4), 4, 24), 0.8);
2396
2416
  break;
2417
+ }
2397
2418
  case "disassemble_progress": {
2398
2419
  const k = `unscrew:${ev.joint}`;
2399
2420
  if (this.time - (this.throttles.get(k) ?? -1) > 0.25) {
@@ -2423,6 +2444,9 @@ var Renderer = class {
2423
2444
  case "stage":
2424
2445
  this.onStage(ev);
2425
2446
  break;
2447
+ case "chip":
2448
+ this.onChip(ev);
2449
+ break;
2426
2450
  case "expose":
2427
2451
  this.cages.set(`${ev.object}|${ev.part}`, ev.bars);
2428
2452
  if (ev.bars.length > 0) {
@@ -2550,6 +2574,7 @@ var Renderer = class {
2550
2574
  const def = pv ? this.world.materials.get(pv.material) : void 0;
2551
2575
  if (kind === "smoke") return { color: SMOKE_TONES[def?.thermal.smoke ?? "grey"] };
2552
2576
  if (kind === "fibers" || kind === "leaves") {
2577
+ if (def?.visual?.innerColor !== void 0) return { color: def.visual.innerColor };
2553
2578
  const c = pv ? this.visuals.baseColorHex(pv.meshes[0] ?? {}) : -1;
2554
2579
  return c >= 0 ? { color: c } : void 0;
2555
2580
  }
@@ -2678,6 +2703,19 @@ var Renderer = class {
2678
2703
  if (!played) this.vfx.burst("dust", ev.opening.center, [0, 1, 0], 14, 1.2, { color });
2679
2704
  this.sound(impactKey(def), ev.opening.center, 0.8);
2680
2705
  }
2706
+ /**
2707
+ * A unit came out of a wall of units: the unit flies as a fragment with a puff of its dust. The gap itself is the drawing's (the house renderer redraws
2708
+ * the wall as its courses without that unit); a part drawn as one box keeps its box.
2709
+ */
2710
+ onChip(ev) {
2711
+ const pv = this.partVis(ev.object, ev.part);
2712
+ const def = pv ? this.world.materials.get(pv.material) : void 0;
2713
+ const color = (pv ? this.partColor(pv, def) : null) ?? fallbackColor(pv?.material ?? "", def);
2714
+ const maxAlive = this.low ? Math.floor(this.maxFragments / 2) : this.maxFragments;
2715
+ for (const fr of ev.fragments) this.fragments.spawn(fr, this.fragments.materialFor(fr.material, fallbackColor(fr.material, def), false), ev.object, maxAlive);
2716
+ if (!this.playEvent({ kind: "spall", material: this.impactMaterial(def) }, ev.center)) this.vfx.burst("dust", ev.center, [0, 1, 0], 6, 0.8, { color });
2717
+ this.sound(impactKey(def), ev.center, 0.7);
2718
+ }
2681
2719
  onFracture(ev) {
2682
2720
  const b = this.bounds.get(ev.object);
2683
2721
  const pv = b?.parts.get(ev.part);
@@ -2698,7 +2736,8 @@ var Renderer = class {
2698
2736
  for (let i = 0; i < ev.fragments.length; i += step) {
2699
2737
  const fr = ev.fragments[i];
2700
2738
  const fdef = this.world.materials.get(fr.material);
2701
- const mat = this.fragments.materialFor(fr.material, fdef === def || !fdef ? color : fallbackColor(fr.material, fdef), transparent || fdef?.visual?.transparent === true, opacity);
2739
+ const tone2 = fr.inner && fdef?.visual?.innerColor !== void 0 ? fdef.visual.innerColor : fdef === def || !fdef ? color : fallbackColor(fr.material, fdef);
2740
+ const mat = this.fragments.materialFor(fr.material, tone2, transparent || fdef?.visual?.transparent === true, opacity);
2702
2741
  this.fragments.spawn(fr, mat, ev.object, maxAlive);
2703
2742
  }
2704
2743
  const up = [0, 1, 0];
@@ -2716,7 +2755,7 @@ var Renderer = class {
2716
2755
  this.vfx.burst("dust", ev.point, up, 5, 0.8, { color: 11901556 });
2717
2756
  break;
2718
2757
  case "tear":
2719
- this.vfx.burst("fibers", ev.point, up, 12 * sizeK, 1.6, { color });
2758
+ this.vfx.burst("fibers", ev.point, up, 12 * sizeK, 1.6, { color: def?.visual?.innerColor ?? color });
2720
2759
  break;
2721
2760
  case "snap":
2722
2761
  this.vfx.burst("chips", ev.point, up, 8 * sizeK, 3);