diff --git a/code/__DEFINES/sound.dm b/code/__DEFINES/sound.dm index f2d78f3438..384b857978 100644 --- a/code/__DEFINES/sound.dm +++ b/code/__DEFINES/sound.dm @@ -3,21 +3,22 @@ #define CHANNEL_ADMIN 1023 #define CHANNEL_VOX 1022 #define CHANNEL_JUKEBOX 1021 -#define CHANNEL_JUSTICAR_ARK 1020 -#define CHANNEL_HEARTBEAT 1019 //sound channel for heartbeats -#define CHANNEL_AMBIENCE 1018 -#define CHANNEL_BUZZ 1017 -#define CHANNEL_BICYCLE 1016 +#define CHANNEL_JUKEBOX_START 1016 +#define CHANNEL_JUSTICAR_ARK 1015 +#define CHANNEL_HEARTBEAT 1014 //sound channel for heartbeats +#define CHANNEL_AMBIENCE 1013 +#define CHANNEL_BUZZ 1012 +#define CHANNEL_BICYCLE 1011 //CIT CHANNELS - TRY NOT TO REGRESS -#define CHANNEL_PRED 1015 -#define CHANNEL_DIGEST 1014 -#define CHANNEL_PREYLOOP 1013 +#define CHANNEL_PRED 1010 +#define CHANNEL_DIGEST 1009 +#define CHANNEL_PREYLOOP 1008 //THIS SHOULD ALWAYS BE THE LOWEST ONE! //KEEP IT UPDATED -#define CHANNEL_HIGHEST_AVAILABLE 1012 //CIT CHANGE - COMPENSATES FOR VORESOUND CHANNELS +#define CHANNEL_HIGHEST_AVAILABLE 1008 //CIT CHANGE - COMPENSATES FOR VORESOUND CHANNELS #define SOUND_MINIMUM_PRESSURE 10 diff --git a/code/controllers/subsystem/jukeboxes.dm b/code/controllers/subsystem/jukeboxes.dm new file mode 100644 index 0000000000..ab510e1efd --- /dev/null +++ b/code/controllers/subsystem/jukeboxes.dm @@ -0,0 +1,100 @@ +SUBSYSTEM_DEF(jukeboxes) + name = "Jukeboxes" + wait = 5 + var/list/songs = list() + var/list/activejukeboxes = list() + +/datum/track + var/song_name = "generic" + var/song_path = null + var/song_length = 0 + var/song_beat = 0 + var/song_associated_id = null + +/datum/track/New(name, path, length, beat, assocID) + song_name = name + song_path = path + song_length = length + song_beat = beat + song_associated_id = assocID + +/datum/controller/subsystem/jukeboxes/proc/addjukebox(obj/jukebox, datum/track/T) + if(!istype(T)) + CRASH("[src] tried to play a song with a nonexistant track") + var/channeltoreserve = CHANNEL_JUKEBOX_START + activejukeboxes.len - 1 + if(channeltoreserve > CHANNEL_JUKEBOX) + return FALSE + activejukeboxes.len++ + activejukeboxes[activejukeboxes.len] = list(T, channeltoreserve, jukebox) + return activejukeboxes.len + +/datum/controller/subsystem/jukeboxes/proc/removejukebox(IDtoremove) + if(islist(activejukeboxes[IDtoremove])) + for(var/mob/M in GLOB.player_list) + if(!M.client) + continue + M.stop_sound_channel(activejukeboxes[IDtoremove][2]) + activejukeboxes.Cut(IDtoremove, IDtoremove+1) + return TRUE + else + to_chat(world, "If you see this, screenshot it and send it to a dev. Tried to remove jukebox with invalid ID") + +/datum/controller/subsystem/jukeboxes/proc/findjukeboxindex(obj/jukebox) + if(activejukeboxes.len) + for(var/list/jukeinfo in activejukeboxes) + if(jukebox in jukeinfo) + return activejukeboxes.Find(jukeinfo) + return FALSE + +/datum/controller/subsystem/jukeboxes/Initialize() + var/list/tracks = flist("config/jukebox_music/sounds/") + for(var/S in tracks) + var/datum/track/T = new() + T.song_path = file("config/jukebox_music/sounds/[S]") + var/list/L = splittext(S,"+") + T.song_name = L[1] + T.song_length = text2num(L[2]) + T.song_beat = text2num(L[3]) + T.song_associated_id = L[4] + songs |= T + return ..() + +/datum/controller/subsystem/jukeboxes/fire() + if(!activejukeboxes.len) + return + for(var/list/jukeinfo in activejukeboxes) + if(!jukeinfo.len) + to_chat(world, "If you see this, screenshot it and send it to a dev. Active jukebox without any associated metadata") + var/datum/track/juketrack = jukeinfo[1] + if(!istype(juketrack)) + to_chat(world, "If you see this, screenshot it and send it to a dev. After jukebox track grabbing") + continue + var/obj/jukebox = jukeinfo[3] + if(!istype(jukebox)) + to_chat(world, "If you see this, screenshot it and send it to a dev. Nonexistant or invalid jukebox in active jukebox list") + continue + var/sound/song_played = sound(juketrack.song_path) + var/area/currentarea = get_area(jukebox) + var/turf/currentturf = get_turf(jukebox) + var/list/hearerscache = hearers(7, jukebox) + + for(var/mob/M in GLOB.player_list) + if(!M.client) + continue + if(!(M.client.prefs.toggles & SOUND_INSTRUMENTS)) + M.stop_sound_channel(jukeinfo[2]) + continue + + var/inrange = FALSE + if(jukebox.z == M.z) //todo - expand this to work with mining planet z-levels when robust jukebox audio gets merged to master + song_played.status = SOUND_UPDATE + if(get_area(M) == currentarea) + inrange = TRUE + else if(M in hearerscache) + inrange = TRUE + else + song_played.status = SOUND_MUTE | SOUND_UPDATE //Setting volume = 0 doesn't let the sound properties update at all, which is lame. + + M.playsound_local(currentturf, null, 100, channel = jukeinfo[2], S = song_played, envwet = (inrange ? -250 : 0), envdry = (inrange ? 0 : -10000)) + CHECK_TICK + return diff --git a/code/game/machinery/dance_machine.dm b/code/game/machinery/dance_machine.dm index cfdf07acdd..f67600252e 100644 --- a/code/game/machinery/dance_machine.dm +++ b/code/game/machinery/dance_machine.dm @@ -9,7 +9,6 @@ var/active = FALSE var/list/rangers = list() var/stop = 0 - var/list/songs = list() var/datum/track/selection = null /obj/machinery/jukebox/disco @@ -29,34 +28,6 @@ resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF flags_1 = NODECONSTRUCT_1 -/datum/track - var/song_name = "generic" - var/song_path = null - var/song_length = 0 - var/song_beat = 0 - -/datum/track/New(name, path, length, beat) - song_name = name - song_path = path - song_length = length - song_beat = beat - -/obj/machinery/jukebox/Initialize() - . = ..() - var/list/tracks = flist("config/jukebox_music/sounds/") - - for(var/S in tracks) - var/datum/track/T = new() - T.song_path = file("config/jukebox_music/sounds/[S]") - var/list/L = splittext(S,"+") - T.song_name = L[1] - T.song_length = text2num(L[2]) - T.song_beat = text2num(L[3]) - songs |= T - - if(songs.len) - selection = pick(songs) - /obj/machinery/jukebox/Destroy() dance_over() return ..() @@ -91,7 +62,7 @@ to_chat(user,"Error: Access Denied.") user.playsound_local(src,'sound/misc/compiler-failure.ogg', 25, 1) return - if(!songs.len) + if(!SSjukeboxes.songs.len) to_chat(user,"Error: No music tracks have been authorized for your station. Petition Central Command to resolve this issue.") playsound(src,'sound/misc/compiler-failure.ogg', 25, 1) return @@ -100,8 +71,11 @@ dat += "[!active ? "BREAK IT DOWN" : "SHUT IT DOWN"]
" dat += "
" dat += " Select Track
" - dat += "Track Selected: [selection.song_name]
" - dat += "Track Length: [DisplayTimeText(selection.song_length)]

" + if(istype(selection)) + dat += "Track Selected: [selection.song_name]
" + dat += "Track Length: [DisplayTimeText(selection.song_length)]

" + else + dat += "Track Selected: None!

" var/datum/browser/popup = new(user, "vending", "[name]", 400, 350) popup.set_content(dat.Join()) popup.open() @@ -120,8 +94,14 @@ to_chat(usr, "Error: The device is still resetting from the last activation, it will be ready again in [DisplayTimeText(stop-world.time)].") playsound(src, 'sound/misc/compiler-failure.ogg', 50, 1) return - activate_music() - START_PROCESSING(SSobj, src) + if(!istype(selection)) + to_chat(usr, "Error: Severe user incompetence detected.") + playsound(src, 'sound/misc/compiler-failure.ogg', 50, 1) + return + if(!activate_music()) + to_chat(usr, "Error: Generic hardware failure.") + playsound(src, 'sound/misc/compiler-failure.ogg', 50, 1) + return updateUsrDialog() else if(active) stop = 0 @@ -132,7 +112,7 @@ return var/list/available = list() - for(var/datum/track/S in songs) + for(var/datum/track/S in SSjukeboxes.songs) available[S.song_name] = S var/selected = input(usr, "Choose your song", "Track:") as null|anything in available if(QDELETED(src) || !selected || !istype(available[selected], /datum/track)) @@ -141,10 +121,15 @@ updateUsrDialog() /obj/machinery/jukebox/proc/activate_music() - active = TRUE - update_icon() - START_PROCESSING(SSobj, src) - stop = world.time + selection.song_length + var/jukeboxslottotake = SSjukeboxes.addjukebox(src, selection) + if(jukeboxslottotake) + active = TRUE + update_icon() + START_PROCESSING(SSobj, src) + stop = world.time + selection.song_length + return TRUE + else + return FALSE /obj/machinery/jukebox/disco/activate_music() ..() @@ -433,23 +418,9 @@ QDEL_LIST(sparkles) /obj/machinery/jukebox/process() - if(world.time < stop && active) - var/sound/song_played = sound(selection.song_path) - - for(var/mob/M in range(10,src)) - if(!M.client || !(M.client.prefs.toggles & SOUND_INSTRUMENTS)) - continue - if(!(M in rangers)) - rangers[M] = TRUE - M.playsound_local(get_turf(M), null, 100, channel = CHANNEL_JUKEBOX, S = song_played) - for(var/mob/L in rangers) - if(get_dist(src,L) > 10) - rangers -= L - if(!L || !L.client) - continue - L.stop_sound_channel(CHANNEL_JUKEBOX) - else if(active) + if(active && world.time >= stop) active = FALSE + SSjukeboxes.removejukebox(SSjukeboxes.findjukeboxindex(src)) STOP_PROCESSING(SSobj, src) dance_over() playsound(src,'sound/machines/terminal_off.ogg',50,1) diff --git a/code/game/sound.dm b/code/game/sound.dm index 48accadb59..5b40e6640a 100644 --- a/code/game/sound.dm +++ b/code/game/sound.dm @@ -26,7 +26,7 @@ if(T && T.z == turf_source.z) M.playsound_local(turf_source, soundin, vol, vary, frequency, falloff, channel, pressure_affected, S) -/mob/proc/playsound_local(turf/turf_source, soundin, vol as num, vary, frequency, falloff, channel = 0, pressure_affected = TRUE, sound/S) +/mob/proc/playsound_local(turf/turf_source, soundin, vol as num, vary, frequency, falloff, channel = 0, pressure_affected = TRUE, sound/S, envwet = -10000, envdry = 0) if(!client || !can_hear()) return @@ -36,6 +36,7 @@ S.wait = 0 //No queue S.channel = channel || open_sound_channel() S.volume = vol + S.environment = 7 if(vary) if(frequency) @@ -64,6 +65,8 @@ else //space pressure_factor = 0 + S.echo = list(envdry, null, envwet, null, null, null, null, null, null, null, null, null, null, 1, 1, 1, null, null) + if(distance <= 1) pressure_factor = max(pressure_factor, 0.15) //touching the source of the sound diff --git a/tgstation.dme b/tgstation.dme index 6fb2973b66..157b78614f 100755 --- a/tgstation.dme +++ b/tgstation.dme @@ -221,6 +221,7 @@ #include "code\controllers\subsystem\input.dm" #include "code\controllers\subsystem\ipintel.dm" #include "code\controllers\subsystem\job.dm" +#include "code\controllers\subsystem\jukeboxes.dm" #include "code\controllers\subsystem\language.dm" #include "code\controllers\subsystem\lighting.dm" #include "code\controllers\subsystem\machines.dm"