#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/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/list/scramble_cache = list() var/default_priority = 0 // the language that an atom knows with the highest "default_priority" is selected by default. var/sing_verb = "sings" // Used for singing. // if you are seeing someone speak popcorn language, then something is wrong. var/icon = 'icons/misc/language.dmi' var/icon_state = "popcorn" /datum/language/proc/display_icon(atom/movable/hearer) var/understands = hearer.has_language(src.type) if(flags & LANGUAGE_HIDE_ICON_IF_UNDERSTOOD && understands) return FALSE if(flags & LANGUAGE_HIDE_ICON_IF_NOT_UNDERSTOOD && !understands) return FALSE return TRUE /datum/language/proc/get_icon() var/datum/asset/spritesheet/sheet = get_asset_datum(/datum/asset/spritesheet/chat) return sheet.icon_tag("language-[icon_state]") /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, 1), 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/check_cache(input) var/lookup = scramble_cache[input] if(lookup) scramble_cache -= input scramble_cache[input] = lookup . = lookup /datum/language/proc/add_to_cache(input, scrambled_text) // 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) /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 = check_cache(input) if(lookup) return lookup var/input_size = length_char(input) var/scrambled_text = "" var/capitalize = TRUE while(length_char(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_char(scrambled_text, -1) if(ending == ".") scrambled_text = copytext_char(scrambled_text, 1, -2) var/input_ending = copytext_char(input, -1) if(input_ending in list("!","?",".")) scrambled_text += input_ending add_to_cache(input, scrambled_text) return scrambled_text /datum/language/proc/scramble_HTML(intext) // Calls scramble() on HTML text, making sure to not disturb the HTML. var/text = "" var/regex/plaintext = regex(@"((>|^)([^<>]+)(?:<|$)") // Finds plaintext within the HTML. var/newtext = intext var/startpos = 1 while(startpos < 8192 && startpos > -1) var/regexstart = plaintext.Find(newtext,startpos) // Where the *regex* first matches if(!regexstart) break var/capturestart = regexstart + length(plaintext.group[1]) // Where the *capture* first matches, the actual plaintext of this section var/sentence = plaintext.group[2] var/scramb = scramble(sentence) // The scrambled version of the sentence. newtext = replacetext(newtext, sentence, scramb, capturestart, capturestart + length(sentence)+1) startpos = plaintext.next + (length(scramb) - length(sentence)) text += newtext return 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