mirror of
https://github.com/SPLURT-Station/S.P.L.U.R.T-Station-13.git
synced 2025-12-26 17:53:14 +00:00
189 lines
6.5 KiB
Plaintext
189 lines
6.5 KiB
Plaintext
//As a brief warning to all those who dare tread upon these grounds:
|
|
//The bulk of this code here was written years ago, back in the days of 512.
|
|
//We were incredibly drunk back then. And nowadays, we've found that being drunk is a hard requirement for working with this code.
|
|
//So if you're here to make changes? Brandish a glass. There are many sins here, but it's exactly as engineered as it needs to be.
|
|
//We physically won't be able to tell you what half of this code does. The only thing that'll help you here is the ballmer peak.
|
|
//Bottoms up, friend. And be sure to drink responsibly. Be sure to fetch some water, too; it eases the hangover. - Bhijn & Myr
|
|
|
|
|
|
// Jukelist indices
|
|
#define JUKE_TRACK 1
|
|
#define JUKE_CHANNEL 2
|
|
#define JUKE_BOX 3
|
|
#define JUKE_FALLOFF 4
|
|
#define JUKE_SOUND 5
|
|
|
|
|
|
SUBSYSTEM_DEF(jukeboxes)
|
|
name = "Jukeboxes"
|
|
wait = 5
|
|
var/list/songs = list()
|
|
var/list/activejukeboxes = list()
|
|
var/list/freejukeboxchannels = 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, jukefalloff = 1)
|
|
if(!istype(T))
|
|
CRASH("[src] tried to play a song with a nonexistant track")
|
|
var/channeltoreserve = pick(freejukeboxchannels)
|
|
if(!channeltoreserve)
|
|
return FALSE
|
|
var/sound/song_to_init = sound(T.song_path)
|
|
freejukeboxchannels -= channeltoreserve
|
|
var/list/youvegotafreejukebox = list(T, channeltoreserve, jukebox, jukefalloff, song_to_init)
|
|
|
|
song_to_init.status = SOUND_MUTE
|
|
song_to_init.environment = 7
|
|
song_to_init.channel = channeltoreserve
|
|
song_to_init.volume = 1
|
|
song_to_init.falloff = jukefalloff
|
|
song_to_init.echo = list(0, null, -10000, null, null, null, null, null, null, null, null, null, null, 1, 1, 1, null, null)
|
|
|
|
activejukeboxes.len++
|
|
activejukeboxes[activejukeboxes.len] = youvegotafreejukebox
|
|
|
|
for(var/mob/M in GLOB.player_list)
|
|
if(!M.client)
|
|
continue
|
|
if(!(M.client.prefs.toggles & SOUND_INSTRUMENTS))
|
|
continue
|
|
|
|
SEND_SOUND(M, song_to_init)
|
|
return activejukeboxes.len
|
|
|
|
|
|
//Updates jukebox by transferring to different object or modifying falloff.
|
|
/datum/controller/subsystem/jukeboxes/proc/updatejukebox(IDtoupdate, obj/jukebox, jukefalloff)
|
|
if(islist(activejukeboxes[IDtoupdate]))
|
|
if(istype(jukebox))
|
|
activejukeboxes[IDtoupdate][JUKE_BOX] = jukebox
|
|
if(!isnull(jukefalloff))
|
|
activejukeboxes[IDtoupdate][JUKE_FALLOFF] = jukefalloff
|
|
|
|
/datum/controller/subsystem/jukeboxes/proc/removejukebox(IDtoremove)
|
|
if(islist(activejukeboxes[IDtoremove]))
|
|
var/jukechannel = activejukeboxes[IDtoremove][JUKE_CHANNEL]
|
|
for(var/mob/M in GLOB.player_list)
|
|
if(!M.client)
|
|
continue
|
|
M.stop_sound_channel(jukechannel)
|
|
freejukeboxchannels |= jukechannel
|
|
activejukeboxes.Cut(IDtoremove, IDtoremove+1)
|
|
return TRUE
|
|
else
|
|
CRASH("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
|
|
for(var/i in CHANNEL_JUKEBOX_START to CHANNEL_JUKEBOX)
|
|
freejukeboxchannels |= i
|
|
return ..()
|
|
|
|
/datum/controller/subsystem/jukeboxes/fire()
|
|
if(!activejukeboxes.len)
|
|
return
|
|
for(var/list/jukeinfo in activejukeboxes)
|
|
if(!jukeinfo.len)
|
|
stack_trace("Active jukebox without any associated metadata.")
|
|
continue
|
|
var/datum/track/juketrack = jukeinfo[JUKE_TRACK]
|
|
if(!istype(juketrack))
|
|
stack_trace("Invalid jukebox track datum.")
|
|
continue
|
|
var/obj/jukebox = jukeinfo[JUKE_BOX]
|
|
if(!istype(jukebox))
|
|
stack_trace("Nonexistant or invalid object associated with jukebox.")
|
|
continue
|
|
|
|
var/list/audible_zlevels = get_multiz_accessible_levels(jukebox.z) //TODO - for multiz refresh, this should use the cached zlevel connections var in SSMapping. For now this is fine!
|
|
|
|
var/sound/song_played = jukeinfo[JUKE_SOUND]
|
|
var/turf/currentturf = get_turf(jukebox)
|
|
var/area/currentarea = get_area(jukebox)
|
|
var/list/hearerscache = hearers(7, jukebox)
|
|
var/targetfalloff = jukeinfo[JUKE_FALLOFF]
|
|
var/mixes = ((targetfalloff*250)-750)
|
|
var/inrange
|
|
var/pressure_factor
|
|
|
|
|
|
var/datum/gas_mixture/source_env = (istype(currentturf) ? currentturf.return_air() : null)
|
|
var/datum/gas_mixture/hearer_env //We init this var outside of the mob loop for the sake of performance
|
|
var/turf/hearerturf //ditto
|
|
|
|
var/source_pressure = (istype(source_env) ? source_env.return_pressure() : 0)
|
|
|
|
song_played.falloff = targetfalloff
|
|
song_played.volume = min((targetfalloff * 50), 100)
|
|
|
|
for(var/mob/M in GLOB.player_list)
|
|
if(!M.client)
|
|
continue
|
|
if(!(M.client.prefs.toggles & SOUND_INSTRUMENTS))
|
|
M.stop_sound_channel(jukeinfo[JUKE_CHANNEL])
|
|
continue
|
|
|
|
inrange = FALSE
|
|
song_played.status = SOUND_MUTE | SOUND_UPDATE
|
|
|
|
if(source_pressure)
|
|
hearerturf = get_turf(M)
|
|
hearer_env = (istype(hearerturf) ? hearerturf.return_air() : null)
|
|
if(istype(hearer_env))
|
|
pressure_factor = min(source_pressure, hearer_env.return_pressure())
|
|
|
|
if(pressure_factor && targetfalloff && M.can_hear() && (hearerturf.z in audible_zlevels))
|
|
if(get_area(hearerturf) == currentarea)
|
|
inrange = TRUE
|
|
else if(M in hearerscache)
|
|
inrange = TRUE
|
|
|
|
song_played.x = (currentturf.x - hearerturf.x) * SOUND_DEFAULT_DISTANCE_MULTIPLIER
|
|
song_played.z = (currentturf.y - hearerturf.y) * SOUND_DEFAULT_DISTANCE_MULTIPLIER
|
|
song_played.y = (((currentturf.z - hearerturf.z) * 10 * SOUND_DEFAULT_DISTANCE_MULTIPLIER) + ((currentturf.z < hearerturf.z) ? -5 : 5))
|
|
|
|
if(pressure_factor < ONE_ATMOSPHERE)
|
|
song_played.volume = (min((targetfalloff * 50), 100) * max((pressure_factor - SOUND_MINIMUM_PRESSURE)/(ONE_ATMOSPHERE - SOUND_MINIMUM_PRESSURE), 1))
|
|
|
|
song_played.echo[1] = (inrange ? 0 : -10000)
|
|
song_played.echo[3] = (inrange ? mixes : max(mixes, 0))
|
|
song_played.status = SOUND_UPDATE
|
|
SEND_SOUND(M, song_played)
|
|
CHECK_TICK
|
|
return
|
|
|
|
#undef JUKE_TRACK
|
|
#undef JUKE_CHANNEL
|
|
#undef JUKE_BOX
|
|
#undef JUKE_FALLOFF
|
|
#undef JUKE_SOUND
|