Skip to content

Commit

Permalink
Sound Environment update (#6620)
Browse files Browse the repository at this point in the history
# About the pull request

Changes to how a client's sound `environment`  and `echo` is handled:
https://www.byond.com/docs/ref/#/sound/var/environment
https://www.byond.com/docs/ref/#/sound/var/echo

A client's `soundOutput` now has sole control over environment and echo.
The environment is updated when the mob moves into a different area, or
if the mob's environment override is set.
The echo is used to enable or disable the environmental reverb
per-sound.

<!-- Remove this text and explain what the purpose of your PR is.

Mention if you have tested your changes. If you changed a map, make sure
you used the mapmerge tool.
If this is an Issue Correction, you can type "Fixes Issue #169420" to
link the PR to the corresponding Issue number #169420.

Remember: something that is self-evident to you might not be to others.
Explain your rationale fully, even if you feel it goes without saying.
-->

# Explain why it's good for the game

Issue: an environment applies to all sounds for that client, current and
future, until another one is set. It applies to in-world sounds as well
as, say, admin pings.

Solution: since an echo is applied per-sound, by adjusting the echo's
Room & RoomHF fields the environmental effects can be enabled or
disabled (more accurately, made so quiet as to be inaudible). This is
set to off by default, and is only enabled for positional sounds. Admin
pings are safe.

Idea from here: tgstation/tgstation#55333

# Testing Photographs and Procedure
Boots without issue. Sound environments change at appropriate points.
Sound environments effect only positional sounds.

# Changelog
:cl:
code: environmental reverb applies more reliably and only to positional
sounds
/:cl:
  • Loading branch information
Doubleumc authored Jul 6, 2024
1 parent 8490454 commit be57509
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 23 deletions.
3 changes: 3 additions & 0 deletions code/__DEFINES/sounds.dm
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@
#define SOUND_ENVIRONMENT_DIZZY 24
#define SOUND_ENVIRONMENT_PSYCHOTIC 25

#define SOUND_ECHO_REVERB_ON list(0, 0, 0, 0, 0, 0.0, 0, 0.25, 1.5, 1.0, 0, 1.0, 0, 0.0, 0.0, 0.0, 1.0, 0)
#define SOUND_ECHO_REVERB_OFF list(0, 0, -10000, -10000, 0, 0.0, 0, 0.25, 1.5, 1.0, 0, 1.0, 0, 0.0, 0.0, 0.0, 1.0, 0) //-10000 to Room & RoomHF makes enviromental reverb effectively inaudible

#define AMBIENCE_SHIP 'sound/ambience/shipambience.ogg'
#define AMBIENCE_JUNGLE 'sound/ambience/ambienceLV624.ogg'
#define AMBIENCE_RIVER 'sound/ambience/ambienceriver.ogg'
Expand Down
75 changes: 63 additions & 12 deletions code/datums/soundOutput.dm
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,25 @@
var/list/soundscape_playlist = list() //Updated on changing areas
var/ambience = null //The file currently being played as ambience
var/status_flags = 0 //For things like ear deafness, psychodelic effects, and other things that change how all sounds behave
var/list/echo
/datum/soundOutput/New(client/C)
if(!C)

/// Currently applied environmental reverb.
VAR_PROTECTED/owner_environment = SOUND_ENVIRONMENT_NONE

/datum/soundOutput/New(client/client)
if(!client)
qdel(src)
return
owner = C
. = ..()
owner = client
RegisterSignal(owner.mob, COMSIG_MOVABLE_MOVED, PROC_REF(on_mob_moved))
RegisterSignal(owner.mob, COMSIG_MOB_LOGOUT, PROC_REF(on_mob_logout))
RegisterSignal(owner, COMSIG_CLIENT_MOB_LOGGED_IN, PROC_REF(on_client_mob_logged_in))
return ..()

/datum/soundOutput/Destroy()
UnregisterSignal(owner.mob, list(COMSIG_MOVABLE_MOVED, COMSIG_MOB_LOGOUT))
UnregisterSignal(owner, COMSIG_CLIENT_MOB_LOGGED_IN)
owner = null
return ..()

/datum/soundOutput/proc/process_sound(datum/sound_template/T)
var/sound/S = sound(T.file, T.wait, T.repeat)
Expand All @@ -22,7 +34,6 @@
S.frequency = T.frequency
S.falloff = T.falloff
S.status = T.status
S.echo = T.echo
if(T.x && T.y && T.z)
var/turf/owner_turf = get_turf(owner.mob)
if(owner_turf)
Expand All @@ -38,16 +49,12 @@
S.x = T.x - owner_turf.x
S.y = 0
S.z = T.y - owner_turf.y
var/area/A = owner_turf.loc
S.environment = A.sound_environment
S.y += T.y_s_offset
S.x += T.x_s_offset
S.echo = SOUND_ECHO_REVERB_ON //enable environment reverb for positional sounds
if(owner.mob.ear_deaf > 0)
S.status |= SOUND_MUTE

if(owner.mob.sound_environment_override != SOUND_ENVIRONMENT_NONE)
S.environment = owner.mob.sound_environment_override

sound_to(owner,S)

/datum/soundOutput/proc/update_ambience(area/target_area, ambience_override, force_update = FALSE)
Expand Down Expand Up @@ -84,7 +91,6 @@
S.status = status_flags

if(target_area)
S.environment = target_area.sound_environment
var/muffle
if(target_area.ceiling_muffle)
switch(target_area.ceiling)
Expand Down Expand Up @@ -128,6 +134,51 @@
S.status = SOUND_UPDATE
sound_to(owner, S)

/// Pulls mob's area's sound_environment and applies if necessary and not overridden.
/datum/soundOutput/proc/update_area_environment()
var/area/owner_area = get_area(owner.mob)
var/new_environment = owner_area.sound_environment

if(owner.mob.sound_environment_override != SOUND_ENVIRONMENT_NONE) //override in effect, can't apply
return

set_owner_environment(new_environment)

/// Pulls mob's sound_environment_override and applies if necessary.
/datum/soundOutput/proc/update_mob_environment_override()
var/new_environment_override = owner.mob.sound_environment_override

if(new_environment_override == SOUND_ENVIRONMENT_NONE) //revert to area environment
update_area_environment()
return

set_owner_environment(new_environment_override)

/// Pushes new_environment to owner and updates owner_environment var.
/datum/soundOutput/proc/set_owner_environment(new_environment = SOUND_ENVIRONMENT_NONE)
if(new_environment ~= src.owner_environment) //no need to change
return

var/sound/sound = sound()
sound.environment = new_environment
sound_to(owner, sound)

src.owner_environment = new_environment

/datum/soundOutput/proc/on_mob_moved(datum/source, atom/oldloc, direction, Forced)
SIGNAL_HANDLER //COMSIG_MOVABLE_MOVED
update_area_environment()

/datum/soundOutput/proc/on_mob_logout(datum/source)
SIGNAL_HANDLER //COMSIG_MOB_LOGOUT
UnregisterSignal(owner.mob, list(COMSIG_MOVABLE_MOVED, COMSIG_MOB_LOGOUT))

/datum/soundOutput/proc/on_client_mob_logged_in(datum/source, mob/new_mob)
SIGNAL_HANDLER //COMSIG_CLIENT_MOB_LOGGED_IN
RegisterSignal(owner.mob, COMSIG_MOVABLE_MOVED, PROC_REF(on_mob_moved))
RegisterSignal(owner.mob, COMSIG_MOB_LOGOUT, PROC_REF(on_mob_logout))
update_mob_environment_override()

/client/proc/adjust_volume_prefs(volume_key, prompt = "", channel_update = 0)
volume_preferences[volume_key] = (tgui_input_number(src, prompt, "Volume", volume_preferences[volume_key]*100)) / 100
if(volume_preferences[volume_key] > 1)
Expand Down
12 changes: 5 additions & 7 deletions code/game/sound.dm
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
/sound
echo = SOUND_ECHO_REVERB_OFF //disable enviroment reverb by default, soundOutput re-enables for positional sounds

/datum/sound_template //Basically a sound datum, but only serves as a way to carry info to soundOutput
var/file //The sound itself
Expand All @@ -11,7 +13,6 @@
var/falloff = 1
var/volume_cat = VOLUME_SFX
var/range = 0
var/list/echo
var/x //Map coordinates, not sound coordinates
var/y
var/z
Expand All @@ -35,7 +36,7 @@
//status: the regular 4 sound flags
//falloff: max range till sound volume starts dropping as distance increases

/proc/playsound(atom/source, soundin, vol = 100, vary = FALSE, sound_range, vol_cat = VOLUME_SFX, channel = 0, status , falloff = 1, echo, y_s_offset,x_s_offset)
/proc/playsound(atom/source, soundin, vol = 100, vary = FALSE, sound_range, vol_cat = VOLUME_SFX, channel = 0, status , falloff = 1, y_s_offset,x_s_offset)
if(isarea(source))
error("[source] is an area and is trying to make the sound: [soundin]")
return FALSE
Expand All @@ -53,7 +54,6 @@
S.falloff = falloff
S.volume = vol
S.volume_cat = vol_cat
S.echo = echo
S.y_s_offset = y_s_offset
S.x_s_offset = x_s_offset
if(vary != FALSE)
Expand Down Expand Up @@ -100,7 +100,7 @@


//This is the replacement for playsound_local. Use this for sending sounds directly to a client
/proc/playsound_client(client/client, soundin, atom/origin, vol = 100, random_freq, vol_cat = VOLUME_SFX, channel = 0, status, list/echo, y_s_offset, x_s_offset)
/proc/playsound_client(client/client, soundin, atom/origin, vol = 100, random_freq, vol_cat = VOLUME_SFX, channel = 0, status, y_s_offset, x_s_offset)
if(!istype(client) || !client.soundOutput) return FALSE
var/datum/sound_template/S = new()
if(origin)
Expand All @@ -123,7 +123,6 @@
S.volume_cat = vol_cat
S.channel = channel
S.status = status
S.echo = echo
S.y_s_offset = y_s_offset
S.x_s_offset = x_s_offset
SSsound.queue(S, list(client))
Expand Down Expand Up @@ -154,13 +153,12 @@


/// Play sound for all on-map clients on a given Z-level. Good for ambient sounds.
/proc/playsound_z(z, soundin, volume = 100, vol_cat = VOLUME_SFX, echo, y_s_offset, x_s_offset)
/proc/playsound_z(z, soundin, volume = 100, vol_cat = VOLUME_SFX, y_s_offset, x_s_offset)
var/datum/sound_template/S = new()
S.file = soundin
S.volume = volume
S.channel = SOUND_CHANNEL_Z
S.volume_cat = vol_cat
S.echo = echo
S.y_s_offset = y_s_offset
S.x_s_offset = x_s_offset
var/list/hearers = list()
Expand Down
2 changes: 2 additions & 0 deletions code/modules/mob/living/init_signals.dm
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,15 @@
if(stat < UNCONSCIOUS)
set_stat(UNCONSCIOUS)
sound_environment_override = SOUND_ENVIRONMENT_PSYCHOTIC
client?.soundOutput?.update_mob_environment_override()

/// Called when [TRAIT_KNOCKEDOUT] is removed from the mob.
/mob/living/proc/on_knockedout_trait_loss(datum/source)
SIGNAL_HANDLER
if(stat <= UNCONSCIOUS)
update_stat()
sound_environment_override = SOUND_ENVIRONMENT_NONE
client?.soundOutput?.update_mob_environment_override()

/// Called when [TRAIT_IMMOBILIZED] is added to the mob.
/mob/living/proc/on_immobilized_trait_gain(datum/source)
Expand Down
4 changes: 0 additions & 4 deletions code/modules/mob/living/living.dm
Original file line number Diff line number Diff line change
Expand Up @@ -503,12 +503,10 @@
if(CONSCIOUS)
if(stat >= UNCONSCIOUS)
ADD_TRAIT(src, TRAIT_IMMOBILIZED, TRAIT_KNOCKEDOUT)
sound_environment_override = SOUND_ENVIRONMENT_PSYCHOTIC
add_traits(list(/*TRAIT_HANDS_BLOCKED, */ TRAIT_INCAPACITATED, TRAIT_FLOORED), STAT_TRAIT)
if(UNCONSCIOUS)
if(stat >= UNCONSCIOUS)
ADD_TRAIT(src, TRAIT_IMMOBILIZED, TRAIT_KNOCKEDOUT) //adding trait sources should come before removing to avoid unnecessary updates
sound_environment_override = SOUND_ENVIRONMENT_PSYCHOTIC
if(DEAD)
SEND_SIGNAL(src, COMSIG_MOB_STAT_SET_ALIVE)
// remove_from_dead_mob_list()
Expand All @@ -518,12 +516,10 @@
if(CONSCIOUS)
if(. >= UNCONSCIOUS)
REMOVE_TRAIT(src, TRAIT_IMMOBILIZED, TRAIT_KNOCKEDOUT)
sound_environment_override = SOUND_ENVIRONMENT_NONE
remove_traits(list(/*TRAIT_HANDS_BLOCKED, */ TRAIT_INCAPACITATED, TRAIT_FLOORED, /*TRAIT_CRITICAL_CONDITION*/), STAT_TRAIT)
if(UNCONSCIOUS)
if(. >= UNCONSCIOUS)
REMOVE_TRAIT(src, TRAIT_IMMOBILIZED, TRAIT_KNOCKEDOUT)
sound_environment_override = SOUND_ENVIRONMENT_NONE
if(DEAD)
SEND_SIGNAL(src, COMSIG_MOB_STAT_SET_DEAD)
// REMOVE_TRAIT(src, TRAIT_CRITICAL_CONDITION, STAT_TRAIT)
Expand Down

0 comments on commit be57509

Please sign in to comment.