@adatechnology/game-destruction-three 0.14.0 → 0.15.1
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/README.md +1 -1
- package/dist/index.d.ts +21 -1
- package/dist/index.global.js +199 -103
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +111 -42
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -104,7 +104,7 @@ loose meshes. An invalid range (outside the geometry or empty) throws from `bind
|
|
|
104
104
|
|---|---|---|
|
|
105
105
|
| `dent` | vertices within `dent.radius` pushed in by `depth * (1 - (d/r)^2)^2` (skipped on `low` for meshes over 20k vertices); sparks on metal | `impact_*` |
|
|
106
106
|
| `hole` | dark disc decal on the surface (and on the exit side of a through hole); a crack star on transparent materials; sparks on metal | `impact_*` |
|
|
107
|
-
| `crack` | star of jagged lines
|
|
107
|
+
| `crack` | star of jagged white lines on glass (transparent materials) only; an opaque body draws no lines, its damage shows as chips, holes and dents | `impact_*` |
|
|
108
108
|
| `ricochet` | sparks along the reflected direction | `ricochet` |
|
|
109
109
|
| `debris` | a burst of the requested kind (`sparks`, `dust`, `shards`, `splinters`, `chips`, `fibers`, `leaves`, `drips`, `ash`, `smoke`, `steam`) | |
|
|
110
110
|
| `fracture` | part hidden; fragments (boxes, thin irregular prisms for shards) with gravity, ground bounce, settling, sleep and shrink-away; debris burst by style | `shatter_glass`, `crumble`, `splinter`, `impact_*` |
|
package/dist/index.d.ts
CHANGED
|
@@ -32,6 +32,10 @@ interface SoundDetail {
|
|
|
32
32
|
readonly confinement?: number;
|
|
33
33
|
/** `primed`: seconds until the vessel bursts (the gas leak lasts that long). */
|
|
34
34
|
readonly seconds?: number;
|
|
35
|
+
/** `burn_loop` / `burn_end`: the material burning (`wood_hard`, `rubber`...), which picks the fire's sound. */
|
|
36
|
+
readonly material?: string;
|
|
37
|
+
/** `burn_loop` / `burn_end`: the fuel itself, when it is not a material (a gas jet, a pool of fuel). Wins over `material`. */
|
|
38
|
+
readonly fuel?: 'wood' | 'fabric' | 'plastic' | 'gas' | 'liquid';
|
|
35
39
|
}
|
|
36
40
|
interface RendererOptions {
|
|
37
41
|
/** Scene that receives fragments, loose pieces, decals and particles. */
|
|
@@ -352,6 +356,12 @@ declare const BLAST_SOUNDS: readonly SoundRecipe[];
|
|
|
352
356
|
declare const FIRE_SOUNDS: readonly SoundRecipe[];
|
|
353
357
|
/** The roar of the fires: low, soft noise; `createDestructionSound` raises it with every part that burns and sprinkles crackles on it. */
|
|
354
358
|
declare const FIRE_LOOP: LoopRecipe;
|
|
359
|
+
/**
|
|
360
|
+
* What is burning, for the sound: each fuel has its own roar (a gas jet, a fuel pool, wood, plastic) and its own share of crackles. The rules are the
|
|
361
|
+
* same for all (the level grows with how much burns, fades with distance, never clips); only the timbre comes from the fuel.
|
|
362
|
+
*/
|
|
363
|
+
declare const FIRE_FUELS: readonly ["wood", "fabric", "plastic", "gas", "liquid"];
|
|
364
|
+
type FireFuel = (typeof FIRE_FUELS)[number];
|
|
355
365
|
/** The sound of a blast family. */
|
|
356
366
|
declare const BLAST_SOUND_OF: Readonly<Record<BlastKind, string>>;
|
|
357
367
|
|
|
@@ -394,8 +404,14 @@ type DestructionSoundOptions = {
|
|
|
394
404
|
};
|
|
395
405
|
/** Burn loop on or off (default on). */
|
|
396
406
|
readonly burnLoop?: boolean;
|
|
397
|
-
/** The
|
|
407
|
+
/** The loop of the wood fire (default `fire_loop`; `burn_loop` is the art scene's bright one). */
|
|
398
408
|
readonly fireLoop?: string;
|
|
409
|
+
/** Adds to or changes `FIRE_FUEL_OF`: which fuel a burning material sounds like. */
|
|
410
|
+
readonly fuels?: Readonly<Record<string, FireFuel>>;
|
|
411
|
+
/** Adds to or changes `FIRE_LOOP_OF`: the loop of each fuel. */
|
|
412
|
+
readonly fireLoops?: Partial<Readonly<Record<FireFuel, string>>>;
|
|
413
|
+
/** The fuel of a fire whose material is not in the table (default `wood`). */
|
|
414
|
+
readonly defaultFuel?: FireFuel;
|
|
399
415
|
/** Crackles per second over the fire loop: `base + perSqrtFire × √(parts burning)`, at most `max` (default 2, 3, 14). `false` turns them off. */
|
|
400
416
|
readonly crackles?: false | {
|
|
401
417
|
readonly base?: number;
|
|
@@ -423,6 +439,10 @@ type DestructionSound = {
|
|
|
423
439
|
rule(key: string, detail?: SoundDetail): SoundKeyRule | undefined;
|
|
424
440
|
/** Parts burning now. */
|
|
425
441
|
readonly burning: () => number;
|
|
442
|
+
/** Parts burning now, by fuel. */
|
|
443
|
+
readonly burningBy: () => Readonly<Partial<Record<FireFuel, number>>>;
|
|
444
|
+
/** Puts every fire sound out (the scene was cleared); the engine and the bank stay. */
|
|
445
|
+
reset(): void;
|
|
426
446
|
dispose(): void;
|
|
427
447
|
};
|
|
428
448
|
declare const DEFAULT_FIRE: {
|
package/dist/index.global.js
CHANGED
|
@@ -13021,7 +13021,6 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
13021
13021
|
var rendererCount = 0;
|
|
13022
13022
|
var COLLAPSE_CLOUD_KG = 1e3;
|
|
13023
13023
|
var CHIP_DECAL_EDGE = 0.05;
|
|
13024
|
-
var OPAQUE_CRACK = 0.1;
|
|
13025
13024
|
var WOOD_RIM = 1.5;
|
|
13026
13025
|
var IMPACT_TAGS = ["metal", "glass", "wood"];
|
|
13027
13026
|
var GLOW_FROM_C = 430;
|
|
@@ -13728,7 +13727,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
13728
13727
|
this.startFire(ev);
|
|
13729
13728
|
this.activate(ev.object, ev.part);
|
|
13730
13729
|
this.sound("ignite", ev.point, 0.7);
|
|
13731
|
-
this.sound("burn_loop", ev.point, 0.5);
|
|
13730
|
+
this.sound("burn_loop", ev.point, 0.5, this.burning(ev.object, ev.part));
|
|
13732
13731
|
break;
|
|
13733
13732
|
case "primed":
|
|
13734
13733
|
if (ev.trigger !== "explosion") {
|
|
@@ -13736,7 +13735,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
13736
13735
|
this.primedBurning.add(`${ev.object}|${ev.part}`);
|
|
13737
13736
|
this.activate(ev.object, ev.part);
|
|
13738
13737
|
this.sound("primed", ev.point, 0.7, { seconds: ev.delay });
|
|
13739
|
-
this.sound("burn_loop", ev.point, 0.5);
|
|
13738
|
+
this.sound("burn_loop", ev.point, 0.5, { fuel: "gas" });
|
|
13740
13739
|
}
|
|
13741
13740
|
break;
|
|
13742
13741
|
case "spall":
|
|
@@ -13762,15 +13761,15 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
13762
13761
|
this.stopFire(`${ev.object}|${ev.part}`);
|
|
13763
13762
|
this.vfx.burst("steam", f.point, [0, 1, 0], 14, 1.2);
|
|
13764
13763
|
}
|
|
13765
|
-
if (f || primed) this.sound("burn_end", f?.point ?? this.rootPoint(ev.object), 0.5);
|
|
13764
|
+
if (f || primed) this.sound("burn_end", f?.point ?? this.rootPoint(ev.object), 0.5, primed ? { fuel: "gas" } : this.burning(ev.object, ev.part));
|
|
13766
13765
|
this.activate(ev.object, ev.part);
|
|
13767
13766
|
this.sound("extinguish", f?.point ?? this.rootPoint(ev.object), 0.6);
|
|
13768
13767
|
break;
|
|
13769
13768
|
}
|
|
13770
13769
|
case "burnout": {
|
|
13771
13770
|
this.stopFire(`${ev.object}|${ev.part}`);
|
|
13772
|
-
this.primedBurning.delete(`${ev.object}|${ev.part}`);
|
|
13773
|
-
this.sound("burn_end", ev.point, 0.5);
|
|
13771
|
+
const primed = this.primedBurning.delete(`${ev.object}|${ev.part}`);
|
|
13772
|
+
this.sound("burn_end", ev.point, 0.5, primed ? { fuel: "gas" } : this.burning(ev.object, ev.part));
|
|
13774
13773
|
this.vfx.burst("ash", ev.point, [0, 1, 0], 16, 1);
|
|
13775
13774
|
this.vfx.burst("smoke", ev.point, [0, 1, 0], 6, 0.8, { color: SMOKE_TONES.grey });
|
|
13776
13775
|
const pv = this.partVis(ev.object, ev.part);
|
|
@@ -13838,7 +13837,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
13838
13837
|
break;
|
|
13839
13838
|
}
|
|
13840
13839
|
case "explode":
|
|
13841
|
-
this.primedBurning.delete(`${ev.object}|${ev.part}`);
|
|
13840
|
+
if (this.primedBurning.delete(`${ev.object}|${ev.part}`)) this.sound("burn_end", ev.point, 0.5, { fuel: "gas" });
|
|
13842
13841
|
this.onExplode(ev);
|
|
13843
13842
|
break;
|
|
13844
13843
|
case "destroyed":
|
|
@@ -13853,6 +13852,11 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
13853
13852
|
if (detail) this.o.onSound?.(key, point, volume, detail);
|
|
13854
13853
|
else this.o.onSound?.(key, point, volume);
|
|
13855
13854
|
}
|
|
13855
|
+
/** What a burning part is made of, for the fire's sound. */
|
|
13856
|
+
burning(objectId, partId) {
|
|
13857
|
+
const material = this.partVis(objectId, partId)?.material || this.world.part(objectId, partId)?.material;
|
|
13858
|
+
return material ? { material } : void 0;
|
|
13859
|
+
}
|
|
13856
13860
|
partVis(objectId, partId) {
|
|
13857
13861
|
return this.bounds.get(objectId)?.parts.get(partId) ?? null;
|
|
13858
13862
|
}
|
|
@@ -13952,14 +13956,11 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
13952
13956
|
const pv = b?.parts.get(ev.part);
|
|
13953
13957
|
if (!b || !pv) return;
|
|
13954
13958
|
const def = this.world.materials.get(pv.material);
|
|
13955
|
-
|
|
13956
|
-
|
|
13957
|
-
|
|
13958
|
-
const
|
|
13959
|
-
|
|
13960
|
-
const color = glass2 ? 15267071 : new this.THREE.Color(own).multiplyScalar(0.45).getHex();
|
|
13961
|
-
const length = glass2 ? ev.crack.length : Math.min(ev.crack.length, OPAQUE_CRACK);
|
|
13962
|
-
this.visuals.addCrack(mv, wp, this.worldDir(b, ev.crack.normal), ev.crack.rays, length, color, hashNumbers(ev.time, ev.worldPoint[0], ev.worldPoint[1], ev.worldPoint[2]));
|
|
13959
|
+
if (def?.visual?.transparent) {
|
|
13960
|
+
const wp = new this.THREE.Vector3(ev.worldPoint[0], ev.worldPoint[1], ev.worldPoint[2]);
|
|
13961
|
+
const mv = this.nearestMesh(pv, wp);
|
|
13962
|
+
const seed = hashNumbers(ev.time, ev.worldPoint[0], ev.worldPoint[1], ev.worldPoint[2]);
|
|
13963
|
+
if (mv) this.visuals.addCrack(mv, wp, this.worldDir(b, ev.crack.normal), ev.crack.rays, ev.crack.length, 15267071, seed);
|
|
13963
13964
|
}
|
|
13964
13965
|
this.impactSound(pv.material, ev.worldPoint, 0.5, ev.blow);
|
|
13965
13966
|
}
|
|
@@ -14539,7 +14540,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
14539
14540
|
}
|
|
14540
14541
|
};
|
|
14541
14542
|
|
|
14542
|
-
// ../game-audio/dist/chunk-
|
|
14543
|
+
// ../game-audio/dist/chunk-KBTUANNG.js
|
|
14543
14544
|
var DISTANCE_CURVES = {
|
|
14544
14545
|
/** The game's `sfx`: `vol / (1 + d² × 0.004)`, cutoff `/ (1 + d × 0.01)`, silent below 0.01 (jogo L62091–62092, L62101). */
|
|
14545
14546
|
game_sfx: { model: "inverse_square", k: 4e-3, cutoffK: 0.01, minGain: 0.01 },
|
|
@@ -14752,7 +14753,11 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
14752
14753
|
["casing_drop_terra_pistol", 1],
|
|
14753
14754
|
["casing_drop_terra_rifle", 1],
|
|
14754
14755
|
["casing_drop_terra_shell", 1],
|
|
14755
|
-
["rocket_fire", 2]
|
|
14756
|
+
["rocket_fire", 2],
|
|
14757
|
+
["smg_45_auto", 2, "sfx_pistol"],
|
|
14758
|
+
["weapon_draw", 2],
|
|
14759
|
+
["suppressor_attach", 3],
|
|
14760
|
+
["suppressor_detach", 3]
|
|
14756
14761
|
]),
|
|
14757
14762
|
...entries("explosoes-fogo", [
|
|
14758
14763
|
["explosion_grenade", 1, "boom"],
|
|
@@ -14766,7 +14771,11 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
14766
14771
|
["fire_loop_large", 1],
|
|
14767
14772
|
["fire_extinguish", 2, "hiss"],
|
|
14768
14773
|
["gas_leak_hiss", 2],
|
|
14769
|
-
["structure_collapse", 2, "crumble"]
|
|
14774
|
+
["structure_collapse", 2, "crumble"],
|
|
14775
|
+
["grenade_bounce", 1],
|
|
14776
|
+
["c4_plant", 2],
|
|
14777
|
+
["c4_beep", 2],
|
|
14778
|
+
["c4_disarm", 2]
|
|
14770
14779
|
]),
|
|
14771
14780
|
...entries("personagem", [
|
|
14772
14781
|
["footstep_concrete_walk", 1, "sfx_step"],
|
|
@@ -14782,7 +14791,19 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
14782
14791
|
["blunt_hit", 1],
|
|
14783
14792
|
["bite", 1, "sfx_flesh"],
|
|
14784
14793
|
["body_fall", 1],
|
|
14785
|
-
["player_hurt", 2]
|
|
14794
|
+
["player_hurt", 2],
|
|
14795
|
+
["footstep_tile_walk", 1, "sfx_step"],
|
|
14796
|
+
["footstep_water_walk", 1, "sfx_step"],
|
|
14797
|
+
["footstep_grate_walk", 2, "sfx_step"],
|
|
14798
|
+
["footstep_duct_walk", 3, "sfx_step"],
|
|
14799
|
+
["ladder_climb", 2],
|
|
14800
|
+
["swim", 2],
|
|
14801
|
+
["zombie_groan", 1],
|
|
14802
|
+
["zombie_alert", 1],
|
|
14803
|
+
["zombie_attack", 1],
|
|
14804
|
+
["zombie_pain", 1],
|
|
14805
|
+
["zombie_claw_hit", 1, "sfx_flesh"],
|
|
14806
|
+
["zombie_claw_miss", 2]
|
|
14786
14807
|
]),
|
|
14787
14808
|
...entries("veiculos", [
|
|
14788
14809
|
["engine_loop_car", 1],
|
|
@@ -14810,7 +14831,8 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
14810
14831
|
["wind_loop", 2],
|
|
14811
14832
|
["thunder_near", 2],
|
|
14812
14833
|
["thunder_far", 2],
|
|
14813
|
-
["water_splash", 2]
|
|
14834
|
+
["water_splash", 2],
|
|
14835
|
+
["helicopter_loop", 3]
|
|
14814
14836
|
])
|
|
14815
14837
|
];
|
|
14816
14838
|
var SFX_MATERIALS = [
|
|
@@ -14892,6 +14914,60 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
14892
14914
|
burst: 20,
|
|
14893
14915
|
burstSpacing: 0.06
|
|
14894
14916
|
};
|
|
14917
|
+
var SFX_TIERS = { light: 0, medium: 0.34, heavy: 0.67 };
|
|
14918
|
+
function splitTier(id) {
|
|
14919
|
+
const match = /^(.*)_(light|medium|heavy)$/.exec(id);
|
|
14920
|
+
return match ? { base: match[1], tier: match[2] } : { base: id };
|
|
14921
|
+
}
|
|
14922
|
+
var refsOf = (entries2, baseUrl) => (entries2 ?? []).map((entry) => ({ url: `${baseUrl}${entry.file}` }));
|
|
14923
|
+
function sampleBankFromManifest(manifest, options) {
|
|
14924
|
+
const baseUrl = options.baseUrl ?? "";
|
|
14925
|
+
const samples = [];
|
|
14926
|
+
const tiersOf = /* @__PURE__ */ new Map();
|
|
14927
|
+
for (const sound of manifest.sounds) {
|
|
14928
|
+
const { base, tier } = splitTier(sound.id);
|
|
14929
|
+
if (tier) tiersOf.set(base, [...tiersOf.get(base) ?? [], sound]);
|
|
14930
|
+
}
|
|
14931
|
+
const bases = /* @__PURE__ */ new Map();
|
|
14932
|
+
for (const sound of manifest.sounds) {
|
|
14933
|
+
if (!splitTier(sound.id).tier) bases.set(sound.id, sound);
|
|
14934
|
+
}
|
|
14935
|
+
for (const [base, tiers] of tiersOf) {
|
|
14936
|
+
if (!bases.has(base)) bases.set(base, { id: base, category: tiers[0]?.category ?? "", layers: { close: tiers[0]?.layers.close ?? [] } });
|
|
14937
|
+
}
|
|
14938
|
+
for (const sound of bases.values()) {
|
|
14939
|
+
const numbers = options.sounds?.[sound.id] ?? options.defaults?.(sound);
|
|
14940
|
+
const close = refsOf(sound.layers.close, baseUrl);
|
|
14941
|
+
if (!numbers || close.length === 0) continue;
|
|
14942
|
+
const tiers = (tiersOf.get(sound.id) ?? []).map((tier) => {
|
|
14943
|
+
const name = splitTier(tier.id).tier;
|
|
14944
|
+
const tierFar = refsOf(tier.layers.far, baseUrl);
|
|
14945
|
+
return { name, from: SFX_TIERS[name] ?? 0, close: refsOf(tier.layers.close, baseUrl), ...tierFar.length > 0 ? { far: tierFar } : {} };
|
|
14946
|
+
}).sort((a, b) => a.from - b.from);
|
|
14947
|
+
const far = refsOf(sound.layers.far, baseUrl);
|
|
14948
|
+
const indoor = refsOf(sound.layers.tail_in, baseUrl);
|
|
14949
|
+
const outdoor = refsOf(sound.layers.tail_out, baseUrl);
|
|
14950
|
+
const files = [sound, ...tiersOf.get(sound.id) ?? []].flatMap((entry) => Object.values(entry.layers).flatMap((entries2) => entries2 ?? []));
|
|
14951
|
+
samples.push({
|
|
14952
|
+
id: sound.id,
|
|
14953
|
+
bus: numbers.bus,
|
|
14954
|
+
close,
|
|
14955
|
+
...far.length > 0 ? { far } : {},
|
|
14956
|
+
...tiers.length > 0 ? { tiers } : {},
|
|
14957
|
+
...numbers.crossover ? { crossover: numbers.crossover } : {},
|
|
14958
|
+
...indoor.length > 0 || outdoor.length > 0 ? { tail: { ...indoor.length > 0 ? { indoor } : {}, ...outdoor.length > 0 ? { outdoor } : {}, ...numbers.tailGain === void 0 ? {} : { gain: numbers.tailGain } } } : {},
|
|
14959
|
+
...numbers.pitch === void 0 ? {} : { pitch: numbers.pitch },
|
|
14960
|
+
...numbers.gain === void 0 ? {} : { gain: numbers.gain },
|
|
14961
|
+
...numbers.falloff ? { falloff: numbers.falloff } : {},
|
|
14962
|
+
...numbers.cutoffK === void 0 ? {} : { cutoffK: numbers.cutoffK },
|
|
14963
|
+
...numbers.group ? { group: numbers.group } : {},
|
|
14964
|
+
...numbers.priority === void 0 ? {} : { priority: numbers.priority },
|
|
14965
|
+
...numbers.fallback ? { fallback: numbers.fallback } : {},
|
|
14966
|
+
sources: files.map((file) => `${file.file}: ${file.source} ${file.author} ${file.license}`)
|
|
14967
|
+
});
|
|
14968
|
+
}
|
|
14969
|
+
return { id: options.id, samples };
|
|
14970
|
+
}
|
|
14895
14971
|
var PT = {
|
|
14896
14972
|
group: "Som",
|
|
14897
14973
|
name: "Painel de som (arquivos e C1\u2013C10)",
|
|
@@ -14899,6 +14975,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
14899
14975
|
category: "1 \xB7 Categoria",
|
|
14900
14976
|
sound: "1 \xB7 Som",
|
|
14901
14977
|
play: "1 \xB7 \u25B6 Tocar",
|
|
14978
|
+
play_user: "1 \xB7 \u25B6 Tocar o seu",
|
|
14902
14979
|
material: "2 \xB7 Material",
|
|
14903
14980
|
blow: "2 \xB7 Golpe",
|
|
14904
14981
|
strike: "2 \xB7 \u25B6 Tocar golpe",
|
|
@@ -14920,6 +14997,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
14920
14997
|
approve: "5 \xB7 Aprovo (C10)"
|
|
14921
14998
|
},
|
|
14922
14999
|
hints: {
|
|
15000
|
+
play_user: "Toca a sua grava\xE7\xE3o deste som (dos seus pacotes, fora do git), mesmo quando o SDK tem uma melhor e toca na frente.",
|
|
14923
15001
|
sound: "A = arquivo, S = sintetizado, F = faltando. O que tem arquivo toca o arquivo; o resto toca o som atual.",
|
|
14924
15002
|
strike: "Toca impact_<material>_<golpe>: o arquivo se existir, sen\xE3o o som atual daquele material.",
|
|
14925
15003
|
wall: "P\xF5e a parede de casa entre voc\xEA e a fonte: o som fica abafado (C4).",
|
|
@@ -14964,9 +15042,10 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
14964
15042
|
strengths: { light: "leve", medium: "m\xE9dio", heavy: "forte" },
|
|
14965
15043
|
states: { file: "A", synth: "S", missing: "F" },
|
|
14966
15044
|
criteria: { C1: "C1 Sincronia", C2: "C2 Certo p/ a\xE7\xE3o", C3: "C3 Dist\xE2ncia", C4: "C4 Posi\xE7\xE3o", C5: "C5 Varia\xE7\xE3o", C6: "C6 Volume", C7: "C7 Intensidade", C8: "C8 Cauda", C9: "C9 Rajada", C10: "C10 Escuta" },
|
|
14967
|
-
metrics: { chosen: "1 \xB7 Escolhido", matrix: "2 \xB7 Matriz", last: "\xDAltimo tocado", ab: "4 \xB7 A \xD7 B", blind: "4 \xB7 X", verdicts: "4 \xB7 Prefer\xEAncias", state: "5 \xB7 Medi\xE7\xE3o", count: "1 \xB7 Cat\xE1logo" },
|
|
15045
|
+
metrics: { source: "1 \xB7 Fonte do que tocou", chosen: "1 \xB7 Escolhido", matrix: "2 \xB7 Matriz", last: "\xDAltimo tocado", ab: "4 \xB7 A \xD7 B", blind: "4 \xB7 X", verdicts: "4 \xB7 Prefer\xEAncias", state: "5 \xB7 Medi\xE7\xE3o", count: "1 \xB7 Cat\xE1logo" },
|
|
14968
15046
|
run: { idle: "parada", measuring: "medindo\u2026", done: "pronta", failed: "falhou", recording: "gravando\u2026", recorded: "grava\xE7\xE3o baixada" },
|
|
14969
15047
|
words: { none: "\u2014", hidden: "? (revele)", prefers: "prefere", approved: "aprovado pelo dono" },
|
|
15048
|
+
sources: { sdk: "SDK", user: "seu som", synth: "sintetizado" },
|
|
14970
15049
|
probe: "Fonte do som",
|
|
14971
15050
|
wall: "Parede (oclus\xE3o)",
|
|
14972
15051
|
scenarios: { pipeline: "Arquivo \u2192 decodifica \u2192 toca (round-robin, cauda)", criteria: "Crit\xE9rios C1\u2013C9 no som de calibra\xE7\xE3o", loop: "Loop de arquivo: emenda sem buraco (crossfade)", panel: "Painel: categorias, matriz, A/B e parede" }
|
|
@@ -14979,6 +15058,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
14979
15058
|
category: "1 \xB7 Category",
|
|
14980
15059
|
sound: "1 \xB7 Sound",
|
|
14981
15060
|
play: "1 \xB7 \u25B6 Play",
|
|
15061
|
+
play_user: "1 \xB7 \u25B6 Play yours",
|
|
14982
15062
|
material: "2 \xB7 Material",
|
|
14983
15063
|
blow: "2 \xB7 Blow",
|
|
14984
15064
|
strike: "2 \xB7 \u25B6 Play blow",
|
|
@@ -15000,6 +15080,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
15000
15080
|
approve: "5 \xB7 Approve (C10)"
|
|
15001
15081
|
},
|
|
15002
15082
|
hints: {
|
|
15083
|
+
play_user: "Plays your own take of this sound (from your packs, kept out of git), even where the SDK has a better one that plays first.",
|
|
15003
15084
|
sound: "A = file, S = synthesized, F = missing. A file plays the file; the rest plays the current sound.",
|
|
15004
15085
|
strike: "Plays impact_<material>_<blow>: the file if there is one, else the current sound of that material.",
|
|
15005
15086
|
wall: "Puts the house wall between you and the source: the sound is muffled (C4).",
|
|
@@ -15034,69 +15115,16 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
15034
15115
|
environments: { indoor: "indoor", outdoor: "outdoor" },
|
|
15035
15116
|
strengths: { light: "light", medium: "medium", heavy: "heavy" },
|
|
15036
15117
|
criteria: { C1: "C1 Sync", C2: "C2 Right sound", C3: "C3 Distance", C4: "C4 Position", C5: "C5 Variation", C6: "C6 Level", C7: "C7 Strength", C8: "C8 Tail", C9: "C9 Burst", C10: "C10 Listening" },
|
|
15037
|
-
metrics: { chosen: "1 \xB7 Chosen", matrix: "2 \xB7 Matrix", last: "Last played", ab: "4 \xB7 A \xD7 B", blind: "4 \xB7 X", verdicts: "4 \xB7 Preferences", state: "5 \xB7 Measurement", count: "1 \xB7 Catalogue" },
|
|
15118
|
+
metrics: { source: "1 \xB7 Source of what played", chosen: "1 \xB7 Chosen", matrix: "2 \xB7 Matrix", last: "Last played", ab: "4 \xB7 A \xD7 B", blind: "4 \xB7 X", verdicts: "4 \xB7 Preferences", state: "5 \xB7 Measurement", count: "1 \xB7 Catalogue" },
|
|
15038
15119
|
run: { idle: "idle", measuring: "measuring\u2026", done: "done", failed: "failed", recording: "recording\u2026", recorded: "recording downloaded" },
|
|
15039
15120
|
words: { none: "\u2014", hidden: "? (reveal)", prefers: "prefers", approved: "approved by the owner" },
|
|
15121
|
+
sources: { sdk: "SDK", user: "your sound", synth: "synthesized" },
|
|
15040
15122
|
probe: "Sound source",
|
|
15041
15123
|
wall: "Wall (occlusion)",
|
|
15042
15124
|
scenarios: { pipeline: "File \u2192 decode \u2192 play (round-robin, tail)", criteria: "Criteria C1\u2013C9 on the calibration sound", loop: "File loop: seamless joins (crossfade)", panel: "Panel: categories, matrix, A/B and wall" }
|
|
15043
15125
|
};
|
|
15044
15126
|
|
|
15045
15127
|
// ../game-audio/dist/index.js
|
|
15046
|
-
var SFX_TIERS = { light: 0, medium: 0.34, heavy: 0.67 };
|
|
15047
|
-
function splitTier(id) {
|
|
15048
|
-
const match = /^(.*)_(light|medium|heavy)$/.exec(id);
|
|
15049
|
-
return match ? { base: match[1], tier: match[2] } : { base: id };
|
|
15050
|
-
}
|
|
15051
|
-
var refsOf = (entries2, baseUrl) => (entries2 ?? []).map((entry) => ({ url: `${baseUrl}${entry.file}` }));
|
|
15052
|
-
function sampleBankFromManifest(manifest, options) {
|
|
15053
|
-
const baseUrl = options.baseUrl ?? "";
|
|
15054
|
-
const samples = [];
|
|
15055
|
-
const tiersOf = /* @__PURE__ */ new Map();
|
|
15056
|
-
for (const sound of manifest.sounds) {
|
|
15057
|
-
const { base, tier } = splitTier(sound.id);
|
|
15058
|
-
if (tier) tiersOf.set(base, [...tiersOf.get(base) ?? [], sound]);
|
|
15059
|
-
}
|
|
15060
|
-
const bases = /* @__PURE__ */ new Map();
|
|
15061
|
-
for (const sound of manifest.sounds) {
|
|
15062
|
-
if (!splitTier(sound.id).tier) bases.set(sound.id, sound);
|
|
15063
|
-
}
|
|
15064
|
-
for (const [base, tiers] of tiersOf) {
|
|
15065
|
-
if (!bases.has(base)) bases.set(base, { id: base, category: tiers[0]?.category ?? "", layers: { close: tiers[0]?.layers.close ?? [] } });
|
|
15066
|
-
}
|
|
15067
|
-
for (const sound of bases.values()) {
|
|
15068
|
-
const numbers = options.sounds?.[sound.id] ?? options.defaults?.(sound);
|
|
15069
|
-
const close = refsOf(sound.layers.close, baseUrl);
|
|
15070
|
-
if (!numbers || close.length === 0) continue;
|
|
15071
|
-
const tiers = (tiersOf.get(sound.id) ?? []).map((tier) => {
|
|
15072
|
-
const name = splitTier(tier.id).tier;
|
|
15073
|
-
const tierFar = refsOf(tier.layers.far, baseUrl);
|
|
15074
|
-
return { name, from: SFX_TIERS[name] ?? 0, close: refsOf(tier.layers.close, baseUrl), ...tierFar.length > 0 ? { far: tierFar } : {} };
|
|
15075
|
-
}).sort((a, b) => a.from - b.from);
|
|
15076
|
-
const far = refsOf(sound.layers.far, baseUrl);
|
|
15077
|
-
const indoor = refsOf(sound.layers.tail_in, baseUrl);
|
|
15078
|
-
const outdoor = refsOf(sound.layers.tail_out, baseUrl);
|
|
15079
|
-
const files = [sound, ...tiersOf.get(sound.id) ?? []].flatMap((entry) => Object.values(entry.layers).flatMap((entries2) => entries2 ?? []));
|
|
15080
|
-
samples.push({
|
|
15081
|
-
id: sound.id,
|
|
15082
|
-
bus: numbers.bus,
|
|
15083
|
-
close,
|
|
15084
|
-
...far.length > 0 ? { far } : {},
|
|
15085
|
-
...tiers.length > 0 ? { tiers } : {},
|
|
15086
|
-
...numbers.crossover ? { crossover: numbers.crossover } : {},
|
|
15087
|
-
...indoor.length > 0 || outdoor.length > 0 ? { tail: { ...indoor.length > 0 ? { indoor } : {}, ...outdoor.length > 0 ? { outdoor } : {}, ...numbers.tailGain === void 0 ? {} : { gain: numbers.tailGain } } } : {},
|
|
15088
|
-
...numbers.pitch === void 0 ? {} : { pitch: numbers.pitch },
|
|
15089
|
-
...numbers.gain === void 0 ? {} : { gain: numbers.gain },
|
|
15090
|
-
...numbers.falloff ? { falloff: numbers.falloff } : {},
|
|
15091
|
-
...numbers.cutoffK === void 0 ? {} : { cutoffK: numbers.cutoffK },
|
|
15092
|
-
...numbers.group ? { group: numbers.group } : {},
|
|
15093
|
-
...numbers.priority === void 0 ? {} : { priority: numbers.priority },
|
|
15094
|
-
...numbers.fallback ? { fallback: numbers.fallback } : {},
|
|
15095
|
-
sources: files.map((file) => `${file.file}: ${file.source} ${file.author} ${file.license}`)
|
|
15096
|
-
});
|
|
15097
|
-
}
|
|
15098
|
-
return { id: options.id, samples };
|
|
15099
|
-
}
|
|
15100
15128
|
var ATTACK = 2e-3;
|
|
15101
15129
|
function lengthOf(d, attack) {
|
|
15102
15130
|
if (typeof d === "number") return attack + d;
|
|
@@ -16087,6 +16115,47 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
16087
16115
|
volume: 0,
|
|
16088
16116
|
sources: ["sdk: the roar under the crackles of a fire"]
|
|
16089
16117
|
};
|
|
16118
|
+
var FIRE_FUEL_OF = {
|
|
16119
|
+
wood_soft: "wood",
|
|
16120
|
+
wood_hard: "wood",
|
|
16121
|
+
plywood: "wood",
|
|
16122
|
+
mdf: "wood",
|
|
16123
|
+
green_wood: "wood",
|
|
16124
|
+
foliage: "wood",
|
|
16125
|
+
cactus: "wood",
|
|
16126
|
+
paper: "fabric",
|
|
16127
|
+
fabric: "fabric",
|
|
16128
|
+
leather: "fabric",
|
|
16129
|
+
foam: "plastic",
|
|
16130
|
+
plastic: "plastic",
|
|
16131
|
+
rubber: "plastic",
|
|
16132
|
+
wax: "plastic"
|
|
16133
|
+
};
|
|
16134
|
+
var FIRE_LOOP_OF = {
|
|
16135
|
+
wood: "fire_loop",
|
|
16136
|
+
fabric: "fire_loop",
|
|
16137
|
+
plastic: "fire_loop_plastic",
|
|
16138
|
+
gas: "fire_loop_gas",
|
|
16139
|
+
liquid: "fire_loop_liquid"
|
|
16140
|
+
};
|
|
16141
|
+
var FIRE_CRACKLE_OF = { wood: 1, fabric: 0.5, plastic: 0.35, gas: 0, liquid: 0 };
|
|
16142
|
+
var roar = (id, bank, source) => ({
|
|
16143
|
+
id,
|
|
16144
|
+
bus: "world",
|
|
16145
|
+
order: "chain_loop",
|
|
16146
|
+
source: { kind: "noise", loop: true },
|
|
16147
|
+
filters: { mode: "serial", bank },
|
|
16148
|
+
volume: 0,
|
|
16149
|
+
sources: [source]
|
|
16150
|
+
});
|
|
16151
|
+
var FIRE_FUEL_LOOPS = [
|
|
16152
|
+
// a gas jet: a steady, broad roar, brighter than wood and without crackles
|
|
16153
|
+
roar("fire_loop_gas", [{ type: "highpass", frequency: { set: 220 }, q: 0.7 }, { type: "lowpass", frequency: { set: 2400 }, q: 0.6 }], "sdk: a gas jet burning (a vessel venting into the flame)"),
|
|
16154
|
+
// a fuel pool: a soft, low, rolling roar
|
|
16155
|
+
roar("fire_loop_liquid", [{ type: "highpass", frequency: { set: 90 }, q: 0.7 }, { type: "lowpass", frequency: { set: 650 }, q: 0.9 }], "sdk: a pool of fuel burning"),
|
|
16156
|
+
// plastic and rubber: a thin sizzle over a low burn
|
|
16157
|
+
roar("fire_loop_plastic", [{ type: "bandpass", frequency: { set: 1800 }, q: 0.6 }], "sdk: plastic and rubber melting in the fire")
|
|
16158
|
+
];
|
|
16090
16159
|
var BLAST_SOUND_OF = {
|
|
16091
16160
|
grenade: "explosion_grenade",
|
|
16092
16161
|
big: "explosion_big",
|
|
@@ -16233,7 +16302,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
16233
16302
|
impact2("plastic_crack", [sceneNoise({ type: "bandpass", f: 1800, q: 2, d: 0.06, vol: 0.75 }), sceneTone({ f: [450, 550], f2: 250, d: 0.05, vol: 0.22 })]),
|
|
16234
16303
|
impact2("mdf_crumble", [sceneNoise({ type: "lowpass", f: 700, d: 0.25, vol: 0.75, wet: 0.2 }), ...sceneMany(4, () => sceneNoise({ type: "lowpass", f: 500, d: 0.05, vol: 0.32, delay: [0.05, 0.3] }))])
|
|
16235
16304
|
];
|
|
16236
|
-
var DESTRUCTION_SOUND_BANK = { id: "destruction_three", sounds: [...SCENE_SOUNDS, ...DRAG_SOUNDS, ...LEAF_SOUNDS, ...IMPACT_SOUNDS, EXPLOSION_BOOM, ...BLAST_SOUNDS, ...FIRE_SOUNDS], loops: [BURN_LOOP, FIRE_LOOP] };
|
|
16305
|
+
var DESTRUCTION_SOUND_BANK = { id: "destruction_three", sounds: [...SCENE_SOUNDS, ...DRAG_SOUNDS, ...LEAF_SOUNDS, ...IMPACT_SOUNDS, EXPLOSION_BOOM, ...BLAST_SOUNDS, ...FIRE_SOUNDS], loops: [BURN_LOOP, FIRE_LOOP, ...FIRE_FUEL_LOOPS] };
|
|
16237
16306
|
|
|
16238
16307
|
// src/audio/sound.ts
|
|
16239
16308
|
var IMPACT_SOUND_KEYS = {
|
|
@@ -16384,31 +16453,52 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
16384
16453
|
const rules = { ...DESTRUCTION_SOUND_KEYS.art_scene, ...options.style === "game" ? DESTRUCTION_SOUND_KEYS.game : {}, ...options.keys };
|
|
16385
16454
|
const blastByKind = options.style !== "game" && !(options.keys && "explode" in options.keys);
|
|
16386
16455
|
const channel = engine.channel({ seed: options.seed ?? 1 });
|
|
16387
|
-
|
|
16388
|
-
|
|
16456
|
+
const fuelOf = { ...FIRE_FUEL_OF, ...options.fuels };
|
|
16457
|
+
const loopOf = { ...FIRE_LOOP_OF, ...options.fireLoop ? { wood: fireLoop, fabric: fireLoop } : {}, ...options.fireLoops };
|
|
16458
|
+
const defaultFuel = options.defaultFuel ?? "wood";
|
|
16459
|
+
const loops = /* @__PURE__ */ new Map();
|
|
16389
16460
|
const fires = [];
|
|
16390
16461
|
let nextCrackle = 0;
|
|
16462
|
+
const fuelFor = (detail) => detail?.fuel ?? (detail?.material !== void 0 ? fuelOf[detail.material] : void 0) ?? defaultFuel;
|
|
16391
16463
|
const setFire = () => {
|
|
16392
16464
|
if (options.burnLoop === false) return;
|
|
16393
|
-
|
|
16394
|
-
|
|
16395
|
-
|
|
16396
|
-
|
|
16465
|
+
const count = /* @__PURE__ */ new Map();
|
|
16466
|
+
for (const f of fires) {
|
|
16467
|
+
const id = loopOf[f.fuel];
|
|
16468
|
+
count.set(id, (count.get(id) ?? 0) + 1);
|
|
16469
|
+
}
|
|
16470
|
+
for (const [id, handle] of loops) {
|
|
16471
|
+
if (count.has(id)) continue;
|
|
16472
|
+
handle.stop();
|
|
16473
|
+
loops.delete(id);
|
|
16474
|
+
}
|
|
16475
|
+
for (const [id, n] of count) {
|
|
16476
|
+
let handle = loops.get(id);
|
|
16477
|
+
if (!handle) {
|
|
16478
|
+
handle = engine.loop(id);
|
|
16479
|
+
loops.set(id, handle);
|
|
16480
|
+
}
|
|
16481
|
+
handle.set({ volume: Math.min(fire2.max, fire2.perFire * n) });
|
|
16397
16482
|
}
|
|
16398
|
-
loop ?? (loop = engine.loop(fireLoop));
|
|
16399
|
-
loop.set({ volume: Math.min(fire2.max, fire2.perFire * burning) });
|
|
16400
16483
|
};
|
|
16401
|
-
const forget = (point) => {
|
|
16484
|
+
const forget = (point, fuel) => {
|
|
16402
16485
|
let best = -1;
|
|
16403
16486
|
let bestD = Infinity;
|
|
16404
16487
|
fires.forEach((f, i) => {
|
|
16405
|
-
|
|
16488
|
+
if (fuel !== void 0 && f.fuel !== fuel) return;
|
|
16489
|
+
const d = (f.point[0] - point[0]) ** 2 + (f.point[1] - point[1]) ** 2 + (f.point[2] - point[2]) ** 2;
|
|
16406
16490
|
if (d < bestD) {
|
|
16407
16491
|
bestD = d;
|
|
16408
16492
|
best = i;
|
|
16409
16493
|
}
|
|
16410
16494
|
});
|
|
16411
|
-
if (best
|
|
16495
|
+
if (best < 0 && fuel !== void 0) forget(point, void 0);
|
|
16496
|
+
else if (best >= 0) fires.splice(best, 1);
|
|
16497
|
+
};
|
|
16498
|
+
const reset = () => {
|
|
16499
|
+
for (const handle of loops.values()) handle.stop();
|
|
16500
|
+
loops.clear();
|
|
16501
|
+
fires.length = 0;
|
|
16412
16502
|
};
|
|
16413
16503
|
const blastSound = (point, volume, detail) => {
|
|
16414
16504
|
const named = detail?.effect === void 0 ? void 0 : kinds[detail.effect];
|
|
@@ -16420,14 +16510,12 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
16420
16510
|
return {
|
|
16421
16511
|
onSound(key, point, volume, detail) {
|
|
16422
16512
|
if (key === "burn_loop") {
|
|
16423
|
-
|
|
16424
|
-
fires.push(point);
|
|
16513
|
+
fires.push({ point, fuel: fuelFor(detail) });
|
|
16425
16514
|
setFire();
|
|
16426
16515
|
return;
|
|
16427
16516
|
}
|
|
16428
16517
|
if (key === "burn_end") {
|
|
16429
|
-
|
|
16430
|
-
forget(point);
|
|
16518
|
+
forget(point, detail?.fuel ?? (detail?.material !== void 0 ? fuelOf[detail.material] : void 0));
|
|
16431
16519
|
setFire();
|
|
16432
16520
|
return;
|
|
16433
16521
|
}
|
|
@@ -16457,12 +16545,15 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
16457
16545
|
},
|
|
16458
16546
|
update(dt) {
|
|
16459
16547
|
if (!crackles || fires.length === 0 || options.burnLoop === false) return;
|
|
16548
|
+
const weight = fires.reduce((sum, f) => sum + FIRE_CRACKLE_OF[f.fuel], 0);
|
|
16549
|
+
if (weight <= 0) return;
|
|
16460
16550
|
nextCrackle -= dt;
|
|
16461
16551
|
for (let i = 0; i < 4 && nextCrackle <= 0; i++) {
|
|
16462
|
-
const rate = Math.min(crackles.max, crackles.base + crackles.perSqrtFire * Math.sqrt(
|
|
16552
|
+
const rate = Math.min(crackles.max, crackles.base * Math.min(1, weight) + crackles.perSqrtFire * Math.sqrt(weight));
|
|
16463
16553
|
nextCrackle += (0.4 + channel.random() * 1.2) / rate;
|
|
16464
|
-
|
|
16465
|
-
|
|
16554
|
+
let pick3 = channel.random() * weight;
|
|
16555
|
+
const at3 = fires.find((f) => (pick3 -= FIRE_CRACKLE_OF[f.fuel]) <= 0) ?? fires[fires.length - 1];
|
|
16556
|
+
engine.play(channel.random() < 0.18 ? "fire_pop" : "fire_crackle", { position: at3.point, volume: crackles.volume });
|
|
16466
16557
|
}
|
|
16467
16558
|
if (nextCrackle < 0) nextCrackle = 0;
|
|
16468
16559
|
},
|
|
@@ -16471,13 +16562,14 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
16471
16562
|
for (const k of detail?.keys ?? []) if (k in rules) return rules[k] ?? void 0;
|
|
16472
16563
|
return rules[key] ?? void 0;
|
|
16473
16564
|
},
|
|
16474
|
-
burning: () =>
|
|
16475
|
-
|
|
16476
|
-
|
|
16477
|
-
|
|
16478
|
-
|
|
16479
|
-
|
|
16480
|
-
|
|
16565
|
+
burning: () => fires.length,
|
|
16566
|
+
burningBy: () => {
|
|
16567
|
+
const by = {};
|
|
16568
|
+
for (const f of fires) by[f.fuel] = (by[f.fuel] ?? 0) + 1;
|
|
16569
|
+
return by;
|
|
16570
|
+
},
|
|
16571
|
+
reset,
|
|
16572
|
+
dispose: reset
|
|
16481
16573
|
};
|
|
16482
16574
|
}
|
|
16483
16575
|
|
|
@@ -16498,7 +16590,11 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
16498
16590
|
fire_extinguish: fire(0.7),
|
|
16499
16591
|
gas_leak: fire(0.5),
|
|
16500
16592
|
// the roar: recorded fires chained with a crossfade (the level comes from `createDestructionSound`, by how much burns)
|
|
16501
|
-
fire_loop: { bus: "world", gain: 4, loop: { crossfade: 1 } }
|
|
16593
|
+
fire_loop: { bus: "world", gain: 4, loop: { crossfade: 1 } },
|
|
16594
|
+
// each fuel has its own roar: a gas jet (burners and torches), a pool of fuel, plastic and rubber sizzling under the flames
|
|
16595
|
+
fire_loop_gas: { bus: "world", gain: 6, loop: { crossfade: 1 } },
|
|
16596
|
+
fire_loop_liquid: { bus: "world", gain: 3.5, loop: { crossfade: 1 } },
|
|
16597
|
+
fire_loop_plastic: { bus: "world", gain: 1, loop: { crossfade: 0.6 } }
|
|
16502
16598
|
};
|
|
16503
16599
|
function blastFireSampleBank(manifest, options = {}) {
|
|
16504
16600
|
const sounds = options.sounds ?? BLAST_FIRE_SAMPLES;
|