diff --git a/code/__DEFINES/preferences.dm b/code/__DEFINES/preferences.dm index f8233a4564..676eaa3aff 100644 --- a/code/__DEFINES/preferences.dm +++ b/code/__DEFINES/preferences.dm @@ -15,10 +15,11 @@ #define DISABLE_DEATHRATTLE (1<<12) #define DISABLE_ARRIVALRATTLE (1<<13) #define COMBOHUD_LIGHTING (1<<14) +#define MUSIC_RADIO (1<<15) // Gap in prefs between tg and fortune13 prefs. #define SPLIT_ADMIN_TABS (1<<23) -#define TOGGLES_DEFAULT (SOUND_ADMINHELP|SOUND_MIDI|SOUND_AMBIENCE|SOUND_LOBBY|MEMBER_PUBLIC|INTENT_STYLE|MIDROUND_ANTAG|SOUND_INSTRUMENTS|SOUND_SHIP_AMBIENCE|SOUND_PRAYERS|SOUND_ANNOUNCEMENTS) +#define TOGGLES_DEFAULT (SOUND_ADMINHELP|SOUND_MIDI|MUSIC_RADIO|SOUND_AMBIENCE|SOUND_LOBBY|MEMBER_PUBLIC|INTENT_STYLE|MIDROUND_ANTAG|SOUND_INSTRUMENTS|SOUND_SHIP_AMBIENCE|SOUND_PRAYERS|SOUND_ANNOUNCEMENTS) //Chat toggles #define CHAT_OOC (1<<0) diff --git a/code/_globalvars/lists/objects.dm b/code/_globalvars/lists/objects.dm index 6ed2b95701..9ab52ba8cc 100644 --- a/code/_globalvars/lists/objects.dm +++ b/code/_globalvars/lists/objects.dm @@ -53,3 +53,4 @@ GLOBAL_LIST_EMPTY(money_piles) GLOBAL_LIST_EMPTY(mob_nests) //list of all nests, /obj/structure/nest GLOBAL_LIST_EMPTY(lamppost) //list of all lampposts +GLOBAL_LIST_EMPTY_TYPED(radio_list, /obj/item/radio) //For the radio station. See radio_station.dm diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm index 9f9f636db4..a2fc569aa1 100644 --- a/code/game/objects/items/devices/PDA/PDA.dm +++ b/code/game/objects/items/devices/PDA/PDA.dm @@ -47,6 +47,8 @@ GLOBAL_LIST_EMPTY(PDAs) var/font_index = 0 //This int tells DM which font is currently selected and lets DM know when the last font has been selected so that it can cycle back to the first font when "toggle font" is pressed again. var/font_mode = "font-family:monospace;" //The currently selected font. var/background_color = "#808000" //The currently selected background color. + var/mob/living/radio_holder = null + var/allow_music = FALSE #define FONT_MONO "font-family:monospace;" #define FONT_SHARE "font-family:\"Share Tech Mono\", monospace;letter-spacing:0px;" @@ -98,6 +100,9 @@ GLOBAL_LIST_EMPTY(PDAs) var/list/blocked_pdas var/list/saved_frequencies = list("Common" = FREQ_COMMON) + var/music_channel + var/TimerID + var/obj/item/record_disk/R /obj/item/pda/suicide_act(mob/living/carbon/user) var/deathMessage = msg_input(user) @@ -121,6 +126,11 @@ GLOBAL_LIST_EMPTY(PDAs) set_light(f_lum, f_pow, f_col) GLOB.PDAs += src + GLOB.radio_list += src //Big Iron. Adds the PDA to the global radio list + var/i + for(i = 1; i <= GLOB.radio_list.len; i++) + if(GLOB.radio_list[i] == src) + music_channel = i if(default_cartridge) cartridge = new default_cartridge(src) if(inserted_item) @@ -317,7 +327,10 @@ GLOBAL_LIST_EMPTY(PDAs) dat += "
  • [PDAIMG(notes)]Notekeeper
  • " dat += "
  • [PDAIMG(mail)]Messenger
  • " dat += "
  • [PDAIMG(signaler)]Radio
  • " - + if (R) + dat += "
  • Eject record disk
  • " //Big-iron + dat += "
  • Play record disk
  • " + dat += "
  • Stop record disk
  • " if (cartridge) if (cartridge.access & CART_MANIFEST) dat += "
  • [PDAIMG(notes)]View Crew Manifest
  • " @@ -394,7 +407,6 @@ GLOBAL_LIST_EMPTY(PDAs) dat += "[PDAIMG(mail)]Send / Receive: [toff == 1 ? "Off" : "On"] | " dat += "[PDAIMG(bell)]Set Ringtone | " dat += "[PDAIMG(mail)]Messages
    " - if(cartridge) dat += cartridge.message_header() @@ -465,6 +477,7 @@ GLOBAL_LIST_EMPTY(PDAs) dat += "+" dat += "+" dat += " | Save Frequency

    " + dat += "Allow music: [allow_music?"Allowed":"disallowed"]
    " if(saved_frequencies) dat += "Saved Frequencies" @@ -473,6 +486,25 @@ GLOBAL_LIST_EMPTY(PDAs) dat += "
  • [freq] ([format_frequency(saved_frequencies[freq])])" dat += " (Delete | Rename)
  • " dat += "" + if(9) + if(R) + stopMusic(user) + radio_holder = null + R.forceMove(get_turf(src)) + playsound(src, 'sound/effects/plastic_click.ogg', 100, 0) + R = null + else + to_chat(src.loc, "No record disk inserted!") + mode = 0 + + if(10) + playMusiclocal(user) + mode = 0 + + if(11) + stopMusic(user) + radio_holder = null + mode = 0 else//Else it links to the cart menu proc. Although, it really uses menu hub 4--menu 4 doesn't really exist as it simply redirects to hub. dat += cartridge.generate_menu() @@ -751,7 +783,10 @@ GLOBAL_LIST_EMPTY(PDAs) if(href_list["rspktoggle"]) radio.listening = !radio.listening Boop() - + if(href_list["allowmmusictoggle"]) + allow_music = !allow_music + stopMusic(radio_holder) + Boop() if(href_list["rfreq"]) var/new_frequency = (radio.frequency + text2num(href_list["rfreq"])) if (!radio.freerange || (radio.frequency < MIN_FREE_FREQ || radio.frequency > MAX_FREE_FREQ)) @@ -897,7 +932,7 @@ GLOBAL_LIST_EMPTY(PDAs) if (!signal.data["done"]) to_chat(user, span_notice("ERROR: Server isn't responding.")) if (!silent) - playsound(src, 'sound/machines/terminal_error.ogg', 15, 1) + playsound(src, 'sound/machines/terminal_error.ogg', 35, channel = music_channel) return var/target_text = signal.format_target() @@ -1090,6 +1125,15 @@ GLOBAL_LIST_EMPTY(PDAs) to_chat(user, span_notice("You insert [cartridge] into [src].")) update_icon() playsound(src, 'sound/machines/button.ogg', 50, 1) + if(istype(C, /obj/item/record_disk)) + if(R) + to_chat(user, "A record disk is already inserted!") + return + else + R = C + C.forceMove(src) + playsound(src, 'sound/effects/plastic_click.ogg', 100, 0) + playMusiclocal(user) else if(istype(C, /obj/item/card/id)) var/obj/item/card/id/idcard = C @@ -1216,6 +1260,9 @@ GLOBAL_LIST_EMPTY(PDAs) /obj/item/pda/Destroy() GLOB.PDAs -= src + GLOB.radio_list -= src //Big iron. Removes from global radio list + stopMusic(radio_holder) + radio_holder = null if(istype(id)) QDEL_NULL(id) if(istype(cartridge)) @@ -1315,6 +1362,45 @@ GLOBAL_LIST_EMPTY(PDAs) continue . += P +/obj/item/pda/proc/playMusiclocal(mob/living/user) + if(istype(src.loc, /mob/living)) + user = src.loc + if(item_flags & IN_INVENTORY) + if(allow_music) + playsound(user, R.R.song_path, 100, channel = music_channel) //plays the music to the user + radio_holder = user + to_chat(user, "You play the [R] on your PDA.") + else + to_chat(user, "The [src] is not allowed to play music!") + else + to_chat(user, "The [src] must be in your inventory to play music!") + +/obj/item/pda/proc/playmusic(music_filepath, name_of_music, music_volume) //Plays music at src using the filepath to the audio file. This proc is directly working with the bluespace radio station at radio_station.dm + var/atom/loc_layer = loc + while(istype(loc_layer, /atom/movable)) + if(!istype(loc_layer, /mob/living)) + loc_layer = loc_layer.loc + else + radio_holder = loc_layer + break + if(!loc_layer) //if loc is null then this proc doesn't need to continue + return + if(!istype(loc_layer, /mob/living)) //doesn't need to continue if not on a mob + return + + if(allow_music) //Music player is on + var/mob/living/M = loc_layer + if(istype(M) && M.client) + var/client/C = M.client + if(!(C.prefs.toggles & MUSIC_RADIO)) + return + stopMusic(radio_holder) //stop the previously playing song to make way for the new one + playsound(radio_holder, music_filepath, music_volume, channel = music_channel) //plays the music to the user + to_chat(radio_holder, "[src] beeps into your ears, 'Now playing: [name_of_music].' ") + +/obj/item/pda/proc/stopMusic(mob/user) + playsound(user, 'sound/machines/button.ogg', 50, channel = music_channel) + playsound(user, null, channel = music_channel) #undef PDA_SCANNER_NONE #undef PDA_SCANNER_MEDICAL diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm index 2c92bb4033..54198cd604 100644 --- a/code/game/objects/items/devices/radio/radio.dm +++ b/code/game/objects/items/devices/radio/radio.dm @@ -47,6 +47,12 @@ var/linked_faction = FALSE // Which faction the radio is linked to. var/mob/living/carbon/linked_mob = null // Which mob the radio is checked out to. //fortuna addition end. radio management. + var/music_channel = null //The sound channel the music is playing on. + var/radio_music_file = "" //The file path to the music's audio file + var/music_toggle = TRUE //Toggles whether music will play or not. + var/music_name = "" //Used to display the name of currently playing music. + var/music_playing = FALSE + var/mob/living/radio_holder //stopmusic() will apply to this person /obj/item/radio/suicide_act(mob/living/user) user.visible_message("[user] starts bouncing [src] off [user.p_their()] head! It looks like [user.p_theyre()] trying to commit suicide!") @@ -97,6 +103,7 @@ LAZYREMOVE(GLOB.bos_radios, src) if(FACTION_ENCLAVE) LAZYREMOVE(GLOB.enclave_radios, src) + GLOB.radio_list -= src //Big-Iron, removes radio from radio list lmao remove_radio_all(src) //Just to be sure QDEL_NULL(wires) QDEL_NULL(keyslot) @@ -104,6 +111,18 @@ /obj/item/radio/Initialize() wires = new /datum/wires/radio(src) + var/obj/item/pda/pdloc = loc + if(!istype(src, /obj/item/radio/intercom) && !istype(pdloc)) //Intercoms playing music is useless + GLOB.radio_list += src //Big iron. Adds the radio to the global radio list for usage in radio_station.dm + var/i + for(i = 1; i <= GLOB.radio_list.len; i++) + if(GLOB.radio_list[i] == src) + music_channel = i //I hope that over 1,000 radios are never initialized. + /* Allow me to explain why. There are 1,024 usable channels. The top ~10 + are preserved for ambience, admin music, etc. The other 1,000 are unused (to my knowledge) + and so to allow radios to play their own music without inferefering with other sounds, I give + each radio their own channel to play music on. This way the user can also stop the music + playing from their radio (headsets, etc.) without stopping the music of someone else's radio. */ if(prison_radio) wires.cut(WIRE_TX) // OH GOD WHY secure_radio_connections = new @@ -161,6 +180,7 @@ data["broadcasting"] = broadcasting data["listening"] = listening + data["music_toggle"] = music_toggle data["frequency"] = frequency data["minFrequency"] = freerange ? MIN_FREE_FREQ : MIN_FREQ data["maxFrequency"] = freerange ? MAX_FREE_FREQ : MAX_FREQ @@ -228,6 +248,10 @@ else recalculateChannels() . = TRUE + if("streammusic") + music_toggle = !music_toggle + stopmusic(radio_holder) + . = TRUE /obj/item/radio/talk_into(atom/movable/M, message, channel, list/spans, datum/language/language) if(HAS_TRAIT(M, TRAIT_SIGN_LANG)) //Forces Sign Language users to wear the translation gloves to speak over radios @@ -410,6 +434,102 @@ to_chat(user, "The radio can no longer be modified or attached!") else return ..() + +/obj/item/radio/AltClick(mob/user) //Big Iron + ..() + if(!istype(user) || !Adjacent(user) || user.incapacitated()) + return + if(user.a_intent == INTENT_HARM) + if(music_toggle) + music_toggle = 0 + stopmusic(radio_holder) + to_chat(user, "[src]'s music player is now OFF. ") + else + music_toggle = 1 + to_chat(user, "[src]'s music player is now ON. ") + return + +/obj/item/radio/proc/avoiding_a_sleep(mob/living/user, music_filepath, name_of_music, music_volume) + music_name = name_of_music + to_chat(user, "[src] beeps into your ears, 'Now playing: [music_name].' ") + if(user.client) + var/mob/M = user + var/client/C = M.client + if(!(C.prefs.toggles & MUSIC_RADIO)) + to_chat(user, "[src] your preferences stopped [music_name] from playing!.' ") + return + music_playing = TRUE + playsound(user, music_filepath, music_volume, channel = music_channel) //plays the music to the user + update_icon() + +/obj/item/radio/proc/playmusic(music_filepath, name_of_music, music_volume) //Plays music at src using the filepath to the audio file. This proc is directly working with the bluespace radio station at radio_station.dm + radio_music_file = music_filepath + + var/atom/loc_layer = loc + while(istype(loc_layer, /atom/movable)) + if(!istype(loc_layer, /mob/living)) + loc_layer = loc_layer.loc + else + radio_holder = loc_layer + break + if(!loc_layer) //if loc is null then this proc doesn't need to continue + return + if(!istype(loc_layer, /mob/living)) //doesn't need to continue if not on a mob + return + + if(music_toggle == 1) //Music player is on + if(istype(src, /obj/item/radio/headset)) + var/mob/living/carbon/wearer = radio_holder + if(!(wearer.ears == src)) //only want headsets to play music if they're equipped + return + stopmusic(radio_holder) //stop the previously playing song to make way for the new one + addtimer(CALLBACK(src, .proc/avoiding_a_sleep, radio_holder, music_filepath, name_of_music, music_volume), 10) + +/obj/item/radio/proc/stopmusic(mob/living/user, music_turnoff_message_type) + if(music_playing) + music_playing = FALSE + update_icon() + playsound(user, null, channel = music_channel) + playsound(user, 'sound/machines/buzz-sigh.ogg', 50, channel = music_channel) + music_name = "" + switch(music_turnoff_message_type) + if(1) + audible_message("[src] beeps, '[src] removed, turning off music.' ") + if(2) + src.audible_message("[src] beeps, 'Music toggled off.' ") //Unused message + if(3) + src.audible_message("[src] beeps, 'Signal interrupted.' ") + music_playing = FALSE + +/obj/item/radio/dropped(mob/user) + ..() + addtimer(CALLBACK(src, .proc/droppedStopMusic, user), 3) + +/obj/item/radio/proc/droppedStopMusic(mob/user) + var/i + for(i = 1, i <= user.contents.len, i++) + if(user.contents[i] == src) + return + if(item_flags & IN_INVENTORY) + return + if(determineIfInMob(user) == TRUE) + return + stopmusic(user, 1) + +/obj/item/radio/proc/determineIfInMob(mob/user) + var/obj/itemholder = src + var/mob/M = src.loc + while(M && !istype(M, /mob/living)) + M = itemholder + if(!M) + return FALSE + itemholder = itemholder.loc + if(M == user) + return TRUE + else + return FALSE + +//Big-iron end /* /obj/item/radio/emp_act(severity) . = ..() diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index f349b32d10..53ae6bf4ff 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -664,6 +664,7 @@ Records disabled until a use for them is found dat += "
    " dat += "Play Admin MIDIs: [(toggles & SOUND_MIDI) ? "Enabled":"Disabled"]
    " dat += "Play Lobby Music: [(toggles & SOUND_LOBBY) ? "Enabled":"Disabled"]
    " + dat += "Stream radio music: [(toggles & MUSIC_RADIO) ? "Enabled":"Disabled"]
    " dat += "See Pull Requests: [(chat_toggles & CHAT_PULLR) ? "Enabled":"Disabled"]
    " dat += "
    " if(user.client) @@ -2542,6 +2543,9 @@ Records disabled until a use for them is found if("ghost_ears") chat_toggles ^= CHAT_GHOSTEARS + if("music_streaming") + toggles ^= MUSIC_RADIO + if("ghost_sight") chat_toggles ^= CHAT_GHOSTSIGHT diff --git a/code/modules/client/preferences_toggles.dm b/code/modules/client/preferences_toggles.dm index 8c637f36c9..6e164c4708 100644 --- a/code/modules/client/preferences_toggles.dm +++ b/code/modules/client/preferences_toggles.dm @@ -236,6 +236,19 @@ TOGGLE_CHECKBOX(/datum/verbs/menu/Settings/Sound, toggleprayersounds)() C?.tgui_panel?.stop_music() SSblackbox.record_feedback("nested tally", "preferences_verb", 1, list("Stop Self Sounds")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! +TOGGLE_CHECKBOX(/datum/verbs/menu/Settings/Sound, toggleradiomusic)() + set name = "Hear/Silence Radio Music" + set category = "Preferences" + set desc = "Hear music streamed by radio stations" + usr.client.prefs.toggles ^= MUSIC_RADIO + usr.client.prefs.save_preferences() + if(usr.client.prefs.toggles & MUSIC_RADIO) + to_chat(usr, "You will now hear songs through radios.") + else + to_chat(usr, "You will no longer hear sounds played in radios") + SSblackbox.record_feedback("nested tally", "preferences_verb", 1, list("Toggle Radio Music", "[usr.client.prefs.toggles & MUSIC_RADIO ? "Enabled" : "Disabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! +/datum/verbs/menu/Settings/Sound/toggleradiomusic/Get_checked(client/C) + return C.prefs.toggles & MUSIC_RADIO TOGGLE_CHECKBOX(/datum/verbs/menu/Settings, listen_ooc)() set name = "Show/Hide OOC" diff --git a/code/modules/jobs/job_types/kebab.dm b/code/modules/jobs/job_types/kebab.dm index 001b096b7d..4ba01ee01b 100644 --- a/code/modules/jobs/job_types/kebab.dm +++ b/code/modules/jobs/job_types/kebab.dm @@ -977,6 +977,7 @@ ears = /obj/item/radio/headset/headset_town glasses = /obj/item/clothing/glasses/sunglasses/big r_pocket = /obj/item/gun/ballistic/revolver/police + l_pocket = /obj/item/circuitboard/machine/radio_station shoes = /obj/item/clothing/shoes/laceup backpack = /obj/item/storage/backpack/satchel/leather backpack_contents = list( diff --git a/fortune13.dme b/fortune13.dme index 749e2ecace..ae360861f4 100644 --- a/fortune13.dme +++ b/fortune13.dme @@ -3701,6 +3701,8 @@ #include "modular_BD2\kitchen_50s\code\kitchen_50s.dm" #include "modular_BD2\legio_invicta\code\legio_invicta.dm" #include "modular_BD2\mortar\code\mortar.dm" +#include "modular_big-iron\code\game\machinery\radio_station.dm" +#include "modular_big-iron\code\game\objects\circuitboards\radio_station.dm" #include "modular_citadel\code\datums\components\souldeath.dm" #include "modular_citadel\code\datums\status_effects\chems.dm" #include "modular_citadel\code\game\objects\cit_screenshake.dm" diff --git a/modular_big-iron/code/game/machinery/radio_station.dm b/modular_big-iron/code/game/machinery/radio_station.dm new file mode 100644 index 0000000000..96f3122283 --- /dev/null +++ b/modular_big-iron/code/game/machinery/radio_station.dm @@ -0,0 +1,156 @@ +//****************************************** +//WHEN ADDING NEW MUSIC, ADD THE MUSIC'S NAME TO _globalvars/lists/objects.dm global_music_list and then scroll down to the switch(music_name) part +//Make sure you put it in alphabetical order and also update the switch(music_file) part at the disk burner's attack_hand proc with whatever music you added +//****************************************** + +/obj/machinery/radio_station + name = "radio station" + desc = "A specially equipped radio station to broadcast music to every radio in a the waste. Comes pre-coded with over 30 songs!" + icon = 'icons/fallout/machines/radio.dmi' + icon_state = "gannets_machine21" + max_integrity = 150 + anchored = TRUE + density = TRUE + use_power = IDLE_POWER_USE + idle_power_usage = 2 + armor = list("melee" = 20, "bullet" = 20, "laser" = 20, "energy" = 20, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 20) + circuit = /obj/item/circuitboard/machine/radio_station + light_color = LIGHT_COLOR_GREEN + var/datum/track/selectedtrack = "None" //File path to the music's audio file + var/selectedtrackname = "none" +// var/datum/track = null //This is the name of the song, not the file name. This is what shows up at the top of the music selection. + var/list/music_list //List of music that can be played. Only the most based songs may be added. + var/cooldowntime + var/obj/item/record_disk/R //The record disk that's currently playing music + var/can_eject_disk = 1 + var/ready_to_delete = 0 //For Destroy() + var/brightness_on = 1 + var/volume = 35 //the volume that music plays at + +/obj/machinery/radio_station/Initialize() + . = ..() + music_list = SSjukeboxes.songs + update_icon() + +/obj/machinery/radio_station/attack_hand(mob/living/user) + ..() + var/machinesound = 'sound/machines/doorclick.ogg' + playsound(src, machinesound, 100, 1) + if(R) + if(can_eject_disk) + update_icon() + playsound(src, 'sound/effects/plastic_click.ogg', 100, 0) + R.forceMove(get_turf(src)) + R = null + stopRadioMusic() + return + else + to_chat(user, "You must wait to eject the record disk!") + return + + if(stat & (NOPOWER|BROKEN) || . & EMP_PROTECT_SELF) + update_icon() + return + if(cooldowntime > world.time) + to_chat(user, "The broadcasting antenna needs time to recharge! It will be ready in [DisplayTimeText(cooldowntime - world.time)].") + return + var/list/songnames = list() + if(music_list.len) + for(var/i = 1, i <= music_list.len, i++) + var/datum/track/CT = music_list[i] + var/ctsn = "[CT.song_name]" + songnames += ctsn + var/datum/track/cooming = input(user, "Last played music: [selectedtrackname]", "Available Music") as null|anything in songnames + if(!user.Adjacent(src)) + to_chat(user, "You are too far away!") + return + if(!cooming) + return + if(cooldowntime > world.time) + to_chat(user, "The broadcasting antenna needs time to recharge! It will be ready in [DisplayTimeText(cooldowntime - world.time)].") + return + for(var/datum/track/S in music_list) + if(S.song_name == cooming)//agghggagaghaghah + selectedtrack = S.song_path + selectedtrackname = S.song_name + continue + playsound(src, machinesound, 100, 1) + playMusicToRadios(user) + +/obj/machinery/radio_station/attackby(obj/item/I, mob/living/user) + if(istype(I, /obj/item/record_disk)) + if(cooldowntime > world.time) + to_chat(user, "The broadcasting antenna needs time to recharge! It will be ready in [DisplayTimeText(cooldowntime - world.time)].") + return + if(!R) + R = I + I.forceMove(src) + playsound(src, 'sound/effects/plastic_click.ogg', 100, 0) + selectedtrack = R.R.song_path + if(R.R.song_name != "CUSTOM") + selectedtrack = R.R.song_path + selectedtrackname = R.R.song_name + else + selectedtrack = R.R.song_path + selectedtrackname = "A custom song!f" + playMusicToRadios(user) + return + else + to_chat(user, "There is already a record disk in the [src]!") + return + ..() + +/obj/machinery/radio_station/proc/playMusicToRadios(mob/living/user) + if(stat & (NOPOWER|BROKEN) || . & EMP_PROTECT_SELF) + update_icon() + return + if(cooldowntime > world.time) + to_chat(user, "The broadcasting antenna needs time to recharge! It will be ready in [DisplayTimeText(cooldowntime - world.time)].") + return + + var/store_resistance_flags = resistance_flags + resistance_flags = INDESTRUCTIBLE //Need to do this so that it can't be destroyed before the music starts playing. + + can_eject_disk = 0 + cooldowntime = world.time + 500 + for(var/obj/item/radio/R in GLOB.radio_list) //Calls the playmusic() proc for every radio in radio_list (everyone) + R.playmusic(selectedtrack, selectedtrackname, volume) + for(var/obj/item/pda/R in GLOB.radio_list) //Calls the playmusic() proc for every radio in radio_list (everyone) + R.playmusic(selectedtrack, selectedtrackname, volume) + + src.audible_message("[src] beeps, 'Now broadcasting: [selectedtrackname]' ") + + resistance_flags = store_resistance_flags + + can_eject_disk = 1 + if(stat & (NOPOWER|BROKEN) || . & EMP_PROTECT_SELF) //Need to check again in case the radio station is destroyed while this proc is in progress + update_icon() + stopRadioMusic() + return + + +/obj/machinery/radio_station/proc/stopRadioMusic() + var/i + for(i = 1; i <= GLOB.radio_list.len; i++) //This time it will stop the music for every radio listening to this radio station. + if(!istype(GLOB.radio_list[i], /obj/item/pda)) + GLOB.radio_list[i].stopmusic(GLOB.radio_list[i].radio_holder, 3) + +/obj/machinery/radio_station/Destroy() + stopRadioMusic() + ..() + +/obj/machinery/radio_station/update_icon() + ..() + if(!(stat & (NOPOWER|BROKEN) || . & EMP_PROTECT_SELF)) + luminosity = 1 + set_light(brightness_on) + return + luminosity = 0 + set_light(0) + +/obj/machinery/radio_station/power_change() + . = ..() + if(stat & (NOPOWER|BROKEN) || . & EMP_PROTECT_SELF) + set_light(0) + else + set_light(brightness_on) diff --git a/modular_big-iron/code/game/objects/circuitboards/radio_station.dm b/modular_big-iron/code/game/objects/circuitboards/radio_station.dm new file mode 100644 index 0000000000..76af946c42 --- /dev/null +++ b/modular_big-iron/code/game/objects/circuitboards/radio_station.dm @@ -0,0 +1,6 @@ +/obj/item/circuitboard/machine/radio_station + name = "circuit board (radio station)" + build_path = /obj/machinery/radio_station + req_components = list( + /obj/item/stock_parts/cell = 1, + /obj/item/stock_parts/capacitor = 2) diff --git a/tgui/packages/tgui/interfaces/Radio.js b/tgui/packages/tgui/interfaces/Radio.js index 738826ba63..06c9ad0d52 100644 --- a/tgui/packages/tgui/interfaces/Radio.js +++ b/tgui/packages/tgui/interfaces/Radio.js @@ -18,6 +18,7 @@ export const Radio = (props, context) => { useCommand, subspace, subspaceSwitchable, + music_toggle, } = data; const tunedChannel = RADIO_CHANNELS .find(channel => channel.freq === frequency); @@ -80,6 +81,12 @@ export const Radio = (props, context) => { icon={broadcasting ? 'microphone' : 'microphone-slash'} selected={broadcasting} onClick={() => act('broadcast')} /> +