diff --git a/code/__DEFINES/combat.dm b/code/__DEFINES/combat.dm index 6e317a7a08a..193daf37c67 100644 --- a/code/__DEFINES/combat.dm +++ b/code/__DEFINES/combat.dm @@ -54,8 +54,6 @@ #define EFFECT_UNCONSCIOUS "unconscious" #define EFFECT_PARALYZE "paralyze" #define EFFECT_IMMOBILIZE "immobilize" -#define EFFECT_STUTTER "stutter" -#define EFFECT_SLUR "slur" #define EFFECT_EYE_BLUR "eye_blur" #define EFFECT_DROWSY "drowsy" #define EFFECT_JITTER "jitter" diff --git a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm index a39377c7c50..de9f1997a61 100644 --- a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm +++ b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm @@ -89,5 +89,8 @@ #define COMSIG_LIVING_Z_IMPACT "living_z_impact" #define NO_Z_IMPACT_DAMAGE (1<<0) +/// From mob/living/treat_message(): (list/message_args) +#define COMSIG_LIVING_TREAT_MESSAGE "living_treat_message" + ///From obj/item/toy/crayon/spraycan #define COMSIG_LIVING_MOB_PAINTED "living_mob_painted" diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm index 68e863459ba..f58f97725eb 100644 --- a/code/__DEFINES/traits.dm +++ b/code/__DEFINES/traits.dm @@ -647,7 +647,11 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai /// The item is magically cursed #define CURSED_ITEM_TRAIT(item_type) "cursed_item_[item_type]" #define ABSTRACT_ITEM_TRAIT "abstract-item" +/// A trait given by any status effect #define STATUS_EFFECT_TRAIT "status-effect" +/// A trait given by a specific status effect (not sure why we need both but whatever!) +#define TRAIT_STATUS_EFFECT(effect_id) "[effect_id]-trait" + #define CLOTHING_TRAIT "clothing" #define HELMET_TRAIT "helmet" /// inherited from the mask diff --git a/code/__DEFINES/vv.dm b/code/__DEFINES/vv.dm index 5f9322eb00c..3df60080109 100644 --- a/code/__DEFINES/vv.dm +++ b/code/__DEFINES/vv.dm @@ -123,6 +123,9 @@ #define VV_HK_OFFER_GHOSTS "offer_ghosts" #define VV_HK_SDQL_SPELL "sdql_spell" +// /mob/living +#define VV_HK_GIVE_SPEECH_IMPEDIMENT "impede_speech" + // /mob/living/carbon #define VV_HK_MAKE_AI "aiify" #define VV_HK_MODIFY_BODYPART "mod_bodypart" diff --git a/code/__HELPERS/honkerblast.dm b/code/__HELPERS/honkerblast.dm index bd05d07417a..b1bdd1cb9dc 100644 --- a/code/__HELPERS/honkerblast.dm +++ b/code/__HELPERS/honkerblast.dm @@ -21,7 +21,7 @@ for(var/mob/living/carbon/victim in severely_honked) victim.Unconscious(40) victim.Stun(100) - victim.stuttering += 15 + victim.adjust_timed_status_effect(30 SECONDS, /datum/status_effect/speech/stutter) victim.Jitter(500) var/obj/item/organ/ears/ears = victim.getorganslot(ORGAN_SLOT_EARS) ears?.adjustEarDamage(10, 15) diff --git a/code/datums/brain_damage/creepy_trauma.dm b/code/datums/brain_damage/creepy_trauma.dm index d20dabc3634..8124140451c 100644 --- a/code/datums/brain_damage/creepy_trauma.dm +++ b/code/datums/brain_damage/creepy_trauma.dm @@ -76,9 +76,9 @@ if(prob(25)) // 25% chances to be nervous and stutter. if(prob(50)) // 12.5% chance (previous check taken into account) of doing something suspicious. addtimer(CALLBACK(src, .proc/on_failed_social_interaction), rand(1, 3) SECONDS) - else if(owner.stuttering == 0) + else if(!owner.has_status_effect(/datum/status_effect/speech/stutter)) to_chat(owner, span_warning("Being near [obsession] makes you nervous and you begin to stutter...")) - owner.stuttering = max(3, owner.stuttering) + owner.set_timed_status_effect(6 SECONDS, /datum/status_effect/speech/stutter, only_if_higher = TRUE) /datum/brain_trauma/special/obsessed/proc/on_hug(datum/source, mob/living/hugger, mob/living/hugged) SIGNAL_HANDLER diff --git a/code/datums/brain_damage/mild.dm b/code/datums/brain_damage/mild.dm index 77b8e10e1c5..f2905f2d01f 100644 --- a/code/datums/brain_damage/mild.dm +++ b/code/datums/brain_damage/mild.dm @@ -27,12 +27,11 @@ lose_text = "You feel in control of your speech." /datum/brain_trauma/mild/stuttering/on_life(delta_time, times_fired) - owner.stuttering = min(owner.stuttering + 5, 25) - ..() + owner.adjust_timed_status_effect(5 SECONDS * delta_time, /datum/status_effect/speech/stutter, max_duration = 50 SECONDS) /datum/brain_trauma/mild/stuttering/on_lose() - owner.stuttering = 0 - ..() + owner.remove_status_effect(/datum/status_effect/speech/stutter) + return ..() /datum/brain_trauma/mild/dumbness name = "Dumbness" @@ -44,25 +43,20 @@ /datum/brain_trauma/mild/dumbness/on_gain() ADD_TRAIT(owner, TRAIT_DUMB, TRAUMA_TRAIT) SEND_SIGNAL(owner, COMSIG_ADD_MOOD_EVENT, "dumb", /datum/mood_event/oblivious) - ..() + return ..() /datum/brain_trauma/mild/dumbness/on_life(delta_time, times_fired) - owner.derpspeech = min(owner.derpspeech + 5, 25) + owner.adjust_timed_status_effect(5 SECONDS * delta_time, /datum/status_effect/speech/stutter/derpspeech, max_duration = 50 SECONDS) if(DT_PROB(1.5, delta_time)) owner.emote("drool") - //SKYRAT EDIT REMOVAL BEGIN - /* else if(owner.stat == CONSCIOUS && DT_PROB(1.5, delta_time)) owner.say(pick_list_replacements(BRAIN_DAMAGE_FILE, "brain_damage"), forced = "brain damage") - */ - //SKYRAT EDIT REMOVAL END - ..() /datum/brain_trauma/mild/dumbness/on_lose() REMOVE_TRAIT(owner, TRAIT_DUMB, TRAUMA_TRAIT) - owner.derpspeech = 0 + owner.remove_status_effect(/datum/status_effect/speech/stutter/derpspeech) SEND_SIGNAL(owner, COMSIG_CLEAR_MOOD_EVENT, "dumb") - ..() + return ..() /datum/brain_trauma/mild/speech_impediment name = "Speech Impediment" @@ -97,7 +91,7 @@ owner.add_confusion(10) owner.blur_eyes(10) if(6 to 9) - owner.slurring += 30 + owner.adjust_timed_status_effect(1 MINUTES, /datum/status_effect/speech/slurring/drunk) if(10) to_chat(owner, span_notice("You forget for a moment what you were doing.")) owner.Stun(20) diff --git a/code/datums/brain_damage/phobia.dm b/code/datums/brain_damage/phobia.dm index 16c10c5fd3c..49f8db7ef28 100644 --- a/code/datums/brain_damage/phobia.dm +++ b/code/datums/brain_damage/phobia.dm @@ -126,7 +126,7 @@ owner.dizziness += 10 owner.add_confusion(10) owner.Jitter(10) - owner.stuttering += 10 + owner.adjust_timed_status_effect(20 SECONDS, /datum/status_effect/speech/stutter) // Defined phobia types for badminry, not included in the RNG trauma pool to avoid diluting. diff --git a/code/datums/diseases/adrenal_crisis.dm b/code/datums/diseases/adrenal_crisis.dm index 44eeec8b36b..9fe40fb6354 100644 --- a/code/datums/diseases/adrenal_crisis.dm +++ b/code/datums/diseases/adrenal_crisis.dm @@ -29,7 +29,7 @@ affected_mob.Unconscious(40) if(DT_PROB(10, delta_time)) - affected_mob.slurring += 7 + affected_mob.adjust_timed_status_effect(14 SECONDS, /datum/status_effect/speech/slurring/drunk) if(DT_PROB(7, delta_time)) affected_mob.Dizzy(10) diff --git a/code/datums/diseases/advance/symptoms/sensory.dm b/code/datums/diseases/advance/symptoms/sensory.dm index 5a9423c81a9..e123b33de73 100644 --- a/code/datums/diseases/advance/symptoms/sensory.dm +++ b/code/datums/diseases/advance/symptoms/sensory.dm @@ -38,7 +38,8 @@ if(A.stage >= 3) M.dizziness = max(0, M.dizziness - 2) M.adjust_drowsyness(-2) - M.slurring = max(0, M.slurring - 2) + M.adjust_timed_status_effect(-1 SECONDS, /datum/status_effect/speech/slurring/drunk) + M.set_confusion(max(0, M.get_confusion() - 2)) if(purge_alcohol) M.reagents.remove_all_type(/datum/reagent/consumable/ethanol, 3) diff --git a/code/datums/diseases/brainrot.dm b/code/datums/diseases/brainrot.dm index 1498ded821f..89e6b085a23 100644 --- a/code/datums/diseases/brainrot.dm +++ b/code/datums/diseases/brainrot.dm @@ -55,4 +55,4 @@ if(prob(1)) affected_mob.emote("snore") if(DT_PROB(7.5, delta_time)) - affected_mob.stuttering += 3 + affected_mob.adjust_timed_status_effect(6 SECONDS, /datum/status_effect/speech/stutter) diff --git a/code/datums/diseases/decloning.dm b/code/datums/diseases/decloning.dm index 886a3bcfc5b..b85d0a1bc93 100644 --- a/code/datums/diseases/decloning.dm +++ b/code/datums/diseases/decloning.dm @@ -47,7 +47,7 @@ affected_mob.adjustOrganLoss(ORGAN_SLOT_BRAIN, 1, 170) affected_mob.adjustCloneLoss(2, FALSE) if(DT_PROB(7.5, delta_time)) - affected_mob.stuttering += 3 + affected_mob.adjust_timed_status_effect(6 SECONDS, /datum/status_effect/speech/stutter) if(5) if(DT_PROB(1, delta_time)) affected_mob.emote("itch") diff --git a/code/datums/elements/spooky.dm b/code/datums/elements/spooky.dm index 5ff4c07219e..f1b68c6760a 100644 --- a/code/datums/elements/spooky.dm +++ b/code/datums/elements/spooky.dm @@ -22,7 +22,7 @@ if(!istype(U.dna.species, /datum/species/skeleton)) U.adjustStaminaLoss(35) //Extra Damage U.Jitter(35) - U.stuttering = 20 + U.set_timed_status_effect(40 SECONDS, /datum/status_effect/speech/stutter) if(U.getStaminaLoss() > 95) to_chat(U, "Your ears weren't meant for this spectral sound.") INVOKE_ASYNC(src, .proc/spectral_change, U) @@ -36,7 +36,7 @@ H.adjustStaminaLoss(25) H.Paralyze(15) //zombies can't resist the doot C.Jitter(35) - C.stuttering = 20 + C.set_timed_status_effect(40 SECONDS, /datum/status_effect/speech/stutter) if((!istype(H.dna.species, /datum/species/skeleton)) && (!istype(H.dna.species, /datum/species/golem)) && (!istype(H.dna.species, /datum/species/android)) && (!istype(H.dna.species, /datum/species/jelly))) C.adjustStaminaLoss(25) //boneless humanoids don't lose the will to live to_chat(C, "DOOT") @@ -44,7 +44,7 @@ else //the sound will spook monkeys. C.Jitter(15) - C.stuttering = 20 + C.set_timed_status_effect(40 SECONDS, /datum/status_effect/speech/stutter) /datum/element/spooky/proc/spectral_change(mob/living/carbon/human/H, mob/user) if((H.getStaminaLoss() > 95) && (!istype(H.dna.species, /datum/species/skeleton)) && (!istype(H.dna.species, /datum/species/golem)) && (!istype(H.dna.species, /datum/species/android)) && (!istype(H.dna.species, /datum/species/jelly))) diff --git a/code/datums/mutations/speech.dm b/code/datums/mutations/speech.dm index 43653d060f8..30203107604 100644 --- a/code/datums/mutations/speech.dm +++ b/code/datums/mutations/speech.dm @@ -9,8 +9,7 @@ /datum/mutation/human/nervousness/on_life(delta_time, times_fired) if(DT_PROB(5, delta_time)) - owner.stuttering = max(10, owner.stuttering) - + owner.set_timed_status_effect(20 SECONDS, /datum/status_effect/speech/stutter, only_if_higher = TRUE) /datum/mutation/human/wacky name = "Wacky" diff --git a/code/datums/quirks/negative.dm b/code/datums/quirks/negative.dm index 9d00e2ac13c..22230dbdba4 100644 --- a/code/datums/quirks/negative.dm +++ b/code/datums/quirks/negative.dm @@ -544,26 +544,13 @@ to_chat(quirker, span_danger("You feel self-conscious and stop talking. You need a moment to recover!")) break if(prob(max(5,(nearby_people*12.5*moodmod)))) //Minimum 1/20 chance of stutter - word = html_decode(word) - var/leng = length(word) - var/stuttered = "" - var/newletter = "" - var/rawchar = "" - var/static/regex/nostutter = regex(@@[aeiouAEIOU ""''()[\]{}.!?,:;_`~-]@) - for(var/i = 1, i <= leng, i += length(rawchar)) - rawchar = newletter = word[i] - if(prob(80) && !nostutter.Find(rawchar)) - if(prob(10)) - newletter = "[newletter]-[newletter]-[newletter]-[newletter]" - else if(prob(20)) - newletter = "[newletter]-[newletter]-[newletter]" - else - newletter = "[newletter]-[newletter]" - stuttered += newletter - sanitize(stuttered) - new_message += stuttered + // Add a short stutter, THEN treat our word + quirker.adjust_timed_status_effect(0.5 SECONDS, /datum/status_effect/speech/stutter) + new_message += quirker.treat_message(word) + else new_message += word + message = jointext(new_message, " ") var/mob/living/carbon/human/quirker = quirk_holder if(prob(min(50,(0.50*(nearby_people*12.5)*moodmod)))) //Max 50% chance of not talking @@ -607,7 +594,7 @@ quirk_holder.Jitter(10) msg += "causing you to start fidgeting!" if(2) - quirk_holder.stuttering = max(3, quirk_holder.stuttering) + quirk_holder.set_timed_status_effect(6 SECONDS, /datum/status_effect/speech/stutter, only_if_higher = TRUE) msg += "causing you to start stuttering!" if(3) quirk_holder.Stun(2 SECONDS) diff --git a/code/datums/status_effects/debuffs.dm b/code/datums/status_effects/debuffs/debuffs.dm similarity index 99% rename from code/datums/status_effects/debuffs.dm rename to code/datums/status_effects/debuffs/debuffs.dm index 026c6069adf..9e76ae9fb24 100644 --- a/code/datums/status_effects/debuffs.dm +++ b/code/datums/status_effects/debuffs/debuffs.dm @@ -1,5 +1,3 @@ -#define TRAIT_STATUS_EFFECT(effect_id) "[effect_id]-trait" - //Largely negative status effects go here, even if they have small benificial effects //STUN EFFECTS /datum/status_effect/incapacitating diff --git a/code/datums/status_effects/debuffs/speech_debuffs.dm b/code/datums/status_effects/debuffs/speech_debuffs.dm new file mode 100644 index 00000000000..62fb365a1ff --- /dev/null +++ b/code/datums/status_effects/debuffs/speech_debuffs.dm @@ -0,0 +1,225 @@ +/datum/status_effect/speech + id = null + alert_type = null + +/datum/status_effect/speech/on_creation(mob/living/new_owner, duration = 10 SECONDS) + src.duration = duration + return ..() + +/datum/status_effect/speech/on_apply() + RegisterSignal(owner, COMSIG_LIVING_TREAT_MESSAGE, .proc/handle_message) + RegisterSignal(owner, COMSIG_LIVING_POST_FULLY_HEAL, .proc/on_heal) + return TRUE + +/datum/status_effect/speech/on_remove() + UnregisterSignal(owner, COMSIG_LIVING_TREAT_MESSAGE) + UnregisterSignal(owner, COMSIG_LIVING_POST_FULLY_HEAL) + +/// Signal proc for [COMSIG_LIVING_POST_FULLY_HEAL], removes all stutters and slurring on full heal +/datum/status_effect/speech/proc/on_heal(datum/source, admin_revive) + SIGNAL_HANDLER + + qdel(src) + +/** + * Signal proc for [COMSIG_LIVING_TREAT_MESSAGE] + * + * Iterates over all of the characters in the past message + * and calls apply_speech() on each. + * + * message_args[1] is the original message passed into the signal. + */ +/datum/status_effect/speech/proc/handle_message(datum/source, list/message_args) + SIGNAL_HANDLER + + var/phrase = html_decode(message_args[1]) + if(!length(phrase)) + return + + var/final_phrase = "" + var/original_char = "" + + for(var/i = 1, i <= length(phrase), i += length(original_char)) + original_char = phrase[i] + + final_phrase += apply_speech(original_char, original_char) + + message_args[1] = sanitize(final_phrase) + +/** + * Applies the speech effects on the past character, changing + * the original_char into the modified_char. + * + * Return the modified_char to be reapplied to the message. + */ +/datum/status_effect/speech/proc/apply_speech(original_char, modified_char) + stack_trace("[type] didn't implement apply_speech.") + return original_char + +/datum/status_effect/speech/stutter + id = "stutter" + /// The probability of adding a stutter to any character + var/stutter_prob = 80 + /// Regex of characters we won't apply a stutter to + var/static/regex/no_stutter + +/datum/status_effect/speech/stutter/on_creation(mob/living/new_owner, ...) + . = ..() + if(!.) + return + if(!no_stutter) + no_stutter = regex(@@[aeiouAEIOU ""''()[\]{}.!?,:;_`~-]@) + +/datum/status_effect/speech/stutter/apply_speech(original_char, modified_char) + if(prob(stutter_prob) && !no_stutter.Find(original_char)) + if(prob(10)) + modified_char = "[modified_char]-[modified_char]-[modified_char]-[modified_char]" + else if(prob(20)) + modified_char = "[modified_char]-[modified_char]-[modified_char]" + else if(prob(95)) + modified_char = "[modified_char]-[modified_char]" + else + modified_char = "" + + return modified_char + +/datum/status_effect/speech/stutter/derpspeech + id = "derp_stutter" + /// The probability of making our message entirely uppercase + adding exclamations + var/capitalize_prob = 50 + /// The probability of adding a stutter to the entire message, if we're not already stuttering + var/message_stutter_prob = 15 + +/datum/status_effect/speech/stutter/derpspeech/handle_message(datum/source, list/message_args) + + var/message = html_decode(message_args[1]) + + message = replacetext(message, " am ", " ") + message = replacetext(message, " is ", " ") + message = replacetext(message, " are ", " ") + message = replacetext(message, "you", "u") + message = replacetext(message, "help", "halp") + message = replacetext(message, "grief", "grife") + message = replacetext(message, "space", "spess") + message = replacetext(message, "carp", "crap") + message = replacetext(message, "reason", "raisin") + + if(prob(capitalize_prob)) + var/exclamation = pick("!", "!!", "!!!") + message = uppertext(message) + message += "[apply_speech(exclamation, exclamation)]" + + message_args[1] = message + + var/mob/living/living_source = source + if(!isliving(source) || living_source.has_status_effect(/datum/status_effect/speech/stutter)) + return + + // If we're not stuttering, we have a chance of calling parent here, adding stutter effects + if(prob(message_stutter_prob)) + return ..() + + // Otherwise just return and don't call parent, we already modified our speech + return + +/datum/status_effect/speech/slurring + /// The chance that any given character in a message will be replaced with a common character + var/common_prob = 25 + /// The chance that any given character in a message will be replaced with an uncommon character + var/uncommon_prob = 10 + /// The chance that any given character will be entirely replaced with a new string / will have a string appended onto it + var/replacement_prob = 5 + /// The chance that any given character will be doubled, or even tripled + var/doubletext_prob = 0 + + /// The file we pull text modifications from + var/text_modification_file = "" + + /// Common replacements for characters - populated in on_creation + var/list/common_replacements + /// Uncommon replacements for characters - populated in on_creation + var/list/uncommon_replacements + /// Strings that fully replace a character - populated in on_creation + var/list/string_replacements + /// Strings that are appended to a character - populated in on_creation + var/list/string_additions + +/datum/status_effect/speech/slurring/on_creation(mob/living/new_owner, duration = 10 SECONDS) + . = ..() + if(!.) + return + + if(!text_modification_file) + CRASH("[type] was created without a text modification file.") + + var/list/speech_changes = strings(text_modification_file, "replacements") + common_replacements = speech_changes["characters"]["common"] + uncommon_replacements = speech_changes["characters"]["uncommon"] + string_replacements = speech_changes["string_replacements"] + string_additions = speech_changes["string_additions"] + +/datum/status_effect/speech/slurring/apply_speech(original_char, modified_char) + + var/lower_char = lowertext(modified_char) + if(prob(common_prob) && (lower_char in common_replacements)) + var/to_replace = common_replacements[lower_char] + if(islist(to_replace)) + modified_char = pick(to_replace) + else + modified_char = to_replace + + if(prob(uncommon_prob) && (modified_char in uncommon_replacements)) + var/to_replace = uncommon_replacements[modified_char] + if(islist(to_replace)) + modified_char = pick(to_replace) + else + modified_char = to_replace + + if(prob(replacement_prob)) + var/replacements_len = length(string_replacements) + var/additions_len = length(string_additions) + if(replacements_len && additions_len) + // Calculate the probability of grabbing a replacement vs an addition + var/weight = (replacements_len + additions_len) / replacements_len * 100 + if(prob(weight)) + modified_char = pick(string_replacements) + else + modified_char += pick(string_additions) + + else if(replacements_len) + modified_char = pick(string_replacements) + + else if(additions_len) + modified_char += pick(string_additions) + + if(prob(doubletext_prob)) + if(prob(50)) + modified_char += "[modified_char]" + else + modified_char += "[modified_char][modified_char]" + + return modified_char + +/datum/status_effect/speech/slurring/drunk + id = "drunk_slurring" + common_prob = 33 + uncommon_prob = 5 + replacement_prob = 5 + doubletext_prob = 10 + text_modification_file = "slurring_drunk_text.json" + +/datum/status_effect/speech/slurring/cult + id = "cult_slurring" + common_prob = 50 + uncommon_prob = 25 + replacement_prob = 33 + doubletext_prob = 0 + text_modification_file = "slurring_cult_text.json" + +/datum/status_effect/speech/slurring/heretic + id = "heretic_slurring" + common_prob = 50 + uncommon_prob = 20 + replacement_prob = 30 + doubletext_prob = 5 + text_modification_file = "slurring_heretic_text.json" diff --git a/code/game/objects/items/devices/paicard.dm b/code/game/objects/items/devices/paicard.dm index b465dec9060..e6c73bc7b6b 100644 --- a/code/game/objects/items/devices/paicard.dm +++ b/code/game/objects/items/devices/paicard.dm @@ -117,9 +117,9 @@ if("fix_speech") to_chat(pai, span_notice("Your owner has corrected your speech modulation!")) to_chat(usr, span_notice("You fix the pAI's speech modulator.")) - pai.stuttering = 0 - pai.slurring = 0 - pai.derpspeech = 0 + for(var/effect in typesof(/datum/status_effect/speech)) + pai.remove_status_effect(effect) + if("request") if(!pai) SSpai.findPAI(src, usr) diff --git a/code/game/objects/items/hand_items.dm b/code/game/objects/items/hand_items.dm index 8e234302bd2..a5a38b460a0 100644 --- a/code/game/objects/items/hand_items.dm +++ b/code/game/objects/items/hand_items.dm @@ -540,7 +540,7 @@ other_msg = "stammers softly for a moment before choking on something!" self_msg = "You feel your tongue disappear down your throat as you fight to remember how to make words!" addtimer(CALLBACK(living_target, /atom/movable.proc/say, pick("Uhhh...", "O-oh, uhm...", "I- uhhhhh??", "You too!!", "What?")), rand(0.5 SECONDS, 1.5 SECONDS)) - living_target.stuttering += rand(5, 15) + living_target.adjust_timed_status_effect(rand(10 SECONDS, 30 SECONDS), /datum/status_effect/speech/stutter) if(3) other_msg = "locks up with a stunned look on [living_target.p_their()] face, staring at [firer ? firer : "the ceiling"]!" self_msg = "Your brain completely fails to process what just happened, leaving you rooted in place staring at [firer ? "[firer]" : "the ceiling"] for what feels like an eternity!" diff --git a/code/game/objects/items/melee/baton.dm b/code/game/objects/items/melee/baton.dm index 40dc9e8497c..68371563267 100644 --- a/code/game/objects/items/melee/baton.dm +++ b/code/game/objects/items/melee/baton.dm @@ -371,7 +371,7 @@ /obj/item/melee/baton/telescopic/contractor_baton/additional_effects_non_cyborg(mob/living/target, mob/living/user) target.Jitter(20) - target.stuttering += 20 + target.adjust_timed_status_effect(40 SECONDS, /datum/status_effect/speech/stutter) /obj/item/melee/baton/security name = "stun baton" @@ -563,8 +563,8 @@ */ /obj/item/melee/baton/security/additional_effects_non_cyborg(mob/living/target, mob/living/user) target.Jitter(20) -// target.set_confusion(max(10, target.get_confusion())) SKYRAT EDIT - Less CC on an already strong melee weapon. - target.stuttering = max(8, target.stuttering) + //target.set_confusion(max(10, target.get_confusion())) SKYRAT EDIT REMOVAL + target.set_timed_status_effect(16 SECONDS, /datum/status_effect/speech/stutter, only_if_higher = TRUE) SEND_SIGNAL(target, COMSIG_LIVING_MINOR_SHOCK) addtimer(CALLBACK(src, .proc/apply_stun_effect_end, target), 2 SECONDS) diff --git a/code/game/objects/items/robot/robot_items.dm b/code/game/objects/items/robot/robot_items.dm index 078aedc48cb..ccbd75340c9 100644 --- a/code/game/objects/items/robot/robot_items.dm +++ b/code/game/objects/items/robot/robot_items.dm @@ -23,7 +23,7 @@ user.do_attack_animation(M) M.Paralyze(100) - M.apply_effect(EFFECT_STUTTER, 5) + M.adjust_timed_status_effect(10 SECONDS, /datum/status_effect/speech/stutter) M.visible_message(span_danger("[user] prods [M] with [src]!"), \ span_userdanger("[user] prods you with [src]!")) @@ -327,12 +327,12 @@ switch(bang_effect) if(1) C.add_confusion(5) - C.stuttering += 10 + C.adjust_timed_status_effect(20 SECONDS, /datum/status_effect/speech/stutter) C.Jitter(10) if(2) C.Paralyze(40) C.add_confusion(10) - C.stuttering += 15 + C.adjust_timed_status_effect(30 SECONDS, /datum/status_effect/speech/stutter) C.Jitter(25) playsound(get_turf(src), 'sound/machines/warning-buzzer.ogg', 130, 3) cooldown = world.time + 600 diff --git a/code/game/objects/structures/watercloset.dm b/code/game/objects/structures/watercloset.dm index a07d82d9ae2..32897631252 100644 --- a/code/game/objects/structures/watercloset.dm +++ b/code/game/objects/structures/watercloset.dm @@ -352,7 +352,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/structure/urinal, 32) if(baton.cell?.charge && baton.active) flick("baton_active", src) user.Paralyze(baton.knockdown_time) - user.stuttering = baton.knockdown_time*0.5 + user.set_timed_status_effect(baton.knockdown_time, /datum/status_effect/speech/stutter) baton.cell.use(baton.cell_hit_cost) user.visible_message(span_warning("[user] shocks [user.p_them()]self while attempting to wash the active [baton.name]!"), \ span_userdanger("You unwisely attempt to wash [baton] while it's still on.")) @@ -557,7 +557,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/structure/urinal, 32) if(baton.cell?.charge && baton.active) flick("baton_active", src) user.Paralyze(baton.knockdown_time) - user.stuttering = baton.knockdown_time*0.5 + user.set_timed_status_effect(baton.knockdown_time, /datum/status_effect/speech/stutter) baton.cell.use(baton.cell_hit_cost) user.visible_message(span_warning("[user] shocks [user.p_them()]self while attempting to wash the active [baton.name]!"), \ span_userdanger("You unwisely attempt to wash [baton] while it's still on.")) diff --git a/code/modules/admin/smites/bsa.dm b/code/modules/admin/smites/bsa.dm index d737c711ef9..15dc72ee033 100644 --- a/code/modules/admin/smites/bsa.dm +++ b/code/modules/admin/smites/bsa.dm @@ -1,7 +1,7 @@ #define BSA_CHANCE_TO_BREAK_TILE_TO_PLATING 80 #define BSA_MAX_DAMAGE 99 -#define BSA_PARALYZE_TIME (40 SECONDS) -#define BSA_STUTTER_TIME 20 +#define BSA_PARALYZE_TIME 40 SECONDS +#define BSA_STUTTER_TIME 40 SECONDS /// Fires the BSA at the target /datum/smite/bsa @@ -27,7 +27,7 @@ else target.adjustBruteLoss(min(BSA_MAX_DAMAGE, target.health - 1)) target.Paralyze(BSA_PARALYZE_TIME) - target.stuttering = BSA_STUTTER_TIME + target.set_timed_status_effect(BSA_STUTTER_TIME, /datum/status_effect/speech/stutter) #undef BSA_CHANCE_TO_BREAK_TILE_TO_PLATING #undef BSA_MAX_DAMAGE diff --git a/code/modules/antagonists/abductor/equipment/abduction_gear.dm b/code/modules/antagonists/abductor/equipment/abduction_gear.dm index 2c78841d023..1df2d3d9c6f 100644 --- a/code/modules/antagonists/abductor/equipment/abduction_gear.dm +++ b/code/modules/antagonists/abductor/equipment/abduction_gear.dm @@ -514,7 +514,7 @@ Congratulations! You are now trained for invasive xenobiology research!"} span_userdanger("[user] stuns you with [src]!")) target.Jitter(20) target.set_confusion(max(10, target.get_confusion())) - target.stuttering = max(8, target.stuttering) + target.set_timed_status_effect(16 SECONDS, /datum/status_effect/speech/stutter, only_if_higher = TRUE) SEND_SIGNAL(target, COMSIG_LIVING_MINOR_SHOCK) target.Paralyze(knockdown_time * (HAS_TRAIT(target, TRAIT_STUNRESISTANCE) ? 0.1 : 1)) if(BATON_SLEEP) diff --git a/code/modules/antagonists/cult/blood_magic.dm b/code/modules/antagonists/cult/blood_magic.dm index fb6ade629bb..7d85850eb8f 100644 --- a/code/modules/antagonists/cult/blood_magic.dm +++ b/code/modules/antagonists/cult/blood_magic.dm @@ -442,8 +442,8 @@ else if(iscarbon(target)) var/mob/living/carbon/carbon_target = target carbon_target.silent += 6 - carbon_target.stuttering += 15 - carbon_target.cultslurring += 15 + carbon_target.adjust_timed_status_effect(30 SECONDS, /datum/status_effect/speech/stutter) + carbon_target.adjust_timed_status_effect(30 SECONDS, /datum/status_effect/speech/slurring/cult) carbon_target.Jitter(1.5 SECONDS) uses-- ..() @@ -740,7 +740,7 @@ if(H.stat == DEAD) to_chat(user,span_warning("[H.p_their(TRUE)] blood has stopped flowing, you'll have to find another way to extract it.")) return - if(H.cultslurring) + if(H.has_status_effect(/datum/status_effect/speech/slurring/cult)) to_chat(user,span_danger("[H.p_their(TRUE)] blood has been tainted by an even stronger form of blood magic, it's no use to us like this!")) return if(H.blood_volume > BLOOD_VOLUME_SAFE) diff --git a/code/modules/antagonists/cult/runes.dm b/code/modules/antagonists/cult/runes.dm index 2844cb7202a..8c58d99a857 100644 --- a/code/modules/antagonists/cult/runes.dm +++ b/code/modules/antagonists/cult/runes.dm @@ -279,8 +279,9 @@ structure_check() searches for nearby cultist structures required for the invoca if(ishuman(convertee)) var/mob/living/carbon/human/H = convertee H.uncuff() - H.stuttering = 0 - H.cultslurring = 0 + H.remove_status_effect(/datum/status_effect/speech/slurring/cult) + H.remove_status_effect(/datum/status_effect/speech/stutter) + if(prob(1) || SSevents.holidays && SSevents.holidays[APRIL_FOOLS]) H.say("You son of a bitch! I'm in.", forced = "That son of a bitch! They're in.") if(isshade(convertee)) diff --git a/code/modules/antagonists/heretic/knowledge/sacrifice_knowledge/sacrifice_knowledge.dm b/code/modules/antagonists/heretic/knowledge/sacrifice_knowledge/sacrifice_knowledge.dm index 8f2c1637fb8..81b4c86f2b5 100644 --- a/code/modules/antagonists/heretic/knowledge/sacrifice_knowledge/sacrifice_knowledge.dm +++ b/code/modules/antagonists/heretic/knowledge/sacrifice_knowledge/sacrifice_knowledge.dm @@ -363,9 +363,8 @@ SEND_SIGNAL(sac_target, COMSIG_CLEAR_MOOD_EVENT, "shadow_realm") // Wherever we end up, we sure as hell won't be able to explain - sac_target.slurring += 20 - sac_target.cultslurring += 20 - sac_target.stuttering += 20 + sac_target.adjust_timed_status_effect(40 SECONDS, /datum/status_effect/speech/slurring/heretic) + sac_target.adjust_timed_status_effect(40 SECONDS, /datum/status_effect/speech/stutter) // They're already back on the station for some reason, don't bother teleporting if(is_station_level(sac_target.z)) diff --git a/code/modules/antagonists/heretic/magic/mansus_grasp.dm b/code/modules/antagonists/heretic/magic/mansus_grasp.dm index 42a6b8182b6..704a774f9ea 100644 --- a/code/modules/antagonists/heretic/magic/mansus_grasp.dm +++ b/code/modules/antagonists/heretic/magic/mansus_grasp.dm @@ -82,7 +82,7 @@ hit.adjustBruteLoss(10) if(iscarbon(hit)) var/mob/living/carbon/carbon_hit = hit - carbon_hit.cultslurring += 2 + carbon_hit.adjust_timed_status_effect(4 SECONDS, /datum/status_effect/speech/slurring/heretic) carbon_hit.AdjustKnockdown(5 SECONDS) carbon_hit.adjustStaminaLoss(80) @@ -106,7 +106,7 @@ playsound(carbon_user, 'sound/effects/wounds/sizzle1.ogg', 70, vary = TRUE) if(prob(50)) carbon_user.emote("scream") - carbon_user.stuttering += 13 + carbon_user.adjust_timed_status_effect(26 SECONDS, /datum/status_effect/speech/stutter) on_mob_hit(user, user) diff --git a/code/modules/antagonists/heretic/structures/carving_knife.dm b/code/modules/antagonists/heretic/structures/carving_knife.dm index c092cb3b070..0d5bf3f08d7 100644 --- a/code/modules/antagonists/heretic/structures/carving_knife.dm +++ b/code/modules/antagonists/heretic/structures/carving_knife.dm @@ -239,7 +239,7 @@ var/mob/living/carbon/carbon_victim = victim carbon_victim.adjustStaminaLoss(80) carbon_victim.silent += 10 - carbon_victim.stuttering += 30 + carbon_victim.adjust_timed_status_effect(1 MINUTES, /datum/status_effect/speech/stutter) carbon_victim.add_confusion(5) carbon_victim.Jitter(10) carbon_victim.Dizzy(20) diff --git a/code/modules/mob/living/carbon/alien/organs.dm b/code/modules/mob/living/carbon/alien/organs.dm index e792556ea44..021cfcb6a68 100644 --- a/code/modules/mob/living/carbon/alien/organs.dm +++ b/code/modules/mob/living/carbon/alien/organs.dm @@ -139,7 +139,7 @@ owner.jitteriness += 30 owner.add_confusion(30) - owner.stuttering += 30 + owner.adjust_timed_status_effect(1 MINUTES, /datum/status_effect/speech/stutter) recent_queen_death = TRUE owner.throw_alert(ALERT_XENO_NOQUEEN, /atom/movable/screen/alert/alien_vulnerable) diff --git a/code/modules/mob/living/carbon/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm index 743c83c340c..3016c66fd1d 100644 --- a/code/modules/mob/living/carbon/carbon_defense.dm +++ b/code/modules/mob/living/carbon/carbon_defense.dm @@ -226,9 +226,8 @@ do_sparks(5, TRUE, src) var/power = M.powerlevel + rand(0,3) - Paralyze(power*20) - if(stuttering < power) - stuttering = power + Paralyze(power * 2 SECONDS) + set_timed_status_effect(power * 2 SECONDS, /datum/status_effect/speech/stutter, only_if_higher = TRUE) if (prob(stunprob) && M.powerlevel >= 8) adjustFireLoss(M.powerlevel * rand(6,10)) updatehealth() @@ -441,7 +440,7 @@ //Jitter and other fluff. jitteriness += 1000 do_jitter_animation(jitteriness) - stuttering += 2 + adjust_timed_status_effect(4 SECONDS, /datum/status_effect/speech/stutter) addtimer(CALLBACK(src, .proc/secondary_shock, should_stun), 20) return shock_damage diff --git a/code/modules/mob/living/carbon/human/human_say.dm b/code/modules/mob/living/carbon/human/human_say.dm index 84bbf696c5a..5d27c1bcfa0 100644 --- a/code/modules/mob/living/carbon/human/human_say.dm +++ b/code/modules/mob/living/carbon/human/human_say.dm @@ -1,12 +1,13 @@ /mob/living/carbon/human/say_mod(input, list/message_mods = list()) verb_say = dna.species.say_mod - if(slurring) + // Any subtype of slurring in our status effects make us "slur" + if(locate(/datum/status_effect/speech/slurring) in status_effects) if (HAS_TRAIT(src, TRAIT_SIGN_LANG)) return "loosely signs" else return "slurs" - else - . = ..() + + return ..() /mob/living/carbon/human/GetVoice() if(istype(wear_mask, /obj/item/clothing/mask/chameleon)) diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm index 9c323859c71..bca99209396 100644 --- a/code/modules/mob/living/carbon/life.dm +++ b/code/modules/mob/living/carbon/life.dm @@ -451,7 +451,7 @@ All effects don't start immediately, but rather get worse over time; the rate is */ #define BALLMER_POINTS 5 -//this updates all special effects: stun, sleeping, knockdown, druggy, stuttering, etc.. +// This updates all special effects that really should be status effect datums: Druggy, Hallucinations, Drunkenness, Mute, etc.. /mob/living/carbon/handle_status_effects(delta_time, times_fired) ..() @@ -519,7 +519,7 @@ All effects don't start immediately, but rather get worse over time; the rate is if(drunkenness >= 6) SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "drunk", /datum/mood_event/drunk) if(DT_PROB(16, delta_time)) - slurring += 2 + adjust_timed_status_effect(4 SECONDS, /datum/status_effect/speech/slurring/drunk) jitteriness = max(jitteriness - (1.5 * delta_time), 0) throw_alert(ALERT_DRUNK, /atom/movable/screen/alert/drunk) sound_environment_override = SOUND_ENVIRONMENT_PSYCHOTIC @@ -530,8 +530,10 @@ All effects don't start immediately, but rather get worse over time; the rate is REMOVE_TRAIT(src, TRAIT_NUMBED, src) //SKYRAT EDIT START - ANESTHETIC EFFECT REMOVAL clear_alert("numbed") //SKYRAT EDIT END - if(drunkenness >= 11 && slurring < 5) - slurring += 0.6 * delta_time + if(drunkenness >= 11) + var/datum/status_effect/speech/slurring/drunk/already_slurring = has_status_effect(/datum/status_effect/speech/slurring/drunk) + if(!already_slurring || already_slurring.duration - world.time <= 10 SECONDS) + adjust_timed_status_effect(1.2 SECONDS * delta_time, /datum/status_effect/speech/slurring/drunk) if(mind && (is_scientist_job(mind.assigned_role) || is_research_director_job(mind.assigned_role))) if(SSresearch.science_tech) diff --git a/code/modules/mob/living/damage_procs.dm b/code/modules/mob/living/damage_procs.dm index dced134476c..e6c4777455f 100644 --- a/code/modules/mob/living/damage_procs.dm +++ b/code/modules/mob/living/damage_procs.dm @@ -104,11 +104,6 @@ Immobilize(effect * hit_percent) if(EFFECT_UNCONSCIOUS) Unconscious(effect * hit_percent) - if(EFFECT_SLUR) - slurring = max(slurring,(effect * hit_percent)) - if(EFFECT_STUTTER) - if((status_flags & CANSTUN) && !HAS_TRAIT(src, TRAIT_STUNIMMUNE)) // stun is usually associated with stutter - stuttering = max(stuttering,(effect * hit_percent)) if(EFFECT_EYE_BLUR) blur_eyes(effect * hit_percent) if(EFFECT_DROWSY) @@ -118,10 +113,30 @@ jitteriness = max(jitteriness,(effect * hit_percent)) return TRUE -/// applies multiple effects at once via [/mob/living/proc/apply_effect] -/mob/living/proc/apply_effects(stun = 0, knockdown = 0, unconscious = 0, slur = 0, stutter = 0, eyeblur = 0, drowsy = 0, blocked = 0, stamina = 0, jitter = 0, paralyze = 0, immobilize = 0) +/** + * Applies multiple effects at once via [/mob/living/proc/apply_effect] + * + * Pretty much only used for projectiles applying effects on hit, + * don't use this for anything else please just cause the effects directly + */ +/mob/living/proc/apply_effects( + stun = 0, + knockdown = 0, + unconscious = 0, + slur = 0 SECONDS, // Speech impediment, not technically an effect + stutter = 0 SECONDS, // Ditto + eyeblur = 0, + drowsy = 0, + blocked = 0, // This one's not an effect, don't be confused - it's block chance + stamina = 0, // This one's a damage type, and not an effect + jitter = 0, + paralyze = 0, + immobilize = 0, + ) + if(blocked >= 100) return FALSE + if(stun) apply_effect(stun, EFFECT_STUN, blocked) if(knockdown) @@ -132,18 +147,21 @@ apply_effect(paralyze, EFFECT_PARALYZE, blocked) if(immobilize) apply_effect(immobilize, EFFECT_IMMOBILIZE, blocked) - if(slur) - apply_effect(slur, EFFECT_SLUR, blocked) - if(stutter) - apply_effect(stutter, EFFECT_STUTTER, blocked) if(eyeblur) apply_effect(eyeblur, EFFECT_EYE_BLUR, blocked) if(drowsy) apply_effect(drowsy, EFFECT_DROWSY, blocked) - if(stamina) - apply_damage(stamina, STAMINA, null, blocked) if(jitter) apply_effect(jitter, EFFECT_JITTER, blocked) + + if(stamina) + apply_damage(stamina, STAMINA, null, blocked) + + if(slur) + adjust_timed_status_effect(slur, /datum/status_effect/speech/slurring/drunk) + if(stutter) + adjust_timed_status_effect(stutter, /datum/status_effect/speech/stutter) + return TRUE diff --git a/code/modules/mob/living/life.dm b/code/modules/mob/living/life.dm index 3f8447ade8c..fcfd8585513 100644 --- a/code/modules/mob/living/life.dm +++ b/code/modules/mob/living/life.dm @@ -157,16 +157,16 @@ return reagents.has_reagent(reagent, amount, needs_metabolizing) /* - * this updates some effects: mostly old stuff such as drunkness, druggy, stuttering, etc. + * this updates some effects: mostly old stuff such as drunkness, druggy, etc. * that should be converted to status effect datums one day. + * ^ March 4th, 2021 + * Stuttering and slurring has been removed, + * but carbons still have a ton of effects that need to be moved over + * Good luck reader + * ^ April 6th, 2022 */ /mob/living/proc/handle_status_effects(delta_time, times_fired) - if(stuttering) - stuttering = max(stuttering - (0.5 * delta_time), 0) - if(slurring) - slurring = max(slurring - (0.5 * delta_time),0) - if(cultslurring) - cultslurring = max(cultslurring - (0.5 * delta_time), 0) + return /mob/living/proc/handle_traits(delta_time, times_fired) //Eyes diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 72f3a7d2594..a0ea323e3af 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -890,8 +890,6 @@ set_confusion(0) dizziness = 0 set_drowsyness(0) - stuttering = 0 - slurring = 0 jitteriness = 0 stop_sound_channel(CHANNEL_HEARTBEAT) SEND_SIGNAL(src, COMSIG_LIVING_POST_FULLY_HEAL, admin_revive) @@ -1753,6 +1751,19 @@ "} +/mob/living/vv_get_dropdown() + . = ..() + VV_DROPDOWN_OPTION("", "---------") + VV_DROPDOWN_OPTION(VV_HK_GIVE_SPEECH_IMPEDIMENT, "Impede Speech (Slurring, stuttering, etc)") + +/mob/living/vv_do_topic(list/href_list) + . = ..() + + if(href_list[VV_HK_GIVE_SPEECH_IMPEDIMENT]) + if(!check_rights(NONE)) + return + admin_give_speech_impediment(usr) + /mob/living/proc/move_to_error_room() var/obj/effect/landmark/error/error_landmark = locate(/obj/effect/landmark/error) in GLOB.landmarks_list if(error_landmark) @@ -2276,3 +2287,25 @@ if(SEND_SIGNAL(src, COMSIG_LIVING_WRITE_MEMORY, dead, gibbed) & COMPONENT_DONT_WRITE_MEMORY) return FALSE return TRUE + +/// Admin only proc for giving a certain speech impediment to this mob +/mob/living/proc/admin_give_speech_impediment(mob/admin) + if(!admin || !check_rights(NONE)) + return + + var/list/impediments = list() + for(var/datum/status_effect/possible as anything in typesof(/datum/status_effect/speech)) + if(!initial(possible.id)) + continue + + impediments[initial(possible.id)] = possible + + var/chosen = tgui_input_list(admin, "What speech impediment?", "Impede Speech", impediments) + if(!chosen || !ispath(impediments[chosen], /datum/status_effect/speech) || QDELETED(src) || !check_rights(NONE)) + return + + var/duration = tgui_input_number(admin, "How long should it last (in seconds)? Max is infinite duration.", "Duration", 0, INFINITY, 0 SECONDS) + if(!isnum(duration) || duration <= 0 || QDELETED(src) || !check_rights(NONE)) + return + + adjust_timed_status_effect(duration SECONDS, impediments[chosen]) diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm index ded09a43b61..a43c4acc872 100644 --- a/code/modules/mob/living/living_defines.dm +++ b/code/modules/mob/living/living_defines.dm @@ -126,12 +126,6 @@ var/list/status_effects ///a list of all status effects the mob has var/druggy = 0 - //Speech - var/stuttering = 0 - var/slurring = 0 - var/cultslurring = 0 - var/derpspeech = 0 - var/list/implants = null var/last_words ///used for database logging diff --git a/code/modules/mob/living/living_say.dm b/code/modules/mob/living/living_say.dm index 5ec91e53064..2185bd3b3bf 100644 --- a/code/modules/mob/living/living_say.dm +++ b/code/modules/mob/living/living_say.dm @@ -442,21 +442,10 @@ GLOBAL_LIST_INIT(message_modes_stat_limits, list( /mob/living/proc/treat_message(message) - if(HAS_TRAIT(src, TRAIT_UNINTELLIGIBLE_SPEECH)) message = unintelligize(message) - if(derpspeech) - message = derpspeech(message, stuttering) - - if(stuttering) - message = stutter(message) - - if(slurring) - message = slur(message) - - if(cultslurring) - message = cultslur(message) + SEND_SIGNAL(src, COMSIG_LIVING_TREAT_MESSAGE, args) message = capitalize(message) @@ -497,12 +486,12 @@ GLOBAL_LIST_INIT(message_modes_stat_limits, list( . = "[verb_whisper] in [p_their()] last breath" else if(message_mods[MODE_SING]) . = verb_sing - else if(stuttering) + else if(has_status_effect(/datum/status_effect/speech/stutter)) if(HAS_TRAIT(src, TRAIT_SIGN_LANG)) . = "shakily signs" else . = "stammers" - else if(derpspeech) + else if(has_status_effect(/datum/status_effect/speech/stutter/derpspeech)) if(HAS_TRAIT(src, TRAIT_SIGN_LANG)) . = "incoherently signs" else diff --git a/code/modules/mob/living/silicon/pai/pai_defense.dm b/code/modules/mob/living/silicon/pai/pai_defense.dm index 517f2608b5f..066cd3497f5 100644 --- a/code/modules/mob/living/silicon/pai/pai_defense.dm +++ b/code/modules/mob/living/silicon/pai/pai_defense.dm @@ -14,13 +14,13 @@ //Ask and you shall receive switch(rand(1, 3)) if(1) - stuttering += 30/severity //temporary, clears in a few ticks after silent is over. + adjust_timed_status_effect(1 MINUTES / severity, /datum/status_effect/speech/stutter) to_chat(src, span_danger("Warning: Feedback loop detected in speech module.")) if(2) - slurring = INFINITY // permanent until speech is fixed through the pAI card UI by someone else. + adjust_timed_status_effect(INFINITY, /datum/status_effect/speech/slurring/drunk) to_chat(src, span_danger("Warning: Audio synthesizer CPU stuck.")) if(3) - derpspeech = 1 // Ditto. + adjust_timed_status_effect(INFINITY, /datum/status_effect/speech/stutter/derpspeech) to_chat(src, span_danger("Warning: Vocabulary databank corrupted.")) if(prob(40)) mind.language_holder.selected_language = get_random_spoken_language() diff --git a/code/modules/mob/living/simple_animal/bot/honkbot.dm b/code/modules/mob/living/simple_animal/bot/honkbot.dm index d45de538b18..b07e09c43c7 100644 --- a/code/modules/mob/living/simple_animal/bot/honkbot.dm +++ b/code/modules/mob/living/simple_animal/bot/honkbot.dm @@ -61,11 +61,12 @@ icon_state = "[initial(icon_state)]-c" addtimer(CALLBACK(src, /atom.proc/update_appearance), 0.2 SECONDS) if(!ishuman(current_target)) - current_target.stuttering = 20 current_target.Paralyze(8 SECONDS) + current_target.set_timed_status_effect(40 SECONDS, /datum/status_effect/speech/stutter) addtimer(CALLBACK(src, .proc/limiting_spam_false), cooldowntime) return - current_target.stuttering = 20 + + current_target.set_timed_status_effect(40 SECONDS, /datum/status_effect/speech/stutter) var/obj/item/organ/ears/target_ears = current_target.getorganslot(ORGAN_SLOT_EARS) if(target_ears && !HAS_TRAIT_FROM(current_target, TRAIT_DEAF, CLOTHING_TRAIT)) target_ears.adjustEarDamage(0, 5) //far less damage than the H.O.N.K. diff --git a/code/modules/mob/living/simple_animal/bot/secbot.dm b/code/modules/mob/living/simple_animal/bot/secbot.dm index 2dc6ed75240..84c332eedb7 100644 --- a/code/modules/mob/living/simple_animal/bot/secbot.dm +++ b/code/modules/mob/living/simple_animal/bot/secbot.dm @@ -303,13 +303,13 @@ if(harm) weapon.attack(current_target, src) if(ishuman(current_target)) - current_target.stuttering = 5 + current_target.set_timed_status_effect(10 SECONDS, /datum/status_effect/speech/stutter) current_target.StaminaKnockdown(60,TRUE) // SKYRAT EDIT CHANGE var/mob/living/carbon/human/human_target = current_target threat = human_target.assess_threat(judgement_criteria, weaponcheck = CALLBACK(src, .proc/check_for_weapons)) else current_target.StaminaKnockdown(60,TRUE) // SKYRAT EDIT CHANGE - current_target.stuttering = 5 + current_target.set_timed_status_effect(10 SECONDS, /datum/status_effect/speech/stutter) threat = current_target.assess_threat(judgement_criteria, weaponcheck = CALLBACK(src, .proc/check_for_weapons)) log_combat(src, target, "stunned") diff --git a/code/modules/mob/living/status_procs.dm b/code/modules/mob/living/status_procs.dm index 2e96cf1932c..2f20fd13510 100644 --- a/code/modules/mob/living/status_procs.dm +++ b/code/modules/mob/living/status_procs.dm @@ -636,3 +636,94 @@ */ /mob/living/proc/reset_shocked() flags_1 &= ~ SHOCKED_1 + +/** + * Adjusts a timed status effect on the mob,taking into account any existing timed status effects. + * This can be any status effect that takes into account "duration" with their initialize arguments. + * + * Positive durations will add deciseconds to the duration of existing status effects + * or apply a new status effect of that duration to the mob. + * + * Negative durations will remove deciseconds from the duration of an existing version of the status effect, + * removing the status effect entirely if the duration becomes less than zero (less than the current world time). + * + * duration - the duration, in deciseconds, to add or remove from the effect + * effect - the type of status effect being adjusted on the mob + * max_duration - optional - if set, positive durations will only be added UP TO the passed max duration + */ +/mob/living/proc/adjust_timed_status_effect(duration, effect, max_duration) + if(!isnum(duration)) + CRASH("adjust_timed_status_effect: called with an invalid duration. (Got: [duration])") + + if(!ispath(effect, /datum/status_effect)) + CRASH("adjust_timed_status_effect: called with an invalid effect type. (Got: [effect])") + + // If we have a max duration set, we need to check our duration does not exceed it + if(isnum(max_duration)) + if(max_duration <= 0) + CRASH("adjust_timed_status_effect: Called with an invalid max_duration. (Got: [max_duration])") + + if(duration >= max_duration) + duration = max_duration + + var/datum/status_effect/existing = has_status_effect(effect) + if(existing) + if(isnum(max_duration) && duration > 0) + // Check the duration remaining on the existing status effect + // If it's greater than / equal to our passed max duration, we don't need to do anything + var/remaining_duration = existing.duration - world.time + if(remaining_duration >= max_duration) + return + + // Otherwise, add duration up to the max (max_duration - remaining_duration), + // or just add duration if it doesn't exceed our max at all + existing.duration += min(max_duration - remaining_duration, duration) + + else + existing.duration += duration + + // If the duration was decreased and is now less 0 seconds, + // qdel it / clean up the status effect immediately + // (rather than waiting for the process tick to handle it) + if(existing.duration <= world.time) + qdel(existing) + + else if(duration > 0) + apply_status_effect(effect, duration) + +/** + * Sets a timed status effect of some kind on a mob to a specific value. + * If only_if_higher is TRUE, it will only set the value up to the passed duration, + * so any pre-existing status effects of the same type won't be reduced down + * + * duration - the duration, in deciseconds, of the effect. 0 or lower will either remove the current effect or do nothing if none are present + * effect - the type of status effect given to the mob + * only_if_higher - if TRUE, we will only set the effect to the new duration if the new duration is longer than any existing duration + */ +/mob/living/proc/set_timed_status_effect(duration, effect, only_if_higher = FALSE) + if(!isnum(duration)) + CRASH("set_timed_status_effect: called with an invalid duration. (Got: [duration])") + + if(!ispath(effect, /datum/status_effect)) + CRASH("set_timed_status_effect: called with an invalid effect type. (Got: [effect])") + + var/datum/status_effect/existing = has_status_effect(effect) + if(existing) + // set_timed_status_effect to 0 technically acts as a way to clear effects, + // though remove_status_effect would achieve the same goal more explicitly. + if(duration <= 0) + qdel(existing) + return + + if(only_if_higher) + // If the existing status effect has a higher remaining duration + // than what we aim to set it to, don't downgrade it - do nothing (return) + var/remaining_duration = existing.duration - world.time + if(remaining_duration >= duration) + return + + // Set the duration accordingly + existing.duration = world.time + duration + + else if(duration > 0) + apply_status_effect(effect, duration) diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index 435288f5f94..787cf1c33c7 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -72,129 +72,6 @@ . += "*" return sanitize(.) -/** - * Makes you speak like you're drunk - */ -/proc/slur(phrase) - phrase = html_decode(phrase) - var/leng = length(phrase) - . = "" - var/newletter = "" - var/rawchar = "" - for(var/i = 1, i <= leng, i += length(rawchar)) - rawchar = newletter = phrase[i] - if(prob(33)) - var/lowerletter = lowertext(newletter) - if(lowerletter == "o") - newletter = "u" - else if(lowerletter == "s") - newletter = "ch" - else if(lowerletter == "a") - newletter = "ah" - else if(lowerletter == "u") - newletter = "oo" - else if(lowerletter == "c") - newletter = "k" - if(prob(5)) - if(newletter == " ") - newletter = "...huuuhhh..." - else if(newletter == ".") - newletter = " *BURP*." - if(prob(15)) - switch(rand(1,3)) - if(1) - newletter += "'" - if(2) - newletter += "[newletter]" - if(3) - newletter += "[newletter][newletter]" - . += "[newletter]" - return sanitize(.) - -/// Makes you talk like you got cult stunned, which is slurring but with some dark messages -/proc/cultslur(phrase) // Inflicted on victims of a stun talisman - phrase = html_decode(phrase) - var/leng = length(phrase) - . = "" - var/newletter = "" - var/rawchar = "" - for(var/i = 1, i <= leng, i += length(rawchar)) - rawchar = newletter = phrase[i] - if(prob(50)) - var/lowerletter = lowertext(newletter) - if(lowerletter == "o") - newletter = "u" - else if(lowerletter == "t") - newletter = "ch" - else if(lowerletter == "a") - newletter = "ah" - else if(lowerletter == "u") - newletter = "oo" - else if(lowerletter == "c") - newletter = " NAR " - else if(lowerletter == "s") - newletter = " SIE " - if(prob(25)) - if(newletter == " ") - newletter = " no hope... " - else if(newletter == "H") - newletter = " IT COMES... " - - if(prob(33)) - switch(rand(1, 5)) - if(1) - newletter = "'" - if(2) - newletter += "agn" - if(3) - newletter = "fth" - if(4) - newletter = "nglu" - if(5) - newletter = "glor" - . += newletter - return sanitize(.) - -///Adds stuttering to the message passed in -/proc/stutter(phrase) - phrase = html_decode(phrase) - var/leng = length(phrase) - . = "" - var/newletter = "" - var/rawchar = "" - var/static/regex/nostutter = regex(@@[aeiouAEIOU ""''()[\]{}.!?,:;_`~-]@) - for(var/i = 1, i <= leng, i += length(rawchar)) - rawchar = newletter = phrase[i] - if(prob(80) && !nostutter.Find(rawchar)) - if(prob(10)) - newletter = "[newletter]-[newletter]-[newletter]-[newletter]" - else if(prob(20)) - newletter = "[newletter]-[newletter]-[newletter]" - else if (prob(5)) - newletter = "" - else - newletter = "[newletter]-[newletter]" - . += newletter - return sanitize(.) - -///Convert a message to derpy speak -/proc/derpspeech(message, stuttering) - message = replacetext(message, " am ", " ") - message = replacetext(message, " is ", " ") - message = replacetext(message, " are ", " ") - message = replacetext(message, "you", "u") - message = replacetext(message, "help", "halp") - message = replacetext(message, "grief", "grife") - message = replacetext(message, "space", "spess") - message = replacetext(message, "carp", "crap") - message = replacetext(message, "reason", "raisin") - if(prob(50)) - message = uppertext(message) - message += "[stutter(pick("!", "!!", "!!!"))]" - if(!stuttering && prob(15)) - message = stutter(message) - return message - /** * Turn text into complete gibberish! * diff --git a/code/modules/ninja/suit/ninja_equipment_actions/ninja_adrenaline.dm b/code/modules/ninja/suit/ninja_equipment_actions/ninja_adrenaline.dm index ff368603eba..06fad9c95fb 100644 --- a/code/modules/ninja/suit/ninja_equipment_actions/ninja_adrenaline.dm +++ b/code/modules/ninja/suit/ninja_equipment_actions/ninja_adrenaline.dm @@ -25,7 +25,7 @@ ninja.SetImmobilized(0) ninja.SetParalyzed(0) ninja.adjustStaminaLoss(-200) - ninja.stuttering = 0 + ninja.remove_status_effect(/datum/status_effect/speech/stutter) ninja.reagents.add_reagent(/datum/reagent/medicine/stimulants, 5) ninja.say(pick("A CORNERED FOX IS MORE DANGEROUS THAN A JACKAL!","HURT ME MOOORRREEE!","IMPRESSIVE!"), forced = "ninjaboost") a_boost = FALSE diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index af587e41b02..537627b38fe 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -142,18 +142,22 @@ var/decayedRange //stores original range var/reflect_range_decrease = 5 //amount of original range that falls off when reflecting, so it doesn't go forever var/reflectable = NONE // Can it be reflected or not? - //Effects + // Status effects applied on hit var/stun = 0 var/knockdown = 0 var/paralyze = 0 var/immobilize = 0 var/unconscious = 0 - var/stutter = 0 - var/slur = 0 var/eyeblur = 0 var/drowsy = 0 - var/stamina = 0 var/jitter = 0 + /// Extra stamina damage applied on projectile hit (in addition to the main damage) + var/stamina = 0 + /// Stuttering applied on projectile hit + var/stutter = 0 SECONDS + /// Slurring applied on projectile hit + var/slur = 0 SECONDS + var/dismemberment = 0 //The higher the number, the greater the bonus to dismembering. 0 will not dismember at all. var/impact_effect_type //what type of impact effect to show when hitting something var/log_override = FALSE //is this type spammed enough to not log? (KAs) diff --git a/code/modules/projectiles/projectile/bullets/cannonball.dm b/code/modules/projectiles/projectile/bullets/cannonball.dm index 3fe2761b391..587e1a2e99d 100644 --- a/code/modules/projectiles/projectile/bullets/cannonball.dm +++ b/code/modules/projectiles/projectile/bullets/cannonball.dm @@ -7,7 +7,7 @@ projectile_piercing = ALL dismemberment = 0 paralyze = 5 SECONDS - stutter = 10 SECONDS + stutter = 20 SECONDS embedding = null hitsound = 'sound/effects/meteorimpact.ogg' hitsound_wall = 'sound/weapons/sonic_jackhammer.ogg' diff --git a/code/modules/projectiles/projectile/bullets/shotgun.dm b/code/modules/projectiles/projectile/bullets/shotgun.dm index 6d7bb9e97c3..ab4394a68b5 100644 --- a/code/modules/projectiles/projectile/bullets/shotgun.dm +++ b/code/modules/projectiles/projectile/bullets/shotgun.dm @@ -34,7 +34,7 @@ name = "stunslug" damage = 5 paralyze = 100 - stutter = 5 + stutter = 10 SECONDS jitter = 20 range = 7 icon_state = "spark" diff --git a/code/modules/projectiles/projectile/energy/ebow.dm b/code/modules/projectiles/projectile/energy/ebow.dm index 6d489029057..3d76e9ae1cb 100644 --- a/code/modules/projectiles/projectile/energy/ebow.dm +++ b/code/modules/projectiles/projectile/energy/ebow.dm @@ -7,7 +7,7 @@ stamina = 60 eyeblur = 10 knockdown = 10 - slur = 5 + slur = 10 SECONDS /obj/projectile/energy/bolt/halloween name = "candy corn" diff --git a/code/modules/projectiles/projectile/energy/stun.dm b/code/modules/projectiles/projectile/energy/stun.dm index 84d7adc5ed4..e556f60bcef 100644 --- a/code/modules/projectiles/projectile/energy/stun.dm +++ b/code/modules/projectiles/projectile/energy/stun.dm @@ -3,9 +3,8 @@ icon_state = "spark" color = "#FFFF00" nodamage = FALSE - //paralyze = 100 //SKYRAT EDIT REMOVAL - COMBAT - stamina = 80 //SKYRAT EDIT ADDITION - COMBAT - stutter = 5 + stamina = 80 // SKYRAT EDIT CHANGE + stutter = 10 SECONDS jitter = 20 hitsound = 'sound/weapons/taserhit.ogg' //range = 7 //ORIGINAL diff --git a/code/modules/projectiles/projectile/special/hallucination.dm b/code/modules/projectiles/projectile/special/hallucination.dm index 306c684b894..9cb974e3806 100644 --- a/code/modules/projectiles/projectile/special/hallucination.dm +++ b/code/modules/projectiles/projectile/special/hallucination.dm @@ -167,7 +167,7 @@ /obj/projectile/hallucination/taser/hal_apply_effect() hal_target.Paralyze(100) - hal_target.stuttering += 20 + hal_target.adjust_timed_status_effect(40 SECONDS, /datum/status_effect/speech/stutter) if(hal_target.dna && hal_target.dna.check_mutation(/datum/mutation/human/hulk)) hal_target.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" ), forced = "hulk") else if((hal_target.status_flags & CANKNOCKDOWN) && !HAS_TRAIT(hal_target, TRAIT_STUNIMMUNE)) @@ -200,7 +200,7 @@ /obj/projectile/hallucination/ebow/hal_apply_effect() hal_target.Paralyze(100) - hal_target.stuttering += 5 + hal_target.adjust_timed_status_effect(10 SECONDS, /datum/status_effect/speech/stutter) hal_target.adjustStaminaLoss(8) /obj/projectile/hallucination/change diff --git a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm index 3bdfd7620db..04c1bbbbd74 100644 --- a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm @@ -1503,9 +1503,7 @@ All effects don't start immediately, but rather get worse over time; the rate is if(!HAS_TRAIT(drinker, TRAIT_ALCOHOL_TOLERANCE)) drinker.set_confusion(max(drinker.get_confusion() + (2 * REM * delta_time),0)) drinker.Dizzy(10 * REM * delta_time) - if (!drinker.slurring) - drinker.slurring = 1 * REM * delta_time - drinker.slurring += 3 * REM * delta_time + drinker.adjust_timed_status_effect(6 SECONDS * REM * delta_time, /datum/status_effect/speech/slurring/drunk) switch(current_cycle) if(51 to 200) drinker.Sleeping(100 * REM * delta_time) @@ -1532,9 +1530,8 @@ All effects don't start immediately, but rather get worse over time; the rate is drinker.dizziness += 1.5 * REM * delta_time switch(current_cycle) if(15 to 45) - if(!drinker.slurring) - drinker.slurring = 1 * REM * delta_time - drinker.slurring += 3 * REM * delta_time + drinker.adjust_timed_status_effect(3 SECONDS * REM * delta_time, /datum/status_effect/speech/slurring/drunk) + if(45 to 55) if(DT_PROB(30, delta_time)) drinker.set_confusion(max(drinker.get_confusion() + 3, 0)) @@ -1607,8 +1604,8 @@ All effects don't start immediately, but rather get worse over time; the rate is chemical_flags = REAGENT_CAN_BE_SYNTHESIZED /datum/reagent/consumable/ethanol/hippies_delight/on_mob_life(mob/living/carbon/drinker, delta_time, times_fired) - if (!drinker.slurring) - drinker.slurring = 1 * REM * delta_time + drinker.set_timed_status_effect(1 SECONDS * REM * delta_time, /datum/status_effect/speech/slurring/drunk, only_if_higher = TRUE) + switch(current_cycle) if(1 to 5) drinker.Dizzy(10 * REM * delta_time) @@ -1666,9 +1663,9 @@ All effects don't start immediately, but rather get worse over time; the rate is liquid_fire_power = 2 //SKYRAT EDIT ADDITION /datum/reagent/consumable/ethanol/narsour/on_mob_life(mob/living/carbon/drinker, delta_time, times_fired) - drinker.cultslurring = min(drinker.cultslurring + (3 * REM * delta_time), 3) - drinker.stuttering = min(drinker.stuttering + (3 * REM * delta_time), 3) - ..() + drinker.adjust_timed_status_effect(6 SECONDS * REM * delta_time, /datum/status_effect/speech/slurring/cult, max_duration = 6 SECONDS) + drinker.adjust_timed_status_effect(6 SECONDS * REM * delta_time, /datum/status_effect/speech/stutter, max_duration = 6 SECONDS) + return ..() /datum/reagent/consumable/ethanol/triple_sec name = "Triple Sec" @@ -2447,7 +2444,7 @@ All effects don't start immediately, but rather get worse over time; the rate is if(drinker.mind?.holy_role) drinker.adjustFireLoss(-2.5 * REM * delta_time, 0) drinker.jitteriness = max(drinker.jitteriness - (1 * REM * delta_time), 0) - drinker.stuttering = max(drinker.stuttering - (1 * REM * delta_time), 0) + drinker.adjust_timed_status_effect(-2 SECONDS * REM * delta_time, /datum/status_effect/speech/stutter) return ..() /datum/reagent/consumable/ethanol/blazaam diff --git a/code/modules/reagents/chemistry/reagents/drug_reagents.dm b/code/modules/reagents/chemistry/reagents/drug_reagents.dm index 3e593b513ec..5b2e2c55d48 100644 --- a/code/modules/reagents/chemistry/reagents/drug_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/drug_reagents.dm @@ -445,8 +445,8 @@ addiction_types = list(/datum/addiction/hallucinogens = 12) /datum/reagent/drug/mushroomhallucinogen/on_mob_life(mob/living/carbon/psychonaut, delta_time, times_fired) - if(!psychonaut.slurring) - psychonaut.slurring = 1 * REM * delta_time + psychonaut.set_timed_status_effect(1 SECONDS * REM * delta_time, /datum/status_effect/speech/slurring/drunk, only_if_higher = TRUE) + switch(current_cycle) if(1 to 5) if(DT_PROB(5, delta_time)) diff --git a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm index 2986415b634..0bfd6817dc7 100644 --- a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm @@ -82,9 +82,10 @@ M.silent = FALSE M.dizziness = 0 M.disgust = 0 - M.set_drowsyness(0) - M.stuttering = 0 - M.slurring = 0 + M.drowsyness = 0 + // Remove all speech related status effects + for(var/effect in typesof(/datum/status_effect/speech)) + M.remove_status_effect(effect) M.jitteriness = 0 M.hallucination = 0 REMOVE_TRAITS_NOT_IN(M, list(SPECIES_TRAIT, ROUNDSTART_TRAIT, ORGAN_TRAIT)) @@ -997,13 +998,13 @@ ph = 4 purity = REAGENT_STANDARD_PURITY chemical_flags = REAGENT_CAN_BE_SYNTHESIZED - inverse_chem_val = 0.35 - inverse_chem = /datum/reagent/inverse/antihol + inverse_chem_val = 0.35 + inverse_chem = /datum/reagent/inverse/antihol /datum/reagent/medicine/antihol/on_mob_life(mob/living/carbon/M, delta_time, times_fired) M.dizziness = 0 M.set_drowsyness(0) - M.slurring = 0 + M.remove_status_effect(/datum/status_effect/speech/slurring/drunk) M.set_confusion(0) M.reagents.remove_all_type(/datum/reagent/consumable/ethanol, 3 * REM * delta_time * normalise_creation_purity(), FALSE, TRUE) M.adjustToxLoss(-0.2 * REM * delta_time, 0) @@ -1354,7 +1355,7 @@ switch(overdose_progress) if(1 to 40) M.jitteriness = min(M.jitteriness + (1 * REM * delta_time), 10) - M.stuttering = min(M.stuttering + (1 * REM * delta_time), 10) + M.adjust_timed_status_effect(2 SECONDS * REM * delta_time, /datum/status_effect/speech/stutter, max_duration = 20 SECONDS) M.Dizzy(5 * REM * delta_time) if(DT_PROB(30, delta_time)) M.losebreath++ @@ -1362,7 +1363,7 @@ M.adjustOxyLoss(0.1 * REM * delta_time, 0) M.adjustStaminaLoss(0.1 * REM * delta_time, 0) M.jitteriness = min(M.jitteriness + (1 * REM * delta_time), 20) - M.stuttering = min(M.stuttering + (1 * REM * delta_time), 20) + M.adjust_timed_status_effect(2 SECONDS * REM * delta_time, /datum/status_effect/speech/stutter, max_duration = 40 SECONDS) M.Dizzy(10 * REM * delta_time) if(DT_PROB(30, delta_time)) M.losebreath++ diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index 21c41d5bd78..5a3327c0892 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -292,9 +292,7 @@ for(var/datum/action/innate/cult/blood_spell/BS in BM.spells) qdel(BS) if(data["misc"] >= (25 SECONDS)) // 10 units - if(!M.stuttering) - M.stuttering = 1 - M.stuttering = min(M.stuttering + (2 * delta_time), 10) + M.adjust_timed_status_effect(4 SECONDS * delta_time, /datum/status_effect/speech/stutter, max_duration = 20 SECONDS) M.Dizzy(5) if(IS_CULTIST(M) && DT_PROB(10, delta_time)) M.say(pick("Av'te Nar'Sie","Pa'lid Mors","INO INO ORA ANA","SAT ANA!","Daim'niodeis Arc'iai Le'eones","R'ge Na'sie","Diabo us Vo'iscum","Eld' Mon Nobis"), forced = "holy water") @@ -308,7 +306,7 @@ M.mind.remove_antag_datum(/datum/antagonist/cult) M.Unconscious(100) M.jitteriness = 0 - M.stuttering = 0 + M.remove_status_effect(/datum/status_effect/speech/stutter) holder.remove_reagent(type, volume) // maybe this is a little too perfect and a max() cap on the statuses would be better?? return holder.remove_reagent(type, 1 * REAGENTS_METABOLISM * delta_time) //fixed consumption to prevent balancing going out of whack diff --git a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm index 5cbd3f2d9d1..2802580546f 100644 --- a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm @@ -254,7 +254,7 @@ if(1 to 5) M.add_confusion(1 * REM * delta_time) M.adjust_drowsyness(1 * REM * delta_time) - M.slurring += 3 * REM * delta_time + M.adjust_timed_status_effect(6 SECONDS * REM * delta_time, /datum/status_effect/speech/slurring/drunk) if(5 to 8) M.adjustStaminaLoss(40 * REM * delta_time, 0) if(9 to INFINITY) diff --git a/code/modules/surgery/organs/stomach/_stomach.dm b/code/modules/surgery/organs/stomach/_stomach.dm index 39793ae622b..d386d48e7c3 100644 --- a/code/modules/surgery/organs/stomach/_stomach.dm +++ b/code/modules/surgery/organs/stomach/_stomach.dm @@ -210,7 +210,7 @@ var/pukeprob = 2.5 + (0.025 * disgusted.disgust) if(disgusted.disgust >= DISGUST_LEVEL_GROSS) if(DT_PROB(5, delta_time)) - disgusted.stuttering += 1 + disgusted.adjust_timed_status_effect(2 SECONDS, /datum/status_effect/speech/stutter) disgusted.add_confusion(2) if(DT_PROB(5, delta_time) && !disgusted.stat) to_chat(disgusted, span_warning("You feel kind of iffy...")) @@ -218,7 +218,7 @@ if(disgusted.disgust >= DISGUST_LEVEL_VERYGROSS) if(DT_PROB(pukeprob, delta_time)) //iT hAndLeS mOrE ThaN PukInG disgusted.add_confusion(2.5) - disgusted.stuttering += 1 + disgusted.adjust_timed_status_effect(2 SECONDS, /datum/status_effect/speech/stutter) disgusted.vomit(10, 0, 1, 0, 1, 0) disgusted.Dizzy(5) if(disgusted.disgust >= DISGUST_LEVEL_DISGUSTED) diff --git a/code/modules/vehicles/mecha/equipment/weapons/weapons.dm b/code/modules/vehicles/mecha/equipment/weapons/weapons.dm index aa07af6affb..1eca7e3422e 100644 --- a/code/modules/vehicles/mecha/equipment/weapons/weapons.dm +++ b/code/modules/vehicles/mecha/equipment/weapons/weapons.dm @@ -194,7 +194,7 @@ continue to_chat(M, "HONK") M.SetSleeping(0) - M.stuttering += 20 + M.adjust_timed_status_effect(40 SECONDS, /datum/status_effect/speech/stutter) var/obj/item/organ/ears/ears = M.getorganslot(ORGAN_SLOT_EARS) if(ears) ears.adjustEarDamage(0, 30) diff --git a/modular_skyrat/modules/contractor/code/items/baton.dm b/modular_skyrat/modules/contractor/code/items/baton.dm index 2fdb0ffa725..4bb372d8825 100644 --- a/modular_skyrat/modules/contractor/code/items/baton.dm +++ b/modular_skyrat/modules/contractor/code/items/baton.dm @@ -76,7 +76,7 @@ if((upgrade_flags & BATON_FOCUS_UPGRADE)) if(target == user.mind?.opposing_force?.contractor_hub?.current_contract?.contract.target?.current) // Pain target.apply_damage(BONUS_STAMINA_DAM, STAMINA, BODY_ZONE_CHEST) - target.stuttering += BONUS_STUTTER + target.adjust_timed_status_effect(10 SECONDS, /datum/status_effect/speech/stutter) /obj/item/melee/baton/telescopic/contractor_baton/examine(mob/user) . = ..() diff --git a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/human.dm b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/human.dm index 304178f27f1..7828865f9ab 100644 --- a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/human.dm +++ b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/human.dm @@ -110,7 +110,7 @@ return var/list/choices = list("Drunkenness", "Stuttering", "Jittering") - if(slurring >= 10 || stuttering >= 10 || jitteriness >= 10) //Give the option to end the impairment if there's one ongoing. + if(jitteriness >= 10) //Give the option to end the impairment if there's one ongoing. var/disable = tgui_input_list(src, "Stop performing existing impairment?", "Impairments", choices) if(disable) acting_expiry(disable) @@ -122,10 +122,6 @@ var/duration = tgui_input_number(src, "How long would you like to feign [impairment] for?", "Duration in seconds", 25, 36000) switch(impairment) - if("Drunkenness") - slurring = duration - if("Stuttering") - stuttering = duration if("Jittering") jitteriness = duration @@ -136,10 +132,6 @@ /mob/living/carbon/human/proc/acting_expiry(var/impairment) //End only the impairment we're affected by. if(impairment) switch(impairment) - if("Drunkenness") - slurring = 0 - if("Stuttering") - stuttering = 0 if("Jittering") jitteriness = 0 to_chat(src, "You are no longer feigning [impairment].") diff --git a/modular_skyrat/modules/customization/modules/surgery/organs/vox.dm b/modular_skyrat/modules/customization/modules/surgery/organs/vox.dm index 5a5e620d835..97a24b6c511 100644 --- a/modular_skyrat/modules/customization/modules/surgery/organs/vox.dm +++ b/modular_skyrat/modules/customization/modules/surgery/organs/vox.dm @@ -35,11 +35,11 @@ to_chat(owner, span_boldwarning("You feel [pick("like your brain is being fried", "a sharp pain in your head")]!")) owner.adjustOrganLoss(ORGAN_SLOT_BRAIN, 20, 150) owner.jitteriness += 30 - owner.stuttering += 30 + owner.adjust_timed_status_effect(30 SECONDS, /datum/status_effect/speech/stutter) owner.add_confusion(10) if(2) to_chat(owner, span_warning("You feel [pick("disoriented", "confused", "dizzy")].")) owner.adjustOrganLoss(ORGAN_SLOT_BRAIN, 10, 150) owner.jitteriness += 10 - owner.stuttering += 10 + owner.adjust_timed_status_effect(30 SECONDS, /datum/status_effect/speech/stutter) owner.add_confusion(3) diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/shockcollar.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/shockcollar.dm index 0445de35d89..8e46051af67 100644 --- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/shockcollar.dm +++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/shockcollar.dm @@ -50,7 +50,7 @@ L.Paralyze(30) L.adjustPain(10) - L.stuttering += 60 + L.adjust_timed_status_effect(30 SECONDS, /datum/status_effect/speech/stutter) if(master) if(isassembly(master)) diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/kinky_shocker.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/kinky_shocker.dm index 60f2ccd1a0e..5cbe4baf72b 100644 --- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/kinky_shocker.dm +++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/kinky_shocker.dm @@ -284,4 +284,4 @@ target.do_jitter_animation() target.adjustStaminaLoss(3) target.adjustPain(9) - target.stuttering += 20 + target.adjust_timed_status_effect(30 SECONDS, /datum/status_effect/speech/stutter) diff --git a/modular_skyrat/modules/morenarcotics/code/quaalude.dm b/modular_skyrat/modules/morenarcotics/code/quaalude.dm index ba953a87e83..fc7b4650341 100644 --- a/modular_skyrat/modules/morenarcotics/code/quaalude.dm +++ b/modular_skyrat/modules/morenarcotics/code/quaalude.dm @@ -21,8 +21,7 @@ var/atom/movable/plane_master_controller/game_plane_master_controller = M.hud_used.plane_master_controllers[PLANE_MASTERS_GAME] game_plane_master_controller.add_filter("quaalude_wave", 10, wave_filter(300, 300, 3, 0, WAVE_SIDEWAYS)) M.set_drugginess(15 * REM * delta_time) - if(!M.slurring) - M.slurring = 10 * REM * delta_time + M.adjust_timed_status_effect(1 MINUTES, /datum/status_effect/speech/slurring/drunk) M.Dizzy(5 * REM * delta_time) M.adjustStaminaLoss(-5 * REM * delta_time, 0) if(DT_PROB(3.5, delta_time)) diff --git a/strings/slurring_cult_text.json b/strings/slurring_cult_text.json new file mode 100644 index 00000000000..192893bdc85 --- /dev/null +++ b/strings/slurring_cult_text.json @@ -0,0 +1,27 @@ +{ + "replacements": { + "characters": { + "common": { + "o": "u", + "t": "ch", + "a": "ah", + "u": "oo", + "c": " NAR ", + "s": " SIE " + }, + "uncommon": { + " ": " no hope... ", + "H": " IT COMES... " + } + }, + "string_replacements": [ + "'", + "fth", + "nglu", + "glor" + ], + "string_additions": [ + "agn" + ] + } +} diff --git a/strings/slurring_drunk_text.json b/strings/slurring_drunk_text.json new file mode 100644 index 00000000000..a68a00b0858 --- /dev/null +++ b/strings/slurring_drunk_text.json @@ -0,0 +1,20 @@ +{ + "replacements": { + "characters": { + "common": { + "o": "u", + "s": "ch", + "a": "ah", + "u": "oo", + "c": "k" + }, + "uncommon": { + " ": "...huuuhhh...", + ".": " *BURP*." + } + }, + "string_additions": [ + "'" + ] + } +} diff --git a/strings/slurring_heretic_text.json b/strings/slurring_heretic_text.json new file mode 100644 index 00000000000..d5b87ec911c --- /dev/null +++ b/strings/slurring_heretic_text.json @@ -0,0 +1,32 @@ +{ + "replacements": { + "characters": { + "common": { + "o": "u", + "t": "ch", + "a": "ah", + "c": "th", + "i": "ks", + "m": "nth" + }, + "uncommon": { + " ": " endless... ", + "H": " THE HANDS... ", + "h": " BRIGHT ", + "s": " LEAK ", + "r": " CRACK " + } + }, + "string_replacements": [ + "'", + "br", + "th", + "see", + "etch" + ], + "string_additions": [ + "ah", + "wth" + ] + } +} diff --git a/tgstation.dme b/tgstation.dme index bc80b9451af..e98dd0cbbbf 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -1165,12 +1165,13 @@ #include "code\datums\station_traits\positive_traits.dm" #include "code\datums\status_effects\agent_pinpointer.dm" #include "code\datums\status_effects\buffs.dm" -#include "code\datums\status_effects\debuffs.dm" #include "code\datums\status_effects\drug_effects.dm" #include "code\datums\status_effects\gas.dm" #include "code\datums\status_effects\neutral.dm" #include "code\datums\status_effects\status_effect.dm" #include "code\datums\status_effects\wound_effects.dm" +#include "code\datums\status_effects\debuffs\debuffs.dm" +#include "code\datums\status_effects\debuffs\speech_debuffs.dm" #include "code\datums\weather\weather.dm" #include "code\datums\weather\weather_types\ash_storm.dm" #include "code\datums\weather\weather_types\floor_is_lava.dm"