[MIRROR] Convert species, organ_data, and rlimb_data to TG (#12570)

This commit is contained in:
CHOMPStation2StaffMirrorBot
2026-03-21 14:19:04 +01:00
committed by GitHub
parent 30f5891bfa
commit 80fcaab9dc
32 changed files with 343 additions and 193 deletions
@@ -394,10 +394,11 @@
var/from_slot = ""
from_slot = "You'll hatch using your current appearance"
if(reload_slot == "From Slot" && client)
if(client.prefs.species == SPECIES_PROTEAN) // Exploit protection
if(client.prefs.read_preference(/datum/preference/choiced/species) == SPECIES_PROTEAN) // Exploit protection
to_chat(src,span_warning("You cannot copy nanoform prosthetic limbs from this species. Please try another character."))
return
var/slot_is_synth = ((O_BRAIN in client.prefs.organ_data) && client.prefs.organ_data[O_BRAIN])
var/list/organ_data = client.prefs.read_preference(/datum/preference/organ_data)
var/slot_is_synth = (organ_data && (O_BRAIN in organ_data) && organ_data[O_BRAIN])
if(slot_is_synth && !isSynthetic()) // Prevents some pretty weird situations
to_chat(src,span_warning("Cannot apply character appearance. [slot_is_synth ? "The slot's character is synthetic." : "The slot's character is organic."] Slot must match the current body's synthetic state. Please try another character."))
return
+3 -2
View File
@@ -82,10 +82,11 @@
return 1
else if(isnewplayer(player.current))
if(player.current.client && player.current.client.prefs)
var/datum/species/S = GLOB.all_species[player.current.client.prefs.species]
var/datum/species/S = GLOB.all_species[player.current.client.prefs.read_preference(/datum/preference/choiced/species)]
if(S && (S.flags & (NO_SLEEVE|NO_DNA)))
return 0
if(player.current.client.prefs.organ_data[BP_TORSO] == "cyborg") // Full synthetic. // TODO, this to issynthetic()?
var/list/organ_data = player.current.client.prefs.read_preference(/datum/preference/organ_data)
if(organ_data && organ_data[BP_TORSO] == "cyborg") // Full synthetic. // TODO, this to issynthetic()?
return 0
return 1
return 0
+7 -7
View File
@@ -50,7 +50,7 @@ GLOBAL_DATUM(job_master, /datum/controller/occupations)
var/datum/job/job = GetJob(rank)
if(!job)
return 0
if((job.minimum_character_age || job.min_age_by_species) && (player.read_preference(/datum/preference/numeric/human/age) < job.get_min_age(player.client.prefs.species, player.client.prefs.organ_data[O_BRAIN])))
if((job.minimum_character_age || job.min_age_by_species) && (player.read_preference(/datum/preference/numeric/human/age) < job.get_min_age(player.client.prefs.read_preference(/datum/preference/choiced/species), player.client.prefs.read_preference(/datum/preference/organ_data)?[O_BRAIN])))
return 0
if(jobban_isbanned(player, rank))
return 0
@@ -104,7 +104,7 @@ GLOBAL_DATUM(job_master, /datum/controller/occupations)
if(!job.player_old_enough(player.client))
Debug("FOC player not old enough, Player: [player]")
continue
if(job.minimum_character_age && (player.read_preference(/datum/preference/numeric/human/age) < job.get_min_age(player.client.prefs.species, player.client.prefs.organ_data[O_BRAIN])))
if(job.minimum_character_age && (player.read_preference(/datum/preference/numeric/human/age) < job.get_min_age(player.client.prefs.read_preference(/datum/preference/choiced/species), player.client.prefs.read_preference(/datum/preference/organ_data)?[O_BRAIN])))
Debug("FOC character not old enough, Player: [player]")
continue
//VOREStation Code Start
@@ -115,7 +115,7 @@ GLOBAL_DATUM(job_master, /datum/controller/occupations)
Debug("FOC is_job_whitelisted failed, Player: [player]")
continue
//VOREStation Code End
if(job.is_species_banned(player.client.prefs.species, player.client.prefs.organ_data[O_BRAIN]) == TRUE)
if(job.is_species_banned(player.client.prefs.read_preference(/datum/preference/choiced/species), player.client.prefs.read_preference(/datum/preference/organ_data)?[O_BRAIN]) == TRUE)
Debug("FOC character species invalid for job, Player: [player]")
continue
if(flag && !(player.client.prefs.be_special & flag))
@@ -132,10 +132,10 @@ GLOBAL_DATUM(job_master, /datum/controller/occupations)
if(!job)
continue
if((job.minimum_character_age || job.min_age_by_species) && (player.read_preference(/datum/preference/numeric/human/age) < job.get_min_age(player.client.prefs.species, player.client.prefs.organ_data[O_BRAIN])))
if((job.minimum_character_age || job.min_age_by_species) && (player.read_preference(/datum/preference/numeric/human/age) < job.get_min_age(player.client.prefs.read_preference(/datum/preference/choiced/species), player.client.prefs.read_preference(/datum/preference/organ_data)?[O_BRAIN])))
continue
if(job.is_species_banned(player.client.prefs.species, player.client.prefs.organ_data[O_BRAIN]) == TRUE)
if(job.is_species_banned(player.client.prefs.read_preference(/datum/preference/choiced/species), player.client.prefs.read_preference(/datum/preference/organ_data)?[O_BRAIN]) == TRUE)
continue
if(istype(job, GetJob(JOB_ALT_VISITOR))) // We don't want to give him assistant, that's boring! //VOREStation Edit - Visitor not Assistant
@@ -193,10 +193,10 @@ GLOBAL_DATUM(job_master, /datum/controller/occupations)
if(!V.client) continue
var/age = V.read_preference(/datum/preference/numeric/human/age)
if(age < job.get_min_age(V.client.prefs.species, V.client.prefs.organ_data[O_BRAIN])) // Nope.
if(age < job.get_min_age(V.client.prefs.read_preference(/datum/preference/choiced/species), V.client.prefs.read_preference(/datum/preference/organ_data)?[O_BRAIN])) // Nope.
continue
var/idealage = job.get_ideal_age(V.client.prefs.species, V.client.prefs.organ_data[O_BRAIN])
var/idealage = job.get_ideal_age(V.client.prefs.read_preference(/datum/preference/choiced/species), V.client.prefs.read_preference(/datum/preference/organ_data)?[O_BRAIN])
var/agediff = abs(idealage - age) // Compute the absolute difference in age from target
switch(agediff) /// If the math sucks, it's because I almost failed algebra in high school.
if(20 to INFINITY)
@@ -62,7 +62,7 @@
if(!landmark)
return
var/mob/living/carbon/human/avatar = new(get_turf(landmark), client.prefs.species)
var/mob/living/carbon/human/avatar = new(get_turf(landmark), client.prefs.read_preference(/datum/preference/choiced/species))
if(!avatar)
to_chat(src, "Something went wrong and spawning failed.")
return
@@ -133,7 +133,7 @@
return
//No whitelist
if(!is_alien_whitelisted(user.client, GLOB.all_species[user.client.prefs.species]))
if(!is_alien_whitelisted(user.client, GLOB.all_species[user.client.prefs.read_preference(/datum/preference/choiced/species)]))
to_chat(user, span_warning("You cannot use this spawnpoint to spawn as a species you are not whitelisted for!"))
return
@@ -211,7 +211,7 @@
return
//No whitelist
if(!is_alien_whitelisted(user.client, GLOB.all_species[user.client.prefs.species]))
if(!is_alien_whitelisted(user.client, GLOB.all_species[user.client.prefs.read_preference(/datum/preference/choiced/species)]))
to_chat(user, span_warning("You cannot use this spawnpoint to spawn as a species you are not whitelisted for!"))
return
@@ -39,7 +39,7 @@
if("Morph")
create_morph(user)
if("Lurker")
if(!is_alien_whitelisted(user.client, GLOB.all_species[user.client.prefs.species]))
if(!is_alien_whitelisted(user.client, GLOB.all_species[user.client.prefs.read_preference(/datum/preference/choiced/species)]))
to_chat(user, span_warning("You cannot use this spawnpoint to spawn as a species you are not whitelisted for!"))
return
create_lurker(user)
+3 -2
View File
@@ -416,9 +416,10 @@ GLOBAL_LIST_INIT(species_sound_map, list(
*/
/proc/select_default_species_sound(var/datum/preferences/pref) // Called in character setup. This is similar to check_gendered_sounds, except here we pull from the prefs.
// First, we determine if we're custom-choosing a body or if we're a base game species.
var/datum/species/valid = GLOB.all_species[pref.species]
var/pref_species = pref.read_preference(/datum/preference/choiced/species)
var/datum/species/valid = GLOB.all_species[pref_species]
if(valid.selects_bodytype == (SELECTS_BODYTYPE_CUSTOM || SELECTS_BODYTYPE_SHAPESHIFTER)) // Custom species or xenochimera handling here
valid = coalesce(GLOB.all_species[pref.custom_base], GLOB.all_species[pref.species])
valid = coalesce(GLOB.all_species[pref.custom_base], GLOB.all_species[pref_species])
// Now we start getting our sounds.
var/id_gender = pref.read_preference(/datum/preference/choiced/gender/identifying)
if(valid.gender_specific_species_sounds) // Do we have gender-specific sounds?
@@ -31,11 +31,12 @@
var/char_real_name = pref.read_preference(/datum/preference/name/real_name)
var/char_bio_gender = pref.read_preference(/datum/preference/choiced/gender/biological)
var/char_id_gender = pref.read_preference(/datum/preference/choiced/gender/identifying)
var/pref_species = pref.read_preference(/datum/preference/choiced/species)
// Re-sanitize name on join.
// Fixes being able to swap from FBP to organic before round join to be organic with numbers in name.
char_real_name = sanitize_name(char_real_name, pref.species, is_FBP())
char_real_name = sanitize_name(char_real_name, pref_species, is_FBP())
if(!char_real_name)
char_real_name = random_name(char_id_gender, pref.species)
char_real_name = random_name(char_id_gender, pref_species)
if(CONFIG_GET(flag/humans_need_surnames))
var/firstspace = findtext(char_real_name, " ")
var/name_length = length(char_real_name)
@@ -91,10 +92,12 @@
var/mob/living/carbon/human/dummy/mannequin/mannequin = get_mannequin(pref.client_ckey)
if(mannequin)
species = mannequin.species
else if(pref.species)
species = GLOB.all_species[pref.species]
else
species = GLOB.all_species[SPECIES_HUMAN]
var/pref_species = pref.read_preference(/datum/preference/choiced/species)
if(pref_species)
species = GLOB.all_species[pref_species]
else
species = GLOB.all_species[SPECIES_HUMAN]
var/list/species_stats = list(
"total_health" = species.total_health,
@@ -193,9 +196,10 @@
switch(action)
if("rename")
var/current_name = pref.read_preference(/datum/preference/name/real_name)
var/pref_species = pref.read_preference(/datum/preference/choiced/species)
var/raw_name = tgui_input_text(user, "Choose your character's name:", "Character Name", current_name, encode = FALSE)
if(!isnull(raw_name))
var/new_name = sanitize_name(raw_name, pref.species, is_FBP())
var/new_name = sanitize_name(raw_name, pref_species, is_FBP())
if(new_name)
pref.update_preference_by_type(/datum/preference/name/real_name, new_name)
return TOPIC_REFRESH
@@ -204,7 +208,7 @@
return TOPIC_NOACTION
if("random_name")
pref.update_preference_by_type(/datum/preference/name/real_name, random_name(pref.read_preference(/datum/preference/choiced/gender/identifying), pref.species))
pref.update_preference_by_type(/datum/preference/name/real_name, random_name(pref.read_preference(/datum/preference/choiced/gender/identifying), pref.read_preference(/datum/preference/choiced/species)))
return TOPIC_REFRESH
if("always_random_name")
@@ -213,9 +217,10 @@
if("nickname")
var/current_nickname = pref.read_preference(/datum/preference/name/nickname)
var/pref_species = pref.read_preference(/datum/preference/choiced/species)
var/raw_nickname = tgui_input_text(user, "Choose your character's nickname:", "Character Nickname", current_nickname, encode = FALSE)
if(!isnull(raw_nickname))
var/new_nickname = sanitize_name(raw_nickname, pref.species, is_FBP())
var/new_nickname = sanitize_name(raw_nickname, pref_species, is_FBP())
if(new_nickname)
pref.update_preference_by_type(/datum/preference/name/nickname, new_nickname)
return TOPIC_REFRESH
@@ -376,12 +381,14 @@
/datum/category_item/player_setup_item/general/basic/proc/get_genders()
var/datum/species/S
if(pref.species)
S = GLOB.all_species[pref.species]
var/pref_species = pref.read_preference(/datum/preference/choiced/species)
if(pref_species)
S = GLOB.all_species[pref_species]
else
S = GLOB.all_species[SPECIES_HUMAN]
var/list/possible_genders = S.genders
if(!pref.organ_data || pref.organ_data[BP_TORSO] != "cyborg")
var/list/organ_data = pref.read_preference(/datum/preference/organ_data)
if(!organ_data || organ_data[BP_TORSO] != "cyborg")
return possible_genders
possible_genders = possible_genders.Copy()
possible_genders |= NEUTER
@@ -12,7 +12,6 @@
pref.alternate_languages = check_list_copy(save_data["language"])
pref.extra_languages = save_data["extra_languages"]
pref.language_prefixes = save_data["language_prefixes"]
pref.species = save_data["species"]
pref.preferred_language = save_data["preflang"]
pref.language_custom_keys = check_list_copy(save_data["language_custom_keys"])
pref.runechat_color = save_data["runechat_color"]
@@ -32,10 +31,11 @@
if(!islist(pref.alternate_languages))
testing("LANGSANI: Sanitizing languages on [pref.client]'s character [char_name] because their character has no languages list")
pref.alternate_languages = list()
if(pref.species)
var/datum/species/S = GLOB.all_species[pref.species]
var/pref_species = pref.read_preference(/datum/preference/choiced/species)
if(pref_species)
var/datum/species/S = GLOB.all_species[pref_species]
if(!istype(S))
testing("LANGSANI: Failed sani on [pref.client]'s character [char_name] because their species ([pref.species]) isn't in the global list")
testing("LANGSANI: Failed sani on [pref.client]'s character [char_name] because their species ([pref_species]) isn't in the global list")
return
if(pref.alternate_languages.len > (S.num_alternate_languages + pref.extra_languages))
@@ -62,7 +62,7 @@
pref.language_prefixes -= prefix
if(isnull(pref.language_custom_keys))
pref.language_custom_keys = list()
var/datum/species/S = GLOB.all_species[pref.species]
var/datum/species/S = GLOB.all_species[pref.read_preference(/datum/preference/choiced/species)]
for(var/key in pref.language_custom_keys)
if(!pref.language_custom_keys[key])
pref.language_custom_keys.Remove(key)
@@ -76,7 +76,7 @@
var/list/languages_list = list()
var/datum/species/S = GLOB.all_species[pref.species]
var/datum/species/S = GLOB.all_species[pref.read_preference(/datum/preference/choiced/species)]
if(S.language)
UNTYPED_LIST_ADD(languages_list, list(
"name" = S.language,
@@ -108,7 +108,7 @@
return
var/mob/user = ui.user
var/datum/species/S = GLOB.all_species[pref.species]
var/datum/species/S = GLOB.all_species[pref.read_preference(/datum/preference/choiced/species)]
switch(action)
if("remove_language")
@@ -50,6 +50,7 @@
/datum/preferences/proc/get_available_styles(var/style_list)
. = list("Normal" = null)
var/pref_species = read_preference(/datum/preference/choiced/species)
for(var/path in style_list)
var/datum/sprite_accessory/instance = style_list[path]
if(!istype(instance))
@@ -58,7 +59,7 @@
continue
if(instance.ckeys_allowed && (!client || !(client.ckey in instance.ckeys_allowed)))
continue
if(instance.species_allowed && (!species || !(species in instance.species_allowed)) && (!client || !check_rights_for(client, R_ADMIN | R_EVENT | R_FUN)) && (!custom_base || !(custom_base in instance.species_allowed)))
if(instance.species_allowed && (!pref_species || !(pref_species in instance.species_allowed)) && (!client || !check_rights_for(client, R_ADMIN | R_EVENT | R_FUN)) && (!custom_base || !(custom_base in instance.species_allowed)))
continue
if(!instance.can_be_selected && (!client || !check_rights_for(client, R_HOLDER)))
continue
@@ -79,14 +80,11 @@
sort_order = 3
/datum/category_item/player_setup_item/general/body/load_character(list/save_data)
pref.species = save_data["species"]
pref.s_tone = save_data["skin_tone"]
pref.h_style = save_data["hair_style_name"]
pref.f_style = save_data["facial_style_name"]
pref.grad_style = save_data["grad_style_name"]
pref.b_type = save_data["b_type"]
pref.organ_data = check_list_copy(save_data["organ_data"])
pref.rlimb_data = check_list_copy(save_data["rlimb_data"])
pref.body_markings = check_list_copy(save_data["body_markings"])
for(var/i in pref.body_markings)
pref.body_markings[i] = check_list_copy(pref.body_markings[i])
@@ -103,14 +101,11 @@
pref.digitigrade = save_data["digitigrade"]
/datum/category_item/player_setup_item/general/body/save_character(list/save_data)
save_data["species"] = pref.species
save_data["skin_tone"] = pref.s_tone
save_data["hair_style_name"] = pref.h_style
save_data["facial_style_name"] = pref.f_style
save_data["grad_style_name"] = pref.grad_style
save_data["b_type"] = pref.b_type
save_data["organ_data"] = check_list_copy(pref.organ_data)
save_data["rlimb_data"] = check_list_copy(pref.rlimb_data)
var/list/body_markings = check_list_copy(pref.body_markings)
for(var/i in pref.body_markings)
body_markings[i] = check_list_copy(body_markings[i])
@@ -128,28 +123,18 @@
save_data["digitigrade"] = pref.digitigrade
/datum/category_item/player_setup_item/general/body/sanitize_character()
if(!pref.species || !(pref.species in GLOB.playable_species))
pref.species = SPECIES_HUMAN
pref.s_tone = sanitize_integer(pref.s_tone, -185, 34, initial(pref.s_tone))
pref.h_style = sanitize_inlist(pref.h_style, GLOB.hair_styles_list, initial(pref.h_style))
pref.f_style = sanitize_inlist(pref.f_style, GLOB.facial_hair_styles_list, initial(pref.f_style))
pref.grad_style = sanitize_inlist(pref.grad_style, GLOB.hair_gradients, initial(pref.grad_style))
pref.b_type = sanitize_text(pref.b_type, initial(pref.b_type))
if(!pref.organ_data) pref.organ_data = list()
if(!pref.rlimb_data || !islist(pref.rlimb_data)) pref.rlimb_data = list()
if(!pref.body_markings) pref.body_markings = list()
else pref.body_markings &= GLOB.body_marking_styles_list
for (var/M in pref.body_markings)
if (!islist(pref.body_markings[M]))
var/col = istext(pref.body_markings[M]) ? pref.body_markings[M] : "#000000"
pref.body_markings[M] = pref.mass_edit_marking_list(M,color=col)
for(var/limb in pref.rlimb_data)
var/key = pref.rlimb_data[limb]
if(!istext(key))
pref.rlimb_data -= limb
if(!LAZYACCESS(GLOB.all_robolimbs, key))
pref.rlimb_data -= limb
if(!pref.bgstate || !(pref.bgstate in pref.bgstate_options))
pref.bgstate = "000"
@@ -198,7 +183,9 @@
character.set_gender(pref.read_preference(/datum/preference/choiced/gender/biological))
character.synthetic = pref.species == "Protean" ? GLOB.all_robolimbs["protean"] : null //Clear the existing var. (unless protean, then switch it to the normal protean limb)
character.synthetic = pref.read_preference(/datum/preference/choiced/species) == "Protean" ? GLOB.all_robolimbs["protean"] : null //Clear the existing var. (unless protean, then switch it to the normal protean limb)
var/list/pref_organ_data = pref.read_preference(/datum/preference/organ_data)
var/list/pref_rlimb_data = pref.read_preference(/datum/preference/rlimb_data)
var/list/organs_to_edit = list()
for (var/name in list(BP_TORSO, BP_HEAD, BP_GROIN, BP_L_ARM, BP_R_ARM, BP_L_HAND, BP_R_HAND, BP_L_LEG, BP_R_LEG, BP_L_FOOT, BP_R_FOOT))
var/obj/item/organ/external/O = character.organs_by_name[name]
@@ -209,19 +196,19 @@
else
organs_to_edit.Insert(x+(O.robotic == ORGAN_NANOFORM ? 1 : 0), name)
for(var/name in organs_to_edit)
var/status = pref.organ_data[name]
var/status = pref_organ_data[name]
var/obj/item/organ/external/O = character.organs_by_name[name]
if(O)
if(status == "amputated")
O.remove_rejuv()
else if(status == "cyborg")
if(pref.rlimb_data[name])
O.robotize(pref.rlimb_data[name])
if(pref_rlimb_data[name])
O.robotize(pref_rlimb_data[name])
else
O.robotize()
for(var/name in list(O_HEART,O_EYES,O_VOICE,O_LUNGS,O_LIVER,O_KIDNEYS,O_SPLEEN,O_STOMACH,O_INTESTINE,O_BRAIN))
var/status = pref.organ_data[name]
var/status = pref_organ_data[name]
if(!status)
continue
var/obj/item/organ/I = character.internal_organs_by_name[name]
@@ -256,31 +243,26 @@
return mob_species && (mob_species.appearance_flags & flag)
/datum/category_item/player_setup_item/general/body/proc/reset_limbs()
for(var/organ in pref.organ_data)
pref.organ_data[organ] = null
while(null in pref.organ_data)
pref.organ_data -= null
for(var/organ in pref.rlimb_data)
pref.rlimb_data[organ] = null
while(null in pref.rlimb_data)
pref.rlimb_data -= null
// Reset organ and robolimb data
pref.write_preference(GLOB.preference_entries[/datum/preference/organ_data], list())
pref.write_preference(GLOB.preference_entries[/datum/preference/rlimb_data], list())
// Sanitize the name so that there aren't any numbers sticking around.
// Is this still necessary with TG conversation?
var/pref_species = pref.read_preference(/datum/preference/choiced/species)
var/current_name = pref.read_preference(/datum/preference/name/real_name)
current_name = sanitize_name(current_name, pref.species)
current_name = sanitize_name(current_name, pref_species)
if(!current_name)
current_name = random_name(pref.read_preference(/datum/preference/choiced/gender/identifying), pref.species)
current_name = random_name(pref.read_preference(/datum/preference/choiced/gender/identifying), pref_species)
pref.update_preference_by_type(/datum/preference/name/real_name, current_name)
/datum/category_item/player_setup_item/general/body/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
var/list/data = ..()
data["species"] = pref.species
data["organ_data"] = pref.organ_data
data["rlimb_data"] = pref.rlimb_data
data["species"] = pref.read_preference(/datum/preference/choiced/species)
data["organ_data"] = pref.read_preference(/datum/preference/organ_data)
data["rlimb_data"] = pref.read_preference(/datum/preference/rlimb_data)
data["s_tone"] = -pref.s_tone + 35
data["eyes_color"] = pref.read_preference(/datum/preference/color/human/eyes_color)
@@ -495,7 +477,7 @@
if(.)
return
var/datum/species/mob_species = GLOB.all_species[pref.species]
var/datum/species/mob_species = GLOB.all_species[pref.read_preference(/datum/preference/choiced/species)]
var/mob/user = ui.user
switch(action)
@@ -753,9 +735,9 @@
if(((!(setting_species.spawn_flags & SPECIES_CAN_JOIN)) || (!is_alien_whitelisted(user.client,setting_species))) && !check_rights(R_ADMIN|R_EVENT, 0) && !(setting_species.spawn_flags & SPECIES_WHITELIST_SELECTABLE))
return TOPIC_NOACTION
var/prev_species = pref.species
pref.species = params["species"]
if(prev_species != pref.species)
var/prev_species = pref.read_preference(/datum/preference/choiced/species)
pref.update_preference_by_type(/datum/preference/choiced/species, params["species"])
if(prev_species != pref.read_preference(/datum/preference/choiced/species))
if(!(pref.read_preference(/datum/preference/choiced/gender/biological) in mob_species.genders))
pref.set_biological_gender(mob_species.genders[1])
pref.custom_species = null
@@ -879,27 +861,35 @@
switch(new_state)
if("Normal")
pref.organ_data[limb] = null
pref.rlimb_data[limb] = null
var/list/organ_data = pref.read_preference(/datum/preference/organ_data)
var/list/rlimb_data = pref.read_preference(/datum/preference/rlimb_data)
organ_data[limb] = null
rlimb_data[limb] = null
if(limb == BP_TORSO) // depends on standardization
for(var/other_limb in BP_ALL - BP_TORSO)
pref.organ_data[other_limb] = null
pref.rlimb_data[other_limb] = null
organ_data[other_limb] = null
rlimb_data[other_limb] = null
for(var/internal in O_STANDARD)
pref.organ_data[internal] = null
pref.rlimb_data[internal] = null
organ_data[internal] = null
rlimb_data[internal] = null
if(third_limb)
pref.organ_data[third_limb] = null
pref.rlimb_data[third_limb] = null
organ_data[third_limb] = null
rlimb_data[third_limb] = null
pref.write_preference(GLOB.preference_entries[/datum/preference/organ_data], organ_data)
pref.write_preference(GLOB.preference_entries[/datum/preference/rlimb_data], rlimb_data)
if("Amputated")
if(limb == BP_TORSO) // depends on standardization
return
pref.organ_data[limb] = "amputated"
pref.rlimb_data[limb] = null
var/list/organ_data = pref.read_preference(/datum/preference/organ_data)
var/list/rlimb_data = pref.read_preference(/datum/preference/rlimb_data)
organ_data[limb] = "amputated"
rlimb_data[limb] = null
if(second_limb)
pref.organ_data[second_limb] = "amputated"
pref.rlimb_data[second_limb] = null
organ_data[second_limb] = "amputated"
rlimb_data[second_limb] = null
pref.write_preference(GLOB.preference_entries[/datum/preference/organ_data], organ_data)
pref.write_preference(GLOB.preference_entries[/datum/preference/rlimb_data], rlimb_data)
if("Prosthesis")
var/list/usable_manufacturers = list()
@@ -907,7 +897,7 @@
var/datum/robolimb/M = GLOB.chargen_robolimbs[company]
if(!(limb in M.parts))
continue
if(pref.species in M.species_cannot_use)
if(pref.read_preference(/datum/preference/choiced/species) in M.species_cannot_use)
continue
if(M.whitelisted_to && !(user.ckey in M.whitelisted_to))
continue
@@ -918,25 +908,29 @@
if(!choice)
return
pref.rlimb_data[limb] = choice
pref.organ_data[limb] = "cyborg"
var/list/organ_data = pref.read_preference(/datum/preference/organ_data)
var/list/rlimb_data = pref.read_preference(/datum/preference/rlimb_data)
rlimb_data[limb] = choice
organ_data[limb] = "cyborg"
if(second_limb)
pref.rlimb_data[second_limb] = choice
pref.organ_data[second_limb] = "cyborg"
if(third_limb && pref.organ_data[third_limb] == "amputated")
pref.organ_data[third_limb] = null
rlimb_data[second_limb] = choice
organ_data[second_limb] = "cyborg"
if(third_limb && organ_data[third_limb] == "amputated")
organ_data[third_limb] = null
if(limb == BP_TORSO)
for(var/other_limb in BP_ALL - BP_TORSO)
if(pref.organ_data[other_limb])
if(organ_data[other_limb])
continue
pref.organ_data[other_limb] = "cyborg"
pref.rlimb_data[other_limb] = choice
if(!pref.organ_data[O_BRAIN])
pref.organ_data[O_BRAIN] = FBP_ASSISTED
organ_data[other_limb] = "cyborg"
rlimb_data[other_limb] = choice
if(!organ_data[O_BRAIN])
organ_data[O_BRAIN] = FBP_ASSISTED
for(var/internal_organ in list(O_HEART,O_EYES))
pref.organ_data[internal_organ] = FBP_MECHANICAL
organ_data[internal_organ] = FBP_MECHANICAL
pref.write_preference(GLOB.preference_entries[/datum/preference/organ_data], organ_data)
pref.write_preference(GLOB.preference_entries[/datum/preference/rlimb_data], rlimb_data)
return TOPIC_REFRESH_UPDATE_PREVIEW
@@ -945,7 +939,8 @@
if(!(zone in O_STANDARD))
return
if(zone == O_BRAIN && pref.organ_data[BP_HEAD] != "cyborg")
var/list/organ_data = pref.read_preference(/datum/preference/organ_data)
if(zone == O_BRAIN && organ_data[BP_HEAD] != "cyborg")
to_chat(user, span_warning("You may only select a cybernetic or synthetic brain if you have a full prosthetic body."))
return
@@ -971,17 +966,18 @@
switch(new_state)
if("Normal")
pref.organ_data[zone] = null
organ_data[zone] = null
if("Assisted")
pref.organ_data[zone] = FBP_ASSISTED
organ_data[zone] = FBP_ASSISTED
if("Cybernetic")
pref.organ_data[zone] = FBP_ASSISTED
organ_data[zone] = FBP_ASSISTED
if("Mechanical")
pref.organ_data[zone] = FBP_MECHANICAL
organ_data[zone] = FBP_MECHANICAL
if("Drone")
pref.organ_data[zone] = FBP_DIGITAL
organ_data[zone] = FBP_DIGITAL
if("Positronic")
pref.organ_data[zone] = FBP_MECHANICAL
organ_data[zone] = FBP_MECHANICAL
pref.write_preference(GLOB.preference_entries[/datum/preference/organ_data], organ_data)
return TOPIC_REFRESH_UPDATE_PREVIEW
@@ -18,7 +18,7 @@
/datum/preferences/proc/get_custom_bases_for_species(var/new_species)
if (!new_species)
new_species = species
new_species = read_preference(/datum/preference/choiced/species)
var/list/choices
var/datum/species/spec = GLOB.all_species[new_species]
if (spec.selects_bodytype == SELECTS_BODYTYPE_SHAPESHIFTER)
@@ -108,14 +108,15 @@
pref.blood_reagents = sanitize_text(pref.blood_reagents, initial(pref.blood_reagents))
if(!pref.traits_cheating)
var/datum/species/S = GLOB.all_species[pref.species]
var/datum/species/S = GLOB.all_species[pref.read_preference(/datum/preference/choiced/species)]
if(S)
pref.starting_trait_points = S.trait_points
else
pref.starting_trait_points = 0
pref.max_traits = MAX_SPECIES_TRAITS
if(pref.organ_data[O_BRAIN]) //Checking if we have a synth on our hands, boys.
var/list/organ_data = pref.read_preference(/datum/preference/organ_data)
if(organ_data && organ_data[O_BRAIN]) //Checking if we have a synth on our hands, boys.
pref.dirty_synth = 1
pref.gross_meatbag = 0
else
@@ -123,11 +124,12 @@
pref.dirty_synth = 0
// Clean up positive traits
var/pref_species = pref.read_preference(/datum/preference/choiced/species)
for(var/datum/trait/path as anything in pref.pos_traits)
if(!(path in GLOB.positive_traits))
pref.pos_traits -= path
continue
if(!(pref.species == SPECIES_CUSTOM) && !(path in GLOB.everyone_traits_positive))
if(!(pref_species == SPECIES_CUSTOM) && !(path in GLOB.everyone_traits_positive))
pref.pos_traits -= path
continue
var/take_flags = initial(path.can_take)
@@ -139,7 +141,7 @@
log_world("removing [path] for not being in neutral_traits")
pref.neu_traits -= path
continue
if(!(pref.species == SPECIES_CUSTOM) && !(path in GLOB.everyone_traits_neutral))
if(!(pref_species == SPECIES_CUSTOM) && !(path in GLOB.everyone_traits_neutral))
log_world("removing [path] for not being a custom species")
pref.neu_traits -= path
continue
@@ -152,14 +154,14 @@
if(!(path in GLOB.negative_traits))
pref.neg_traits -= path
continue
if(!(pref.species == SPECIES_CUSTOM) && !(path in GLOB.everyone_traits_negative))
if(!(pref_species == SPECIES_CUSTOM) && !(path in GLOB.everyone_traits_negative))
pref.neg_traits -= path
continue
var/take_flags = initial(path.can_take)
if((pref.dirty_synth && !(take_flags & SYNTHETICS)) || (pref.gross_meatbag && !(take_flags & ORGANICS)))
pref.neg_traits -= path
var/datum/species/selected_species = GLOB.all_species[pref.species]
var/datum/species/selected_species = GLOB.all_species[pref_species]
if(selected_species.selects_bodytype)
if (!(pref.custom_base in pref.get_custom_bases_for_species()))
pref.custom_base = selected_species.default_custom_base
@@ -193,7 +195,7 @@
new_S.species_sounds = species_sounds_to_copy // Now we send our sounds over to the mob
if(pref.species == SPECIES_CUSTOM)
if(pref.read_preference(/datum/preference/choiced/species) == SPECIES_CUSTOM)
//Statistics for this would be nice
var/english_traits = english_list(new_S.traits, and_text = ";", comma_text = ";")
log_game("TRAITS [pref.client_ckey]/([character]) with: [english_traits]") //Terrible 'fake' key_name()... but they aren't in the same entity yet
@@ -201,7 +203,7 @@
/datum/category_item/player_setup_item/general/traits/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
var/list/data = ..()
var/datum/species/selected_species = GLOB.all_species[pref.species]
var/datum/species/selected_species = GLOB.all_species[pref.read_preference(/datum/preference/choiced/species)]
data["selects_bodytype"] = selected_species.selects_bodytype
data["custom_base"] = pref.custom_base
data["blood_color"] = pref.blood_color
@@ -252,7 +254,7 @@
pref.blood_color = sanitize_hexcolor(color_choice, default="#A10808")
return TOPIC_REFRESH
if("blood_reset")
var/datum/species/spec = GLOB.all_species[pref.species]
var/datum/species/spec = GLOB.all_species[pref.read_preference(/datum/preference/choiced/species)]
var/new_blood = spec.blood_color ? spec.blood_color : "#A10808"
var/choice = tgui_alert(user, "Reset blood color to species default ([new_blood])?","Reset Blood Color",list("Reset","Cancel"))
if(choice == "Reset")
@@ -295,23 +297,24 @@
var/mode = text2num(params["add_trait"])
var/list/picklist
var/list/mylist
var/pref_species_for_traits = pref.read_preference(/datum/preference/choiced/species)
switch(mode)
if(POSITIVE_MODE)
if(pref.species == SPECIES_CUSTOM)
if(pref_species_for_traits == SPECIES_CUSTOM)
picklist = GLOB.positive_traits.Copy() - pref.pos_traits
mylist = pref.pos_traits
else
picklist = GLOB.everyone_traits_positive.Copy() - pref.pos_traits
mylist = pref.pos_traits
if(NEUTRAL_MODE)
if(pref.species == SPECIES_CUSTOM)
if(pref_species_for_traits == SPECIES_CUSTOM)
picklist = GLOB.neutral_traits.Copy() - pref.neu_traits
mylist = pref.neu_traits
else
picklist = GLOB.everyone_traits_neutral.Copy() - pref.neu_traits
mylist = pref.neu_traits
if(NEGATIVE_MODE)
if(pref.species == SPECIES_CUSTOM)
if(pref_species_for_traits == SPECIES_CUSTOM)
picklist = GLOB.negative_traits.Copy() - pref.neg_traits
mylist = pref.neg_traits
else
@@ -375,11 +378,11 @@
tgui_alert_async(user, "The trait you've selected can only be taken by synthetic characters!", "Error")
return TOPIC_REFRESH
if(pref.species in instance.banned_species)
if(pref_species_for_traits in instance.banned_species)
tgui_alert_async(user, "The trait you've selected cannot be taken by the species you've chosen!", "Error")
return TOPIC_REFRESH
if( LAZYLEN(instance.allowed_species) && !(pref.species in instance.allowed_species))
if( LAZYLEN(instance.allowed_species) && !(pref_species_for_traits in instance.allowed_species))
tgui_alert_async(user, "The trait you've selected cannot be taken by the species you've chosen!", "Error")
return TOPIC_REFRESH
@@ -42,7 +42,7 @@
pref.nif_path = null //Kill!
WARNING("Loaded a NIF but it was an invalid path, [char_name]")
if (ispath(pref.nif_path, /obj/item/nif/protean) && pref.species != SPECIES_PROTEAN) //no free nifs
if (ispath(pref.nif_path, /obj/item/nif/protean) && pref.read_preference(/datum/preference/choiced/species) != SPECIES_PROTEAN) //no free nifs
pref.nif_path = null
if(ispath(pref.nif_path) && isnull(pref.nif_durability)) //How'd you lose this?
@@ -66,7 +66,7 @@ GLOBAL_LIST_EMPTY_TYPED(gear_datums, /datum/gear)
/datum/category_item/player_setup_item/loadout/loadout/proc/is_valid_gear(datum/gear/G, max_cost)
if(G.whitelisted && CONFIG_GET(flag/loadout_whitelist) != LOADOUT_WHITELIST_OFF && pref.client)
if(CONFIG_GET(flag/loadout_whitelist) == LOADOUT_WHITELIST_STRICT && (G.whitelisted != pref.species && G.whitelisted != pref.custom_base))
if(CONFIG_GET(flag/loadout_whitelist) == LOADOUT_WHITELIST_STRICT && (G.whitelisted != pref.read_preference(/datum/preference/choiced/species) && G.whitelisted != pref.custom_base))
return FALSE
if(CONFIG_GET(flag/loadout_whitelist) == LOADOUT_WHITELIST_LAX && !is_alien_whitelisted(pref.client, GLOB.all_species[G.whitelisted]))
return FALSE
@@ -113,14 +113,14 @@
"denylist_whitelist" = !is_job_whitelisted(user, job.title),
// tigercat2000 - these shouldn't exist >:(
"denylist_character_age" = FALSE,
"min_age" = job.get_min_age(pref.species, pref.organ_data[O_BRAIN]),
"min_age" = job.get_min_age(pref.read_preference(/datum/preference/choiced/species), pref.read_preference(/datum/preference/organ_data)?[O_BRAIN]),
"special_color" = "",
"selected" = 0,
"selected_title" = "",
"alt_titles" = list(),
)
if((job.minimum_character_age || job.min_age_by_species) && user.client && (user.read_preference(/datum/preference/numeric/human/age) < job.get_min_age(user.client.prefs.species, user.client.prefs.organ_data[O_BRAIN])))
if((job.minimum_character_age || job.min_age_by_species) && user.client && (user.read_preference(/datum/preference/numeric/human/age) < job.get_min_age(user.client.prefs.read_preference(/datum/preference/choiced/species), user.client.prefs.read_preference(/datum/preference/organ_data)?[O_BRAIN])))
job_data["denylist_character_age"] = TRUE
if((pref.job_civilian_low & ASSISTANT) && job.type != /datum/job/assistant)
@@ -233,7 +233,8 @@
// Checks in a really hacky way if a character's preferences say they are an FBP or not.
/datum/category_item/player_setup_item/proc/is_FBP()
if(pref.organ_data && pref.organ_data[BP_TORSO] != "cyborg")
var/list/organ_data = pref.read_preference(/datum/preference/organ_data)
if(organ_data && organ_data[BP_TORSO] != "cyborg")
return 0
return 1
@@ -241,8 +242,9 @@
/datum/category_item/player_setup_item/proc/get_FBP_type()
if(!is_FBP())
return 0 // Not a robot.
if(O_BRAIN in pref.organ_data)
switch(pref.organ_data[O_BRAIN])
var/list/organ_data = pref.read_preference(/datum/preference/organ_data)
if(organ_data && (O_BRAIN in organ_data))
switch(organ_data[O_BRAIN])
if(FBP_ASSISTED)
return PREF_FBP_CYBORG
if(FBP_MECHANICAL)
@@ -252,7 +254,8 @@
return 0 //Something went wrong!
/datum/category_item/player_setup_item/proc/get_min_age()
var/datum/species/S = GLOB.all_species[pref.species ? pref.species : "Human"]
var/pref_species = pref.read_preference(/datum/preference/choiced/species) || "Human"
var/datum/species/S = GLOB.all_species[pref_species]
if(!is_FBP())
return S.min_age // If they're not a robot, we can just use the species var.
var/FBP_type = get_FBP_type()
@@ -266,7 +269,8 @@
return S.min_age // welp
/datum/category_item/player_setup_item/proc/get_max_age()
var/datum/species/S = GLOB.all_species[pref.species ? pref.species : "Human"]
var/pref_species = pref.read_preference(/datum/preference/choiced/species) || "Human"
var/datum/species/S = GLOB.all_species[pref_species]
if(!is_FBP())
return S.max_age // If they're not a robot, we can just use the species var.
var/FBP_type = get_FBP_type()
@@ -1,7 +1,8 @@
//Minimum limit is 18
/datum/category_item/player_setup_item/get_min_age()
var/min_age = 18
var/datum/species/S = GLOB.all_species[pref.species ? pref.species : "Human"]
var/pref_species = pref.read_preference(/datum/preference/choiced/species) || "Human"
var/datum/species/S = GLOB.all_species[pref_species]
if(!is_FBP() && S.min_age > 18)
min_age = S.min_age
return min_age
+9 -10
View File
@@ -31,7 +31,6 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/grad_style = "none" //Gradient style
var/f_style = "Shaved" //Face hair type
var/s_tone = -75 //Skin tone
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() //Language prefix keys
@@ -87,8 +86,6 @@ GLOBAL_LIST_EMPTY(preferences_datums)
// maps each organ to either null(intact), "cyborg" or "amputated"
// will probably not be able to do this for head and torso ;)
var/list/organ_data = list()
var/list/rlimb_data = list()
var/list/player_alt_titles = new() // the default name of a job like JOB_MEDICAL_DOCTOR
var/list/body_markings = list() // "name" = "#rgbcolor" //VOREStation Edit: "name" = list(BP_HEAD = list("on" = <enabled>, "color" = "#rgbcolor"), BP_TORSO = ...)
@@ -159,7 +156,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
// Didn't load a character, so let's randomize
set_biological_gender(pick(MALE, FEMALE))
update_preference_by_type(/datum/preference/name/real_name, random_name(read_preference(/datum/preference/choiced/gender/identifying), species))
update_preference_by_type(/datum/preference/name/real_name, random_name(read_preference(/datum/preference/choiced/gender/identifying), read_preference(/datum/preference/choiced/species)))
b_type = RANDOM_BLOOD_TYPE
if(client)
@@ -298,10 +295,10 @@ GLOBAL_LIST_EMPTY(preferences_datums)
player_setup.sanitize_setup()
// This needs to happen before anything else becuase it sets some variables.
character.set_species(species)
character.set_species(read_preference(/datum/preference/choiced/species))
// Special Case: This references variables owned by two different datums, so do it here.
if(read_preference(/datum/preference/toggle/human/name_is_always_random))
update_preference_by_type(/datum/preference/name/real_name, random_name(read_preference(/datum/preference/choiced/gender/identifying), species))
update_preference_by_type(/datum/preference/name/real_name, random_name(read_preference(/datum/preference/choiced/gender/identifying), read_preference(/datum/preference/choiced/species)))
// Ask the preferences datums to apply their own settings to the new mob
player_setup.copy_to_mob(character)
@@ -515,6 +512,8 @@ GLOBAL_LIST_EMPTY(preferences_datums)
// Destroy/cyborgize organs and limbs.
if (convert_to_prosthetics) //should only really be run for proteans
var/list/pref_organ_data = read_preference(/datum/preference/organ_data)
var/list/pref_rlimb_data = read_preference(/datum/preference/rlimb_data)
var/list/organs_to_edit = list()
for (var/name in list(BP_TORSO, BP_HEAD, BP_GROIN, BP_L_ARM, BP_R_ARM, BP_L_HAND, BP_R_HAND, BP_L_LEG, BP_R_LEG, BP_L_FOOT, BP_R_FOOT))
var/obj/item/organ/external/O = character.organs_by_name[name]
@@ -525,16 +524,16 @@ GLOBAL_LIST_EMPTY(preferences_datums)
else
organs_to_edit.Insert(x+(O.robotic == ORGAN_NANOFORM ? 1 : 0), name)
for(var/name in organs_to_edit)
var/status = organ_data[name]
var/status = pref_organ_data[name]
var/obj/item/organ/external/O = character.organs_by_name[name]
if(O)
if(status == "amputated")
continue
else if(status == "cyborg")
O.robotize(rlimb_data[name])
O.robotize(pref_rlimb_data[name])
else
var/bodytype
var/datum/species/selected_species = GLOB.all_species[species]
var/datum/species/selected_species = GLOB.all_species[read_preference(/datum/preference/choiced/species)]
if(selected_species.selects_bodytype && custom_base) //Everyone technically has custom_base set to HUMAN, but only some species actually select it.
bodytype = custom_base
else
@@ -621,7 +620,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
character.species?.blood_color = blood_color
var/datum/species/selected_species = GLOB.all_species[species]
var/datum/species/selected_species = GLOB.all_species[read_preference(/datum/preference/choiced/species)]
var/bodytype_selected
if(selected_species.selects_bodytype && custom_base)
bodytype_selected = custom_base
@@ -11,15 +11,17 @@
/// FBP check
/datum/preference/choiced/gender/proc/is_fbp(datum/preferences/preferences)
if(!preferences?.organ_data)
var/list/organ_data = preferences?.read_preference(/datum/preference/organ_data)
if(!organ_data)
return FALSE
return preferences.organ_data[BP_TORSO] == "cyborg"
return organ_data[BP_TORSO] == "cyborg"
/// Get the list of valid bio genders for the species
/datum/preference/choiced/gender/proc/get_valid_biological_genders(datum/preferences/preferences)
var/datum/species/S
if(preferences?.species)
S = GLOB.all_species[preferences.species]
var/species_name = preferences?.read_preference(/datum/preference/choiced/species)
if(species_name)
S = GLOB.all_species[species_name]
if(!S)
S = GLOB.all_species[SPECIES_HUMAN]
var/list/possible_genders = S.genders
@@ -11,9 +11,10 @@
/// Check if the character is a Full Body Prosthetic (allows numbers in name)
/datum/preference/name/proc/is_fbp(datum/preferences/preferences)
if(!preferences?.organ_data)
var/list/organ_data = preferences?.read_preference(/datum/preference/organ_data)
if(!organ_data)
return FALSE
return preferences.organ_data[BP_TORSO] == "cyborg"
return organ_data[BP_TORSO] == "cyborg"
/datum/preference/name/is_valid(value)
if(!istext(value))
@@ -26,8 +27,8 @@
if(!istext(input))
return create_default_value()
var/species = default_species
if(preferences?.species)
species = preferences.species
if(preferences)
species = preferences.read_preference(/datum/preference/choiced/species)
var/allow_numbers = is_fbp(preferences)
var/sanitized = sanitize_name(input, species, allow_numbers)
if(!sanitized)
@@ -63,7 +64,7 @@
/datum/preference/name/real_name/create_informed_default_value(datum/preferences/preferences)
var/gender = preferences?.read_preference(/datum/preference/choiced/gender/identifying) || MALE
var/species = preferences?.species || SPECIES_HUMAN
var/species = preferences?.read_preference(/datum/preference/choiced/species) || SPECIES_HUMAN
return random_name(gender, species)
/datum/preference/name/real_name/create_random_value(datum/preferences/preferences, datum/species/current_species)
@@ -0,0 +1,38 @@
// Organ data preference for character creation
// Stores an assoc list mapping organ tags to their prosthetic/modified status.
// Values can be: null (normal), "cyborg", "amputated", FBP_ASSISTED, FBP_MECHANICAL, or FBP_DIGITAL.
/datum/preference/organ_data
savefile_key = "organ_data"
savefile_identifier = PREFERENCE_CHARACTER
category = PREFERENCE_CATEGORY_MANUALLY_RENDERED
can_randomize = FALSE
/datum/preference/organ_data/create_default_value()
return list()
/datum/preference/organ_data/pref_deserialize(input, datum/preferences/preferences)
if(!islist(input))
return list()
// Return the list directly (same reference) so in-place mutations update the cache.
return input
/datum/preference/organ_data/pref_serialize(input)
if(!islist(input))
return list()
return check_list_copy(input)
/datum/preference/organ_data/is_valid(value)
return islist(value)
/datum/preference/organ_data/apply_to_human(mob/living/carbon/human/target, value)
return // Organ application is handled by copy_to_mob in 03_body.dm
/datum/preference/organ_data/apply_to_living(mob/living/target, value)
return
/datum/preference/organ_data/apply_to_silicon(mob/living/silicon/target, value)
return
/datum/preference/organ_data/apply_to_animal(mob/living/simple_mob/target, value)
return
@@ -0,0 +1,42 @@
// Robolimb data preference for character creation
// Stores an assoc list mapping organ tags to robolimb manufacturer model names.
// Values are strings corresponding to keys in GLOB.all_robolimbs.
/datum/preference/rlimb_data
savefile_key = "rlimb_data"
savefile_identifier = PREFERENCE_CHARACTER
category = PREFERENCE_CATEGORY_MANUALLY_RENDERED
can_randomize = FALSE
/datum/preference/rlimb_data/create_default_value()
return list()
/datum/preference/rlimb_data/pref_deserialize(input, datum/preferences/preferences)
if(!islist(input))
return list()
// Sanitize: remove entries with invalid robolimb keys
for(var/limb in input)
var/key = input[limb]
if(!istext(key) || !LAZYACCESS(GLOB.all_robolimbs, key))
input -= limb
return input
/datum/preference/rlimb_data/pref_serialize(input)
if(!islist(input))
return list()
return check_list_copy(input)
/datum/preference/rlimb_data/is_valid(value)
return islist(value)
/datum/preference/rlimb_data/apply_to_human(mob/living/carbon/human/target, value)
return // Robolimb application is handled by copy_to_mob in 03_body.dm
/datum/preference/rlimb_data/apply_to_living(mob/living/target, value)
return
/datum/preference/rlimb_data/apply_to_silicon(mob/living/silicon/target, value)
return
/datum/preference/rlimb_data/apply_to_animal(mob/living/simple_mob/target, value)
return
@@ -0,0 +1,38 @@
// Species preference for character creation
// Handles the player's selected species, validated against GLOB.playable_species.
/datum/preference/choiced/species
savefile_key = "species"
savefile_identifier = PREFERENCE_CHARACTER
category = PREFERENCE_CATEGORY_MANUALLY_RENDERED
can_randomize = FALSE
priority = PREFERENCE_PRIORITY_SPECIES
/datum/preference/choiced/species/init_possible_values()
// GLOB.playable_species is populated at world init and contains all joinable species names.
return GLOB.playable_species
/datum/preference/choiced/species/create_default_value()
return SPECIES_HUMAN
/datum/preference/choiced/species/pref_deserialize(input, datum/preferences/preferences)
if(!input || !istext(input) || !(input in GLOB.playable_species))
return SPECIES_HUMAN
return input
/datum/preference/choiced/species/is_valid(value)
if(!istext(value))
return FALSE
return value in GLOB.playable_species
/datum/preference/choiced/species/apply_to_human(mob/living/carbon/human/target, value)
return // Species application is handled by copy_to via character.set_species()
/datum/preference/choiced/species/apply_to_living(mob/living/target, value)
return
/datum/preference/choiced/species/apply_to_silicon(mob/living/silicon/target, value)
return
/datum/preference/choiced/species/apply_to_animal(mob/living/simple_mob/target, value)
return
+6 -4
View File
@@ -392,8 +392,9 @@
var/use_species_name
var/datum/species/chosen_species
if(client.prefs.species)
chosen_species = GLOB.all_species[client.prefs.species]
var/pref_species = client.prefs.read_preference(/datum/preference/choiced/species)
if(pref_species)
chosen_species = GLOB.all_species[pref_species]
use_species_name = chosen_species.get_station_variant() //Only used by pariahs atm.
if(chosen_species && use_species_name)
@@ -475,8 +476,9 @@
/mob/new_player/get_species()
var/datum/species/chosen_species
if(client.prefs.species)
chosen_species = GLOB.all_species[client.prefs.species]
var/pref_species = client.prefs.read_preference(/datum/preference/choiced/species)
if(pref_species)
chosen_species = GLOB.all_species[pref_species]
if(!chosen_species)
return SPECIES_HUMAN
+5 -5
View File
@@ -27,18 +27,18 @@
to_chat(src,span_warning("You have not set your scale yet. Do this on the VORE tab in character setup."))
//Can they play?
if(!is_alien_whitelisted(src.client,GLOB.all_species[client?.prefs?.species]) && !check_rights(R_ADMIN, 0))
if(!is_alien_whitelisted(src.client,GLOB.all_species[client?.prefs?.read_preference(/datum/preference/choiced/species)]) && !check_rights(R_ADMIN, 0))
pass = FALSE
to_chat(src,span_warning("You are not allowed to spawn in as this species."))
//CHOMPEdit Begin - Check species job bans... (Only used for shadekin)
if(J.is_species_banned(client?.prefs?.species, client?.prefs?.organ_data["brain"]))
if(J.is_species_banned(client?.prefs?.read_preference(/datum/preference/choiced/species), client?.prefs?.read_preference(/datum/preference/organ_data)?[O_BRAIN]))
pass = FALSE
to_chat(src,span_warning("Your species is not permitted to take this role or job."))
//CHOMPEdit End
//Custom species checks
if (client?.prefs?.species == "Custom Species")
if (client?.prefs?.read_preference(/datum/preference/choiced/species) == SPECIES_CUSTOM)
//Didn't name it
if(!client?.prefs?.custom_species)
@@ -82,10 +82,10 @@
if(client?.prefs?.neu_traits)
for(var/T in client.prefs.neu_traits)
var/datum/trait/instance = GLOB.all_traits[T]
if(client.prefs.species in instance.banned_species)
if(client.prefs.read_preference(/datum/preference/choiced/species))
pass = FALSE
to_chat(src,span_warning("One of your traits, [instance.name], is not available for your species! Please fix this conflict and then try again."))
else if(LAZYLEN(instance.allowed_species) && !(client.prefs.species in instance.allowed_species)) //We use else if here, so as to prevent getting two errors for one trait.
else if(LAZYLEN(instance.allowed_species) && !(client.prefs.read_preference(/datum/preference/choiced/species) in instance.allowed_species)) //We use else if here, so as to prevent getting two errors for one trait.
pass = FALSE
to_chat(src,span_warning("One of your traits, [instance.name], is not available for your species! Please fix this conflict and then try again."))
//CHOMP Addition End
@@ -276,11 +276,12 @@
/datum/preferences/proc/get_valid_hairstyles(mob/user)
var/list/valid_hairstyles = list()
var/pref_species = read_preference(/datum/preference/choiced/species)
for(var/hairstyle in GLOB.hair_styles_list)
var/datum/sprite_accessory/S = GLOB.hair_styles_list[hairstyle]
if(S.name == DEVELOPER_WARNING_NAME)
continue
if(!(species in S.species_allowed) && (!custom_base || !(custom_base in S.species_allowed)))
if(!(pref_species in S.species_allowed) && (!custom_base || !(custom_base in S.species_allowed)))
continue
if(!S.can_be_selected && (!client || !check_rights_for(client, R_HOLDER)))
continue
@@ -293,6 +294,7 @@
/datum/preferences/proc/get_valid_facialhairstyles()
var/list/valid_facialhairstyles = list()
var/bio_gender = read_preference(/datum/preference/choiced/gender/biological)
var/pref_species = read_preference(/datum/preference/choiced/species)
for(var/facialhairstyle in GLOB.facial_hair_styles_list)
var/datum/sprite_accessory/S = GLOB.facial_hair_styles_list[facialhairstyle]
if(S.name == DEVELOPER_WARNING_NAME)
@@ -301,7 +303,7 @@
continue
if(bio_gender == FEMALE && S.gender == MALE)
continue
if(!(species in S.species_allowed) && (!custom_base || !(custom_base in S.species_allowed)))
if(!(pref_species in S.species_allowed) && (!custom_base || !(custom_base in S.species_allowed)))
continue
if(!S.can_be_selected && (!client || !check_rights_for(client, R_HOLDER)))
continue
+2 -1
View File
@@ -332,7 +332,8 @@
if(owner)
handle_organ_mod_special()
if(!ignore_prosthetic_prefs && owner && owner.client && owner.client.prefs && owner.client.prefs.read_preference(/datum/preference/name/real_name) == owner.real_name)
var/status = owner.client.prefs.organ_data[organ_tag]
var/list/organ_data = owner.client.prefs.read_preference(/datum/preference/organ_data)
var/status = organ_data?[organ_tag]
if(status == FBP_ASSISTED)
mechassist()
else if(status == FBP_MECHANICAL)
+4 -2
View File
@@ -667,11 +667,13 @@ This function completely restores a damaged organ to perfect condition.
if(owner && !ignore_prosthetic_prefs)
if(owner.client && owner.client.prefs && owner.client.prefs.read_preference(/datum/preference/name/real_name) == owner.real_name)
var/status = owner.client.prefs.organ_data[organ_tag]
var/list/organ_data = owner.client.prefs.read_preference(/datum/preference/organ_data)
var/status = organ_data?[organ_tag]
if(status == "amputated")
remove_rejuv()
else if(status == "cyborg")
var/robodata = owner.client.prefs.rlimb_data[organ_tag]
var/list/rlimb_data = owner.client.prefs.read_preference(/datum/preference/rlimb_data)
var/robodata = rlimb_data?[organ_tag]
if(robodata)
robotize(robodata)
else
+4 -3
View File
@@ -85,15 +85,16 @@ GLOBAL_LIST_EMPTY(active_autoresleevers)
var/client/ghost_client = ghost.client
if(!is_alien_whitelisted(ghost.client, 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.
if(!is_alien_whitelisted(ghost.client, GLOB.all_species[ghost_client?.prefs?.read_preference(/datum/preference/choiced/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, span_warning("You are not whitelisted to spawn as this species!"))
return
// CHOMPedit start
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]
var/pref_species = ghost.client.prefs.read_preference(/datum/preference/choiced/species)
if(pref_species) // In case we somehow don't have a species set here.
chosen_species = GLOB.all_species[pref_species]
if((chosen_species.spawn_flags & SPECIES_IS_WHITELISTED) || (chosen_species.spawn_flags & SPECIES_IS_RESTRICTED))
to_chat(ghost, span_warning("This species cannot be resleeved!"))
+6 -5
View File
@@ -49,7 +49,7 @@
if(!job.minimum_character_age && !job.min_age_by_species)
return TRUE
var/min_age = job.get_min_age(prefs.species, prefs.organ_data[O_BRAIN])
var/min_age = job.get_min_age(prefs.read_preference(/datum/preference/choiced/species), prefs.read_preference(/datum/preference/organ_data)?[O_BRAIN])
if(prefs.read_preference(/datum/preference/numeric/human/age) >= min_age)
return TRUE
return FALSE
@@ -81,7 +81,7 @@
continue
//CHOMPEdit Begin - Check species job bans... (Only used for shadekin)
if(job.is_species_banned(user.client.prefs.species, user.client.prefs.organ_data["brain"]))
if(job.is_species_banned(user.client.prefs.read_preference(/datum/preference/choiced/species), user.client.prefs.read_preference(/datum/preference/organ_data)?[O_BRAIN]))
continue
//CHOMPEdit End
@@ -130,13 +130,14 @@
to_chat(new_user, span_danger("The station is currently exploding. Joining would go poorly."))
return
var/datum/species/S = GLOB.all_species[new_user.client.prefs.species]
var/pref_species = new_user.client.prefs.read_preference(/datum/preference/choiced/species)
var/datum/species/S = GLOB.all_species[pref_species]
if(!is_alien_whitelisted(new_user.client, S))
tgui_alert(new_user, "You are currently not whitelisted to play [new_user.client.prefs.species].")
tgui_alert(new_user, "You are currently not whitelisted to play [pref_species].")
return 0
if(!(S.spawn_flags & SPECIES_CAN_JOIN))
tgui_alert_async(new_user,"Your current species, [new_user.client.prefs.species], is not available for play on the station.")
tgui_alert_async(new_user,"Your current species, [pref_species], is not available for play on the station.")
return 0
new_user.AttemptLateSpawn(job)
+1 -1
View File
@@ -55,7 +55,7 @@
if(confirmation_prey == "Yes" && potential_prey && src && belly_choice)
//Now we finally spawn them in!
if(!is_alien_whitelisted(potential_prey, GLOB.all_species[potential_prey.prefs.species]))
if(!is_alien_whitelisted(potential_prey, GLOB.all_species[potential_prey.prefs.read_preference(/datum/preference/choiced/species)]))
to_chat(potential_prey, span_notice("You are not whitelisted to play as currently selected character."))
to_chat(src, span_notice("Prey accepted the confirmation, but something went wrong with spawning their character."))
return
+23 -19
View File
@@ -166,35 +166,39 @@
// This basically needs to be the reverse of /datum/category_item/player_setup_item/general/body/copy_to_mob() ~Leshana
/proc/apply_organs_to_prefs(var/mob/living/carbon/human/character, var/datum/preferences/prefs)
if(!istype(character) || !character.species) return
var/list/organ_data = prefs.read_preference(/datum/preference/organ_data) || list()
var/list/rlimb_data = prefs.read_preference(/datum/preference/rlimb_data) || list()
// Checkify the limbs!
for(var/name in character.species.has_limbs)
var/obj/item/organ/external/O = character.organs_by_name[name]
if(!O)
var/obj/item/organ/external/external_organ = character.organs_by_name[name]
if(!external_organ)
if(name in GLOB.storable_amputated_organs)
prefs.organ_data[name] = "amputated"
organ_data[name] = "amputated"
else
prefs.rlimb_data.Remove(name) // Missing limb and not in the global list means default model
else if(O.robotic >= ORGAN_ROBOT)
prefs.organ_data[name] = "cyborg"
if(O.model)
prefs.rlimb_data[name] = O.model
rlimb_data.Remove(name) // Missing limb and not in the global list means default model
else if(external_organ.robotic >= ORGAN_ROBOT)
organ_data[name] = "cyborg"
if(external_organ.model)
rlimb_data[name] = external_organ.model
else
prefs.rlimb_data.Remove(name) // Missing rlimb_data entry means default model
rlimb_data.Remove(name) // Missing rlimb_data entry means default model
else
prefs.organ_data.Remove(name) // Misisng organ_data entry means normal
organ_data.Remove(name) // Misisng organ_data entry means normal
// Internal organs also
for(var/name in character.species.has_organ)
var/obj/item/organ/I = character.internal_organs_by_name[name]
if(I)
if(istype(I, /obj/item/organ/internal/mmi_holder/robot))
prefs.organ_data[name] = FBP_DIGITAL // Need a better way to detect this special type
else if(I.robotic == ORGAN_ASSISTED)
prefs.organ_data[name] = FBP_ASSISTED
else if(I.robotic >= ORGAN_ROBOT)
prefs.organ_data[name] = FBP_MECHANICAL
var/obj/item/organ/internal_organ = character.internal_organs_by_name[name]
if(internal_organ)
if(istype(internal_organ, /obj/item/organ/internal/mmi_holder/robot))
organ_data[name] = FBP_DIGITAL // Need a better way to detect this special type
else if(internal_organ.robotic == ORGAN_ASSISTED)
organ_data[name] = FBP_ASSISTED
else if(internal_organ.robotic >= ORGAN_ROBOT)
organ_data[name] = FBP_MECHANICAL
else
prefs.organ_data.Remove(name) // Missing organ_data entry means normal
organ_data.Remove(name) // Missing organ_data entry means normal
prefs.write_preference(GLOB.preference_entries[/datum/preference/organ_data], organ_data)
prefs.write_preference(GLOB.preference_entries[/datum/preference/rlimb_data], rlimb_data)
// Saves mob's current body markings state to prefs.
// This basically needs to be the reverse of /datum/category_item/player_setup_item/general/body/copy_to_mob() ~Leshana
+3
View File
@@ -2580,6 +2580,9 @@
#include "code\modules\client\preferences\migrations\19_paifile.dm"
#include "code\modules\client\preferences\types\character\gender.dm"
#include "code\modules\client\preferences\types\character\names.dm"
#include "code\modules\client\preferences\types\character\organ_data.dm"
#include "code\modules\client\preferences\types\character\rlimb_data.dm"
#include "code\modules\client\preferences\types\character\species.dm"
#include "code\modules\client\preferences\types\character\antagonism\01_basic.dm"
#include "code\modules\client\preferences\types\character\general\01_basic.dm"
#include "code\modules\client\preferences\types\character\general\03_body.dm"