From 391100a00eeb84852f7292155d8e8458c7966bb4 Mon Sep 17 00:00:00 2001 From: Jage9 Date: Sun, 22 Feb 2026 19:33:42 -0500 Subject: [PATCH] Add short fade-in ramp to local movement footsteps --- client/public/version.js | 2 +- client/src/audio/audioEngine.ts | 10 ++++++++-- client/src/main.ts | 2 +- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/client/public/version.js b/client/public/version.js index dc9b0bb..f90e5ae 100644 --- a/client/public/version.js +++ b/client/public/version.js @@ -1,5 +1,5 @@ // Maintainer-controlled web client version. // Format: YYYY.MM.DD Rn (example: 2026.02.20 R2) -window.CHGRID_WEB_VERSION = "2026.02.22 R173"; +window.CHGRID_WEB_VERSION = "2026.02.22 R174"; // Optional display timezone for timestamps. Falls back to America/Detroit if unset/invalid. window.CHGRID_TIME_ZONE = "America/Detroit"; diff --git a/client/src/audio/audioEngine.ts b/client/src/audio/audioEngine.ts index f2f62c9..c761a0a 100644 --- a/client/src/audio/audioEngine.ts +++ b/client/src/audio/audioEngine.ts @@ -369,7 +369,7 @@ export class AudioEngine { } } - async playSample(url: string, gain = 1): Promise { + async playSample(url: string, gain = 1, fadeInMs = 0): Promise { await this.ensureContext(); const { audioCtx, sfxGainNode } = this; if (!audioCtx || !sfxGainNode) return; @@ -380,7 +380,13 @@ export class AudioEngine { const source = audioCtx.createBufferSource(); source.buffer = buffer; const gainNode = audioCtx.createGain(); - gainNode.gain.value = gain; + const safeFadeMs = Number.isFinite(fadeInMs) ? Math.max(0, fadeInMs) : 0; + if (safeFadeMs > 0) { + gainNode.gain.setValueAtTime(0, audioCtx.currentTime); + gainNode.gain.linearRampToValueAtTime(gain, audioCtx.currentTime + safeFadeMs / 1000); + } else { + gainNode.gain.value = gain; + } source.connect(gainNode).connect(sfxGainNode); source.start(); } catch { diff --git a/client/src/main.ts b/client/src/main.ts index 6581b70..ffa4cfb 100644 --- a/client/src/main.ts +++ b/client/src/main.ts @@ -1136,7 +1136,7 @@ function handleMovement(): void { persistPlayerPosition(); state.player.lastMoveTime = now; void refreshAudioSubscriptions(true); - void audio.playSample(randomFootstepUrl(), FOOTSTEP_GAIN); + void audio.playSample(randomFootstepUrl(), FOOTSTEP_GAIN, 40); signaling.send({ type: 'update_position', x: nextX, y: nextY }); const namesOnTile = getPeerNamesAtPosition(nextX, nextY);