@adatechnology/game-destruction-three 0.16.0 → 0.17.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.d.ts CHANGED
@@ -386,6 +386,11 @@ type DestructionSoundStyle = 'art_scene' | 'game';
386
386
  * sends them before its legacy family key, so the first one with a rule plays; a game replaces any of them in `keys`.
387
387
  */
388
388
  declare const IMPACT_SOUND_KEYS: Readonly<Record<string, SoundKeyRule>>;
389
+ /**
390
+ * Every sound a blow, ricochet or break on a material can play (`sound`, `above.sound` and `fallback` of each rule of `rules`): a game preloads them on
391
+ * the first input, so even the first ricochet or impact plays the recording instead of the synthesized recipe while the file is still loading.
392
+ */
393
+ declare const impactSoundIds: (rules?: Readonly<Record<string, SoundKeyRule>>) => string[];
389
394
  /**
390
395
  * The keys `createDestructionRenderer` sends to `onSound`, mapped to the sounds the teams delivered. The Cena de Arte has a sound for every material
391
396
  * (clang, wood, glass, crumble, thud...); the game has four classes (impact, glass, wood, explosion) and its own explosion thump. Which team sound answers
@@ -492,4 +497,4 @@ declare function blastFireSampleBank(manifest: SfxManifest, options?: BlastFireS
492
497
  /** Every particle kind the renderer can emit (the game's sprite kinds, see `@adatechnology/game-vfx`). */
493
498
  type ParticleKind = SpriteKind;
494
499
 
495
- export { BIG_BLAST_RADIUS, BLAST_FALLOFF, BLAST_FAR_DISTANCE, BLAST_FAR_FALLOFF, BLAST_FIRE_SAMPLES, BLAST_KINDS, BLAST_KIND_OF, BLAST_SOUNDS, BLAST_SOUND_OF, BURN_LOOP, type BindOptions, type BlastFireSampleBankOptions, type BlastFireSampleDefaults, type BlastKind, DEFAULT_CRACKLES, DEFAULT_FIRE, DEFAULT_INDOOR_CONFINEMENT, DESTRUCTION_SOUND_BANK, DESTRUCTION_SOUND_KEYS, DRAG_SOUNDS, type DestructionRenderer, type DestructionSound, type DestructionSoundOptions, type DestructionSoundStyle, EXPLOSION_BOOM, type ExplodeOptions, FIRE_FALLOFF, FIRE_LOOP, FIRE_SOUNDS, type FragmentLifeRule, IMPACT_FAMILY_TAGS, IMPACT_SOUNDS, IMPACT_SOUND_KEYS, type ImpactFamily, type ImpactKeys, type LooseBody, type Mesh, type MeshRange, type Object3D, type PartHint, type ParticleKind, type Piece, type Quality, type RendererOptions, SCENE_SOUNDS, type SolidBox, type SoundDetail, type SoundKeyRule, type SpecFromObjectOptions, type SpecFromObjectResult, type ThreeNamespace, blastFireSampleBank, breakSoundKeys, createDestructionRenderer, createDestructionSound, dragSoundKey, heatColor, impactFamily, impactKey, impactSoundKeys, ricochetSoundKeys, shotKey, specFromObject3D };
500
+ export { BIG_BLAST_RADIUS, BLAST_FALLOFF, BLAST_FAR_DISTANCE, BLAST_FAR_FALLOFF, BLAST_FIRE_SAMPLES, BLAST_KINDS, BLAST_KIND_OF, BLAST_SOUNDS, BLAST_SOUND_OF, BURN_LOOP, type BindOptions, type BlastFireSampleBankOptions, type BlastFireSampleDefaults, type BlastKind, DEFAULT_CRACKLES, DEFAULT_FIRE, DEFAULT_INDOOR_CONFINEMENT, DESTRUCTION_SOUND_BANK, DESTRUCTION_SOUND_KEYS, DRAG_SOUNDS, type DestructionRenderer, type DestructionSound, type DestructionSoundOptions, type DestructionSoundStyle, EXPLOSION_BOOM, type ExplodeOptions, FIRE_FALLOFF, FIRE_LOOP, FIRE_SOUNDS, type FragmentLifeRule, IMPACT_FAMILY_TAGS, IMPACT_SOUNDS, IMPACT_SOUND_KEYS, type ImpactFamily, type ImpactKeys, type LooseBody, type Mesh, type MeshRange, type Object3D, type PartHint, type ParticleKind, type Piece, type Quality, type RendererOptions, SCENE_SOUNDS, type SolidBox, type SoundDetail, type SoundKeyRule, type SpecFromObjectOptions, type SpecFromObjectResult, type ThreeNamespace, blastFireSampleBank, breakSoundKeys, createDestructionRenderer, createDestructionSound, dragSoundKey, heatColor, impactFamily, impactKey, impactSoundIds, impactSoundKeys, ricochetSoundKeys, shotKey, specFromObject3D };
@@ -55,6 +55,7 @@ var GameDestructionThree = (() => {
55
55
  heatColor: () => heatColor,
56
56
  impactFamily: () => impactFamily,
57
57
  impactKey: () => impactKey,
58
+ impactSoundIds: () => impactSoundIds,
58
59
  impactSoundKeys: () => impactSoundKeys,
59
60
  ricochetSoundKeys: () => ricochetSoundKeys,
60
61
  shotKey: () => shotKey,
@@ -11237,6 +11238,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
11237
11238
  floor: 60
11238
11239
  }
11239
11240
  },
11241
+ ricochetDeg: 12,
11240
11242
  hitDebris: "chips",
11241
11243
  breakDebris: "dust",
11242
11244
  visual: { innerColor: 10197652 },
@@ -11268,6 +11270,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
11268
11270
  0.04,
11269
11271
  0.12
11270
11272
  ],
11273
+ ricochetDeg: 10,
11271
11274
  hitDebris: "chips",
11272
11275
  breakDebris: "dust",
11273
11276
  visual: { innerColor: 12085567 },
@@ -11325,6 +11328,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
11325
11328
  0.06,
11326
11329
  0.3
11327
11330
  ],
11331
+ ricochetDeg: 15,
11328
11332
  hitDebris: "chips",
11329
11333
  breakDebris: "dust",
11330
11334
  visual: { innerColor: 9407364 },
@@ -11753,6 +11757,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
11753
11757
  0.03,
11754
11758
  0.15
11755
11759
  ],
11760
+ ricochetDeg: 8,
11756
11761
  hitDebris: "chips",
11757
11762
  breakDebris: "dust",
11758
11763
  thermal: {
@@ -11852,6 +11857,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
11852
11857
  0.02,
11853
11858
  0.08
11854
11859
  ],
11860
+ ricochetDeg: 8,
11855
11861
  hitDebris: "chips",
11856
11862
  breakDebris: "dust",
11857
11863
  thermal: {
@@ -11946,6 +11952,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
11946
11952
  0.05,
11947
11953
  0.15
11948
11954
  ],
11955
+ ricochetDeg: 15,
11949
11956
  hitDebris: "chips",
11950
11957
  breakDebris: "chips",
11951
11958
  thermal: {
@@ -11971,6 +11978,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
11971
11978
  0.04,
11972
11979
  0.12
11973
11980
  ],
11981
+ ricochetDeg: 12,
11974
11982
  hitDebris: "chips",
11975
11983
  breakDebris: "chips",
11976
11984
  thermal: {
@@ -14231,8 +14239,8 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
14231
14239
  }
14232
14240
  case "melt":
14233
14241
  this.activate(ev.object, ev.part);
14234
- if (this.time - (this.throttles.get(`melt:${ev.object}|${ev.part}`) ?? -9) > 1.5) {
14235
- this.throttles.set(`melt:${ev.object}|${ev.part}`, this.time);
14242
+ if (this.time - (this.throttles.get(`melt:${ev.object}`) ?? -9) > 1.5) {
14243
+ this.throttles.set(`melt:${ev.object}`, this.time);
14236
14244
  this.sound("melt_sizzle", this.rootPoint(ev.object), 0.4);
14237
14245
  }
14238
14246
  break;
@@ -15082,7 +15090,63 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
15082
15090
  }
15083
15091
  };
15084
15092
 
15085
- // ../game-audio/dist/chunk-C2K7XN2K.js
15093
+ // ../game-audio/dist/chunk-JV5XXCQE.js
15094
+ var SFX_TIERS = { light: 0, medium: 0.34, heavy: 0.67 };
15095
+ function splitTier(id) {
15096
+ const match = /^(.*)_(light|medium|heavy)$/.exec(id);
15097
+ return match ? { base: match[1], tier: match[2] } : { base: id };
15098
+ }
15099
+ var refsOf = (entries2, baseUrl) => (entries2 ?? []).map((entry) => ({ url: `${baseUrl}${entry.file}` }));
15100
+ function sampleBankFromManifest(manifest, options) {
15101
+ const baseUrl = options.baseUrl ?? "";
15102
+ const samples = [];
15103
+ const tiersOf = /* @__PURE__ */ new Map();
15104
+ for (const sound of manifest.sounds) {
15105
+ const { base, tier } = splitTier(sound.id);
15106
+ if (tier) tiersOf.set(base, [...tiersOf.get(base) ?? [], sound]);
15107
+ }
15108
+ const bases = /* @__PURE__ */ new Map();
15109
+ for (const sound of manifest.sounds) {
15110
+ if (!splitTier(sound.id).tier) bases.set(sound.id, sound);
15111
+ }
15112
+ for (const [base, tiers] of tiersOf) {
15113
+ if (!bases.has(base)) bases.set(base, { id: base, category: tiers[0]?.category ?? "", layers: { close: tiers[0]?.layers.close ?? [] } });
15114
+ }
15115
+ for (const sound of bases.values()) {
15116
+ const numbers = options.sounds?.[sound.id] ?? options.defaults?.(sound);
15117
+ const close = refsOf(sound.layers.close, baseUrl);
15118
+ if (!numbers || close.length === 0) continue;
15119
+ const tiers = (tiersOf.get(sound.id) ?? []).map((tier) => {
15120
+ const name = splitTier(tier.id).tier;
15121
+ const tierFar = refsOf(tier.layers.far, baseUrl);
15122
+ return { name, from: SFX_TIERS[name] ?? 0, close: refsOf(tier.layers.close, baseUrl), ...tierFar.length > 0 ? { far: tierFar } : {} };
15123
+ }).sort((a, b) => a.from - b.from);
15124
+ const far = refsOf(sound.layers.far, baseUrl);
15125
+ const indoor = refsOf(sound.layers.tail_in, baseUrl);
15126
+ const outdoor = refsOf(sound.layers.tail_out, baseUrl);
15127
+ const files = [sound, ...tiersOf.get(sound.id) ?? []].flatMap((entry) => Object.values(entry.layers).flatMap((entries2) => entries2 ?? []));
15128
+ samples.push({
15129
+ id: sound.id,
15130
+ bus: numbers.bus,
15131
+ close,
15132
+ ...far.length > 0 ? { far } : {},
15133
+ ...tiers.length > 0 ? { tiers } : {},
15134
+ ...numbers.crossover ? { crossover: numbers.crossover } : {},
15135
+ ...indoor.length > 0 || outdoor.length > 0 ? { tail: { ...indoor.length > 0 ? { indoor } : {}, ...outdoor.length > 0 ? { outdoor } : {}, ...numbers.tailGain === void 0 ? {} : { gain: numbers.tailGain } } } : {},
15136
+ ...numbers.pitch === void 0 ? {} : { pitch: numbers.pitch },
15137
+ ...numbers.gain === void 0 ? {} : { gain: numbers.gain },
15138
+ ...numbers.falloff ? { falloff: numbers.falloff } : {},
15139
+ ...numbers.cutoffK === void 0 ? {} : { cutoffK: numbers.cutoffK },
15140
+ ...numbers.group ? { group: numbers.group } : {},
15141
+ ...numbers.priority === void 0 ? {} : { priority: numbers.priority },
15142
+ ...numbers.fallback ? { fallback: numbers.fallback } : {},
15143
+ sources: files.map((file) => `${file.file}: ${file.source} ${file.author} ${file.license}`)
15144
+ });
15145
+ }
15146
+ return { id: options.id, samples };
15147
+ }
15148
+
15149
+ // ../game-audio/dist/chunk-UUWKSG4J.js
15086
15150
  var DISTANCE_CURVES = {
15087
15151
  /** The game's `sfx`: `vol / (1 + d² × 0.004)`, cutoff `/ (1 + d × 0.01)`, silent below 0.01 (jogo L62091–62092, L62101). */
15088
15152
  game_sfx: { model: "inverse_square", k: 4e-3, cutoffK: 0.01, minGain: 0.01 },
@@ -15517,60 +15581,6 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
15517
15581
  burst: 20,
15518
15582
  burstSpacing: 0.06
15519
15583
  };
15520
- var SFX_TIERS = { light: 0, medium: 0.34, heavy: 0.67 };
15521
- function splitTier(id) {
15522
- const match = /^(.*)_(light|medium|heavy)$/.exec(id);
15523
- return match ? { base: match[1], tier: match[2] } : { base: id };
15524
- }
15525
- var refsOf = (entries2, baseUrl) => (entries2 ?? []).map((entry) => ({ url: `${baseUrl}${entry.file}` }));
15526
- function sampleBankFromManifest(manifest, options) {
15527
- const baseUrl = options.baseUrl ?? "";
15528
- const samples = [];
15529
- const tiersOf = /* @__PURE__ */ new Map();
15530
- for (const sound of manifest.sounds) {
15531
- const { base, tier } = splitTier(sound.id);
15532
- if (tier) tiersOf.set(base, [...tiersOf.get(base) ?? [], sound]);
15533
- }
15534
- const bases = /* @__PURE__ */ new Map();
15535
- for (const sound of manifest.sounds) {
15536
- if (!splitTier(sound.id).tier) bases.set(sound.id, sound);
15537
- }
15538
- for (const [base, tiers] of tiersOf) {
15539
- if (!bases.has(base)) bases.set(base, { id: base, category: tiers[0]?.category ?? "", layers: { close: tiers[0]?.layers.close ?? [] } });
15540
- }
15541
- for (const sound of bases.values()) {
15542
- const numbers = options.sounds?.[sound.id] ?? options.defaults?.(sound);
15543
- const close = refsOf(sound.layers.close, baseUrl);
15544
- if (!numbers || close.length === 0) continue;
15545
- const tiers = (tiersOf.get(sound.id) ?? []).map((tier) => {
15546
- const name = splitTier(tier.id).tier;
15547
- const tierFar = refsOf(tier.layers.far, baseUrl);
15548
- return { name, from: SFX_TIERS[name] ?? 0, close: refsOf(tier.layers.close, baseUrl), ...tierFar.length > 0 ? { far: tierFar } : {} };
15549
- }).sort((a, b) => a.from - b.from);
15550
- const far = refsOf(sound.layers.far, baseUrl);
15551
- const indoor = refsOf(sound.layers.tail_in, baseUrl);
15552
- const outdoor = refsOf(sound.layers.tail_out, baseUrl);
15553
- const files = [sound, ...tiersOf.get(sound.id) ?? []].flatMap((entry) => Object.values(entry.layers).flatMap((entries2) => entries2 ?? []));
15554
- samples.push({
15555
- id: sound.id,
15556
- bus: numbers.bus,
15557
- close,
15558
- ...far.length > 0 ? { far } : {},
15559
- ...tiers.length > 0 ? { tiers } : {},
15560
- ...numbers.crossover ? { crossover: numbers.crossover } : {},
15561
- ...indoor.length > 0 || outdoor.length > 0 ? { tail: { ...indoor.length > 0 ? { indoor } : {}, ...outdoor.length > 0 ? { outdoor } : {}, ...numbers.tailGain === void 0 ? {} : { gain: numbers.tailGain } } } : {},
15562
- ...numbers.pitch === void 0 ? {} : { pitch: numbers.pitch },
15563
- ...numbers.gain === void 0 ? {} : { gain: numbers.gain },
15564
- ...numbers.falloff ? { falloff: numbers.falloff } : {},
15565
- ...numbers.cutoffK === void 0 ? {} : { cutoffK: numbers.cutoffK },
15566
- ...numbers.group ? { group: numbers.group } : {},
15567
- ...numbers.priority === void 0 ? {} : { priority: numbers.priority },
15568
- ...numbers.fallback ? { fallback: numbers.fallback } : {},
15569
- sources: files.map((file) => `${file.file}: ${file.source} ${file.author} ${file.license}`)
15570
- });
15571
- }
15572
- return { id: options.id, samples };
15573
- }
15574
15584
  var CATALOG = new Map([...SFX_CATALOG, ...SFX_IMPACTS].map((entry) => [entry.id, entry]));
15575
15585
  var PT = {
15576
15586
  group: "Som",
@@ -16832,7 +16842,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
16832
16842
  };
16833
16843
 
16834
16844
  // src/audio/recipes.ts
16835
- var scene = (id, layers, line, vars) => sceneRecipe(id, layers, line, vars ? { vars } : {});
16845
+ var scene = (id, layers, line, vars, group) => sceneRecipe(id, layers, line, { ...vars ? { vars } : {}, ...group ? { group } : {} });
16836
16846
  var boomLayers = (big) => [
16837
16847
  sceneNoise({ f: 1200, f2: 120, d: 1.8, vol: 2, wet: 1.2 }),
16838
16848
  sceneTone({ f: 65, f2: 24, d: 1, vol: 1.8 }),
@@ -16851,7 +16861,8 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
16851
16861
  [sceneNoise({ type: "bandpass", f: 850, q: 1, d: 0.25, vol: 0.9, wet: 0.3 }), sceneTone({ f: 210, f2: 90, d: 0.1, vol: 0.6 }), sceneNoise({ type: "highpass", f: 2e3, d: 0.04, vol: 0.5 })],
16852
16862
  "L1360 wood"
16853
16863
  ),
16854
- scene("thunk", [sceneNoise({ type: "bandpass", f: 700, q: 2, d: 0.07, vol: 0.4 })], "L1361 thunk"),
16864
+ // many parts coming loose at once share the `debris_knock` voices (game-audio voice-groups.json)
16865
+ scene("thunk", [sceneNoise({ type: "bandpass", f: 700, q: 2, d: 0.07, vol: 0.4 })], "L1361 thunk", void 0, "debris_knock"),
16855
16866
  scene("ping", [sceneTone({ f: [2600, 3500], f2: 1400, d: 0.14, vol: 0.18, wet: 0.3 })], "L1362 ping"),
16856
16867
  scene("clang", [sceneTone({ f: [520, 720], f2: 480, d: 0.5, vol: 0.35, wet: 0.4 }), sceneTone({ f: 1370, f2: 1300, d: 0.3, vol: 0.15 }), sceneNoise({ type: "highpass", f: 2e3, d: 0.05, vol: 0.5 })], "L1363 clang"),
16857
16868
  scene("chip", [sceneNoise({ type: "bandpass", f: 1600, q: 1.2, d: 0.06, vol: 0.5 })], "L1364 chip"),
@@ -16863,7 +16874,8 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
16863
16874
  // `thud(x, z, v)`: `v` is the `scale` param (default 1)
16864
16875
  scene("thud", [sceneTone({ f: 75, f2: 38, d: 0.22, vol: { param: "scale", scale: 0.6 } }), sceneNoise({ f: 420, d: 0.16, vol: { param: "scale", scale: 0.45 } })], "L1358 thud", { scale: 1 }),
16865
16876
  // `hiss(x, z, d)`: `seconds` is the param `d` (default 1.2)
16866
- scene("hiss", [sceneNoise({ type: "highpass", f: 3500, a: 0.05, d: { param: "seconds" }, vol: 0.35 })], "L1366 hiss", { seconds: 1.2 }),
16877
+ // every melting part shares one `sizzle` voice
16878
+ scene("hiss", [sceneNoise({ type: "highpass", f: 3500, a: 0.05, d: { param: "seconds" }, vol: 0.35 })], "L1366 hiss", { seconds: 1.2 }, "sizzle"),
16867
16879
  scene("boom", boomLayers(false), "L1367 boom"),
16868
16880
  scene("boom_big", boomLayers(true), "L1367 boom (big)"),
16869
16881
  scene("burst", [sceneNoise({ f: 700, f2: 120, d: 0.7, vol: 1.4, wet: 0.5 }), sceneNoise({ type: "highpass", f: 3e3, a: 0.05, d: 1.2, vol: 0.4, delay: 0.1 })], "L1357 burst"),
@@ -17018,6 +17030,15 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
17018
17030
  break_paper: { sound: "paper_tear" },
17019
17031
  break_plant: { sound: "branch_cut" }
17020
17032
  };
17033
+ var impactSoundIds = (rules = IMPACT_SOUND_KEYS) => {
17034
+ const ids = /* @__PURE__ */ new Set();
17035
+ for (const rule of Object.values(rules)) {
17036
+ ids.add(rule.sound);
17037
+ if (rule.above) ids.add(rule.above.sound);
17038
+ if (rule.fallback) ids.add(rule.fallback);
17039
+ }
17040
+ return [...ids];
17041
+ };
17021
17042
  var DESTRUCTION_SOUND_KEYS = {
17022
17043
  art_scene: {
17023
17044
  impact_metal: { sound: "clang" },