diff --git a/code/datums/antagonists/datum_cult.dm b/code/datums/antagonists/datum_cult.dm index 9016331440..346c88e6b1 100644 --- a/code/datums/antagonists/datum_cult.dm +++ b/code/datums/antagonists/datum_cult.dm @@ -76,6 +76,7 @@ if(mob_override) current = mob_override current.faction |= "cult" + current.grant_language(/datum/language/narsie) current.verbs += /mob/living/proc/cult_help if(!GLOB.cult_mastered) current.verbs += /mob/living/proc/cult_master @@ -88,6 +89,7 @@ if(mob_override) current = mob_override current.faction -= "cult" + current.remove_language(/datum/language/narsie) current.verbs -= /mob/living/proc/cult_help communion.Remove(current) owner.current.verbs -= /mob/living/proc/cult_master diff --git a/code/game/gamemodes/cult/runes.dm b/code/game/gamemodes/cult/runes.dm index 4573b460da..fca7d1ac1c 100644 --- a/code/game/gamemodes/cult/runes.dm +++ b/code/game/gamemodes/cult/runes.dm @@ -136,7 +136,7 @@ structure_check() searches for nearby cultist structures required for the invoca if(invocation) for(var/M in invokers) var/mob/living/L = M - L.say(invocation) + L.say(invocation, language = /datum/language/common) do_invoke_glow() /obj/effect/rune/proc/do_invoke_glow() @@ -516,7 +516,7 @@ structure_check() searches for nearby cultist structures required for the invoca /obj/effect/rune/raise_dead cultist_name = "Raise Dead" cultist_desc = "requires the corpse of a cultist placed upon the rune. Provided there have been sufficient sacrifices, they will be revived." - invocation = null //Depends on the name of the user - see below + invocation = "Pasnar val'keriam usinar. Savrae ines amutan. Yam'toth remium il'tarat!" //Depends on the name of the user - see below icon_state = "1" color = "#C80000" var/static/revives_used = 0 @@ -556,9 +556,9 @@ structure_check() searches for nearby cultist structures required for the invoca return rune_in_use = 1 if(user.name == "Herbert West") - user.say("To life, to life, I bring them!") + invocation = "To life, to life, I bring them!" else - user.say("Pasnar val'keriam usinar. Savrae ines amutan. Yam'toth remium il'tarat!") + invocation = initial(invocation) ..() revives_used++ mob_to_revive.revive(1, 1) //This does remove disabilities and such, but the rune might actually see some use because of it! diff --git a/code/game/gamemodes/cult/runes.dm.rej b/code/game/gamemodes/cult/runes.dm.rej new file mode 100644 index 0000000000..cd7962db1e --- /dev/null +++ b/code/game/gamemodes/cult/runes.dm.rej @@ -0,0 +1,10 @@ +diff a/code/game/gamemodes/cult/runes.dm b/code/game/gamemodes/cult/runes.dm (rejected hunks) +@@ -516,7 +516,7 @@ structure_check() searches for nearby cultist structures required for the invoca + /obj/effect/rune/raise_dead + cultist_name = "Resurrect Cultist" + cultist_desc = "requires the corpse of a cultist placed upon the rune. Provided there have been sufficient sacrifices, they will be revived." +- invocation = null //Depends on the name of the user - see below ++ invocation = "Pasnar val'keriam usinar. Savrae ines amutan. Yam'toth remium il'tarat!" //Depends on the name of the user - see below + icon_state = "1" + color = "#C80000" + var/static/revives_used = 0 diff --git a/code/game/gamemodes/cult/talisman.dm b/code/game/gamemodes/cult/talisman.dm index 15b850eb33..027df31acd 100644 --- a/code/game/gamemodes/cult/talisman.dm +++ b/code/game/gamemodes/cult/talisman.dm @@ -28,7 +28,7 @@ . = successfuluse if(successfuluse) //if the calling whatever says we succeed, do the fancy stuff if(invocation) - user.whisper(invocation) + user.whisper(invocation, language = /datum/language/common) if(health_cost && iscarbon(user)) var/mob/living/carbon/C = user C.apply_damage(health_cost, BRUTE, pick("l_arm", "r_arm")) diff --git a/code/modules/language/language.dm b/code/modules/language/language.dm index efeabfe73d..5354532cfa 100644 --- a/code/modules/language/language.dm +++ b/code/modules/language/language.dm @@ -1,27 +1,27 @@ -#define SCRAMBLE_CACHE_LEN 20 - -/* - Datum based languages. Easily editable and modular. -*/ - -/datum/language - var/name = "an unknown language" // Fluff name of language if any. - var/desc = "A language." // Short description for 'Check Languages'. - var/speech_verb = "says" // 'says', 'hisses', 'farts'. - var/ask_verb = "asks" // Used when sentence ends in a ? - var/exclaim_verb = "exclaims" // Used when sentence ends in a ! - var/whisper_verb = "whispers" // Optional. When not specified speech_verb + quietly/softly is used instead. - var/list/signlang_verb = list("signs", "gestures") // list of emotes that might be displayed if this language has NONVERBAL or SIGNLANG flags +#define SCRAMBLE_CACHE_LEN 50 //maximum of 50 specific scrambled lines per language + +/* + Datum based languages. Easily editable and modular. +*/ + +/datum/language + var/name = "an unknown language" // Fluff name of language if any. + var/desc = "A language." // Short description for 'Check Languages'. + var/speech_verb = "says" // 'says', 'hisses', 'farts'. + var/ask_verb = "asks" // Used when sentence ends in a ? + var/exclaim_verb = "exclaims" // Used when sentence ends in a ! + var/whisper_verb = "whispers" // Optional. When not specified speech_verb + quietly/softly is used instead. + var/list/signlang_verb = list("signs", "gestures") // list of emotes that might be displayed if this language has NONVERBAL or SIGNLANG flags var/key // Character used to speak in language // If key is null, then the language isn't real or learnable. - var/flags // Various language flags. - var/list/syllables // Used when scrambling text for a non-speaker. - var/list/sentence_chance = 5 // Likelihood of making a new sentence after each syllable. - var/list/space_chance = 55 // Likelihood of getting a space in the random scramble string - var/list/spans = list() - var/static/list/scramble_cache = list() - var/default_priority = 0 // the language that an atom knows with the highest "default_priority" is selected by default. - + var/flags // Various language flags. + var/list/syllables // Used when scrambling text for a non-speaker. + var/list/sentence_chance = 5 // Likelihood of making a new sentence after each syllable. + var/list/space_chance = 55 // Likelihood of getting a space in the random scramble string + var/list/spans = list() + var/list/scramble_cache = list() + var/default_priority = 0 // the language that an atom knows with the highest "default_priority" is selected by default. + // if you are seeing someone speak popcorn language, then something is wrong. var/icon = 'icons/misc/language.dmi' var/icon_state = "popcorn" @@ -37,75 +37,75 @@ /datum/language/proc/get_icon() return "" -/datum/language/proc/get_random_name(gender, name_count=2, syllable_count=4, syllable_divisor=2) - if(!syllables || !syllables.len) - if(gender==FEMALE) - return capitalize(pick(GLOB.first_names_female)) + " " + capitalize(pick(GLOB.last_names)) - else - return capitalize(pick(GLOB.first_names_male)) + " " + capitalize(pick(GLOB.last_names)) - - var/full_name = "" - var/new_name = "" - - for(var/i in 0 to name_count) - new_name = "" - var/Y = rand(Floor(syllable_count/syllable_divisor), syllable_count) - for(var/x in Y to 0) - new_name += pick(syllables) - full_name += " [capitalize(lowertext(new_name))]" - - return "[trim(full_name)]" - -/datum/language/proc/scramble(input) - - if(!syllables || !syllables.len) - return stars(input) - - // If the input is cached already, move it to the end of the cache and return it - var/lookup = scramble_cache[input] - if(lookup) - scramble_cache -= input - scramble_cache[input] = lookup - return lookup - - var/input_size = length(input) - var/scrambled_text = "" - var/capitalize = TRUE - - while(length(scrambled_text) < input_size) - var/next = pick(syllables) - if(capitalize) - next = capitalize(next) - capitalize = FALSE - scrambled_text += next - var/chance = rand(100) - if(chance <= sentence_chance) - scrambled_text += ". " - capitalize = TRUE - else if(chance > sentence_chance && chance <= space_chance) - scrambled_text += " " - - scrambled_text = trim(scrambled_text) - var/ending = copytext(scrambled_text, length(scrambled_text)) - if(ending == ".") - scrambled_text = copytext(scrambled_text,1,length(scrambled_text)-1) - var/input_ending = copytext(input, input_size) - if(input_ending in list("!","?",".")) - scrambled_text += input_ending - - // Add it to cache, cutting old entries if the list is too long - scramble_cache[input] = scrambled_text - if(scramble_cache.len > SCRAMBLE_CACHE_LEN) - scramble_cache.Cut(1, scramble_cache.len-SCRAMBLE_CACHE_LEN-1) - - return scrambled_text - -/datum/language/proc/get_spoken_verb(msg_end) - switch(msg_end) - if("!") - return exclaim_verb - if("?") - return ask_verb - return speech_verb - -#undef SCRAMBLE_CACHE_LEN +/datum/language/proc/get_random_name(gender, name_count=2, syllable_count=4, syllable_divisor=2) + if(!syllables || !syllables.len) + if(gender==FEMALE) + return capitalize(pick(GLOB.first_names_female)) + " " + capitalize(pick(GLOB.last_names)) + else + return capitalize(pick(GLOB.first_names_male)) + " " + capitalize(pick(GLOB.last_names)) + + var/full_name = "" + var/new_name = "" + + for(var/i in 0 to name_count) + new_name = "" + var/Y = rand(Floor(syllable_count/syllable_divisor), syllable_count) + for(var/x in Y to 0) + new_name += pick(syllables) + full_name += " [capitalize(lowertext(new_name))]" + + return "[trim(full_name)]" + +/datum/language/proc/scramble(input) + + if(!syllables || !syllables.len) + return stars(input) + + // If the input is cached already, move it to the end of the cache and return it + var/lookup = scramble_cache[input] + if(lookup) + scramble_cache -= input + scramble_cache[input] = lookup + return lookup + + var/input_size = length(input) + var/scrambled_text = "" + var/capitalize = TRUE + + while(length(scrambled_text) < input_size) + var/next = pick(syllables) + if(capitalize) + next = capitalize(next) + capitalize = FALSE + scrambled_text += next + var/chance = rand(100) + if(chance <= sentence_chance) + scrambled_text += ". " + capitalize = TRUE + else if(chance > sentence_chance && chance <= space_chance) + scrambled_text += " " + + scrambled_text = trim(scrambled_text) + var/ending = copytext(scrambled_text, length(scrambled_text)) + if(ending == ".") + scrambled_text = copytext(scrambled_text,1,length(scrambled_text)-1) + var/input_ending = copytext(input, input_size) + if(input_ending in list("!","?",".")) + scrambled_text += input_ending + + // Add it to cache, cutting old entries if the list is too long + scramble_cache[input] = scrambled_text + if(scramble_cache.len > SCRAMBLE_CACHE_LEN) + scramble_cache.Cut(1, scramble_cache.len-SCRAMBLE_CACHE_LEN-1) + + return scrambled_text + +/datum/language/proc/get_spoken_verb(msg_end) + switch(msg_end) + if("!") + return exclaim_verb + if("?") + return ask_verb + return speech_verb + +#undef SCRAMBLE_CACHE_LEN diff --git a/code/modules/language/language.dm.rej b/code/modules/language/language.dm.rej new file mode 100644 index 0000000000..c7f2ac173f --- /dev/null +++ b/code/modules/language/language.dm.rej @@ -0,0 +1,15 @@ +diff a/code/modules/language/language.dm b/code/modules/language/language.dm (rejected hunks) +@@ -16,10 +16,10 @@ + // If key is null, then the language isn't real or learnable. + var/flags // Various language flags. + var/list/syllables // Used when scrambling text for a non-speaker. +- var/list/sentence_chance = 5 // Likelihood of making a new sentence after each syllable. +- var/list/space_chance = 55 // Likelihood of getting a space in the random scramble string ++ var/sentence_chance = 5 // Likelihood of making a new sentence after each syllable. ++ var/space_chance = 55 // Likelihood of getting a space in the random scramble string + var/list/spans = list() +- var/static/list/scramble_cache = list() ++ var/list/scramble_cache = list() + var/default_priority = 0 // the language that an atom knows with the highest "default_priority" is selected by default. + + // if you are seeing someone speak popcorn language, then something is wrong. diff --git a/code/modules/language/language_holder.dm b/code/modules/language/language_holder.dm index cd0ce23b23..c8ba509400 100644 --- a/code/modules/language/language_holder.dm +++ b/code/modules/language/language_holder.dm @@ -87,6 +87,10 @@ languages = list(/datum/language/common, /datum/language/ratvar) only_speaks_language = /datum/language/ratvar +/datum/language_holder/construct + languages = list(/datum/language/common, /datum/language/narsie) + only_speaks_language = /datum/language/narsie + /datum/language_holder/drone languages = list(/datum/language/common, /datum/language/drone, /datum/language/machine) only_speaks_language = /datum/language/drone diff --git a/code/modules/language/narsian.dm b/code/modules/language/narsian.dm new file mode 100644 index 0000000000..70966ad880 --- /dev/null +++ b/code/modules/language/narsian.dm @@ -0,0 +1,43 @@ +/datum/language/narsie + name = "Nar-Sian" + desc = "The ancient, blood-soaked, impossibly complex language of Nar-Sian cultists." + speech_verb = "intones" + ask_verb = "inquires" + exclaim_verb = "invokes" + key = "n" + sentence_chance = 8 + space_chance = 95 //very high due to the potential length of each syllable + var/static/list/base_syllables = list( + "h", "v", "c", "e", "g", "d", "r", "n", "h", "o", "p", + "ra", "so", "at", "il", "ta", "gh", "sh", "ya", "te", "sh", "ol", "ma", "om", "ig", "ni", "in", + "sha", "mir", "sas", "mah", "zar", "tok", "lyr", "nqa", "nap", "olt", "val", "qha", + "fwe", "ath", "yro", "eth", "gal", "gib", "bar", "jin", "kla", "atu", "kal", "lig", + "yoka", "drak", "loso", "arta", "weyh", "ines", "toth", "fara", "amar", "nyag", "eske", "reth", "dedo", "btoh", "nikt", "neth", + "kanas", "garis", "uloft", "tarat", "khari", "thnor", "rekka", "ragga", "rfikk", "harfr", "andid", "ethra", "dedol", "totum", + "ntrath", "keriam" + ) //the list of syllables we'll combine with itself to get a larger list of syllables + syllables = list( + "sha", "mir", "sas", "mah", "hra", "zar", "tok", "lyr", "nqa", "nap", "olt", "val", + "yam", "qha", "fel", "det", "fwe", "mah", "erl", "ath", "yro", "eth", "gal", "mud", + "gib", "bar", "tea", "fuu", "jin", "kla", "atu", "kal", "lig", + "yoka", "drak", "loso", "arta", "weyh", "ines", "toth", "fara", "amar", "nyag", "eske", "reth", "dedo", "btoh", "nikt", "neth", "abis", + "kanas", "garis", "uloft", "tarat", "khari", "thnor", "rekka", "ragga", "rfikk", "harfr", "andid", "ethra", "dedol", "totum", + "verbot", "pleggh", "ntrath", "barhah", "pasnar", "keriam", "usinar", "savrae", "amutan", "tannin", "remium", "barada", + "forbici" + ) //the base syllables, which include a few rare ones that won't appear in the mixed syllables + icon_state = "narsie" + default_priority = 10 + +/datum/language/narsie/New() + for(var/syllable in base_syllables) //we only do this once, since there's only ever a single one of each language datum. + for(var/target_syllable in base_syllables) + if(syllable != target_syllable) //don't combine with yourself + if(length(syllable) + length(target_syllable) > 8) //if the resulting syllable would be very long, don't put anything between it + syllables += "[syllable][target_syllable]" + else if(prob(80)) //we'll be minutely different each round. + syllables += "[syllable]'[target_syllable]" + else if(prob(25)) //5% chance of - instead of ' + syllables += "[syllable]-[target_syllable]" + else //15% chance of no ' or - at all + syllables += "[syllable][target_syllable]" + ..() diff --git a/code/modules/language/ratvar.dm b/code/modules/language/ratvarian.dm similarity index 51% rename from code/modules/language/ratvar.dm rename to code/modules/language/ratvarian.dm index cef4a3164e..b924d2fc79 100644 --- a/code/modules/language/ratvar.dm +++ b/code/modules/language/ratvarian.dm @@ -1,14 +1,19 @@ /datum/language/ratvar name = "Ratvarian" desc = "A timeless language full of power and incomprehensible to the unenlightened." - speech_verb = "clinks" - ask_verb = "clunks" - exclaim_verb = "clanks" + var/static/random_speech_verbs = list("clanks", "clinks", "clunks", "clangs") + ask_verb = "requests" + exclaim_verb = "proclaims" + whisper_verb = "imparts" key = "r" default_priority = 10 spans = list(SPAN_ROBOT) - icon_state = "ratvar" /datum/language/ratvar/scramble(var/input) . = text2ratvar(input) + +/datum/language/ratvar/get_spoken_verb(msg_end) + if(!msg_end) + return pick(random_speech_verbs) + return ..() \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/constructs.dm b/code/modules/mob/living/simple_animal/constructs.dm index a1253f27b4..304eb31e11 100644 --- a/code/modules/mob/living/simple_animal/constructs.dm +++ b/code/modules/mob/living/simple_animal/constructs.dm @@ -27,7 +27,8 @@ unique_name = 1 AIStatus = AI_OFF //normal constructs don't have AI loot = list(/obj/item/weapon/ectoplasm) - del_on_death = 1 + del_on_death = TRUE + initial_language_holder = /datum/language_holder/construct deathmessage = "collapses in a shattered heap." var/list/construct_spells = list() var/playstyle_string = "You are a generic construct! Your job is to not exist, and you should probably adminhelp this." diff --git a/code/modules/mob/living/simple_animal/shade.dm b/code/modules/mob/living/simple_animal/shade.dm index 8c08263aa7..4eaa10195b 100644 --- a/code/modules/mob/living/simple_animal/shade.dm +++ b/code/modules/mob/living/simple_animal/shade.dm @@ -28,7 +28,8 @@ status_flags = CANPUSH movement_type = FLYING loot = list(/obj/item/weapon/ectoplasm) - del_on_death = 1 + del_on_death = TRUE + initial_language_holder = /datum/language_holder/construct /mob/living/simple_animal/shade/death() deathmessage = "lets out a contented sigh as [p_their()] form unwinds." diff --git a/code/modules/surgery/organs/tongue.dm b/code/modules/surgery/organs/tongue.dm index 575a634a11..5a3555c8f9 100644 --- a/code/modules/surgery/organs/tongue.dm +++ b/code/modules/surgery/organs/tongue.dm @@ -15,7 +15,7 @@ /datum/language/common, /datum/language/draconic, /datum/language/monkey, - /datum/language/ratvar + /datum/language/narsie, )) /obj/item/organ/tongue/get_spans() diff --git a/code/modules/surgery/organs/tongue.dm.rej b/code/modules/surgery/organs/tongue.dm.rej new file mode 100644 index 0000000000..c1f978600b --- /dev/null +++ b/code/modules/surgery/organs/tongue.dm.rej @@ -0,0 +1,9 @@ +diff a/code/modules/surgery/organs/tongue.dm b/code/modules/surgery/organs/tongue.dm (rejected hunks) +@@ -15,6 +15,7 @@ + /datum/language/common, + /datum/language/draconic, + /datum/language/monkey, ++ /datum/language/narsie, + /datum/language/ratvar + )) + diff --git a/icons/misc/language.dmi b/icons/misc/language.dmi index e961c35191..081bbf1aa3 100644 Binary files a/icons/misc/language.dmi and b/icons/misc/language.dmi differ diff --git a/tgstation.dme b/tgstation.dme index c4b2676f1d..95c2255dfa 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -1432,7 +1432,8 @@ #include "code\modules\language\language_menu.dm" #include "code\modules\language\machine.dm" #include "code\modules\language\monkey.dm" -#include "code\modules\language\ratvar.dm" +#include "code\modules\language\narsian.dm" +#include "code\modules\language\ratvarian.dm" #include "code\modules\language\slime.dm" #include "code\modules\language\swarmer.dm" #include "code\modules\language\xenocommon.dm"