diff --git a/code/datums/brain_damage/hypnosis.dm b/code/datums/brain_damage/hypnosis.dm
new file mode 100644
index 00000000000..61e59026ebb
--- /dev/null
+++ b/code/datums/brain_damage/hypnosis.dm
@@ -0,0 +1,48 @@
+/datum/brain_trauma/hypnosis
+ name = "Hypnosis"
+ desc = "Patient's unconscious is completely enthralled by a word or sentence, focusing their thoughts and actions on it."
+ scan_desc = "looping thought pattern"
+ gain_text = ""
+ lose_text = ""
+ resilience = TRAUMA_RESILIENCE_SURGERY
+
+ var/hypnotic_phrase = ""
+
+/datum/brain_trauma/hypnosis/New(phrase)
+ if(!phrase)
+ qdel(src)
+ hypnotic_phrase = phrase
+ ..()
+
+/datum/brain_trauma/hypnosis/on_gain()
+ message_admins("[ADMIN_LOOKUPFLW(owner)] was hypnotized with the phrase '[hypnotic_phrase]'.")
+ log_game("[key_name(owner)] was hypnotized with the phrase '[hypnotic_phrase]'.")
+ to_chat(owner, "[hypnotic_phrase]")
+ to_chat(owner, "[pick("You feel your thoughts focusing on this phrase... you can't seem to get it out of your head.",\
+ "Your head hurts, but this is all you can think of. It must be vitally important.",\
+ "You feel a part of your mind repeating this over and over. You need to follow these words.",\
+ "Something about this sounds... right, for some reason. You feel like you should follow these words.",\
+ "These words keep echoing in your mind. You find yourself completely fascinated by them.")]")
+ to_chat(owner, "You've been hypnotized by this sentence. You must follow these words. If it isn't a clear order, you can freely interpret how to do so,\
+ as long as you act like the words are your highest priority.")
+ ..()
+
+/datum/brain_trauma/hypnosis/on_lose()
+ message_admins("[ADMIN_LOOKUPFLW(owner)] is no longer hypnotized with the phrase '[hypnotic_phrase]'.")
+ log_game("[key_name(owner)] is no longer hypnotized with the phrase '[hypnotic_phrase]'.")
+ to_chat(owner, "You suddenly snap out of your hypnosis. The phrase '[hypnotic_phrase]' no longer feels important to you.")
+ ..()
+
+/datum/brain_trauma/hypnosis/on_life()
+ ..()
+ if(prob(2))
+ switch(rand(1,2))
+ if(1)
+ to_chat(owner, "...[lowertext(hypnotic_phrase)]...")
+ if(2)
+ new /datum/hallucination/chat(owner, TRUE, FALSE, "[hypnotic_phrase]")
+
+/datum/brain_trauma/hypnosis/on_hear(message, speaker, message_language, raw_message, radio_freq)
+ var/regex/target_phrase = new("(\\b[hypnotic_phrase]\\b)","ig")
+ message = target_phrase.Replace(message, "$1")
+ return message
\ No newline at end of file
diff --git a/code/datums/brain_damage/severe.dm b/code/datums/brain_damage/severe.dm
index a8adbfbce81..9c8bfffcb33 100644
--- a/code/datums/brain_damage/severe.dm
+++ b/code/datums/brain_damage/severe.dm
@@ -203,4 +203,21 @@
/datum/brain_trauma/severe/pacifism/on_lose()
owner.remove_trait(TRAIT_PACIFISM, TRAUMA_TRAIT)
- ..()
\ No newline at end of file
+ ..()
+
+/datum/brain_trauma/severe/hypnotic_stupor
+ name = "Hypnotic Stupor"
+ desc = "Patient is prone to episodes of extreme stupor that leaves them extremely suggestible."
+ scan_desc = "oneiric feedback loop"
+ gain_text = "You feel somewhat dazed."
+ lose_text = "You feel like a fog was lifted from your mind."
+
+/datum/brain_trauma/severe/hypnotic_stupor/on_lose() //hypnosis must be cleared separately, but brain surgery should get rid of both anyway
+ ..()
+ owner.remove_status_effect(/datum/status_effect/trance)
+
+/datum/brain_trauma/severe/hypnotic_stupor/on_life()
+ ..()
+ if(prob(1) && !owner.has_status_effect(/datum/status_effect/trance))
+ owner.apply_status_effect(/datum/status_effect/trance, rand(100,300), FALSE)
+
\ No newline at end of file
diff --git a/code/datums/status_effects/debuffs.dm b/code/datums/status_effects/debuffs.dm
index 63b826a8989..286b92861b2 100644
--- a/code/datums/status_effects/debuffs.dm
+++ b/code/datums/status_effects/debuffs.dm
@@ -524,4 +524,52 @@
/datum/status_effect/gonbolaPacify/on_remove()
owner.remove_trait(TRAIT_PACIFISM, "gonbolaPacify")
owner.remove_trait(TRAIT_MUTE, "gonbolaMute")
- owner.remove_trait(TRAIT_JOLLY, "gonbolaJolly")
\ No newline at end of file
+ owner.remove_trait(TRAIT_JOLLY, "gonbolaJolly")
+
+/datum/status_effect/trance
+ id = "trance"
+ status_type = STATUS_EFFECT_UNIQUE
+ duration = 300
+ tick_interval = 10
+ examine_text = "SUBJECTPRONOUN seems slow and unfocused."
+ var/stun = TRUE
+
+/datum/status_effect/trance/tick()
+ if(stun)
+ owner.Stun(60, TRUE, TRUE)
+ owner.dizziness = 20
+
+/datum/status_effect/trance/on_apply()
+ if(!iscarbon(owner))
+ return FALSE
+ RegisterSignal(owner, COMSIG_MOVABLE_HEAR, .proc/hypnotize)
+ owner.add_trait(TRAIT_MUTE, "trance")
+ if(!owner.has_quirk(/datum/quirk/monochromatic))
+ owner.add_client_colour(/datum/client_colour/monochrome)
+ owner.visible_message("[stun ? "[owner] stands still as [owner.p_their()] eyes seem to focus on a distant point." : ""]", \
+ "[pick("You feel your thoughts slow down...", "You suddenly feel extremely dizzy...", "You feel like you're in the middle of a dream...","You feel incredibly relaxed...")]")
+ return TRUE
+
+/datum/status_effect/trance/on_creation(mob/living/new_owner, _duration, _stun = TRUE)
+ duration = _duration
+ stun = _stun
+ . = ..()
+
+/datum/status_effect/trance/on_remove()
+ UnregisterSignal(owner, COMSIG_MOVABLE_HEAR)
+ owner.remove_trait(TRAIT_MUTE, "trance")
+ owner.dizziness = 0
+ if(!owner.has_quirk(/datum/quirk/monochromatic))
+ owner.remove_client_colour(/datum/client_colour/monochrome)
+ to_chat(owner, "You snap out of your trance!")
+
+/datum/status_effect/trance/proc/hypnotize(datum/source, message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, message_mode)
+ if(!owner.can_hear())
+ return
+ if(speaker == owner)
+ return
+ var/mob/living/carbon/C = owner
+ C.cure_trauma_type(/datum/brain_trauma/hypnosis, TRAUMA_RESILIENCE_SURGERY) //clear previous hypnosis
+ addtimer(CALLBACK(C, /mob/living/carbon.proc/gain_trauma, /datum/brain_trauma/hypnosis, TRAUMA_RESILIENCE_SURGERY, raw_message), 10)
+ addtimer(CALLBACK(C, /mob/living.proc/Stun, 60, TRUE, TRUE), 15) //Take some time to think about it
+ qdel(src)
diff --git a/code/modules/goonchat/browserassets/css/browserOutput.css b/code/modules/goonchat/browserassets/css/browserOutput.css
index fe90e8a333e..0451c45069a 100644
--- a/code/modules/goonchat/browserassets/css/browserOutput.css
+++ b/code/modules/goonchat/browserassets/css/browserOutput.css
@@ -393,6 +393,13 @@ h1.alert, h2.alert {color: #000000;}
.redtext {color: #FF0000; font-size: 24px;}
.clown {color: #FF69Bf; font-size: 24px; font-family: "Comic Sans MS", cursive, sans-serif; font-weight: bold;}
.his_grace {color: #15D512; font-family: "Courier New", cursive, sans-serif; font-style: italic;}
+.hypnophrase {color: #0d0d0d; font-weight: bold; animation: hypnocolor 1500ms infinite;}
+@keyframes hypnocolor {
+ 0% { color: #0d0d0d; }
+ 25% { color: #410194; }
+ 50% { color: #7f17d8; }
+ 75% { color: #410194; }
+}
.icon {height: 1em; width: auto;}
diff --git a/code/modules/mob/living/carbon/say.dm b/code/modules/mob/living/carbon/say.dm
index f6e43f487f4..2c12a0d7995 100644
--- a/code/modules/mob/living/carbon/say.dm
+++ b/code/modules/mob/living/carbon/say.dm
@@ -39,10 +39,8 @@
else
. = initial(dt.flags) & TONGUELESS_SPEECH
-/mob/living/carbon/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, message_mode)
- . = ..()
- if(!client)
- return
+/mob/living/carbon/hear_intercept(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, message_mode)
for(var/T in get_traumas())
var/datum/brain_trauma/trauma = T
- message = trauma.on_hear(message, speaker, message_language, raw_message, radio_freq)
\ No newline at end of file
+ message = trauma.on_hear(message, speaker, message_language, raw_message, radio_freq)
+ return message
diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm
index 5ed5534e993..49edbfe81de 100644
--- a/code/modules/mob/living/say.dm
+++ b/code/modules/mob/living/say.dm
@@ -228,9 +228,13 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
// Recompose message for AI hrefs, language incomprehension.
message = compose_message(speaker, message_language, raw_message, radio_freq, spans, message_mode)
+ message = hear_intercept(message, speaker, message_language, raw_message, radio_freq, spans, message_mode)
show_message(message, 2, deaf_message, deaf_type)
return message
+/mob/living/proc/hear_intercept(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, message_mode)
+ 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)
var/static/list/eavesdropping_modes = list(MODE_WHISPER = TRUE, MODE_WHISPER_CRIT = TRUE)
var/eavesdrop_range = 0
diff --git a/interface/stylesheet.dm b/interface/stylesheet.dm
index 5eb4a355766..bca391f6539 100644
--- a/interface/stylesheet.dm
+++ b/interface/stylesheet.dm
@@ -153,6 +153,13 @@ h1.alert, h2.alert {color: #000000;}
.redtext {color: #FF0000; font-size: 3;}
.clown {color: #FF69Bf; font-size: 3; font-family: "Comic Sans MS", cursive, sans-serif; font-weight: bold;}
.his_grace {color: #15D512; font-family: "Courier New", cursive, sans-serif; font-style: italic;}
+.hypnophrase {color: #3bb5d3; font-weight: bold; animation: hypnocolor 1500ms infinite;}
+@keyframes hypnocolor {
+ 0% { color: #0d0d0d; }
+ 25% { color: #410194; }
+ 50% { color: #7f17d8; }
+ 75% { color: #410194; }
+}
.icon {height: 1em; width: auto;}
diff --git a/tgstation.dme b/tgstation.dme
index c2f49a9d2a3..538006dcdbb 100755
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -318,6 +318,7 @@
#include "code\datums\actions\beam_rifle.dm"
#include "code\datums\actions\ninja.dm"
#include "code\datums\brain_damage\brain_trauma.dm"
+#include "code\datums\brain_damage\hypnosis.dm"
#include "code\datums\brain_damage\imaginary_friend.dm"
#include "code\datums\brain_damage\mild.dm"
#include "code\datums\brain_damage\phobia.dm"