From 9adb94ff5511f33a2f643140b222686ba2d33c36 Mon Sep 17 00:00:00 2001 From: PsiOmega Date: Wed, 29 Oct 2014 00:14:20 +0100 Subject: [PATCH] Area-based Jukebox A jukebox which alters the ambient sound in the current area and plays it with 100% probability. Leaving the area stops the ambient sound. Entering the area resumes playing the ambient sound. --- baystation12.dme | 1 + code/game/area/Space Station 13 areas.dm | 1 + code/game/area/areas.dm | 23 ++- code/game/machinery/jukebox.dm | 207 +++++++++++++++++++++++ code/modules/mob/mob_helpers.dm | 7 + icons/obj/jukebox.dmi | Bin 0 -> 7659 bytes nano/templates/jukebox.tmpl | 19 +++ 7 files changed, 251 insertions(+), 7 deletions(-) create mode 100644 code/game/machinery/jukebox.dm create mode 100644 icons/obj/jukebox.dmi create mode 100644 nano/templates/jukebox.tmpl diff --git a/baystation12.dme b/baystation12.dme index f17fd812b4b..f77e38af3b5 100644 --- a/baystation12.dme +++ b/baystation12.dme @@ -312,6 +312,7 @@ #include "code\game\machinery\holosign.dm" #include "code\game\machinery\igniter.dm" #include "code\game\machinery\iv_drip.dm" +#include "code\game\machinery\jukebox.dm" #include "code\game\machinery\lightswitch.dm" #include "code\game\machinery\machinery.dm" #include "code\game\machinery\magnet.dm" diff --git a/code/game/area/Space Station 13 areas.dm b/code/game/area/Space Station 13 areas.dm index 8085e9eb023..f48e04a3717 100755 --- a/code/game/area/Space Station 13 areas.dm +++ b/code/game/area/Space Station 13 areas.dm @@ -56,6 +56,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station var/list/all_doors = list() //Added by Strumpetplaya - Alarm Change - Contains a list of doors adjacent to this area var/air_doors_activated = 0 var/list/ambience = list('sound/ambience/ambigen1.ogg','sound/ambience/ambigen3.ogg','sound/ambience/ambigen4.ogg','sound/ambience/ambigen5.ogg','sound/ambience/ambigen6.ogg','sound/ambience/ambigen7.ogg','sound/ambience/ambigen8.ogg','sound/ambience/ambigen9.ogg','sound/ambience/ambigen10.ogg','sound/ambience/ambigen11.ogg','sound/ambience/ambigen12.ogg','sound/ambience/ambigen14.ogg') + var/sound/forced_ambience = null /*Adding a wizard area teleport list because motherfucking lag -- Urist*/ /*I am far too lazy to make it a proper list of areas so I'll just make it run the usual telepot routine at the start of the game*/ diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm index bc456405223..8279cde6a42 100644 --- a/code/game/area/areas.dm +++ b/code/game/area/areas.dm @@ -282,10 +282,9 @@ master.used_environ += amount -/area/Entered(A) - var/musVolume = 25 - var/sound = 'sound/ambience/ambigen1.ogg' +var/list/mob/living/forced_ambiance_list = new +/area/Entered(A) if(!istype(A,/mob/living)) return var/mob/living/L = A @@ -300,18 +299,28 @@ L.make_floating(0) L.lastarea = newarea + play_ambience(L) +/area/proc/play_ambience(var/mob/living/L) // Ambience goes down here -- make sure to list each area seperately for ease of adding things in later, thanks! Note: areas adjacent to each other should have the same sounds to prevent cutoff when possible.- LastyScratch if(!(L && L.client && (L.client.prefs.toggles & SOUND_AMBIENCE))) return + // If we previously were in an area with force-played ambiance, stop it. + if(L in forced_ambiance_list) + L << sound(null, channel = 1) + forced_ambiance_list -= L + if(!L.client.ambience_playing) L.client.ambience_playing = 1 L << sound('sound/ambience/shipambience.ogg', repeat = 1, wait = 0, volume = 35, channel = 2) - if(src.ambience.len && prob(35)) - sound = pick(ambience) - - if(world.time > L.client.played + 600) + if(forced_ambience) + forced_ambiance_list += L + L << forced_ambience + else if(src.ambience.len && prob(35)) + if((world.time >= L.client.played + 600)) + var/musVolume = 25 + var/sound = pick(ambience) L << sound(sound, repeat = 0, wait = 0, volume = musVolume, channel = 1) L.client.played = world.time diff --git a/code/game/machinery/jukebox.dm b/code/game/machinery/jukebox.dm new file mode 100644 index 00000000000..4bca09fdcc9 --- /dev/null +++ b/code/game/machinery/jukebox.dm @@ -0,0 +1,207 @@ +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 + +datum/track + var/title + var/sound + +datum/track/New(var/title_name, var/audio) + title = title_name + sound = audio + +/obj/machinery/media/jukebox/ + name = "space jukebox" + icon = 'icons/obj/jukebox.dmi' + icon_state = "jukebox2-nopower" + var/state_base = "jukebox2" + anchored = 1 + density = 1 + power_channel = EQUIP + + var/playing = 0 + + var/datum/track/current_track + var/list/datum/track/tracks = list( + new/datum/track("Beyond", 'sound/ambience/ambispace.ogg'), + new/datum/track("Clouds of Fire", 'sound/music/clouds.s3m'), + new/datum/track("D`Bert", 'sound/music/title2.ogg'), + new/datum/track("D`Fort", 'sound/ambience/song_game.ogg'), + new/datum/track("Floating", 'sound/music/main.ogg'), + new/datum/track("Endless Space", 'sound/music/space.ogg'), + new/datum/track("Part A", 'sound/misc/TestLoop1.ogg'), + new/datum/track("Scratch", 'sound/music/title1.ogg'), + new/datum/track("Trai`Tor", 'sound/music/traitor.ogg'), + ) + +/obj/machinery/media/jukebox/Del() + StopPlaying() + +/obj/machinery/media/jukebox/power_change() + if(!powered(power_channel) || !anchored) + stat |= NOPOWER + else + stat &= ~NOPOWER + + if(stat & (NOPOWER|BROKEN) && playing) + StopPlaying() + update_icon() + +/obj/machinery/media/jukebox/update_icon() + overlays.Cut() + if(stat & (NOPOWER|BROKEN) || !anchored) + if(stat & BROKEN) + icon_state = "[state_base]-broken" + else + icon_state = "[state_base]-nopower" + return + icon_state = state_base + if(playing) + if(emagged) + overlays += "[state_base]-emagged" + else + overlays += "[state_base]-running" + +/obj/machinery/media/jukebox/Topic(href, href_list) + if(..() || !(Adjacent(usr) || istype(usr, /mob/living/silicon))) + return + + if(!anchored) + usr << "You must secure \the [src] first." + return + + if(stat & (NOPOWER|BROKEN)) + usr << "\the [src] doesn't appear to function." + return + + if(href_list["change_track"]) + for(var/datum/track/T in tracks) + if(T.title == href_list["title"]) + current_track = T + StartPlaying() + break + else if(href_list["stop"]) + StopPlaying() + else if(href_list["play"]) + if(emagged) + playsound(src.loc, 'sound/items/AirHorn.ogg', 100, 1) + for(var/mob/living/carbon/M in ohearers(6, src)) + if(istype(M, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = M + if(istype(H.l_ear, /obj/item/clothing/ears/earmuffs) || istype(H.r_ear, /obj/item/clothing/ears/earmuffs)) + continue + M.sleeping = 0 + M.stuttering += 20 + M.ear_deaf += 30 + M.Weaken(3) + if(prob(30)) + M.Stun(10) + M.Paralyse(4) + else + M.make_jittery(500) + spawn(15) + explode() + else if(current_track == null) + usr << "No track selected." + else + StartPlaying() + + return 1 + +/obj/machinery/media/jukebox/interact(mob/user) + if(stat & (NOPOWER|BROKEN)) + usr << "\the [src] doesn't appear to function." + return + + ui_interact(user) + +/obj/machinery/media/jukebox/ui_interact(mob/user, ui_key = "jukebox", var/datum/nanoui/ui = null, var/force_open = 1) + var/title = "RetroBox - Space Style" + var/data[0] + + if(!(stat & (NOPOWER|BROKEN))) + data["current_track"] = current_track != null ? current_track.title : "" + data["playing"] = playing + + var/list/nano_tracks = new + for(var/datum/track/T in tracks) + nano_tracks[++nano_tracks.len] = list("track" = T.title) + + data["tracks"] = nano_tracks + + // update the ui if it exists, returns null if no ui is passed/found + ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) + if (!ui) + // the ui does not exist, so we'll create a new() one + // for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm + ui = new(user, src, ui_key, "jukebox.tmpl", title, 450, 600) + // when the ui is first opened this is the data it will use + ui.set_initial_data(data) + // open the new ui window + ui.open() + +/obj/machinery/media/jukebox/attack_ai(mob/user as mob) + return src.attack_hand(user) + +/obj/machinery/media/jukebox/attack_hand(var/mob/user as mob) + interact(user) + +/obj/machinery/media/jukebox/proc/explode() + walk_to(src,0) + src.visible_message("\the [src] blows apart!", 1) + + explosion(src.loc, 0, 0, 1, rand(1,2), 1) + + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(3, 1, src) + s.start() + + new /obj/effect/decal/cleanable/blood/oil(src.loc) + del(src) + +/obj/machinery/media/jukebox/attackby(obj/item/W as obj, mob/user as mob) + src.add_fingerprint(user) + + if(istype(W, /obj/item/weapon/wrench)) + if(playing) + StopPlaying() + user.visible_message("[user] has [anchored ? "un" : ""]secured \the [src].", "You [anchored ? "un" : ""]secure \the [src].") + anchored = !anchored + playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1) + power_change() + update_icon() + return + if(istype(W, /obj/item/weapon/card/emag)) + if(!emagged) + emagged = 1 + StopPlaying() + visible_message("\the [src] makes a fizzling sound.") + log_and_message_admins("emagged \the [src]") + update_icon() + return + + return ..() + +/obj/machinery/media/jukebox/proc/StopPlaying() + var/area/A = get_area(src) + // Always kill the current sound + for(var/mob/living/M in mobs_in_area(A)) + M << sound(null, channel = 1) + + A.forced_ambience = null + playing = 0 + update_icon() + + +/obj/machinery/media/jukebox/proc/StartPlaying() + StopPlaying() + if(!current_track) + return + + var/area/A = get_area(src) + A.forced_ambience = sound(current_track.sound, channel = 1, repeat = 1, volume = 25) + + for(var/mob/living/M in mobs_in_area(A)) + if(M.mind) + A.play_ambience(M) + + playing = 1 + update_icon() diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index 51676ca04fb..774e7afe1cc 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -426,3 +426,10 @@ var/list/intents = list("help","disarm","grab","hurt") var/turf/targetturf = get_turf(M) if((targetturf.z == sourceturf.z)) M.show_message("\icon[icon] [message]", 1) + +/proc/mobs_in_area(var/area/A) + var/list/mobs = new + for(var/mob/living/M in mob_list) + if(get_area(M) == A) + mobs += M + return mobs diff --git a/icons/obj/jukebox.dmi b/icons/obj/jukebox.dmi new file mode 100644 index 0000000000000000000000000000000000000000..910904970424f60e49b47581930725cd69d90311 GIT binary patch literal 7659 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 literal 0 HcmV?d00001 diff --git a/nano/templates/jukebox.tmpl b/nano/templates/jukebox.tmpl new file mode 100644 index 00000000000..f7fac89ff9f --- /dev/null +++ b/nano/templates/jukebox.tmpl @@ -0,0 +1,19 @@ + + +

Current track: {{:data.current_track}}

+
+ {{:helper.link('Play' , 'play', {'play' : 1}, data.playing == 1 ? 'disabled' : null, null)}} + {{:helper.link('Stop' , 'stop', {'stop' : 1}, data.playing == 0 ? 'disabled' : null, null)}} +
+ +

Available tracks:

+
+ {{for data.tracks}} +
+ {{:helper.link( value.track, 'gear', {'change_track' : 1, 'title' : value.track}, value.track == data.current_track ? 'disabled' : null, null)}} +
+ {{/for}} +
\ No newline at end of file