Skip to content

Commit

Permalink
Fixes languages + Give them a basic UI for selection (MrMelbert#101)
Browse files Browse the repository at this point in the history
  • Loading branch information
MrMelbert authored Oct 22, 2021
1 parent 58fe0ae commit 15dbbe8
Show file tree
Hide file tree
Showing 7 changed files with 249 additions and 60 deletions.
2 changes: 1 addition & 1 deletion jollystation_modules/code/datums/quirks/good.dm
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
/// Trilingual quirk - Gives the owner a language.
/datum/quirk/trilingual
name = "Trilingual"
desc = "You're trilingual - you know another random language besides common and your native tongue."
desc = "You're trilingual - you know another random language besides common and your native tongue. (If you take this quirk, you cannot select an additional language.)"
icon = "globe"
value = 1
gain_text = "<span class='notice'>You understand a new language.</span>"
Expand Down
4 changes: 2 additions & 2 deletions jollystation_modules/code/datums/quirks/negative.dm
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
/datum/quirk/bad_touch
value = -2

/datum/quirk/light_drinker/New()
desc += " - (Unallowed: Skrell)"
/datum/quirk/light_drinker
desc = "You just can't handle your drinks and get drunk very quickly. (Unallowed: Skrell)"

// Modular quirks
// More vulnerabile to pain (increased pain modifier)
Expand Down
181 changes: 136 additions & 45 deletions jollystation_modules/code/modules/client/preferences/languages.dm
Original file line number Diff line number Diff line change
@@ -1,73 +1,164 @@
// -- Language preference and UI.

/// Simple define to denote no language.
#define NO_LANGUAGE "No Language"

/datum/preference/choiced/additional_language
/// List of species IDs of species's that can't get an additional language
#define BLACKLISTED_SPECIES_FROM_LANGUAGES list(SPECIES_SYNTH_MILITARY, SPECIES_SYNTH, SPECIES_ANDROID)

// Stores a typepath of a language, or "No language" when passed a null / invalid language.
/datum/preference/additional_language
savefile_key = "language"
savefile_identifier = PREFERENCE_CHARACTER
category = PREFERENCE_CATEGORY_SECONDARY_FEATURES
priority = PREFERENCE_PRIORITY_NAMES
can_randomize = FALSE

/datum/preference/choiced/additional_language/init_possible_values()
return list(NO_LANGUAGE, "Skrellian", "Nekomimetic", "Moffic", "Draconic", "High Draconic")
/datum/preference/additional_language/deserialize(input, datum/preferences/preferences)
var/datum/species/species = preferences.read_preference(/datum/preference/choiced/species)
var/species_id = initial(species.id)

/datum/preference/choiced/additional_language/create_default_value()
return NO_LANGUAGE
if(species_id in BLACKLISTED_SPECIES_FROM_LANGUAGES)
return NO_LANGUAGE

/datum/preference/choiced/additional_language/is_accessible(datum/preferences/preferences)
. = ..()
if(!.)
return
var/datum/language/lang_to_add = GLOB.language_datum_instances[input]
if(!lang_to_add)
return NO_LANGUAGE

if(lang_to_add.base_species && lang_to_add.base_species == species_id)
return NO_LANGUAGE
if(lang_to_add.req_species && lang_to_add.req_species != species_id)
return NO_LANGUAGE

// Not compatible with trilingual.
if("Trilingual" in preferences.all_quirks)
return FALSE
return NO_LANGUAGE

return TRUE
return input

// We need to apply our language at the very end
/datum/preference/choiced/additional_language/apply_to_human(mob/living/carbon/human/target, value)
return
/datum/preference/additional_language/serialize(input)
return ispath(input) ? input : NO_LANGUAGE

/datum/preference/choiced/additional_language/after_apply_to_human(mob/living/carbon/human/target, datum/preferences/prefs, value)
if(!prefs)
CRASH("language preference after_apply_to_human called without preferences datum.")
/datum/preference/additional_language/create_default_value()
return NO_LANGUAGE

/datum/preference/additional_language/is_valid(value)
return ispath(value) || value == NO_LANGUAGE

/datum/preference/additional_language/apply_to_human(mob/living/carbon/human/target, value)
if(value == NO_LANGUAGE)
return

if("Trilingual" in prefs.all_quirks)
prefs.write_preference(GLOB.preference_entries[type], NO_LANGUAGE)
return
target.grant_language(value, TRUE, TRUE, LANGUAGE_PREF)

var/datum/language/language_type
var/datum/language/language_instance
for(var/found_language in GLOB.language_datum_instances)
var/datum/language/found_instance = GLOB.language_datum_instances[found_language]
if(found_instance.name == value)
language_type = found_language
language_instance = found_instance
break
/datum/language
// Vars used in determining valid languages for the language preferences.
/// The 'base species' of the language, the lizard to the draconic.
var/base_species
/// The 'required species' of the language, languages that require you be a certain species to know.
var/req_species

if(!language_type || !language_instance)
CRASH("language preference after_apply_to_human could not find a corresponding [language_type ? "language instance" : "language type"]! passed value: [value]")
/datum/language/skrell
base_species = SPECIES_SKRELL

var/datum/language_holder/target_languages = target.get_language_holder()
/datum/language/draconic
base_species = SPECIES_LIZARD

if(language_type in target_languages.spoken_languages)
to_chat(prefs.parent, span_notice("You already know the [value] language."))
prefs.write_preference(GLOB.preference_entries[type], NO_LANGUAGE)
return
/datum/language/impdraconic
req_species = SPECIES_LIZARD

/datum/language/nekomimetic
base_species = SPECIES_FELINE

/datum/language/moffic
base_species = SPECIES_MOTH


/// TGUI for selecting languages.
/datum/language_picker
/// The preferences our ui is linked to
var/datum/preferences/owner_prefs

/datum/language_picker/New(datum/preferences/prefs)
owner_prefs = prefs

/datum/language_picker/ui_close(mob/user)
owner_prefs = null
qdel(src)

/datum/language_picker/ui_state(mob/user)
return GLOB.always_state

if( \
(language_type in target_languages.blocked_languages) \
|| (LAZYLEN(language_instance.blacklist_species_on_roundstart) && (target.dna.species in language_instance.blacklist_species_on_roundstart)) \
|| (LAZYLEN(language_instance.whitelist_species_on_roundstart) && !(target.dna.species in language_instance.whitelist_species_on_roundstart)) \
)
to_chat(prefs.parent, span_notice("Your species, [target.dna.species.name], cannot learn the [value] language."))
prefs.write_preference(GLOB.preference_entries[type], NO_LANGUAGE)
/datum/language_picker/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "_LanguagePicker")
ui.open()

/datum/language_picker/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
. = ..()
if(.)
return

target.grant_language(language_type, TRUE, TRUE, LANGUAGE_PREF)
to_chat(prefs.parent, span_notice("Either due to your past or species, you know the [value] language."))
switch(action)
if("set_language")
if(params["deselecting"])
owner_prefs.write_preference(GLOB.preference_entries[/datum/preference/additional_language], NO_LANGUAGE)

else
var/datum/species/species = owner_prefs.read_preference(/datum/preference/choiced/species)
var/species_id = initial(species.id)
var/lang_path = text2path(params["langType"])
var/datum/language/lang_to_add = GLOB.language_datum_instances[lang_path]
if(!lang_to_add)
return

// Sanity checking
if(lang_to_add.base_species && lang_to_add.base_species == species_id)
to_chat(usr, span_warning("Invalid language for current species."))
return

if(lang_to_add.req_species && lang_to_add.req_species != species_id)
to_chat(usr, span_warning("Language requires another species."))
return

// Write the preference
owner_prefs.write_preference(GLOB.preference_entries[/datum/preference/additional_language], lang_path)

return TRUE

/datum/language_picker/ui_data(mob/user)
var/list/data = list()

var/datum/species/species = owner_prefs.read_preference(/datum/preference/choiced/species)
data["species"] = initial(species.id)
data["selected_lang"] = owner_prefs.read_preference(/datum/preference/additional_language)
data["trilingual"] = ("Trilingual" in owner_prefs.all_quirks)
data["pref_name"] = owner_prefs.read_preference(/datum/preference/name/real_name)

return data

/datum/language_picker/ui_static_data(mob/user)
var/list/data = list()

data["blacklisted_species"] = BLACKLISTED_SPECIES_FROM_LANGUAGES
data["base_languages"] = list()
data["bonus_languages"] = list()

for(var/found_language in GLOB.language_datum_instances)
var/datum/language/found_instance = GLOB.language_datum_instances[found_language]
var/list/lang_data = list()
lang_data["name"] = found_instance.name
lang_data["type"] = found_language

if(found_instance.base_species)
lang_data["barred_species"] = found_instance.base_species
data["base_languages"] += list(lang_data)

if(found_instance.req_species)
lang_data["allowed_species"] = found_instance.req_species
data["bonus_languages"] += list(lang_data)

return data

#undef NO_LANGUAGE
#undef BLACKLISTED_SPECIES_FROM_LANGUAGES
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,7 @@
var/datum/loadout_manager/tgui = new(usr)
tgui.ui_interact(usr)
return TRUE
if ("open_language_picker")
var/datum/language_picker/tgui = new(src)
tgui.ui_interact(usr)
return TRUE
8 changes: 0 additions & 8 deletions jollystation_modules/code/modules/language/highdraconic.dm
Original file line number Diff line number Diff line change
@@ -1,13 +1,6 @@
/// -- High draconic language. It's like Draconic, but more posh. --
// Credit to EOBgames for the initial syllables list / concept, changed and adapted for use.

/datum/language
// For preferences.
/// A list of species this language is whitelisted for on roundstart.
var/list/whitelist_species_on_roundstart
/// A list of species this language is blacklisted for on roundstart.
var/list/blacklist_species_on_roundstart

/datum/language/impdraconic
name = "High Draconic"
desc = "A distinct dialect of Draconic common to lizards born and raised in the Core Systems of the Lizard Empire."
Expand All @@ -27,7 +20,6 @@
icon = 'jollystation_modules/icons/misc/language.dmi'
icon_state = "lizardred"
default_priority = 85
whitelist_species_on_roundstart = list(/datum/species/lizard)

// Edit to the base lizard language holder - lizards can understand high draconic.
/datum/language_holder/lizard
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,19 @@
import { FeatureChoiced, FeatureDropdownInput } from "../base";
import { Feature, FeatureValueProps } from "../base";
import { Button, Stack } from "../../../../../components";

export const language: FeatureChoiced = {
name: "Language",
component: FeatureDropdownInput,
export const language: Feature<undefined, undefined> = {
name: "Access Languages",
component: (props: FeatureValueProps<undefined, undefined>) => {
const { act } = props;

return (
<Stack>
<Stack.Item>
<Button
content="Open"
onClick={() => act('open_language_picker')}
/>
</Stack.Item>
</Stack>
); },
};
89 changes: 89 additions & 0 deletions tgui/packages/tgui/interfaces/_LanguagePicker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import { useBackend } from '../backend';
import { Button, Dimmer, Section, Stack } from '../components';
import { Window } from '../layouts';

export const _LanguagePicker = (props, context) => {
const { act, data } = useBackend(context);

const {
pref_name,
species,
selected_lang,
trilingual,
blacklisted_species = [],
base_languages = [],
bonus_languages = [],
} = data;

return (
<Window
title={pref_name + "'s Languages"}
width={350}
height={300}>
<Window.Content>
{ !!trilingual && (
<Dimmer>
You cannot chose a language with the trilingual quirk.
</Dimmer>
)}
{ blacklisted_species.includes(species) && (
<Dimmer>
Your species already starts with a multitude of languages.
</Dimmer>
)}
<Section title="Base Racial Languages">
<Stack vertical>
{base_languages.map(language => (
<Stack.Item key={language}>
<Stack>
<Stack.Item grow align="left">
{language.name}
</Stack.Item>
<Stack.Item>
<Button.Checkbox
fluid
checked={language.type === selected_lang}
disabled={language.barred_species === species}
tooltip={"This language cannot be picked by the "
+ language.barred_species + " species."}
content="Select"
onClick={() => act('set_language', {
langType: language.type,
deselecting:
language.type === selected_lang })} />
</Stack.Item>
</Stack>
</Stack.Item>
))}
</Stack>
</Section>
<Section title="Unique Racial Languages">
<Stack vertical>
{bonus_languages.map(language => (
<Stack.Item key={language}>
<Stack>
<Stack.Item grow align="left">
{language.name}
</Stack.Item>
<Stack.Item>
<Button.Checkbox
fluid
checked={language.type === selected_lang}
disabled={language.allowed_species !== species}
tooltip={"This language requires the "
+ language.allowed_species + " species."}
content="Select"
onClick={() => act('set_language', {
langType: language.type,
deselecting:
language.type === selected_lang })} />
</Stack.Item>
</Stack>
</Stack.Item>
))}
</Stack>
</Section>
</Window.Content>
</Window>
);
};

0 comments on commit 15dbbe8

Please sign in to comment.