Apply item-specific spatial range to use sounds

This commit is contained in:
Jage9
2026-02-27 01:10:32 -05:00
parent 4ed52649f1
commit 47a7aa0a83
7 changed files with 15 additions and 6 deletions

View File

@@ -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.25 R269";
window.CHGRID_WEB_VERSION = "2026.02.25 R270";
// Optional display timezone for timestamps. Falls back to America/Detroit if unset/invalid.
window.CHGRID_TIME_ZONE = "America/Detroit";

View File

@@ -35,6 +35,7 @@ const ONE_SHOT_ATTACK_SECONDS = 0.02;
type ActiveSpatialSampleRuntime = {
sourceX: number;
sourceY: number;
range: number;
baseGain: number;
gainNode: GainNode;
pannerNode: StereoPannerNode | null;
@@ -361,6 +362,7 @@ export class AudioEngine {
sourcePosition: { x: number; y: number },
playerPosition: { x: number; y: number },
gain = 1,
range = HEARING_RADIUS,
): Promise<void> {
await this.ensureContext();
const { audioCtx, sfxGainNode } = this;
@@ -383,6 +385,7 @@ export class AudioEngine {
const runtime: ActiveSpatialSampleRuntime = {
sourceX: sourcePosition.x,
sourceY: sourcePosition.y,
range: Math.max(1, range),
baseGain: gain,
gainNode,
pannerNode,
@@ -412,6 +415,7 @@ export class AudioEngine {
sourcePosition: { x: number; y: number },
playerPosition: { x: number; y: number },
gain = 1,
range = HEARING_RADIUS,
): Promise<void> {
await this.ensureContext();
const { audioCtx, sfxGainNode } = this;
@@ -434,6 +438,7 @@ export class AudioEngine {
const runtime: ActiveSpatialSampleRuntime = {
sourceX: sourcePosition.x,
sourceY: sourcePosition.y,
range: Math.max(1, range),
baseGain: gain,
gainNode,
pannerNode,
@@ -619,7 +624,7 @@ export class AudioEngine {
const mix = resolveSpatialMix({
dx: sample.sourceX - playerPosition.x,
dy: sample.sourceY - playerPosition.y,
range: HEARING_RADIUS,
range: sample.range,
baseGain: sample.baseGain,
});
const gainValue = mix?.gain ?? 0;

View File

@@ -1657,8 +1657,8 @@ const onAppMessage = createOnMessageHandler({
shouldAnnounceItemPropertyEcho: () => Date.now() >= suppressItemPropertyEchoUntilMs,
playLocateToneAt: (x, y) => audio.sfxLocate({ x: x - state.player.x, y: y - state.player.y }),
resolveIncomingSoundUrl,
playIncomingItemUseSound: (url, x, y) => {
void audio.playSpatialSample(url, { x, y }, { x: state.player.x, y: state.player.y }, 1);
playIncomingItemUseSound: (url, x, y, range) => {
void audio.playSpatialSample(url, { x, y }, { x: state.player.x, y: state.player.y }, 1, range ?? HEARING_RADIUS);
},
playClockAnnouncement: (sounds, x, y) => {
void clockAnnouncer.playSequence(sounds.map(resolveIncomingSoundUrl), x, y);

View File

@@ -68,7 +68,7 @@ type MessageHandlerDeps = {
shouldAnnounceItemPropertyEcho: () => boolean;
playLocateToneAt: (x: number, y: number) => void;
resolveIncomingSoundUrl: (url: string) => string;
playIncomingItemUseSound: (url: string, x: number, y: number) => void;
playIncomingItemUseSound: (url: string, x: number, y: number, range?: number) => void;
playClockAnnouncement: (sounds: string[], x: number, y: number) => void;
handleAuthRequired: (message: Extract<IncomingMessage, { type: 'auth_required' }>) => void;
handleAuthResult: (message: Extract<IncomingMessage, { type: 'auth_result' }>) => Promise<void>;
@@ -297,7 +297,7 @@ export function createOnMessageHandler(deps: MessageHandlerDeps): (message: Inco
const soundUrl = deps.resolveIncomingSoundUrl(message.sound);
if (!soundUrl) break;
if (deps.getAudioLayers().world) {
deps.playIncomingItemUseSound(soundUrl, message.x, message.y);
deps.playIncomingItemUseSound(soundUrl, message.x, message.y, message.range);
}
break;
}

View File

@@ -213,6 +213,7 @@ export const itemUseSoundSchema = z.object({
sound: z.string(),
x: z.number().int(),
y: z.number().int(),
range: z.number().int().positive().optional(),
});
export const itemClockAnnounceSchema = z.object({