diff --git a/aurorastation.dme b/aurorastation.dme
index 66820e30554..089372b3441 100644
--- a/aurorastation.dme
+++ b/aurorastation.dme
@@ -1771,6 +1771,7 @@
#include "code\modules\mob\animations.dm"
#include "code\modules\mob\death.dm"
#include "code\modules\mob\emote.dm"
+#include "code\modules\mob\floating_messages.dm"
#include "code\modules\mob\gender.dm"
#include "code\modules\mob\hear_say.dm"
#include "code\modules\mob\holder.dm"
diff --git a/code/__defines/misc.dm b/code/__defines/misc.dm
index 2a708ac4ba2..827df15124b 100644
--- a/code/__defines/misc.dm
+++ b/code/__defines/misc.dm
@@ -58,6 +58,7 @@
#define PARALLAX_DUST 0x2
#define PROGRESS_BARS 0x4
#define PARALLAX_IS_STATIC 0x8
+#define FLOATING_MESSAGES 0x10
#define TOGGLES_DEFAULT (SOUND_ADMINHELP|SOUND_MIDI|SOUND_AMBIENCE|SOUND_LOBBY|CHAT_OOC|CHAT_DEAD|CHAT_GHOSTEARS|CHAT_GHOSTSIGHT|CHAT_PRAYER|CHAT_RADIO|CHAT_ATTACKLOGS|CHAT_LOOC)
diff --git a/code/modules/client/preference_setup/global/02_settings.dm b/code/modules/client/preference_setup/global/02_settings.dm
index 4d67028f079..f6b67e53e3e 100644
--- a/code/modules/client/preference_setup/global/02_settings.dm
+++ b/code/modules/client/preference_setup/global/02_settings.dm
@@ -94,6 +94,7 @@
"Space Parallax: [(pref.toggles_secondary & PARALLAX_SPACE) ? "Yes" : "No"]
",
"Space Dust: [(pref.toggles_secondary & PARALLAX_DUST) ? "Yes" : "No"]
",
"Progress Bars: [(pref.toggles_secondary & PROGRESS_BARS) ? "Yes" : "No"]
",
+ "Floating Messages: [(pref.toggles_secondary & FLOATING_MESSAGES) ? "Yes" : "No"]
",
"Static Space: [(pref.toggles_secondary & PARALLAX_IS_STATIC) ? "Yes" : "No"]
"
)
diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm
index 5996f9cc228..4487f25f708 100644
--- a/code/modules/client/preferences.dm
+++ b/code/modules/client/preferences.dm
@@ -128,7 +128,7 @@ datum/preferences
// SPAAAACE
var/parallax_speed = 2
- var/toggles_secondary = PARALLAX_SPACE | PARALLAX_DUST | PROGRESS_BARS
+ var/toggles_secondary = PARALLAX_SPACE | PARALLAX_DUST | PROGRESS_BARS | FLOATING_MESSAGES
var/clientfps = 0
var/list/pai = list() // A list for holding pAI related data.
diff --git a/code/modules/client/preferences_toggles.dm b/code/modules/client/preferences_toggles.dm
index 0fffff8d743..e776abcf18e 100644
--- a/code/modules/client/preferences_toggles.dm
+++ b/code/modules/client/preferences_toggles.dm
@@ -203,6 +203,15 @@
else
to_chat(src, "You will no longer see progress bars on delayed actions.")
+/client/verb/toggle_floating_messages()
+ set name = "Toggle Floating Messages"
+ set desc = "Toggles messages appearing above mobs when they speak."
+ set category = "Preferences"
+
+ prefs.toggles_secondary ^= FLOATING_MESSAGES
+ prefs.save_preferences()
+ to_chat(src, SPAN_NOTICE("Floating messages are now [prefs.toggles_secondary & FLOATING_MESSAGES ? "enabled" : "disabled"]."))
+
/client/verb/toggle_static_spess()
set name = "Toggle Parallax Movement"
set category = "Preferences"
diff --git a/code/modules/hallucinations/mob.dm b/code/modules/hallucinations/mob.dm
index 173aca0c322..42fbad45c99 100644
--- a/code/modules/hallucinations/mob.dm
+++ b/code/modules/hallucinations/mob.dm
@@ -8,7 +8,7 @@
var/orig_message = message
message = pick(SShallucinations.hallucinated_phrases)
log_say("Hallucination level changed [orig_message] by [speaker] to [message] for [key_name(src)].", ckey=key_name(src))
- ..()
+ return ..()
/mob/living/carbon/hear_radio(var/message, var/verb="says", var/datum/language/language, var/part_a, var/part_b, var/mob/speaker, var/hard_to_hear = 0, var/vname ="")
if(hallucination >= 60 && prob(1))
diff --git a/code/modules/mob/floating_messages.dm b/code/modules/mob/floating_messages.dm
new file mode 100644
index 00000000000..33d8b64d4c1
--- /dev/null
+++ b/code/modules/mob/floating_messages.dm
@@ -0,0 +1,70 @@
+// Thanks to Burger from Burgerstation for the foundation for this
+var/list/floating_chat_colors = list()
+
+/atom/movable
+ var/list/stored_chat_text
+
+/atom/movable/proc/animate_chat(message, datum/language/language, small, list/show_to, duration)
+ set waitfor = FALSE
+
+ var/style //additional style params for the message
+ var/fontsize = 6
+ if(small)
+ fontsize = 5
+ var/limit = 50
+ if(copytext(message, length(message) - 1) == "!!")
+ fontsize = 8
+ limit = 30
+ style += "font-weight: bold;"
+
+ if(length(message) > limit)
+ message = "[copytext(message, 1, limit)]..."
+
+ if(!floating_chat_colors[name])
+ floating_chat_colors[name] = get_random_colour(0, 160, 230)
+ style += "color: [floating_chat_colors[name]];"
+
+ // create 2 messages, one that appears if you know the language, and one that appears when you don't know the language
+ var/image/understood = generate_floating_text(src, capitalize(message), style, fontsize, duration, show_to)
+ var/image/gibberish
+ if(!isnull(language))
+ gibberish = generate_floating_text(src, language.scramble(message), style, fontsize, duration, show_to)
+
+ for(var/client/C in show_to)
+ if(!(C.prefs.toggles_secondary & FLOATING_MESSAGES))
+ continue
+
+ if(isnull(language))
+ C.images += understood
+ continue
+
+ if(C.mob.say_understands(null, language))
+ C.images += understood
+ else
+ C.images += gibberish
+
+/proc/generate_floating_text(atom/movable/holder, message, style, size, duration, show_to)
+ var/image/I = image(null, holder)
+ I.layer = FLY_LAYER
+ I.alpha = 0
+ I.maptext_width = 80
+ I.maptext_height = 64
+ I.plane = FLOAT_PLANE
+ I.pixel_x = -round(I.maptext_width/2) + 16
+
+ style = "font-family: 'Small Fonts'; -dm-text-outline: 1 black; font-size: [size]px; [style]"
+ I.maptext = "