diff --git a/code/__DEFINES/say.dm b/code/__DEFINES/say.dm
index 4ad9ebfdc..975fb5d4b 100644
--- a/code/__DEFINES/say.dm
+++ b/code/__DEFINES/say.dm
@@ -65,9 +65,9 @@
#define SPAN_ORC "orc"
//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
@@ -94,3 +94,6 @@
// 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)
diff --git a/code/__HELPERS/_logging.dm b/code/__HELPERS/_logging.dm
index 567c87fec..0c92278ef 100644
--- a/code/__HELPERS/_logging.dm
+++ b/code/__HELPERS/_logging.dm
@@ -1,9 +1,11 @@
//wrapper macros for easier grepping
#define DIRECT_OUTPUT(A, B) A << B
+#define DIRECT_INPUT(A, B) A >> B
#define SEND_IMAGE(target, image) DIRECT_OUTPUT(target, image)
#define SEND_SOUND(target, sound) DIRECT_OUTPUT(target, sound)
#define SEND_TEXT(target, text) DIRECT_OUTPUT(target, text)
#define WRITE_FILE(file, text) DIRECT_OUTPUT(file, text)
+#define READ_FILE(file, text) DIRECT_INPUT(file, text)
#define WRITE_LOG(log, text) text2file(text,log) //rustg_log_write
//print a warning message to world.log
diff --git a/code/datums/chatmessage.dm b/code/datums/chatmessage.dm
index b974a6ebd..64edcbf03 100644
--- a/code/datums/chatmessage.dm
+++ b/code/datums/chatmessage.dm
@@ -113,7 +113,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]"
// 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
@@ -202,7 +205,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 = list(), message_mode)
+/mob/proc/create_chat_message(atom/movable/speaker, datum/language/message_language, raw_message, list/spans = list(), message_mode, 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?.Copy()
@@ -218,7 +221,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
diff --git a/code/datums/emotes.dm b/code/datums/emotes.dm
index 469db802b..1618d6ff7 100644
--- a/code/datums/emotes.dm
+++ b/code/datums/emotes.dm
@@ -76,7 +76,7 @@
if(!nomsg)
user.log_message(msg, LOG_EMOTE)
- msg = "[user] " + msg
+ var/dchatmsg = "[user] [msg]"
var/pitch = 1 //bespoke vary system so deep voice/high voiced humans
if(isliving(user))
@@ -97,11 +97,11 @@
continue
var/T = get_turf(user)
if(M.stat == DEAD && M.client && (M.client.prefs?.chat_toggles & CHAT_GHOSTSIGHT) && !(M in viewers(T, null)))
- 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)
/mob/living/proc/get_emote_pitch()
return clamp(voice_pitch, 0.5, 2)
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index 71bca41b2..113cb529c 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -188,19 +188,27 @@ GLOBAL_VAR_INIT(mobids, 1)
* * vision_distance (optional) define how many tiles away the message can be seen.
* * ignored_mob (optional) doesn't show any message to a given mob if TRUE.
*/
-/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
+
if(!islist(ignored_mobs))
ignored_mobs = list(ignored_mobs)
var/list/hearers = get_hearers_in_view(vision_distance, src) //caches the hearers and then removes ignored mobs.
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
+
//This entire if/else chain could be in two lines but isn't for readibilties sake.
var/msg = message
if(M.see_invisible < invisibility)//if src is invisible to M
@@ -211,10 +219,15 @@ GLOBAL_VAR_INIT(mobids, 1)
// msg = blind_message
if(!msg)
continue
+
+ if(visible_message_flags & EMOTE_MESSAGE)
+ 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)
@@ -229,13 +242,19 @@ GLOBAL_VAR_INIT(mobids, 1)
* * deaf_message (optional) is what deaf people will see.
* * hearing_distance (optional) is the range, how many tiles away the message can be heard.
*/
-/atom/proc/audible_message(message, deaf_message, hearing_distance = DEFAULT_MESSAGE_RANGE, self_message)
+/atom/proc/audible_message(message, deaf_message, hearing_distance = DEFAULT_MESSAGE_RANGE, self_message, audible_message_flags = NONE)
var/list/hearers = get_hearers_in_view(hearing_distance, src)
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)
+ M.create_chat_message(src, raw_message = raw_msg, runechat_flags = audible_message_flags)
M.show_message(message, MSG_AUDIBLE, deaf_message, MSG_VISUAL)
+
/**
* Show a message to all mobs in earshot of this one
*
@@ -247,7 +266,7 @@ GLOBAL_VAR_INIT(mobids, 1)
* * deaf_message (optional) is what deaf people will see.
* * hearing_distance (optional) is the range, how many tiles away the message can be heard.
*/
-/mob/audible_message(message, deaf_message, hearing_distance = DEFAULT_MESSAGE_RANGE, self_message)
+/mob/audible_message(message, deaf_message, hearing_distance = DEFAULT_MESSAGE_RANGE, self_message, audible_message_flags = NONE)
. = ..()
if(self_message)
show_message(self_message, MSG_AUDIBLE, deaf_message, MSG_VISUAL)
diff --git a/icons/UI_Icons/chat/chat_icons.dmi b/icons/UI_Icons/chat/chat_icons.dmi
index 3b3330422..c8427c54e 100644
Binary files a/icons/UI_Icons/chat/chat_icons.dmi and b/icons/UI_Icons/chat/chat_icons.dmi differ