diff --git a/code/controllers/subsystems/explosives.dm b/code/controllers/subsystems/explosives.dm index c11cfae6aaf..3c81d0275eb 100644 --- a/code/controllers/subsystems/explosives.dm +++ b/code/controllers/subsystems/explosives.dm @@ -108,7 +108,6 @@ var/datum/controller/subsystem/explosives/SSexplosives // 3/7/14 will calculate to 80 + 35 var/volume = 10 + (power * 20) - var/frequency = get_rand_frequency() var/closedist = round(max_range + world.view - 2, 1) //Whether or not this explosion causes enough vibration to send sound or shockwaves through the station @@ -150,11 +149,11 @@ var/datum/controller/subsystem/explosives/SSexplosives if (reception == 2 && (M.ear_deaf <= 0 || !M.ear_deaf))//Dont play sounds to deaf people // If inside the blast radius + world.view - 2 if(dist <= closedist) - M.playsound_local(epicenter, get_sfx("explosion"), min(100, volume), 1, frequency, falloff = 5) // get_sfx() is so that everyone gets the same sound + M.playsound_simple(epicenter, get_sfx("explosion"), min(100, volume), use_random_freq = TRUE, falloff = 5) //You hear a far explosion if you're outside the blast radius. Small bombs shouldn't be heard all over the station. else - volume = M.playsound_local(epicenter, 'sound/effects/explosionfar.ogg', volume, 1, frequency, usepressure = 0, falloff = 1000) + volume = M.playsound_simple(epicenter, 'sound/effects/explosionfar.ogg', volume, use_random_freq = TRUE, falloff = 1000, use_pressure = FALSE) //Playsound local will return the final volume the sound is actually played at //It will return 0 if the sound volume falls to 0 due to falloff or pressure //Also return zero if sound playing failed for some other reason @@ -312,7 +311,6 @@ var/datum/controller/subsystem/explosives/SSexplosives var/volume = 10 + (power * 20) - var/frequency = get_rand_frequency() var/close_dist = round(power + world.view - 2, 1) var/sound/explosion_sound = sound(get_sfx("explosion")) @@ -345,10 +343,10 @@ var/datum/controller/subsystem/explosives/SSexplosives var/dist = get_dist(M, epicenter) || 1 if ((reception & EXPLFX_SOUND) && M.ear_deaf <= 0) if (dist <= close_dist) - M.playsound_local(epicenter, explosion_sound, min(100, volume), 1, frequency, falloff = 5) + M.playsound_simple(epicenter, explosion_sound, min(100, volume), use_random_freq = TRUE, falloff = 5) //You hear a far explosion if you're outside the blast radius. Small bombs shouldn't be heard all over the station. else - volume = M.playsound_local(epicenter, 'sound/effects/explosionfar.ogg', volume, 1, frequency, usepressure = 0, falloff = 1000) + volume = M.playsound_simple(epicenter, 'sound/effects/explosionfar.ogg', volume, use_random_freq = TRUE, falloff = 1000, use_pressure = FALSE) if ((reception & EXPLFX_SHAKE) && volume > 0) shake_camera(M, min(30, max(2,(power*2) / dist)), min(3.5, ((power/3) / dist)),0.05) diff --git a/code/game/gamemodes/meteor/meteors.dm b/code/game/gamemodes/meteor/meteors.dm index b7db908383d..38fd6b93486 100644 --- a/code/game/gamemodes/meteor/meteors.dm +++ b/code/game/gamemodes/meteor/meteors.dm @@ -329,5 +329,5 @@ var/turf/mobloc = get_turf(M) if(mobloc && mobloc.z == T.z) if(M.ear_deaf <= 0 || !M.ear_deaf) - M.playsound_local(T, 'sound/effects/meteorimpact.ogg', range, 1, usepressure = 0) + M.playsound_simple(T, 'sound/effects/meteorimpact.ogg', range, use_random_freq = TRUE, use_pressure = FALSE) diff --git a/code/game/objects/structures/musician.dm b/code/game/objects/structures/musician.dm index ebe6428714a..d76c0ef76f7 100644 --- a/code/game/objects/structures/musician.dm +++ b/code/game/objects/structures/musician.dm @@ -209,8 +209,7 @@ //hearers(15, src) << sound(soundfile) var/turf/source = get_turf(src) for(var/mob/M in hearers(15, source)) - M.playsound_local(source, file(soundfile), 100, falloff = 5) - + M.playsound_simple(source, file(soundfile), 100, falloff = 5) /obj/structure/device/piano/proc/playsong() do diff --git a/code/game/sound.dm b/code/game/sound.dm index d11bf2307ed..ccdea05606a 100644 --- a/code/game/sound.dm +++ b/code/game/sound.dm @@ -168,77 +168,145 @@ var/list/footstepfx = list("defaultstep","concretestep","grassstep","dirtstep"," //var/list/gun_sound = list('sound/weapons/gunshot/gunshot1.ogg', 'sound/weapons/gunshot/gunshot2.ogg','sound/weapons/gunshot/gunshot3.ogg','sound/weapons/gunshot/gunshot4.ogg') -/proc/playsound(atom/source, soundin, vol as num, vary, extrarange as num, falloff, is_global, usepressure = 1, environment = -1, required_preferences = 0, required_asfx_toggles = 0) - if (istext(soundin)) - soundin = get_sfx(soundin) // same sound for everyone - else if (isarea(source)) - error("[source] is an area and is trying to make the sound: [soundin]") +/proc/playsound(atom/source, soundin, vol, vary, extrarange, falloff, is_global, usepressure = 1, environment = -1, required_preferences = 0, required_asfx_toggles = 0) + if (isarea(source)) + crash_with("[source] is an area and is trying to make the sound: [soundin]") return - var/frequency = get_rand_frequency() // Same frequency for everybody - var/turf/turf_source = get_turf(source) - // cache this so we don't create a new one for everybody + var/sound/original_sound = playsound_get_sound(soundin, vol, falloff, get_rand_frequency(), environment) + + if (!original_sound) + crash_with("Could not construct original sound.") + return + + if (is_global) + playsound_allinrange(source, original_sound, + extra_range = extrarange, + is_global = is_global, + use_random_freq = !!vary, + use_pressure = usepressure, + modify_environment = (environment != 0), + required_preferences = required_preferences, + required_asfx_toggles = required_asfx_toggles + ) + else + playsound_lineofsight(source, original_sound, + use_pressure = usepressure, + use_random_freq = !!vary, + modify_environment = (environment != 0), + required_preferences = required_preferences, + required_asfx_toggles = required_asfx_toggles + ) + +/proc/playsound_get_sound(soundin, volume, fall_off, frequency = 0, environment = -1) + if (istext(soundin)) + soundin = get_sfx(soundin) + var/sound/S = sound(soundin) - // Looping through the player list has the added bonus of working for mobs inside containers - for (var/P in player_list) - var/mob/M = P - if(!M || !M.client) - continue - var/distance = get_dist(M, turf_source) - if(distance <= (world.view + extrarange) * 3) - var/turf/T = get_turf(M) - - // These checks are split into multiple ifs for readability reasons. - - if (!T || T.z != turf_source.z) - continue - - if (required_preferences && (M.client.prefs.toggles & required_preferences) != required_preferences) - continue - - if (required_asfx_toggles && (M.client.prefs.asfx_togs & required_asfx_toggles) != required_asfx_toggles) - continue - - M.playsound_local(turf_source, soundin, vol, vary, frequency, falloff, is_global, usepressure, environment, S) - -/mob/proc/playsound_local(turf/turf_source, soundin, vol as num, vary, frequency, falloff, is_global, usepressure = 1, environment = -1, sound/S) - if(!client || ear_deaf > 0) - return 0 - - if (!S) - S = sound(get_sfx(soundin)) - - S.wait = 0 //No queue - S.channel = 0 //Any channel + S.wait = 0 + S.channel = 0 + S.frequency = frequency + S.falloff = fall_off || FALLOFF_SOUNDS S.environment = environment - if (vary) - if(frequency) - S.frequency = frequency - else - S.frequency = get_rand_frequency() + return S + +/proc/copy_sound(sound/original) + var/sound/S = sound(original.file, original.repeat, 0, 0, original.volume) + + S.wait = original.wait + S.channel = original.channel + S.frequency = original.frequency + S.falloff = original.falloff + S.environment = original.environment + + return S + +/proc/playsound_allinrange(atom/source, sound/S, extra_range = 0, is_global = FALSE, use_random_freq = FALSE, use_pressure = TRUE, modify_environment = TRUE, required_preferences = 0, required_asfx_toggles = 0) + var/turf/source_turf = get_turf(source) + + for (var/MM in player_list) + var/mob/M = MM + + if (!M?.client) + continue + + var/dist = get_dist(M, source_turf) + + if (dist <= (world.view + extra_range) * 3) + var/turf/T = get_turf(M) + + if (!T || T.z != source_turf.z) + continue + else if (!M.sound_can_play(required_preferences, required_asfx_toggles)) + continue + + M.playsound_to(source_turf, S, use_random_freq = use_random_freq, use_pressure = use_pressure, modify_environment = modify_environment) + +/proc/playsound_lineofsight(atom/source, sound/S, use_random_freq = FALSE, use_pressure = TRUE, modify_environment = TRUE, required_preferences = 0, required_asfx_toggles = 0) + var/list/mobs = get_mobs_or_objects_in_view(world.view, source, include_objects = FALSE) + + var/turf/source_turf = get_turf(source) + + for (var/MM in mobs) + var/mob/M = MM + if (!M.sound_can_play(required_preferences, required_asfx_toggles)) + continue + + M.playsound_to(source_turf, S, use_random_freq = use_random_freq, use_pressure = use_pressure, modify_environment = modify_environment) + +/mob/proc/sound_can_play(required_preferences = 0, required_asfx_toggles = 0) + if (!client) + return FALSE + + if (required_preferences && (client.prefs.toggles & required_preferences) != required_preferences) + return FALSE + + if (required_asfx_toggles && (client.prefs.asfx_togs & required_asfx_toggles) != required_asfx_toggles) + return FALSE + + return TRUE + +/mob/proc/playsound_get_environment(pressure_factor = 1.0) + if (pressure_factor < 0.5) + return SPACE + else + var/area/A = get_area(src) + return A.sound_env + +/mob/living/playsound_get_environment(pressure_factor = 1.0) + if (hallucination) + return PSYCHOTIC + else if (druggy) + return DRUGGED + else if (drowsyness) + return DIZZY + else if (confused) + return DIZZY + else if (sleeping) + return UNDERWATER + else + return ..() + +/mob/proc/playsound_to(turf/source_turf, sound/original_sound, use_random_freq, modify_environment = TRUE, use_pressure = TRUE) + var/sound/S = copy_sound(original_sound) - //sound volume falloff with pressure var/pressure_factor = 1.0 - if(isturf(turf_source)) - // 3D sounds, the technology is here! + if (use_random_freq) + S.frequency = get_rand_frequency() + + if (isturf(source_turf)) var/turf/T = get_turf(src) - //sound volume falloff with distance - var/distance = get_dist(T, turf_source) + var/distance = get_dist(T, source_turf) - vol -= max(distance - world.view, 0) * 2 //multiplicative falloff to add on top of natural audio falloff. - //Not sure if author understood what they were doing, but this is not multiplicative, its linear, and its implementation breaks longdistance sounds. - //This extra falloff should probably be rewritten or removed, but for now ive implemented a quick fix by only setting S.volume to vol after calculations are done - //This fix allows feeding in high volume values (>100) to make longrange sounds audible - // -Nanako - if (usepressure) - //sound volume falloff with pressure. Pass usepressure = 0 to disable these calculations + S.volume -= max(distance - world.view, 0) * 2 + if (use_pressure) var/datum/gas_mixture/hearer_env = T.return_air() - var/datum/gas_mixture/source_env = turf_source.return_air() + var/datum/gas_mixture/source_env = source_turf.return_air() if (hearer_env && source_env) var/pressure = min(hearer_env.return_pressure(), source_env.return_pressure()) @@ -251,48 +319,27 @@ var/list/footstepfx = list("defaultstep","concretestep","grassstep","dirtstep"," if (distance <= 1) pressure_factor = max(pressure_factor, 0.15) //hearing through contact - vol *= pressure_factor + S.volume *= pressure_factor - if (vol <= 0) - return 0//no volume means no sound + if (S.volume <= 0) + return 0 - S.volume = vol - var/dx = turf_source.x - T.x // Hearing from the right/left - S.x = dx - var/dz = turf_source.y - T.y // Hearing from infront/behind - S.z = dz - // 3D sound, truly this is the future. - S.y = (turf_source.z - T.z) * SOUND_Z_FACTOR - S.falloff = (falloff ? falloff : FALLOFF_SOUNDS) + S.x = source_turf.x - T.x // left/right + S.z = source_turf.y - T.y // front/back + S.y = (source_turf.z - T.z) * SOUND_Z_FACTOR // above/below-ish - if(!is_global && environment != 0) - if(istype(src,/mob/living/)) - var/mob/living/M = src - if (M.hallucination) - S.environment = PSYCHOTIC - else if (M.druggy) - S.environment = DRUGGED - else if (M.drowsyness) - S.environment = DIZZY - else if (M.confused) - S.environment = DIZZY - else if (M.sleeping) - S.environment = UNDERWATER - else if (pressure_factor < 0.5) - S.environment = SPACE - else - var/area/A = get_area(src) - S.environment = A.sound_env - - else if (pressure_factor < 0.5) - S.environment = SPACE - else - var/area/A = get_area(src) - S.environment = A.sound_env + if (modify_environment) + S.environment = playsound_get_environment(pressure_factor) sound_to(src, S) + return S.volume +/mob/proc/playsound_simple(source, soundin, volume, use_random_freq = FALSE, frequency = 0, falloff = 0, use_pressure = TRUE) + var/sound/S = playsound_get_sound(soundin, volume, falloff, frequency) + + playsound_to(source ? get_turf(source) : null, S, use_random_freq, use_pressure = use_pressure) + /client/proc/playtitlemusic() if(!SSticker.login_music) return if(prefs.toggles & SOUND_LOBBY) diff --git a/code/modules/mob/hear_say.dm b/code/modules/mob/hear_say.dm index cf386085b09..a9caf0cfef6 100644 --- a/code/modules/mob/hear_say.dm +++ b/code/modules/mob/hear_say.dm @@ -72,7 +72,7 @@ on_hear_say("[track][speaker_name][alt_name] [verb], \"[message]\"") if (speech_sound && (get_dist(speaker, src) <= world.view && src.z == speaker.z)) var/turf/source = speaker? get_turf(speaker) : get_turf(src) - src.playsound_local(source, speech_sound, sound_vol, 1) + playsound_simple(source, speech_sound, sound_vol, use_random_freq = TRUE) /mob/proc/on_hear_say(var/message) to_chat(src, message) diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index 377c1419fd8..1412efd483b 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -1321,8 +1321,8 @@ //0.1% chance of playing a scary sound to someone who's in complete darkness if(isturf(loc) && rand(1,1000) == 1) var/turf/T = loc - if(T.get_lumcount() < 0.01) // give a little bit of tolerance for near-dark areas. - playsound_local(src,pick(scarySounds),50, 1, -1) + if (T.get_lumcount() < 0.01) // give a little bit of tolerance for near-dark areas. + playsound_simple(null, pick(scarySounds), 50, TRUE) /mob/living/carbon/human/proc/handle_changeling() if(mind && mind.changeling) diff --git a/code/modules/power/gravitygenerator.dm b/code/modules/power/gravitygenerator.dm index 8a1fdc0ba1b..6927b7db3d8 100644 --- a/code/modules/power/gravitygenerator.dm +++ b/code/modules/power/gravitygenerator.dm @@ -425,7 +425,7 @@ if(M.client) if(!M) return shake_camera(M, 5, 1) - M.playsound_local(our_turf, 'sound/effects/alert.ogg', 100, 1, 0.5) + M.playsound_simple(our_turf, 'sound/effects/alert.ogg', 100, use_random_freq = TRUE, falloff = 0.5) /obj/machinery/gravity_generator/main/proc/update_list(var/gravity_changed = FALSE) var/turf/T = get_turf(src.loc) diff --git a/html/changelogs/skull132_sounds.yml b/html/changelogs/skull132_sounds.yml new file mode 100644 index 00000000000..fa56a661aa7 --- /dev/null +++ b/html/changelogs/skull132_sounds.yml @@ -0,0 +1,4 @@ +author: Skull132 +delete-after: True +changes: + - tweak: "Walls now block sound properly!"