mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-08-30 08:29:57 +01:00
Updated the sound system (#18724)
* sdaf * sdaf * sdfa * sadf * sfda * gfd * reduce thrusters volume * sdafsadsdaf * sdfa * Reduced some sound ranges and made some/more not ignore walls for loops * health analyzers too * ivdrip adjustment * most tools now use play_tool_sound to have the sound played, reduced range for it
This commit is contained in:
@@ -1,136 +1,249 @@
|
||||
/*
|
||||
output_atoms (list of atoms) The destination(s) for the sounds
|
||||
|
||||
mid_sounds (list or soundfile) Since this can be either a list or a single soundfile you can have random sounds. May contain further lists but must contain a soundfile at the end.
|
||||
mid_length (num) The length to wait between playing mid_sounds
|
||||
|
||||
start_sound (soundfile) Played before starting the mid_sounds loop
|
||||
start_length (num) How long to wait before starting the main loop after playing start_sound
|
||||
|
||||
end_sound (soundfile) The sound played after the main loop has concluded
|
||||
|
||||
chance (num) Chance per loop to play a mid_sound
|
||||
volume (num) Sound output volume
|
||||
max_loops (num) The max amount of loops to run for.
|
||||
direct (bool) If true plays directly to provided atoms instead of from them
|
||||
*/
|
||||
|
||||
/**
|
||||
* A datum for sounds that need to loop, with a high amount of configurability.
|
||||
*/
|
||||
/datum/looping_sound
|
||||
|
||||
///A `/list` of `/atom`, destinations for the sound
|
||||
var/list/atom/output_atoms = list()
|
||||
|
||||
/**
|
||||
* A list with soundfiles, or a soundfile, to play for the intermediate steps
|
||||
*
|
||||
* Must contain at least one sound
|
||||
*/
|
||||
/// (list or soundfile) Since this can be either a list or a single soundfile you can have random sounds. May contain further lists but must contain a soundfile at the end.
|
||||
var/mid_sounds
|
||||
|
||||
///The length to wait between playing mid_sounds
|
||||
/// The length of time to wait between playing mid_sounds.
|
||||
var/mid_length
|
||||
|
||||
///Volume for the start sound
|
||||
/// Amount of time to add/take away from the mid length, randomly
|
||||
var/mid_length_vary = 0
|
||||
/// If we should always play each sound once per loop of all sounds. Weights here only really effect order, and could be disgarded
|
||||
var/each_once = FALSE
|
||||
/// Whether if the sounds should be played in order or not. Defaults to FALSE.
|
||||
var/in_order = FALSE
|
||||
/// Override for volume of start sound.
|
||||
var/start_volume
|
||||
|
||||
///A soundfile, played before starting the mid_sounds loop
|
||||
/// (soundfile) Played before starting the mid_sounds loop.
|
||||
var/start_sound
|
||||
|
||||
///How long to wait before starting the main loop after playing start_sound
|
||||
/// How long to wait before starting the main loop after playing start_sound.
|
||||
var/start_length
|
||||
|
||||
///Volume for the end sound
|
||||
/// Override for volume of end sound.
|
||||
var/end_volume
|
||||
|
||||
///A soundfile, the sound played after the main loop has concluded
|
||||
/// (soundfile) The sound played after the main loop has concluded.
|
||||
var/end_sound
|
||||
|
||||
///Chance per loop to play a mid_sound
|
||||
/// Chance per loop to play a mid_sound.
|
||||
var/chance
|
||||
|
||||
///Sound output volume
|
||||
/// Sound output volume.
|
||||
var/volume = 100
|
||||
|
||||
///Whether or not the sounds will vary in pitch when played
|
||||
/// Whether or not the sounds will vary in pitch when played.
|
||||
var/vary = FALSE
|
||||
|
||||
///The max amount of loops to run for
|
||||
/// The max amount of loops to run for.
|
||||
var/max_loops
|
||||
/// The extra range of the sound in tiles, defaults to 0.
|
||||
var/extra_range = 0
|
||||
/// How much the sound will be affected by falloff per tile.
|
||||
var/falloff_exponent
|
||||
/// The falloff distance of the sound,
|
||||
var/falloff_distance
|
||||
/// Are the sounds affected by pressure? Defaults to TRUE.
|
||||
var/pressure_affected = TRUE
|
||||
/// Are the sounds subject to reverb? Defaults to TRUE.
|
||||
var/use_reverb = TRUE
|
||||
/// Are we ignoring walls? Defaults to TRUE.
|
||||
var/ignore_walls = TRUE
|
||||
|
||||
// State stuff
|
||||
/// The source of the sound, or the recipient of the sound.
|
||||
var/atom/parent
|
||||
/// The ID of the timer that's used to loop the sounds.
|
||||
var/timer_id
|
||||
/// Has the looping started yet?
|
||||
var/loop_started = FALSE
|
||||
/// If we're using cut_mid, this is the list we cut from
|
||||
var/list/cut_list
|
||||
///The index of the current song we're playing in the mid_sounds list, only used if in_order is used
|
||||
///This is immediately set to 1, so we start the index at 0
|
||||
var/audio_index = 0
|
||||
|
||||
// Args
|
||||
/// Do we skip the starting sounds?
|
||||
var/skip_starting_sounds = FALSE
|
||||
/// If true, plays directly to provided atoms instead of from them.
|
||||
var/direct
|
||||
/// Sound channel to play on, random if not provided
|
||||
var/sound_channel
|
||||
|
||||
///The extra range of the sound in tiles, defaults to 0.
|
||||
var/extra_range
|
||||
var/falloff
|
||||
|
||||
///The ID of the timer that's used to loop the sounds.
|
||||
var/timerid
|
||||
|
||||
/datum/looping_sound/New(list/_output_atoms=list(), start_immediately=FALSE, _direct=FALSE)
|
||||
/datum/looping_sound/New(_parent, start_immediately = FALSE, _direct = FALSE, _skip_starting_sounds = FALSE)
|
||||
if(!mid_sounds)
|
||||
crash_with("A looping sound datum was created without sounds to play.")
|
||||
WARNING("A looping sound datum was created without sounds to play.")
|
||||
return
|
||||
|
||||
output_atoms |= _output_atoms
|
||||
set_parent(_parent)
|
||||
direct = _direct
|
||||
skip_starting_sounds = _skip_starting_sounds
|
||||
|
||||
if(start_immediately)
|
||||
start()
|
||||
|
||||
/datum/looping_sound/Destroy()
|
||||
stop()
|
||||
output_atoms = null
|
||||
stop(TRUE)
|
||||
return ..()
|
||||
|
||||
/datum/looping_sound/proc/start(atom/add_thing)
|
||||
if(add_thing)
|
||||
output_atoms |= add_thing
|
||||
if(timerid)
|
||||
/**
|
||||
* The proc to actually kickstart the whole sound sequence. This is what you should call to start the `looping_sound`.
|
||||
*
|
||||
* Arguments:
|
||||
* * on_behalf_of - The new object to set as a parent.
|
||||
*/
|
||||
/datum/looping_sound/proc/start(on_behalf_of)
|
||||
if(on_behalf_of)
|
||||
set_parent(on_behalf_of)
|
||||
if(timer_id)
|
||||
return
|
||||
on_start()
|
||||
|
||||
/datum/looping_sound/proc/stop(atom/remove_thing)
|
||||
if(remove_thing)
|
||||
output_atoms -= remove_thing
|
||||
if(!timerid)
|
||||
/**
|
||||
* The proc to call to stop the sound loop.
|
||||
*
|
||||
* Arguments:
|
||||
* * null_parent - Whether or not we should set the parent to null (useful when destroying the `looping_sound` itself). Defaults to FALSE.
|
||||
*/
|
||||
/datum/looping_sound/proc/stop(null_parent = FALSE)
|
||||
stop_current()
|
||||
if(null_parent)
|
||||
set_parent(null)
|
||||
if(!timer_id)
|
||||
return
|
||||
on_stop()
|
||||
deltimer(timerid)
|
||||
timerid = null
|
||||
deltimer(timer_id, SSsound_loops)
|
||||
timer_id = null
|
||||
loop_started = FALSE
|
||||
|
||||
/datum/looping_sound/proc/sound_loop(starttime)
|
||||
if(max_loops && (world.time >= starttime + mid_length * max_loops))
|
||||
/// The proc that handles starting the actual core sound loop.
|
||||
/datum/looping_sound/proc/start_sound_loop()
|
||||
loop_started = TRUE
|
||||
sound_loop()
|
||||
timer_id = addtimer(CALLBACK(src, PROC_REF(sound_loop), world.time), mid_length, TIMER_CLIENT_TIME | TIMER_STOPPABLE | TIMER_LOOP | TIMER_DELETE_ME, SSsound_loops)
|
||||
|
||||
/**
|
||||
* A simple proc handling the looping of the sound itself.
|
||||
*
|
||||
* Arguments:
|
||||
* * start_time - The time at which the `mid_sounds` started being played (so we know when to stop looping).
|
||||
*/
|
||||
/datum/looping_sound/proc/sound_loop(start_time)
|
||||
if(max_loops && world.time >= start_time + mid_length * max_loops)
|
||||
stop()
|
||||
return
|
||||
// If we have a timer, we're varying mid length, and this is happening while we're runnin mid_sounds
|
||||
if(timer_id && mid_length_vary && start_time)
|
||||
updatetimedelay(timer_id, mid_length + rand(-mid_length_vary, mid_length_vary), timer_subsystem = SSsound_loops)
|
||||
if(!chance || prob(chance))
|
||||
play(get_sound(starttime))
|
||||
if(!timerid)
|
||||
timerid = addtimer(CALLBACK(src, PROC_REF(sound_loop), world.time), mid_length, TIMER_STOPPABLE | TIMER_LOOP)
|
||||
play(get_sound())
|
||||
|
||||
/**
|
||||
* Applies a new mid length to the sound
|
||||
*/
|
||||
/datum/looping_sound/proc/set_mid_length(new_mid)
|
||||
mid_length = new_mid
|
||||
if(!timer_id)
|
||||
return
|
||||
updatetimedelay(timer_id, mid_length + rand(-mid_length_vary, mid_length_vary), timer_subsystem = SSsound_loops)
|
||||
|
||||
/**
|
||||
* The proc that handles actually playing the sound.
|
||||
*
|
||||
* Arguments:
|
||||
* * soundfile - The soundfile we want to play.
|
||||
* * volume_override - The volume we want to play the sound at, overriding the `volume` variable.
|
||||
*/
|
||||
/datum/looping_sound/proc/play(soundfile, volume_override)
|
||||
var/list/atoms_cache = output_atoms
|
||||
var/sound/S = sound(soundfile)
|
||||
// if(direct)
|
||||
// S.channel = open_sound_channel() someone could probably make this work but you could probably just delete this with no reprecussions.
|
||||
// S.volume = volume
|
||||
for(var/i in 1 to atoms_cache.len)
|
||||
var/atom/thing = atoms_cache[i]
|
||||
// if(direct)
|
||||
// SEND_SOUND(thing, S)
|
||||
// else
|
||||
playsound(thing, S, volume_override || volume, vary, extra_range, falloff, required_preferences = ASFX_AMBIENCE) // you can turn it off, i guess.
|
||||
var/sound/sound_to_play = sound(soundfile)
|
||||
if(direct)
|
||||
sound_to_play.channel = sound_channel || SSsounds.random_available_channel()
|
||||
sound_to_play.volume = volume_override || volume //Use volume as fallback if theres no override
|
||||
SEND_SOUND(parent, sound_to_play)
|
||||
else
|
||||
playsound(
|
||||
parent,
|
||||
sound_to_play,
|
||||
volume,
|
||||
vary,
|
||||
extra_range,
|
||||
falloff_exponent = falloff_exponent,
|
||||
pressure_affected = pressure_affected,
|
||||
ignore_walls = ignore_walls,
|
||||
falloff_distance = falloff_distance,
|
||||
use_reverb = use_reverb
|
||||
)
|
||||
|
||||
/datum/looping_sound/proc/get_sound(starttime, _mid_sounds)
|
||||
. = _mid_sounds || mid_sounds
|
||||
/// Returns the sound we should now be playing.
|
||||
/datum/looping_sound/proc/get_sound(_mid_sounds)
|
||||
var/list/play_from = _mid_sounds || mid_sounds
|
||||
if(!each_once)
|
||||
. = play_from
|
||||
while(!isfile(.) && !isnull(.))
|
||||
. = pick_weight(.)
|
||||
return .
|
||||
|
||||
if(in_order)
|
||||
. = play_from
|
||||
audio_index++
|
||||
if(audio_index > length(play_from))
|
||||
audio_index = 1
|
||||
return .[audio_index]
|
||||
|
||||
if(!length(cut_list))
|
||||
cut_list = shuffle(play_from.Copy())
|
||||
var/list/tree = list()
|
||||
. = cut_list
|
||||
while(!isfile(.) && !isnull(.))
|
||||
. = pickweight(.)
|
||||
// Tree is a list of lists containign files
|
||||
// If an entry in the tree goes to 0 length, we cut it from the list
|
||||
tree += list(.)
|
||||
. = pick_weight(.)
|
||||
|
||||
if(!isfile(.))
|
||||
return
|
||||
|
||||
// Remove the sound file
|
||||
tree[length(tree)] -= .
|
||||
|
||||
// Walk the tree bottom up, remove any lists that are empty
|
||||
// Don't do anything for the topmost list, cause we do not care
|
||||
for(var/i in length(tree) to 2 step -1)
|
||||
var/list/branch = tree[i]
|
||||
if(length(branch))
|
||||
break
|
||||
tree[i - 1] -= list(branch) // Remove the empty list
|
||||
return .
|
||||
|
||||
|
||||
|
||||
/// A proc that's there to handle delaying the main sounds if there's a start_sound, and simply starting the sound loop in general.
|
||||
/datum/looping_sound/proc/on_start()
|
||||
var/start_wait = 0
|
||||
if(start_sound)
|
||||
if(start_sound && !skip_starting_sounds)
|
||||
play(start_sound, start_volume)
|
||||
start_wait = start_length
|
||||
addtimer(CALLBACK(src, PROC_REF(sound_loop)), start_wait)
|
||||
timer_id = addtimer(CALLBACK(src, PROC_REF(start_sound_loop)), start_wait, TIMER_CLIENT_TIME | TIMER_DELETE_ME | TIMER_STOPPABLE, SSsound_loops)
|
||||
|
||||
/// Stops sound playing on current channel, if specified
|
||||
/datum/looping_sound/proc/stop_current()
|
||||
if(!sound_channel || !ismob(parent))
|
||||
return
|
||||
var/mob/mob_parent = parent
|
||||
mob_parent.stop_sound_channel(sound_channel)
|
||||
|
||||
/// Simple proc that's executed when the looping sound is stopped, so that the `end_sound` can be played, if there's one.
|
||||
/datum/looping_sound/proc/on_stop()
|
||||
if(end_sound)
|
||||
if(end_sound && loop_started)
|
||||
play(end_sound, end_volume)
|
||||
|
||||
/// A simple proc to change who our parent is set to, also handling registering and unregistering the QDELETING signals on the parent.
|
||||
/datum/looping_sound/proc/set_parent(new_parent)
|
||||
if(parent)
|
||||
UnregisterSignal(parent, COMSIG_QDELETING)
|
||||
parent = new_parent
|
||||
if(parent)
|
||||
RegisterSignal(parent, COMSIG_QDELETING, PROC_REF(handle_parent_del))
|
||||
|
||||
/// A simple proc that lets us know whether the sounds are currently active or not.
|
||||
/datum/looping_sound/proc/is_active()
|
||||
return !!timer_id
|
||||
|
||||
/// A simple proc to handle the deletion of the parent, so that it does not force it to hard-delete.
|
||||
/datum/looping_sound/proc/handle_parent_del(datum/source)
|
||||
SIGNAL_HANDLER
|
||||
set_parent(null)
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
mid_length = 10
|
||||
end_sound = 'sound/machines/shower/shower_end.ogg'
|
||||
volume = 20
|
||||
extra_range = SHORT_RANGE_SOUND_EXTRARANGE
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -12,8 +13,8 @@
|
||||
mid_sounds = list('sound/machines/sm/loops/calm.ogg' = 1)
|
||||
mid_length = 60
|
||||
volume = 40
|
||||
extra_range = 10
|
||||
falloff = 4
|
||||
ignore_walls = FALSE
|
||||
falloff_distance = 4
|
||||
vary = TRUE
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -32,6 +33,7 @@
|
||||
mid_sounds = list('sound/machines/grill/grillsizzle.ogg' = 1)
|
||||
mid_length = 18
|
||||
volume = 50
|
||||
extra_range = SHORT_RANGE_SOUND_EXTRARANGE
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -42,7 +44,8 @@
|
||||
mid_length = 13
|
||||
end_sound = 'sound/machines/oven/oven_loop_end.ogg'
|
||||
volume = 100
|
||||
falloff = 4
|
||||
falloff_distance = 4
|
||||
extra_range = SHORT_RANGE_SOUND_EXTRARANGE
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -53,6 +56,7 @@
|
||||
mid_length = 10
|
||||
end_sound = 'sound/machines/microwave/microwave-end.ogg'
|
||||
volume = 30
|
||||
extra_range = SHORT_RANGE_SOUND_EXTRARANGE
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -67,7 +71,8 @@
|
||||
'sound/machines/tcomms/tcomms_mid7.ogg' = 1
|
||||
)
|
||||
mid_length = 1.8 SECONDS
|
||||
extra_range = -4.5
|
||||
extra_range = SHORT_RANGE_SOUND_EXTRARANGE
|
||||
ignore_walls = FALSE
|
||||
volume = 10
|
||||
|
||||
// mid_length = 1.8 SECONDS
|
||||
@@ -87,7 +92,8 @@
|
||||
end_sound = 'sound/machines/computer/computer_end.ogg'
|
||||
end_volume = 10
|
||||
volume = 1
|
||||
extra_range = -5.5
|
||||
extra_range = SILENCED_SOUND_EXTRARANGE
|
||||
ignore_walls = FALSE
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -96,6 +102,7 @@
|
||||
mid_length = 1.8 SECONDS
|
||||
extra_range = 10
|
||||
volume = 70
|
||||
ignore_walls = FALSE
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -103,5 +110,6 @@
|
||||
mid_sounds = list('sound/machines/firealarm/FireAlarm1.ogg' = 1,'sound/machines/firealarm/FireAlarm2.ogg' = 1,'sound/machines/firealarm/FireAlarm3.ogg' = 1,'sound/machines/firealarm/FireAlarm4.ogg' = 1)
|
||||
mid_length = 2.4 SECONDS
|
||||
volume = 75
|
||||
ignore_walls = FALSE
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -250,7 +250,7 @@ GLOBAL_DATUM_INIT(sound_player, /singleton/sound_player, new)
|
||||
|
||||
/datum/sound_token/proc/PrivGetEnvironment(listener)
|
||||
var/area/A = get_area(listener)
|
||||
return A && PrivIsValidEnvironment(A.sound_env) ? A.sound_env : sound.environment
|
||||
return A && PrivIsValidEnvironment(A.sound_environment) ? A.sound_environment : sound.environment
|
||||
|
||||
/datum/sound_token/proc/PrivIsValidEnvironment(environment)
|
||||
if(islist(environment) && length(environment) != 23)
|
||||
|
||||
Reference in New Issue
Block a user