diff --git a/code/__DEFINES/say.dm b/code/__DEFINES/say.dm index 9502db55f..49010f957 100644 --- a/code/__DEFINES/say.dm +++ b/code/__DEFINES/say.dm @@ -61,9 +61,9 @@ #define SPAN_SMALL "small" //bitflag #defines for return value of the radio() proc. -#define ITALICS 1 -#define REDUCE_RANGE 2 -#define NOPASS 4 +#define ITALICS (1<<0) +#define REDUCE_RANGE (1<<1) +#define NOPASS (1<<2) //Eavesdropping #define EAVESDROP_EXTRA_RANGE 1 //how much past the specified message_range does the message get starred, whispering only @@ -88,3 +88,7 @@ // Audio/Visual Flags. Used to determine what sense are required to notice a message. #define MSG_VISUAL (1<<0) #define MSG_AUDIBLE (1<<1) + + +//Used in visible_message_flags, audible_message_flags and runechat_flags +#define EMOTE_MESSAGE (1<<0) \ No newline at end of file diff --git a/code/datums/chatmessage.dm b/code/datums/chatmessage.dm index 8cac8b435..4c773a7e1 100644 --- a/code/datums/chatmessage.dm +++ b/code/datums/chatmessage.dm @@ -55,15 +55,6 @@ message = null return ..() -/** - * Calls qdel on the chatmessage when its parent is deleted, used to register qdel signal - */ -/datum/chatmessage/proc/on_parent_qdel() - UnregisterSignal(src, COMSIG_PARENT_QDELETING) - qdel(src) - - - /** * Generates a chat message image representation * @@ -107,10 +98,10 @@ // Append radio icon if from a virtual speaker if (extra_classes.Find("virtual-speaker")) var/image/r_icon = image('icons/UI_Icons/chat/chat_icons.dmi', icon_state = "radio") - text = "\icon[r_icon] " + text + text = "\icon[r_icon] [text]" else if (extra_classes.Find("emote")) - var/image/r_icon = image('icons/ui_icons/chat/chat_icons.dmi', icon_state = "emote") - text = "\icon[r_icon] " + text + var/image/r_icon = image('icons/UI_Icons/chat/chat_icons.dmi', icon_state = "emote") + text = "\icon[r_icon] [text]" // We dim italicized text to make it more distinguishable from regular text var/tgt_color = extra_classes.Find("italics") ? target.chat_color_darkened : target.chat_color @@ -120,7 +111,7 @@ // BYOND Bug #2563917 // Construct text var/static/regex/html_metachars = new(@"&[A-Za-z]{1,7};", "g") - var/complete_text = "[owner.say_emphasis(text)]" + var/complete_text = "[text]" var/mheight = WXH_TO_HEIGHT(owned_by.MeasureText(replacetext(complete_text, html_metachars, "m"), null, CHAT_MESSAGE_WIDTH)) approx_lines = max(1, mheight / CHAT_MESSAGE_APPROX_LHEIGHT) @@ -176,7 +167,7 @@ * * 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, message_mode) +/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 spans = spans ? spans.Copy() : list() @@ -192,7 +183,10 @@ return // Display visual above source - new /datum/chatmessage(lang_treat(speaker, message_language, raw_message, spans, null, TRUE), speaker, src, spans) + if(runechat_flags & EMOTE_MESSAGE) + new /datum/chatmessage(raw_message, speaker, src, list("emote", "italics")) + else + new /datum/chatmessage(lang_treat(speaker, message_language, raw_message, spans, null, TRUE), speaker, src, spans) // Tweak these defines to change the available color ranges @@ -246,3 +240,11 @@ return "#[num2hex(x, 2)][num2hex(m, 2)][num2hex(c, 2)]" if(5) return "#[num2hex(c, 2)][num2hex(m, 2)][num2hex(x, 2)]" + + +/** + * Calls qdel on the chatmessage when its parent is deleted, used to register qdel signal + */ +/datum/chatmessage/proc/on_parent_qdel() + qdel(src) + diff --git a/code/datums/emotes.dm b/code/datums/emotes.dm index fe3456f2c..02c964045 100644 --- a/code/datums/emotes.dm +++ b/code/datums/emotes.dm @@ -58,19 +58,19 @@ return user.log_message(msg, LOG_EMOTE) - msg = "[user] " + msg + var/dchatmsg = "[user] [msg]" for(var/mob/M in GLOB.dead_mob_list) if(!M.client || isnewplayer(M)) continue var/T = get_turf(user) if(M.stat == DEAD && M.client && (M.client.prefs.chat_toggles & CHAT_GHOSTSIGHT) && !(M in viewers(T, null)) && (user.client)) //SKYRAT CHANGE - only user controlled mobs show their emotes to all-seeing ghosts, to reduce chat spam - M.show_message(msg) + M.show_message("[FOLLOW_LINK(M, user)] [dchatmsg]") if(emote_type == EMOTE_AUDIBLE) - user.audible_message(msg) + user.audible_message(msg, audible_message_flags = EMOTE_MESSAGE) else - user.visible_message(msg) + user.visible_message(msg, visible_message_flags = EMOTE_MESSAGE) /datum/emote/proc/replace_pronoun(mob/user, message) if(findtext(message, "their")) diff --git a/code/modules/antagonists/disease/disease_mob.dm b/code/modules/antagonists/disease/disease_mob.dm index 1ae020554..410eda7d0 100644 --- a/code/modules/antagonists/disease/disease_mob.dm +++ b/code/modules/antagonists/disease/disease_mob.dm @@ -129,6 +129,11 @@ the new instance inside the host to be updated to the template's stats. link = FOLLOW_LINK(src, to_follow) else 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) + // Recompose the message, because it's scrambled by default message = compose_message(speaker, message_language, raw_message, radio_freq, spans, message_mode, FALSE, source) to_chat(src, "[link] [message]") diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index d50fdc5f0..4917cbaa5 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -50,6 +50,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) var/radiosounds = TRUE var/max_chat_length = CHAT_MESSAGE_MAX_LENGTH var/see_chat_non_mob = TRUE + var/see_rc_emotes = TRUE var/tgui_fancy = TRUE var/tgui_lock = TRUE var/windowflashing = TRUE @@ -1041,6 +1042,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) dat += "Chat Bubbles: [chat_on_map ? "Enabled" : "Disabled"]
" dat += "Chat Bubbles message char limit: [max_chat_length]
" dat += "Chat Bubbles for non-mobs: [see_chat_non_mob ? "Enabled" : "Disabled"]
" + dat += "Chat Bubbles emotes: [see_rc_emotes ? "Enabled" : "Disabled"]
" dat += "
" dat += "Autocorrect: [(autocorrect) ? "On" : "Off"]
" dat += "Radio Sounds: [radiosounds ? "Enabled" : "Disabled"]
" @@ -2835,6 +2837,8 @@ GLOBAL_LIST_EMPTY(preferences_datums) radiosounds = !radiosounds if("see_chat_non_mob") see_chat_non_mob = !see_chat_non_mob + if("see_rc_emotes") + see_rc_emotes = !see_rc_emotes if("tgui_fancy") tgui_fancy = !tgui_fancy if("tgui_lock") diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm index 47afd6d98..190a6c2f8 100644 --- a/code/modules/client/preferences_savefile.dm +++ b/code/modules/client/preferences_savefile.dm @@ -116,6 +116,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car S["radiosounds"] >> radiosounds S["max_chat_length"] >> max_chat_length S["see_chat_non_mob"] >> see_chat_non_mob + S["see_rc_emotes"] >> see_rc_emotes S["parallax"] >> parallax @@ -224,6 +225,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car WRITE_FILE(S["radiosounds"], radiosounds) WRITE_FILE(S["max_chat_length"], max_chat_length) WRITE_FILE(S["see_chat_non_mob"], see_chat_non_mob) + WRITE_FILE(S["see_rc_emotes"], see_rc_emotes) WRITE_FILE(S["tgui_fancy"], tgui_fancy) WRITE_FILE(S["tgui_lock"], tgui_lock) WRITE_FILE(S["buttons_locked"], buttons_locked) diff --git a/code/modules/flufftext/Hallucination.dm b/code/modules/flufftext/Hallucination.dm index e5aa0c3d0..4119dfbbc 100644 --- a/code/modules/flufftext/Hallucination.dm +++ b/code/modules/flufftext/Hallucination.dm @@ -703,7 +703,7 @@ GLOBAL_LIST_INIT(hallucination_list, list( var/image/speech_overlay = image('icons/mob/talk.dmi', person, "default0", layer = ABOVE_MOB_LAYER) INVOKE_ASYNC(GLOBAL_PROC, /proc/flick_overlay, speech_overlay, list(target.client), 30) if (target.client?.prefs.chat_on_map) - target.create_chat_message(person, understood_language, chosen, spans, 0) + target.create_chat_message(person, understood_language, chosen, spans) to_chat(target, message) qdel(src) diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm index c4032177e..df278390d 100644 --- a/code/modules/mob/living/say.dm +++ b/code/modules/mob/living/say.dm @@ -249,6 +249,10 @@ GLOBAL_LIST_INIT(department_radio_keys, list( deaf_message = "You can't hear yourself!" 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) + if (client?.prefs.radiosounds && stat != UNCONSCIOUS && can_hear() && radio_freq) playsound_local(src,'sound/voice/radio.ogg', 30, 0) @@ -304,7 +308,8 @@ GLOBAL_LIST_INIT(department_radio_keys, list( //speech bubble var/list/speech_bubble_recipients = list() for(var/mob/M in listening) - speech_bubble_recipients.Add(M.client) + if(M.client && !M.client.prefs.chat_on_map) + speech_bubble_recipients.Add(M.client) var/image/I = image('icons/mob/talk.dmi', src, "[bubble_type][say_test(message)]", FLY_LAYER) I.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA INVOKE_ASYNC(GLOBAL_PROC, /.proc/flick_overlay, I, speech_bubble_recipients, 30) diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm index 1da1c8326..46c4858b4 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm @@ -80,7 +80,7 @@ Difficulty: Medium return FALSE return ..() -/mob/living/simple_animal/hostile/megafauna/dragon/visible_message(message, self_message, blind_message, vision_distance = DEFAULT_MESSAGE_RANGE, list/ignored_mobs) +/mob/living/simple_animal/hostile/megafauna/dragon/visible_message(message, self_message, blind_message, vision_distance = DEFAULT_MESSAGE_RANGE, list/ignored_mobs, visible_message_flags = NONE) if(swooping & SWOOP_INVULNERABLE) //to suppress attack messages without overriding every single proc that could send a message saying we got hit return return ..() diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index f3ca2844d..0dda0ed3e 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -127,7 +127,7 @@ * * vision_distance (optional) define how many tiles away the message can be seen. * * ignored_mobs (optional) doesn't show any message to any given mob in the list. */ -/atom/proc/visible_message(message, self_message, blind_message, vision_distance = DEFAULT_MESSAGE_RANGE, list/ignored_mobs) +/atom/proc/visible_message(message, self_message, blind_message, vision_distance = DEFAULT_MESSAGE_RANGE, list/ignored_mobs, visible_message_flags = NONE) var/turf/T = get_turf(src) if(!T) return @@ -139,6 +139,11 @@ hearers -= ignored_mobs if(self_message) hearers -= src + + var/raw_msg = message + if(visible_message_flags & EMOTE_MESSAGE) + message = "[src] [message]" + for(var/mob/M in hearers) if(!M.client) continue @@ -152,10 +157,14 @@ if(!msg) continue + + if(visible_message_flags & EMOTE_MESSAGE && runechat_prefs_check(M, visible_message_flags)) + M.create_chat_message(src, raw_message = raw_msg, runechat_flags = visible_message_flags) + M.show_message(msg, MSG_VISUAL,blind_message, MSG_AUDIBLE) ///Adds the functionality to self_message. -mob/visible_message(message, self_message, blind_message, vision_distance = DEFAULT_MESSAGE_RANGE, list/ignored_mobs) +/mob/visible_message(message, self_message, blind_message, vision_distance = DEFAULT_MESSAGE_RANGE, list/ignored_mobs, visible_message_flags = NONE) . = ..() if(self_message) show_message(self_message, MSG_VISUAL, blind_message, MSG_AUDIBLE) @@ -171,7 +180,7 @@ mob/visible_message(message, self_message, blind_message, vision_distance = DEFA * * hearing_distance (optional) is the range, how many tiles away the message can be heard. * * ignored_mobs (optional) doesn't show any message to any given mob in the list. */ -/atom/proc/audible_message(message, deaf_message, hearing_distance = DEFAULT_MESSAGE_RANGE, self_message, list/ignored_mobs) +/atom/proc/audible_message(message, deaf_message, hearing_distance = DEFAULT_MESSAGE_RANGE, self_message, list/ignored_mobs, visible_message_flags = NONE, audible_message_flags = NONE) var/turf/T = get_turf(src) if(!T) return @@ -183,7 +192,15 @@ mob/visible_message(message, self_message, blind_message, vision_distance = DEFA hearers -= ignored_mobs if(self_message) hearers -= src + + var/raw_msg = message + if(audible_message_flags & EMOTE_MESSAGE) + message = "[src] [message]" + for(var/mob/M in hearers) + if(audible_message_flags & EMOTE_MESSAGE && runechat_prefs_check(M, audible_message_flags)) + M.create_chat_message(src, raw_message = raw_msg, runechat_flags = audible_message_flags) + M.show_message(message, MSG_AUDIBLE, deaf_message, MSG_VISUAL) /** @@ -198,11 +215,27 @@ mob/visible_message(message, self_message, blind_message, vision_distance = DEFA * * hearing_distance (optional) is the range, how many tiles away the message can be heard. * * ignored_mobs (optional) doesn't show any message to any given mob in the list. */ -/mob/audible_message(message, deaf_message, hearing_distance = DEFAULT_MESSAGE_RANGE, self_message, list/ignored_mobs) +/mob/audible_message(message, deaf_message, hearing_distance = DEFAULT_MESSAGE_RANGE, self_message, list/ignored_mobs, audible_message_flags = NONE) . = ..() if(self_message) show_message(self_message, MSG_AUDIBLE, deaf_message, MSG_VISUAL) + +///Returns the client runechat visible messages preference according to the message type. +/atom/proc/runechat_prefs_check(mob/target, visible_message_flags = NONE) + if(!target.client?.prefs.chat_on_map || !target.client.prefs.see_chat_non_mob) + return FALSE + if(visible_message_flags & EMOTE_MESSAGE && !target.client.prefs.see_rc_emotes) + return FALSE + return TRUE + +/mob/runechat_prefs_check(mob/target, message, visible_message_flags = NONE) + if(!target.client?.prefs.chat_on_map) + return FALSE + if(visible_message_flags & EMOTE_MESSAGE && !target.client.prefs.see_rc_emotes) + return FALSE + return TRUE + /mob/proc/Life() set waitfor = FALSE