From b80a77572df0afb719c51a9d0a8d3d53dbd0a742 Mon Sep 17 00:00:00 2001 From: Jamie D <993128+JamieD1@users.noreply.github.com> Date: Thu, 5 Nov 2020 20:25:37 +0000 Subject: [PATCH] Fixes Runechat runtimes and Adds Singing And fixes lots of other runtimes (#10325) * E * More runtimes * Fucking i(n)dent I swear --- code/__DEFINES/say.dm | 8 + code/datums/brain_damage/imaginary_friend.dm | 6 +- code/datums/chatmessage.dm | 4 +- code/game/atoms_movable.dm | 1 + code/game/machinery/doors/passworddoor.dm | 2 +- code/game/machinery/hologram.dm | 6 +- code/game/machinery/requests_console.dm | 2 +- code/game/machinery/telecomms/broadcasting.dm | 7 +- code/game/mecha/mecha.dm | 4 +- code/game/objects/items.dm | 2 +- .../objects/items/devices/radio/headset.dm | 2 +- .../objects/items/devices/radio/intercom.dm | 4 +- .../game/objects/items/devices/radio/radio.dm | 17 +- .../objects/items/devices/taperecorder.dm | 2 +- code/game/objects/items/eightball.dm | 2 +- code/game/objects/items/toys.dm | 2 +- code/game/say.dm | 34 ++-- .../antagonists/disease/disease_mob.dm | 6 +- code/modules/assembly/voice.dm | 2 +- .../machinery/components/components_base.dm | 4 +- .../machinery/pipes/heat_exchange/he_pipes.dm | 2 +- code/modules/clothing/neck/bodycamera.dm | 2 +- code/modules/language/aphasia.dm | 1 + code/modules/language/beachbum.dm | 1 + code/modules/language/common.dm | 1 + code/modules/language/draconic.dm | 1 + code/modules/language/drone.dm | 1 + code/modules/language/language.dm | 2 +- code/modules/language/machine.dm | 1 + code/modules/language/monkey.dm | 2 +- code/modules/language/mushroom.dm | 1 + code/modules/language/narsian.dm | 1 + code/modules/language/piratespeak.dm | 1 + code/modules/language/slime.dm | 2 +- code/modules/language/swarmer.dm | 2 +- code/modules/language/sylvan.dm | 1 + code/modules/language/xenocommon.dm | 2 +- code/modules/mob/dead/observer/say.dm | 33 ++-- code/modules/mob/living/brain/say.dm | 6 +- code/modules/mob/living/carbon/alien/say.dm | 2 +- code/modules/mob/living/carbon/human/say.dm | 27 ++- code/modules/mob/living/say.dm | 158 ++++++++---------- code/modules/mob/living/silicon/ai/ai.dm | 6 +- .../mob/living/silicon/ai/freelook/eye.dm | 4 +- code/modules/mob/living/silicon/ai/say.dm | 11 +- code/modules/mob/living/silicon/say.dm | 19 +-- .../mob/living/simple_animal/bot/bot.dm | 21 +-- .../hostile/megafauna/colossus.dm | 2 +- .../mob/living/simple_animal/parrot.dm | 29 ++-- .../mob/living/simple_animal/simple_animal.dm | 2 +- .../mob/living/simple_animal/slime/say.dm | 2 +- code/modules/mob/say.dm | 52 ++++-- interface/stylesheet.dm | 1 + strings/names/verbs.txt | 1 + 54 files changed, 272 insertions(+), 245 deletions(-) diff --git a/code/__DEFINES/say.dm b/code/__DEFINES/say.dm index 6d3852cf4e6a..2eacecbf0e64 100644 --- a/code/__DEFINES/say.dm +++ b/code/__DEFINES/say.dm @@ -3,6 +3,10 @@ Currently contains speech spans and message modes */ +#define RADIO_EXTENSION "department specific" +#define RADIO_KEY "department specific key" +#define LANGUAGE_EXTENSION "language specific" + //Message modes. Each one defines a radio channel, more or less. #define MODE_HEADSET "headset" #define MODE_ROBOT "robot" @@ -20,6 +24,7 @@ #define MODE_KEY_BINARY "b" #define MODE_TOKEN_BINARY ":b" +#define WHISPER_MODE "the type of whisper" #define MODE_WHISPER "whisper" #define MODE_WHISPER_CRIT "whispercrit" @@ -45,6 +50,8 @@ #define MODE_MONKEY "monkeyhive" +#define MODE_SING "sing" + #define MODE_DARKSPAWN "mindlink" //Spans. Robot speech, italics, etc. Applied in compose_message(). @@ -56,6 +63,7 @@ #define SPAN_REALLYBIG "reallybig" #define SPAN_COMMAND "command_headset" #define SPAN_CLOWN "clown" +#define SPAN_SINGING "singing" //bitflag #defines for return value of the radio() proc. #define ITALICS (1<<0) diff --git a/code/datums/brain_damage/imaginary_friend.dm b/code/datums/brain_damage/imaginary_friend.dm index 1584e9c6a84a..aceaa5440ba0 100644 --- a/code/datums/brain_damage/imaginary_friend.dm +++ b/code/datums/brain_damage/imaginary_friend.dm @@ -146,10 +146,10 @@ friend_talk(message) -/mob/camera/imaginary_friend/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, message_mode) +/mob/camera/imaginary_friend/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, list/message_mods = list()) if (client?.prefs.chat_on_map && (client.prefs.see_chat_non_mob || ismob(speaker))) - create_chat_message(speaker, message_language, raw_message, spans, message_mode) - to_chat(src, compose_message(speaker, message_language, raw_message, radio_freq, spans, message_mode)) + create_chat_message(speaker, message_language, raw_message, spans) + to_chat(src, compose_message(speaker, message_language, raw_message, radio_freq, spans, message_mods)) /mob/camera/imaginary_friend/proc/friend_talk(message) message = capitalize(trim(copytext_char(sanitize(message), 1, MAX_MESSAGE_LEN))) diff --git a/code/datums/chatmessage.dm b/code/datums/chatmessage.dm index 396714763e6c..48760cc02eb0 100644 --- a/code/datums/chatmessage.dm +++ b/code/datums/chatmessage.dm @@ -47,6 +47,7 @@ var/datum/chatmessage/prev /// The current index used for adjusting the layer of each sequential chat message such that recent messages will overlay older ones var/static/current_z_idx = 0 + /** * Constructs a chat message overlay * @@ -91,7 +92,7 @@ * Arguments: * * text - The text content of the overlay * * target - The target atom to display the overlay at - * * owner - The mob that owns this overlay, only this mob will be able to view it# + * * owner - The mob that owns this overlay, only this mob will be able to view it * * language - The language this message was spoken in * * extra_classes - Extra classes to apply to the span that holds the text * * lifespan - The lifespan of the message in deciseconds @@ -224,7 +225,6 @@ * * message_language - The language that the message is said in * * raw_message - The text content of the message * * spans - Additional classes to be added to the message - * * message_mode - Bitflags relating to the mode of the message */ /mob/proc/create_chat_message(atom/movable/speaker, datum/language/message_language, raw_message, list/spans, runechat_flags = NONE) // Ensure the list we are using, if present, is a copy so we don't modify the list provided to us diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index bd9c578fd3e4..d4621d620531 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -16,6 +16,7 @@ var/verb_ask = "asks" var/verb_exclaim = "exclaims" var/verb_whisper = "whispers" + var/verb_sing = "sings" var/verb_yell = "yells" var/speech_span var/inertia_dir = 0 diff --git a/code/game/machinery/doors/passworddoor.dm b/code/game/machinery/doors/passworddoor.dm index fcbb214bb66a..6ad4fd80e965 100644 --- a/code/game/machinery/doors/passworddoor.dm +++ b/code/game/machinery/doors/passworddoor.dm @@ -22,7 +22,7 @@ if(voice_activated) flags_1 |= HEAR_1 -/obj/machinery/door/password/Hear(message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, message_mode) +/obj/machinery/door/password/Hear(message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, list/message_mods = list()) . = ..() if(!density || !voice_activated || radio_freq) return diff --git a/code/game/machinery/hologram.dm b/code/game/machinery/hologram.dm index 8229ef77e62c..560d98fc8568 100644 --- a/code/game/machinery/hologram.dm +++ b/code/game/machinery/hologram.dm @@ -420,17 +420,17 @@ obj/machinery/holopad/secure/Initialize() /*This is the proc for special two-way communication between AI and holopad/people talking near holopad. For the other part of the code, check silicon say.dm. Particularly robot talk.*/ -/obj/machinery/holopad/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, message_mode) +/obj/machinery/holopad/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, list/message_mods = list()) . = ..() if(speaker && LAZYLEN(masters) && !radio_freq)//Master is mostly a safety in case lag hits or something. Radio_freq so AIs dont hear holopad stuff through radios. for(var/mob/living/silicon/ai/master in masters) if(masters[master] && speaker != master) - master.relay_speech(message, speaker, message_language, raw_message, radio_freq, spans, message_mode) + master.relay_speech(message, speaker, message_language, raw_message, radio_freq, spans, message_mods) for(var/I in holo_calls) var/datum/holocall/HC = I if(HC.connected_holopad == src && speaker != HC.hologram) - HC.user.Hear(message, speaker, message_language, raw_message, radio_freq, spans, message_mode) + HC.user.Hear(message, speaker, message_language, raw_message, radio_freq, spans, message_mods) if(outgoing_call && speaker == outgoing_call.user) outgoing_call.hologram.say(raw_message) diff --git a/code/game/machinery/requests_console.dm b/code/game/machinery/requests_console.dm index b9c52d441df9..f1a368256751 100644 --- a/code/game/machinery/requests_console.dm +++ b/code/game/machinery/requests_console.dm @@ -344,7 +344,7 @@ GLOBAL_LIST_EMPTY(req_console_ckey_departments) updateUsrDialog() -/obj/machinery/requests_console/say_mod(input, message_mode) +/obj/machinery/requests_console/say_mod(input, list/message_mods = list()) if(spantext_char(input, "!", -3)) return "blares" else diff --git a/code/game/machinery/telecomms/broadcasting.dm b/code/game/machinery/telecomms/broadcasting.dm index 1fc3a3b98fd0..7c320f600d01 100644 --- a/code/game/machinery/telecomms/broadcasting.dm +++ b/code/game/machinery/telecomms/broadcasting.dm @@ -103,6 +103,7 @@ datum/language/language, // the language of the message message, // the text content of the message spans, // the list of spans applied to the message + list/message_mods, // the list of modification applied to the message. Whispering, singing, ect lvls = null //Yogs -- For NTSL. It's the list of Z-levels that should hear this message. ) src.source = source @@ -116,7 +117,8 @@ "message" = message, "compression" = rand(35, 65), "language" = lang_instance.name, - "spans" = spans + "spans" = spans, + "mods" = message_mods ) //Yogs start if(lvls) @@ -188,9 +190,10 @@ // Render the message and have everybody hear it. // Always call this on the virtualspeaker to avoid issues. var/spans = data["spans"] + var/list/message_mods = data["mods"] var/rendered = virt.compose_message(virt, language, message, frequency, spans) for(var/atom/movable/hearer in receive) - hearer.Hear(rendered, virt, language, message, frequency, spans) + hearer.Hear(rendered, virt, language, message, frequency, spans, message_mods) // This following recording is intended for research and feedback in the use of department radio channels if(length(receive)) diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm index 836e832bc44a..15cc984113c8 100644 --- a/code/game/mecha/mecha.dm +++ b/code/game/mecha/mecha.dm @@ -462,11 +462,11 @@ /obj/mecha/proc/drop_item()//Derpfix, but may be useful in future for engineering exosuits. return -/obj/mecha/Hear(message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, message_mode) +/obj/mecha/Hear(message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, list/message_mods = list()) . = ..() if(speaker == occupant) if(radio?.broadcasting) - radio.talk_into(speaker, text, , spans, message_language) + radio.talk_into(speaker, text, , spans, message_language, message_mods) //flick speech bubble var/list/speech_bubble_recipients = list() for(var/mob/M in get_hearers_in_view(7,src)) diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 124b2665ac9b..434286fa4775 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -376,7 +376,7 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE) return 1 return 0 -/obj/item/proc/talk_into(mob/M, input, channel, spans, datum/language/language) +/obj/item/proc/talk_into(mob/M, input, channel, spans, datum/language/language, list/message_mods) return ITALICS | REDUCE_RANGE /obj/item/proc/dropped(mob/user) diff --git a/code/game/objects/items/devices/radio/headset.dm b/code/game/objects/items/devices/radio/headset.dm index 92a4548a8d0e..755c28039fc7 100644 --- a/code/game/objects/items/devices/radio/headset.dm +++ b/code/game/objects/items/devices/radio/headset.dm @@ -60,7 +60,7 @@ GLOBAL_LIST_INIT(channel_tokens, list( QDEL_NULL(keyslot2) return ..() -/obj/item/radio/headset/talk_into(mob/living/M, message, channel, list/spans,datum/language/language) +/obj/item/radio/headset/talk_into(mob/living/M, message, channel, list/spans, datum/language/language, list/message_mods) if (!listening) return ITALICS | REDUCE_RANGE return ..() diff --git a/code/game/objects/items/devices/radio/intercom.dm b/code/game/objects/items/devices/radio/intercom.dm index 40c7b9051fcd..8232354b9203 100644 --- a/code/game/objects/items/devices/radio/intercom.dm +++ b/code/game/objects/items/devices/radio/intercom.dm @@ -112,8 +112,8 @@ return TRUE -/obj/item/radio/intercom/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, list/spans, message_mode) - if (message_mode == MODE_INTERCOM) +/obj/item/radio/intercom/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, list/spans, list/message_mods = list()) + if(message_mods[RADIO_EXTENSION] == MODE_INTERCOM) return // Avoid hearing the same thing twice if(!anyai && !(speaker in ai)) // set the intercomms in AI cores to 0 when this gets implemented return diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm index 3f0860e91df4..1245106a308c 100644 --- a/code/game/objects/items/devices/radio/radio.dm +++ b/code/game/objects/items/devices/radio/radio.dm @@ -189,15 +189,15 @@ recalculateChannels() . = TRUE -/obj/item/radio/talk_into(atom/movable/M, message, channel, list/spans, datum/language/language) +/obj/item/radio/talk_into(atom/movable/M, message, channel, list/spans, datum/language/language, list/message_mods) if(!spans) spans = list(M.speech_span) if(!language) language = M.get_selected_language() - INVOKE_ASYNC(src, .proc/talk_into_impl, M, message, channel, spans.Copy(), language) + INVOKE_ASYNC(src, .proc/talk_into_impl, M, message, channel, spans.Copy(), language, message_mods) return ITALICS | REDUCE_RANGE -/obj/item/radio/proc/talk_into_impl(atom/movable/M, message, channel, list/spans, datum/language/language) +/obj/item/radio/proc/talk_into_impl(atom/movable/M, message, channel, list/spans, datum/language/language, list/message_mods) if(!on) return // the device has to be on if(!M || !message) @@ -246,7 +246,7 @@ var/atom/movable/virtualspeaker/speaker = new(null, M, src) // Construct the signal - var/datum/signal/subspace/vocal/signal = new(src, freq, speaker, language, message, spans) + var/datum/signal/subspace/vocal/signal = new(src, freq, speaker, language, message, spans, message_mods) // Independent radios, on the CentCom frequency, reach all independent radios if (independent && (freq == FREQ_CENTCOM || freq == FREQ_CTF_RED || freq == FREQ_CTF_BLUE)) @@ -278,21 +278,18 @@ signal.levels = list(T.z) signal.broadcast() -/obj/item/radio/Hear(message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, message_mode) +/obj/item/radio/Hear(message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, list/message_mods = list()) . = ..() if(radio_freq || !broadcasting || get_dist(src, speaker) > canhear_range) return - if(message_mode == MODE_WHISPER || message_mode == MODE_WHISPER_CRIT) - // radios don't pick up whispers very well - raw_message = stars(raw_message) - else if(message_mode == MODE_L_HAND || message_mode == MODE_R_HAND) + if(message_mods[RADIO_EXTENSION] == MODE_L_HAND || message_mods[RADIO_EXTENSION] == MODE_R_HAND) // try to avoid being heard double if (loc == speaker && ismob(speaker)) var/mob/M = speaker var/idx = M.get_held_index_of_item(src) // left hands are odd slots - if (idx && (idx % 2) == (message_mode == MODE_L_HAND)) + if (idx && (idx % 2) == (message_mods[RADIO_EXTENSION] == MODE_L_HAND)) return talk_into(speaker, raw_message, , spans, language=message_language) diff --git a/code/game/objects/items/devices/taperecorder.dm b/code/game/objects/items/devices/taperecorder.dm index 85f26c1d1dcc..e5b8790fc8bd 100644 --- a/code/game/objects/items/devices/taperecorder.dm +++ b/code/game/objects/items/devices/taperecorder.dm @@ -114,7 +114,7 @@ icon_state = "taperecorder_idle" -/obj/item/taperecorder/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, spans, message_mode) +/obj/item/taperecorder/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, spans, list/message_mods = list()) . = ..() if(mytape && recording) mytape.timestamp += mytape.used_capacity diff --git a/code/game/objects/items/eightball.dm b/code/game/objects/items/eightball.dm index 95a4389498be..86f46b8c562d 100644 --- a/code/game/objects/items/eightball.dm +++ b/code/game/objects/items/eightball.dm @@ -153,7 +153,7 @@ interact(user) return ..() -/obj/item/toy/eightball/haunted/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, spans, message_mode) +/obj/item/toy/eightball/haunted/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, spans, list/message_mods = list()) . = ..() last_message = raw_message diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm index 6d298607a695..7d76988c0d6f 100644 --- a/code/game/objects/items/toys.dm +++ b/code/game/objects/items/toys.dm @@ -1569,7 +1569,7 @@ obj/item/toy/turn_tracker to_chat(user, "You name the dummy as \"[doll_name]\"") name = "[initial(name)] - [doll_name]" -/obj/item/toy/dummy/talk_into(atom/movable/A, message, channel, list/spans, datum/language/language) +/obj/item/toy/dummy/talk_into(atom/movable/A, message, channel, list/spans, datum/language/language, list/message_mods) var/mob/M = A if (istype(M)) M.log_talk(message, LOG_SAY, tag="dummy toy") diff --git a/code/game/say.dm b/code/game/say.dm index 00120579768d..e43f6a3554cb 100644 --- a/code/game/say.dm +++ b/code/game/say.dm @@ -31,19 +31,19 @@ GLOBAL_LIST_INIT(freqtospan, list( language = get_selected_language() send_speech(message, 7, src, , spans, message_language=language) -/atom/movable/proc/Hear(message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, message_mode) +/atom/movable/proc/Hear(message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, list/message_mods = list()) SEND_SIGNAL(src, COMSIG_MOVABLE_HEAR, args) /atom/movable/proc/can_speak() return 1 -/atom/movable/proc/send_speech(message, range = 7, obj/source = src, bubble_type, list/spans, datum/language/message_language = null, message_mode) - var/rendered = compose_message(src, message_language, message, , spans, message_mode) +/atom/movable/proc/send_speech(message, range = 7, obj/source = src, bubble_type, list/spans, datum/language/message_language = null, list/message_mods = list()) + var/rendered = compose_message(src, message_language, message, , spans, message_mods) for(var/_AM in get_hearers_in_view(range, source)) var/atom/movable/AM = _AM - AM.Hear(rendered, src, message_language, message, , spans, message_mode) + AM.Hear(rendered, src, message_language, message, , spans, message_mods) -/atom/movable/proc/compose_message(atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, message_mode, face_name = FALSE) +/atom/movable/proc/compose_message(atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, list/message_mods = list(), face_name = FALSE) //This proc uses text() because it is faster than appending strings. Thanks BYOND. //Basic span var/spanpart1 = "" @@ -61,7 +61,7 @@ GLOBAL_LIST_INIT(freqtospan, list( var/endspanpart = ""// Yogs //Message - var/messagepart = " [lang_treat(speaker, message_language, raw_message, spans, message_mode)]" + var/messagepart = " [lang_treat(speaker, message_language, raw_message, spans, message_mods)]" var/languageicon = "" var/datum/language/D = GLOB.language_datum_instances[message_language] @@ -77,10 +77,12 @@ GLOBAL_LIST_INIT(freqtospan, list( /atom/movable/proc/compose_job(atom/movable/speaker, message_langs, raw_message, radio_freq) return "" -/atom/movable/proc/say_mod(input, message_mode) +/atom/movable/proc/say_mod(input, list/message_mods = list()) var/ending = copytext_char(input, -1) if(copytext_char(input, -2) == "!!") return verb_yell + else if(message_mods[MODE_SING]) + . = verb_sing else if(ending == "?") return verb_ask else if(ending == "!") @@ -88,7 +90,7 @@ GLOBAL_LIST_INIT(freqtospan, list( else return verb_say -/atom/movable/proc/say_quote(input, list/spans=list(speech_span), message_mode) +/atom/movable/proc/say_quote(input, list/spans=list(speech_span), list/message_mods = list()) if(!input) input = "..." @@ -96,23 +98,23 @@ GLOBAL_LIST_INIT(freqtospan, list( spans |= SPAN_YELL var/spanned = attach_spans(input, spans) - return "[say_mod(input, message_mode)], \"[spanned]\"" + return "[say_mod(input, message_mods)], \"[spanned]\"" -/atom/movable/proc/lang_treat(atom/movable/speaker, datum/language/language, raw_message, list/spans, message_mode, no_quote = FALSE) +/atom/movable/proc/lang_treat(atom/movable/speaker, datum/language/language, raw_message, list/spans, list/message_mods = list(), no_quote = FALSE) if(has_language(language)) var/atom/movable/AM = speaker.GetSource() if(AM) //Basically means "if the speaker is virtual" - return no_quote ? raw_message : AM.say_quote(raw_message, spans, message_mode) + return no_quote ? raw_message : AM.say_quote(raw_message, spans, message_mods) else - return no_quote ? raw_message : speaker.say_quote(raw_message, spans, message_mode) + return no_quote ? raw_message : speaker.say_quote(raw_message, spans, message_mods) else if(language) var/atom/movable/AM = speaker.GetSource() var/datum/language/D = GLOB.language_datum_instances[language] raw_message = D.scramble(raw_message) if(AM) - return no_quote ? raw_message : AM.say_quote(raw_message, spans, message_mode) + return no_quote ? raw_message : AM.say_quote(raw_message, spans, message_mods) else - return no_quote ? raw_message : speaker.say_quote(raw_message, spans, message_mode) + return no_quote ? raw_message : speaker.say_quote(raw_message, spans, message_mods) else return "makes a strange sound." @@ -210,13 +212,13 @@ INITIALIZE_IMMEDIATE(/atom/movable/virtualspeaker) return job // Yogs start -- Returns the TRUE voice if bool is true -/atom/movable/virtualspeaker/GetVoice(bool) +/atom/movable/virtualspeaker/GetVoice(bool) if(bool && realvoice) return realvoice else return "[src]" -/* +/* // Commented out because this was causing NTSL to not properly be capable of editing verb_say & al. // However, I don't exactly know why it was even in here in the first place, so, // if there's some weird bugs involving virtualspeaker, check here first. diff --git a/code/modules/antagonists/disease/disease_mob.dm b/code/modules/antagonists/disease/disease_mob.dm index c754b8e45ae5..7d5860c2345b 100644 --- a/code/modules/antagonists/disease/disease_mob.dm +++ b/code/modules/antagonists/disease/disease_mob.dm @@ -113,7 +113,7 @@ the new instance inside the host to be updated to the template's stats. follow_next(Dir & NORTHWEST) last_move_tick = world.time -/mob/camera/disease/Hear(message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, message_mode) +/mob/camera/disease/Hear(message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, list/message_mods = list()) . = ..() var/atom/movable/to_follow = speaker if(radio_freq) @@ -126,9 +126,9 @@ the new instance inside the host to be updated to the template's stats. link = "" // Create map text prior to modifying message for goonchat if (client?.prefs.chat_on_map && (client.prefs.see_chat_non_mob || ismob(speaker))) - create_chat_message(speaker, message_language, raw_message, spans, message_mode) + create_chat_message(speaker, message_language, raw_message, spans) // Recompose the message, because it's scrambled by default - message = compose_message(speaker, message_language, raw_message, radio_freq, spans, message_mode) + message = compose_message(speaker, message_language, raw_message, radio_freq, spans, message_mods) to_chat(src, "[link] [message]") diff --git a/code/modules/assembly/voice.dm b/code/modules/assembly/voice.dm index cd92269d88bc..1457b51e0e96 100644 --- a/code/modules/assembly/voice.dm +++ b/code/modules/assembly/voice.dm @@ -25,7 +25,7 @@ . = ..() . += "Use a multitool to swap between \"inclusive\", \"exclusive\", \"recognizer\", and \"voice sensor\" mode." -/obj/item/assembly/voice/Hear(message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, message_mode) +/obj/item/assembly/voice/Hear(message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, list/message_mods = list()) . = ..() if(speaker == src) return diff --git a/code/modules/atmospherics/machinery/components/components_base.dm b/code/modules/atmospherics/machinery/components/components_base.dm index 506d3896246c..5a11343de6b0 100644 --- a/code/modules/atmospherics/machinery/components/components_base.dm +++ b/code/modules/atmospherics/machinery/components/components_base.dm @@ -145,8 +145,8 @@ if(!parent) WARNING("Component is missing a pipenet! Rebuilding...") SSair.add_to_rebuild_queue(src) - parent = parents[i] - parent.update = 1 + else + parent.update = 1 /obj/machinery/atmospherics/components/returnPipenets() . = list() diff --git a/code/modules/atmospherics/machinery/pipes/heat_exchange/he_pipes.dm b/code/modules/atmospherics/machinery/pipes/heat_exchange/he_pipes.dm index 66475be45a21..7bc6043fd76c 100644 --- a/code/modules/atmospherics/machinery/pipes/heat_exchange/he_pipes.dm +++ b/code/modules/atmospherics/machinery/pipes/heat_exchange/he_pipes.dm @@ -35,7 +35,7 @@ else environment_temperature = T.return_temperature() - if(abs(environment_temperature-pipe_air.return_temperature()) > minimum_temperature_difference) + if(abs(environment_temperature-pipe_air?.return_temperature()) > minimum_temperature_difference) parent.temperature_interact(T, volume, thermal_conductivity) diff --git a/code/modules/clothing/neck/bodycamera.dm b/code/modules/clothing/neck/bodycamera.dm index 31ff70bf87a5..56603d7ba8de 100644 --- a/code/modules/clothing/neck/bodycamera.dm +++ b/code/modules/clothing/neck/bodycamera.dm @@ -112,7 +112,7 @@ /obj/item/clothing/neck/bodycam/dropped(mob/wearer) ..() - if (bodcam.status)//if it's on + if (bodcam?.status)//if it's on attack_self(wearer) //turn it off GLOB.cameranet.updatePortableCamera(bodcam) UnregisterSignal(listeningTo, COMSIG_MOVABLE_MOVED) diff --git a/code/modules/language/aphasia.dm b/code/modules/language/aphasia.dm index 91f14f91118b..26b93bfafb63 100644 --- a/code/modules/language/aphasia.dm +++ b/code/modules/language/aphasia.dm @@ -11,3 +11,4 @@ space_chance = 20 default_priority = 10 icon_state = "aphasia" + sing_verb = "gibbers" \ No newline at end of file diff --git a/code/modules/language/beachbum.dm b/code/modules/language/beachbum.dm index 528e9a8da2f4..f0e656c8a7c9 100644 --- a/code/modules/language/beachbum.dm +++ b/code/modules/language/beachbum.dm @@ -20,3 +20,4 @@ "tail", "trim", "tube", "wobble", "roll", "gnarly", "epic") icon_state = "beach" + sing_verb = "parties" \ No newline at end of file diff --git a/code/modules/language/common.dm b/code/modules/language/common.dm index 8d06dd8fa039..ea92df712357 100644 --- a/code/modules/language/common.dm +++ b/code/modules/language/common.dm @@ -9,6 +9,7 @@ default_priority = 100 icon_state = "galcom" + sing_verb = "sings" //Syllable Lists /* diff --git a/code/modules/language/draconic.dm b/code/modules/language/draconic.dm index aaa998c2c0dc..ca5b64f97b50 100644 --- a/code/modules/language/draconic.dm +++ b/code/modules/language/draconic.dm @@ -18,3 +18,4 @@ ) icon_state = "lizard" default_priority = 90 + sing_verb = "sings" \ No newline at end of file diff --git a/code/modules/language/drone.dm b/code/modules/language/drone.dm index 390e0027cf83..00d3949c9c65 100644 --- a/code/modules/language/drone.dm +++ b/code/modules/language/drone.dm @@ -14,3 +14,4 @@ default_priority = 20 icon_state = "drone" + sing_verb = "chimes" \ No newline at end of file diff --git a/code/modules/language/language.dm b/code/modules/language/language.dm index ff4a19b92459..6bc108d49acd 100644 --- a/code/modules/language/language.dm +++ b/code/modules/language/language.dm @@ -21,7 +21,7 @@ var/list/spans = list() var/list/scramble_cache = list() var/default_priority = 0 // the language that an atom knows with the highest "default_priority" is selected by default. - + var/sing_verb = "sings" // Used for singing. // if you are seeing someone speak popcorn language, then something is wrong. var/icon = 'icons/misc/language.dmi' var/icon_state = "popcorn" diff --git a/code/modules/language/machine.dm b/code/modules/language/machine.dm index b7ef701e3020..7dd851161d79 100644 --- a/code/modules/language/machine.dm +++ b/code/modules/language/machine.dm @@ -12,6 +12,7 @@ default_priority = 90 icon_state = "eal" + sing_verb = "whistles melodically" /datum/language/machine/get_random_name() if(prob(70)) diff --git a/code/modules/language/monkey.dm b/code/modules/language/monkey.dm index 53e598b02b25..7bf871b5e674 100644 --- a/code/modules/language/monkey.dm +++ b/code/modules/language/monkey.dm @@ -8,5 +8,5 @@ space_chance = 100 syllables = list("oop", "aak", "chee", "eek") default_priority = 80 - + sing_verb = "chimpers tunefully" icon_state = "animal" diff --git a/code/modules/language/mushroom.dm b/code/modules/language/mushroom.dm index b896d11449c3..aea98952ff52 100644 --- a/code/modules/language/mushroom.dm +++ b/code/modules/language/mushroom.dm @@ -9,3 +9,4 @@ sentence_chance = 0 default_priority = 80 syllables = list("poof", "pff", "pFfF", "piff", "puff", "pooof", "pfffff", "piffpiff", "puffpuff", "poofpoof", "pifpafpofpuf") + sing_verb = "puffs musically" \ No newline at end of file diff --git a/code/modules/language/narsian.dm b/code/modules/language/narsian.dm index 70966ad8802e..aeb35ed58bbd 100644 --- a/code/modules/language/narsian.dm +++ b/code/modules/language/narsian.dm @@ -6,6 +6,7 @@ exclaim_verb = "invokes" key = "n" sentence_chance = 8 + sing_verb = "intones" space_chance = 95 //very high due to the potential length of each syllable var/static/list/base_syllables = list( "h", "v", "c", "e", "g", "d", "r", "n", "h", "o", "p", diff --git a/code/modules/language/piratespeak.dm b/code/modules/language/piratespeak.dm index 10d307395cad..a0300002283b 100644 --- a/code/modules/language/piratespeak.dm +++ b/code/modules/language/piratespeak.dm @@ -13,3 +13,4 @@ "shiver","timbers","matey","swashbuckler" ) icon_state = "pirate" + sing_verb = "shanties" \ No newline at end of file diff --git a/code/modules/language/slime.dm b/code/modules/language/slime.dm index 7171c07b3915..ffa95eec8400 100644 --- a/code/modules/language/slime.dm +++ b/code/modules/language/slime.dm @@ -7,5 +7,5 @@ key = "k" syllables = list("qr","qrr","xuq","qil","quum","xuqm","vol","xrim","zaoo","qu-uu","qix","qoo","zix","*","!") default_priority = 70 - + sing_verb = "warbles" icon_state = "slime" diff --git a/code/modules/language/swarmer.dm b/code/modules/language/swarmer.dm index 2549f836692a..7c04f46f9a23 100644 --- a/code/modules/language/swarmer.dm +++ b/code/modules/language/swarmer.dm @@ -10,7 +10,7 @@ space_chance = 100 sentence_chance = 0 default_priority = 60 - + sing_verb = "tones" icon_state = "swarmer" // since various flats and sharps are the same, diff --git a/code/modules/language/sylvan.dm b/code/modules/language/sylvan.dm index 11e8866cfc3d..24b9a6d66ddd 100644 --- a/code/modules/language/sylvan.dm +++ b/code/modules/language/sylvan.dm @@ -7,6 +7,7 @@ exclaim_verb = "declares" key = "h" space_chance = 20 + sing_verb = "serenades" syllables = list( "fii", "sii", "rii", "rel", "maa", "ala", "san", "tol", "tok", "dia", "eres", "fal", "tis", "bis", "qel", "aras", "losk", "rasa", "eob", "hil", "tanl", "aere", diff --git a/code/modules/language/xenocommon.dm b/code/modules/language/xenocommon.dm index f046ecd34a63..b932a0a0766a 100644 --- a/code/modules/language/xenocommon.dm +++ b/code/modules/language/xenocommon.dm @@ -7,5 +7,5 @@ key = "4" syllables = list("sss","sSs","SSS") default_priority = 50 - + sing_verb = "hisses musically" icon_state = "xeno" diff --git a/code/modules/mob/dead/observer/say.dm b/code/modules/mob/dead/observer/say.dm index 88998cb0d038..e5c69f24bcef 100644 --- a/code/modules/mob/dead/observer/say.dm +++ b/code/modules/mob/dead/observer/say.dm @@ -1,16 +1,27 @@ +/mob/dead/observer/check_emote(message, forced) + if(message == "*spin" || message == "*flip") + emote(copytext(message, length(message[1]) + 1), intentional = !forced) + return TRUE + +//Modified version of get_message_mods, removes the trimming, the only thing we care about here is admin channels +/mob/dead/observer/get_message_mods(message, list/mods) + var/key = message[1] + if((key in GLOB.department_radio_prefixes) && length(message) > length(key) + 1 && !mods[RADIO_EXTENSION]) + mods[RADIO_KEY] = lowertext(message[1 + length(key)]) + mods[RADIO_EXTENSION] = GLOB.department_radio_keys[mods[RADIO_KEY]] + return message + /mob/dead/observer/say(message, bubble_type, var/list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null) message = trim(copytext_char(sanitize(message), 1, MAX_MESSAGE_LEN)) if (!message) return - - var/message_mode = get_message_mode(message) - if(client && (message_mode == MODE_ADMIN || message_mode == MODE_DEADMIN)) - message = copytext_char(message, 3) - message = trim_left(message) - - if(message_mode == MODE_ADMIN) + var/list/message_mods = list() + message = get_message_mods(message, message_mods) + if(client && (message_mods[RADIO_EXTENSION] == MODE_ADMIN || message_mods[RADIO_EXTENSION] == MODE_DEADMIN)) + message = trim_left(copytext_char(message, length(message_mods[RADIO_KEY]) + 2)) + if(message_mods[RADIO_EXTENSION] == MODE_ADMIN) client.cmd_admin_say(message) - else if(message_mode == MODE_DEADMIN) + else if(message_mods[RADIO_EXTENSION] == MODE_DEADMIN) client.dsay(message) return @@ -19,7 +30,7 @@ . = say_dead(message) -/mob/dead/observer/Hear(message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, message_mode) +/mob/dead/observer/Hear(message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, list/message_mods = list()) . = ..() var/atom/movable/to_follow = speaker if(radio_freq) @@ -33,7 +44,7 @@ var/link = FOLLOW_LINK(src, to_follow) // Create map text prior to modifying message for goonchat if (client?.prefs.chat_on_map && (client.prefs.see_chat_non_mob || ismob(speaker))) - create_chat_message(speaker, message_language, raw_message, spans, message_mode) + create_chat_message(speaker, message_language, raw_message, spans) // Recompose the message, because it's scrambled by default - message = compose_message(speaker, message_language, raw_message, radio_freq, spans, message_mode) + message = compose_message(speaker, message_language, raw_message, radio_freq, spans, message_mods) to_chat(src, "[link] [message]") diff --git a/code/modules/mob/living/brain/say.dm b/code/modules/mob/living/brain/say.dm index c37873e0cb34..ea2fa7aa2f84 100644 --- a/code/modules/mob/living/brain/say.dm +++ b/code/modules/mob/living/brain/say.dm @@ -10,11 +10,11 @@ ..() -/mob/living/brain/radio(message, message_mode, list/spans, language) - if(message_mode == MODE_HEADSET && istype(container, /obj/item/mmi)) +/mob/living/brain/radio(message, list/message_mods = list(), list/spans, language) + if(message_mods[MODE_HEADSET] && istype(container, /obj/item/mmi)) var/obj/item/mmi/R = container if(R.radio) - R.radio.talk_into(src, message, language = language) + R.radio.talk_into(src, message, language = language, message_mods = message_mods) return ITALICS | REDUCE_RANGE else return ..() diff --git a/code/modules/mob/living/carbon/alien/say.dm b/code/modules/mob/living/carbon/alien/say.dm index 1ad0a1e7ffd6..988d76827e07 100644 --- a/code/modules/mob/living/carbon/alien/say.dm +++ b/code/modules/mob/living/carbon/alien/say.dm @@ -20,4 +20,4 @@ /mob/living/carbon/hivecheck() var/obj/item/organ/alien/hivenode/N = getorgan(/obj/item/organ/alien/hivenode) if(N && !N.recent_queen_death) //Mob has alien hive node and is not under the dead queen special effect. - return N + return TRUE diff --git a/code/modules/mob/living/carbon/human/say.dm b/code/modules/mob/living/carbon/human/say.dm index 1f79dad4604b..834112d55d97 100644 --- a/code/modules/mob/living/carbon/human/say.dm +++ b/code/modules/mob/living/carbon/human/say.dm @@ -52,25 +52,22 @@ if(dongle.translate_binary) return TRUE -/mob/living/carbon/human/radio(message, message_mode, list/spans, language) +/mob/living/carbon/human/radio(message, list/message_mods = list(), list/spans, language) //Poly has a copy of this, lazy bastard . = ..() - if(. != 0) + if(. != FALSE) return . - switch(message_mode) - if(MODE_HEADSET) - if (ears) - ears.talk_into(src, message, , spans, language) - return ITALICS | REDUCE_RANGE - - if(MODE_DEPARTMENT) - if (ears) - ears.talk_into(src, message, message_mode, spans, language) - return ITALICS | REDUCE_RANGE - - if(message_mode in GLOB.radiochannels) + if(message_mods[MODE_HEADSET]) if(ears) - ears.talk_into(src, message, message_mode, spans, language) + ears.talk_into(src, message, , spans, language, message_mods) + return ITALICS | REDUCE_RANGE + else if(message_mods[RADIO_EXTENSION] == MODE_DEPARTMENT) + if(ears) + ears.talk_into(src, message, message_mods[RADIO_EXTENSION], spans, language, message_mods) + return ITALICS | REDUCE_RANGE + else if(GLOB.radiochannels[message_mods[RADIO_EXTENSION]]) + if(ears) + ears.talk_into(src, message, message_mods[RADIO_EXTENSION], spans, language, message_mods) return ITALICS | REDUCE_RANGE return 0 diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm index 34cef60ebce0..b836013c00c4 100644 --- a/code/modules/mob/living/say.dm +++ b/code/modules/mob/living/say.dm @@ -82,33 +82,26 @@ GLOBAL_LIST_INIT(department_radio_keys, list( return new_msg /mob/living/say(message, bubble_type,var/list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null) - var/static/list/crit_allowed_modes = list(MODE_WHISPER = TRUE, MODE_CHANGELING = TRUE, MODE_ALIEN = TRUE) + var/static/list/crit_allowed_modes = list(WHISPER_MODE = TRUE, MODE_CHANGELING = TRUE, MODE_ALIEN = TRUE) var/static/list/unconscious_allowed_modes = list(MODE_CHANGELING = TRUE, MODE_ALIEN = TRUE) - var/talk_key = get_key(message) - - var/static/list/one_character_prefix = list(MODE_HEADSET = TRUE, MODE_ROBOT = TRUE, MODE_WHISPER = TRUE) if(sanitize) message = trim(copytext_char(sanitize(message), 1, MAX_MESSAGE_LEN)) if(!message || message == "") return - var/datum/saymode/saymode = SSradio.saymodes[talk_key] - var/message_mode = get_message_mode(message) + var/list/message_mods = list() var/original_message = message + message = get_message_mods(message, message_mods) + var/datum/saymode/saymode = SSradio.saymodes[message_mods[RADIO_KEY]] var/in_critical = InCritical() - if(one_character_prefix[message_mode]) - message = copytext_char(message, 2) - else if(message_mode || saymode) - message = copytext_char(message, 3) - message = trim_left(message) - if(message_mode == MODE_ADMIN) + if(message_mods[RADIO_EXTENSION] == MODE_ADMIN) if(client) client.cmd_admin_say(message) return - if(message_mode == MODE_DEADMIN) + if(message_mods[RADIO_EXTENSION] == MODE_DEADMIN) if(client) client.dsay(message) return @@ -120,34 +113,28 @@ GLOBAL_LIST_INIT(department_radio_keys, list( if(check_emote(original_message, forced) || !can_speak_basic(original_message, ignore_spam)) return - if(in_critical) - if(!(crit_allowed_modes[message_mode])) + if(in_critical) //There are cheaper ways to do this, but they're less flexible, and this isn't ran all that often + var/end = TRUE + for(var/index in message_mods) + if(crit_allowed_modes[index]) + end = FALSE + break + if(end) return else if(stat == UNCONSCIOUS) - if(!(unconscious_allowed_modes[message_mode])) + var/end = TRUE + for(var/index in message_mods) + if(unconscious_allowed_modes[index]) + end = FALSE + break + if(end) return - // language comma detection. - var/datum/language/message_language = get_message_language(message) - if(message_language) - // No, you cannot speak in xenocommon just because you know the key - if(can_speak_language(message_language)) - language = message_language - message = copytext_char(message, 3) - - // Trim the space if they said ",0 I LOVE LANGUAGES" - message = trim_left(message) + language = message_mods[LANGUAGE_EXTENSION] if(!language) language = get_selected_language() - // Detection of language needs to be before inherent channels, because - // AIs use inherent channels for the holopad. Most inherent channels - // ignore the language argument however. - - if(saymode && !saymode.handle_message(src, message, language)) - return - if(!can_speak_vocal(message)) to_chat(src, "You find yourself unable to speak!") return @@ -157,13 +144,13 @@ GLOBAL_LIST_INIT(department_radio_keys, list( var/succumbed = FALSE var/fullcrit = InFullCritical() - if((InCritical() && !fullcrit) || message_mode == MODE_WHISPER) + if((InCritical() && !fullcrit) || message_mods[WHISPER_MODE] == MODE_WHISPER) if(fullcrit) var/alertresult = alert(src, "You will be immediately killed by this action. Proceed?",,"Accept", "Decline") if(alertresult == "Decline" || QDELETED(src)) return FALSE message_range = 1 - message_mode = MODE_WHISPER + message_mods[WHISPER_MODE] = MODE_WHISPER src.log_talk(message, LOG_WHISPER) if(fullcrit) var/health_diff = round(-HEALTH_THRESHOLD_DEAD + health) @@ -172,7 +159,7 @@ GLOBAL_LIST_INIT(department_radio_keys, list( message = copytext_char(message, 1, health_diff) + "[message_len > health_diff ? "-.." : "..."]" message = Ellipsis(message, 10, 1) last_words = message - message_mode = MODE_WHISPER_CRIT + message_mods[WHISPER_MODE] = MODE_WHISPER_CRIT succumbed = TRUE else src.log_talk(message, LOG_SAY, forced_by=forced) @@ -190,11 +177,26 @@ GLOBAL_LIST_INIT(department_radio_keys, list( var/datum/language/L = GLOB.language_datum_instances[language] spans |= L.spans - var/radio_return = radio(message, message_mode, spans, language) + if(message_mods[MODE_SING]) + var/randomnote = pick("\u2669", "\u266A", "\u266B") + message = "[randomnote] [message] [randomnote]" + spans |= SPAN_SINGING + + //This is before anything that sends say a radio message, and after all important message type modifications, so you can scumb in alien chat or something + if(saymode && !saymode.handle_message(src, message, language)) + return + var/radio_message = message + if(message_mods[WHISPER_MODE]) + // radios don't pick up whispers very well + radio_message = stars(radio_message) + spans |= SPAN_ITALICS + var/radio_return = radio(radio_message, message_mods, spans, language) if(radio_return & ITALICS) spans |= SPAN_ITALICS if(radio_return & REDUCE_RANGE) message_range = 1 + if(!message_mods[WHISPER_MODE]) + message_mods[WHISPER_MODE] = MODE_WHISPER if(radio_return & NOPASS) return 1 @@ -208,15 +210,15 @@ GLOBAL_LIST_INIT(department_radio_keys, list( if(pressure < ONE_ATMOSPHERE*0.4) //Thin air, let's italicise the message spans |= SPAN_ITALICS - send_speech(message, message_range, src, bubble_type, spans, language, message_mode) + send_speech(message, message_range, src, bubble_type, spans, language, message_mods) if(succumbed) succumb(1) - to_chat(src, compose_message(src, language, message, , spans, message_mode)) + to_chat(src, compose_message(src, language, message, , spans, message_mods)) return 1 -/mob/living/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, message_mode) +/mob/living/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, list/message_mods = list()) . = ..() if(!client) return @@ -231,20 +233,20 @@ GLOBAL_LIST_INIT(department_radio_keys, list( deaf_type = 2 // Since you should be able to hear yourself without looking // Create map text prior to modifying message for goonchat if (client?.prefs.chat_on_map && stat != UNCONSCIOUS && (client.prefs.see_chat_non_mob || ismob(speaker)) && can_hear()) - create_chat_message(speaker, message_language, raw_message, spans, message_mode) + create_chat_message(speaker, message_language, raw_message, spans) // Recompose message for AI hrefs, language incomprehension. - message = compose_message(speaker, message_language, raw_message, radio_freq, spans, message_mode) + message = compose_message(speaker, message_language, raw_message, radio_freq, spans, message_mods) SEND_SIGNAL(src, COMSIG_MOVABLE_HEAR, args) show_message(message, 2, deaf_message, deaf_type) return message -/mob/living/send_speech(message, message_range = 6, obj/source = src, bubble_type = bubble_icon, list/spans, datum/language/message_language=null, message_mode) +/mob/living/send_speech(message, message_range = 6, obj/source = src, bubble_type = bubble_icon, list/spans, datum/language/message_language=null, list/message_mods = list()) var/static/list/eavesdropping_modes = list(MODE_WHISPER = TRUE, MODE_WHISPER_CRIT = TRUE) var/eavesdrop_range = 0 - if(eavesdropping_modes[message_mode]) + if(message_mods[WHISPER_MODE]) //If we're whispering eavesdrop_range = EAVESDROP_EXTRA_RANGE var/list/listening = get_hearers_in_view(message_range+eavesdrop_range, source) var/list/the_dead = list() @@ -257,7 +259,7 @@ GLOBAL_LIST_INIT(department_radio_keys, list( if(!M.client || !client) //client is so that ghosts don't have to listen to mice continue if(get_dist(M, src) > 7 || M.z != z) //they're out of range of normal hearing - if(eavesdropping_modes[message_mode] && !(M.client.prefs.chat_toggles & CHAT_GHOSTWHISPER)) //they're whispering and we have hearing whispers at any range off + if(eavesdrop_range && !(M.client.prefs.chat_toggles & CHAT_GHOSTWHISPER)) //they're whispering and we have hearing whispers at any range off continue if(!(M.client.prefs.chat_toggles & CHAT_GHOSTEARS)) //they're talking normally and we have hearing at any range off continue @@ -268,15 +270,15 @@ GLOBAL_LIST_INIT(department_radio_keys, list( var/eavesrendered if(eavesdrop_range) eavesdropping = stars(message) - eavesrendered = compose_message(src, message_language, eavesdropping, , spans, message_mode) + eavesrendered = compose_message(src, message_language, eavesdropping, , spans, message_mods) - var/rendered = compose_message(src, message_language, message, , spans, message_mode) + var/rendered = compose_message(src, message_language, message, , spans, message_mods) for(var/_AM in listening) var/atom/movable/AM = _AM if(eavesdrop_range && get_dist(source, AM) > message_range && !(the_dead[AM])) - AM.Hear(eavesrendered, src, message_language, eavesdropping, , spans, message_mode) + AM.Hear(eavesrendered, src, message_language, eavesdropping, , spans, message_mods) else - AM.Hear(rendered, src, message_language, message, , spans, message_mode) + AM.Hear(rendered, src, message_language, message, , spans, message_mods) SEND_GLOBAL_SIGNAL(COMSIG_GLOB_LIVING_SAY_SPECIAL, src, message) //speech bubble @@ -293,43 +295,29 @@ GLOBAL_LIST_INIT(department_radio_keys, list( /mob/living/can_speak(message) //For use outside of Say() if(can_speak_basic(message) && can_speak_vocal(message)) - return 1 + return TRUE /mob/living/proc/can_speak_basic(message, ignore_spam = FALSE) //Check BEFORE handling of xeno and ling channels if(client) if(client.prefs.muted & MUTE_IC) to_chat(src, "You cannot speak in IC (muted).") - return 0 + return FALSE if(!ignore_spam && client.handle_spam_prevention(message,MUTE_IC)) - return 0 + return FALSE - return 1 + return TRUE /mob/living/proc/can_speak_vocal(message) //Check AFTER handling of xeno and ling channels if(HAS_TRAIT(src, TRAIT_MUTE)) - return 0 + return FALSE if(is_muzzled()) - return 0 + return FALSE if(!IsVocal()) - return 0 + return FALSE - return 1 - -/mob/living/proc/get_key(message) - var/key = message[1] - if(key in GLOB.department_radio_prefixes) - return lowertext(message[1 + length(key)]) - -/mob/living/proc/get_message_language(message) - if(message[1] == ",") - var/key = message[1 + length(message[1])] - for(var/ld in GLOB.all_languages) - var/datum/language/LD = ld - if(initial(LD.key) == key) - return LD - return null + return TRUE /mob/living/proc/treat_message(message) if(HAS_TRAIT(src, TRAIT_UNINTELLIGIBLE_SPEECH)) @@ -351,33 +339,31 @@ GLOBAL_LIST_INIT(department_radio_keys, list( return message -/mob/living/proc/radio(message, message_mode, list/spans, language) +/mob/living/proc/radio(message, list/message_mods = list(), list/spans, language) var/obj/item/implant/radio/imp = locate() in src if(imp && imp.radio.on) - if(message_mode == MODE_HEADSET) - imp.radio.talk_into(src, message, , spans, language) + if(message_mods[MODE_HEADSET]) + imp.radio.talk_into(src, message, , spans, language, message_mods) return ITALICS | REDUCE_RANGE - if(message_mode == MODE_DEPARTMENT || (message_mode in GLOB.radiochannels)) - imp.radio.talk_into(src, message, message_mode, spans, language) + if(message_mods[RADIO_EXTENSION] == MODE_DEPARTMENT || (message_mods[RADIO_EXTENSION] in imp.radio.channels)) + imp.radio.talk_into(src, message, message_mods[RADIO_EXTENSION], spans, language, message_mods) return ITALICS | REDUCE_RANGE - switch(message_mode) - if(MODE_WHISPER) - return ITALICS + switch(message_mods[RADIO_EXTENSION]) if(MODE_R_HAND) for(var/obj/item/r_hand in get_held_items_for_side("r", all = TRUE)) if (r_hand) - return r_hand.talk_into(src, message, , spans, language) + return r_hand.talk_into(src, message, , spans, language, message_mods) return ITALICS | REDUCE_RANGE if(MODE_L_HAND) for(var/obj/item/l_hand in get_held_items_for_side("l", all = TRUE)) if (l_hand) - return l_hand.talk_into(src, message, , spans, language) + return l_hand.talk_into(src, message, , spans, language, message_mods) return ITALICS | REDUCE_RANGE if(MODE_INTERCOM) for (var/obj/item/radio/intercom/I in view(1, null)) - I.talk_into(src, message, , spans, language) + I.talk_into(src, message, , spans, language, message_mods) return ITALICS | REDUCE_RANGE if(MODE_BINARY) @@ -385,11 +371,13 @@ GLOBAL_LIST_INIT(department_radio_keys, list( return 0 -/mob/living/say_mod(input, message_mode) - if(message_mode == MODE_WHISPER) +/mob/living/say_mod(input, list/message_mods = list()) + if(message_mods[WHISPER_MODE] == MODE_WHISPER) . = verb_whisper - else if(message_mode == MODE_WHISPER_CRIT) + else if(message_mods[WHISPER_MODE] == MODE_WHISPER_CRIT) . = "[verb_whisper] in [p_their()] last breath" + else if(message_mods[MODE_SING]) + . = verb_sing else if(stuttering) . = "stammers" else if(derpspeech) diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index 0a3056164c7c..eff1b618578b 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -822,8 +822,8 @@ var/list/viewscale = getviewsize(client.view) return get_dist(src, A) <= max(viewscale[1]*0.5,viewscale[2]*0.5) -/mob/living/silicon/ai/proc/relay_speech(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, message_mode) - var/treated_message = lang_treat(speaker, message_language, raw_message, spans, message_mode) +/mob/living/silicon/ai/proc/relay_speech(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, list/message_mods = list()) + var/treated_message = lang_treat(speaker, message_language, raw_message, spans, message_mods) var/start = "Relayed Speech: " var/namepart = "[speaker.GetVoice()][speaker.get_alt_name()]" var/hrefpart = "" @@ -841,7 +841,7 @@ var/rendered = "[start][hrefpart][namepart] ([jobpart]) [treated_message]" if (client?.prefs.chat_on_map && (client.prefs.see_chat_non_mob || ismob(speaker))) - create_chat_message(speaker, message_language, raw_message, spans, message_mode) + create_chat_message(speaker, message_language, raw_message, spans) show_message(rendered, 2) diff --git a/code/modules/mob/living/silicon/ai/freelook/eye.dm b/code/modules/mob/living/silicon/ai/freelook/eye.dm index 77f1461be176..b3bd45e4b680 100644 --- a/code/modules/mob/living/silicon/ai/freelook/eye.dm +++ b/code/modules/mob/living/silicon/ai/freelook/eye.dm @@ -193,10 +193,10 @@ acceleration = !acceleration to_chat(usr, "Camera acceleration has been toggled [acceleration ? "on" : "off"].") -/mob/camera/aiEye/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, message_mode) +/mob/camera/aiEye/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, list/message_mods = list()) . = ..() if(relay_speech && speaker && ai && !radio_freq && speaker != ai && near_camera(speaker)) - ai.relay_speech(message, speaker, message_language, raw_message, radio_freq, spans, message_mode) + ai.relay_speech(message, speaker, message_language, raw_message, radio_freq, spans, message_mods) /obj/effect/overlay/ai_detect_hud name = "" diff --git a/code/modules/mob/living/silicon/ai/say.dm b/code/modules/mob/living/silicon/ai/say.dm index e5c50fe23677..9bbe30634b0b 100644 --- a/code/modules/mob/living/silicon/ai/say.dm +++ b/code/modules/mob/living/silicon/ai/say.dm @@ -17,7 +17,7 @@ /mob/living/silicon/ai/IsVocal() return !CONFIG_GET(flag/silent_ai) -/mob/living/silicon/ai/radio(message, message_mode, list/spans, language) +/mob/living/silicon/ai/radio(message, list/message_mods = list(), list/spans, language) if(incapacitated()) return FALSE if(!radio_enabled) //AI cannot speak if radio is disabled (via intellicard) or depowered. @@ -25,13 +25,6 @@ return FALSE ..() -/mob/living/silicon/ai/get_message_mode(message) - var/static/regex/holopad_finder = regex(@"[:.#][hH]") - if(holopad_finder.Find(message, 1, 1)) - return MODE_HOLOPAD - else - return ..() - //For holopads only. Usable by AI. /mob/living/silicon/ai/proc/holopad_talk(message, language) @@ -52,7 +45,7 @@ var/obj/effect/overlay/hologram = T.masters[src] src.log_talk(message, LOG_SAY, tag="HOLOPAD in [padloc]") hologram.say("[message]") - send_speech(message, 7, T, "robot", message_language = language) + send_speech(message, 7, T, MODE_ROBOT, message_language = language) to_chat(src, "Holopad transmitted, [real_name] \"[message]\"") else to_chat(src, "No holopad connected.") diff --git a/code/modules/mob/living/silicon/say.dm b/code/modules/mob/living/silicon/say.dm index fbc1eb4eb969..3efc0b65a388 100644 --- a/code/modules/mob/living/silicon/say.dm +++ b/code/modules/mob/living/silicon/say.dm @@ -29,26 +29,19 @@ /mob/living/silicon/lingcheck() return 0 //Borged or AI'd lings can't speak on the ling channel. -/mob/living/silicon/radio(message, message_mode, list/spans, language) +/mob/living/silicon/radio(message, list/message_mods = list(), list/spans, language) . = ..() if(. != 0) return . - if(message_mode == "robot") - if (radio) - radio.talk_into(src, message, , spans, language) + if(message_mods[MODE_HEADSET]) + if(radio) + radio.talk_into(src, message, , spans, language, message_mods) return REDUCE_RANGE - else if(message_mode in GLOB.radiochannels) + else if(message_mods[RADIO_EXTENSION] in GLOB.radiochannels) if(radio) - radio.talk_into(src, message, message_mode, spans, language) + radio.talk_into(src, message, message_mods[RADIO_EXTENSION], spans, language, message_mods) return ITALICS | REDUCE_RANGE return 0 - -/mob/living/silicon/get_message_mode(message) - . = ..() - if(..() == MODE_HEADSET) - return MODE_ROBOT - else - return . diff --git a/code/modules/mob/living/simple_animal/bot/bot.dm b/code/modules/mob/living/simple_animal/bot/bot.dm index 8e7871fd88ba..ad8660a3f00f 100644 --- a/code/modules/mob/living/simple_animal/bot/bot.dm +++ b/code/modules/mob/living/simple_animal/bot/bot.dm @@ -373,22 +373,19 @@ else say(message) -/mob/living/simple_animal/bot/radio(message, message_mode, list/spans, language) +/mob/living/simple_animal/bot/radio(message, list/message_mods = list(), list/spans, language) . = ..() if(. != 0) return - switch(message_mode) - if(MODE_HEADSET) - Radio.talk_into(src, message, , spans, language) - return REDUCE_RANGE - - if(MODE_DEPARTMENT) - Radio.talk_into(src, message, message_mode, spans, language) - return REDUCE_RANGE - - if(message_mode in GLOB.radiochannels) - Radio.talk_into(src, message, message_mode, spans, language) + if(message_mods[MODE_HEADSET]) + Radio.talk_into(src, message, , spans, language, message_mods) + return REDUCE_RANGE + else if(message_mods[RADIO_EXTENSION] == MODE_DEPARTMENT) + Radio.talk_into(src, message, message_mods[RADIO_EXTENSION], spans, language, message_mods) + return REDUCE_RANGE + else if(message_mods[RADIO_EXTENSION] in GLOB.radiochannels) + Radio.talk_into(src, message, message_mods[RADIO_EXTENSION], spans, language, message_mods) return REDUCE_RANGE /mob/living/simple_animal/bot/proc/drop_part(obj/item/drop_item, dropzone) diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm index f45e773dcda6..2ef75c4d6483 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm @@ -424,7 +424,7 @@ Difficulty: Very Hard . += observer_desc . += "It is activated by [activation_method]." -/obj/machinery/anomalous_crystal/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, spans, message_mode) +/obj/machinery/anomalous_crystal/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, spans, list/message_mods = list()) ..() if(isliving(speaker)) ActivationReaction(speaker, ACTIVATE_SPEECH) diff --git a/code/modules/mob/living/simple_animal/parrot.dm b/code/modules/mob/living/simple_animal/parrot.dm index 0b44436747c0..b44d6a1a3775 100644 --- a/code/modules/mob/living/simple_animal/parrot.dm +++ b/code/modules/mob/living/simple_animal/parrot.dm @@ -143,7 +143,7 @@ . += "Held Item: [held_item]" . += "Mode: [a_intent]" -/mob/living/simple_animal/parrot/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, list/spans, message_mode) +/mob/living/simple_animal/parrot/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, list/spans, list/message_mods = list()) . = ..() if(speaker != src && prob(50)) //Dont imitate ourselves if(!radio_freq || prob(10)) @@ -153,29 +153,24 @@ if(speaker == src && !client) //If a parrot squawks in the woods and no one is around to hear it, does it make a sound? This code says yes! return message -/mob/living/simple_animal/parrot/radio(message, message_mode, list/spans, language) //literally copied from human/radio(), but there's no other way to do this. at least it's better than it used to be. +/mob/living/simple_animal/parrot/radio(message, list/message_mods = list(), list/spans, language) //literally copied from human/radio(), but there's no other way to do this. at least it's better than it used to be. . = ..() if(. != 0) return . - - switch(message_mode) - if(MODE_HEADSET) - if (ears) - ears.talk_into(src, message, , spans, language) - return ITALICS | REDUCE_RANGE - - if(MODE_DEPARTMENT) - if (ears) - ears.talk_into(src, message, message_mode, spans, language) - return ITALICS | REDUCE_RANGE - - if(message_mode in GLOB.radiochannels) + if(message_mods[MODE_HEADSET]) if(ears) - ears.talk_into(src, message, message_mode, spans, language) + ears.talk_into(src, message, , spans, language, message_mods) + return ITALICS | REDUCE_RANGE + else if(message_mods[RADIO_EXTENSION] == MODE_DEPARTMENT) + if(ears) + ears.talk_into(src, message, message_mods[RADIO_EXTENSION], spans, language, message_mods) + return ITALICS | REDUCE_RANGE + else if(message_mods[RADIO_EXTENSION] in GLOB.radiochannels) + if(ears) + ears.talk_into(src, message, message_mods[RADIO_EXTENSION], spans, language, message_mods) return ITALICS | REDUCE_RANGE return 0 - /* * Inventory */ diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index 36c5e996eb0c..4a3c39085575 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -276,7 +276,7 @@ if(icon_gib) new /obj/effect/temp_visual/gib_animation/animal(loc, icon_gib) -/mob/living/simple_animal/say_mod(input, message_mode) +/mob/living/simple_animal/say_mod(input, list/message_mods = list()) if(speak_emote && speak_emote.len) verb_say = pick(speak_emote) . = ..() diff --git a/code/modules/mob/living/simple_animal/slime/say.dm b/code/modules/mob/living/simple_animal/slime/say.dm index a2618b711e96..0b692e6d5c0d 100644 --- a/code/modules/mob/living/simple_animal/slime/say.dm +++ b/code/modules/mob/living/simple_animal/slime/say.dm @@ -1,4 +1,4 @@ -/mob/living/simple_animal/slime/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, spans, message_mode) +/mob/living/simple_animal/slime/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, spans, list/message_mods = list()) . = ..() if(speaker != src && !radio_freq && !stat) if (speaker in Friends) diff --git a/code/modules/mob/say.dm b/code/modules/mob/say.dm index 569dbbfbf17f..47475e3b8c44 100644 --- a/code/modules/mob/say.dm +++ b/code/modules/mob/say.dm @@ -116,20 +116,50 @@ /mob/proc/lingcheck() return LINGHIVE_NONE +///The amount of items we are looking for in the message +#define MESSAGE_MODS_LENGTH 6 + /** - * Get the mode of a message + * Extracts and cleans message of any extenstions at the begining of the message + * Inserts the info into the passed list, returns the cleaned message * * Result can be + * * SAY_MODE (Things like aliens, channels that aren't channels) * * MODE_WHISPER (Quiet speech) + * * MODE_SING (Singing) * * MODE_HEADSET (Common radio channel) - * * A department radio (lots of values here) + * * RADIO_EXTENSION the extension we're using (lots of values here) + * * RADIO_KEY the radio key we're using, to make some things easier later (lots of values here) + * * LANGUAGE_EXTENSION the language we're trying to use (lots of values here) */ -/mob/proc/get_message_mode(message) - var/key = message[1] - if(key == "#") - return MODE_WHISPER - else if(key == ";") - return MODE_HEADSET - else if((length(message) > (length(key) + 1)) && (key in GLOB.department_radio_prefixes)) - var/key_symbol = lowertext(message[length(key) + 1]) - return GLOB.department_radio_keys[key_symbol] +/mob/proc/get_message_mods(message, list/mods) + for(var/I in 1 to MESSAGE_MODS_LENGTH) + var/key = message[1] + var/chop_to = 2 //By default we just take off the first char + if(key == "#" && !mods[WHISPER_MODE]) + mods[WHISPER_MODE] = MODE_WHISPER + else if(key == "%" && !mods[MODE_SING]) + mods[MODE_SING] = TRUE + else if(key == ";" && !mods[MODE_HEADSET]) + mods[MODE_HEADSET] = TRUE + else if((key in GLOB.department_radio_prefixes) && length(message) > length(key) + 1 && !mods[RADIO_EXTENSION]) + mods[RADIO_KEY] = lowertext(message[1 + length(key)]) + mods[RADIO_EXTENSION] = GLOB.department_radio_keys[mods[RADIO_KEY]] + chop_to = length(key) + 2 + else if(key == "," && !mods[LANGUAGE_EXTENSION]) + for(var/ld in GLOB.all_languages) + var/datum/language/LD = ld + if(initial(LD.key) == message[1 + length(message[1])]) + // No, you cannot speak in xenocommon just because you know the key + if(!can_speak_language(LD)) + return message + mods[LANGUAGE_EXTENSION] = LD + chop_to = length(key) + length(initial(LD.key)) + 1 + if(!mods[LANGUAGE_EXTENSION]) + return message + else + return message + message = trim_left(copytext_char(message, chop_to)) + if(!message) + return + return message \ No newline at end of file diff --git a/interface/stylesheet.dm b/interface/stylesheet.dm index b3b8e5224bb0..ae39840bbebe 100644 --- a/interface/stylesheet.dm +++ b/interface/stylesheet.dm @@ -55,6 +55,7 @@ em {font-style: normal; font-weight: bold;} .aiprivradio {color: #ff00ff;} .redteamradio {color: #ff0000;} .blueteamradio {color: #0000ff;} +.singing {font-family: "Trebuchet MS", cursive, sans-serif; font-style: italic;} .yell { font-weight: bold;} diff --git a/strings/names/verbs.txt b/strings/names/verbs.txt index fc90f89e4008..623cf0185f45 100644 --- a/strings/names/verbs.txt +++ b/strings/names/verbs.txt @@ -486,6 +486,7 @@ sigh sign signal sin +sing sip ski skip