mirror of
https://github.com/yogstation13/Yogstation.git
synced 2025-02-26 09:04:50 +00:00
Ports Bees ambience, reverb & sound system (#19559)
* ambience part 1 * almost there * p3 * 420blazeit * jesus christ im sorry * virofix * hm * increase max time
This commit is contained in:
82
code/controllers/subsystem/ambience.dm
Normal file
82
code/controllers/subsystem/ambience.dm
Normal file
@@ -0,0 +1,82 @@
|
||||
/// The subsystem used to play ambience to users every now and then, makes them real excited.
|
||||
SUBSYSTEM_DEF(ambience)
|
||||
name = "Ambience"
|
||||
flags = SS_BACKGROUND|SS_NO_INIT
|
||||
priority = FIRE_PRIORITY_AMBIENCE
|
||||
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
|
||||
wait = 2
|
||||
///Assoc list of listening client - next ambience time
|
||||
var/list/ambience_listening_clients = list()
|
||||
var/list/currentrun = list()
|
||||
|
||||
/datum/controller/subsystem/ambience/fire(resumed)
|
||||
if(!resumed)
|
||||
currentrun = ambience_listening_clients.Copy()
|
||||
var/list/cached_clients = currentrun
|
||||
for(var/client/client_iterator as anything in cached_clients)
|
||||
if(isnull(client_iterator))
|
||||
continue
|
||||
|
||||
if(isnewplayer(client_iterator.mob))
|
||||
continue
|
||||
|
||||
process_ambience_client(client_iterator)
|
||||
|
||||
if(MC_TICK_CHECK)
|
||||
return
|
||||
|
||||
/datum/controller/subsystem/ambience/proc/process_ambience_client(client/to_process)
|
||||
var/mob/current_mob = to_process.mob
|
||||
var/area/current_area = get_area(current_mob)
|
||||
if(!current_area) //Something's gone horribly wrong
|
||||
stack_trace("[key_name(to_process)] has somehow ended up in nullspace. WTF did you do -xoxo ambience subsystem")
|
||||
ambience_listening_clients -= to_process
|
||||
return
|
||||
|
||||
if(current_area.ambient_buzz)
|
||||
play_buzz(current_mob, current_area)
|
||||
|
||||
if(ambience_listening_clients[to_process] > world.time)
|
||||
return //Not ready for the next sound
|
||||
|
||||
if(current_area.ambientsounds && length(current_area.ambientsounds))
|
||||
var/ambi_fx = pick(current_area.ambientsounds)
|
||||
|
||||
play_ambience_effects(current_mob, ambi_fx, current_area)
|
||||
|
||||
if(current_area.ambientmusic && length(current_area.ambientmusic))
|
||||
var/ambi_music = pick(current_area.ambientmusic)
|
||||
play_ambience_music(current_mob, ambi_music, current_area)
|
||||
|
||||
ambience_listening_clients[to_process] = world.time + rand(current_area.min_ambience_cooldown, current_area.max_ambience_cooldown)
|
||||
|
||||
/datum/controller/subsystem/ambience/proc/add_ambience_client(client/to_add)
|
||||
if(SSambience.ambience_listening_clients[to_add] > world.time)
|
||||
return // If already properly set we don't want to reset the timer.
|
||||
SSambience.ambience_listening_clients[to_add] = world.time + 10 SECONDS //Just wait 10 seconds before the next one aight mate? cheers.
|
||||
|
||||
/datum/controller/subsystem/ambience/proc/remove_ambience_client(client/to_remove)
|
||||
ambience_listening_clients -= to_remove
|
||||
currentrun -= to_remove
|
||||
|
||||
///Buzzing sound, the low ship drone that plays constantly, IC (requires the user to be able to hear)
|
||||
/datum/controller/subsystem/ambience/proc/play_buzz(mob/M, area/A)
|
||||
if (A.ambient_buzz && (M.client.prefs.toggles & SOUND_SHIP_AMBIENCE) && M.can_hear_ambience())
|
||||
if (!M.client.buzz_playing || (A.ambient_buzz != M.client.buzz_playing))
|
||||
SEND_SOUND(M, sound(A.ambient_buzz, repeat = 1, wait = 0, volume = A.ambient_buzz_vol, channel = CHANNEL_BUZZ))
|
||||
M.client.buzz_playing = A.ambient_buzz // It's done this way so I can tell when the user switches to an area that has a different buzz effect, so we can seamlessly swap over to that one
|
||||
return
|
||||
|
||||
if(M.client.buzz_playing) // If it's playing, and it shouldn't be, stop it
|
||||
M.stop_sound_channel(CHANNEL_BUZZ)
|
||||
M.client.buzz_playing = null
|
||||
|
||||
///Effect, random sounds that will play at random times, IC (requires the user to be able to hear)
|
||||
/datum/controller/subsystem/ambience/proc/play_ambience_effects(mob/M, _ambi_fx, area/A)
|
||||
if(M.can_hear_ambience() && !M.client?.channel_in_use(CHANNEL_AMBIENT_EFFECTS))
|
||||
SEND_SOUND(M, sound(_ambi_fx, repeat = 0, wait = 0, volume = 45, channel = CHANNEL_AMBIENT_EFFECTS))
|
||||
|
||||
///Play background music, the more OOC ambience, like eerie space music
|
||||
/datum/controller/subsystem/ambience/proc/play_ambience_music(mob/M, _ambi_music, area/A)
|
||||
if(!M.client?.channel_in_use(CHANNEL_AMBIENT_MUSIC))
|
||||
SEND_SOUND(M, sound(_ambi_music, repeat = 0, wait = 0, volume = 75, channel = CHANNEL_AMBIENT_MUSIC))
|
||||
127
code/controllers/subsystem/sound.dm
Normal file
127
code/controllers/subsystem/sound.dm
Normal file
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Sound subsystem:
|
||||
* Used for things that need constant updating (sound fading in / out)
|
||||
*/
|
||||
|
||||
SUBSYSTEM_DEF(sound_effects)
|
||||
name = "Sound"
|
||||
wait = 1
|
||||
priority = FIRE_PRIORITY_AMBIENCE
|
||||
flags = SS_NO_INIT
|
||||
//Note: Make sure you update this if you use sound fading pre-game
|
||||
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
|
||||
|
||||
var/list/acting_effects = list() //key = sound, value = datum
|
||||
var/list/currentrun = list()
|
||||
|
||||
/datum/controller/subsystem/sound_effects/fire(resumed = 0)
|
||||
if (!resumed)
|
||||
src.currentrun = acting_effects.Copy()
|
||||
|
||||
//cache for sanic speed (lists are references anyways)
|
||||
var/list/currentrun = src.currentrun
|
||||
|
||||
while(LAZYLEN(currentrun))
|
||||
var/datum/sound_effect/sound_effect = currentrun[currentrun[currentrun.len]]
|
||||
currentrun.len--
|
||||
|
||||
sound_effect.update_effect()
|
||||
|
||||
if(world.time > sound_effect.end_tick)
|
||||
sound_effect.end_effect()
|
||||
acting_effects -= sound_effect.effect_id
|
||||
|
||||
if (MC_TICK_CHECK)
|
||||
return
|
||||
|
||||
// ===== Sound effect procs =====
|
||||
|
||||
/proc/sound_fade(sound/S, start_volume = 100, end_volume = 0, time = 10, var/listeners)
|
||||
//Check basics
|
||||
if(!S)
|
||||
CRASH("sound_fade called without a sound file.")
|
||||
if(!listeners)
|
||||
return
|
||||
//Check in list format
|
||||
var/listeners_list = listeners
|
||||
if(!islist(listeners_list))
|
||||
listeners_list = list(listeners)
|
||||
//Create datum
|
||||
new /datum/sound_effect/fade(S, listeners_list, time, start_volume, end_volume)
|
||||
|
||||
// ===== Sound effect datum =====
|
||||
|
||||
/datum/sound_effect
|
||||
var/name = "null"
|
||||
var/sound/sound
|
||||
var/list/listeners
|
||||
var/start_tick
|
||||
var/end_tick
|
||||
var/effect_id
|
||||
|
||||
/datum/sound_effect/New(S, list/_listeners, time)
|
||||
. = ..()
|
||||
sound = S
|
||||
listeners = _listeners
|
||||
start_tick = world.time
|
||||
end_tick = world.time + time
|
||||
effect_id = generate_id()
|
||||
start_sound()
|
||||
|
||||
/datum/sound_effect/proc/generate_id()
|
||||
var/id = "[name][sound.file]"
|
||||
for(var/A in listeners)
|
||||
id = "[id][REF(A)]"
|
||||
return id
|
||||
|
||||
/datum/sound_effect/proc/send_sound()
|
||||
for(var/receiver in listeners)
|
||||
SEND_SOUND(receiver, sound)
|
||||
|
||||
/datum/sound_effect/proc/update_effect()
|
||||
return //Not implemented
|
||||
|
||||
/datum/sound_effect/proc/end_effect()
|
||||
return //Not implemented
|
||||
|
||||
// Send the sound to the person it's affecting and add it to the sound subsystem.
|
||||
// Should be overridden to account for if an effect is already playing for that sound.
|
||||
/datum/sound_effect/proc/start_sound()
|
||||
send_sound()
|
||||
SSsound_effects.acting_effects[effect_id] = src
|
||||
|
||||
//============== Fade =============
|
||||
|
||||
/datum/sound_effect/fade
|
||||
name = "fade"
|
||||
var/in_vol
|
||||
var/out_vol
|
||||
//Calculated
|
||||
var/current_vol
|
||||
|
||||
/datum/sound_effect/fade/New(S, list/_listeners, time, start_vol, end_vol)
|
||||
in_vol = start_vol
|
||||
out_vol = end_vol
|
||||
. = ..(S, _listeners, time)
|
||||
|
||||
/datum/sound_effect/fade/start_sound()
|
||||
//If the sound is already playing, make it fade from the current point
|
||||
if(SSsound_effects.acting_effects[effect_id])
|
||||
var/datum/sound_effect/fade/old_sound = SSsound_effects.acting_effects[effect_id]
|
||||
in_vol = old_sound.current_vol
|
||||
else
|
||||
send_sound()
|
||||
SSsound_effects.acting_effects[effect_id] = src
|
||||
|
||||
/datum/sound_effect/fade/update_effect()
|
||||
var/time_multiplier = clamp((world.time - start_tick) / (end_tick - start_tick), 0, 1)
|
||||
current_vol = (time_multiplier * out_vol) + ((1-time_multiplier) * in_vol)
|
||||
sound.status = SOUND_UPDATE
|
||||
sound.volume = current_vol
|
||||
|
||||
for(var/receiver in listeners)
|
||||
SEND_SOUND(receiver, sound)
|
||||
|
||||
/datum/sound_effect/fade/end_effect()
|
||||
if(!out_vol)
|
||||
sound.repeat = FALSE
|
||||
Reference in New Issue
Block a user