From a8127a39ab0af02fa7d59df4e2ff43d8a31cb8b4 Mon Sep 17 00:00:00 2001 From: XDTM Date: Sat, 29 Sep 2018 00:07:43 +0200 Subject: [PATCH] [Ready]Adds hypnosis and the hypnotic stupor brain trauma (#40362) cl XDTM add: Added a new severe brain trauma: hypnotic stupor. Victims of hypnotic stupor occasionally fall into a trance, and upon hearing a sentence they'll focus on it to the point of obsession, until it is replaced by a new hypnosis or the trauma is cured. /cl Adds the potential for some fancy rp gameplay. The idea is that they should take a passing message way too seriously, while leaving room for interpretation to the player. Hearing an isolated "greytide" over the radio might prompt a player to take up arms against the rampaging greyshirts, another might interpret it as having to become the greytide. Someone who realizes what's up might use this to give clear orders to the victim, although they'll only last until the following trance. I plan on adding more methods to inflict hypnosis with the same trance->"focus on a sentence" mechanics, perhaps as a traitor/CMO pendulum item, or as a wizard/cult spell. --- code/datums/brain_damage/hypnosis.dm | 48 ++++++++++++++++++ code/datums/brain_damage/severe.dm | 19 ++++++- code/datums/status_effects/debuffs.dm | 50 ++++++++++++++++++- .../browserassets/css/browserOutput.css | 7 +++ code/modules/mob/living/carbon/say.dm | 8 ++- code/modules/mob/living/say.dm | 4 ++ interface/stylesheet.dm | 7 +++ tgstation.dme | 1 + 8 files changed, 137 insertions(+), 7 deletions(-) create mode 100644 code/datums/brain_damage/hypnosis.dm diff --git a/code/datums/brain_damage/hypnosis.dm b/code/datums/brain_damage/hypnosis.dm new file mode 100644 index 000000000000..61e59026ebba --- /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 a8adbfbce81c..9c8bfffcb33e 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 63b826a89892..286b92861b2a 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 ddf924fcdc22..1df889e7d58c 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 f6e43f487f49..2c12a0d7995c 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 d06a68803f5c..5aebd063f370 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 1ab1aa620ef6..d200a8c368e2 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 568faad3fc94..1a89243edc0d 100644 --- 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"