Skyrat jukebox code cleanup (#2762)

## About The Pull Request

And by cleanup I mean rip literally all of it out because it turns out
tg's jukebox code basically has feature parity with what we have now
while also being better code-wise.

## Why It's Good For The Game

Less code to maintain.

## Proof Of Testing

It compiled and it plays music properly and the rave visor also plays
music properly

## Changelog

🆑
refactor: ripped out all the skyrat jukebox code in favor of tg's.
/🆑
This commit is contained in:
Roxy
2024-12-24 14:06:36 -05:00
committed by GitHub
parent e7d1ccc18b
commit 1305ab885a
15 changed files with 8 additions and 758 deletions

View File

@@ -42886,7 +42886,7 @@
/obj/effect/turf_decal/siding/wood{
dir = 8
},
/obj/machinery/jukebox/public,
/obj/machinery/jukebox/no_access,
/turf/open/floor/wood/large,
/area/station/commons/lounge)
"oGU" = (

View File

@@ -3733,7 +3733,7 @@
/obj/effect/turf_decal/trimline/white/filled/warning{
dir = 4
},
/obj/machinery/jukebox/public,
/obj/machinery/jukebox/no_access,
/turf/open/floor/iron/dark,
/area/shuttle/escape)
"Sz" = (

View File

@@ -16,8 +16,7 @@
#define MAX_INSTRUMENT_CHANNELS (128 * 6)
// SKYRAT EDIT START - JUKEBOX
#define CHANNEL_JUKEBOX_START 1006
// SKYRAT EDIT START
#define CHANNEL_HEV 1005
//SKYRAT EDIT CHANGE END

View File

@@ -1,4 +1,4 @@
/* SKYRAT EDIT: See modular_skyrat/modules/jukebox /// Checks if the mob has jukebox muted in their preferences
/// Checks if the mob has jukebox muted in their preferences
#define IS_PREF_MUTED(mob) (!isnull(mob.client) && !mob.client.prefs.read_preference(/datum/preference/toggle/sound_jukebox))
// Reasons for appling STATUS_MUTE to a mob's sound status
@@ -103,7 +103,7 @@
var/datum/track/new_track = new()
new_track.song_path = file("[global.config.directory]/jukebox_music/sounds/[track_file]")
var/list/track_data = splittext(track_file, "+")
if(length(track_data) != 3)
if(length(track_data) < 3) // BUBBER EDIT - This is fucking stupid - ORIGINAL: if(length(track_data) != 3)
continue
new_track.song_name = track_data[1]
new_track.song_length = text2num(track_data[2])
@@ -404,4 +404,3 @@
song_name = "Tintin on the Moon"
song_length = 3 MINUTES + 52 SECONDS
song_beat = 1 SECONDS
SKYRAT EDIT END*/

View File

@@ -1,4 +1,3 @@
/* SKYRAT EDIT: See modular_skyrat/modules/jukebox
/obj/machinery/jukebox
name = "jukebox"
desc = "A classic music player."
@@ -384,4 +383,3 @@
/obj/machinery/jukebox/disco/proc/dance4_revert(mob/living/dancer, matrix/starting_matrix)
animate(dancer, transform = starting_matrix, time = 5, loop = 0)
REMOVE_TRAIT(dancer, TRAIT_DISCO_DANCER, REF(src))
SKYRAT EDIT END*/

View File

@@ -80,7 +80,6 @@
flash_color(mod.wearer, flash_color = "#FF0000", flash_time = 10 SECONDS)
set_off = FALSE
/* SKYRAT EDIT: See skyrat_modular/modules/jukebox
///Rave Visor - Gives you a rainbow visor and plays jukebox music to you.
/obj/item/mod/module/visor/rave
name = "MOD rave visor module"
@@ -159,7 +158,7 @@
return
music_player.selection = new_song
SKYRAT EDIT END */
///Tanner - Tans you with spraytan.
/obj/item/mod/module/tanner
name = "MOD tanning module"

View File

@@ -13,5 +13,3 @@ Every sound you add must have a unique name. Avoid using the plus sign "+" and t
Sound names must be in the format of [song name]+[length in deciseconds]+[beat in deciseconds].ogg
A three minute song title "SS13" that lasted 3 minutes would have a file name SS13+1800+5.ogg
SKYRAT CHANGE: The title must also include the associated ID. So: [song name]+[length in deciseconds]+[beat in deciseconds]+[song ID]

View File

@@ -52,7 +52,7 @@
/datum/area_spawn/bar_jukebox
target_areas = list(/area/station/commons/lounge, /area/station/service/bar/atrium, /area/station/service/bar)
desired_atom = /obj/machinery/jukebox/public
desired_atom = /obj/machinery/jukebox/no_access
mode = AREA_SPAWN_MODE_OPEN
// Wall mounts. Use sparingly as walls are prime real estate

View File

@@ -1,484 +0,0 @@
/// Helper macro to check if the passed mob has jukebox sound preference enabled
#define HAS_JUKEBOX_PREF(mob) (!QDELETED(mob) && !isnull(mob.client) && mob.client.prefs.read_preference(/datum/preference/toggle/sound_jukebox))
/obj/machinery/jukebox
name = "jukebox"
desc = "A classic music player."
icon = 'icons/obj/machines/music.dmi'
icon_state = "jukebox"
verb_say = "states"
density = TRUE
req_access = list(ACCESS_BAR)
/// Whether we're actively playing music
var/active = FALSE
/// List of weakrefs to mobs listening to the current song
var/list/datum/weakref/rangers = list()
/// World.time when the current song will stop playing, but also a cooldown between activations
var/stop = 0
/// Current song selected
var/datum/track/selection = null
/// Volume of the songs played
var/volume = 50
//https://www.desmos.com/calculator/ybto1dyqzk
var/falloff_dist_offset = 20 // higher = jukebox can be heard from further away
var/falloff_dist_divider = 100 // lower = falloff begins sooner
/obj/machinery/jukebox/disco
name = "radiant dance machine mark IV"
desc = "The first three prototypes were discontinued after mass casualty incidents."
icon = 'icons/obj/machines/music.dmi'
icon_state = "disco"
anchored = FALSE
var/list/spotlights = list()
var/list/sparkles = list()
/obj/machinery/jukebox/disco/indestructible
name = "radiant dance machine mark V"
desc = "Now redesigned with data gathered from the extensive disco and plasma research."
anchored = TRUE
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
/obj/machinery/jukebox/public
req_access = list()
falloff_dist_offset = 10
falloff_dist_divider = 50
/obj/machinery/jukebox/no_access
req_access = null
falloff_dist_offset = 10
falloff_dist_divider = 50
/obj/machinery/jukebox/Initialize(mapload)
. = ..()
if(length(SSjukeboxes.songs))
selection = pick(SSjukeboxes.songs)
/obj/machinery/jukebox/Destroy()
dance_over()
selection = null
return ..()
/obj/machinery/jukebox/attackby(obj/item/O, mob/user, params)
if(!active)
if(O.tool_behaviour == TOOL_WRENCH)
if(!anchored && !isinspace())
to_chat(user,span_notice("You secure [src] to the floor."))
set_anchored(TRUE)
else if(anchored)
to_chat(user,span_notice("You unsecure and disconnect [src]."))
set_anchored(FALSE)
playsound(src, 'sound/items/deconstruct.ogg', 50, TRUE)
return
return ..()
/obj/machinery/jukebox/update_icon_state()
. = ..()
SSvis_overlays.remove_vis_overlay(src, managed_vis_overlays)
luminosity = 0
if(active)
luminosity = 1
SSvis_overlays.add_vis_overlay(src, icon, "active", layer, plane, dir, alpha)
SSvis_overlays.add_vis_overlay(src, icon, "active", 0, EMISSIVE_PLANE, dir, alpha)
/obj/machinery/jukebox/examine(mob/user)
. = ..()
if (active)
. += "Now playing: [selection.song_name]"
/obj/machinery/jukebox/ui_status(mob/user)
if(!anchored)
to_chat(user,span_warning("This device must be anchored by a wrench!"))
return UI_CLOSE
if(!allowed(user) && !isobserver(user))
to_chat(user,span_warning("Error: Access Denied."))
return UI_CLOSE
if(!SSjukeboxes.songs.len && !isobserver(user))
to_chat(user,span_warning("Error: No music tracks have been authorized for your station. Petition Central Command to resolve this issue."))
return UI_CLOSE
return ..()
/obj/machinery/jukebox/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "Jukebox", name)
ui.open()
/obj/machinery/jukebox/ui_data(mob/user)
var/list/data = list()
data["active"] = active
data["songs"] = list()
for(var/datum/track/S in SSjukeboxes.songs)
var/list/track_data = list(
name = S.song_name
)
data["songs"] += list(track_data)
data["track_selected"] = null
data["track_length"] = null
data["track_beat"] = null
if(selection)
data["track_selected"] = selection.song_name
data["track_length"] = DisplayTimeText(selection.song_length)
data["track_beat"] = selection.song_beat
data["volume"] = volume
return data
/obj/machinery/jukebox/ui_act(action, list/params)
. = ..()
if(.)
return
switch(action)
if("toggle")
if(QDELETED(src))
return
if(!active)
if(stop > world.time)
to_chat(usr, span_warning("Error: The device is still resetting from the last activation, it will be ready again in [DisplayTimeText(stop-world.time)]."))
return
activate_music()
return TRUE
else
stop = 0
return TRUE
if("select_track")
if(active)
to_chat(usr, span_warning("Error: You cannot change the song until the current one is over."))
return
var/list/available = list()
for(var/datum/track/S in SSjukeboxes.songs)
available[S.song_name] = S
var/selected = params["track"]
if(QDELETED(src) || !selected || !istype(available[selected], /datum/track))
return
selection = available[selected]
return TRUE
if("set_volume")
var/new_volume = params["volume"]
if(new_volume == "reset")
volume = initial(volume)
return TRUE
else if(new_volume == "min")
volume = 0
return TRUE
else if(new_volume == "max")
volume = 100
return TRUE
else if(text2num(new_volume) != null)
volume = text2num(new_volume)
return TRUE
/obj/machinery/jukebox/proc/activate_music()
var/jukeboxslottotake = SSjukeboxes.addjukebox(src, selection, 2)
if(jukeboxslottotake)
active = TRUE
update_use_power(ACTIVE_POWER_USE)
update_appearance(UPDATE_ICON_STATE)
START_PROCESSING(SSobj, src)
stop = world.time + selection.song_length
return TRUE
else
return FALSE
/obj/machinery/jukebox/disco/activate_music()
..()
dance_setup()
lights_spin()
/obj/machinery/jukebox/disco/proc/dance_setup()
var/turf/cen = get_turf(src)
FOR_DVIEW(var/turf/t, 3, get_turf(src),INVISIBILITY_LIGHTING)
if(t.x == cen.x && t.y > cen.y)
spotlights += new /obj/item/flashlight/spotlight(t, 1 + get_dist(src, t), 30 - (get_dist(src, t) * 8), COLOR_SOFT_RED)
continue
if(t.x == cen.x && t.y < cen.y)
spotlights += new /obj/item/flashlight/spotlight(t, 1 + get_dist(src, t), 30 - (get_dist(src, t) * 8), LIGHT_COLOR_PURPLE)
continue
if(t.x > cen.x && t.y == cen.y)
spotlights += new /obj/item/flashlight/spotlight(t, 1 + get_dist(src, t), 30 - (get_dist(src, t) * 8), LIGHT_COLOR_BRIGHT_YELLOW)
continue
if(t.x < cen.x && t.y == cen.y)
spotlights += new /obj/item/flashlight/spotlight(t, 1 + get_dist(src, t), 30 - (get_dist(src, t) * 8), LIGHT_COLOR_GREEN)
continue
if((t.x+1 == cen.x && t.y+1 == cen.y) || (t.x+2==cen.x && t.y+2 == cen.y))
spotlights += new /obj/item/flashlight/spotlight(t, 1.4 + get_dist(src, t), 30 - (get_dist(src, t) * 8), LIGHT_COLOR_ORANGE)
continue
if((t.x-1 == cen.x && t.y-1 == cen.y) || (t.x-2==cen.x && t.y-2 == cen.y))
spotlights += new /obj/item/flashlight/spotlight(t, 1.4 + get_dist(src, t), 30 - (get_dist(src, t) * 8), LIGHT_COLOR_CYAN)
continue
if((t.x-1 == cen.x && t.y+1 == cen.y) || (t.x-2==cen.x && t.y+2 == cen.y))
spotlights += new /obj/item/flashlight/spotlight(t, 1.4 + get_dist(src, t), 30 - (get_dist(src, t) * 8), LIGHT_COLOR_BLUEGREEN)
continue
if((t.x+1 == cen.x && t.y-1 == cen.y) || (t.x+2==cen.x && t.y-2 == cen.y))
spotlights += new /obj/item/flashlight/spotlight(t, 1.4 + get_dist(src, t), 30 - (get_dist(src, t) * 8), LIGHT_COLOR_BLUE)
continue
continue
FOR_DVIEW_END
/obj/machinery/jukebox/disco/proc/hierofunk()
for(var/i in 1 to 10)
spawn_atom_to_turf(/obj/effect/temp_visual/hierophant/telegraph/edge, src, 1, FALSE)
sleep(0.5 SECONDS)
if(QDELETED(src))
return
#define DISCO_INFENO_RANGE (rand(85, 115)*0.01)
/obj/machinery/jukebox/disco/proc/lights_spin()
for(var/i in 1 to 25)
if(QDELETED(src) || !active)
return
var/obj/effect/overlay/sparkles/S = new /obj/effect/overlay/sparkles(src)
S.alpha = 0
sparkles += S
switch(i)
if(1 to 8)
S.orbit(src, 30, TRUE, 60, 36, TRUE)
if(9 to 16)
S.orbit(src, 62, TRUE, 60, 36, TRUE)
if(17 to 24)
S.orbit(src, 95, TRUE, 60, 36, TRUE)
if(25)
S.pixel_y = 7
S.forceMove(get_turf(src))
sleep(0.7 SECONDS)
if(selection.song_name == "Engineering's Ultimate High-Energy Hustle")
sleep(28 SECONDS)
for(var/s in sparkles)
var/obj/effect/overlay/sparkles/reveal = s
reveal.alpha = 255
while(active)
for(var/g in spotlights) // The multiples reflects custom adjustments to each colors after dozens of tests
var/obj/item/flashlight/spotlight/glow = g
if(QDELETED(glow))
stack_trace("[glow?.gc_destroyed ? "Qdeleting glow" : "null entry"] found in [src].[gc_destroyed ? " Source qdeleting at the time." : ""]")
return
switch(glow.light_color)
if(COLOR_SOFT_RED)
if(glow.even_cycle)
glow.set_light_on(FALSE)
glow.set_light_color(LIGHT_COLOR_BLUE)
else
glow.set_light_range_power_color(glow.base_light_range * DISCO_INFENO_RANGE, glow.light_power * 1.48, LIGHT_COLOR_BLUE)
glow.set_light_on(TRUE)
if(LIGHT_COLOR_BLUE)
if(glow.even_cycle)
glow.set_light_range_power_color(glow.base_light_range * DISCO_INFENO_RANGE, glow.light_power * 2, LIGHT_COLOR_GREEN)
glow.set_light_on(TRUE)
else
glow.set_light_on(FALSE)
glow.set_light_color(LIGHT_COLOR_GREEN)
if(LIGHT_COLOR_GREEN)
if(glow.even_cycle)
glow.set_light_on(FALSE)
glow.set_light_color(LIGHT_COLOR_ORANGE)
else
glow.set_light_range_power_color(glow.base_light_range * DISCO_INFENO_RANGE, glow.light_power * 0.5, LIGHT_COLOR_ORANGE)
glow.set_light_on(TRUE)
if(LIGHT_COLOR_ORANGE)
if(glow.even_cycle)
glow.set_light_range_power_color(glow.base_light_range * DISCO_INFENO_RANGE, glow.light_power * 2.27, LIGHT_COLOR_PURPLE)
glow.set_light_on(TRUE)
else
glow.set_light_on(FALSE)
glow.set_light_color(LIGHT_COLOR_PURPLE)
if(LIGHT_COLOR_PURPLE)
if(glow.even_cycle)
glow.set_light_on(FALSE)
glow.set_light_color(LIGHT_COLOR_BLUEGREEN)
else
glow.set_light_range_power_color(glow.base_light_range * DISCO_INFENO_RANGE, glow.light_power * 0.44, LIGHT_COLOR_BLUEGREEN)
glow.set_light_on(TRUE)
if(LIGHT_COLOR_BLUEGREEN)
if(glow.even_cycle)
glow.set_light_range(glow.base_light_range * DISCO_INFENO_RANGE)
glow.set_light_color(LIGHT_COLOR_BRIGHT_YELLOW)
glow.set_light_on(TRUE)
else
glow.set_light_on(FALSE)
glow.set_light_color(LIGHT_COLOR_DIM_YELLOW)
if(LIGHT_COLOR_DIM_YELLOW)
if(glow.even_cycle)
glow.set_light_on(FALSE)
glow.set_light_color(LIGHT_COLOR_CYAN)
else
glow.set_light_range(glow.base_light_range * DISCO_INFENO_RANGE)
glow.set_light_color(LIGHT_COLOR_CYAN)
glow.set_light_on(TRUE)
if(LIGHT_COLOR_CYAN)
if(glow.even_cycle)
glow.set_light_range_power_color(glow.base_light_range * DISCO_INFENO_RANGE, glow.light_power * 0.68, COLOR_SOFT_RED)
glow.set_light_on(TRUE)
else
glow.set_light_on(FALSE)
glow.set_light_color(COLOR_SOFT_RED)
glow.even_cycle = !glow.even_cycle
if(prob(2)) // Unique effects for the dance floor that show up randomly to mix things up
INVOKE_ASYNC(src, PROC_REF(hierofunk))
sleep(selection.song_beat)
if(QDELETED(src))
return
#undef DISCO_INFENO_RANGE
/obj/machinery/jukebox/disco/proc/dance(mob/living/M) //Show your moves
set waitfor = FALSE
switch(rand(0, 9))
if(0 to 1)
dance2(M)
if(2 to 3)
dance3(M)
if(4 to 6)
dance4(M)
if(7 to 9)
dance5(M)
/obj/machinery/jukebox/disco/proc/dance2(mob/living/M)
for(var/i in 0 to 9)
dance_rotate(M, CALLBACK(M, TYPE_PROC_REF(/mob, dance_flip)))
sleep(2 SECONDS)
/mob/proc/dance_flip()
if(dir == WEST)
emote("flip")
/obj/machinery/jukebox/disco/proc/dance3(mob/living/M)
set waitfor = FALSE
var/matrix/initial_matrix = matrix(M.transform)
for (var/i in 1 to 75)
if (!M)
return
switch(i)
if (1 to 15)
initial_matrix = matrix(M.transform)
initial_matrix.Translate(0,1)
animate(M, transform = initial_matrix, time = 0.1 SECONDS, loop = 0)
if (16 to 30)
initial_matrix = matrix(M.transform)
initial_matrix.Translate(1,-1)
animate(M, transform = initial_matrix, time = 0.1 SECONDS, loop = 0)
if (31 to 45)
initial_matrix = matrix(M.transform)
initial_matrix.Translate(-1,-1)
animate(M, transform = initial_matrix, time = 0.1 SECONDS, loop = 0)
if (46 to 60)
initial_matrix = matrix(M.transform)
initial_matrix.Translate(-1,1)
animate(M, transform = initial_matrix, time = 0.1 SECONDS, loop = 0)
if (61 to 75)
initial_matrix = matrix(M.transform)
initial_matrix.Translate(1,0)
animate(M, transform = initial_matrix, time = 0.1 SECONDS, loop = 0)
M.setDir(turn(M.dir, 90))
switch (M.dir)
if (NORTH)
initial_matrix = matrix(M.transform)
initial_matrix.Translate(0,3)
animate(M, transform = initial_matrix, time = 0.1 SECONDS, loop = 0)
if (SOUTH)
initial_matrix = matrix(M.transform)
initial_matrix.Translate(0,-3)
animate(M, transform = initial_matrix, time = 0.1 SECONDS, loop = 0)
if (EAST)
initial_matrix = matrix(M.transform)
initial_matrix.Translate(3,0)
animate(M, transform = initial_matrix, time = 0.1 SECONDS, loop = 0)
if (WEST)
initial_matrix = matrix(M.transform)
initial_matrix.Translate(-3,0)
animate(M, transform = initial_matrix, time = 0.1 SECONDS, loop = 0)
sleep(0.1 SECONDS)
M.lying_fix()
/obj/machinery/jukebox/disco/proc/dance4(mob/living/lead_dancer)
var/speed = rand(1,3)
set waitfor = 0
var/time = 30
while(time)
sleep(speed)
for(var/i in 1 to speed)
lead_dancer.setDir(pick(GLOB.cardinals))
// makes people dance with us nearby
for(var/datum/weakref/weak_dancer as anything in rangers)
var/mob/living/carbon/dancer = weak_dancer.resolve()
if(!istype(dancer))
continue
dancer.set_resting(!dancer.resting, silent = TRUE, instant = TRUE)
time--
/obj/machinery/jukebox/disco/proc/dance5(mob/living/M)
animate(M, transform = matrix(180, MATRIX_ROTATE), time = 1, loop = 0)
var/matrix/initial_matrix = matrix(M.transform)
for (var/i in 1 to 60)
if (!M)
return
if(!active)
break
if (i<31)
initial_matrix = matrix(M.transform)
initial_matrix.Translate(0,1)
animate(M, transform = initial_matrix, time = 1, loop = 0)
if (i>30)
initial_matrix = matrix(M.transform)
initial_matrix.Translate(0,-1)
animate(M, transform = initial_matrix, time = 1, loop = 0)
M.setDir(turn(M.dir, 90))
switch (M.dir)
if (NORTH)
initial_matrix = matrix(M.transform)
initial_matrix.Translate(0,3)
animate(M, transform = initial_matrix, time = 1, loop = 0)
if (SOUTH)
initial_matrix = matrix(M.transform)
initial_matrix.Translate(0,-3)
animate(M, transform = initial_matrix, time = 1, loop = 0)
if (EAST)
initial_matrix = matrix(M.transform)
initial_matrix.Translate(3,0)
animate(M, transform = initial_matrix, time = 1, loop = 0)
if (WEST)
initial_matrix = matrix(M.transform)
initial_matrix.Translate(-3,0)
animate(M, transform = initial_matrix, time = 1, loop = 0)
sleep(0.1 SECONDS)
M.lying_fix()
/mob/living/proc/lying_fix()
animate(src, transform = null, time = 0.1 SECONDS, loop = 0)
lying_prev = 0
/obj/machinery/jukebox/proc/dance_over()
var/position = SSjukeboxes.findjukeboxindex(src)
if(!position)
return
SSjukeboxes.removejukebox(position)
STOP_PROCESSING(SSobj, src)
rangers.Cut()
/obj/machinery/jukebox/disco/dance_over()
..()
QDEL_LIST(spotlights)
QDEL_LIST(sparkles)
/obj/machinery/jukebox/process()
if(active && world.time >= stop)
active = FALSE
update_use_power(IDLE_POWER_USE)
STOP_PROCESSING(SSobj, src)
dance_over()
playsound(src,'sound/machines/terminal/terminal_off.ogg',50,TRUE)
update_appearance(UPDATE_ICON_STATE)
stop = world.time + 100
/obj/machinery/jukebox/disco/process()
. = ..()
if(!active)
return
for(var/datum/weakref/weak_dancer as anything in rangers)
var/mob/living/to_dance = weak_dancer.resolve()
if(!istype(to_dance) || !(to_dance.mobility_flags & MOBILITY_MOVE))
continue
if(prob(5 + (allowed(to_dance) * 4)))
dance(to_dance)
#undef HAS_JUKEBOX_PREF

View File

@@ -1,138 +0,0 @@
#define HAS_JUKEBOX_PREF(mob) (!QDELETED(mob) && !isnull(mob.client) && mob.client.prefs.read_preference(/datum/preference/toggle/sound_jukebox) && mob.can_hear())
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/controller/subsystem/jukeboxes/proc/addjukebox(obj/machinery/jukebox/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
freejukeboxchannels -= channeltoreserve
var/list/youvegotafreejukebox = list(T, channeltoreserve, jukebox, jukefalloff)
activejukeboxes.len++
activejukeboxes[activejukeboxes.len] = youvegotafreejukebox
//Due to changes in later versions of 512, SOUND_UPDATE no longer properly plays audio when a file is defined in the sound datum. As such, we are now required to init the audio before we can actually do anything with it.
//Downsides to this? This means that you can *only* hear the jukebox audio if you were present on the server when it started playing, and it means that it's now impossible to add loops to the jukebox track list.
var/sound/song_to_init = sound(T.song_path)
song_to_init.status = SOUND_MUTE
for(var/mob/M in GLOB.player_list)
if(!M.client)
continue
if(!(M.client.prefs.read_preference(/datum/preference/toggle/sound_instruments)))
continue
M.playsound_local(M, null, (jukebox.volume / 2), channel = youvegotafreejukebox[2], sound_to_use = song_to_init)
return activejukeboxes.len
/datum/controller/subsystem/jukeboxes/proc/removejukebox(IDtoremove)
if(islist(activejukeboxes[IDtoremove]))
var/jukechannel = activejukeboxes[IDtoremove][2]
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/machinery/jukebox)
if(length(activejukeboxes))
for(var/list/jukeinfo in activejukeboxes)
if(jukebox in jukeinfo)
return activejukeboxes.Find(jukeinfo)
return FALSE
/datum/controller/subsystem/jukeboxes/proc/reload_songs()
songs = list()
var/list/tracks = flist("[global.config.directory]/jukebox_music/sounds/")
for(var/S in tracks)
var/datum/track/T = new()
T.song_path = file("[global.config.directory]/jukebox_music/sounds/[S]")
var/list/L = splittext(S,"+")
if(L.len != 4)
continue
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
/datum/controller/subsystem/jukeboxes/Initialize()
reload_songs()
for(var/i in CHANNEL_JUKEBOX_START to CHANNEL_JUKEBOX)
freejukeboxchannels |= i
return SS_INIT_SUCCESS
/datum/controller/subsystem/jukeboxes/fire()
if(!length(activejukeboxes))
return
for(var/list/jukeinfo in activejukeboxes)
if(!length(jukeinfo))
stack_trace("Active jukebox without any associated metadata.")
continue
var/datum/track/juketrack = jukeinfo[1]
if(!istype(juketrack))
stack_trace("Invalid jukebox track datum.")
continue
var/obj/machinery/jukebox/jukebox = jukeinfo[3]
if(!istype(jukebox))
stack_trace("Nonexistant or invalid object associated with jukebox.")
continue
var/sound/song_played = sound(juketrack.song_path)
song_played.falloff = 255
for(var/mob/M in GLOB.player_list)
if(!HAS_JUKEBOX_PREF(M))
M.stop_sound_channel(jukeinfo[2])
continue
var/volume = jukebox.volume
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
//https://www.desmos.com/calculator/ybto1dyqzk
if(jukeinfo[4]) //HAS FALLOFF
var/distance = get_dist(M,jukebox)
volume = min(
50,
volume,
volume * ((max(1,volume*0.1 + jukebox.falloff_dist_offset - distance)/80)**0.2 - (distance/jukebox.falloff_dist_divider))
)
volume = round(volume,1)
if(volume < jukebox.volume*0.5)
var/volume_mod = 1 - (volume / 50)
song_played.x = clamp(jukebox.x - M.x,-1,1) * volume_mod * 4
song_played.y = clamp(jukebox.y - M.y,-1,1) * volume_mod * 4
song_played.z = 1
else
song_played.x = 0
song_played.y = 0
song_played.z = 1
if(volume < 1)
song_played.status |= SOUND_MUTE
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(null, null, volume, channel = jukeinfo[2], sound_to_use = song_played)
CHECK_TICK
return
#undef HAS_JUKEBOX_PREF

View File

@@ -1,90 +0,0 @@
///Rave Visor - Gives you a rainbow visor and plays jukebox music to you.
/obj/item/mod/module/visor/rave
name = "MOD rave visor module"
desc = "A Super Cool Awesome Visor (SCAV), intended for modular suits."
icon_state = "rave_visor"
complexity = 1
overlay_state_inactive = "module_rave"
/// The client colors applied to the wearer.
var/datum/client_colour/rave_screen
/// The current element in the rainbow_order list we are on.
var/rave_number = 1
/// The track we selected to play.
var/datum/track/selection
/// A list of all the songs we can play.
var/list/songs = list()
/// A list of the colors the module can take.
var/static/list/rainbow_order = list(
list(1,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,1, 0,0,0,0),
list(1,0,0,0, 0,0.5,0,0, 0,0,0,0, 0,0,0,1, 0,0,0,0),
list(1,0,0,0, 0,1,0,0, 0,0,0,0, 0,0,0,1, 0,0,0,0),
list(0,0,0,0, 0,1,0,0, 0,0,0,0, 0,0,0,1, 0,0,0,0),
list(0,0,0,0, 0,0.5,0,0, 0,0,1,0, 0,0,0,1, 0,0,0,0),
list(1,0,0,0, 0,0,0,0, 0,0,1,0, 0,0,0,1, 0,0,0,0),
)
/obj/item/mod/module/visor/rave/Initialize(mapload)
. = ..()
var/list/tracks = flist("[global.config.directory]/jukebox_music/sounds/")
for(var/sound in tracks)
var/datum/track/track = new()
track.song_path = file("[global.config.directory]/jukebox_music/sounds/[sound]")
var/list/sound_params = splittext(sound,"+")
if(length(sound_params) != 3)
continue
track.song_name = sound_params[1]
track.song_length = text2num(sound_params[2])
track.song_beat = text2num(sound_params[3])
songs[track.song_name] = track
if(length(songs))
var/song_name = pick(songs)
selection = songs[song_name]
/obj/item/mod/module/visor/rave/on_activation()
. = ..()
if(!.)
return
rave_screen = mod.wearer.add_client_colour(/datum/client_colour/rave)
rave_screen.update_colour(rainbow_order[rave_number])
if(selection)
mod.wearer.playsound_local(get_turf(src), null, 50, channel = CHANNEL_JUKEBOX, sound_to_use = sound(selection.song_path), use_reverb = FALSE)
/obj/item/mod/module/visor/rave/on_deactivation(display_message = TRUE, deleting = FALSE)
. = ..()
if(!.)
return
QDEL_NULL(rave_screen)
if(selection)
mod.wearer.stop_sound_channel(CHANNEL_JUKEBOX)
if(deleting)
return
SEND_SOUND(mod.wearer, sound('sound/machines/terminal/terminal_off.ogg', volume = 50, channel = CHANNEL_JUKEBOX))
/obj/item/mod/module/visor/rave/generate_worn_overlay(mutable_appearance/standing)
. = ..()
for(var/mutable_appearance/appearance as anything in .)
appearance.color = active ? rainbow_order[rave_number] : null
/obj/item/mod/module/visor/rave/on_active_process(seconds_per_tick)
rave_number++
if(rave_number > length(rainbow_order))
rave_number = 1
mod.wearer.update_clothing(mod.slot_flags)
rave_screen.update_colour(rainbow_order[rave_number])
/obj/item/mod/module/visor/rave/get_configuration()
. = ..()
if(length(songs))
.["selection"] = add_ui_configuration("Song", "list", selection.song_name, clean_songs())
/obj/item/mod/module/visor/rave/configure_edit(key, value)
switch(key)
if("selection")
if(active)
return
selection = songs[value]
/obj/item/mod/module/visor/rave/proc/clean_songs()
. = list()
for(var/track in songs)
. += track

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

View File

@@ -1,29 +0,0 @@
https://github.com/Skyrat-SS13/Skyrat-tg/pull/892
## Title: Jukebox
MODULE ID: JUKEBOX
### Description:
Adds a new sound system for the jukebox, and also updates the jukebox to be good.
### TG Proc Changes:
- Skyrat-tg\code\__DEFINES\sound.dm > DEFINES CHANGED, SEE FILE.
### Defines:
- #define CHANNEL_JUKEBOX_START 1016
### Master file additions
- modular_skyrat\master_files\code\game\sound.dm
### Included files that are not contained in this module:
- N/A
### Credits:
Gandalf2k15 - porting
NotRanged - Original code

View File

@@ -7805,9 +7805,6 @@
#include "modular_skyrat\modules\interaction_menu\code\click.dm"
#include "modular_skyrat\modules\interaction_menu\code\interaction_component.dm"
#include "modular_skyrat\modules\interaction_menu\code\interaction_datum.dm"
#include "modular_skyrat\modules\jukebox\code\dance_machine.dm"
#include "modular_skyrat\modules\jukebox\code\jukebox_subsystem.dm"
#include "modular_skyrat\modules\jukebox\code\ravemod.dm"
#include "modular_skyrat\modules\jungle\code\flora.dm"
#include "modular_skyrat\modules\kahraman_equipment\code\gps_beacon.dm"
#include "modular_skyrat\modules\kahraman_equipment\code\looping_sounds.dm"

View File

@@ -0,0 +1 @@
/obj/machinery/jukebox/public : /obj/machinery/jukebox/no_access{@OLD}