From 99337c670fd0ce80a0842f4dda04f9efd269deb2 Mon Sep 17 00:00:00 2001 From: SkyratBot <59378654+SkyratBot@users.noreply.github.com> Date: Thu, 11 Jul 2024 16:08:22 +0200 Subject: [PATCH] [MIRROR] Converts common speech modifiers into a component (#28752) * Converts common speech modifiers into a component * modular --------- Co-authored-by: SmArtKar <44720187+SmArtKar@users.noreply.github.com> Co-authored-by: SpaceLoveSs13 <68121607+SpaceLoveSs13@users.noreply.github.com> --- .../signals/signals_mob/signals_mob_carbon.dm | 5 + code/datums/components/speechmod.dm | 125 ++++++++++++++++++ code/datums/mutations/_mutations.dm | 2 + code/datums/mutations/hulk.dm | 17 +-- code/datums/mutations/speech.dm | 91 ++----------- .../dna_infuser/organ_sets/fly_organs.dm | 40 +++--- code/modules/clothing/head/frenchberet.dm | 26 +--- code/modules/clothing/masks/_masks.dm | 26 ---- code/modules/clothing/masks/animal_masks.dm | 25 +++- code/modules/clothing/masks/boxing.dm | 27 +--- code/modules/clothing/masks/gondola.dm | 17 +-- code/modules/clothing/masks/moustache.dm | 22 +-- .../surgery/organs/internal/tongue/_tongue.dm | 61 +++++---- .../lewd_items/code/lewd_clothing/ballgag.dm | 16 ++- .../code/lewd_clothing/bdsm_mask.dm | 21 ++- .../code/lewd_items/leather_whip.dm | 16 ++- strings/elvis_replacement.json | 13 ++ strings/luchador_replacement.json | 20 +++ tgstation.dme | 1 + 19 files changed, 311 insertions(+), 260 deletions(-) create mode 100644 code/datums/components/speechmod.dm create mode 100644 strings/elvis_replacement.json create mode 100644 strings/luchador_replacement.json diff --git a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_carbon.dm b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_carbon.dm index f0808a5a691..051953bd7e5 100644 --- a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_carbon.dm +++ b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_carbon.dm @@ -161,3 +161,8 @@ /// from /datum/status_effect/limp/proc/check_step(mob/whocares, OldLoc, Dir, forced) iodk where it shuld go #define COMSIG_CARBON_LIMPING "mob_limp_check" #define COMPONENT_CANCEL_LIMP (1<<0) + +///Called from on_acquiring(mob/living/carbon/human/acquirer) +#define COMSIG_MUTATION_GAINED "mutation_gained" +///Called from on_losing(mob/living/carbon/human/owner) +#define COMSIG_MUTATION_LOST "mutation_lost" diff --git a/code/datums/components/speechmod.dm b/code/datums/components/speechmod.dm new file mode 100644 index 00000000000..71991c80d83 --- /dev/null +++ b/code/datums/components/speechmod.dm @@ -0,0 +1,125 @@ +/// Used to apply certain speech patterns +/// Can be used on organs, wearables, mutations and mobs +/datum/component/speechmod + /// Assoc list for strings/regexes and their replacements. Should be lowercase, as case will be automatically changed + var/list/replacements = list() + /// String added to the end of the message + var/end_string = "" + /// Chance for the end string to be applied + var/end_string_chance = 100 + /// Current target for modification + var/mob/targeted + /// Slot tags in which this item works when equipped + var/slots + /// If set to true, turns all text to uppercase + var/uppercase = FALSE + +/datum/component/speechmod/Initialize(replacements = list(), end_string = "", end_string_chance = 100, slots, uppercase = FALSE) + if (!ismob(parent) && !isitem(parent) && !istype(parent, /datum/mutation/human)) + return COMPONENT_INCOMPATIBLE + + src.replacements = replacements + src.end_string = end_string + src.end_string_chance = end_string_chance + src.slots = slots + src.uppercase = uppercase + + if (istype(parent, /datum/mutation/human)) + RegisterSignal(parent, COMSIG_MUTATION_GAINED, PROC_REF(on_mutation_gained)) + RegisterSignal(parent, COMSIG_MUTATION_LOST, PROC_REF(on_mutation_lost)) + return + + var/atom/owner = parent + + if (ismob(parent)) + targeted = parent + RegisterSignal(targeted, COMSIG_MOB_SAY, PROC_REF(handle_speech)) + return + + if (ismob(owner.loc)) + targeted = owner.loc + RegisterSignal(targeted, COMSIG_MOB_SAY, PROC_REF(handle_speech)) + + RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, PROC_REF(on_equipped)) + RegisterSignal(parent, COMSIG_ITEM_DROPPED, PROC_REF(on_unequipped)) + RegisterSignal(parent, COMSIG_ORGAN_IMPLANTED, PROC_REF(on_implanted)) + RegisterSignal(parent, COMSIG_ORGAN_REMOVED, PROC_REF(on_removed)) + +/datum/component/speechmod/proc/handle_speech(datum/source, list/speech_args) + SIGNAL_HANDLER + + var/message = speech_args[SPEECH_MESSAGE] + if(message[1] == "*") + return + + for (var/to_replace in replacements) + var/replacement = replacements[to_replace] + // Values can be lists to be picked randomly from + if (islist(replacement)) + replacement = pick(replacement) + + message = replacetextEx(message, to_replace, replacement) + message = trim(message) + if (prob(end_string_chance)) + message += islist(end_string) ? pick(end_string) : end_string + speech_args[SPEECH_MESSAGE] = trim(message) + + if (uppercase) + return COMPONENT_UPPERCASE_SPEECH + +/datum/component/speechmod/proc/on_equipped(datum/source, mob/living/user, slot) + SIGNAL_HANDLER + + if (!isnull(slots) && !(slot & slots)) + if (!isnull(targeted)) + UnregisterSignal(targeted, COMSIG_MOB_SAY) + targeted = null + return + + if (targeted == user) + return + + targeted = user + RegisterSignal(targeted, COMSIG_MOB_SAY, PROC_REF(handle_speech)) + +/datum/component/speechmod/proc/on_unequipped(datum/source, mob/living/user) + SIGNAL_HANDLER + + if (isnull(targeted)) + return + UnregisterSignal(targeted, COMSIG_MOB_SAY) + targeted = null + +/datum/component/speechmod/proc/on_implanted(datum/source, mob/living/carbon/receiver) + SIGNAL_HANDLER + + if (targeted == receiver) + return + + targeted = receiver + RegisterSignal(targeted, COMSIG_MOB_SAY, PROC_REF(handle_speech)) + +/datum/component/speechmod/proc/on_removed(datum/source, mob/living/carbon/former_owner) + SIGNAL_HANDLER + + if (isnull(targeted)) + return + UnregisterSignal(targeted, COMSIG_MOB_SAY) + targeted = null + +/datum/component/speechmod/proc/on_mutation_gained(datum/source, mob/living/carbon/human/owner) + SIGNAL_HANDLER + + if (targeted == owner) + return + + targeted = owner + RegisterSignal(targeted, COMSIG_MOB_SAY, PROC_REF(handle_speech)) + +/datum/component/speechmod/proc/on_mutation_lost(datum/source, mob/living/carbon/human/owner) + SIGNAL_HANDLER + + if (isnull(targeted)) + return + UnregisterSignal(targeted, COMSIG_MOB_SAY) + targeted = null diff --git a/code/datums/mutations/_mutations.dm b/code/datums/mutations/_mutations.dm index d8aaf3baaaa..dc7b64089bd 100644 --- a/code/datums/mutations/_mutations.dm +++ b/code/datums/mutations/_mutations.dm @@ -136,6 +136,7 @@ owner = acquirer dna = acquirer.dna dna.mutations += src + SEND_SIGNAL(src, COMSIG_MUTATION_GAINED, acquirer) if(text_gain_indication) to_chat(owner, text_gain_indication) if(visual_indicators.len) @@ -162,6 +163,7 @@ if(!istype(owner) || !(owner.dna.mutations.Remove(src))) return TRUE . = FALSE + SEND_SIGNAL(src, COMSIG_MUTATION_LOST, owner) if(text_lose_indication && owner.stat != DEAD) to_chat(owner, text_lose_indication) if(visual_indicators.len) diff --git a/code/datums/mutations/hulk.dm b/code/datums/mutations/hulk.dm index 5717f649b11..dcd49768552 100644 --- a/code/datums/mutations/hulk.dm +++ b/code/datums/mutations/hulk.dm @@ -20,6 +20,9 @@ TRAIT_STUNIMMUNE, ) +/datum/mutation/human/hulk/New(class, timer, datum/mutation/human/copymut) + . = ..() + AddComponent(/datum/component/speechmod, replacements = list("." = "!"), end_string = "!!", uppercase = TRUE) /datum/mutation/human/hulk/on_acquiring(mob/living/carbon/human/owner) if(..()) @@ -29,7 +32,6 @@ owner.update_body_parts() owner.add_mood_event("hulk", /datum/mood_event/hulk) RegisterSignal(owner, COMSIG_LIVING_EARLY_UNARMED_ATTACK, PROC_REF(on_attack_hand)) - RegisterSignal(owner, COMSIG_MOB_SAY, PROC_REF(handle_speech)) RegisterSignal(owner, COMSIG_MOB_CLICKON, PROC_REF(check_swing)) /datum/mutation/human/hulk/proc/on_attack_hand(mob/living/carbon/human/source, atom/target, proximity, modifiers) @@ -91,21 +93,8 @@ owner.update_body_parts() owner.clear_mood_event("hulk") UnregisterSignal(owner, COMSIG_LIVING_EARLY_UNARMED_ATTACK) - UnregisterSignal(owner, COMSIG_MOB_SAY) UnregisterSignal(owner, COMSIG_MOB_CLICKON) -/datum/mutation/human/hulk/proc/handle_speech(datum/source, list/speech_args) - SIGNAL_HANDLER - - var/message = speech_args[SPEECH_MESSAGE] - if(message) - message = "[replacetext(message, ".", "!")]!!" - speech_args[SPEECH_MESSAGE] = message - - // the reason we don't just uppertext(message) in this proc is so that our hulk speech - // can uppercase all other speech moidifiers after they are done (by returning COMPONENT_UPPERCASE_SPEECH) - return COMPONENT_UPPERCASE_SPEECH - /// How many steps it takes to throw the mob #define HULK_TAILTHROW_STEPS 28 diff --git a/code/datums/mutations/speech.dm b/code/datums/mutations/speech.dm index 98560bb2526..d6b6f714e59 100644 --- a/code/datums/mutations/speech.dm +++ b/code/datums/mutations/speech.dm @@ -177,30 +177,11 @@ quality = MINOR_NEGATIVE text_gain_indication = span_notice("You feel Swedish, however that works.") text_lose_indication = span_notice("The feeling of Swedishness passes.") + var/static/list/language_mutilation = list("w" = "v", "j" = "y", "bo" = "bjo", "a" = list("å","ä","æ","a"), "o" = list("ö","ø","o")) -/datum/mutation/human/swedish/on_acquiring(mob/living/carbon/human/owner) - if(..()) - return - RegisterSignal(owner, COMSIG_MOB_SAY, PROC_REF(handle_speech)) - -/datum/mutation/human/swedish/on_losing(mob/living/carbon/human/owner) - if(..()) - return - UnregisterSignal(owner, COMSIG_MOB_SAY) - -/datum/mutation/human/swedish/proc/handle_speech(datum/source, list/speech_args) - SIGNAL_HANDLER - - var/message = speech_args[SPEECH_MESSAGE] - if(message) - message = replacetext(message,"w","v") - message = replacetext(message,"j","y") - message = replacetext(message,"a",pick("å","ä","æ","a")) - message = replacetext(message,"bo","bjo") - message = replacetext(message,"o",pick("ö","ø","o")) - if(prob(30)) - message += " Bork[pick("",", bork",", bork, bork")]!" - speech_args[SPEECH_MESSAGE] = trim(message) +/datum/mutation/human/swedish/New(class, timer, datum/mutation/human/copymut) + . = ..() + AddComponent(/datum/component/speechmod, replacements = language_mutilation, end_string = list("",", bork",", bork, bork"), end_string_chance = 30) /datum/mutation/human/chav name = "Chav" @@ -210,35 +191,9 @@ text_gain_indication = span_notice("Ye feel like a reet prat like, innit?") text_lose_indication = span_notice("You no longer feel like being rude and sassy.") -/datum/mutation/human/chav/on_acquiring(mob/living/carbon/human/owner) - if(..()) - return - RegisterSignal(owner, COMSIG_MOB_SAY, PROC_REF(handle_speech)) - -/datum/mutation/human/chav/on_losing(mob/living/carbon/human/owner) - if(..()) - return - UnregisterSignal(owner, COMSIG_MOB_SAY) - -/datum/mutation/human/chav/proc/handle_speech(datum/source, list/speech_args) - SIGNAL_HANDLER - - var/message = speech_args[SPEECH_MESSAGE] - if(message[1] != "*") - message = " [message]" - var/list/chav_words = strings("chav_replacement.json", "chav") - - for(var/key in chav_words) - var/value = chav_words[key] - if(islist(value)) - value = pick(value) - - message = replacetextEx(message, " [uppertext(key)]", " [uppertext(value)]") - message = replacetextEx(message, " [capitalize(key)]", " [capitalize(value)]") - message = replacetextEx(message, " [key]", " [value]") - if(prob(30)) - message += ", mate" - speech_args[SPEECH_MESSAGE] = trim(message) +/datum/mutation/human/chav/New(class, timer, datum/mutation/human/copymut) + . = ..() + AddComponent(/datum/component/speechmod, replacements = strings("chav_replacement.json", "chav"), end_string = ", mate", end_string_chance = 30) /datum/mutation/human/elvis name = "Elvis" @@ -248,6 +203,10 @@ text_gain_indication = span_notice("You feel pretty good, honeydoll.") text_lose_indication = span_notice("You feel a little less conversation would be great.") +/datum/mutation/human/chav/New(class, timer, datum/mutation/human/copymut) + . = ..() + AddComponent(/datum/component/speechmod, replacements = strings("elvis_replacement.json", "elvis")) + /datum/mutation/human/elvis/on_life(seconds_per_tick, times_fired) switch(pick(1,2)) if(1) @@ -259,34 +218,6 @@ if(SPT_PROB(7.5, seconds_per_tick)) owner.visible_message("[owner] [pick("jiggles their hips", "rotates their hips", "gyrates their hips", "taps their foot", "dances to an imaginary song", "jiggles their legs", "snaps their fingers")]!") -/datum/mutation/human/elvis/on_acquiring(mob/living/carbon/human/owner) - if(..()) - return - RegisterSignal(owner, COMSIG_MOB_SAY, PROC_REF(handle_speech)) - -/datum/mutation/human/elvis/on_losing(mob/living/carbon/human/owner) - if(..()) - return - UnregisterSignal(owner, COMSIG_MOB_SAY) - -/datum/mutation/human/elvis/proc/handle_speech(datum/source, list/speech_args) - SIGNAL_HANDLER - - var/message = speech_args[SPEECH_MESSAGE] - if(message) - message = " [message] " - message = replacetext(message," i'm not "," I ain't ") - message = replacetext(message," girl ",pick(" honey "," baby "," baby doll ")) - message = replacetext(message," man ",pick(" son "," buddy "," brother"," pal "," friendo ")) - message = replacetext(message," out of "," outta ") - message = replacetext(message," thank you "," thank you, thank you very much ") - message = replacetext(message," thanks "," thank you, thank you very much ") - message = replacetext(message," what are you "," whatcha ") - message = replacetext(message," yes ",pick(" sure", "yea ")) - message = replacetext(message," muh valids "," my kicks ") - speech_args[SPEECH_MESSAGE] = trim(message) - - /datum/mutation/human/stoner name = "Stoner" desc = "A common mutation that severely decreases intelligence." diff --git a/code/game/machinery/dna_infuser/organ_sets/fly_organs.dm b/code/game/machinery/dna_infuser/organ_sets/fly_organs.dm index e7551394131..60d1b10e231 100644 --- a/code/game/machinery/dna_infuser/organ_sets/fly_organs.dm +++ b/code/game/machinery/dna_infuser/organ_sets/fly_organs.dm @@ -42,26 +42,28 @@ toxic_foodtypes = NONE // these fucks eat vomit, i am sure they can handle drinking bleach or whatever too modifies_speech = TRUE languages_native = list(/datum/language/buzzwords) + var/static/list/speech_replacements = list( + new /regex("z+", "g") = "zzz", + new /regex("Z+", "g") = "ZZZ", + "s" = "z", + "S" = "Z", + ) + // SKYRAT EDIT ADDITION START - Russian version + var/static/list/russian_speech_replacements = list( + new /regex("z+", "g") = "zzz", + new /regex("Z+", "g") = "ZZZ", + new /regex("з+", "g") = "ззз", + new /regex("З+", "g") = "ЗЗЗ", + "s" = "z", + "S" = "Z", + "с" = "з", + "С" = "З", + ) + // SKYRAT EDIT ADDITION END -/obj/item/organ/internal/tongue/fly/modify_speech(datum/source, list/speech_args) - var/static/regex/fly_buzz = new("z+", "g") - var/static/regex/fly_buZZ = new("Z+", "g") - var/message = speech_args[SPEECH_MESSAGE] - if(message[1] != "*") - message = fly_buzz.Replace(message, "zzz") - message = fly_buZZ.Replace(message, "ZZZ") - message = replacetext(message, "s", "z") - message = replacetext(message, "S", "Z") -//SKYRAT EDIT START: Adding russian version to autohiss - if(CONFIG_GET(flag/russian_text_formation)) - var/static/regex/fly_buzz_ru = new("з+", "g") - var/static/regex/fly_buZZ_ru = new("З+", "g") - message = fly_buzz_ru.Replace(message, "ззз") - message = fly_buZZ_ru.Replace(message, "ЗЗЗ") - message = replacetext(message, "с", "з") - message = replacetext(message, "С", "З") -//SKYRAT EDIT END: Adding russian version to autohiss - speech_args[SPEECH_MESSAGE] = message +/obj/item/organ/internal/tongue/fly/New(class, timer, datum/mutation/human/copymut) + . = ..() + AddComponent(/datum/component/speechmod, replacements = CONFIG_GET(flag/russian_text_formation) ? russian_speech_replacements : speech_replacements) // SKYRAT EDIT CHANGE - ORIGINAL: AddComponent(/datum/component/speechmod, replacements = speech_replacements) /obj/item/organ/internal/tongue/fly/Initialize(mapload) . = ..() diff --git a/code/modules/clothing/head/frenchberet.dm b/code/modules/clothing/head/frenchberet.dm index 40d8abc5b62..de63c6fddfd 100644 --- a/code/modules/clothing/head/frenchberet.dm +++ b/code/modules/clothing/head/frenchberet.dm @@ -6,37 +6,17 @@ greyscale_config_worn = /datum/greyscale_config/beret/worn greyscale_colors = "#972A2A" +/obj/item/clothing/head/frenchberet/Initialize(mapload) + . = ..() + AddComponent(/datum/component/speechmod, replacements = strings("french_replacement.json", "french"), end_string = list(" Honh honh honh!"," Honh!"," Zut Alors!"), end_string_chance = 3, slots = ITEM_SLOT_HEAD) /obj/item/clothing/head/frenchberet/equipped(mob/M, slot) . = ..() if (slot & ITEM_SLOT_HEAD) - RegisterSignal(M, COMSIG_MOB_SAY, PROC_REF(handle_speech)) ADD_TRAIT(M, TRAIT_GARLIC_BREATH, type) else - UnregisterSignal(M, COMSIG_MOB_SAY) REMOVE_TRAIT(M, TRAIT_GARLIC_BREATH, type) /obj/item/clothing/head/frenchberet/dropped(mob/M) . = ..() - UnregisterSignal(M, COMSIG_MOB_SAY) REMOVE_TRAIT(M, TRAIT_GARLIC_BREATH, type) - -/obj/item/clothing/head/frenchberet/proc/handle_speech(datum/source, list/speech_args) - SIGNAL_HANDLER - var/message = speech_args[SPEECH_MESSAGE] - if(message[1] != "*") - message = " [message]" - var/list/french_words = strings("french_replacement.json", "french") - - for(var/key in french_words) - var/value = french_words[key] - if(islist(value)) - value = pick(value) - - message = replacetextEx(message, " [uppertext(key)]", " [uppertext(value)]") - message = replacetextEx(message, " [capitalize(key)]", " [capitalize(value)]") - message = replacetextEx(message, " [key]", " [value]") - - if(prob(3)) - message += pick(" Honh honh honh!"," Honh!"," Zut Alors!") - speech_args[SPEECH_MESSAGE] = trim(message) diff --git a/code/modules/clothing/masks/_masks.dm b/code/modules/clothing/masks/_masks.dm index c1d29d65c86..5255b758b6f 100644 --- a/code/modules/clothing/masks/_masks.dm +++ b/code/modules/clothing/masks/_masks.dm @@ -8,7 +8,6 @@ strip_delay = 40 equip_delay_other = 40 visor_vars_to_toggle = NONE - var/modifies_speech = FALSE var/adjusted_flags = null ///Did we install a filtering cloth? var/has_filter = FALSE @@ -25,31 +24,6 @@ var/status = !(clothing_flags & VOICEBOX_DISABLED) to_chat(user, span_notice("You turn the voice box in [src] [status ? "on" : "off"].")) -/obj/item/clothing/mask/equipped(mob/M, slot) - . = ..() - if ((slot & ITEM_SLOT_MASK) && modifies_speech) - RegisterSignal(M, COMSIG_MOB_SAY, PROC_REF(handle_speech)) - else - UnregisterSignal(M, COMSIG_MOB_SAY) - -/obj/item/clothing/mask/dropped(mob/M) - . = ..() - UnregisterSignal(M, COMSIG_MOB_SAY) - -/obj/item/clothing/mask/vv_edit_var(vname, vval) - if(vname == NAMEOF(src, modifies_speech) && ismob(loc)) - var/mob/M = loc - if(M.get_item_by_slot(ITEM_SLOT_MASK) == src) - if(vval) - if(!modifies_speech) - RegisterSignal(M, COMSIG_MOB_SAY, PROC_REF(handle_speech)) - else if(modifies_speech) - UnregisterSignal(M, COMSIG_MOB_SAY) - return ..() - -/obj/item/clothing/mask/proc/handle_speech() - SIGNAL_HANDLER - /obj/item/clothing/mask/worn_overlays(mutable_appearance/standing, isinhands = FALSE) . = ..() if(isinhands) diff --git a/code/modules/clothing/masks/animal_masks.dm b/code/modules/clothing/masks/animal_masks.dm index 5df5c6738d8..05e5888168e 100644 --- a/code/modules/clothing/masks/animal_masks.dm +++ b/code/modules/clothing/masks/animal_masks.dm @@ -16,7 +16,7 @@ GLOBAL_LIST_INIT(cursed_animal_masks, list( /obj/item/clothing/mask/animal w_class = WEIGHT_CLASS_SMALL clothing_flags = VOICEBOX_TOGGLABLE - modifies_speech = TRUE + var/modifies_speech = TRUE flags_cover = MASKCOVERSMOUTH var/animal_type ///what kind of animal the masks represents. used for automatic name and description generation. @@ -32,6 +32,17 @@ GLOBAL_LIST_INIT(cursed_animal_masks, list( if(cursed) make_cursed() +/obj/item/clothing/mask/animal/equipped(mob/M, slot) + . = ..() + if ((slot & ITEM_SLOT_MASK) && modifies_speech) + RegisterSignal(M, COMSIG_MOB_SAY, PROC_REF(handle_speech)) + else + UnregisterSignal(M, COMSIG_MOB_SAY) + +/obj/item/clothing/mask/animal/dropped(mob/M) + . = ..() + UnregisterSignal(M, COMSIG_MOB_SAY) + /obj/item/clothing/mask/animal/vv_edit_var(vname, vval) if(vname == NAMEOF(src, cursed)) if(vval) @@ -39,6 +50,14 @@ GLOBAL_LIST_INIT(cursed_animal_masks, list( make_cursed() else if(cursed) clear_curse() + if(vname == NAMEOF(src, modifies_speech) && ismob(loc)) + var/mob/M = loc + if(M.get_item_by_slot(ITEM_SLOT_MASK) == src) + if(vval) + if(!modifies_speech) + RegisterSignal(M, COMSIG_MOB_SAY, PROC_REF(handle_speech)) + else if(modifies_speech) + UnregisterSignal(M, COMSIG_MOB_SAY) return ..() /obj/item/clothing/mask/animal/examine(mob/user) @@ -90,7 +109,9 @@ GLOBAL_LIST_INIT(cursed_animal_masks, list( UnregisterSignal(M, COMSIG_MOB_SAY) M.update_worn_mask() -/obj/item/clothing/mask/animal/handle_speech(datum/source, list/speech_args) +/obj/item/clothing/mask/animal/proc/handle_speech(datum/source, list/speech_args) + SIGNAL_HANDLER + if(clothing_flags & VOICEBOX_DISABLED) return if(!modifies_speech || !LAZYLEN(animal_sounds)) diff --git a/code/modules/clothing/masks/boxing.dm b/code/modules/clothing/masks/boxing.dm index 468b1272f86..9ac45c42d99 100644 --- a/code/modules/clothing/masks/boxing.dm +++ b/code/modules/clothing/masks/boxing.dm @@ -34,31 +34,10 @@ inhand_icon_state = null flags_inv = HIDEFACE|HIDEHAIR|HIDEFACIALHAIR|HIDESNOUT w_class = WEIGHT_CLASS_SMALL - modifies_speech = TRUE -/obj/item/clothing/mask/luchador/handle_speech(datum/source, list/speech_args) - var/message = speech_args[SPEECH_MESSAGE] - if(message[1] != "*") - message = replacetext(message, "captain", "CAPITÁN") - message = replacetext(message, "station", "ESTACIÓN") - message = replacetext(message, "sir", "SEÑOR") - message = replacetext(message, "the ", "el ") - message = replacetext(message, "my ", "mi ") - message = replacetext(message, "is ", "es ") - message = replacetext(message, "it's", "es") - message = replacetext(message, "friend", "amigo") - message = replacetext(message, "buddy", "amigo") - message = replacetext(message, "hello", "hola") - message = replacetext(message, " hot", " caliente") - message = replacetext(message, " very ", " muy ") - message = replacetext(message, "sword", "espada") - message = replacetext(message, "library", "biblioteca") - message = replacetext(message, "traitor", "traidor") - message = replacetext(message, "wizard", "mago") - message = uppertext(message) //Things end up looking better this way (no mixed cases), and it fits the macho wrestler image. - if(prob(25)) - message += " OLE!" - speech_args[SPEECH_MESSAGE] = message +/obj/item/clothing/head/frenchberet/Initialize(mapload) + . = ..() + AddComponent(/datum/component/speechmod, replacements = strings("luchador_replacement.json", "luchador"), end_string = " OLE!", end_string_chance = 25, uppercase = TRUE, slots = ITEM_SLOT_MASK) /obj/item/clothing/mask/luchador/tecnicos name = "Tecnicos Mask" diff --git a/code/modules/clothing/masks/gondola.dm b/code/modules/clothing/masks/gondola.dm index 7a8283293de..bfaae3cb3f3 100644 --- a/code/modules/clothing/masks/gondola.dm +++ b/code/modules/clothing/masks/gondola.dm @@ -5,18 +5,7 @@ inhand_icon_state = null flags_inv = HIDEFACE|HIDEHAIR|HIDEFACIALHAIR|HIDESNOUT w_class = WEIGHT_CLASS_SMALL - modifies_speech = TRUE -/obj/item/clothing/mask/gondola/handle_speech(datum/source, list/speech_args) - var/message = speech_args[SPEECH_MESSAGE] - if(message[1] != "*") - message = " [message]" - var/list/spurdo_words = strings("spurdo_replacement.json", "spurdo") - for(var/key in spurdo_words) - var/value = spurdo_words[key] - if(islist(value)) - value = pick(value) - message = replacetextEx(message,regex(uppertext(key),"g"), "[uppertext(value)]") - message = replacetextEx(message,regex(capitalize(key),"g"), "[capitalize(value)]") - message = replacetextEx(message,regex(key,"g"), "[value]") - speech_args[SPEECH_MESSAGE] = trim(message) +/obj/item/clothing/mask/gondola/Initialize(mapload) + . = ..() + AddComponent(/datum/component/speechmod, replacements = strings("spurdo_replacement.json", "spurdo"), slots = ITEM_SLOT_MASK) diff --git a/code/modules/clothing/masks/moustache.dm b/code/modules/clothing/masks/moustache.dm index aaf59be51e4..5b71e7a4260 100644 --- a/code/modules/clothing/masks/moustache.dm +++ b/code/modules/clothing/masks/moustache.dm @@ -10,23 +10,7 @@ /obj/item/clothing/mask/fakemoustache/italian name = "italian moustache" desc = "Made from authentic Italian moustache hairs. Gives the wearer an irresistable urge to gesticulate wildly." - modifies_speech = TRUE -/obj/item/clothing/mask/fakemoustache/italian/handle_speech(datum/source, list/speech_args) - var/message = speech_args[SPEECH_MESSAGE] - if(message[1] != "*") - message = " [message]" - var/list/italian_words = strings("italian_replacement.json", "italian") - - for(var/key in italian_words) - var/value = italian_words[key] - if(islist(value)) - value = pick(value) - - message = replacetextEx(message, " [uppertext(key)]", " [uppertext(value)]") - message = replacetextEx(message, " [capitalize(key)]", " [capitalize(value)]") - message = replacetextEx(message, " [key]", " [value]") - - if(prob(3)) - message += pick(" Ravioli, ravioli, give me the formuoli!"," Mamma-mia!"," Mamma-mia! That's a spicy meat-ball!", " La la la la la funiculi funicula!") - speech_args[SPEECH_MESSAGE] = trim(message) +/obj/item/clothing/mask/fakemoustache/italian/Initialize(mapload) + . = ..() + AddComponent(/datum/component/speechmod, replacements = strings("italian_replacement.json", "italian"), end_string = list(" Ravioli, ravioli, give me the formuoli!"," Mamma-mia!"," Mamma-mia! That's a spicy meat-ball!", " La la la la la funiculi funicula!"), end_string_chance = 3, slots = ITEM_SLOT_MASK) diff --git a/code/modules/surgery/organs/internal/tongue/_tongue.dm b/code/modules/surgery/organs/internal/tongue/_tongue.dm index a47639fe0e6..784f9d9c82f 100644 --- a/code/modules/surgery/organs/internal/tongue/_tongue.dm +++ b/code/modules/surgery/organs/internal/tongue/_tongue.dm @@ -187,38 +187,37 @@ liked_foodtypes = GORE | MEAT | SEAFOOD | NUTS | BUGS disliked_foodtypes = GRAIN | DAIRY | CLOTH | GROSS voice_filter = @{"[0:a] asplit [out0][out2]; [out0] asetrate=%SAMPLE_RATE%*0.9,aresample=%SAMPLE_RATE%,atempo=1/0.9,aformat=channel_layouts=mono,volume=0.2 [p0]; [out2] asetrate=%SAMPLE_RATE%*1.1,aresample=%SAMPLE_RATE%,atempo=1/1.1,aformat=channel_layouts=mono,volume=0.2[p2]; [p0][0][p2] amix=inputs=3"} + var/static/list/speech_replacements = list( + new /regex("s+", "g") = "sss", + new /regex("S+", "g") = "SSS", + new /regex(@"(\w)x", "g") = "$1kss", + //new /regex(@"(\w)X", "g") = "$1KSSS", // SKYRAT EDIT REMOVAL + new /regex(@"\bx([\-|r|R]|\b)", "g") = "ecks$1", + new /regex(@"\bX([\-|r|R]|\b)", "g") = "ECKS$1", + ) + // SKYRAT EDIT ADDITION START - Russian version + var/static/list/russian_speech_replacements = list( + new /regex("s+", "g") = "sss", + new /regex("S+", "g") = "SSS", + new /regex(@"(\w)x", "g") = "$1kss", + new /regex(@"\bx([\-|r|R]|\b)", "g") = "ecks$1", + new /regex(@"\bX([\-|r|R]|\b)", "g") = "ECKS$1", + new /regex(@"(\w)x", "g") = "$1kss", + new /regex(@"\bx([\-|r|R]|\b)", "g") = "ecks$1", + new /regex(@"\bX([\-|r|R]|\b)", "g") = "ECKS$1", + new /regex("с+", "g") = "ссс", + new /regex("С+", "g") = "ССС", + "з" = "с", + "З" = "С", + "ж" = "ш", + "Ж" = "Ш", + ) + // SKYRAT EDIT ADDITION END -/obj/item/organ/internal/tongue/lizard/modify_speech(datum/source, list/speech_args) - var/static/regex/lizard_hiss = new("s+", "g") - var/static/regex/lizard_hiSS = new("S+", "g") - var/static/regex/lizard_kss = new(@"(\w)x", "g") - /* // SKYRAT EDIT: REMOVAL - var/static/regex/lizard_kSS = new(@"(\w)X", "g") - */ - var/static/regex/lizard_ecks = new(@"\bx([\-|r|R]|\b)", "g") - var/static/regex/lizard_eckS = new(@"\bX([\-|r|R]|\b)", "g") - var/message = speech_args[SPEECH_MESSAGE] - if(message[1] != "*") - message = lizard_hiss.Replace(message, "sss") - message = lizard_hiSS.Replace(message, "SSS") - message = lizard_kss.Replace(message, "$1kss") - /* // SKYRAT EDIT: REMOVAL - message = lizard_kSS.Replace(message, "$1KSS") - */ - message = lizard_ecks.Replace(message, "ecks$1") - message = lizard_eckS.Replace(message, "ECKS$1") - //SKYRAT EDIT START: Adding russian version to autohiss - if(CONFIG_GET(flag/russian_text_formation)) - var/static/regex/lizard_hiss_ru = new("с+", "g") - var/static/regex/lizard_hiSS_ru = new("С+", "g") - message = replacetext(message, "з", "с") - message = replacetext(message, "З", "С") - message = replacetext(message, "ж", "ш") - message = replacetext(message, "Ж", "Ш") - message = lizard_hiss_ru.Replace(message, "ссс") - message = lizard_hiSS_ru.Replace(message, "ССС") - //SKYRAT EDIT END: Adding russian version to autohiss - speech_args[SPEECH_MESSAGE] = message + +/obj/item/organ/internal/tongue/lizard/New(class, timer, datum/mutation/human/copymut) + . = ..() + AddComponent(/datum/component/speechmod, replacements = CONFIG_GET(flag/russian_text_formation) ? russian_speech_replacements : speech_replacements) // SKYRAT EDIT CHANGE - ORIGINAL: AddComponent(/datum/component/speechmod, replacements = speech_replacements) /obj/item/organ/internal/tongue/lizard/silver name = "silver tongue" diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/ballgag.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/ballgag.dm index ea1e10de656..432c6442259 100644 --- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/ballgag.dm +++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/ballgag.dm @@ -16,7 +16,6 @@ greyscale_config_inhand_right = /datum/greyscale_config/ballgag/right_hand greyscale_colors = "#AD66BE" w_class = WEIGHT_CLASS_SMALL - modifies_speech = TRUE flags_cover = MASKCOVERSMOUTH /// Does this gag choke the wearer? @@ -51,14 +50,27 @@ var/size_list_position = 1 /// How big the gag is currently var/gag_size = "small" + var/modifies_speech = TRUE // To update the sprite /obj/item/clothing/mask/ballgag/Initialize(mapload) . = ..() AddElement(/datum/element/update_icon_updates_onmob) +/obj/item/clothing/mask/ballgag/equipped(mob/equipper, slot) + . = ..() + if ((slot & ITEM_SLOT_MASK) && modifies_speech) + RegisterSignal(equipper, COMSIG_MOB_SAY, PROC_REF(handle_speech)) + else + UnregisterSignal(equipper, COMSIG_MOB_SAY) + +/obj/item/clothing/mask/ballgag/dropped(mob/dropper) + . = ..() + UnregisterSignal(dropper, COMSIG_MOB_SAY) + // Changes speech while worn -/obj/item/clothing/mask/ballgag/handle_speech(datum/source, list/speech_args) +/obj/item/clothing/mask/ballgag/proc/handle_speech(datum/source, list/speech_args) + SIGNAL_HANDLER if(!LAZYLEN(moans)) return speech_args[SPEECH_MESSAGE] = pick((prob(moans_alt_probability) && LAZYLEN(moans_alt)) ? moans_alt : moans) diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/bdsm_mask.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/bdsm_mask.dm index 32e3f8c2040..8f05c532768 100644 --- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/bdsm_mask.dm +++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/bdsm_mask.dm @@ -15,6 +15,8 @@ icon_state = "mask_pink_off" base_icon_state = "mask" slot_flags = ITEM_SLOT_MASK + w_class = WEIGHT_CLASS_SMALL + flags_cover = MASKCOVERSMOUTH var/mask_on = FALSE var/current_mask_color = "pink" var/breath_status = TRUE @@ -35,9 +37,7 @@ var/temp_check = TRUE //Used to check if user unconsious to prevent choking him until he wakes up /// Does the gasmask impede the user's ability to talk? var/speech_disabled - w_class = WEIGHT_CLASS_SMALL - modifies_speech = TRUE - flags_cover = MASKCOVERSMOUTH + var/modifies_speech = TRUE /obj/item/clothing/mask/gas/bdsm_mask/Initialize(mapload) . = ..() @@ -55,7 +55,20 @@ button.button_icon = 'modular_skyrat/modules/modular_items/lewd_items/icons/obj/lewd_items/lewd_icons.dmi' update_icon() -/obj/item/clothing/mask/gas/bdsm_mask/handle_speech(datum/source, list/speech_args) +/obj/item/clothing/mask/gas/bdsm_mask/equipped(mob/equipper, slot) + . = ..() + if ((slot & ITEM_SLOT_MASK) && modifies_speech) + RegisterSignal(equipper, COMSIG_MOB_SAY, PROC_REF(handle_speech)) + else + UnregisterSignal(equipper, COMSIG_MOB_SAY) + +/obj/item/clothing/mask/gas/bdsm_mask/dropped(mob/dropper) + . = ..() + UnregisterSignal(dropper, COMSIG_MOB_SAY) + +/obj/item/clothing/mask/gas/bdsm_mask/proc/handle_speech(datum/source, list/speech_args) + SIGNAL_HANDLER + if(speech_disabled) return diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/leather_whip.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/leather_whip.dm index 11b86eabe3b..475936eb6ff 100644 --- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/leather_whip.dm +++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/leather_whip.dm @@ -14,8 +14,8 @@ hitsound = 'sound/weapons/whip.ogg' clothing_flags = INEDIBLE_CLOTHING //When taking that thing in mouth - modifies_speech = TRUE flags_cover = MASKCOVERSMOUTH + var/modifies_speech = TRUE /// If the color of the toy has been changed before var/color_changed = FALSE /// If the form (or size) of the toy has been changed before @@ -50,8 +50,20 @@ if(!isinhands) . += whip_overlay +/obj/item/clothing/mask/leatherwhip/equipped(mob/equipper, slot) + . = ..() + if ((slot & ITEM_SLOT_MASK) && modifies_speech) + RegisterSignal(equipper, COMSIG_MOB_SAY, PROC_REF(handle_speech)) + else + UnregisterSignal(equipper, COMSIG_MOB_SAY) + +/obj/item/clothing/mask/leatherwhip/dropped(mob/dropper) + . = ..() + UnregisterSignal(dropper, COMSIG_MOB_SAY) + // Speech handler for moansing when talking -/obj/item/clothing/mask/leatherwhip/handle_speech(datum/source, list/speech_args) +/obj/item/clothing/mask/leatherwhip/proc/handle_speech(datum/source, list/speech_args) + SIGNAL_HANDLER speech_args[SPEECH_MESSAGE] = pick((prob(moans_alt_probability) && LAZYLEN(moans_alt)) ? moans_alt : moans) play_lewd_sound(loc, pick('modular_skyrat/modules/modular_items/lewd_items/sounds/under_moan_f1.ogg', 'modular_skyrat/modules/modular_items/lewd_items/sounds/under_moan_f2.ogg', diff --git a/strings/elvis_replacement.json b/strings/elvis_replacement.json new file mode 100644 index 00000000000..fb7c3f4d02d --- /dev/null +++ b/strings/elvis_replacement.json @@ -0,0 +1,13 @@ +{ + "elvis": { + "i'm not ": "I ain't ", + " girl ": [" honey ", " baby ", " baby doll "], + " man ": [" son ", " buddy ", " brother ", " pal ", " friendo "], + " out of ": " outta ", + " thank you ": " thank you, thank you very much ", + " thanks ": " thank you, thank you very much ", + " what are you": " whatcha ", + " yes": [" sure ", " yea "], + " muh valids ": " my kicks " + } +} diff --git a/strings/luchador_replacement.json b/strings/luchador_replacement.json new file mode 100644 index 00000000000..71b6122adba --- /dev/null +++ b/strings/luchador_replacement.json @@ -0,0 +1,20 @@ +{ + "luchador": { + "captain": "CAPITÁN", + "station": "ESTACIÓN", + "sir": "SEÑOR", + "the ": "el ", + "my ": "mi ", + "is ": "es ", + "it's": "es", + "friend": "amigo", + "buddy": "amigo", + "hello": "hola", + " hot": " caliente", + " very ": " muy ", + "sword": "espada", + "library": "biblioteca", + "traitor": "traidor", + "wizard": "mago" + } +} diff --git a/tgstation.dme b/tgstation.dme index 7ab2b76e54b..5e1e9774cd7 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -1302,6 +1302,7 @@ #include "code\datums\components\soulstoned.dm" #include "code\datums\components\sound_player.dm" #include "code\datums\components\spawner.dm" +#include "code\datums\components\speechmod.dm" #include "code\datums\components\spill.dm" #include "code\datums\components\spin2win.dm" #include "code\datums\components\spinny.dm"