diff --git a/code/modules/client/preference_setup/general/02_language.dm b/code/modules/client/preference_setup/general/02_language.dm index 4a6bf5810fb..ed7ec1adf20 100644 --- a/code/modules/client/preference_setup/general/02_language.dm +++ b/code/modules/client/preference_setup/general/02_language.dm @@ -11,12 +11,14 @@ S["extra_languages"] >> pref.extra_languages testing("LANGSANI: Loaded from [pref.client]'s character [pref.real_name || "-name not yet loaded-"] savefile: [english_list(pref.alternate_languages || list())]") S["language_prefixes"] >> pref.language_prefixes + S["language_custom_keys"] >> pref.language_custom_keys /datum/category_item/player_setup_item/general/language/save_character(var/savefile/S) S["language"] << pref.alternate_languages S["extra_languages"] << pref.extra_languages testing("LANGSANI: Saved to [pref.client]'s character [pref.real_name || "-name not yet loaded-"] savefile: [english_list(pref.alternate_languages || list())]") S["language_prefixes"] << pref.language_prefixes + S["language_custom_keys"] << pref.language_custom_keys /datum/category_item/player_setup_item/general/language/sanitize_character() if(!islist(pref.alternate_languages)) @@ -44,6 +46,14 @@ for(var/prefix in pref.language_prefixes) if(prefix in forbidden_prefixes) pref.language_prefixes -= prefix + if(isnull(pref.language_custom_keys)) + pref.language_custom_keys = list() + var/datum/species/S = GLOB.all_species[pref.species] + for(var/key in pref.language_custom_keys) + if(!pref.language_custom_keys[key]) + pref.language_custom_keys.Remove(key) + if(!((pref.language_custom_keys[key] == S.language) || (pref.language_custom_keys[key] == S.default_language && S.default_language != S.language) || (pref.language_custom_keys[key] in pref.alternate_languages))) + pref.language_custom_keys.Remove(key) /datum/category_item/player_setup_item/general/language/content() . += "Languages
" @@ -52,14 +62,14 @@ testing("LANGSANI: Truncated [pref.client]'s character [pref.real_name || "-name not yet loaded-"] language list because it was too long (len: [pref.alternate_languages.len], allowed: [S.num_alternate_languages])") pref.alternate_languages.len = (S.num_alternate_languages + pref.extra_languages) // Truncate to allowed length if(S.language) - . += "- [S.language]
" + . += "- [S.language] - Set Custom Key
" if(S.default_language && S.default_language != S.language) - . += "- [S.default_language]
" + . += "- [S.default_language] - Set Custom Key
" if(S.num_alternate_languages + pref.extra_languages) if(pref.alternate_languages.len) for(var/i = 1 to pref.alternate_languages.len) var/lang = pref.alternate_languages[i] - . += "- [lang] - remove
" + . += "- [lang] - remove - Set Custom Key
" if(pref.alternate_languages.len < (S.num_alternate_languages + pref.extra_languages)) . += "- add ([(S.num_alternate_languages + pref.extra_languages) - pref.alternate_languages.len] remaining)
" @@ -127,4 +137,32 @@ pref.language_prefixes = config.language_prefixes.Copy() return TOPIC_REFRESH + else if(href_list["set_custom_key"]) + var/lang = href_list["set_custom_key"] + if(!(lang in GLOB.all_languages)) + return TOPIC_REFRESH + + var/oldkey = "" + for(var/key in pref.language_custom_keys) + if(pref.language_custom_keys[key] == lang) + oldkey = key + break + + var/char = tgui_input_text(user, "Input a language key for [lang]. Input a single space to reset.", "Language Custom Key", oldkey) + if(length(char) != 1) + return TOPIC_REFRESH + else if(char == " ") + for(var/key in pref.language_custom_keys) + if(pref.language_custom_keys[key] == lang) + pref.language_custom_keys -= key + break + else if(contains_az09(char)) + if(!(char in pref.language_custom_keys)) + pref.language_custom_keys += char + pref.language_custom_keys[char] = lang + else + tgui_alert_async(user, "Improper language key. Rejected.", "Error") + + return TOPIC_REFRESH + return ..() diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 334d901e4bb..8d23ca6e5f1 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -63,7 +63,8 @@ var/list/preferences_datums = list() var/species = SPECIES_HUMAN //Species datum to use. var/species_preview //Used for the species selection window. var/list/alternate_languages = list() //Secondary language(s) - var/list/language_prefixes = list() //Kanguage prefix keys + var/list/language_prefixes = list() //Language prefix keys + var/list/language_custom_keys = list() //Language custom call keys var/list/gear //Left in for Legacy reasons, will no longer save. var/list/gear_list = list() //Custom/fluff item loadouts. var/gear_slot = 1 //The current gear save slot @@ -426,12 +427,12 @@ var/list/preferences_datums = list() selecting_slots = FALSE if(!choice) return - + var/slotnum = charlist[choice] if(!slotnum) error("Player picked [choice] slot to load, but that wasn't one we sent.") return - + load_character(slotnum) attempt_vr(user.client?.prefs_vr,"load_vore","") //VOREStation Edit sanitize_preferences() @@ -466,12 +467,12 @@ var/list/preferences_datums = list() selecting_slots = FALSE if(!choice) return - + var/slotnum = charlist[choice] if(!slotnum) error("Player picked [choice] slot to copy to, but that wasn't one we sent.") return - + overwrite_character(slotnum) sanitize_preferences() ShowChoices(user) diff --git a/code/modules/mob/language/language.dm b/code/modules/mob/language/language.dm index 4cb01b981fd..4fa749f41e1 100644 --- a/code/modules/mob/language/language.dm +++ b/code/modules/mob/language/language.dm @@ -192,6 +192,9 @@ /mob/proc/remove_language(var/rem_language) var/datum/language/L = GLOB.all_languages[rem_language] . = (L in languages) + var/prefix = get_custom_prefix_by_lang(src, L) + if(prefix) + language_keys.Remove(prefix) languages.Remove(L) /mob/living/remove_language(rem_language) @@ -240,7 +243,8 @@ for(var/datum/language/L in languages) if(!(L.flags & NONGLOBAL)) - . += "[L.name] ([get_language_prefix()][L.key])
[L.desc]

" + var/lang_key = get_custom_prefix_by_lang(src, L) + . += "[L.name] ([get_language_prefix()][L.key][lang_key ? " [get_language_prefix()][lang_key]" : ""])
[L.desc]

" /mob/living/check_lang_data() . = "" @@ -250,12 +254,13 @@ for(var/datum/language/L in languages) if(!(L.flags & NONGLOBAL)) + var/lang_key = get_custom_prefix_by_lang(src, L) if(L == default_language) - . += "[L.name] ([get_language_prefix()][L.key]) - default - reset
[L.desc]

" + . += "[L.name] ([get_language_prefix()][L.key][lang_key ? " [get_language_prefix()][lang_key]" : ""]) Edit Custom Key - default - reset
[L.desc]

" else if (can_speak(L)) - . += "[L.name] ([get_language_prefix()][L.key]) - set default
[L.desc]

" + . += "[L.name] ([get_language_prefix()][L.key][lang_key ? " [get_language_prefix()][lang_key]" : ""]) Edit Custom Key - set default
[L.desc]

" else - . += "[L.name] ([get_language_prefix()][L.key]) - cannot speak!
[L.desc]

" + . += "[L.name] ([get_language_prefix()][L.key][lang_key ? " [get_language_prefix()][lang_key]" : ""]) Edit Custom Key - cannot speak!
[L.desc]

" /mob/verb/check_languages() set name = "Check Known Languages" @@ -279,6 +284,22 @@ set_default_language(L) check_languages() return 1 + else if(href_list["set_lang_key"]) + var/datum/language/L = locate(href_list["set_lang_key"]) + if(L && (L in languages)) + var/old_key = get_custom_prefix_by_lang(src, L) + var/custom_key = tgui_input_text(src, "Input a new key for [L.name]", "Language Key", old_key) + if(custom_key && length(custom_key) == 1) + if(contains_az09(custom_key)) + language_keys[custom_key] = L + if(old_key && old_key != custom_key) + language_keys.Remove(old_key) + else if(custom_key == " ") + if(old_key && old_key != custom_key) + language_keys.Remove(old_key) + else + tgui_alert_async(src, "Improper language key. Rejected.", "Error") + check_languages() else return ..() @@ -287,5 +308,17 @@ if(L.flags & except_flags) continue target.add_language(L.name) + for(var/key in source.language_keys) + if(L == source.language_keys[key]) + if(!(key in target.language_keys)) + target.language_keys[key] = L + +/proc/get_custom_prefix_by_lang(var/mob/our_mob, var/language) + if(!our_mob || !our_mob.language_keys.len || !language) + return + + for(var/key in our_mob.language_keys) + if(our_mob.language_keys[key] == language) + return key #undef SCRAMBLE_CACHE_LEN diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index dc1f1fc2196..19476f24606 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -94,6 +94,7 @@ var/list/pinned = list() // List of things pinning this creature to walls (see living_defense.dm) var/list/embedded = list() // Embedded items, since simple mobs don't have organs. var/list/languages = list() // For speaking/listening. + var/list/language_keys = list() // List of language keys indexing languages var/species_language = null // For species who want reset to use a specified default. var/only_species_language = 0 // For species who can only speak their default and no other languages. Does not affect understanding. var/list/speak_emote = list("says") // Verbs used when speaking. Defaults to 'say' if speak_emote is null. diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm index efe2531616e..3d9cd13a511 100644 --- a/code/modules/mob/new_player/new_player.dm +++ b/code/modules/mob/new_player/new_player.dm @@ -604,6 +604,11 @@ if(chosen_language) if(is_lang_whitelisted(src,chosen_language) || (new_character.species && (chosen_language.name in new_character.species.secondary_langs))) new_character.add_language(lang) + for(var/key in client.prefs.language_custom_keys) + if(client.prefs.language_custom_keys[key]) + var/datum/language/keylang = GLOB.all_languages[client.prefs.language_custom_keys[key]] + if(keylang) + new_character.language_keys[key] = keylang // And uncomment this, too. //new_character.dna.UpdateSE() diff --git a/code/modules/mob/say.dm b/code/modules/mob/say.dm index 646c82a168a..a603ee36f0f 100644 --- a/code/modules/mob/say.dm +++ b/code/modules/mob/say.dm @@ -180,6 +180,8 @@ // Okay, we're definitely now trying to invoke a language (probably) // This "[]" is probably unnecessary but BYOND will runtime if a number is used var/datum/language/L = GLOB.language_keys["[language_key]"] + if((language_key in language_keys) && language_keys[language_key]) + L = language_keys[language_key] // MULTILINGUAL_SPACE enforces a space after the language key if(client && (client.prefs.multilingual_mode == MULTILINGUAL_SPACE) && (text2ascii(copytext(selection, 3, 4)) != 32)) // If we're looking for a space and we don't find one diff --git a/code/modules/resleeving/autoresleever.dm b/code/modules/resleeving/autoresleever.dm index 0b8433e90ca..1e6753f4d77 100644 --- a/code/modules/resleeving/autoresleever.dm +++ b/code/modules/resleeving/autoresleever.dm @@ -74,21 +74,21 @@ return var/client/ghost_client = ghost.client - + if(!is_alien_whitelisted(ghost, GLOB.all_species[ghost_client?.prefs?.species]) && !check_rights(R_ADMIN, 0)) // Prevents a ghost ghosting in on a slot and spawning via a resleever with race they're not whitelisted for, getting around normal join restrictions. to_chat(ghost, "You are not whitelisted to spawn as this species!") return - + /* // Comments out NO_SCAN restriction, as per headmin/maintainer request. var/datum/species/chosen_species if(ghost.client.prefs.species) // In case we somehow don't have a species set here. chosen_species = GLOB.all_species[ghost_client.prefs.species] - + if(chosen_species.flags && NO_SCAN) // Sanity. Prevents species like Xenochimera, Proteans, etc from rejoining the round via resleeve, as they should have their own methods of doing so already, as agreed to when you whitelist as them. to_chat(ghost, "This species cannot be resleeved!") return */ - + //Name matching is ugly but mind doesn't persist to look at. var/charjob var/datum/data/record/record_found @@ -132,7 +132,7 @@ else spawn_slots -- return - + if(tgui_alert(ghost, "Would you like to be resleeved?", "Resleeve", list("No","Yes")) == "No") return var/mob/living/carbon/human/new_character @@ -152,7 +152,7 @@ ghost.mind.transfer_to(new_character) new_character.key = player_key - + //Were they any particular special role? If so, copy. if(new_character.mind) new_character.mind.loaded_from_ckey = picked_ckey @@ -167,6 +167,11 @@ if(chosen_language) if(is_lang_whitelisted(src,chosen_language) || (new_character.species && (chosen_language.name in new_character.species.secondary_langs))) new_character.add_language(lang) + for(var/key in ghost_client.prefs.language_custom_keys) + if(ghost_client.prefs.language_custom_keys[key]) + var/datum/language/keylang = GLOB.all_languages[ghost_client.prefs.language_custom_keys[key]] + if(keylang) + new_character.language_keys[key] = keylang //If desired, apply equipment. if(equip_body) diff --git a/code/modules/vore/eating/inbelly_spawn.dm b/code/modules/vore/eating/inbelly_spawn.dm index 39c09554e02..207f3ca4e01 100644 --- a/code/modules/vore/eating/inbelly_spawn.dm +++ b/code/modules/vore/eating/inbelly_spawn.dm @@ -161,6 +161,11 @@ Please do not abuse this ability. if(chosen_language) if(is_lang_whitelisted(prey,chosen_language) || (new_character.species && (chosen_language.name in new_character.species.secondary_langs))) new_character.add_language(lang) + for(var/key in prey.prefs.language_custom_keys) + if(prey.prefs.language_custom_keys[key]) + var/datum/language/keylang = GLOB.all_languages[prey.prefs.language_custom_keys[key]] + if(keylang) + new_character.language_keys[key] = keylang new_character.regenerate_icons()