From 01d45ca2e182e71d1ea5bf82328d82b40d314094 Mon Sep 17 00:00:00 2001 From: Geeves Date: Thu, 30 Jul 2020 19:49:09 +0200 Subject: [PATCH] Silicon Accents (#9429) Stationbounds now have accents, starting off with Text-to-Speech, and can choose to mimic any accent. The bots that robotics can produce now also have TTS accents. IPCs can choose to use the TTS accent if they wish. --- aurorastation.dme | 2 ++ code/modules/background/accent/silicon.dm | 4 +++ code/modules/background/defines.dm | 4 ++- code/modules/mob/hear_say.dm | 5 +-- code/modules/mob/living/bot/bot.dm | 3 ++ code/modules/mob/living/carbon/human/human.dm | 31 ++++++++---------- .../mob/living/carbon/human/human_defines.dm | 1 - .../carbon/human/species/station/ipc/ipc.dm | 2 +- .../species/station/ipc/ipc_subspecies.dm | 6 ++-- code/modules/mob/living/living.dm | 2 +- code/modules/mob/living/silicon/computer.dm | 8 +++-- code/modules/mob/living/silicon/pai/pai.dm | 1 + code/modules/mob/living/silicon/silicon.dm | 4 ++- .../mob/living/silicon/silicon_procs.dm | 10 ++++++ code/modules/mob/mob_defines.dm | 1 + code/modules/mob/mob_helpers.dm | 10 +++++- html/changelogs/geeves-silicon_accents.yml | 8 +++++ icons/accent_tags.dmi | Bin 7054 -> 7161 bytes 18 files changed, 70 insertions(+), 32 deletions(-) create mode 100644 code/modules/background/accent/silicon.dm create mode 100644 code/modules/mob/living/silicon/silicon_procs.dm create mode 100644 html/changelogs/geeves-silicon_accents.yml diff --git a/aurorastation.dme b/aurorastation.dme index 7f5e71b678d..c052a7de593 100644 --- a/aurorastation.dme +++ b/aurorastation.dme @@ -1243,6 +1243,7 @@ #include "code\modules\background\accent\accent.dm" #include "code\modules\background\accent\diona.dm" #include "code\modules\background\accent\human.dm" +#include "code\modules\background\accent\silicon.dm" #include "code\modules\background\accent\skrell.dm" #include "code\modules\background\accent\tajara.dm" #include "code\modules\background\accent\unathi.dm" @@ -1953,6 +1954,7 @@ #include "code\modules\mob\living\silicon\login.dm" #include "code\modules\mob\living\silicon\say.dm" #include "code\modules\mob\living\silicon\silicon.dm" +#include "code\modules\mob\living\silicon\silicon_procs.dm" #include "code\modules\mob\living\silicon\ai\ai.dm" #include "code\modules\mob\living\silicon\ai\ai_movement.dm" #include "code\modules\mob\living\silicon\ai\death.dm" diff --git a/code/modules/background/accent/silicon.dm b/code/modules/background/accent/silicon.dm new file mode 100644 index 00000000000..862f6069eef --- /dev/null +++ b/code/modules/background/accent/silicon.dm @@ -0,0 +1,4 @@ +/datum/accent/silicon + name = ACCENT_SILICON + description = "A barebones text-to-speech accent. This is usually used to de-humanize or to cut speech synthesizer costs in silicon based machines." + tag_icon = "tts" \ No newline at end of file diff --git a/code/modules/background/defines.dm b/code/modules/background/defines.dm index 6deff7a6864..d28b547ae31 100644 --- a/code/modules/background/defines.dm +++ b/code/modules/background/defines.dm @@ -88,4 +88,6 @@ #define ACCENT_SKRELL "Standard Nral'Malic" -#define ACCENT_DIONA "Diona" \ No newline at end of file +#define ACCENT_DIONA "Diona" + +#define ACCENT_SILICON "Text-to-Speech" \ No newline at end of file diff --git a/code/modules/mob/hear_say.dm b/code/modules/mob/hear_say.dm index ce09724d021..84193f51c5a 100644 --- a/code/modules/mob/hear_say.dm +++ b/code/modules/mob/hear_say.dm @@ -41,15 +41,12 @@ else message = stars(message) - var/accent_icon - + var/accent_icon = speaker.get_accent_icon(language) var/speaker_name = speaker.name if(ishuman(speaker)) var/mob/living/carbon/human/H = speaker speaker_name = H.GetVoice() - accent_icon = H.get_accent_icon(language) - if(italics) message = "[message]" diff --git a/code/modules/mob/living/bot/bot.dm b/code/modules/mob/living/bot/bot.dm index 54c7c6829ca..50948b5408d 100644 --- a/code/modules/mob/living/bot/bot.dm +++ b/code/modules/mob/living/bot/bot.dm @@ -1,5 +1,6 @@ /mob/living/bot name = "Bot" + accent = ACCENT_SILICON health = 20 maxHealth = 20 icon = 'icons/obj/aibots.dmi' @@ -28,6 +29,8 @@ /mob/living/bot/Initialize() . = ..() update_icon() + add_language(LANGUAGE_TCB) + set_default_language(LANGUAGE_TCB) botcard = new /obj/item/card/id(src) botcard.access = botcard_access.Copy() diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 28243d9a149..5d5ccbc2c0b 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -2014,27 +2014,24 @@ randmutg(src) // Applies good mutation domutcheck(src,null,MUTCHK_FORCED) -/mob/living/carbon/human/proc/get_accent_icon(var/datum/language/speaking = null) - if(accent && speaking && speaking.allow_accents) - var/used_accent = accent //starts with the mob's default accent +/mob/living/carbon/human/get_accent_icon(var/datum/language/speaking = null) + var/used_accent = accent //starts with the mob's default accent - if(mind?.changeling) - used_accent = mind.changeling.mimiced_accent + if(mind?.changeling) + used_accent = mind.changeling.mimiced_accent - if(istype(back,/obj/item/rig)) //checks for the rig voice changer module - var/obj/item/rig/rig = back - if(rig.speech && rig.speech.voice_holder && rig.speech.voice_holder.active && rig.speech.voice_holder.current_accent) - used_accent = rig.speech.voice_holder.current_accent + if(istype(back,/obj/item/rig)) //checks for the rig voice changer module + var/obj/item/rig/rig = back + if(rig.speech && rig.speech.voice_holder && rig.speech.voice_holder.active && rig.speech.voice_holder.current_accent) + used_accent = rig.speech.voice_holder.current_accent - for(var/obj/item/gear in list(wear_mask,wear_suit,head)) //checks for voice changers masks now - if(gear) - var/obj/item/voice_changer/changer = locate() in gear - if(changer && changer.active && changer.current_accent) - used_accent = changer.current_accent + for(var/obj/item/gear in list(wear_mask,wear_suit,head)) //checks for voice changers masks now + if(gear) + var/obj/item/voice_changer/changer = locate() in gear + if(changer && changer.active && changer.current_accent) + used_accent = changer.current_accent - var/datum/accent/a = SSrecords.accents[used_accent] - var/final_icon = a.tag_icon - return "" + return ..(speaking, used_accent) /mob/living/carbon/human/proc/generate_valid_accent() var/list/valid_accents = new() diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm index 8bfd76fae2c..a4744e0ed9e 100644 --- a/code/modules/mob/living/carbon/human/human_defines.dm +++ b/code/modules/mob/living/carbon/human/human_defines.dm @@ -44,7 +44,6 @@ var/citizenship = "" var/employer_faction = "" var/religion = "" - var/accent = "" //Equipment slots var/obj/item/wear_suit = null diff --git a/code/modules/mob/living/carbon/human/species/station/ipc/ipc.dm b/code/modules/mob/living/carbon/human/species/station/ipc/ipc.dm index 29d6d8a659a..f448dcc3cdc 100644 --- a/code/modules/mob/living/carbon/human/species/station/ipc/ipc.dm +++ b/code/modules/mob/living/carbon/human/species/station/ipc/ipc.dm @@ -117,7 +117,7 @@ bodyfall_sound = "bodyfall_machine" allowed_accents = list(ACCENT_CETI, ACCENT_GIBSON, ACCENT_SOL, ACCENT_COC, ACCENT_ERIDANI, ACCENT_ERIDANIDREG, ACCENT_ELYRA, ACCENT_KONYAN, ACCENT_JUPITER, ACCENT_MARTIAN, ACCENT_LUNA, - ACCENT_HIMEO, ACCENT_VENUS, ACCENT_VENUSJIN, ACCENT_PHONG) + ACCENT_HIMEO, ACCENT_VENUS, ACCENT_VENUSJIN, ACCENT_PHONG, ACCENT_SILICON) // Special snowflake machine vars. var/sprint_temperature_factor = 1.15 diff --git a/code/modules/mob/living/carbon/human/species/station/ipc/ipc_subspecies.dm b/code/modules/mob/living/carbon/human/species/station/ipc/ipc_subspecies.dm index b95c103abf9..eac5a6e2998 100644 --- a/code/modules/mob/living/carbon/human/species/station/ipc/ipc_subspecies.dm +++ b/code/modules/mob/living/carbon/human/species/station/ipc/ipc_subspecies.dm @@ -74,7 +74,7 @@ bodyfall_sound = "bodyfall" allowed_accents = list(ACCENT_CETI, ACCENT_GIBSON, ACCENT_SOL, ACCENT_COC, ACCENT_ERIDANI, ACCENT_ERIDANIDREG, ACCENT_ELYRA, ACCENT_KONYAN, ACCENT_JUPITER, ACCENT_MARTIAN, ACCENT_LUNA, - ACCENT_HIMEO, ACCENT_VENUS, ACCENT_VENUSJIN, ACCENT_PHONG, ACCENT_SILVERSUN) + ACCENT_HIMEO, ACCENT_VENUS, ACCENT_VENUSJIN, ACCENT_PHONG, ACCENT_SILVERSUN, ACCENT_SILICON) /datum/species/machine/shell/get_light_color() return @@ -495,7 +495,7 @@ ) allowed_accents = list(ACCENT_CETI, ACCENT_GIBSON, ACCENT_SOL, ACCENT_COC, ACCENT_ERIDANI, ACCENT_ERIDANIDREG, ACCENT_ELYRA, ACCENT_KONYAN, ACCENT_JUPITER, ACCENT_MARTIAN, ACCENT_LUNA, - ACCENT_HIMEO, ACCENT_VENUS, ACCENT_VENUSJIN, ACCENT_PHONG, ACCENT_SILVERSUN) + ACCENT_HIMEO, ACCENT_VENUS, ACCENT_VENUSJIN, ACCENT_PHONG, ACCENT_SILVERSUN, ACCENT_SILICON) /datum/species/machine/bishop/get_light_color(mob/living/carbon/human/H) if (istype(H)) @@ -553,4 +553,4 @@ /datum/species/machine/unbranded/get_light_color(mob/living/carbon/human/H) if (istype(H)) - return rgb(H.r_eyes, H.g_eyes, H.b_eyes) + return rgb(H.r_eyes, H.g_eyes, H.b_eyes) \ No newline at end of file diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 1e88a377e36..c0b02f35225 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -957,4 +957,4 @@ default behaviour is: return ..() /mob/living/proc/needs_wheelchair() - return FALSE + return FALSE \ No newline at end of file diff --git a/code/modules/mob/living/silicon/computer.dm b/code/modules/mob/living/silicon/computer.dm index 8a567b1bf47..83159887aef 100644 --- a/code/modules/mob/living/silicon/computer.dm +++ b/code/modules/mob/living/silicon/computer.dm @@ -6,12 +6,16 @@ /mob/living/silicon/proc/subsystem_alarm_monitor, /mob/living/silicon/proc/subsystem_law_manager, /mob/living/silicon/ai/proc/subsystem_ntnet_monitor, - /mob/living/silicon/proc/computer_interact + /mob/living/silicon/proc/computer_interact, + /mob/living/silicon/proc/silicon_mimic_accent ) /mob/living/silicon/robot/syndicate register_alarms = 0 - silicon_subsystems = list(/mob/living/silicon/proc/subsystem_law_manager) + silicon_subsystems = list( + /mob/living/silicon/proc/subsystem_law_manager, + /mob/living/silicon/proc/silicon_mimic_accent + ) /mob/living/silicon/ai/Destroy() QDEL_NULL(ntnet_monitor) diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm index b2c293f222c..2a2bb5ce06f 100644 --- a/code/modules/mob/living/silicon/pai/pai.dm +++ b/code/modules/mob/living/silicon/pai/pai.dm @@ -180,6 +180,7 @@ verbs += /mob/living/silicon/pai/proc/choose_chassis verbs += /mob/living/silicon/pai/proc/choose_verbs verbs += /mob/living/silicon/proc/computer_interact + verbs += /mob/living/silicon/proc/silicon_mimic_accent //PDA pda = new(src) diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm index bf5336a9a3d..4461e944886 100644 --- a/code/modules/mob/living/silicon/silicon.dm +++ b/code/modules/mob/living/silicon/silicon.dm @@ -6,6 +6,7 @@ // Speaking gender = NEUTER voice_name = "Synthesized Voice" + accent = ACCENT_SILICON var/list/speech_synthesizer_langs = list() //which languages can be vocalized by the speech synthesizer var/speak_statement = "states" var/speak_exclamation = "declares" @@ -42,7 +43,8 @@ var/list/silicon_subsystems = list( /mob/living/silicon/proc/subsystem_alarm_monitor, /mob/living/silicon/proc/subsystem_law_manager, - /mob/living/silicon/proc/computer_interact + /mob/living/silicon/proc/computer_interact, + /mob/living/silicon/proc/silicon_mimic_accent ) // Utility diff --git a/code/modules/mob/living/silicon/silicon_procs.dm b/code/modules/mob/living/silicon/silicon_procs.dm new file mode 100644 index 00000000000..2ab67bfea24 --- /dev/null +++ b/code/modules/mob/living/silicon/silicon_procs.dm @@ -0,0 +1,10 @@ +/mob/living/silicon/proc/silicon_mimic_accent() + set name = "Mimic Accent" + set category = "Subsystems" + + var/chosen_accent = input(src, "Choose an accent to mimic.", "Accent Mimicry") as null|anything in SSrecords.accents + if(!chosen_accent) + return + + accent = chosen_accent + to_chat(src, SPAN_NOTICE("You have set your synthesizer to mimic the [chosen_accent] accent.")) \ No newline at end of file diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index 97538a1ee11..aa698f9b177 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -171,6 +171,7 @@ //see: setup.dm for list of mutations var/voice_name = "unidentifiable voice" + var/accent var/faction = "neutral" //Used for checking whether hostile simple animals will attack you, possibly more stuff later var/captured = 0 //Functionally, should give the same effect as being buckled into a chair when true. diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index 6b8a2bcd866..f9e3ee83bbc 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -1224,4 +1224,12 @@ proc/is_blind(A) W.add_fingerprint(src) /mob/proc/set_intent(var/set_intent) - a_intent = set_intent \ No newline at end of file + a_intent = set_intent + +/mob/proc/get_accent_icon(var/datum/language/speaking = null, var/force_accent) + SHOULD_CALL_PARENT(TRUE) + var/used_accent = force_accent ? force_accent : accent + if(used_accent && speaking?.allow_accents) + var/datum/accent/a = SSrecords.accents[used_accent] + var/final_icon = a.tag_icon + return "" \ No newline at end of file diff --git a/html/changelogs/geeves-silicon_accents.yml b/html/changelogs/geeves-silicon_accents.yml new file mode 100644 index 00000000000..6469a3322c2 --- /dev/null +++ b/html/changelogs/geeves-silicon_accents.yml @@ -0,0 +1,8 @@ +author: Geeves + +delete-after: True + +changes: + - rscadd: "Stationbounds now have accents, starting off with Text-to-Speech, and can choose to mimic any accent." + - rscadd: "The bots that robotics can produce now also have TTS accents." + - rscadd: "IPCs can choose to use the TTS accent if they wish." \ No newline at end of file diff --git a/icons/accent_tags.dmi b/icons/accent_tags.dmi index f2849b1dd01a2c9f19652ec3fe041f8095bbbb5b..ff9e8e26501021d079c38ce190ae23ae43d81d59 100644 GIT binary patch literal 7161 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 literal 7054 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