@adatechnology/game-test-room 0.23.0 → 0.25.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 +8 -1
- package/dist/index.global.js +364 -164
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +77 -13
- package/dist/index.js.map +1 -1
- package/package.json +13 -13
package/dist/index.global.js
CHANGED
|
@@ -62,8 +62,29 @@ var GameTestRoom = (() => {
|
|
|
62
62
|
const length3 = Math.hypot(direction[0], direction[1], direction[2]);
|
|
63
63
|
return { speed, direction: [direction[0] / length3, direction[1] / length3, direction[2] / length3], distance: distance4, falloff };
|
|
64
64
|
}
|
|
65
|
+
var DEFAULT_BLAST_IMPULSE = { bodyArea: 0.7, lift: 0.15, minSpeed: 0.3, tntPerJoule: 0.24 / 2e5 };
|
|
66
|
+
var NEAREST = 0.3;
|
|
67
|
+
function sideOnImpulse(tnt, distance4) {
|
|
68
|
+
if (!(tnt > 0)) return 0;
|
|
69
|
+
const w3 = Math.cbrt(tnt);
|
|
70
|
+
const z = Math.max(distance4, NEAREST) / w3;
|
|
71
|
+
const scaled2 = 0.067 * Math.sqrt(1 + (z / 0.23) ** 4) / (z * z * Math.cbrt(1 + (z / 1.55) ** 3));
|
|
72
|
+
return scaled2 * w3 * 100;
|
|
73
|
+
}
|
|
74
|
+
function bodyImpulse(tnt, distance4) {
|
|
75
|
+
if (!(tnt > 0)) return 0;
|
|
76
|
+
const z = Math.max(distance4, NEAREST) / Math.cbrt(tnt);
|
|
77
|
+
return sideOnImpulse(tnt, distance4) * (2 + 4 / (1 + z * z));
|
|
78
|
+
}
|
|
79
|
+
function blastBodySpeed(tnt, distance4, mass, reach = 1, options = {}) {
|
|
80
|
+
const area = options.bodyArea ?? DEFAULT_BLAST_IMPULSE.bodyArea;
|
|
81
|
+
return bodyImpulse(tnt, distance4) * area * Math.max(0, reach) / Math.max(mass, 1);
|
|
82
|
+
}
|
|
65
83
|
var KNOCK_DOWN_SPEED = 2.5;
|
|
66
84
|
var LIE_SECONDS = 1.6;
|
|
85
|
+
var WOUNDED_LIE_SECONDS = 6;
|
|
86
|
+
var FRAGMENT_COVER = 0.5;
|
|
87
|
+
var STUN_SECONDS = 4;
|
|
67
88
|
var STAND_UP_PER_SPEED = 0.25;
|
|
68
89
|
var FALL_SECONDS = 0.25;
|
|
69
90
|
var RISE_SECONDS = 0.6;
|
|
@@ -72,11 +93,38 @@ var GameTestRoom = (() => {
|
|
|
72
93
|
var KNOCK_CHEST = 1.1;
|
|
73
94
|
var CHEST = KNOCK_CHEST;
|
|
74
95
|
var bodyMass = (height, build = 1) => 70 * (height / 1.75) ** 2 * build;
|
|
75
|
-
function knockOf(blast3, feet, mass, options) {
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
const
|
|
79
|
-
|
|
96
|
+
function knockOf(blast3, feet, mass, options, impulse = {}) {
|
|
97
|
+
const o = { ...DEFAULT_BLAST_IMPULSE, ...impulse };
|
|
98
|
+
const chest = [feet[0], feet[1] + CHEST, feet[2]];
|
|
99
|
+
const dx = chest[0] - blast3.point[0];
|
|
100
|
+
const dy = chest[1] - blast3.point[1];
|
|
101
|
+
const dz = chest[2] - blast3.point[2];
|
|
102
|
+
const distance4 = Math.hypot(dx, dy, dz);
|
|
103
|
+
if (!(blast3.radius > 0) || distance4 > blast3.radius) return void 0;
|
|
104
|
+
const reach = Math.max(0, Math.min(1, blast3.reach ?? 1));
|
|
105
|
+
const tnt = blast3.tnt ?? blast3.energy * o.tntPerJoule;
|
|
106
|
+
let speed = blastBodySpeed(tnt, distance4, mass, reach, o);
|
|
107
|
+
const minSpeed = impulse.minSpeed ?? options?.minSpeed ?? o.minSpeed;
|
|
108
|
+
if (speed < minSpeed) speed = 0;
|
|
109
|
+
const struck = reach >= FRAGMENT_COVER;
|
|
110
|
+
const wounded = struck && blast3.lethalRadius !== void 0 && distance4 <= blast3.lethalRadius;
|
|
111
|
+
const edge = 1 - distance4 / blast3.radius;
|
|
112
|
+
const stunSeconds = struck ? STUN_SECONDS * edge * edge * reach : 0;
|
|
113
|
+
if (speed === 0 && !wounded && stunSeconds < 0.25) return void 0;
|
|
114
|
+
const horizontal = Math.hypot(dx, dz);
|
|
115
|
+
const away = horizontal > 1e-4 ? [dx / horizontal, o.lift, dz / horizontal] : [0, 1, 0];
|
|
116
|
+
const length3 = Math.hypot(away[0], away[1], away[2]);
|
|
117
|
+
const velocity = [away[0] / length3 * speed, away[1] / length3 * speed, away[2] / length3 * speed];
|
|
118
|
+
return {
|
|
119
|
+
velocity,
|
|
120
|
+
airborne: velocity[1] > 0.5,
|
|
121
|
+
lying: 0,
|
|
122
|
+
lieLeft: wounded ? WOUNDED_LIE_SECONDS : 0,
|
|
123
|
+
away: horizontal > 1e-4 ? [dx / horizontal, 0, dz / horizontal] : [0, 0, 0],
|
|
124
|
+
down: speed >= KNOCK_DOWN_SPEED || wounded,
|
|
125
|
+
...wounded ? { wounded } : {},
|
|
126
|
+
...stunSeconds >= 0.25 ? { stunSeconds } : {}
|
|
127
|
+
};
|
|
80
128
|
}
|
|
81
129
|
function stepKnock(knock2, position, dt, groundAt, alive) {
|
|
82
130
|
const v = knock2.velocity;
|
|
@@ -100,14 +148,11 @@ var GameTestRoom = (() => {
|
|
|
100
148
|
}
|
|
101
149
|
const moving = horizontal > 0.05 || knock2.airborne;
|
|
102
150
|
if (knock2.down) {
|
|
103
|
-
if (moving) knock2.lying = Math.min(1, knock2.lying + dt / FALL_SECONDS);
|
|
104
|
-
else {
|
|
105
|
-
knock2.
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
knock2.lieLeft -= dt;
|
|
109
|
-
if (knock2.lieLeft <= 0) knock2.down = false;
|
|
110
|
-
}
|
|
151
|
+
if (moving || knock2.lying < 1) knock2.lying = Math.min(1, knock2.lying + dt / FALL_SECONDS);
|
|
152
|
+
else if (alive) {
|
|
153
|
+
knock2.lieLeft = knock2.lieLeft > 0 ? knock2.lieLeft : LIE_SECONDS + Math.hypot(v[0], v[2]) * STAND_UP_PER_SPEED;
|
|
154
|
+
knock2.lieLeft -= dt;
|
|
155
|
+
if (knock2.lieLeft <= 0) knock2.down = false;
|
|
111
156
|
}
|
|
112
157
|
} else if (knock2.lying > 0) knock2.lying = Math.max(0, knock2.lying - dt / RISE_SECONDS);
|
|
113
158
|
return !moving && !knock2.down && knock2.lying === 0;
|
|
@@ -5020,7 +5065,7 @@ var GameTestRoom = (() => {
|
|
|
5020
5065
|
return;
|
|
5021
5066
|
}
|
|
5022
5067
|
if (ex) {
|
|
5023
|
-
emit2({ ...base(o, src), type: "explode", part: p.spec.id, point: c, energy: ex.energy, radius: ex.radius, ...ex.lethalRadius !== void 0 ? { lethalRadius: ex.lethalRadius } : {}, ...ex.effect !== void 0 ? { effect: ex.effect } : {} });
|
|
5068
|
+
emit2({ ...base(o, src), type: "explode", part: p.spec.id, point: c, energy: ex.energy, radius: ex.radius, ...ex.lethalRadius !== void 0 ? { lethalRadius: ex.lethalRadius } : {}, ...ex.tnt !== void 0 ? { tnt: ex.tnt } : {}, ...ex.effect !== void 0 ? { effect: ex.effect } : {} });
|
|
5024
5069
|
blasts.push({ point: c, energy: ex.energy, radius: ex.radius, ...ex.lethalRadius !== void 0 ? { lethalRadius: ex.lethalRadius } : {}, source: src });
|
|
5025
5070
|
}
|
|
5026
5071
|
partLost(o, p, src);
|
|
@@ -6657,7 +6702,7 @@ var GameTestRoom = (() => {
|
|
|
6657
6702
|
};
|
|
6658
6703
|
var resolveStrings = (locale) => locales[locale ?? "en"] ?? locales.en;
|
|
6659
6704
|
|
|
6660
|
-
// ../game-audio/dist/chunk-
|
|
6705
|
+
// ../game-audio/dist/chunk-KBTUANNG.js
|
|
6661
6706
|
var DISTANCE_CURVES = {
|
|
6662
6707
|
/** The game's `sfx`: `vol / (1 + d² × 0.004)`, cutoff `/ (1 + d × 0.01)`, silent below 0.01 (jogo L62091–62092, L62101). */
|
|
6663
6708
|
game_sfx: { model: "inverse_square", k: 4e-3, cutoffK: 0.01, minGain: 0.01 },
|
|
@@ -8526,10 +8571,12 @@ var GameTestRoom = (() => {
|
|
|
8526
8571
|
noise: () => noiseBuffer(store, audio, mix.noise.seconds),
|
|
8527
8572
|
time
|
|
8528
8573
|
});
|
|
8574
|
+
const recipeBank = registry.bankOf(plan.id);
|
|
8529
8575
|
announce({
|
|
8530
8576
|
id: plan.id,
|
|
8531
8577
|
kind: "recipe",
|
|
8532
8578
|
...fallbackOf ? { fallbackOf } : {},
|
|
8579
|
+
...recipeBank ? { bank: recipeBank } : {},
|
|
8533
8580
|
requestedAt,
|
|
8534
8581
|
startAt: time,
|
|
8535
8582
|
outputLatency: latencyOf(audio),
|
|
@@ -8631,9 +8678,11 @@ var GameTestRoom = (() => {
|
|
|
8631
8678
|
const time = requestedAt + (playOptions.delay ?? 0);
|
|
8632
8679
|
const chokeList = sample.choke ? choked(sample.id) : void 0;
|
|
8633
8680
|
const realized = realizeSample(plan, { context: audio, output: sampleOutput(plan.bus), buffer: (url2) => sampleStore.buffer(url2), time });
|
|
8681
|
+
const sampleBank = registry.bankOf(plan.id);
|
|
8634
8682
|
announce({
|
|
8635
8683
|
id: plan.id,
|
|
8636
8684
|
kind: "sample",
|
|
8685
|
+
...sampleBank ? { bank: sampleBank } : {},
|
|
8637
8686
|
requestedAt,
|
|
8638
8687
|
startAt: time,
|
|
8639
8688
|
outputLatency: latencyOf(audio),
|
|
@@ -8954,7 +9003,11 @@ var GameTestRoom = (() => {
|
|
|
8954
9003
|
["casing_drop_terra_pistol", 1],
|
|
8955
9004
|
["casing_drop_terra_rifle", 1],
|
|
8956
9005
|
["casing_drop_terra_shell", 1],
|
|
8957
|
-
["rocket_fire", 2]
|
|
9006
|
+
["rocket_fire", 2],
|
|
9007
|
+
["smg_45_auto", 2, "sfx_pistol"],
|
|
9008
|
+
["weapon_draw", 2],
|
|
9009
|
+
["suppressor_attach", 3],
|
|
9010
|
+
["suppressor_detach", 3]
|
|
8958
9011
|
]),
|
|
8959
9012
|
...entries("explosoes-fogo", [
|
|
8960
9013
|
["explosion_grenade", 1, "boom"],
|
|
@@ -8968,7 +9021,11 @@ var GameTestRoom = (() => {
|
|
|
8968
9021
|
["fire_loop_large", 1],
|
|
8969
9022
|
["fire_extinguish", 2, "hiss"],
|
|
8970
9023
|
["gas_leak_hiss", 2],
|
|
8971
|
-
["structure_collapse", 2, "crumble"]
|
|
9024
|
+
["structure_collapse", 2, "crumble"],
|
|
9025
|
+
["grenade_bounce", 1],
|
|
9026
|
+
["c4_plant", 2],
|
|
9027
|
+
["c4_beep", 2],
|
|
9028
|
+
["c4_disarm", 2]
|
|
8972
9029
|
]),
|
|
8973
9030
|
...entries("personagem", [
|
|
8974
9031
|
["footstep_concrete_walk", 1, "sfx_step"],
|
|
@@ -8984,7 +9041,19 @@ var GameTestRoom = (() => {
|
|
|
8984
9041
|
["blunt_hit", 1],
|
|
8985
9042
|
["bite", 1, "sfx_flesh"],
|
|
8986
9043
|
["body_fall", 1],
|
|
8987
|
-
["player_hurt", 2]
|
|
9044
|
+
["player_hurt", 2],
|
|
9045
|
+
["footstep_tile_walk", 1, "sfx_step"],
|
|
9046
|
+
["footstep_water_walk", 1, "sfx_step"],
|
|
9047
|
+
["footstep_grate_walk", 2, "sfx_step"],
|
|
9048
|
+
["footstep_duct_walk", 3, "sfx_step"],
|
|
9049
|
+
["ladder_climb", 2],
|
|
9050
|
+
["swim", 2],
|
|
9051
|
+
["zombie_groan", 1],
|
|
9052
|
+
["zombie_alert", 1],
|
|
9053
|
+
["zombie_attack", 1],
|
|
9054
|
+
["zombie_pain", 1],
|
|
9055
|
+
["zombie_claw_hit", 1, "sfx_flesh"],
|
|
9056
|
+
["zombie_claw_miss", 2]
|
|
8988
9057
|
]),
|
|
8989
9058
|
...entries("veiculos", [
|
|
8990
9059
|
["engine_loop_car", 1],
|
|
@@ -9012,7 +9081,8 @@ var GameTestRoom = (() => {
|
|
|
9012
9081
|
["wind_loop", 2],
|
|
9013
9082
|
["thunder_near", 2],
|
|
9014
9083
|
["thunder_far", 2],
|
|
9015
|
-
["water_splash", 2]
|
|
9084
|
+
["water_splash", 2],
|
|
9085
|
+
["helicopter_loop", 3]
|
|
9016
9086
|
])
|
|
9017
9087
|
];
|
|
9018
9088
|
var SFX_MATERIALS = [
|
|
@@ -9094,6 +9164,175 @@ var GameTestRoom = (() => {
|
|
|
9094
9164
|
burst: 20,
|
|
9095
9165
|
burstSpacing: 0.06
|
|
9096
9166
|
};
|
|
9167
|
+
var SFX_TIERS = { light: 0, medium: 0.34, heavy: 0.67 };
|
|
9168
|
+
function splitTier(id) {
|
|
9169
|
+
const match = /^(.*)_(light|medium|heavy)$/.exec(id);
|
|
9170
|
+
return match ? { base: match[1], tier: match[2] } : { base: id };
|
|
9171
|
+
}
|
|
9172
|
+
var refsOf = (entries2, baseUrl) => (entries2 ?? []).map((entry) => ({ url: `${baseUrl}${entry.file}` }));
|
|
9173
|
+
function sampleBankFromManifest(manifest, options) {
|
|
9174
|
+
const baseUrl = options.baseUrl ?? "";
|
|
9175
|
+
const samples = [];
|
|
9176
|
+
const tiersOf = /* @__PURE__ */ new Map();
|
|
9177
|
+
for (const sound of manifest.sounds) {
|
|
9178
|
+
const { base, tier } = splitTier(sound.id);
|
|
9179
|
+
if (tier) tiersOf.set(base, [...tiersOf.get(base) ?? [], sound]);
|
|
9180
|
+
}
|
|
9181
|
+
const bases = /* @__PURE__ */ new Map();
|
|
9182
|
+
for (const sound of manifest.sounds) {
|
|
9183
|
+
if (!splitTier(sound.id).tier) bases.set(sound.id, sound);
|
|
9184
|
+
}
|
|
9185
|
+
for (const [base, tiers] of tiersOf) {
|
|
9186
|
+
if (!bases.has(base)) bases.set(base, { id: base, category: tiers[0]?.category ?? "", layers: { close: tiers[0]?.layers.close ?? [] } });
|
|
9187
|
+
}
|
|
9188
|
+
for (const sound of bases.values()) {
|
|
9189
|
+
const numbers = options.sounds?.[sound.id] ?? options.defaults?.(sound);
|
|
9190
|
+
const close = refsOf(sound.layers.close, baseUrl);
|
|
9191
|
+
if (!numbers || close.length === 0) continue;
|
|
9192
|
+
const tiers = (tiersOf.get(sound.id) ?? []).map((tier) => {
|
|
9193
|
+
const name = splitTier(tier.id).tier;
|
|
9194
|
+
const tierFar = refsOf(tier.layers.far, baseUrl);
|
|
9195
|
+
return { name, from: SFX_TIERS[name] ?? 0, close: refsOf(tier.layers.close, baseUrl), ...tierFar.length > 0 ? { far: tierFar } : {} };
|
|
9196
|
+
}).sort((a, b) => a.from - b.from);
|
|
9197
|
+
const far = refsOf(sound.layers.far, baseUrl);
|
|
9198
|
+
const indoor = refsOf(sound.layers.tail_in, baseUrl);
|
|
9199
|
+
const outdoor = refsOf(sound.layers.tail_out, baseUrl);
|
|
9200
|
+
const files = [sound, ...tiersOf.get(sound.id) ?? []].flatMap((entry) => Object.values(entry.layers).flatMap((entries2) => entries2 ?? []));
|
|
9201
|
+
samples.push({
|
|
9202
|
+
id: sound.id,
|
|
9203
|
+
bus: numbers.bus,
|
|
9204
|
+
close,
|
|
9205
|
+
...far.length > 0 ? { far } : {},
|
|
9206
|
+
...tiers.length > 0 ? { tiers } : {},
|
|
9207
|
+
...numbers.crossover ? { crossover: numbers.crossover } : {},
|
|
9208
|
+
...indoor.length > 0 || outdoor.length > 0 ? { tail: { ...indoor.length > 0 ? { indoor } : {}, ...outdoor.length > 0 ? { outdoor } : {}, ...numbers.tailGain === void 0 ? {} : { gain: numbers.tailGain } } } : {},
|
|
9209
|
+
...numbers.pitch === void 0 ? {} : { pitch: numbers.pitch },
|
|
9210
|
+
...numbers.gain === void 0 ? {} : { gain: numbers.gain },
|
|
9211
|
+
...numbers.falloff ? { falloff: numbers.falloff } : {},
|
|
9212
|
+
...numbers.cutoffK === void 0 ? {} : { cutoffK: numbers.cutoffK },
|
|
9213
|
+
...numbers.group ? { group: numbers.group } : {},
|
|
9214
|
+
...numbers.priority === void 0 ? {} : { priority: numbers.priority },
|
|
9215
|
+
...numbers.fallback ? { fallback: numbers.fallback } : {},
|
|
9216
|
+
sources: files.map((file) => `${file.file}: ${file.source} ${file.author} ${file.license}`)
|
|
9217
|
+
});
|
|
9218
|
+
}
|
|
9219
|
+
return { id: options.id, samples };
|
|
9220
|
+
}
|
|
9221
|
+
var KIT_CATEGORY_BUS = {
|
|
9222
|
+
armas: "weapons",
|
|
9223
|
+
impactos: "world",
|
|
9224
|
+
"explosoes-fogo": "world",
|
|
9225
|
+
personagem: "world",
|
|
9226
|
+
veiculos: "world",
|
|
9227
|
+
"itens-portas": "world",
|
|
9228
|
+
ambiente: "ambience"
|
|
9229
|
+
};
|
|
9230
|
+
var VOICE_IDS = /^(player_(hurt|death|effort|breath)|scream|zombie_)/;
|
|
9231
|
+
var KIT_SAMPLE_ALIASES = {
|
|
9232
|
+
// a house door: the latch giving, the hinge, the leaf meeting the frame, a locked one shaken; a drawer on its runners
|
|
9233
|
+
latch: "metal_latch",
|
|
9234
|
+
creak_wood: "door_creak",
|
|
9235
|
+
shut_wood: "door_wood_shut",
|
|
9236
|
+
rattle: "door_locked_rattle",
|
|
9237
|
+
// a drawer stays on its recipe: the recorded runs (1 to 1.9 s) outlast a drawer's pull
|
|
9238
|
+
// an item taken in the hand (game-destruction-three grab_* keys)
|
|
9239
|
+
grab_hard: "item_pickup_generic",
|
|
9240
|
+
grab_soft: "item_pickup_leather"
|
|
9241
|
+
};
|
|
9242
|
+
function kitSampleDefaults(sound) {
|
|
9243
|
+
const bus = VOICE_IDS.test(sound.id) ? "voices" : KIT_CATEGORY_BUS[sound.category];
|
|
9244
|
+
if (!bus) return void 0;
|
|
9245
|
+
return { bus, pitch: sound.category === "ambiente" || /_loop/.test(sound.id) ? 0 : 0.04 };
|
|
9246
|
+
}
|
|
9247
|
+
function withAliases(manifest, aliases) {
|
|
9248
|
+
const byId = new Map(manifest.sounds.map((sound) => [sound.id, sound]));
|
|
9249
|
+
const extra = [];
|
|
9250
|
+
for (const [alias, target] of Object.entries(aliases)) {
|
|
9251
|
+
const sound = byId.get(target);
|
|
9252
|
+
if (sound && !byId.has(alias)) extra.push({ ...sound, id: alias });
|
|
9253
|
+
}
|
|
9254
|
+
return { ...manifest, sounds: [...manifest.sounds, ...extra] };
|
|
9255
|
+
}
|
|
9256
|
+
function kitSampleBank(manifest, options = {}) {
|
|
9257
|
+
return sampleBankFromManifest(withAliases(manifest, options.aliases ?? KIT_SAMPLE_ALIASES), {
|
|
9258
|
+
id: options.id ?? "kit_samples",
|
|
9259
|
+
baseUrl: options.baseUrl ?? "",
|
|
9260
|
+
defaults: kitSampleDefaults
|
|
9261
|
+
});
|
|
9262
|
+
}
|
|
9263
|
+
var isFileUrl = (url2) => {
|
|
9264
|
+
const page = globalThis.location?.href;
|
|
9265
|
+
try {
|
|
9266
|
+
return new URL(url2, page).protocol === "file:";
|
|
9267
|
+
} catch {
|
|
9268
|
+
return false;
|
|
9269
|
+
}
|
|
9270
|
+
};
|
|
9271
|
+
var fetchJson = async (url2) => {
|
|
9272
|
+
if (isFileUrl(url2)) throw new Error(`${url2}: file:// is not fetched`);
|
|
9273
|
+
const response = await fetch(url2);
|
|
9274
|
+
if (!response.ok) throw new Error(`${url2}: ${response.status}`);
|
|
9275
|
+
return await response.json();
|
|
9276
|
+
};
|
|
9277
|
+
async function loadKitSamples(engine, options = {}) {
|
|
9278
|
+
const baseUrl = options.baseUrl ?? "";
|
|
9279
|
+
let manifest;
|
|
9280
|
+
try {
|
|
9281
|
+
manifest = await (options.fetchManifest ?? fetchJson)(`${baseUrl}manifest.json`);
|
|
9282
|
+
} catch {
|
|
9283
|
+
return null;
|
|
9284
|
+
}
|
|
9285
|
+
const bank = kitSampleBank(manifest, options);
|
|
9286
|
+
engine.register(bank);
|
|
9287
|
+
if (options.preload && engine.loadSamples) void engine.loadSamples(options.preload).catch(() => void 0);
|
|
9288
|
+
return bank;
|
|
9289
|
+
}
|
|
9290
|
+
var USER_SAMPLES_BANK = "user_samples";
|
|
9291
|
+
var USER_SOUND_PREFIX = "user:";
|
|
9292
|
+
function userSampleBank(manifest, options = {}) {
|
|
9293
|
+
const playing = [];
|
|
9294
|
+
const behindKit = [];
|
|
9295
|
+
const sounds = [];
|
|
9296
|
+
for (const picked of manifest.sounds) {
|
|
9297
|
+
const sound = { ...picked, id: splitTier(picked.id).base };
|
|
9298
|
+
sounds.push({ ...sound, id: `${USER_SOUND_PREFIX}${sound.id}` });
|
|
9299
|
+
if (sound.role === "fallback" && options.kitHas?.(sound.id)) {
|
|
9300
|
+
behindKit.push(sound.id);
|
|
9301
|
+
continue;
|
|
9302
|
+
}
|
|
9303
|
+
sounds.push(sound);
|
|
9304
|
+
playing.push(sound.id);
|
|
9305
|
+
}
|
|
9306
|
+
const bank = sampleBankFromManifest(
|
|
9307
|
+
{ sounds },
|
|
9308
|
+
{
|
|
9309
|
+
id: USER_SAMPLES_BANK,
|
|
9310
|
+
baseUrl: options.baseUrl ?? "",
|
|
9311
|
+
defaults: (sound) => kitSampleDefaults({ id: sound.id.replace(USER_SOUND_PREFIX, ""), category: sound.category })
|
|
9312
|
+
}
|
|
9313
|
+
);
|
|
9314
|
+
return { bank, playing, behindKit };
|
|
9315
|
+
}
|
|
9316
|
+
var fetchManifestJson = async (url2) => {
|
|
9317
|
+
const page = globalThis.location?.href;
|
|
9318
|
+
if (new URL(url2, page ?? "http://localhost/").protocol === "file:") throw new Error(`${url2}: file:// is not fetched`);
|
|
9319
|
+
const response = await fetch(url2);
|
|
9320
|
+
if (!response.ok) throw new Error(`${url2}: ${response.status}`);
|
|
9321
|
+
return await response.json();
|
|
9322
|
+
};
|
|
9323
|
+
async function loadUserSamples(engine, options = {}) {
|
|
9324
|
+
const baseUrl = options.baseUrl ?? "./sfx-local/";
|
|
9325
|
+
let manifest;
|
|
9326
|
+
try {
|
|
9327
|
+
manifest = await (options.fetchManifest ?? fetchManifestJson)(`${baseUrl}manifest.json`);
|
|
9328
|
+
} catch {
|
|
9329
|
+
return null;
|
|
9330
|
+
}
|
|
9331
|
+
const kitHas = options.kitHas ?? ((id) => Boolean(engine.registry?.sample(id)));
|
|
9332
|
+
const result2 = userSampleBank(manifest, { baseUrl, kitHas });
|
|
9333
|
+
engine.register(result2.bank);
|
|
9334
|
+
return result2;
|
|
9335
|
+
}
|
|
9097
9336
|
var PT = {
|
|
9098
9337
|
group: "Som",
|
|
9099
9338
|
name: "Painel de som (arquivos e C1\u2013C10)",
|
|
@@ -9101,6 +9340,7 @@ var GameTestRoom = (() => {
|
|
|
9101
9340
|
category: "1 \xB7 Categoria",
|
|
9102
9341
|
sound: "1 \xB7 Som",
|
|
9103
9342
|
play: "1 \xB7 \u25B6 Tocar",
|
|
9343
|
+
play_user: "1 \xB7 \u25B6 Tocar o seu",
|
|
9104
9344
|
material: "2 \xB7 Material",
|
|
9105
9345
|
blow: "2 \xB7 Golpe",
|
|
9106
9346
|
strike: "2 \xB7 \u25B6 Tocar golpe",
|
|
@@ -9122,6 +9362,7 @@ var GameTestRoom = (() => {
|
|
|
9122
9362
|
approve: "5 \xB7 Aprovo (C10)"
|
|
9123
9363
|
},
|
|
9124
9364
|
hints: {
|
|
9365
|
+
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.",
|
|
9125
9366
|
sound: "A = arquivo, S = sintetizado, F = faltando. O que tem arquivo toca o arquivo; o resto toca o som atual.",
|
|
9126
9367
|
strike: "Toca impact_<material>_<golpe>: o arquivo se existir, sen\xE3o o som atual daquele material.",
|
|
9127
9368
|
wall: "P\xF5e a parede de casa entre voc\xEA e a fonte: o som fica abafado (C4).",
|
|
@@ -9166,9 +9407,10 @@ var GameTestRoom = (() => {
|
|
|
9166
9407
|
strengths: { light: "leve", medium: "m\xE9dio", heavy: "forte" },
|
|
9167
9408
|
states: { file: "A", synth: "S", missing: "F" },
|
|
9168
9409
|
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" },
|
|
9169
|
-
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" },
|
|
9410
|
+
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" },
|
|
9170
9411
|
run: { idle: "parada", measuring: "medindo\u2026", done: "pronta", failed: "falhou", recording: "gravando\u2026", recorded: "grava\xE7\xE3o baixada" },
|
|
9171
9412
|
words: { none: "\u2014", hidden: "? (revele)", prefers: "prefere", approved: "aprovado pelo dono" },
|
|
9413
|
+
sources: { sdk: "SDK", user: "seu som", synth: "sintetizado" },
|
|
9172
9414
|
probe: "Fonte do som",
|
|
9173
9415
|
wall: "Parede (oclus\xE3o)",
|
|
9174
9416
|
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" }
|
|
@@ -9181,6 +9423,7 @@ var GameTestRoom = (() => {
|
|
|
9181
9423
|
category: "1 \xB7 Category",
|
|
9182
9424
|
sound: "1 \xB7 Sound",
|
|
9183
9425
|
play: "1 \xB7 \u25B6 Play",
|
|
9426
|
+
play_user: "1 \xB7 \u25B6 Play yours",
|
|
9184
9427
|
material: "2 \xB7 Material",
|
|
9185
9428
|
blow: "2 \xB7 Blow",
|
|
9186
9429
|
strike: "2 \xB7 \u25B6 Play blow",
|
|
@@ -9202,6 +9445,7 @@ var GameTestRoom = (() => {
|
|
|
9202
9445
|
approve: "5 \xB7 Approve (C10)"
|
|
9203
9446
|
},
|
|
9204
9447
|
hints: {
|
|
9448
|
+
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.",
|
|
9205
9449
|
sound: "A = file, S = synthesized, F = missing. A file plays the file; the rest plays the current sound.",
|
|
9206
9450
|
strike: "Plays impact_<material>_<blow>: the file if there is one, else the current sound of that material.",
|
|
9207
9451
|
wall: "Puts the house wall between you and the source: the sound is muffled (C4).",
|
|
@@ -9236,138 +9480,16 @@ var GameTestRoom = (() => {
|
|
|
9236
9480
|
environments: { indoor: "indoor", outdoor: "outdoor" },
|
|
9237
9481
|
strengths: { light: "light", medium: "medium", heavy: "heavy" },
|
|
9238
9482
|
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" },
|
|
9239
|
-
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" },
|
|
9483
|
+
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" },
|
|
9240
9484
|
run: { idle: "idle", measuring: "measuring\u2026", done: "done", failed: "failed", recording: "recording\u2026", recorded: "recording downloaded" },
|
|
9241
9485
|
words: { none: "\u2014", hidden: "? (reveal)", prefers: "prefers", approved: "approved by the owner" },
|
|
9486
|
+
sources: { sdk: "SDK", user: "your sound", synth: "synthesized" },
|
|
9242
9487
|
probe: "Sound source",
|
|
9243
9488
|
wall: "Wall (occlusion)",
|
|
9244
9489
|
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" }
|
|
9245
9490
|
};
|
|
9246
9491
|
|
|
9247
9492
|
// ../game-audio/dist/index.js
|
|
9248
|
-
var SFX_TIERS = { light: 0, medium: 0.34, heavy: 0.67 };
|
|
9249
|
-
function splitTier(id) {
|
|
9250
|
-
const match = /^(.*)_(light|medium|heavy)$/.exec(id);
|
|
9251
|
-
return match ? { base: match[1], tier: match[2] } : { base: id };
|
|
9252
|
-
}
|
|
9253
|
-
var refsOf = (entries2, baseUrl) => (entries2 ?? []).map((entry) => ({ url: `${baseUrl}${entry.file}` }));
|
|
9254
|
-
function sampleBankFromManifest(manifest, options) {
|
|
9255
|
-
const baseUrl = options.baseUrl ?? "";
|
|
9256
|
-
const samples = [];
|
|
9257
|
-
const tiersOf = /* @__PURE__ */ new Map();
|
|
9258
|
-
for (const sound of manifest.sounds) {
|
|
9259
|
-
const { base, tier } = splitTier(sound.id);
|
|
9260
|
-
if (tier) tiersOf.set(base, [...tiersOf.get(base) ?? [], sound]);
|
|
9261
|
-
}
|
|
9262
|
-
const bases = /* @__PURE__ */ new Map();
|
|
9263
|
-
for (const sound of manifest.sounds) {
|
|
9264
|
-
if (!splitTier(sound.id).tier) bases.set(sound.id, sound);
|
|
9265
|
-
}
|
|
9266
|
-
for (const [base, tiers] of tiersOf) {
|
|
9267
|
-
if (!bases.has(base)) bases.set(base, { id: base, category: tiers[0]?.category ?? "", layers: { close: tiers[0]?.layers.close ?? [] } });
|
|
9268
|
-
}
|
|
9269
|
-
for (const sound of bases.values()) {
|
|
9270
|
-
const numbers = options.sounds?.[sound.id] ?? options.defaults?.(sound);
|
|
9271
|
-
const close = refsOf(sound.layers.close, baseUrl);
|
|
9272
|
-
if (!numbers || close.length === 0) continue;
|
|
9273
|
-
const tiers = (tiersOf.get(sound.id) ?? []).map((tier) => {
|
|
9274
|
-
const name = splitTier(tier.id).tier;
|
|
9275
|
-
const tierFar = refsOf(tier.layers.far, baseUrl);
|
|
9276
|
-
return { name, from: SFX_TIERS[name] ?? 0, close: refsOf(tier.layers.close, baseUrl), ...tierFar.length > 0 ? { far: tierFar } : {} };
|
|
9277
|
-
}).sort((a, b) => a.from - b.from);
|
|
9278
|
-
const far = refsOf(sound.layers.far, baseUrl);
|
|
9279
|
-
const indoor = refsOf(sound.layers.tail_in, baseUrl);
|
|
9280
|
-
const outdoor = refsOf(sound.layers.tail_out, baseUrl);
|
|
9281
|
-
const files = [sound, ...tiersOf.get(sound.id) ?? []].flatMap((entry) => Object.values(entry.layers).flatMap((entries2) => entries2 ?? []));
|
|
9282
|
-
samples.push({
|
|
9283
|
-
id: sound.id,
|
|
9284
|
-
bus: numbers.bus,
|
|
9285
|
-
close,
|
|
9286
|
-
...far.length > 0 ? { far } : {},
|
|
9287
|
-
...tiers.length > 0 ? { tiers } : {},
|
|
9288
|
-
...numbers.crossover ? { crossover: numbers.crossover } : {},
|
|
9289
|
-
...indoor.length > 0 || outdoor.length > 0 ? { tail: { ...indoor.length > 0 ? { indoor } : {}, ...outdoor.length > 0 ? { outdoor } : {}, ...numbers.tailGain === void 0 ? {} : { gain: numbers.tailGain } } } : {},
|
|
9290
|
-
...numbers.pitch === void 0 ? {} : { pitch: numbers.pitch },
|
|
9291
|
-
...numbers.gain === void 0 ? {} : { gain: numbers.gain },
|
|
9292
|
-
...numbers.falloff ? { falloff: numbers.falloff } : {},
|
|
9293
|
-
...numbers.cutoffK === void 0 ? {} : { cutoffK: numbers.cutoffK },
|
|
9294
|
-
...numbers.group ? { group: numbers.group } : {},
|
|
9295
|
-
...numbers.priority === void 0 ? {} : { priority: numbers.priority },
|
|
9296
|
-
...numbers.fallback ? { fallback: numbers.fallback } : {},
|
|
9297
|
-
sources: files.map((file) => `${file.file}: ${file.source} ${file.author} ${file.license}`)
|
|
9298
|
-
});
|
|
9299
|
-
}
|
|
9300
|
-
return { id: options.id, samples };
|
|
9301
|
-
}
|
|
9302
|
-
var KIT_CATEGORY_BUS = {
|
|
9303
|
-
armas: "weapons",
|
|
9304
|
-
impactos: "world",
|
|
9305
|
-
"explosoes-fogo": "world",
|
|
9306
|
-
personagem: "world",
|
|
9307
|
-
veiculos: "world",
|
|
9308
|
-
"itens-portas": "world",
|
|
9309
|
-
ambiente: "ambience"
|
|
9310
|
-
};
|
|
9311
|
-
var VOICE_IDS = /^(player_(hurt|death|effort|breath)|scream|zombie_)/;
|
|
9312
|
-
var KIT_SAMPLE_ALIASES = {
|
|
9313
|
-
// a house door: the latch giving, the hinge, the leaf meeting the frame, a locked one shaken; a drawer on its runners
|
|
9314
|
-
latch: "metal_latch",
|
|
9315
|
-
creak_wood: "door_creak",
|
|
9316
|
-
shut_wood: "door_wood_shut",
|
|
9317
|
-
rattle: "door_locked_rattle",
|
|
9318
|
-
// a drawer stays on its recipe: the recorded runs (1 to 1.9 s) outlast a drawer's pull
|
|
9319
|
-
// an item taken in the hand (game-destruction-three grab_* keys)
|
|
9320
|
-
grab_hard: "item_pickup_generic",
|
|
9321
|
-
grab_soft: "item_pickup_leather"
|
|
9322
|
-
};
|
|
9323
|
-
function kitSampleDefaults(sound) {
|
|
9324
|
-
const bus = VOICE_IDS.test(sound.id) ? "voices" : KIT_CATEGORY_BUS[sound.category];
|
|
9325
|
-
if (!bus) return void 0;
|
|
9326
|
-
return { bus, pitch: sound.category === "ambiente" || /_loop/.test(sound.id) ? 0 : 0.04 };
|
|
9327
|
-
}
|
|
9328
|
-
function withAliases(manifest, aliases) {
|
|
9329
|
-
const byId = new Map(manifest.sounds.map((sound) => [sound.id, sound]));
|
|
9330
|
-
const extra = [];
|
|
9331
|
-
for (const [alias, target] of Object.entries(aliases)) {
|
|
9332
|
-
const sound = byId.get(target);
|
|
9333
|
-
if (sound && !byId.has(alias)) extra.push({ ...sound, id: alias });
|
|
9334
|
-
}
|
|
9335
|
-
return { ...manifest, sounds: [...manifest.sounds, ...extra] };
|
|
9336
|
-
}
|
|
9337
|
-
function kitSampleBank(manifest, options = {}) {
|
|
9338
|
-
return sampleBankFromManifest(withAliases(manifest, options.aliases ?? KIT_SAMPLE_ALIASES), {
|
|
9339
|
-
id: options.id ?? "kit_samples",
|
|
9340
|
-
baseUrl: options.baseUrl ?? "",
|
|
9341
|
-
defaults: kitSampleDefaults
|
|
9342
|
-
});
|
|
9343
|
-
}
|
|
9344
|
-
var isFileUrl = (url2) => {
|
|
9345
|
-
const page = globalThis.location?.href;
|
|
9346
|
-
try {
|
|
9347
|
-
return new URL(url2, page).protocol === "file:";
|
|
9348
|
-
} catch {
|
|
9349
|
-
return false;
|
|
9350
|
-
}
|
|
9351
|
-
};
|
|
9352
|
-
var fetchJson = async (url2) => {
|
|
9353
|
-
if (isFileUrl(url2)) throw new Error(`${url2}: file:// is not fetched`);
|
|
9354
|
-
const response = await fetch(url2);
|
|
9355
|
-
if (!response.ok) throw new Error(`${url2}: ${response.status}`);
|
|
9356
|
-
return await response.json();
|
|
9357
|
-
};
|
|
9358
|
-
async function loadKitSamples(engine, options = {}) {
|
|
9359
|
-
const baseUrl = options.baseUrl ?? "";
|
|
9360
|
-
let manifest;
|
|
9361
|
-
try {
|
|
9362
|
-
manifest = await (options.fetchManifest ?? fetchJson)(`${baseUrl}manifest.json`);
|
|
9363
|
-
} catch {
|
|
9364
|
-
return null;
|
|
9365
|
-
}
|
|
9366
|
-
const bank = kitSampleBank(manifest, options);
|
|
9367
|
-
engine.register(bank);
|
|
9368
|
-
if (options.preload && engine.loadSamples) void engine.loadSamples(options.preload).catch(() => void 0);
|
|
9369
|
-
return bank;
|
|
9370
|
-
}
|
|
9371
9493
|
var ATTACK = 2e-3;
|
|
9372
9494
|
function lengthOf(d, attack) {
|
|
9373
9495
|
if (typeof d === "number") return attack + d;
|
|
@@ -22848,7 +22970,6 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
22848
22970
|
var rendererCount = 0;
|
|
22849
22971
|
var COLLAPSE_CLOUD_KG = 1e3;
|
|
22850
22972
|
var CHIP_DECAL_EDGE = 0.05;
|
|
22851
|
-
var OPAQUE_CRACK = 0.1;
|
|
22852
22973
|
var WOOD_RIM = 1.5;
|
|
22853
22974
|
var IMPACT_TAGS = ["metal", "glass", "wood"];
|
|
22854
22975
|
var GLOW_FROM_C = 430;
|
|
@@ -23772,14 +23893,11 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
23772
23893
|
const pv = b?.parts.get(ev.part);
|
|
23773
23894
|
if (!b || !pv) return;
|
|
23774
23895
|
const def = this.world.materials.get(pv.material);
|
|
23775
|
-
|
|
23776
|
-
|
|
23777
|
-
|
|
23778
|
-
const
|
|
23779
|
-
|
|
23780
|
-
const color = glass2 ? 15267071 : new this.THREE.Color(own).multiplyScalar(0.45).getHex();
|
|
23781
|
-
const length3 = glass2 ? ev.crack.length : Math.min(ev.crack.length, OPAQUE_CRACK);
|
|
23782
|
-
this.visuals.addCrack(mv, wp, this.worldDir(b, ev.crack.normal), ev.crack.rays, length3, color, hashNumbers(ev.time, ev.worldPoint[0], ev.worldPoint[1], ev.worldPoint[2]));
|
|
23896
|
+
if (def?.visual?.transparent) {
|
|
23897
|
+
const wp = new this.THREE.Vector3(ev.worldPoint[0], ev.worldPoint[1], ev.worldPoint[2]);
|
|
23898
|
+
const mv = this.nearestMesh(pv, wp);
|
|
23899
|
+
const seed = hashNumbers(ev.time, ev.worldPoint[0], ev.worldPoint[1], ev.worldPoint[2]);
|
|
23900
|
+
if (mv) this.visuals.addCrack(mv, wp, this.worldDir(b, ev.crack.normal), ev.crack.rays, ev.crack.length, 15267071, seed);
|
|
23783
23901
|
}
|
|
23784
23902
|
this.impactSound(pv.material, ev.worldPoint, 0.5, ev.blow);
|
|
23785
23903
|
}
|
|
@@ -28757,6 +28875,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
28757
28875
|
lethalRadius: 5,
|
|
28758
28876
|
injuryRadius: 15,
|
|
28759
28877
|
energy: 2e5,
|
|
28878
|
+
tnt: 0.24,
|
|
28760
28879
|
destructionLevel: 2,
|
|
28761
28880
|
noise: 500,
|
|
28762
28881
|
fuse: 4,
|
|
@@ -28802,6 +28921,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
28802
28921
|
lethalRadius: 3,
|
|
28803
28922
|
injuryRadius: 10,
|
|
28804
28923
|
energy: 43200,
|
|
28924
|
+
tnt: 0.15,
|
|
28805
28925
|
destructionLevel: 2,
|
|
28806
28926
|
noise: 450,
|
|
28807
28927
|
fuse: 3,
|
|
@@ -28821,6 +28941,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
28821
28941
|
lethalRadius: 5,
|
|
28822
28942
|
injuryRadius: 14,
|
|
28823
28943
|
energy: 2e5,
|
|
28944
|
+
tnt: 1.5,
|
|
28824
28945
|
destructionLevel: 2,
|
|
28825
28946
|
noise: 550,
|
|
28826
28947
|
fire: {
|
|
@@ -28867,6 +28988,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
28867
28988
|
lethalRadius: 4,
|
|
28868
28989
|
injuryRadius: 12,
|
|
28869
28990
|
energy: 102400,
|
|
28991
|
+
tnt: 0.25,
|
|
28870
28992
|
destructionLevel: 3,
|
|
28871
28993
|
noise: 600,
|
|
28872
28994
|
fuseLength: 0.03,
|
|
@@ -28889,6 +29011,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
28889
29011
|
lethalRadius: 6,
|
|
28890
29012
|
injuryRadius: 18,
|
|
28891
29013
|
energy: 345600,
|
|
29014
|
+
tnt: 0.76,
|
|
28892
29015
|
destructionLevel: 3,
|
|
28893
29016
|
noise: 700,
|
|
28894
29017
|
triggers: [
|
|
@@ -28912,6 +29035,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
28912
29035
|
length: 50
|
|
28913
29036
|
},
|
|
28914
29037
|
energy: 102400,
|
|
29038
|
+
tnt: 0.9,
|
|
28915
29039
|
destructionLevel: 1,
|
|
28916
29040
|
noise: 500,
|
|
28917
29041
|
triggers: [
|
|
@@ -28935,6 +29059,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
28935
29059
|
lethalRadius: 0,
|
|
28936
29060
|
injuryRadius: 10,
|
|
28937
29061
|
energy: 0,
|
|
29062
|
+
tnt: 0.01,
|
|
28938
29063
|
destructionLevel: 0,
|
|
28939
29064
|
noise: 400,
|
|
28940
29065
|
fuseRange: [
|
|
@@ -28959,6 +29084,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
28959
29084
|
lethalRadius: 4,
|
|
28960
29085
|
injuryRadius: 12,
|
|
28961
29086
|
energy: 102400,
|
|
29087
|
+
tnt: 0.045,
|
|
28962
29088
|
destructionLevel: 2,
|
|
28963
29089
|
noise: 450,
|
|
28964
29090
|
triggers: [
|
|
@@ -28977,6 +29103,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
28977
29103
|
lethalRadius: 5,
|
|
28978
29104
|
injuryRadius: 15,
|
|
28979
29105
|
energy: 2e5,
|
|
29106
|
+
tnt: 0.45,
|
|
28980
29107
|
destructionLevel: 3,
|
|
28981
29108
|
noise: 700,
|
|
28982
29109
|
triggers: [
|
|
@@ -28995,6 +29122,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
28995
29122
|
lethalRadius: 5,
|
|
28996
29123
|
injuryRadius: 16,
|
|
28997
29124
|
energy: 2e5,
|
|
29125
|
+
tnt: 0.7,
|
|
28998
29126
|
destructionLevel: 3,
|
|
28999
29127
|
noise: 750,
|
|
29000
29128
|
triggers: [
|
|
@@ -29013,6 +29141,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
29013
29141
|
lethalRadius: 5,
|
|
29014
29142
|
injuryRadius: 16,
|
|
29015
29143
|
energy: 2e5,
|
|
29144
|
+
tnt: 0.45,
|
|
29016
29145
|
destructionLevel: 3,
|
|
29017
29146
|
noise: 750,
|
|
29018
29147
|
triggers: [
|
|
@@ -29031,6 +29160,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
29031
29160
|
lethalRadius: 5,
|
|
29032
29161
|
injuryRadius: 16,
|
|
29033
29162
|
energy: 2e5,
|
|
29163
|
+
tnt: 0.7,
|
|
29034
29164
|
destructionLevel: 3,
|
|
29035
29165
|
noise: 750,
|
|
29036
29166
|
triggers: [
|
|
@@ -29049,6 +29179,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
29049
29179
|
lethalRadius: 4,
|
|
29050
29180
|
injuryRadius: 12,
|
|
29051
29181
|
energy: 102400,
|
|
29182
|
+
tnt: 1,
|
|
29052
29183
|
destructionLevel: 2,
|
|
29053
29184
|
noise: 550,
|
|
29054
29185
|
fire: {
|
|
@@ -29082,6 +29213,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
29082
29213
|
lethalRadius: 5,
|
|
29083
29214
|
injuryRadius: 14,
|
|
29084
29215
|
energy: 2e5,
|
|
29216
|
+
tnt: 0.5,
|
|
29085
29217
|
destructionLevel: 2,
|
|
29086
29218
|
noise: 550,
|
|
29087
29219
|
fire: {
|
|
@@ -29119,6 +29251,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
29119
29251
|
lethalRadius: 4,
|
|
29120
29252
|
injuryRadius: 12,
|
|
29121
29253
|
energy: 102400,
|
|
29254
|
+
tnt: 0.5,
|
|
29122
29255
|
destructionLevel: 3,
|
|
29123
29256
|
noise: 700,
|
|
29124
29257
|
fire: {
|
|
@@ -29148,6 +29281,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
29148
29281
|
lethalRadius: 12,
|
|
29149
29282
|
injuryRadius: 30,
|
|
29150
29283
|
energy: 2764800,
|
|
29284
|
+
tnt: 20,
|
|
29151
29285
|
destructionLevel: 3,
|
|
29152
29286
|
noise: 700,
|
|
29153
29287
|
fire: {
|
|
@@ -29175,6 +29309,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
29175
29309
|
lethalRadius: 4,
|
|
29176
29310
|
injuryRadius: 12,
|
|
29177
29311
|
energy: 102400,
|
|
29312
|
+
tnt: 0.045,
|
|
29178
29313
|
destructionLevel: 2,
|
|
29179
29314
|
noise: 450,
|
|
29180
29315
|
triggers: [
|
|
@@ -37893,6 +38028,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
37893
38028
|
direction: this.facing,
|
|
37894
38029
|
at: at3,
|
|
37895
38030
|
energy: def.energy,
|
|
38031
|
+
...def.tnt !== void 0 ? { tnt: def.tnt } : {},
|
|
37896
38032
|
lethalRadius: def.lethalRadius,
|
|
37897
38033
|
injuryRadius: def.injuryRadius,
|
|
37898
38034
|
noise: def.noise,
|
|
@@ -45695,7 +45831,17 @@ void main(){
|
|
|
45695
45831
|
if (onPlayer.zone !== "none") {
|
|
45696
45832
|
action("blast_player", translate("act.blast_player", { weapon: weaponName, zone: translate(`blast.zone.${onPlayer.zone}`), distance: format(onPlayer.distance, 1), stun: format(onPlayer.stunSeconds, 1) }), { data: { ...onPlayer } });
|
|
45697
45833
|
}
|
|
45698
|
-
context.emitHost({
|
|
45834
|
+
context.emitHost({
|
|
45835
|
+
type: "explosion",
|
|
45836
|
+
source: projectile.weapon,
|
|
45837
|
+
point: detonation.point,
|
|
45838
|
+
energy: detonation.energy,
|
|
45839
|
+
radius: reach,
|
|
45840
|
+
cause: detonation.cause,
|
|
45841
|
+
explosive: detonation.explosive,
|
|
45842
|
+
lethalRadius: detonation.lethalRadius,
|
|
45843
|
+
...detonation.tnt !== void 0 ? { tnt: detonation.tnt } : {}
|
|
45844
|
+
});
|
|
45699
45845
|
if (detonation.fire) context.startFire(projectile.weapon, detonation.point, detonation.fire, detonation.cause === "impact");
|
|
45700
45846
|
};
|
|
45701
45847
|
const detonateBare = (projectile, isImpact) => {
|
|
@@ -47864,6 +48010,9 @@ void main(){
|
|
|
47864
48010
|
var LYING_PITCH = 1.05;
|
|
47865
48011
|
var LYING_ROLL = 0.35;
|
|
47866
48012
|
var LYING_PITCH_FACE_DOWN = -1.05;
|
|
48013
|
+
var STUN_PITCH = 0.05;
|
|
48014
|
+
var STUN_ROLL = 0.08;
|
|
48015
|
+
var STUN_FULL = 2;
|
|
47867
48016
|
function createPlayer(THREE, o) {
|
|
47868
48017
|
const cam = o.camera;
|
|
47869
48018
|
let yaw = 0;
|
|
@@ -47903,11 +48052,16 @@ void main(){
|
|
|
47903
48052
|
};
|
|
47904
48053
|
let knocked = null;
|
|
47905
48054
|
let knockedForward = false;
|
|
48055
|
+
let stunLeft = 0;
|
|
48056
|
+
let stunPhase = 0;
|
|
47906
48057
|
let rollSide = 1;
|
|
47907
48058
|
const apply = () => {
|
|
47908
48059
|
const lying = knocked?.lying ?? 0;
|
|
47909
48060
|
const fallen = lying * lying * (3 - 2 * lying);
|
|
47910
|
-
|
|
48061
|
+
const sway = Math.min(1, stunLeft / STUN_FULL);
|
|
48062
|
+
const swayPitch = STUN_PITCH * sway * Math.sin(stunPhase * 1.3);
|
|
48063
|
+
const swayRoll = STUN_ROLL * sway * Math.sin(stunPhase * 0.9 + 1);
|
|
48064
|
+
euler.set(pitch + ((knockedForward ? LYING_PITCH_FACE_DOWN : LYING_PITCH) - pitch) * fallen + swayPitch, yaw, LYING_ROLL * rollSide * fallen + swayRoll, "YXZ");
|
|
47911
48065
|
cam.quaternion.setFromEuler(euler);
|
|
47912
48066
|
const standing = eye - CROUCH_DROP * crouch - bend;
|
|
47913
48067
|
cam.position.set(px.x, floorLevel + y + standing + (LYING_EYE - standing) * fallen, px.z);
|
|
@@ -48181,11 +48335,15 @@ void main(){
|
|
|
48181
48335
|
knocked.velocity = [knocked.velocity[0] + next.velocity[0], knocked.velocity[1] + next.velocity[1], knocked.velocity[2] + next.velocity[2]];
|
|
48182
48336
|
knocked.airborne || (knocked.airborne = next.airborne);
|
|
48183
48337
|
knocked.down || (knocked.down = next.down);
|
|
48338
|
+
knocked.wounded || (knocked.wounded = next.wounded);
|
|
48339
|
+
knocked.lieLeft = Math.max(knocked.lieLeft, next.lieLeft);
|
|
48184
48340
|
} else knocked = { ...next, velocity: [...next.velocity] };
|
|
48341
|
+
stunLeft = Math.max(stunLeft, next.stunSeconds ?? 0);
|
|
48185
48342
|
if (next.down) {
|
|
48186
|
-
const
|
|
48343
|
+
const away = next.away && (next.away[0] !== 0 || next.away[2] !== 0) ? next.away : next.velocity;
|
|
48344
|
+
const right = Math.cos(yaw) * away[0] - Math.sin(yaw) * away[2];
|
|
48187
48345
|
rollSide = right >= 0 ? -1 : 1;
|
|
48188
|
-
knockedForward = -Math.sin(yaw) *
|
|
48346
|
+
knockedForward = -Math.sin(yaw) * away[0] - Math.cos(yaw) * away[2] > 0;
|
|
48189
48347
|
crouchLatched = false;
|
|
48190
48348
|
}
|
|
48191
48349
|
if (knocked.airborne) vy2 = Math.max(vy2, knocked.velocity[1]);
|
|
@@ -48196,7 +48354,14 @@ void main(){
|
|
|
48196
48354
|
get knockedForward() {
|
|
48197
48355
|
return knockedForward;
|
|
48198
48356
|
},
|
|
48357
|
+
get stunned() {
|
|
48358
|
+
return stunLeft;
|
|
48359
|
+
},
|
|
48199
48360
|
update(dt) {
|
|
48361
|
+
if (stunLeft > 0) {
|
|
48362
|
+
stunLeft = Math.max(0, stunLeft - dt);
|
|
48363
|
+
stunPhase += dt * 2.4;
|
|
48364
|
+
}
|
|
48200
48365
|
if (knocked) {
|
|
48201
48366
|
stepKnocked(dt);
|
|
48202
48367
|
return;
|
|
@@ -51345,6 +51510,9 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
51345
51510
|
"act.player_slammed": "The player was thrown into {what} at {speed} m/s",
|
|
51346
51511
|
"act.player_fell": "The player hit the floor at {speed} m/s",
|
|
51347
51512
|
"act.player_shoved": "The blast pushed the player at {speed} m/s ({reach}% got through the cover)",
|
|
51513
|
+
"act.player_wounded": "The blast felled the player where they stood, {distance} m from it: badly wounded, stunned for {stun} s ({reach}% got through the cover)",
|
|
51514
|
+
"act.player_thrown_wounded": "The blast threw the player at {speed} m/s, {distance} m from it: badly wounded, stunned for {stun} s ({reach}% got through the cover)",
|
|
51515
|
+
"act.player_stunned": "The blast stunned the player for {stun} s, {distance} m from it: dizzy, ears ringing",
|
|
51348
51516
|
"act.came_apart": "{name} came apart: what stayed is loose and falls",
|
|
51349
51517
|
"act.shoved": "{name} stands free: the shots moved it",
|
|
51350
51518
|
"act.impact": "{name} hit {where} at {speed} m/s: {energy} J of blunt damage",
|
|
@@ -51707,6 +51875,9 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
51707
51875
|
"act.player_slammed": "O jogador foi arremessado contra {what} a {speed} m/s",
|
|
51708
51876
|
"act.player_fell": "O jogador bateu no ch\xE3o a {speed} m/s",
|
|
51709
51877
|
"act.player_shoved": "A explos\xE3o empurrou o jogador a {speed} m/s ({reach}% passou pela cobertura)",
|
|
51878
|
+
"act.player_wounded": "A explos\xE3o derrubou o jogador onde estava, a {distance} m dela: ferido gravemente, atordoado por {stun} s ({reach}% passou pela cobertura)",
|
|
51879
|
+
"act.player_thrown_wounded": "A explos\xE3o arremessou o jogador a {speed} m/s, a {distance} m dela: ferido gravemente, atordoado por {stun} s ({reach}% passou pela cobertura)",
|
|
51880
|
+
"act.player_stunned": "A explos\xE3o atordoou o jogador por {stun} s, a {distance} m dela: tonto, com os ouvidos zumbindo",
|
|
51710
51881
|
"act.came_apart": "{name} se desmontou: o que ficou est\xE1 solto e cai",
|
|
51711
51882
|
"act.shoved": "{name} estava solto no ch\xE3o: os tiros o moveram",
|
|
51712
51883
|
"act.impact": "{name} bateu em {where} a {speed} m/s: {energy} J de dano de impacto",
|
|
@@ -53203,7 +53374,11 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
53203
53374
|
const audio = options.audio === false ? null : options.audio ?? createAudioEngine({ deferredStart: {} });
|
|
53204
53375
|
const destructionSound = audio ? createDestructionSound(audio) : null;
|
|
53205
53376
|
if (audio && options.samplesBaseUrl !== null) {
|
|
53206
|
-
void loadKitSamples(audio, { baseUrl: options.samplesBaseUrl ?? "./sfx/" }).then((bank) => {
|
|
53377
|
+
void loadKitSamples(audio, { baseUrl: options.samplesBaseUrl ?? "./sfx/" }).then(async (bank) => {
|
|
53378
|
+
if (options.userSamplesBaseUrl !== null) {
|
|
53379
|
+
const own = await loadUserSamples(audio, { baseUrl: options.userSamplesBaseUrl ?? "./sfx-local/" });
|
|
53380
|
+
if (own) log.add({ channel: "event", type: "user_sounds", text: `sons do dono: ${own.playing.length} tocando, ${own.behindKit.length} atr\xE1s do SDK`, data: { playing: own.playing, behindKit: own.behindKit } });
|
|
53381
|
+
}
|
|
53207
53382
|
if (!bank || typeof window === "undefined") return;
|
|
53208
53383
|
const preload = () => {
|
|
53209
53384
|
window.removeEventListener("keydown", preload, true);
|
|
@@ -53432,7 +53607,19 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
53432
53607
|
for (const ev of batch) {
|
|
53433
53608
|
if (ev.type === "leak") puncture(ev);
|
|
53434
53609
|
else if (ev.type === "ignite") igniteNear(ev.point, 0.9);
|
|
53435
|
-
else if (ev.type === "explode")
|
|
53610
|
+
else if (ev.type === "explode") {
|
|
53611
|
+
emitHost({
|
|
53612
|
+
type: "explosion",
|
|
53613
|
+
source: ev.object,
|
|
53614
|
+
point: ev.point,
|
|
53615
|
+
energy: ev.energy,
|
|
53616
|
+
radius: ev.radius,
|
|
53617
|
+
cause: "part",
|
|
53618
|
+
...ev.effect !== void 0 ? { explosive: ev.effect } : {},
|
|
53619
|
+
...ev.tnt !== void 0 ? { tnt: ev.tnt } : {},
|
|
53620
|
+
...ev.lethalRadius !== void 0 ? { lethalRadius: ev.lethalRadius } : {}
|
|
53621
|
+
});
|
|
53622
|
+
}
|
|
53436
53623
|
fire2("event", ev);
|
|
53437
53624
|
options.onEvent?.(ev);
|
|
53438
53625
|
}
|
|
@@ -54128,14 +54315,27 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
54128
54315
|
const knockPlayer = (event) => {
|
|
54129
54316
|
if (seating.seat) return;
|
|
54130
54317
|
const feet = [player.x, player.feet, player.z];
|
|
54131
|
-
const
|
|
54132
|
-
const
|
|
54318
|
+
const chest = [feet[0], feet[1] + KNOCK_CHEST, feet[2]];
|
|
54319
|
+
const reach = world.blastReach(event.point, chest, event.source ? { ignore: [event.source] } : {});
|
|
54320
|
+
const blast3 = {
|
|
54321
|
+
point: event.point,
|
|
54322
|
+
energy: event.energy,
|
|
54323
|
+
radius: event.radius,
|
|
54324
|
+
reach,
|
|
54325
|
+
...event.tnt !== void 0 ? { tnt: event.tnt } : {},
|
|
54326
|
+
...event.lethalRadius !== void 0 ? { lethalRadius: event.lethalRadius } : {}
|
|
54327
|
+
};
|
|
54328
|
+
const knock2 = knockOf(blast3, feet, playerMass, options.blastShove, options.blastImpulse);
|
|
54133
54329
|
if (!knock2) return;
|
|
54134
54330
|
player.knock(knock2);
|
|
54135
54331
|
const speed = Math.hypot(knock2.velocity[0], knock2.velocity[1], knock2.velocity[2]);
|
|
54136
|
-
|
|
54137
|
-
|
|
54138
|
-
}
|
|
54332
|
+
const distance4 = Math.hypot(chest[0] - event.point[0], chest[1] - event.point[1], chest[2] - event.point[2]);
|
|
54333
|
+
const data = { speed, reach, distance: distance4, down: knock2.down, wounded: Boolean(knock2.wounded), stunSeconds: knock2.stunSeconds ?? 0, source: event.source };
|
|
54334
|
+
const values = { speed: num(speed, 1), reach: num(reach * 100, 0), distance: num(distance4, 1), stun: num(knock2.stunSeconds ?? 0, 1) };
|
|
54335
|
+
if (knock2.wounded) action("player_wounded", t(speed >= KNOCK_DOWN_SPEED ? "act.player_thrown_wounded" : "act.player_wounded", values), { data });
|
|
54336
|
+
else if (knock2.down) action("player_knocked_down", t("act.knocked_down", values), { data });
|
|
54337
|
+
else if (speed > 0) action("player_shoved", t("act.player_shoved", values), { data });
|
|
54338
|
+
else action("player_stunned", t("act.player_stunned", values), { data });
|
|
54139
54339
|
};
|
|
54140
54340
|
const avatarState = { speed: 0, running: false, crouch: false, down: false, armed: false, pitch: 0 };
|
|
54141
54341
|
let feetPrev = null;
|