diff --git a/code/game/communications.dm b/code/game/communications.dm index a980f3d751d..ac4576042c2 100644 --- a/code/game/communications.dm +++ b/code/game/communications.dm @@ -134,8 +134,23 @@ var/list/radiochannels = list( "Syndicate" = 1213, "Supply" = 1347, "Service" = 1349, - "AI Private" = 1447, + "AI Private" = 1447 ) + +var/list/radiochannelsreverse = list( + "1459" = "Common", + "1351" = "Science", + "1353" = "Command", + "1355" = "Medical", + "1357" = "Engineering", + "1359" = "Security", + "1441" = "Deathsquad", + "1213" = "Syndicate", + "1347" = "Supply", + "1349" = "Service", + "1447" = "AI Private" +) + //depenging helpers var/const/SYND_FREQ = 1213 //nuke op frequency, coloured dark brown in chat window var/const/SUPP_FREQ = 1347 //supply, coloured light brown in chat window diff --git a/code/game/machinery/doppler_array.dm b/code/game/machinery/doppler_array.dm index 6a1518e311b..ece99b86d64 100644 --- a/code/game/machinery/doppler_array.dm +++ b/code/game/machinery/doppler_array.dm @@ -7,7 +7,7 @@ var/list/doppler_arrays = list() icon_state = "tdoppler" density = 1 anchored = 1 - + languages = HUMAN /obj/machinery/doppler_array/New() ..() @@ -74,10 +74,11 @@ var/list/doppler_arrays = list() if(devastation_range < orig_dev_range || heavy_impact_range < orig_heavy_range || light_impact_range < orig_light_range) messages += "Theoretical: Epicenter radius: [orig_dev_range]. Outer radius: [orig_heavy_range]. Shockwave radius: [orig_light_range]." - for(var/mob/O in hearers(src, null)) - for(var/message in messages) - O.show_message("[src] states coldly, \"[message]\"",2) + for(var/message in messages) + say(message) +/obj/machinery/doppler_array/say_quote(text) + return "states coldly, \"[text]\"" /obj/machinery/doppler_array/power_change() if(stat & BROKEN) diff --git a/code/game/machinery/newscaster.dm b/code/game/machinery/newscaster.dm index 1ea98bb5c4b..cc7ce49f772 100644 --- a/code/game/machinery/newscaster.dm +++ b/code/game/machinery/newscaster.dm @@ -113,6 +113,7 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co desc = "A standard Nanotrasen-licensed newsfeed handler for use in commercial space stations. All the news you absolutely have no use for, in one place!" icon = 'icons/obj/terminals.dmi' icon_state = "newscaster_normal" + languages = HUMAN var/isbroken = 0 //1 if someone banged it with something heavy var/ispowered = 1 //starts powered, changes with power_change() //var/list/datum/feed_channel/channel_list = list() //This list will contain the names of the feed channels. Each name will refer to a data region where the messages of the feed channels are stored. @@ -1013,10 +1014,8 @@ obj/item/weapon/newspaper/attackby(obj/item/weapon/W as obj, mob/user as mob) // return //bode well with a newscaster network of 10+ machines. Let's just return it, as it's added in the machines list. /obj/machinery/newscaster/proc/newsAlert(channel) //This isn't Agouri's work, for it is ugly and vile. - var/turf/T = get_turf(src) //Who the fuck uses spawn(600) anyway, jesus christ - if(channel) - for(var/mob/O in hearers(world.view-1, T)) - O.show_message("[src.name] beeps, \"Breaking news from [channel]!\"",2) + if(channel) //Who the fuck uses spawn(600) anyway, jesus christ + say("Breaking news from [channel]!") src.alert = 1 src.update_icon() spawn(300) @@ -1024,7 +1023,9 @@ obj/item/weapon/newspaper/attackby(obj/item/weapon/W as obj, mob/user as mob) src.update_icon() playsound(src.loc, 'sound/machines/twobeep.ogg', 75, 1) else - for(var/mob/O in hearers(world.view-1, T)) - O.show_message("[src.name] beeps, \"Attention! Wanted issue distributed!\"",2) + say("Attention! Wanted issue distributed!") playsound(src.loc, 'sound/machines/warning-buzzer.ogg', 75, 1) - return \ No newline at end of file + return + +/obj/machinery/newscaster/say_quote(text) + return "beeps, \"[text]\"" diff --git a/code/game/machinery/requests_console.dm b/code/game/machinery/requests_console.dm index 851fd8c7055..e9e821238cd 100644 --- a/code/game/machinery/requests_console.dm +++ b/code/game/machinery/requests_console.dm @@ -12,6 +12,7 @@ var/list/obj/machinery/requests_console/allConsoles = list() anchored = 1 icon = 'icons/obj/terminals.dmi' icon_state = "req_comp0" + languages = HUMAN var/department = "Unknown" //The list of all departments on the station (Determined from this variable on each unit) Set this to the same thing if you want several consoles in one department var/list/messages = list() //List of all messages var/departmentType = 0 @@ -317,8 +318,7 @@ var/list/obj/machinery/requests_console/allConsoles = list() Console.update_icon() if(!Console.silent) playsound(Console.loc, 'sound/machines/twobeep.ogg', 50, 1) - for (var/mob/O in hearers(5, Console.loc)) - O.show_message("\icon[Console] *The Requests Console beeps: 'PRIORITY Alert in [department]'") + say("PRIORITY Alert in [department]!") Console.messages += "High Priority
From: [department]
[sending]" var/obj/item/weapon/paper/slip = new /obj/item/weapon/paper(Console.loc) // Same message, but without the hyperlink. @@ -331,8 +331,7 @@ var/list/obj/machinery/requests_console/allConsoles = list() Console.update_icon() if(1) // This is EXTREMELY important, so beep. playsound(Console.loc, 'sound/machines/twobeep.ogg', 50, 1) - for (var/mob/O in hearers(7, Console.loc)) - O.show_message("\icon[Console] *The Requests Console yells: 'EXTREME PRIORITY alert in [department]'") + say("!!!EXTREME PRIORITY ALERT IN [department]!!!") Console.messages += "!!!Extreme Priority!!!
From: [department]
[sending]" var/obj/item/weapon/paper/slip = new /obj/item/weapon/paper(Console.loc) // Same message, but without the hyperlink. @@ -349,8 +348,7 @@ var/list/obj/machinery/requests_console/allConsoles = list() Console.update_icon() if(!Console.silent) playsound(Console.loc, 'sound/machines/twobeep.ogg', 50, 1) - for (var/mob/O in hearers(4, Console.loc)) - O.show_message("\icon[Console] *The Requests Console beeps: 'Message from [department]'") + say("Message from [department].") Console.messages += "From: [department]
[sending]" var/obj/item/weapon/paper/slip = new /obj/item/weapon/paper(Console.loc) slip.info = "From: [department]
[sending]" @@ -365,8 +363,7 @@ var/list/obj/machinery/requests_console/allConsoles = list() else messages += "To: [dpt]
[sending]" else - for (var/mob/O in hearers(4, src.loc)) - O.show_message("\icon[src] *The Requests Console beeps: 'NOTICE: No server detected!'") + say("NOTICE: No server detected!") //Handle screen switching @@ -410,6 +407,13 @@ var/list/obj/machinery/requests_console/allConsoles = list() updateUsrDialog() return +/obj/machinery/say_quote(var/text) + var/ending = copytext(text, length(text) - 2) + if (ending == "!!!") + return "yells, \"[text]\"" + + return "beeps, \"[text]\"" + /obj/machinery/requests_console/attackby(var/obj/item/weapon/O as obj, var/mob/user as mob) if (istype(O, /obj/item/weapon/crowbar)) if(open) diff --git a/code/game/machinery/telecomms/broadcaster.dm b/code/game/machinery/telecomms/broadcaster.dm index 1748e91c8eb..0701bb9de84 100644 --- a/code/game/machinery/telecomms/broadcaster.dm +++ b/code/game/machinery/telecomms/broadcaster.dm @@ -143,15 +143,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept signal.data["vmask"], signal.data["radio"], signal.data["message"], signal.data["name"], signal.data["job"], - signal.data["realname"],, signal.data["compression"], list(0), signal.frequency) - else - if(intercept) - Broadcast_Message(signal.data["mob"], - signal.data["vmask"], - signal.data["radio"], signal.data["message"], - signal.data["name"], signal.data["job"], - signal.data["realname"], 3, signal.data["compression"], list(0), signal.frequency) - + signal.data["realname"],, signal.data["compression"], list(0, z), signal.frequency) /** @@ -213,11 +205,14 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept var/vmask, var/obj/item/device/radio/radio, var/message, var/name, var/job, var/realname, var/data, var/compression, var/list/level, var/freq) + message = copytext(message, 1, MAX_BROADCAST_LEN) + if(!message) return - world << data + var/list/radios = list() + var/atom/movable/virtualspeaker/virt = new(null) //fuck this code. virt.name = name virt.job = job @@ -247,20 +242,18 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept if(R.receive_range(freq, level) > -1) radios += R - else if(data == 3) - - for(var/obj/item/device/radio/R in all_radios["[SYND_FREQ]"]) - if(R.receive_range(SYND_FREQ, level) > -1) - radios += R - // --- Broadcast to ALL radio devices --- else - world << "radios:" for(var/obj/item/device/radio/R in all_radios["[freq]"]) if(R.receive_range(freq, level) > -1) radios += R + var/freqtext = num2text(freq) + for(var/obj/item/device/radio/R in all_radios["[SYND_FREQ]"]) //syndicate radios use magic that allows them to hear everything. this was already the case, now it just doesn't need the allinone anymore. solves annoying bugs that aren't worth solving. + if(R.receive_range(SYND_FREQ, list(R.z)) > -1 && freqtext in radiochannelsreverse) + radios |= R + // Get a list of mobs who can hear from the radios we collected. var/list/receive = get_mobs_in_radio_ranges(radios) //this includes all hearers. @@ -268,7 +261,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept if (R.client && !(R.client.prefs.toggles & CHAT_RADIO)) //Adminning with 80 people on can be fun when you're trying to talk and all you can hear is radios. receive -= R - var/rendered = radio.compose_message(AM, AM.languages, message, freq) //The object this is called on is arbitrary as long as it's not an AI, using the radio just lets met advoid having to make a new atom/movable to call this on. + var/rendered = virt.compose_message(virt, virt.languages, message, freq) //Always call this on the virtualspeaker to advoid issues. for(var/atom/movable/hearer in receive) hearer.Hear(rendered, virt, AM.languages, message, freq) diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm index 50da8e4965b..076992e12a0 100644 --- a/code/game/machinery/vending.dm +++ b/code/game/machinery/vending.dm @@ -14,6 +14,7 @@ layer = 2.9 anchored = 1 density = 1 + languages = HUMAN var/active = 1 //No sales pitches if off! var/vend_ready = 1 //Are we ready to vend?? Is it time?? var/vend_delay = 10 //How long does it take to vend? @@ -406,8 +407,10 @@ if(!message) return - visible_message("[src] beeps, \"[message]\"") + say(message) +/obj/machinery/vending/say_quote(text) + return "beeps, \"[text]\"" /obj/machinery/vending/power_change() if(stat & BROKEN) diff --git a/code/game/objects/items/devices/radio/headset.dm b/code/game/objects/items/devices/radio/headset.dm index 1754b162f7f..57523e21956 100644 --- a/code/game/objects/items/devices/radio/headset.dm +++ b/code/game/objects/items/devices/radio/headset.dm @@ -26,15 +26,9 @@ ..() /obj/item/device/radio/headset/receive_range(freq, level) - world << "receive_range() called" if(ishuman(src.loc)) var/mob/living/carbon/human/H = src.loc if(H.ears == src) - world << "calling ..()" - world << freq - for(var/wub in level) - world << wub - world << H return ..(freq, level) return -1 diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm index af21cdd5646..6f3b3039049 100644 --- a/code/game/objects/items/devices/radio/radio.dm +++ b/code/game/objects/items/devices/radio/radio.dm @@ -249,6 +249,7 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use var/real_name = M.name // mob's real name var/mobkey = "none" // player key associated with mob var/voicemask = 0 // the speaker is wearing a voice mask + var/voice = M.GetVoice() // Why reinvent the wheel when there is a proc that does nice things already if(ismob(M)) var/mob/speaker = M real_name = speaker.real_name @@ -261,7 +262,6 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use // --- Human: use their job as seen on the crew manifest - makes it unneeded to carry an ID for an AI to see their job if (ishuman(M)) - var/voice = M.GetVoice() // Why reinvent the wheel when there is a proc that does nice things already var/datum/data/record/findjob = find_record("name", voice, data_core.general) if(voice != real_name) @@ -310,7 +310,7 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use "mob" = M, // store a reference to the mob "mobtype" = M.type, // the mob's type "realname" = real_name, // the mob's real name - "name" = displayname, // the mob's display name + "name" = voice, // the mob's display name "job" = jobname, // the mob's job "key" = mobkey, // the mob's key "vmask" = voicemask, // 1 if the mob is using a voice gas mask diff --git a/code/game/objects/items/devices/taperecorder.dm b/code/game/objects/items/devices/taperecorder.dm index fba2462307a..3945db0dd83 100644 --- a/code/game/objects/items/devices/taperecorder.dm +++ b/code/game/objects/items/devices/taperecorder.dm @@ -183,19 +183,16 @@ break if(mytape.storedinfo.len < i) break - var/turf/T = get_turf(src) - T.visible_message("Tape Recorder: [mytape.storedinfo[i]]") + say(mytape.storedinfo[i]) if(mytape.storedinfo.len < i + 1) playsleepseconds = 1 sleep(10) - T = get_turf(src) - T.visible_message("Tape Recorder: End of recording.") + say("End of recording.") else playsleepseconds = mytape.timestamp[i + 1] - mytape.timestamp[i] if(playsleepseconds > 14) sleep(10) - T = get_turf(src) - T.visible_message("Tape Recorder: Skipping [playsleepseconds] seconds of silence") + say("Skipping [playsleepseconds] seconds of silence") playsleepseconds = 1 i++ @@ -288,4 +285,4 @@ //Random colour tapes /obj/item/device/tape/random/New() - icon_state = "tape_[pick("white", "blue", "red", "yellow", "purple")]" \ No newline at end of file + icon_state = "tape_[pick("white", "blue", "red", "yellow", "purple")]" diff --git a/code/game/say.dm b/code/game/say.dm index b283a8546c0..18b054aeb76 100644 --- a/code/game/say.dm +++ b/code/game/say.dm @@ -17,8 +17,9 @@ return 1 /atom/movable/proc/send_speech(message, range) + var/rendered = compose_message(src, languages, message) for(var/atom/movable/AM in get_hearers_in_view(range, src)) - AM.Hear(message, src, languages, message) + AM.Hear(rendered, src, languages, message) /atom/movable/proc/compose_message(atom/movable/speaker, message_langs, raw_message, radio_freq) //This proc uses text() because it is faster than appending strings. Thanks BYOND. diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index 384b2171c29..2c65b03a1c8 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -494,17 +494,19 @@ var/list/admin_verbs_hideable = list( /client/proc/make_sound(var/obj/O in world) set category = "Special Verbs" - set name = "Make Sound" - set desc = "Display a message to everyone who can hear the target" - if(O) + set name = "Object Say" + set desc = "Makes an object say something." + if(istype(O)) var/message = input("What do you want the message to be?", "Make Sound") as text|null if(!message) return - for (var/mob/V in hearers(O)) - V.show_message(message, 2) - log_admin("[key_name(usr)] made [O] at [O.x], [O.y], [O.z]. make a sound") - message_admins("\blue [key_name_admin(usr)] made [O] at [O.x], [O.y], [O.z]. make a sound", 1) - feedback_add_details("admin_verb","MS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + var/templanguages = O.languages + O.languages |= ALL + O.say(message) + O.languages = templanguages + log_admin("[key_name(usr)] made [O] at [O.x], [O.y], [O.z]. say [message]") + message_admins("\blue [key_name_admin(usr)] made [O] at [O.x], [O.y], [O.z]. say [message]", 1) + feedback_add_details("admin_verb","OS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! /client/proc/togglebuildmodeself() diff --git a/code/modules/mob/living/carbon/human/say.dm b/code/modules/mob/living/carbon/human/say.dm index 7b170246ae9..205decd4442 100644 --- a/code/modules/mob/living/carbon/human/say.dm +++ b/code/modules/mob/living/carbon/human/say.dm @@ -69,12 +69,10 @@ special_voice = new_voice return - /mob/living/carbon/human/proc/UnsetSpecialVoice() special_voice = "" return - /mob/living/carbon/human/proc/GetSpecialVoice() return special_voice diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm index 9a0b1737a48..4b5ecff807d 100644 --- a/code/modules/mob/living/say.dm +++ b/code/modules/mob/living/say.dm @@ -77,10 +77,17 @@ var/list/department_radio_keys = list( /mob/living/say(message, bubble_type) message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN)) + if(stat == DEAD) + say_dead(message) + return + + if(stat) + return + if(check_emote(message)) return - if(!can_speak_basic(message) || stat) //Stat is seperate so I can handle whispers properly. + if(!can_speak_basic(message)) //Stat is seperate so I can handle whispers properly. return var/message_mode = get_message_mode(message) @@ -127,7 +134,7 @@ var/list/department_radio_keys = list( else deaf_message = "You can't hear yourself!" deaf_type = 2 // Since you should be able to hear yourself without looking - if(!(message_langs & languages) && !force_compose) //force_compose is so AIs don't end up without their hrefs. + if(!(message_langs & languages) || force_compose) //force_compose is so AIs don't end up without their hrefs. message = compose_message(speaker, message_langs, raw_message, radio_freq) show_message(message, 2, deaf_message, deaf_type) return message @@ -172,10 +179,6 @@ var/list/department_radio_keys = list( if(!message || message == "") return - if(stat == DEAD) - say_dead(message) - return - if(client) if(client.prefs.muted & MUTE_IC) src << "You cannot speak in IC (muted)." @@ -201,8 +204,9 @@ var/list/department_radio_keys = list( return 1 /mob/living/proc/check_emote(message) - if (copytext(message, 1, 2) == "*") - return emote(copytext(message, 2)) + if(copytext(message, 1, 2) == "*") + emote(copytext(message, 2)) + return 1 /mob/living/proc/get_message_mode(message) if(copytext(message, 1, 2) == ";") diff --git a/code/modules/mob/living/silicon/ai/say.dm b/code/modules/mob/living/silicon/ai/say.dm index 3119ede0dcb..4e1a3315ad0 100644 --- a/code/modules/mob/living/silicon/ai/say.dm +++ b/code/modules/mob/living/silicon/ai/say.dm @@ -4,7 +4,7 @@ return ..(message) -/mob/living/silicon/ai/compose_track_href(message, atom/movable/speaker, message_langs, raw_message, radio_freq) +/mob/living/silicon/ai/compose_track_href(atom/movable/speaker, message_langs, raw_message, radio_freq) //this proc assumes that the message originated from a radio. if the speaker is not a virtual speaker this will probably fuck up hard. var/mob/M = speaker.GetSource() var/obj/item/device/radio = speaker.GetRadio() @@ -15,9 +15,9 @@ return "" return "" -/mob/living/silicon/ai/compose_job(message, atom/movable/speaker, message_langs, raw_message, radio_freq) +/mob/living/silicon/ai/compose_job(atom/movable/speaker, message_langs, raw_message, radio_freq) //Also includes the for AI hrefs, for convenience. - return " [radio_freq ? "(" + speaker.GetJob() + ")" : ""]" + "[speaker.GetSource() ? "" : ""] " + return " [radio_freq ? "(" + speaker.GetJob() + ")" : ""]" + "[speaker.GetSource() ? "" : ""]" /mob/living/silicon/ai/say_quote(var/text) var/ending = copytext(text, length(text)) diff --git a/code/modules/mob/living/silicon/robot/emote.dm b/code/modules/mob/living/silicon/robot/emote.dm index 0a902e97fad..005ff990ec6 100644 --- a/code/modules/mob/living/silicon/robot/emote.dm +++ b/code/modules/mob/living/silicon/robot/emote.dm @@ -207,4 +207,4 @@ else for(var/mob/O in hearers(src, null)) O.show_message(message, m_type) - return \ No newline at end of file + return diff --git a/code/modules/mob/living/simple_animal/parrot.dm b/code/modules/mob/living/simple_animal/parrot.dm index 16f62f3628d..feac6bc38f1 100644 --- a/code/modules/mob/living/simple_animal/parrot.dm +++ b/code/modules/mob/living/simple_animal/parrot.dm @@ -127,7 +127,7 @@ if(speaker != src && prob(20)) //Dont imitate ourselves if(speech_buffer.len >= 20) speech_buffer -= pick(speech_buffer) - speech_buffer |= html_decode(message) + speech_buffer |= html_decode(raw_message) ..() /mob/living/simple_animal/parrot/radio(message, message_mode) //literally copied from human/radio(), but there's no other way to do this. at least it's better than it used to be. diff --git a/code/modules/mob/say_readme.dm b/code/modules/mob/say_readme.dm index 7739ea6f382..f57b4249549 100644 --- a/code/modules/mob/say_readme.dm +++ b/code/modules/mob/say_readme.dm @@ -13,6 +13,7 @@ Radio code, while very much related to saycode, is not something I wanted to tou If you came here to see how to use saycode, all you will ever really need to call is say(message). To have things react when other things speak around them, add the HEAR flag to their flags variable and override their Hear() proc. + =======================PROCS & VARIABLES======================= Here follows a list of say()-related procs and variables. global procs @@ -97,7 +98,6 @@ global procs can_speak_basic(message) Sees if the mob can "think" the message. Does not include vocalization or stat checks. Vocalization checks are in can_speak_vocal, stat checks have to be done manually. - Will call say_dead() if the speaker is dead. Called right before handle_inherent_channels() can_speak_vocal(message) @@ -135,13 +135,13 @@ I did not want to interfere with radios too much, but I sort of had to. For future generations, here is how radio code works: First, talk_into() is called on a radio. This sends a signal datum into the magic machine that is tcomms, which eventually results in broadcast_message() being called. - + Broadcast_message() does NOT call say() on radios, but rather calls Hear() on everyone in range of a radio. This is because the system does not like repeating says. - + Furthermore, I changed radios to not be in the radio_controller. Instead, they are in a global list called all_radios. This is an associative list, and the numbers as strings are the keys. The values are lists of radios that can hear said frequency. - + To add a radio, simply use add_radio(radio, frequency). To remove a radio, use remove_radio(radio, frequency). To remove a radio from ALL frequencies, use remove_radio_all(radio). @@ -156,7 +156,7 @@ If radio_freq is not null, the code will rely on the fact that the speaker is vi GetSource() Returns the source of the virtual speaker. GetRadio() - Returns the radio that was spoken through by the source. + Returns the radio that was spoken through by the source. Needed for AI tracking. This is fairly hacky, but it means that I can advoid using istypes. It's mainly relevant for AI tracking and AI job display.