forked from tgstation/tgstation
-
Notifications
You must be signed in to change notification settings - Fork 38
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
26 changed files
with
546 additions
and
18 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
#define LANGUAGE_UNDERSTOOD 1 | ||
#define LANGUAGE_SPOKEN 2 | ||
// LANGUAGE SOURCE DEFINES | ||
/// Use this when granting languages in special() for spawner roles, to prevent prefs from removing them | ||
#define LANGUAGE_SPAWNER "spawner" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
/datum/language/ | ||
/// Should this be hidden on the language buy menu? | ||
var/secret = FALSE | ||
|
||
|
||
/datum/language/aphasia | ||
secret = TRUE | ||
|
||
/datum/language/codespeak | ||
secret = TRUE | ||
|
||
/datum/language/drone | ||
secret = TRUE | ||
|
||
/datum/language/narsie | ||
secret = TRUE | ||
|
||
/datum/language/piratespeak | ||
secret = TRUE | ||
|
||
/datum/language/xenocommon | ||
secret = TRUE |
169 changes: 169 additions & 0 deletions
169
modular_doppler/languages/code/language menu/client_languages.dm
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,169 @@ | ||
#define MAX_LANGUAGES_NORMAL 3 | ||
#define MAX_LANGUAGES_LINGUIST 4 | ||
|
||
/datum/asset/spritesheet/languages | ||
name = "languages" | ||
early = TRUE | ||
cross_round_cachable = TRUE | ||
|
||
/datum/asset/spritesheet/languages/create_spritesheets() | ||
var/list/to_insert = list() | ||
|
||
if(!GLOB.all_languages.len) | ||
stack_trace("Warning: Language spritesheets could not be created because language subsystem has not been loaded yet. This should not happen--adjust the init_order in master_files/code/controllers/subsystem/language.dm.") | ||
return | ||
|
||
for (var/language_name in GLOB.all_languages) | ||
var/datum/language/language = GLOB.language_datum_instances[language_name] | ||
var/icon/language_icon = icon(language.icon, icon_state = language.icon_state) | ||
to_insert[sanitize_css_class_name(language.name)] = language_icon | ||
|
||
for (var/spritesheet_key in to_insert) | ||
Insert(spritesheet_key, to_insert[spritesheet_key]) | ||
|
||
/// Middleware to handle languages | ||
/datum/preference_middleware/languages | ||
/// A associative list of language names to their typepath | ||
var/static/list/name_to_language = list() | ||
action_delegations = list( | ||
"give_language" = PROC_REF(give_language), | ||
"remove_language" = PROC_REF(remove_language), | ||
) | ||
|
||
/datum/preference_middleware/languages/apply_to_human(mob/living/carbon/human/target, datum/preferences/preferences, visuals_only = FALSE) | ||
var/datum/language_holder/language_holder = target.get_language_holder() | ||
language_holder.adjust_languages_to_prefs(preferences) | ||
|
||
/datum/preference_middleware/languages/get_ui_assets() | ||
return list( | ||
get_asset_datum(/datum/asset/spritesheet/languages), | ||
) | ||
|
||
/datum/preference_middleware/languages/post_set_preference(mob/user, preference, value) | ||
if(preference != "species") | ||
return | ||
preferences.languages = list() | ||
var/species_type = preferences.read_preference(/datum/preference/choiced/species) | ||
var/datum/species/species = new species_type() | ||
var/datum/language_holder/lang_holder = new species.species_language_holder() | ||
for(var/language in preferences.get_adjusted_language_holder()) | ||
preferences.languages[language] = LANGUAGE_SPOKEN | ||
qdel(lang_holder) | ||
qdel(species) | ||
|
||
for(var/language in lang_holder.spoken_languages) | ||
preferences.languages[language] = LANGUAGE_SPOKEN | ||
|
||
qdel(lang_holder) | ||
qdel(species) | ||
|
||
return ..() | ||
|
||
/datum/preference_middleware/languages/get_ui_data(mob/user) | ||
if(length(name_to_language) != length(GLOB.all_languages)) | ||
initialize_name_to_language() | ||
|
||
var/list/data = list() | ||
|
||
var/max_languages = preferences.all_quirks.Find(TRAIT_LINGUIST) ? MAX_LANGUAGES_LINGUIST : MAX_LANGUAGES_NORMAL | ||
var/species_type = preferences.read_preference(/datum/preference/choiced/species) | ||
var/datum/species/species = new species_type() | ||
var/datum/language_holder/lang_holder = preferences.get_adjusted_language_holder() | ||
if(!preferences.languages || !preferences.languages.len || (preferences.languages && preferences.languages.len > max_languages)) // Too many languages, or no languages. | ||
preferences.languages = list() | ||
for(var/language in lang_holder.spoken_languages) | ||
preferences.languages[language] = LANGUAGE_SPOKEN | ||
|
||
var/list/selected_languages = list() | ||
var/list/unselected_languages = list() | ||
|
||
for (var/language_name in GLOB.all_languages) | ||
var/datum/language/language = GLOB.language_datum_instances[language_name] | ||
|
||
if(language.secret && !(language.type in species.language_prefs_whitelist)) // For ghostrole species who are able to speak a secret language, e.g. ashwalkers, display it. | ||
continue | ||
|
||
if(species.always_customizable && !(language.type in lang_holder.spoken_languages)) // For the ghostrole species. We don't want ashwalkers speaking beachtongue now. | ||
continue | ||
if(preferences.languages[language.type]) | ||
selected_languages += list(list( | ||
"description" = language.desc, | ||
"name" = language.name, | ||
"icon" = sanitize_css_class_name(language.name) | ||
)) | ||
else | ||
unselected_languages += list(list( | ||
"description" = language.desc, | ||
"name" = language.name, | ||
"icon" = sanitize_css_class_name(language.name) | ||
)) | ||
|
||
qdel(lang_holder) | ||
qdel(species) | ||
|
||
data["total_language_points"] = max_languages | ||
data["selected_languages"] = selected_languages | ||
data["unselected_languages"] = unselected_languages | ||
return data | ||
|
||
/// (Re-)Initializes the `name_to_language` associative list, to ensure that it's properly populated. | ||
/datum/preference_middleware/languages/proc/initialize_name_to_language() | ||
name_to_language = list() | ||
for(var/language_name in GLOB.all_languages) | ||
var/datum/language/language = GLOB.language_datum_instances[language_name] | ||
name_to_language[language.name] = language_name | ||
|
||
/** | ||
* Proc that gives a language to a character, granted that they don't already have too many | ||
* of them, based on their maximum amount of languages. | ||
* | ||
* Arguments: | ||
* * params - List of parameters, given to us by the `act()` method from TGUI. Needs to | ||
* contain a value under `"language_name"`. | ||
* | ||
* Returns TRUE all the time, to ensure that the UI is updated. | ||
*/ | ||
/datum/preference_middleware/languages/proc/give_language(list/params) | ||
var/language_name = params["language_name"] | ||
var/max_languages = preferences.all_quirks.Find(TRAIT_LINGUIST) ? MAX_LANGUAGES_LINGUIST : MAX_LANGUAGES_NORMAL | ||
|
||
if(preferences.languages && preferences.languages.len == max_languages) // too many languages | ||
return TRUE | ||
|
||
preferences.languages[name_to_language[language_name]] = LANGUAGE_SPOKEN | ||
return TRUE | ||
|
||
/** | ||
* Proc that removes a language from a character. | ||
* | ||
* Arguments: | ||
* * params - List of parameters, given to us by the `act()` method from TGUI. Needs to | ||
* contain a value under `"language_name"`. | ||
* | ||
* Returns TRUE all the time, to ensure that the UI is updated. | ||
*/ | ||
/datum/preference_middleware/languages/proc/remove_language(list/params) | ||
var/language_name = params["language_name"] | ||
preferences.languages -= name_to_language[language_name] | ||
return TRUE | ||
|
||
/// Cleans up any invalid languages. Typically happens on language renames and codedels. | ||
/datum/preferences/proc/sanitize_languages() | ||
var/languages_edited = FALSE | ||
for(var/lang_path as anything in languages) | ||
if(!lang_path) | ||
languages.Remove(lang_path) | ||
languages_edited = TRUE | ||
continue | ||
|
||
var/datum/language/language = new lang_path() | ||
// Yes, checking subtypes is VERY necessary, because byond doesn't check to see if a path is valid at runtime! | ||
// If you delete /datum/language/meme, it will still load as /datum/language/meme, and will instantiate with /datum/language's defaults! | ||
var/species_type = read_preference(/datum/preference/choiced/species) | ||
var/datum/species/species = new species_type() | ||
if(!(language.type in subtypesof(/datum/language)) || (language.secret && !(language.type in species.language_prefs_whitelist))) | ||
languages.Remove(lang_path) | ||
languages_edited = TRUE | ||
qdel(species) | ||
qdel(language) | ||
return languages_edited |
111 changes: 111 additions & 0 deletions
111
modular_doppler/languages/code/language menu/language_holder.dm
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
GLOBAL_DATUM_INIT(language_holder_adjustor, /datum/language_holder_adjustor, new) | ||
|
||
/// Language code needs to be purged. Make sure, once and for all, that we get the correct languages on spawn. | ||
/// Every time a crew member joins the adjustor will personally fix their language, because there is too much coupling between mind and language code to do it reliably otherwise. | ||
/// It has already needed to be fixed like 3 times. This will (hopefully) be the final time. | ||
/datum/language_holder_adjustor/New() | ||
RegisterSignal(SSdcs, COMSIG_GLOB_CREWMEMBER_JOINED, PROC_REF(handle_new_player)) | ||
|
||
/datum/language_holder_adjustor/proc/handle_new_player(datum/source, mob/living/carbon/human/new_crewmember, rank) | ||
SIGNAL_HANDLER | ||
|
||
// sanity checking because we really do not want to be causing any runtimes | ||
if(!istype(new_crewmember)) | ||
return | ||
if(isnull(new_crewmember.mind)) | ||
return | ||
|
||
var/datum/language_holder/language_holder = new_crewmember.get_language_holder() | ||
|
||
if(isnull(language_holder)) | ||
return | ||
|
||
language_holder.adjust_languages_to_prefs(new_crewmember.client?.prefs) | ||
|
||
/datum/language_holder_adjustor/Destroy() | ||
..() | ||
UnregisterSignal(SSdcs, COMSIG_GLOB_CREWMEMBER_JOINED) | ||
|
||
/datum/language_holder/proc/adjust_languages_to_prefs(datum/preferences/preferences) | ||
// no prefs? then don't remove any languages | ||
if(!preferences) | ||
return | ||
|
||
// remove the innate languages (like common, and other species languages) and instead use the language prefs | ||
// do not remove any languages granted by spawners, which are denoted by source = LANGUAGE_SPAWNER | ||
remove_languages_by_source(list(LANGUAGE_MIND, LANGUAGE_ATOM, LANGUAGE_SPECIES)) | ||
|
||
for(var/lang_path in preferences.languages) | ||
grant_language(lang_path) | ||
|
||
get_selected_language() | ||
|
||
/// Removes every language whose source(s) match the provided source list arg | ||
/datum/language_holder/proc/remove_languages_by_source(list/sources) | ||
if(!length(sources)) | ||
return | ||
for(var/language in understood_languages) | ||
for(var/source in sources) | ||
remove_language(language, ALL, source) | ||
// in most cases spoken_languages should be empty by now, but just in case we should remove what's left | ||
for(var/language in spoken_languages) | ||
for(var/source in sources) | ||
remove_language(language, ALL, source) | ||
|
||
//************************************************ | ||
//* Specific language holders * | ||
//* Use atom language sources only. * | ||
//************************************************/ | ||
|
||
/datum/language_holder/machine // SYNTHETIC LIZARD & CO LANGUAGE | ||
understood_languages = list(/datum/language/common = list(LANGUAGE_ATOM), | ||
/datum/language/machine = list(LANGUAGE_ATOM)) | ||
spoken_languages = list(/datum/language/common = list(LANGUAGE_ATOM), | ||
/datum/language/machine = list(LANGUAGE_ATOM)) | ||
|
||
/// Modularized the Cyborg and AI language_holder, add here the languages that you want them to be able to speak and understand. | ||
/datum/language_holder/synthetic | ||
understood_languages = list( | ||
/datum/language/common = list(LANGUAGE_ATOM), | ||
/datum/language/uncommon = list(LANGUAGE_ATOM), | ||
/datum/language/machine = list(LANGUAGE_ATOM), | ||
/datum/language/draconic = list(LANGUAGE_ATOM), | ||
/datum/language/moffic = list(LANGUAGE_ATOM), | ||
/datum/language/calcic = list(LANGUAGE_ATOM), | ||
/datum/language/voltaic = list(LANGUAGE_ATOM), | ||
/datum/language/nekomimetic = list(LANGUAGE_ATOM), | ||
/datum/language/gutter = list(LANGUAGE_ATOM), | ||
/datum/language/konjin = list(LANGUAGE_ATOM), | ||
/datum/language/monkey = list(LANGUAGE_ATOM), | ||
/datum/language/slime = list(LANGUAGE_ATOM), | ||
/datum/language/beachbum = list(LANGUAGE_ATOM), | ||
/datum/language/mushroom = list(LANGUAGE_ATOM), | ||
/datum/language/shadowtongue = list(LANGUAGE_ATOM), | ||
/datum/language/buzzwords = list(LANGUAGE_ATOM), | ||
/datum/language/terrum = list(LANGUAGE_ATOM), | ||
/datum/language/sylvan = list(LANGUAGE_ATOM), | ||
) | ||
spoken_languages = list( | ||
/datum/language/common = list(LANGUAGE_ATOM), | ||
/datum/language/uncommon = list(LANGUAGE_ATOM), | ||
/datum/language/machine = list(LANGUAGE_ATOM), | ||
/datum/language/draconic = list(LANGUAGE_ATOM), | ||
/datum/language/moffic = list(LANGUAGE_ATOM), | ||
/datum/language/calcic = list(LANGUAGE_ATOM), | ||
/datum/language/voltaic = list(LANGUAGE_ATOM), | ||
/datum/language/nekomimetic = list(LANGUAGE_ATOM), | ||
/datum/language/gutter = list(LANGUAGE_ATOM), | ||
/datum/language/konjin = list(LANGUAGE_ATOM), | ||
/datum/language/monkey = list(LANGUAGE_ATOM), | ||
/datum/language/slime = list(LANGUAGE_ATOM), | ||
/datum/language/beachbum = list(LANGUAGE_ATOM), | ||
/datum/language/mushroom = list(LANGUAGE_ATOM), | ||
/datum/language/shadowtongue = list(LANGUAGE_ATOM), | ||
/datum/language/buzzwords = list(LANGUAGE_ATOM), | ||
/datum/language/terrum = list(LANGUAGE_ATOM), | ||
/datum/language/sylvan = list(LANGUAGE_ATOM), | ||
) | ||
|
||
/datum/language_holder/drone_nova | ||
understood_languages = list(/datum/language/drone = list(LANGUAGE_ATOM), /datum/language/common = list(LANGUAGE_ATOM)) | ||
spoken_languages = list(/datum/language/drone = list(LANGUAGE_ATOM)) |
29 changes: 29 additions & 0 deletions
29
modular_doppler/languages/code/language menu/language_preferences.dm
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
#define MAX_MUTANT_ROWS 4 | ||
|
||
/datum/preferences | ||
/// Associative list, keyed by language typepath, pointing to LANGUAGE_UNDERSTOOD, or LANGUAGE_SPOKEN, for whether we understand or speak the language | ||
var/list/languages = list() | ||
|
||
/datum/preferences/proc/species_updated(species_type) | ||
all_quirks = list() | ||
// Reset cultural stuff | ||
languages[try_get_common_language()] = LANGUAGE_SPOKEN | ||
save_character() | ||
|
||
/// This helper proc gets the current species language holder and does any post-processing that's required in one easy to track place. | ||
/// This proc should *always* be edited or used when modifying or getting the default languages of a player controlled, unrestricted species, to prevent any errant conflicts. | ||
/datum/preferences/proc/get_adjusted_language_holder() | ||
var/datum/species/species = read_preference(/datum/preference/choiced/species) | ||
species = new species() | ||
var/datum/language_holder/language_holder = new species.species_language_holder() | ||
|
||
// Do language post procesing here. Used to house our foreigner functionality. | ||
// I saw little reason to remove this proc, considering it makes code using this a little easier to read. | ||
|
||
return language_holder | ||
|
||
/// Tries to get the topmost language of the language holder. Should be the species' native language, and if it isn't, you should pester a coder. | ||
/datum/preferences/proc/try_get_common_language() | ||
var/datum/language_holder/language_holder = get_adjusted_language_holder() | ||
var/language = language_holder.spoken_languages[1] | ||
return language |
Oops, something went wrong.