diff --git a/code/__DEFINES/DNA.dm b/code/__DEFINES/DNA.dm index 9cae56645f..a057d3cf41 100644 --- a/code/__DEFINES/DNA.dm +++ b/code/__DEFINES/DNA.dm @@ -200,3 +200,8 @@ #define G_FEMALE 2 #define G_PLURAL 3 #define G_NEUTER 4 + +#define PREVIEW_PREF_JOB "Job" +#define PREVIEW_PREF_LOADOUT "Loadout" +#define PREVIEW_PREF_NAKED "Naked" +#define PREVIEW_PREF_NAKED_AROUSED "Naked - Aroused" diff --git a/code/__DEFINES/loadout.dm b/code/__DEFINES/loadout.dm index 4a52d25fb3..0b1db1ecc6 100644 --- a/code/__DEFINES/loadout.dm +++ b/code/__DEFINES/loadout.dm @@ -88,12 +88,21 @@ //the names of the customization tabs #define SETTINGS_TAB 0 -#define GAME_PREFERENCES_TAB 1 -#define APPEARANCE_TAB 2 -#define SPEECH_TAB 3 -#define LOADOUT_TAB 4 -#define CONTENT_PREFERENCES_TAB 5 -#define KEYBINDINGS_TAB 6 +#define PREFERENCES_TAB 1 +#define KEYBINDINGS_TAB 2 + +//subtabs for the character settings tab +#define GENERAL_CHAR_TAB 0 +#define BACKGROUND_CHAR_TAB 1 +#define APPEARANCE_CHAR_TAB 2 +#define MARKINGS_CHAR_TAB 3 +#define SPEECH_CHAR_TAB 4 +#define LOADOUT_CHAR_TAB 5 + +//subtabs for preferences tab +#define GAME_PREFS_TAB 0 +#define OOC_PREFS_TAB 1 +#define CONTENT_PREFS_TAB 2 //quirks #define QUIRK_POSITIVE "Positive" diff --git a/code/_globalvars/lists/loadout_categories.dm b/code/_globalvars/lists/loadout_categories.dm index 4ddb451f19..37e6145e47 100644 --- a/code/_globalvars/lists/loadout_categories.dm +++ b/code/_globalvars/lists/loadout_categories.dm @@ -1,10 +1,10 @@ GLOBAL_LIST_INIT(loadout_categories, list( - LOADOUT_CATEGORY_ACCESSORY = LOADOUT_SUBCATEGORIES_NONE, LOADOUT_CATEGORY_BACKPACK = list(LOADOUT_SUBCATEGORY_BACKPACK_GENERAL, LOADOUT_SUBCATEGORY_BACKPACK_TOYS), LOADOUT_CATEGORY_NECK = list(LOADOUT_SUBCATEGORY_NECK_GENERAL, LOADOUT_SUBCATEGORY_NECK_TIE, LOADOUT_SUBCATEGORY_NECK_SCARVES), LOADOUT_CATEGORY_MASK = LOADOUT_SUBCATEGORIES_NONE, LOADOUT_CATEGORY_HANDS = LOADOUT_SUBCATEGORIES_NONE, LOADOUT_CATEGORY_UNIFORM = list(LOADOUT_SUBCATEGORY_UNIFORM_GENERAL, LOADOUT_SUBCATEGORY_UNIFORM_JOBS, LOADOUT_SUBCATEGORY_UNIFORM_SUITS, LOADOUT_SUBCATEGORY_UNIFORM_SKIRTS, LOADOUT_SUBCATEGORY_UNIFORM_DRESSES, LOADOUT_SUBCATEGORY_UNIFORM_SWEATERS, LOADOUT_SUBCATEGORY_UNIFORM_PANTS, LOADOUT_SUBCATEGORY_UNIFORM_SHORTS), + LOADOUT_CATEGORY_ACCESSORY = LOADOUT_SUBCATEGORIES_NONE, LOADOUT_CATEGORY_SUIT = list(LOADOUT_SUBCATEGORY_SUIT_GENERAL, LOADOUT_SUBCATEGORY_SUIT_COATS, LOADOUT_SUBCATEGORY_SUIT_JACKETS, LOADOUT_SUBCATEGORY_SUIT_JOBS), LOADOUT_CATEGORY_HEAD = list(LOADOUT_SUBCATEGORY_HEAD_GENERAL, LOADOUT_SUBCATEGORY_HEAD_JOBS), LOADOUT_CATEGORY_SHOES = LOADOUT_SUBCATEGORIES_NONE, diff --git a/code/_onclick/hud/new_player.dm b/code/_onclick/hud/new_player.dm index 4eff9cd7e6..b01199c6c2 100644 --- a/code/_onclick/hud/new_player.dm +++ b/code/_onclick/hud/new_player.dm @@ -280,7 +280,7 @@ if(!.) return - hud.mymob.client.prefs.current_tab = GAME_PREFERENCES_TAB + hud.mymob.client.prefs.current_tab = PREFERENCES_TAB hud.mymob.client.prefs.ShowChoices(hud.mymob) /atom/movable/screen/lobby/button/bottom/changelog_button diff --git a/code/modules/arousal/genitals.dm b/code/modules/arousal/genitals.dm index 3e16a46526..e9fe56cadf 100644 --- a/code/modules/arousal/genitals.dm +++ b/code/modules/arousal/genitals.dm @@ -41,7 +41,8 @@ return FALSE if(!((HAS_TRAIT(owner,TRAIT_PERMABONER) && !new_state) || HAS_TRAIT(owner,TRAIT_NEVERBONER) && new_state)) aroused_state = new_state - owner.log_message("[src]'s arousal was [new_state ? "enabled" : "disabled"] due to [cause]", LOG_EMOTE) + if(cause) + owner.log_message("[src]'s arousal was [new_state ? "enabled" : "disabled"] due to [cause]", LOG_EMOTE) return aroused_state /obj/item/organ/genital/proc/update() diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 20db71a3dc..43f800b812 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -221,6 +221,10 @@ GLOBAL_LIST_EMPTY(preferences_datums) var/show_mismatched_markings = FALSE //determines whether or not the markings lists should show markings that don't match the currently selected species. Intentionally left unsaved. + var/character_settings_tab = GENERAL_CHAR_TAB + var/preferences_tab = GAME_PREFS_TAB + var/preview_pref = PREVIEW_PREF_JOB + var/no_tetris_storage = FALSE ///loadout stuff @@ -300,11 +304,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) var/list/dat = list("
") dat += "Character Settings" - dat += "Character Appearance" - dat += "Character Speech" - dat += "Loadout" - dat += "Game Preferences" - dat += "Content Preferences" + dat += "Preferences" dat += "Keybindings" if(!path) @@ -334,854 +334,930 @@ GLOBAL_LIST_EMPTY(preferences_datums) dat += "[name] " dat += "
" - dat += "

Occupation Choices

" - dat += "Set Occupation Preferences
" - if(CONFIG_GET(flag/roundstart_traits)) - dat += "

Quirk Setup

" - dat += "Configure Quirks
" - dat += "
Current Quirks: [all_quirks.len ? all_quirks.Join(", ") : "None"]
" - dat += "

Identity

" - dat += "" - dat += "
Records
" - dat += "
Security Records
" - if(length_char(security_records) <= 40) - if(!length(security_records)) - dat += "\[...\]" + dat += "
" + dat += "
" + dat += "
" - if(jobban_isbanned(user, "appearance")) - dat += "You are banned from using custom names and appearances. You can continue to adjust your characters, but you will be randomised once you join the game.
" - dat += "Random Name " - dat += "Always Random Name:[be_random_name ? "Yes" : "No"]
" + dat += "
" - dat += "[nameless ? "Default designation" : "Name"]:" - dat += "[real_name]
" - dat += "Be nameless: [nameless ? "Yes" : "No"]
" + dat += "
" + dat += "General" + dat += "Background" + dat += "Appearance" + dat += "Markings" + dat += "Speech" + dat += "Loadout" //If you change the index of this tab, change all the logic regarding tab + dat += "
" - dat += "Gender: [gender == MALE ? "Male" : (gender == FEMALE ? "Female" : (gender == PLURAL ? "Non-binary" : "Object"))]
" - dat += "Age: [age]
" - - dat += "Special Names:
" - var/old_group - for(var/custom_name_id in GLOB.preferences_custom_names) - var/namedata = GLOB.preferences_custom_names[custom_name_id] - if(!old_group) - old_group = namedata["group"] - else if(old_group != namedata["group"]) - old_group = namedata["group"] - dat += "
" - dat += "[namedata["pref_name"]]: [custom_names[custom_name_id]] " - dat += "

" - - dat += "Custom job preferences:
" - dat += "Preferred AI Core Display: [preferred_ai_core_display]
" - dat += "Preferred Security Department: [prefered_security_department]
" + dat += "" + dat += "" + if(character_settings_tab == LOADOUT_CHAR_TAB) //if loadout + //calculate your gear points from the chosen item + gear_points = CONFIG_GET(number/initial_gear_points) + var/list/chosen_gear = loadout_data["SAVE_[loadout_slot]"] + if(chosen_gear) + for(var/loadout_item in chosen_gear) + var/loadout_item_path = loadout_item[LOADOUT_ITEM] + if(loadout_item_path) + var/datum/gear/loadout_gear = text2path(loadout_item_path) + if(loadout_gear) + gear_points -= initial(loadout_gear.cost) else - dat += "[security_records]" + chosen_gear = list() + + dat += "" else - dat += "[TextPreview(security_records)]...
" + dat += "" - dat += "
Medical Records
" - if(length_char(medical_records) <= 40) - if(!length(medical_records)) - dat += "\[...\]
" - else - dat += "[medical_records]" - else - dat += "[TextPreview(medical_records)]...
" - dat += "
Hide ckey: [hide_ckey ? "Enabled" : "Disabled"]
" - dat += "
" + dat += "
Preview:

" + dat += "
" + dat += "[PREVIEW_PREF_JOB]" + dat += "[PREVIEW_PREF_LOADOUT]" + dat += "[PREVIEW_PREF_NAKED]" + dat += "
" + dat += "[PREVIEW_PREF_NAKED_AROUSED]" + dat += "
" + dat += "
" + dat += "
[gear_points] loadout point[gear_points == 1 ? "" : "s"] remaining

" + dat += "
Clear Loadout
" + dat += "
" + dat += "
Mismatched parts:

" + dat += "
[(show_mismatched_markings) ? "Enabled" : "Disabled"]
" + dat += "
" + dat += "" + dat += "
Advanced colors:

" + dat += "
[(features["color_scheme"] == ADVANCED_CHARACTER_COLORING) ? "Enabled" : "Disabled"]
" + dat += "" - //Character Appearance - if(APPEARANCE_TAB) - if(path) - var/savefile/S = new /savefile(path) - if(S) - dat += "
" - var/name - var/unspaced_slots = 0 - for(var/i=1, i<=max_save_slots, i++) - unspaced_slots++ - if(unspaced_slots > 4) - dat += "
" - unspaced_slots = 0 - S.cd = "/character[i]" - S["real_name"] >> name - if(!name) - name = "Character[i]" - dat += "[name] " - dat += "
" + dat += "" + dat += "" + dat += "" + dat += "
" + switch(character_settings_tab) + //General + if(GENERAL_CHAR_TAB) + dat += "

Occupation Choices

" + dat += "Set Occupation Preferences
" + if(CONFIG_GET(flag/roundstart_traits)) + dat += "

Quirk Setup

" + dat += "Configure Quirks
" + dat += "
Current Quirks: [all_quirks.len ? all_quirks.Join(", ") : "None"]
" + dat += "

Identity

" + dat += "" - var/matrixed_sections = accessory.matrixed_sections - if(accessory.color_src == MATRIXED && !matrixed_sections) - message_admins("Sprite Accessory Failure (customization): Accessory [accessory.type] is a matrixed item without any matrixed sections set!") - continue - else if(accessory.color_src == MATRIXED) - switch(matrixed_sections) - if(MATRIX_GREEN) //only composed of a green section - primary_feature = secondary_feature //swap primary for secondary, so it properly assigns the second colour, reserved for the green section - if(MATRIX_BLUE) - primary_feature = tertiary_feature //same as above, but the tertiary feature is for the blue section - if(MATRIX_RED_BLUE) //composed of a red and blue section - secondary_feature = tertiary_feature //swap secondary for tertiary, as blue should always be tertiary - if(MATRIX_GREEN_BLUE) //composed of a green and blue section - primary_feature = secondary_feature //swap primary for secondary, as first option is green, which is linked to the secondary - secondary_feature = tertiary_feature //swap secondary for tertiary, as second option is blue, which is linked to the tertiary - dat += "Primary Color
" - dat += "   Change
" - if((accessory.color_src == MATRIXED && (matrixed_sections == MATRIX_RED_BLUE || matrixed_sections == MATRIX_GREEN_BLUE || matrixed_sections == MATRIX_RED_GREEN || matrixed_sections == MATRIX_ALL)) || (accessory.extra && (accessory.extra_color_src == MUTCOLORS || accessory.extra_color_src == MUTCOLORS2 || accessory.extra_color_src == MUTCOLORS3))) - dat += "Secondary Color
" - dat += "   Change
" - if((accessory.color_src == MATRIXED && matrixed_sections == MATRIX_ALL) || (accessory.extra2 && (accessory.extra2_color_src == MUTCOLORS || accessory.extra2_color_src == MUTCOLORS2 || accessory.extra2_color_src == MUTCOLORS3))) - dat += "Tertiary Color
" - dat += "   Change
" + dat += "
" + if(jobban_isbanned(user, "appearance")) + dat += "You are banned from using custom names and appearances. You can continue to adjust your characters, but you will be randomised once you join the game.
" - dat += "" - else - dat += "

Left Eye Color

" - dat += "   Change" - dat += "

Right Eye Color

" - dat += "   Change
" - dat += "" - else if(use_skintones || mutant_colors) + dat += "Gender:[gender == MALE ? "Male" : (gender == FEMALE ? "Female" : (gender == PLURAL ? "Non-binary" : "Object"))]
" + dat += "Age:[age]
" + dat += "Hide ckey: [hide_ckey ? "Enabled" : "Disabled"]
" dat += "" - if(HAIR in pref_species.species_traits) + dat += "
" - dat += "

Flavor Text

" - dat += "Set Examine Text
" - if(length(features["flavor_text"]) <= MAX_FLAVOR_PREVIEW_LEN) - if(!length(features["flavor_text"])) - dat += "\[...\]" - else - dat += "[features["flavor_text"]]" - else - dat += "[TextPreview(features["flavor_text"])]...
" - dat += "

Silicon Flavor Text

" - dat += "Set Silicon Examine Text
" - if(length(features["silicon_flavor_text"]) <= MAX_FLAVOR_PREVIEW_LEN) - if(!length(features["silicon_flavor_text"])) - dat += "\[...\]" - else - dat += "[features["silicon_flavor_text"]]" - else - dat += "[TextPreview(features["silicon_flavor_text"])]...
" - dat += "

OOC notes

" - dat += "Set OOC notes
" - var/ooc_notes_len = length(features["ooc_notes"]) - if(ooc_notes_len <= MAX_FLAVOR_PREVIEW_LEN) - if(!ooc_notes_len) - dat += "\[...\]" - else - dat += "[features["ooc_notes"]]" - else - dat += "[TextPreview(features["ooc_notes"])]...
" - dat += "

Body

" - dat += "Gender:[gender == MALE ? "Male" : (gender == FEMALE ? "Female" : (gender == PLURAL ? "Non-binary" : "Object"))]
" - if(gender != NEUTER && pref_species.sexes) - dat += "Body Model:[features["body_model"] == MALE ? "Masculine" : "Feminine"]
" - dat += "Limb Modification:
" - dat += "Modify Limbs
" - for(var/modification in modified_limbs) - if(modified_limbs[modification][1] == LOADOUT_LIMB_PROSTHETIC) - dat += "[modification]: [modified_limbs[modification][2]]
" - else - dat += "[modification]: [modified_limbs[modification][1]]
" - dat += "
" - dat += "Species:[pref_species.name]
" - dat += "Custom Species Name:[custom_species ? custom_species : "None"]
" - dat += "Random Body:Randomize!
" - dat += "Always Random Body:[be_random_body ? "Yes" : "No"]
" - dat += "
Cycle background:[bgstate]
" - var/use_skintones = pref_species.use_skintones - if(use_skintones) - dat += APPEARANCE_CATEGORY_COLUMN + dat += "[nameless ? "Default designation" : "Name"]:
" + dat += "[real_name]
" + dat += "Random Name
" + dat += "Be nameless: [nameless ? "Yes" : "No"]
" + dat += "Always Random Name:[be_random_name ? "Yes" : "No"]
" - dat += "

Skin Tone

" - - dat += "[use_custom_skin_tone ? "custom:    " : skin_tone]
" - - var/mutant_colors - if((MUTCOLORS in pref_species.species_traits) || (MUTCOLORS_PARTSONLY in pref_species.species_traits)) - if(!use_skintones) - dat += APPEARANCE_CATEGORY_COLUMN - - dat += "

Advanced Coloring

" - dat += "[(features["color_scheme"] == ADVANCED_CHARACTER_COLORING) ? "Enabled" : "Disabled"]" - - dat += "

Body Colors

" - - dat += "Primary Color:
" - dat += "    Change
" - - dat += "Secondary Color:
" - dat += "    Change
" - - dat += "Tertiary Color:
" - dat += "    Change
" - mutant_colors = TRUE - - dat += "Sprite Size: [features["body_size"]*100]%
" - - if(!(NOEYES in pref_species.species_traits)) - dat += "

Eye Type

" - dat += "[eye_type]
" - if((EYECOLOR in pref_species.species_traits)) - if(!use_skintones && !mutant_colors) - dat += APPEARANCE_CATEGORY_COLUMN - if(left_eye_color != right_eye_color) - split_eye_colors = TRUE - dat += "

Heterochromia

" - dat += "[split_eye_colors ? "Enabled" : "Disabled"]" - if(!split_eye_colors) - dat += "

Eye Color

" - dat += "    Change" - dat += "
" + dat += "Special Names:
" + var/old_group + for(var/custom_name_id in GLOB.preferences_custom_names) + var/namedata = GLOB.preferences_custom_names[custom_name_id] + if(!old_group) + old_group = namedata["group"] + else if(old_group != namedata["group"]) + old_group = namedata["group"] + dat += "
" + dat += "[namedata["pref_name"]]: [custom_names[custom_name_id]] " + dat += "

" - dat += APPEARANCE_CATEGORY_COLUMN + dat += "Custom job preferences:
" + dat += "Preferred AI Core Display: [preferred_ai_core_display]
" + dat += "Preferred Security Department: [prefered_security_department]
" - dat += "

Hair Style

" + dat += "
" + //Character background + if(BACKGROUND_CHAR_TAB) + dat += "" - //Mutant stuff - var/mutant_category = 0 - - dat += APPEARANCE_CATEGORY_COLUMN - dat += "

Show mismatched markings

" - dat += "[show_mismatched_markings ? "Yes" : "No"]" - mutant_category++ - if(mutant_category >= MAX_MUTANT_ROWS) //just in case someone sets the max rows to 1 or something dumb like that - dat += "" - mutant_category = 0 - - // rp marking selection - // assume you can only have mam markings or regular markings or none, never both - var/marking_type - if(parent.can_have_part("mam_body_markings")) - marking_type = "mam_body_markings" - if(marking_type) - dat += APPEARANCE_CATEGORY_COLUMN - dat += "

[GLOB.all_mutant_parts[marking_type]]

" // give it the appropriate title for the type of marking - dat += "Add marking" - // list out the current markings you have - if(length(features[marking_type])) - dat += "
" - dat += "[hair_style]" - dat += "< >
" - dat += "    Change
" - - dat += "

Facial Hair Style

" - - dat += "[facial_hair_style]" - dat += "< >
" - dat += "    Change
" - - dat += "

Hair Gradient

" - - dat += "[grad_style]" - dat += "< >
" - dat += "    Change
" - - dat += "
" - var/list/markings = features[marking_type] - if(!islist(markings)) - // something went terribly wrong - markings = list() - var/list/reverse_markings = reverseList(markings) - for(var/list/marking_list in reverse_markings) - var/marking_index = markings.Find(marking_list) // consider changing loop to go through indexes over lists instead of using Find here - var/limb_value = marking_list[1] - var/actual_name = GLOB.bodypart_names[num2text(limb_value)] // get the actual name from the bitflag representing the part the marking is applied to - var/color_marking_dat = "" - var/number_colors = 1 - var/datum/sprite_accessory/mam_body_markings/S = GLOB.mam_body_markings_list[marking_list[2]] - var/matrixed_sections = S.covered_limbs[actual_name] - if(S && matrixed_sections) - // if it has nothing initialize it to white - if(length(marking_list) == 2) - var/first = "#FFFFFF" - var/second = "#FFFFFF" - var/third = "#FFFFFF" - if(features["mcolor"]) - first = "#[features["mcolor"]]" - if(features["mcolor2"]) - second = "#[features["mcolor2"]]" - if(features["mcolor3"]) - third = "#[features["mcolor3"]]" - marking_list += list(list(first, second, third)) // just assume its 3 colours if it isnt it doesnt matter we just wont use the other values - // index magic - var/primary_index = 1 - var/secondary_index = 2 - var/tertiary_index = 3 - switch(matrixed_sections) - if(MATRIX_GREEN) - primary_index = 2 - if(MATRIX_BLUE) - primary_index = 3 - if(MATRIX_RED_BLUE) - secondary_index = 2 - if(MATRIX_GREEN_BLUE) - primary_index = 2 - secondary_index = 3 - - // we know it has one matrixed section at minimum - color_marking_dat += "   " - // if it has a second section, add it - if(matrixed_sections == MATRIX_RED_BLUE || matrixed_sections == MATRIX_GREEN_BLUE || matrixed_sections == MATRIX_RED_GREEN || matrixed_sections == MATRIX_ALL) - color_marking_dat += "   " - number_colors = 2 - // if it has a third section, add it - if(matrixed_sections == MATRIX_ALL) - color_marking_dat += "   " - number_colors = 3 - color_marking_dat += " Change
" - dat += "" - dat += "
[marking_list[2]] - [actual_name] ˄ ˅ X [color_marking_dat]
" - - for(var/mutant_part in GLOB.all_mutant_parts) - if(mutant_part == "mam_body_markings") - continue - if(parent.can_have_part(mutant_part)) - if(!mutant_category) - dat += APPEARANCE_CATEGORY_COLUMN - dat += "

[GLOB.all_mutant_parts[mutant_part]]

" - dat += "[features[mutant_part]]" - var/color_type = GLOB.colored_mutant_parts[mutant_part] //if it can be coloured, show the appropriate button - if(color_type) - dat += "    Change
" + dat += "

Flavor Text

" + dat += "Set Examine Text
" + if(length(features["flavor_text"]) <= MAX_FLAVOR_PREVIEW_LEN) + if(!length(features["flavor_text"])) + dat += "\[...\]" + else + dat += "[features["flavor_text"]]" else - if(features["color_scheme"] == ADVANCED_CHARACTER_COLORING) //advanced individual part colouring system - //is it matrixed or does it have extra parts to be coloured? - var/find_part = features[mutant_part] || pref_species.mutant_bodyparts[mutant_part] - var/find_part_list = GLOB.mutant_reference_list[mutant_part] - if(find_part && find_part != "None" && find_part_list) - var/datum/sprite_accessory/accessory = find_part_list[find_part] - if(accessory) - if(accessory.color_src == MATRIXED || accessory.color_src == MUTCOLORS || accessory.color_src == MUTCOLORS2 || accessory.color_src == MUTCOLORS3) //mutcolors1-3 are deprecated now, please don't rely on these in the future - var/mutant_string = accessory.mutant_part_string - var/primary_feature = "[mutant_string]_primary" - var/secondary_feature = "[mutant_string]_secondary" - var/tertiary_feature = "[mutant_string]_tertiary" - if(!features[primary_feature]) - features[primary_feature] = features["mcolor"] - if(!features[secondary_feature]) - features[secondary_feature] = features["mcolor2"] - if(!features[tertiary_feature]) - features[tertiary_feature] = features["mcolor3"] + dat += "[TextPreview(features["flavor_text"])]..." + dat += "

Silicon Flavor Text

" + dat += "Set Silicon Examine Text
" + if(length(features["silicon_flavor_text"]) <= MAX_FLAVOR_PREVIEW_LEN) + if(!length(features["silicon_flavor_text"])) + dat += "\[...\]" + else + dat += "[features["silicon_flavor_text"]]" + else + dat += "[TextPreview(features["silicon_flavor_text"])]..." + dat += "

OOC notes

" + dat += "Set OOC notes
" + var/ooc_notes_len = length(features["ooc_notes"]) + if(ooc_notes_len <= MAX_FLAVOR_PREVIEW_LEN) + if(!ooc_notes_len) + dat += "\[...\]" + else + dat += "[features["ooc_notes"]]" + else + dat += "[TextPreview(features["ooc_notes"])]..." + dat += "
" + dat += "

Records

" + dat += "Security Records
" + if(length_char(security_records) <= 40) + if(!length(security_records)) + dat += "\[...\]" + else + dat += "[security_records]" + else + dat += "[TextPreview(security_records)]..." - mutant_category++ - if(mutant_category >= MAX_MUTANT_ROWS) + dat += "
Medical Records
" + if(length_char(medical_records) <= 40) + if(!length(medical_records)) + dat += "\[...\]" + else + dat += "[medical_records]" + else + dat += "[TextPreview(medical_records)]..." + dat += "
" + //Character Appearance + if(APPEARANCE_CHAR_TAB) + dat += "" + + var/use_skintones = pref_species.use_skintones + if(use_skintones) + dat += APPEARANCE_CATEGORY_COLUMN + + dat += "

Skin Tone

" + + dat += "[use_custom_skin_tone ? "custom: [skin_tone]" : skin_tone]
" + + var/mutant_colors + if((MUTCOLORS in pref_species.species_traits) || (MUTCOLORS_PARTSONLY in pref_species.species_traits)) + if(!use_skintones) + dat += APPEARANCE_CATEGORY_COLUMN + + dat += "

Body Colors

" + + dat += "Primary Color:
" + dat += "#[features["mcolor"]]Change
" + + dat += "Secondary Color:
" + dat += "#[features["mcolor2"]]Change
" + + dat += "Tertiary Color:
" + dat += "#[features["mcolor3"]]Change
" + mutant_colors = TRUE + + dat += "Sprite Size:[features["body_size"]*100]%
" + + if(!(NOEYES in pref_species.species_traits)) + dat += "

Eye Type

" + dat += "[eye_type]
" + if((EYECOLOR in pref_species.species_traits)) + if(!use_skintones && !mutant_colors) + dat += APPEARANCE_CATEGORY_COLUMN + if(left_eye_color != right_eye_color) + split_eye_colors = TRUE + dat += "

Heterochromia

" + dat += "[split_eye_colors ? "Enabled" : "Disabled"]" + if(!split_eye_colors) + dat += "

Eye Color

" + dat += "#[left_eye_color]Change" + else + dat += "

Left Eye Color

" + dat += "#[left_eye_color]Change" + dat += "

Right Eye Color

" + dat += "#[right_eye_color]Change
" + + if(HAIR in pref_species.species_traits) + + dat += APPEARANCE_CATEGORY_COLUMN + + dat += "

Hair Style

" + + dat += "[hair_style]" + dat += "<>
" + dat += "#[hair_color]Change
" + + dat += "

Facial Hair Style

" + + dat += "[facial_hair_style]" + dat += "<>
" + dat += "#[facial_hair_color]Change
" + + dat += "

Hair Gradient

" + + dat += "[grad_style]" + dat += "<>
" + dat += "#[grad_color]Change
" + + dat += "" + + //Mutant stuff + var/mutant_category = 0 + + for(var/mutant_part in GLOB.all_mutant_parts) + if(mutant_part == "mam_body_markings") + continue + if(parent.can_have_part(mutant_part)) + if(!mutant_category) + dat += APPEARANCE_CATEGORY_COLUMN + dat += "

[GLOB.all_mutant_parts[mutant_part]]

" + dat += "[features[mutant_part]]" + var/color_type = GLOB.colored_mutant_parts[mutant_part] //if it can be coloured, show the appropriate button + if(color_type) + dat += "#[features[color_type]]Change
" + else + if(features["color_scheme"] == ADVANCED_CHARACTER_COLORING) //advanced individual part colouring system + //is it matrixed or does it have extra parts to be coloured? + var/find_part = features[mutant_part] || pref_species.mutant_bodyparts[mutant_part] + var/find_part_list = GLOB.mutant_reference_list[mutant_part] + if(find_part && find_part != "None" && find_part_list) + var/datum/sprite_accessory/accessory = find_part_list[find_part] + if(accessory) + if(accessory.color_src == MATRIXED || accessory.color_src == MUTCOLORS || accessory.color_src == MUTCOLORS2 || accessory.color_src == MUTCOLORS3) //mutcolors1-3 are deprecated now, please don't rely on these in the future + var/mutant_string = accessory.mutant_part_string + var/primary_feature = "[mutant_string]_primary" + var/secondary_feature = "[mutant_string]_secondary" + var/tertiary_feature = "[mutant_string]_tertiary" + if(!features[primary_feature]) + features[primary_feature] = features["mcolor"] + if(!features[secondary_feature]) + features[secondary_feature] = features["mcolor2"] + if(!features[tertiary_feature]) + features[tertiary_feature] = features["mcolor3"] + + var/matrixed_sections = accessory.matrixed_sections + if(accessory.color_src == MATRIXED && !matrixed_sections) + message_admins("Sprite Accessory Failure (customization): Accessory [accessory.type] is a matrixed item without any matrixed sections set!") + continue + else if(accessory.color_src == MATRIXED) + switch(matrixed_sections) + if(MATRIX_GREEN) //only composed of a green section + primary_feature = secondary_feature //swap primary for secondary, so it properly assigns the second colour, reserved for the green section + if(MATRIX_BLUE) + primary_feature = tertiary_feature //same as above, but the tertiary feature is for the blue section + if(MATRIX_RED_BLUE) //composed of a red and blue section + secondary_feature = tertiary_feature //swap secondary for tertiary, as blue should always be tertiary + if(MATRIX_GREEN_BLUE) //composed of a green and blue section + primary_feature = secondary_feature //swap primary for secondary, as first option is green, which is linked to the secondary + secondary_feature = tertiary_feature //swap secondary for tertiary, as second option is blue, which is linked to the tertiary + dat += "Primary Color
" + dat += "#[features[primary_feature]]Change
" + if((accessory.color_src == MATRIXED && (matrixed_sections == MATRIX_RED_BLUE || matrixed_sections == MATRIX_GREEN_BLUE || matrixed_sections == MATRIX_RED_GREEN || matrixed_sections == MATRIX_ALL)) || (accessory.extra && (accessory.extra_color_src == MUTCOLORS || accessory.extra_color_src == MUTCOLORS2 || accessory.extra_color_src == MUTCOLORS3))) + dat += "Secondary Color
" + dat += "#[features[secondary_feature]]Change
" + if((accessory.color_src == MATRIXED && matrixed_sections == MATRIX_ALL) || (accessory.extra2 && (accessory.extra2_color_src == MUTCOLORS || accessory.extra2_color_src == MUTCOLORS2 || accessory.extra2_color_src == MUTCOLORS3))) + dat += "Tertiary Color
" + dat += "#[features[tertiary_feature]]Change
" + + mutant_category++ + if(mutant_category >= MAX_MUTANT_ROWS) + dat += "" + mutant_category = 0 + + if(length(pref_species.allowed_limb_ids)) + if(!chosen_limb_id || !(chosen_limb_id in pref_species.allowed_limb_ids)) + chosen_limb_id = pref_species.limbs_id || pref_species.id + if(!mutant_category) + dat += APPEARANCE_CATEGORY_COLUMN + dat += "

Body sprite

" + dat += "[chosen_limb_id]" + + if(mutant_category) dat += "" mutant_category = 0 - if(length(pref_species.allowed_limb_ids)) - if(!chosen_limb_id || !(chosen_limb_id in pref_species.allowed_limb_ids)) - chosen_limb_id = pref_species.limbs_id || pref_species.id - dat += "

Body sprite

" - dat += "[chosen_limb_id]" + dat += "
" + + dat += "

Body

" + dat += "Gender:[gender == MALE ? "Male" : (gender == FEMALE ? "Female" : (gender == PLURAL ? "Non-binary" : "Object"))]
" + if(gender != NEUTER && pref_species.sexes) + dat += "Body Model:[features["body_model"] == MALE ? "Masculine" : "Feminine"]
" + dat += "Limb Modification:
" + dat += "Modify Limbs
" + for(var/modification in modified_limbs) + if(modified_limbs[modification][1] == LOADOUT_LIMB_PROSTHETIC) + dat += "[modification]: [modified_limbs[modification][2]]
" + else + dat += "[modification]: [modified_limbs[modification][1]]
" + dat += "
" + dat += "Species:[pref_species.name]
" + dat += "Custom Species Name:[custom_species ? custom_species : "None"]
" + dat += "Random Body:Randomize!
" + dat += "Always Random Body:[be_random_body ? "Yes" : "No"]
" + dat += "
Cycle background:[bgstate]
" + + dat += "
" - if(mutant_category) - dat += "" - mutant_category = 0 + dat += "" + dat += "" - dat += "
" + dat += "

Clothing & Equipment

" + dat += "Underwear:[underwear]" + if(GLOB.underwear_list[underwear]?.has_color) + dat += "Underwear Color: #[undie_color] Change
" + dat += "Undershirt:[undershirt]" + if(GLOB.undershirt_list[undershirt]?.has_color) + dat += "Undershirt Color: #[shirt_color] Change
" + dat += "Socks:[socks]" + if(GLOB.socks_list[socks]?.has_color) + dat += "Socks Color: #[socks_color] Change
" + dat += "Backpack:[backbag]" + dat += "Jumpsuit:
[jumpsuit_style]
" + if((HAS_FLESH in pref_species.species_traits) || (HAS_BONE in pref_species.species_traits)) + dat += "
Temporal Scarring:
[(persistent_scars) ? "Enabled" : "Disabled"]" + dat += "Clear scar slots" + dat += "Uplink Location:[uplink_spawn_loc]" + dat += "
" + dat += APPEARANCE_CATEGORY_COLUMN - dat += "" - dat += "" - - dat +="" - dat += APPEARANCE_CATEGORY_COLUMN - dat += "

Breasts

" - dat += "[features["has_breasts"] == TRUE ? "Yes" : "No"]" - if(features["has_breasts"]) - if(pref_species.use_skintones && features["genitals_use_skintone"] == TRUE) - dat += "Color:
" - dat += "   (Skin tone overriding)
" - else - dat += "Color:
" - dat += "   Change
" - dat += "Cup Size:[features["breasts_size"]]" - dat += "Breasts Shape:[features["breasts_shape"]]" - dat += "Breasts Visibility:[features["breasts_visibility"]]" - dat += "Lactates:[features["breasts_producing"] == TRUE ? "Yes" : "No"]" - dat += "" - dat += APPEARANCE_CATEGORY_COLUMN - dat += "

Butt

" - dat += "[features["has_butt"] == TRUE ? "Yes" : "No"]" - if(features["has_butt"]) - if(pref_species.use_skintones && features["genitals_use_skintone"] == TRUE) - dat += "Color:
" - dat += "   (Skin tone overriding)
" - else - dat += "Color:
" - dat += "   Change
" - dat += "Butt Size:[features["butt_size"]]" - dat += "Butt Visibility:[features["butt_visibility"]]" - dat += "" - dat += "" - dat += "
" - dat += "

Clothing & Equipment

" - dat += "Underwear:[underwear]" - if(GLOB.underwear_list[underwear]?.has_color) - dat += "Underwear Color:     Change
" - dat += "Undershirt:[undershirt]" - if(GLOB.undershirt_list[undershirt]?.has_color) - dat += "Undershirt Color:     Change
" - dat += "Socks:[socks]" - if(GLOB.socks_list[socks]?.has_color) - dat += "Socks Color:     Change
" - dat += "Backpack:[backbag]" - dat += "Jumpsuit:
[jumpsuit_style]
" - if((HAS_FLESH in pref_species.species_traits) || (HAS_BONE in pref_species.species_traits)) - dat += "
Temporal Scarring:
[(persistent_scars) ? "Enabled" : "Disabled"]" - dat += "Clear scar slots" - dat += "Uplink Location:[uplink_spawn_loc]" - dat += "
" - if(NOGENITALS in pref_species.species_traits) - dat += "Your species ([pref_species.name]) does not support genitals!
" - else - if(pref_species.use_skintones) - dat += "Genitals use skintone:[features["genitals_use_skintone"] == TRUE ? "Yes" : "No"]" - dat += "

Penis

" - dat += "[features["has_cock"] == TRUE ? "Yes" : "No"]" - if(features["has_cock"]) - if(pref_species.use_skintones && features["genitals_use_skintone"] == TRUE) - dat += "Penis Color:
" - dat += "   (Skin tone overriding)
" + if(NOGENITALS in pref_species.species_traits) + dat += "Your species ([pref_species.name]) does not support genitals!
" else - dat += "Penis Color:
" - dat += "    Change
" - var/tauric_shape = FALSE - if(features["cock_taur"]) - var/datum/sprite_accessory/penis/P = GLOB.cock_shapes_list[features["cock_shape"]] - if(P.taur_icon && parent.can_have_part("taur")) - var/datum/sprite_accessory/taur/T = GLOB.taur_list[features["taur"]] - if(T.taur_mode & P.accepted_taurs) - tauric_shape = TRUE - dat += "Penis Shape: [features["cock_shape"]][tauric_shape ? " (Taur)" : ""]" - dat += "Penis Length: [features["cock_length"]] inch(es)" - dat += "Penis Visibility:[features["cock_visibility"]]" - dat += "Has Testicles:[features["has_balls"] == TRUE ? "Yes" : "No"]" - if(features["has_balls"]) - if(pref_species.use_skintones && features["genitals_use_skintone"] == TRUE) - dat += "Testicles Color:
" - dat += "   (Skin tone overriding)
" - else - dat += "Testicles Color:
" - dat += "    Change
" - dat += "Testicles Shape: [features["balls_shape"]]" - dat += "Testicles Visibility:[features["balls_visibility"]]" - dat += APPEARANCE_CATEGORY_COLUMN - dat += "

Vagina

" - dat += "[features["has_vag"] == TRUE ? "Yes" : "No"]" - if(features["has_vag"]) - dat += "Vagina Type: [features["vag_shape"]]" - if(pref_species.use_skintones && features["genitals_use_skintone"] == TRUE) - dat += "Vagina Color:
" - dat += "   (Skin tone overriding)
" - else - dat += "Vagina Color:
" - dat += "    Change
" - dat += "Vagina Visibility:[features["vag_visibility"]]" - dat += "Has Womb:[features["has_womb"] == TRUE ? "Yes" : "No"]" - dat += "
" - - if(SPEECH_TAB) - if(path) - var/savefile/S = new /savefile(path) - if(S) - dat += "
" - var/name - var/unspaced_slots = 0 - for(var/i=1, i<=max_save_slots, i++) - unspaced_slots++ - if(unspaced_slots > 4) - dat += "
" - unspaced_slots = 0 - S.cd = "/character[i]" - S["real_name"] >> name - if(!name) - name = "Character[i]" - dat += "[name] " - dat += "
" - - dat += "" - dat += "" - dat += "
" - dat += "

Speech preferences

" - dat += "Custom Speech Verb:
" - dat += "[custom_speech_verb]
" - dat += "Custom Tongue:
" - dat += "[custom_tongue]
" - dat += "Additional Language
" - dat += "[additional_language]
" - dat += "
" - dat += "

Vocal Bark preferences

" - var/datum/bark/B = GLOB.bark_list[bark_id] - dat += "Vocal Bark Sound:
" - dat += "[B ? initial(B.name) : "INVALID"]
" - dat += "Vocal Bark Speed: [bark_speed]
" - dat += "Vocal Bark Pitch: [bark_pitch]
" - dat += "Vocal Bark Variance: [bark_variance]
" - dat += "
Preview Bark
" - dat += "
" - - if(GAME_PREFERENCES_TAB) // Game Preferences - dat += "" - if(user.client.holder) - dat +="" - - dat +="" - dat += "
" - dat += "

General Settings

" - dat += "UI Style: [UI_style]
" - dat += "Outline: [outline_enabled ? "Enabled" : "Disabled"]
" - dat += "Outline Color: [outline_color ? "" : "Theme-based (null)"]    Change
" - dat += "Screentip: [screentip_pref]
" - dat += "Screentip Color:     Change
" - dat += "\ - Screentip context with images: [screentip_images ? "Allowed" : "Disallowed"]
" - dat += "tgui Monitors: [(tgui_lock) ? "Primary" : "All"]
" - dat += "tgui Style: [(tgui_fancy) ? "Fancy" : "No Frills"]
" - dat += "Show Runechat Chat Bubbles: [chat_on_map ? "Enabled" : "Disabled"]
" - dat += "Runechat message char limit: [max_chat_length]
" - dat += "See Runechat for non-mobs: [see_chat_non_mob ? "Enabled" : "Disabled"]
" - dat += "
" - dat += "Action Buttons: [(buttons_locked) ? "Locked In Place" : "Unlocked"]
" - dat += "
" - dat += "PDA Color:     Change
" - dat += "PDA Style: [pda_style]
" - dat += "PDA Reskin: [pda_skin]
" - dat += "
" - dat += "Ghost Ears: [(chat_toggles & CHAT_GHOSTEARS) ? "All Speech" : "Nearest Creatures"]
" - dat += "Ghost Radio: [(chat_toggles & CHAT_GHOSTRADIO) ? "All Messages":"No Messages"]
" - dat += "Ghost Sight: [(chat_toggles & CHAT_GHOSTSIGHT) ? "All Emotes" : "Nearest Creatures"]
" - dat += "Ghost Whispers: [(chat_toggles & CHAT_GHOSTWHISPER) ? "All Speech" : "Nearest Creatures"]
" - dat += "Ghost PDA: [(chat_toggles & CHAT_GHOSTPDA) ? "All Messages" : "Nearest Creatures"]
" - dat += "Window Flashing: [(windowflashing) ? "Enabled":"Disabled"]
" - dat += "
" - dat += "Play Admin MIDIs: [(toggles & SOUND_MIDI) ? "Enabled":"Disabled"]
" - dat += "Play Lobby Music: [(toggles & SOUND_LOBBY) ? "Enabled":"Disabled"]
" - dat += "See Pull Requests: [(chat_toggles & CHAT_PULLR) ? "Enabled":"Disabled"]
" - dat += "
" - if(user.client) - if(unlock_content) - dat += "BYOND Membership Publicity: [(toggles & MEMBER_PUBLIC) ? "Public" : "Hidden"]
" - if(unlock_content || check_rights_for(user.client, R_ADMIN)) - dat += "OOC Color:     Change
" - dat += "Antag OOC Color:     Change
" - - dat += "
" - dat += "

Admin Settings

" - dat += "Adminhelp Sounds: [(toggles & SOUND_ADMINHELP)?"Enabled":"Disabled"]
" - dat += "Announce Login: [(toggles & ANNOUNCE_LOGIN)?"Enabled":"Disabled"]
" - dat += "
" - dat += "Combo HUD Lighting: [(toggles & COMBOHUD_LIGHTING)?"Full-bright":"No Change"]
" - dat += "
" - - //deadmin - dat += "

Deadmin While Playing

" - if(CONFIG_GET(flag/auto_deadmin_players)) - dat += "Always Deadmin: FORCED
" - else - dat += "Always Deadmin: [(deadmin & DEADMIN_ALWAYS)?"Enabled":"Disabled"]
" - if(!(deadmin & DEADMIN_ALWAYS)) - dat += "
" - if(!CONFIG_GET(flag/auto_deadmin_antagonists)) - dat += "As Antag: [(deadmin & DEADMIN_ANTAGONIST)?"Deadmin":"Keep Admin"]
" - else - dat += "As Antag: FORCED
" - - if(!CONFIG_GET(flag/auto_deadmin_heads)) - dat += "As Command: [(deadmin & DEADMIN_POSITION_HEAD)?"Deadmin":"Keep Admin"]
" - else - dat += "As Command: FORCED
" - - if(!CONFIG_GET(flag/auto_deadmin_security)) - dat += "As Security: [(deadmin & DEADMIN_POSITION_SECURITY)?"Deadmin":"Keep Admin"]
" - else - dat += "As Security: FORCED
" - - if(!CONFIG_GET(flag/auto_deadmin_silicons)) - dat += "As Silicon: [(deadmin & DEADMIN_POSITION_SILICON)?"Deadmin":"Keep Admin"]
" - else - dat += "As Silicon: FORCED
" - dat += "
" - dat += "

Citadel Preferences

" //Because fuck me if preferences can't be fucking modularized and expected to update in a reasonable timeframe. - dat += "Widescreen: [widescreenpref ? "Enabled ([CONFIG_GET(string/default_view)])" : "Disabled (15x15)"]
" - dat += "Long strip menu: [long_strip_menu ? "Enabled" : "Disabled"]
" - dat += "Auto stand: [autostand ? "Enabled" : "Disabled"]
" - dat += "Auto OOC: [auto_ooc ? "Enabled" : "Disabled"]
" - dat += "Force Slot Storage HUD: [no_tetris_storage ? "Enabled" : "Disabled"]
" - dat += "Screen Shake: [(screenshake==100) ? "Full" : ((screenshake==0) ? "None" : "[screenshake]")]
" - if (user && user.client && !user.client.prefs.screenshake==0) - dat += "Damage Screen Shake: [(damagescreenshake==1) ? "On" : ((damagescreenshake==0) ? "Off" : "Only when down")]
" - dat += "Recoil Screen Push: [(recoil_screenshake==100) ? "Full" : ((recoil_screenshake==0) ? "None" : "[screenshake]")]
" - var/p_chaos - if (!preferred_chaos) - p_chaos = "No preference" - else - p_chaos = preferred_chaos - dat += "Preferred Chaos Amount: [p_chaos]
" - dat += "
" - dat += "
" - if(unlock_content) - dat += "Ghost Form: [ghost_form]
" - dat += "Ghost Orbit: [ghost_orbit]
" - var/button_name = "If you see this something went wrong." - switch(ghost_accs) - if(GHOST_ACCS_FULL) - button_name = GHOST_ACCS_FULL_NAME - if(GHOST_ACCS_DIR) - button_name = GHOST_ACCS_DIR_NAME - if(GHOST_ACCS_NONE) - button_name = GHOST_ACCS_NONE_NAME - - dat += "Ghost Accessories: [button_name]
" - switch(ghost_others) - if(GHOST_OTHERS_THEIR_SETTING) - button_name = GHOST_OTHERS_THEIR_SETTING_NAME - if(GHOST_OTHERS_DEFAULT_SPRITE) - button_name = GHOST_OTHERS_DEFAULT_SPRITE_NAME - if(GHOST_OTHERS_SIMPLE) - button_name = GHOST_OTHERS_SIMPLE_NAME - - dat += "Ghosts of Others: [button_name]
" - dat += "
" - - dat += "FPS: [clientfps]
" - - dat += "Income Updates: [(chat_toggles & CHAT_BANKCARD) ? "Allowed" : "Muted"]
" - dat += "
" - - dat += "Parallax (Fancy Space): " - switch (parallax) - if (PARALLAX_LOW) - dat += "Low" - if (PARALLAX_MED) - dat += "Medium" - if (PARALLAX_INSANE) - dat += "Insane" - if (PARALLAX_DISABLE) - dat += "Disabled" - else - dat += "High" - dat += "
" - dat += "Ambient Occlusion: [ambientocclusion ? "Enabled" : "Disabled"]
" - dat += "Fit Viewport: [auto_fit_viewport ? "Auto" : "Manual"]
" - dat += "HUD Button Flashes: [hud_toggle_flash ? "Enabled" : "Disabled"]
" - dat += "HUD Button Flash Color:     Change
" - -/* CITADEL EDIT - We're using top menu instead - button_name = pixel_size - dat += "Pixel Scaling: [(button_name) ? "Pixel Perfect [button_name]x" : "Stretch to fit"]
" - - switch(scaling_method) - if(SCALING_METHOD_NORMAL) - button_name = "Nearest Neighbor" - if(SCALING_METHOD_DISTORT) - button_name = "Point Sampling" - if(SCALING_METHOD_BLUR) - button_name = "Bilinear" - dat += "Scaling Method: [button_name]
" -*/ - - if (CONFIG_GET(flag/maprotation) && CONFIG_GET(flag/tgstyle_maprotation)) - var/p_map = preferred_map - if (!p_map) - p_map = "Default" - if (config.defaultmap) - p_map += " ([config.defaultmap.map_name])" - else - if (p_map in config.maplist) - var/datum/map_config/VM = config.maplist[p_map] - if (!VM) - p_map += " (No longer exists)" - else - p_map = VM.map_name - else - p_map += " (No longer exists)" - if(CONFIG_GET(flag/allow_map_voting)) - dat += "Preferred Map: [p_map]
" - - dat += "" - - dat += "

Special Role Settings

" - - if(jobban_isbanned(user, ROLE_SYNDICATE)) - dat += "You are banned from antagonist roles." - src.be_special = list() - - dat += "DISABLE ALL ANTAGONISM [(toggles & NO_ANTAG) ? "YES" : "NO"]
" - - for (var/i in GLOB.special_roles) - if(jobban_isbanned(user, i)) - dat += "Be [capitalize(i)]: BANNED
" - else - var/days_remaining = null - if(ispath(GLOB.special_roles[i]) && CONFIG_GET(flag/use_age_restriction_for_jobs)) //If it's a game mode antag, check if the player meets the minimum age - var/mode_path = GLOB.special_roles[i] - var/datum/game_mode/temp_mode = new mode_path - days_remaining = temp_mode.get_remaining_days(user.client) - - if(days_remaining) - dat += "Be [capitalize(i)]: \[IN [days_remaining] DAYS]
" - else - var/enabled_text = "" - if(i in be_special) - if(be_special[i] >= 1) - enabled_text = "Enabled" + if(pref_species.use_skintones) + dat += "Genitals use skintone:[features["genitals_use_skintone"] == TRUE ? "Yes" : "No"]" + dat += "

Penis

" + dat += "[features["has_cock"] == TRUE ? "Yes" : "No"]" + if(features["has_cock"]) + if(pref_species.use_skintones && features["genitals_use_skintone"] == TRUE) + dat += "Penis Color:
" + dat += "[SKINTONE2HEX(skin_tone)](Skin tone overriding)
" else - enabled_text = "Low" - else - enabled_text = "Disabled" - dat += "Be [capitalize(i)]: [enabled_text]
" - dat += "Midround Antagonist: [(toggles & MIDROUND_ANTAG) ? "Enabled" : "Disabled"]
" - - dat += "
" - - if(LOADOUT_TAB) - //calculate your gear points from the chosen item - gear_points = CONFIG_GET(number/initial_gear_points) - var/list/chosen_gear = loadout_data["SAVE_[loadout_slot]"] - if(chosen_gear) - for(var/loadout_item in chosen_gear) - var/loadout_item_path = loadout_item[LOADOUT_ITEM] - if(loadout_item_path) - var/datum/gear/loadout_gear = text2path(loadout_item_path) - if(loadout_gear) - gear_points -= initial(loadout_gear.cost) - else - chosen_gear = list() - - dat += "" - dat += "" - dat += "" - dat += "" - dat += "" - - dat += "" - - dat += "" - dat += "" - dat += "" - dat += "" - for(var/name in GLOB.loadout_items[gear_category][gear_subcategory]) - var/datum/gear/gear = GLOB.loadout_items[gear_category][gear_subcategory][name] - var/donoritem = gear.donoritem - if(donoritem && !gear.donator_ckey_check(user.ckey)) - continue - var/class_link = "" - var/list/loadout_item = has_loadout_gear(loadout_slot, "[gear.type]") - var/extra_loadout_data = "" - if(loadout_item) - class_link = "style='white-space:normal;' class='linkOn' href='?_src_=prefs;preference=gear;toggle_gear_path=[html_encode(name)];toggle_gear=0'" - if(gear.loadout_flags & LOADOUT_CAN_COLOR_POLYCHROMIC) - extra_loadout_data += "
Color" - for(var/loadout_color in loadout_item[LOADOUT_COLOR]) - extra_loadout_data += "   " - else - var/loadout_color_non_poly = "#FFFFFF" - if(length(loadout_item[LOADOUT_COLOR])) - loadout_color_non_poly = loadout_item[LOADOUT_COLOR][1] - extra_loadout_data += "
Color" - extra_loadout_data += "   " - if(gear.loadout_flags & LOADOUT_CAN_NAME) - extra_loadout_data += "
Name [loadout_item[LOADOUT_CUSTOM_NAME] ? loadout_item[LOADOUT_CUSTOM_NAME] : "N/A"]" - if(gear.loadout_flags & LOADOUT_CAN_DESCRIPTION) - extra_loadout_data += "
Description" - else if((gear_points - gear.cost) < 0) - class_link = "style='white-space:normal;' class='linkOff'" - else if(donoritem) - class_link = "style='white-space:normal;background:#ebc42e;' href='?_src_=prefs;preference=gear;toggle_gear_path=[html_encode(name)];toggle_gear=1'" - else if(!istype(gear, /datum/gear/unlockable) || can_use_unlockable(gear)) - class_link = "style='white-space:normal;' href='?_src_=prefs;preference=gear;toggle_gear_path=[html_encode(name)];toggle_gear=1'" - else - class_link = "style='white-space:normal;background:#eb2e2e;' class='linkOff'" - dat += "" - dat += "" - else - //we add the user's progress to the description assuming they have progress - var/datum/gear/unlockable/unlockable = gear - var/progress_made = unlockable_loadout_data[unlockable.progress_key] - if(!progress_made) - progress_made = 0 - dat += "" + dat += "Testicles Color:
" + dat += "#[features["balls_color"]]Change
" + dat += "Testicles Shape:[features["balls_shape"]]" + dat += "Testicles Visibility:[features["balls_visibility"]]" + dat += APPEARANCE_CATEGORY_COLUMN + dat += "

Vagina

" + dat += "[features["has_vag"] == TRUE ? "Yes" : "No"]" + if(features["has_vag"]) + dat += "Vagina Type:[features["vag_shape"]]" + if(pref_species.use_skintones && features["genitals_use_skintone"] == TRUE) + dat += "Vagina Color:
" + dat += "[SKINTONE2HEX(skin_tone)](Skin tone overriding)
" + else + dat += "Vagina Color:
" + dat += "#[features["vag_color"]]Change
" + dat += "Vagina Visibility:[features["vag_visibility"]]" + dat += "Has Womb:[features["has_womb"] == TRUE ? "Yes" : "No"]" + dat += "" + dat += APPEARANCE_CATEGORY_COLUMN + dat += "

Breasts

" + dat += "[features["has_breasts"] == TRUE ? "Yes" : "No"]" + if(features["has_breasts"]) + if(pref_species.use_skintones && features["genitals_use_skintone"] == TRUE) + dat += "Color:
" + dat += "[SKINTONE2HEX(skin_tone)](Skin tone overriding)
" + else + dat += "Color:
" + dat += "#[features["breasts_color"]]Change
" + dat += "Cup Size:[features["breasts_size"]]" + dat += "Breasts Shape:[features["breasts_shape"]]" + dat += "Breasts Visibility:[features["breasts_visibility"]]" + dat += "Lactates:[features["breasts_producing"] == TRUE ? "Yes" : "No"]" + dat += "" + dat += APPEARANCE_CATEGORY_COLUMN + dat += "

Butt

" + dat += "[features["has_butt"] == TRUE ? "Yes" : "No"]" + if(features["has_butt"]) + if(pref_species.use_skintones && features["genitals_use_skintone"] == TRUE) + dat += "Color:
" + dat += "[SKINTONE2HEX(skin_tone)](Skin tone overriding)
" + else + dat += "Color:
" + dat += "#[features["butt_color"]]Change
" + dat += "Butt Size:[features["butt_size"]]" + dat += "Butt Visibility:[features["butt_visibility"]]" + dat += "" + dat += "" + dat += "
[gear_points] loadout points remaining. \[Clear Loadout\]
You can only choose one item per category, unless it's an item that spawns in your backpack or hands.
" - - if(!length(GLOB.loadout_items)) - dat += "
ERROR: No loadout categories - something is horribly wrong!" - else - if(!GLOB.loadout_categories[gear_category]) - gear_category = GLOB.loadout_categories[1] - var/firstcat = TRUE - for(var/category in GLOB.loadout_categories) - if(firstcat) - firstcat = FALSE - else - dat += " |" - if(category == gear_category) - dat += " [category] " - else - dat += " [category] " - - dat += "

" - - if(!length(GLOB.loadout_categories[gear_category])) - dat += "No subcategories detected. Something is horribly wrong!" - else - var/list/subcategories = GLOB.loadout_categories[gear_category] - if(!subcategories.Find(gear_subcategory)) - gear_subcategory = subcategories[1] - - var/firstsubcat = TRUE - for(var/subcategory in subcategories) - if(firstsubcat) - firstsubcat = FALSE - else - dat += " |" - if(gear_subcategory == subcategory) - dat += " [subcategory] " - else - dat += " [subcategory] " - dat += "
NameCostRestrictionsDescription
[name][extra_loadout_data][gear.cost]" - if(islist(gear.restricted_roles)) - if(gear.restricted_roles.len) - if(gear.restricted_desc) - dat += "" - dat += gear.restricted_desc - dat += "" + dat += "Penis Color:
" + dat += "#[features["cock_color"]] Change
" + var/tauric_shape = FALSE + if(features["cock_taur"]) + var/datum/sprite_accessory/penis/P = GLOB.cock_shapes_list[features["cock_shape"]] + if(P.taur_icon && parent.can_have_part("taur")) + var/datum/sprite_accessory/taur/T = GLOB.taur_list[features["taur"]] + if(T.taur_mode & P.accepted_taurs) + tauric_shape = TRUE + dat += "Penis Shape: [features["cock_shape"]][tauric_shape ? " (Taur)" : ""]" + dat += "Penis Length: [features["cock_length"]] inch(es)" + dat += "Penis Visibility:[features["cock_visibility"]]" + dat += "Has Testicles:[features["has_balls"] == TRUE ? "Yes" : "No"]" + if(features["has_balls"]) + if(pref_species.use_skintones && features["genitals_use_skintone"] == TRUE) + dat += "Testicles Color:
" + dat += "[SKINTONE2HEX(skin_tone)](Skin tone overriding)
" else - dat += "" - dat += gear.restricted_roles.Join(";") - dat += "" - if(!istype(gear, /datum/gear/unlockable)) - // the below line essentially means "if the loadout item is picked by the user and has a custom description, give it the custom description, otherwise give it the default description" - dat += "
[loadout_item ? (loadout_item[LOADOUT_CUSTOM_DESCRIPTION] ? loadout_item[LOADOUT_CUSTOM_DESCRIPTION] : gear.description) : gear.description]
[loadout_item ? (loadout_item[LOADOUT_CUSTOM_DESCRIPTION] ? loadout_item[LOADOUT_CUSTOM_DESCRIPTION] : gear.description) : gear.description] Progress: [min(progress_made, unlockable.progress_required)]/[unlockable.progress_required]
" + //Markings + if(MARKINGS_CHAR_TAB) + var/iterated_markings = 0 + var/total_pages = 0 + // rp marking selection + // assume you can only have mam markings or regular markings or none, never both + var/marking_type + if(parent.can_have_part("mam_body_markings")) + marking_type = "mam_body_markings" + if(marking_type) + dat += APPEARANCE_CATEGORY_COLUMN + dat += "
" + dat += "

[GLOB.all_mutant_parts[marking_type]]

" // give it the appropriate title for the type of marking + dat += "Add marking" + dat += "
" + dat += "" + + for(var/limb in GLOB.bodypart_values) + if(length(GLOB.bodypart_values) % 3 != 0) + continue + total_pages++ + + for(var/limb in GLOB.bodypart_values) + if(!iterated_markings) + dat += "" + iterated_markings = 0 + dat += "
" + dat += "

[limb]

" + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + + // list out the current markings you have + if(length(features[marking_type])) + var/list/markings = features[marking_type] + if(!islist(markings)) + // something went terribly wrong + markings = list() + + for(var/list/marking_list in markings) + var/marking_index = markings.Find(marking_list) // consider changing loop to go through indexes over lists instead of using Find here + var/limb_value = marking_list[1] + var/actual_name = GLOB.bodypart_names[num2text(limb_value)] // get the actual name from the bitflag representing the part the marking is applied to + if(actual_name != limb) + continue + var/color_marking_dat = "" + var/number_colors = 1 + var/datum/sprite_accessory/mam_body_markings/S = GLOB.mam_body_markings_list[marking_list[2]] + var/matrixed_sections = S.covered_limbs[actual_name] + if(S && matrixed_sections) + // if it has nothing initialize it to white + if(length(marking_list) == 2) + var/first = "#FFFFFF" + var/second = "#FFFFFF" + var/third = "#FFFFFF" + if(features["mcolor"]) + first = "#[features["mcolor"]]" + if(features["mcolor2"]) + second = "#[features["mcolor2"]]" + if(features["mcolor3"]) + third = "#[features["mcolor3"]]" + marking_list += list(list(first, second, third)) // just assume its 3 colours if it isnt it doesnt matter we just wont use the other values + // index magic + var/primary_index = 1 + var/secondary_index = 2 + var/tertiary_index = 3 + switch(matrixed_sections) + if(MATRIX_GREEN) + primary_index = 2 + if(MATRIX_BLUE) + primary_index = 3 + if(MATRIX_RED_BLUE) + secondary_index = 2 + if(MATRIX_GREEN_BLUE) + primary_index = 2 + secondary_index = 3 + + // we know it has one matrixed section at minimum + color_marking_dat += "[marking_list[3][primary_index]]" + // if it has a second section, add it + if(matrixed_sections == MATRIX_RED_BLUE || matrixed_sections == MATRIX_GREEN_BLUE || matrixed_sections == MATRIX_RED_GREEN || matrixed_sections == MATRIX_ALL) + number_colors = 2 + color_marking_dat += "[marking_list[3][secondary_index]]" + // if it has a third section, add it + if(matrixed_sections == MATRIX_ALL) + number_colors = 3 + color_marking_dat += "[marking_list[3][tertiary_index]]" + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + + else + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + + dat += "
[marking_index]˅˄[marking_list[2]][color_marking_dat]X
" + + iterated_markings++ + if(iterated_markings >= 3) + dat += "
" + + if(SPEECH_CHAR_TAB) + dat += "" + dat += "" + dat += "
" + dat += "

Speech preferences

" + dat += "Custom Speech Verb:
" + dat += "[custom_speech_verb]
" + dat += "Custom Tongue:
" + dat += "[custom_tongue]
" + dat += "Additional Language
" + dat += "[additional_language]
" + dat += "
" + dat += "

Vocal Bark preferences

" + var/datum/bark/B = GLOB.bark_list[bark_id] + dat += "Vocal Bark Sound:
" + dat += "[B ? initial(B.name) : "INVALID"]
" + dat += "Vocal Bark Speed: [bark_speed]
" + dat += "Vocal Bark Pitch: [bark_pitch]
" + dat += "Vocal Bark Variance: [bark_variance]
" + dat += "
Preview Bark
" + dat += "
" + if(LOADOUT_CHAR_TAB) + dat += "" + dat += "" + dat += "" + dat += "" + + dat += "" + + dat += "
You can only choose one item per category, unless it's an item that spawns in your backpack or hands.
" + + if(!length(GLOB.loadout_items)) + dat += "
ERROR: No loadout categories - something is horribly wrong!" + else + if(!GLOB.loadout_categories[gear_category]) + gear_category = GLOB.loadout_categories[1] + var/firstcat = TRUE + for(var/category in GLOB.loadout_categories) + if(firstcat) + firstcat = FALSE + else + dat += " |" + if(category == gear_category) + dat += " [category] " + else + dat += " [category] " + + dat += "

" + + if(!length(GLOB.loadout_categories[gear_category])) + dat += "No subcategories detected. Something is horribly wrong!" + else + var/list/subcategories = GLOB.loadout_categories[gear_category] + if(!subcategories.Find(gear_subcategory)) + gear_subcategory = subcategories[1] + + var/firstsubcat = TRUE + for(var/subcategory in subcategories) + if(firstsubcat) + firstsubcat = FALSE + else + dat += " |" + if(gear_subcategory == subcategory) + dat += " [subcategory] " + else + dat += " [subcategory] " + dat += "
" + dat += "
" + dat += "
" + dat += "" + dat += "" + dat += "" + dat += "" + + var/even = FALSE + for(var/name in GLOB.loadout_items[gear_category][gear_subcategory]) + var/datum/gear/gear = GLOB.loadout_items[gear_category][gear_subcategory][name] + var/donoritem = gear.donoritem + if(donoritem && !gear.donator_ckey_check(user.ckey)) + continue + var/background_cl = "#23273C" + if(even) + background_cl = "#17191C" + even = !even + var/class_link = "" + var/list/loadout_item = has_loadout_gear(loadout_slot, "[gear.type]") + var/extra_loadout_data = "" + if(loadout_item) + class_link = "style='white-space:normal;' class='linkOn' href='?_src_=prefs;preference=gear;toggle_gear_path=[html_encode(name)];toggle_gear=0'" + if(gear.loadout_flags & LOADOUT_CAN_COLOR_POLYCHROMIC) + extra_loadout_data += "
Color" + for(var/loadout_color in loadout_item[LOADOUT_COLOR]) + extra_loadout_data += "[loadout_color]" + else + var/loadout_color_non_poly = "#FFFFFF" + if(length(loadout_item[LOADOUT_COLOR])) + loadout_color_non_poly = loadout_item[LOADOUT_COLOR][1] + extra_loadout_data += "
Color" + extra_loadout_data += "[loadout_color_non_poly]" + if(gear.loadout_flags & LOADOUT_CAN_NAME) + extra_loadout_data += "
Name [loadout_item[LOADOUT_CUSTOM_NAME] ? loadout_item[LOADOUT_CUSTOM_NAME] : "N/A"]" + if(gear.loadout_flags & LOADOUT_CAN_DESCRIPTION) + extra_loadout_data += "
Description" + else if((gear_points - gear.cost) < 0) + class_link = "style='white-space:normal;' class='linkOff'" + else if(donoritem) + class_link = "style='white-space:normal;background:#ebc42e;' href='?_src_=prefs;preference=gear;toggle_gear_path=[html_encode(name)];toggle_gear=1'" + else if(!istype(gear, /datum/gear/unlockable) || can_use_unlockable(gear)) + class_link = "style='white-space:normal;' href='?_src_=prefs;preference=gear;toggle_gear_path=[html_encode(name)];toggle_gear=1'" + else + class_link = "style='white-space:normal;background:#eb2e2e;' class='linkOff'" + dat += "" + dat += "" + else + //we add the user's progress to the description assuming they have progress + var/datum/gear/unlockable/unlockable = gear + var/progress_made = unlockable_loadout_data[unlockable.progress_key] + if(!progress_made) + progress_made = 0 + dat += "" + dat += "
NameCostRestrictionsDescription
[name][extra_loadout_data][gear.cost]" + if(islist(gear.restricted_roles)) + if(gear.restricted_roles.len) + if(gear.restricted_desc) + dat += "" + dat += gear.restricted_desc + dat += "" + else + dat += "" + dat += gear.restricted_roles.Join(";") + dat += "" + if(!istype(gear, /datum/gear/unlockable)) + // the below line essentially means "if the loadout item is picked by the user and has a custom description, give it the custom description, otherwise give it the default description" + dat += "[loadout_item ? (loadout_item[LOADOUT_CUSTOM_DESCRIPTION] ? loadout_item[LOADOUT_CUSTOM_DESCRIPTION] : gear.description) : gear.description]
[loadout_item ? (loadout_item[LOADOUT_CUSTOM_DESCRIPTION] ? loadout_item[LOADOUT_CUSTOM_DESCRIPTION] : gear.description) : gear.description] Progress: [min(progress_made, unlockable.progress_required)]/[unlockable.progress_required]
" dat += "" - if(CONTENT_PREFERENCES_TAB) // Content preferences - dat += "" - dat +="
" - dat += "

Fetish content prefs

" - dat += "Arousal:[arousable == TRUE ? "Enabled" : "Disabled"]
" - dat += "Genital examine text:[(cit_toggles & GENITAL_EXAMINE) ? "Enabled" : "Disabled"]
" - dat += "Vore examine text:[(cit_toggles & VORE_EXAMINE) ? "Enabled" : "Disabled"]
" - dat += "Voracious MediHound sleepers: [(cit_toggles & MEDIHOUND_SLEEPER) ? "Yes" : "No"]
" - dat += "Hear Vore Sounds: [(cit_toggles & EATING_NOISES) ? "Yes" : "No"]
" - dat += "Hear Vore Digestion Sounds: [(cit_toggles & DIGESTION_NOISES) ? "Yes" : "No"]
" - dat += "Allow trash forcefeeding (requires Trashcan quirk) [(cit_toggles & TRASH_FORCEFEED) ? "Yes" : "No"]
" - dat += "Forced Feminization: [(cit_toggles & FORCED_FEM) ? "Allowed" : "Disallowed"]
" - dat += "Forced Masculinization: [(cit_toggles & FORCED_MASC) ? "Allowed" : "Disallowed"]
" - dat += "Lewd Hypno: [(cit_toggles & HYPNO) ? "Allowed" : "Disallowed"]
" - dat += "Bimbofication: [(cit_toggles & BIMBOFICATION) ? "Allowed" : "Disallowed"]
" - dat += "
" - dat += "

Other content prefs

" - dat += "Breast Enlargement: [(cit_toggles & BREAST_ENLARGEMENT) ? "Allowed" : "Disallowed"]
" - dat += "Penis Enlargement: [(cit_toggles & PENIS_ENLARGEMENT) ? "Allowed" : "Disallowed"]
" - dat += "Butt Enlargement: [(cit_toggles & BUTT_ENLARGEMENT) ? "Allowed" : "Disallowed"]
" - dat += "Hypno: [(cit_toggles & NEVER_HYPNO) ? "Disallowed" : "Allowed"]
" - dat += "Aphrodisiacs: [(cit_toggles & NO_APHRO) ? "Disallowed" : "Allowed"]
" - dat += "Ass Slapping: [(cit_toggles & NO_ASS_SLAP) ? "Disallowed" : "Allowed"]
" - dat += "Automatic Wagging: [(cit_toggles & NO_AUTO_WAG) ? "Disabled" : "Enabled"]
" - dat += "
" - dat += "
" + if(PREFERENCES_TAB) // Game Preferences + dat += "
" + dat += "General" + dat += "OOC" + dat += "Content" + dat += "
" + + dat += "
" + + switch(preferences_tab) + if(GAME_PREFS_TAB) + dat += "" + + dat += "
" + dat += "

General Settings

" + dat += "UI Style: [UI_style]
" + dat += "Outline: [outline_enabled ? "Enabled" : "Disabled"]
" + dat += "Outline Color: [outline_color ? "" : "Theme-based (null)"][outline_color] Change
" + dat += "Screentip: [screentip_pref ? "Enabled" : "Disabled"]
" + dat += "Screentip Color: [screentip_color] Change
" + dat += "\ + Screentip context with images: [screentip_images ? "Allowed" : "Disallowed"]
" + dat += "tgui Monitors: [(tgui_lock) ? "Primary" : "All"]
" + dat += "tgui Style: [(tgui_fancy) ? "Fancy" : "No Frills"]
" + dat += "Show Runechat Chat Bubbles: [chat_on_map ? "Enabled" : "Disabled"]
" + dat += "Runechat message char limit: [max_chat_length]
" + dat += "See Runechat for non-mobs: [see_chat_non_mob ? "Enabled" : "Disabled"]
" + dat += "
" + dat += "Action Buttons: [(buttons_locked) ? "Locked In Place" : "Unlocked"]
" + dat += "
" + dat += "PDA Color: [pda_color] Change
" + dat += "PDA Style: [pda_style]
" + dat += "PDA Reskin: [pda_skin]
" + dat += "
" + dat += "Ghost Ears: [(chat_toggles & CHAT_GHOSTEARS) ? "All Speech" : "Nearest Creatures"]
" + dat += "Ghost Radio: [(chat_toggles & CHAT_GHOSTRADIO) ? "All Messages":"No Messages"]
" + dat += "Ghost Sight: [(chat_toggles & CHAT_GHOSTSIGHT) ? "All Emotes" : "Nearest Creatures"]
" + dat += "Ghost Whispers: [(chat_toggles & CHAT_GHOSTWHISPER) ? "All Speech" : "Nearest Creatures"]
" + dat += "Ghost PDA: [(chat_toggles & CHAT_GHOSTPDA) ? "All Messages" : "Nearest Creatures"]
" + + dat += "
" + + dat += "

Special Role Settings

" + + if(jobban_isbanned(user, ROLE_SYNDICATE)) + dat += "You are banned from antagonist roles." + src.be_special = list() + + dat += "DISABLE ALL ANTAGONISM [(toggles & NO_ANTAG) ? "YES" : "NO"]
" + + for (var/i in GLOB.special_roles) + if(jobban_isbanned(user, i)) + dat += "Be [capitalize(i)]: BANNED
" + else + var/days_remaining = null + if(ispath(GLOB.special_roles[i]) && CONFIG_GET(flag/use_age_restriction_for_jobs)) //If it's a game mode antag, check if the player meets the minimum age + var/mode_path = GLOB.special_roles[i] + var/datum/game_mode/temp_mode = new mode_path + days_remaining = temp_mode.get_remaining_days(user.client) + + if(days_remaining) + dat += "Be [capitalize(i)]: \[IN [days_remaining] DAYS\]
" + else + var/enabled_text = "" + if(i in be_special) + if(be_special[i] >= 1) + enabled_text = "Enabled" + else + enabled_text = "Low" + else + enabled_text = "Disabled" + dat += "Be [capitalize(i)]: [enabled_text]
" + dat += "Midround Antagonist: [(toggles & MIDROUND_ANTAG) ? "Enabled" : "Disabled"]
" + + dat += "
" + + if(OOC_PREFS_TAB) + dat += "" + dat += "" + + dat += "
" + dat += "

OOC Settings

" + dat += "Window Flashing: [(windowflashing) ? "Enabled":"Disabled"]
" + dat += "
" + dat += "Play Admin MIDIs: [(toggles & SOUND_MIDI) ? "Enabled":"Disabled"]
" + dat += "Play Lobby Music: [(toggles & SOUND_LOBBY) ? "Enabled":"Disabled"]
" + dat += "See Pull Requests: [(chat_toggles & CHAT_PULLR) ? "Enabled":"Disabled"]
" + dat += "
" + if(user.client) + if(unlock_content) + dat += "BYOND Membership Publicity: [(toggles & MEMBER_PUBLIC) ? "Public" : "Hidden"]
" + if(unlock_content || check_rights_for(user.client, R_ADMIN)) + dat += "OOC Color: [ooccolor ? ooccolor : GLOB.normal_ooc_colour] Change
" + dat += "Antag OOC Color: [aooccolor ? aooccolor : GLOB.normal_aooc_colour] Change
" + + if(user.client.holder) + dat += "

Admin Settings

" + dat += "Adminhelp Sounds: [(toggles & SOUND_ADMINHELP)?"Enabled":"Disabled"]
" + dat += "Announce Login: [(toggles & ANNOUNCE_LOGIN)?"Enabled":"Disabled"]
" + dat += "
" + dat += "Combo HUD Lighting: [(toggles & COMBOHUD_LIGHTING)?"Full-bright":"No Change"]
" + + //deadmin + dat += "

Deadmin While Playing

" + if(CONFIG_GET(flag/auto_deadmin_players)) + dat += "Always Deadmin: FORCED
" + else + dat += "Always Deadmin: [(deadmin & DEADMIN_ALWAYS)?"Enabled":"Disabled"]
" + if(!(deadmin & DEADMIN_ALWAYS)) + dat += "
" + if(!CONFIG_GET(flag/auto_deadmin_antagonists)) + dat += "As Antag: [(deadmin & DEADMIN_ANTAGONIST)?"Deadmin":"Keep Admin"]
" + else + dat += "As Antag: FORCED
" + + if(!CONFIG_GET(flag/auto_deadmin_heads)) + dat += "As Command: [(deadmin & DEADMIN_POSITION_HEAD)?"Deadmin":"Keep Admin"]
" + else + dat += "As Command: FORCED
" + + if(!CONFIG_GET(flag/auto_deadmin_security)) + dat += "As Security: [(deadmin & DEADMIN_POSITION_SECURITY)?"Deadmin":"Keep Admin"]
" + else + dat += "As Security: FORCED
" + + if(!CONFIG_GET(flag/auto_deadmin_silicons)) + dat += "As Silicon: [(deadmin & DEADMIN_POSITION_SILICON)?"Deadmin":"Keep Admin"]
" + else + dat += "As Silicon: FORCED
" + + dat += "
" + + dat += "

Citadel Preferences

" //Because fuck me if preferences can't be fucking modularized and expected to update in a reasonable timeframe. + dat += "Widescreen: [widescreenpref ? "Enabled ([CONFIG_GET(string/default_view)])" : "Disabled (15x15)"]
" + dat += "Long strip menu: [long_strip_menu ? "Enabled" : "Disabled"]
" + dat += "Auto stand: [autostand ? "Enabled" : "Disabled"]
" + dat += "Auto OOC: [auto_ooc ? "Enabled" : "Disabled"]
" + dat += "Force Slot Storage HUD: [no_tetris_storage ? "Enabled" : "Disabled"]
" + dat += "Screen Shake: [(screenshake==100) ? "Full" : ((screenshake==0) ? "None" : "[screenshake]")]
" + if (user && user.client && !user.client.prefs.screenshake==0) + dat += "Damage Screen Shake: [(damagescreenshake==1) ? "On" : ((damagescreenshake==0) ? "Off" : "Only when down")]
" + dat += "Recoil Screen Push: [(recoil_screenshake==100) ? "Full" : ((recoil_screenshake==0) ? "None" : "[screenshake]")]
" + var/p_chaos + if (!preferred_chaos) + p_chaos = "No preference" + else + p_chaos = preferred_chaos + dat += "Preferred Chaos Amount: [p_chaos]
" + dat += "
" + + if(unlock_content) + dat += "Ghost Form: [ghost_form]
" + dat += "Ghost Orbit: [ghost_orbit]
" + var/button_name = "If you see this something went wrong." + switch(ghost_accs) + if(GHOST_ACCS_FULL) + button_name = GHOST_ACCS_FULL_NAME + if(GHOST_ACCS_DIR) + button_name = GHOST_ACCS_DIR_NAME + if(GHOST_ACCS_NONE) + button_name = GHOST_ACCS_NONE_NAME + + dat += "Ghost Accessories: [button_name]
" + switch(ghost_others) + if(GHOST_OTHERS_THEIR_SETTING) + button_name = GHOST_OTHERS_THEIR_SETTING_NAME + if(GHOST_OTHERS_DEFAULT_SPRITE) + button_name = GHOST_OTHERS_DEFAULT_SPRITE_NAME + if(GHOST_OTHERS_SIMPLE) + button_name = GHOST_OTHERS_SIMPLE_NAME + + dat += "Ghosts of Others: [button_name]
" + dat += "
" + + dat += "FPS: [clientfps]
" + + dat += "Income Updates: [(chat_toggles & CHAT_BANKCARD) ? "Allowed" : "Muted"]
" + dat += "
" + + dat += "Parallax (Fancy Space): " + switch (parallax) + if (PARALLAX_LOW) + dat += "Low" + if (PARALLAX_MED) + dat += "Medium" + if (PARALLAX_INSANE) + dat += "Insane" + if (PARALLAX_DISABLE) + dat += "Disabled" + else + dat += "High" + dat += "
" + dat += "Ambient Occlusion: [ambientocclusion ? "Enabled" : "Disabled"]
" + dat += "Fit Viewport: [auto_fit_viewport ? "Auto" : "Manual"]
" + dat += "HUD Button Flashes: [hud_toggle_flash ? "Enabled" : "Disabled"]
" + dat += "HUD Button Flash Color: [hud_toggle_color] Change
" + + + if (CONFIG_GET(flag/maprotation) && CONFIG_GET(flag/tgstyle_maprotation)) + var/p_map = preferred_map + if (!p_map) + p_map = "Default" + if (config.defaultmap) + p_map += " ([config.defaultmap.map_name])" + else + if (p_map in config.maplist) + var/datum/map_config/VM = config.maplist[p_map] + if (!VM) + p_map += " (No longer exists)" + else + p_map = VM.map_name + else + p_map += " (No longer exists)" + if(CONFIG_GET(flag/allow_map_voting)) + dat += "Preferred Map: [p_map]
" + + dat += "
" + + if(CONTENT_PREFS_TAB) + dat += "" + dat +="
" + dat += "

Fetish content prefs

" + dat += "Arousal:[arousable == TRUE ? "Enabled" : "Disabled"]
" + dat += "Genital examine text:[(cit_toggles & GENITAL_EXAMINE) ? "Enabled" : "Disabled"]
" + dat += "Vore examine text:[(cit_toggles & VORE_EXAMINE) ? "Enabled" : "Disabled"]
" + dat += "Voracious MediHound sleepers: [(cit_toggles & MEDIHOUND_SLEEPER) ? "Yes" : "No"]
" + dat += "Hear Vore Sounds: [(cit_toggles & EATING_NOISES) ? "Yes" : "No"]
" + dat += "Hear Vore Digestion Sounds: [(cit_toggles & DIGESTION_NOISES) ? "Yes" : "No"]
" + dat += "Allow trash forcefeeding (requires Trashcan quirk) [(cit_toggles & TRASH_FORCEFEED) ? "Yes" : "No"]
" + dat += "Forced Feminization: [(cit_toggles & FORCED_FEM) ? "Allowed" : "Disallowed"]
" + dat += "Forced Masculinization: [(cit_toggles & FORCED_MASC) ? "Allowed" : "Disallowed"]
" + dat += "Lewd Hypno: [(cit_toggles & HYPNO) ? "Allowed" : "Disallowed"]
" + dat += "Bimbofication: [(cit_toggles & BIMBOFICATION) ? "Allowed" : "Disallowed"]
" + dat += "
" + dat += "

Other content prefs

" + dat += "Breast Enlargement: [(cit_toggles & BREAST_ENLARGEMENT) ? "Allowed" : "Disallowed"]
" + dat += "Penis Enlargement: [(cit_toggles & PENIS_ENLARGEMENT) ? "Allowed" : "Disallowed"]
" + dat += "Butt Enlargement: [(cit_toggles & BUTT_ENLARGEMENT) ? "Allowed" : "Disallowed"]
" + dat += "Hypno: [(cit_toggles & NEVER_HYPNO) ? "Disallowed" : "Allowed"]
" + dat += "Aphrodisiacs: [(cit_toggles & NO_APHRO) ? "Disallowed" : "Allowed"]
" + dat += "Ass Slapping: [(cit_toggles & NO_ASS_SLAP) ? "Disallowed" : "Allowed"]
" + dat += "Automatic Wagging: [(cit_toggles & NO_AUTO_WAG) ? "Disabled" : "Enabled"]
" + dat += "
" + if(KEYBINDINGS_TAB) // Custom keybindings dat += "Keybindings: [(hotkeys) ? "Hotkeys" : "Input"]
" dat += "Keybindings mode controls how the game behaves with tab and map/input focus.
If it is on Hotkeys, the game will always attempt to force you to map focus, meaning keypresses are sent \ @@ -2565,7 +2641,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) gender = chosengender if("body_size") - var/new_body_size = input(user, "Choose your desired sprite size: (90-125%)\nWarning: This may make your character look distorted. Additionally, any size under 100% takes a 10% maximum health penalty", "Character Preference", features["body_size"]*100) as num|null + var/new_body_size = input(user, "Choose your desired sprite size: ([CONFIG_GET(number/body_size_min)]-[CONFIG_GET(number/body_size_max)]%)\nWarning: This may make your character look distorted. Additionally, any size under 100% takes a 10% maximum health penalty", "Character Preference", features["body_size"]*100) as num|null if(new_body_size) features["body_size"] = clamp(new_body_size * 0.01, CONFIG_GET(number/body_size_min), CONFIG_GET(number/body_size_max)) @@ -2689,47 +2765,36 @@ GLOBAL_LIST_EMPTY(preferences_datums) var/limb_value = text2num(GLOB.bodypart_values[limb]) features[marking_type] += list(list(limb_value, selected_marking)) - if("marking_color") + if("marking_color_specific") var/index = text2num(href_list["marking_index"]) var/marking_type = href_list["marking_type"] - if(index && marking_type && features[marking_type]) - // work out the input options to show the user - var/list/options = list("Primary") - var/number_colors = text2num(href_list["number_colors"]) - var/color_number = 1 // 1-3 which color are we editing - if(number_colors >= 2) - options += "Secondary" - if(number_colors == 3) - options += "Tertiary" - var/color_option = input(user, "Select the colour you wish to edit") as null|anything in options - if(color_option) - if(color_option == "Secondary") color_number = 2 - if(color_option == "Tertiary") color_number = 3 - // perform some magic on the color number - var/list/marking_list = features[marking_type][index] - var/datum/sprite_accessory/mam_body_markings/S = GLOB.mam_body_markings_list[marking_list[2]] - var/matrixed_sections = S.covered_limbs[GLOB.bodypart_names[num2text(marking_list[1])]] - if(color_number == 1) - switch(matrixed_sections) - if(MATRIX_GREEN) - color_number = 2 - if(MATRIX_BLUE) - color_number = 3 - else if(color_number == 2) - switch(matrixed_sections) - if(MATRIX_RED_BLUE) - color_number = 3 - if(MATRIX_GREEN_BLUE) - color_number = 3 + var/color_number = text2num(href_list["number_color"]) + if(index && marking_type && color_number && features[marking_type]) + // perform some magic on the color number + var/list/marking_list = features[marking_type][index] + var/datum/sprite_accessory/mam_body_markings/S = GLOB.mam_body_markings_list[marking_list[2]] + var/matrixed_sections = S.covered_limbs[GLOB.bodypart_names[num2text(marking_list[1])]] + if(color_number == 1) + switch(matrixed_sections) + if(MATRIX_GREEN) + color_number = 2 + if(MATRIX_BLUE) + color_number = 3 + else if(color_number == 2) + switch(matrixed_sections) + if(MATRIX_RED_BLUE) + color_number = 3 + if(MATRIX_GREEN_BLUE) + color_number = 3 - var/color_list = features[marking_type][index][3] - var/new_marking_color = input(user, "Choose your character's marking color:", "Character Preference","#"+color_list[color_number]) as color|null - if(new_marking_color) - var/temp_hsv = RGBtoHSV(new_marking_color) - if((MUTCOLORS_PARTSONLY in pref_species.species_traits) || ReadHSV(temp_hsv)[3] >= ReadHSV(MINIMUM_MUTANT_COLOR)[3]) // mutantcolors must be bright, but only if they affect the skin - color_list[color_number] = "#[sanitize_hexcolor(new_marking_color, 6)]" - else - to_chat(user, "Invalid color. Your color is not bright enough.") + var/color_list = features[marking_type][index][3] + var/new_marking_color = input(user, "Choose your character's marking color:", "Character Preference","#"+color_list[color_number]) as color|null + if(new_marking_color) + var/temp_hsv = RGBtoHSV(new_marking_color) + if((MUTCOLORS_PARTSONLY in pref_species.species_traits) || ReadHSV(temp_hsv)[3] >= ReadHSV(MINIMUM_MUTANT_COLOR)[3]) // mutantcolors must be bright, but only if they affect the skin + color_list[color_number] = "#[sanitize_hexcolor(new_marking_color, 6)]" + else + to_chat(user, "Invalid color. Your color is not bright enough.") else switch(href_list["preference"]) //CITADEL PREFERENCES EDIT - I can't figure out how to modularize these, so they have to go here. :c -Pooj @@ -3130,6 +3195,18 @@ GLOBAL_LIST_EMPTY(preferences_datums) if("tab") if(href_list["tab"]) current_tab = text2num(href_list["tab"]) + + if("character_preview") + preview_pref = href_list["tab"] + + if("character_tab") + if(href_list["tab"]) + character_settings_tab = text2num(href_list["tab"]) + + if("preferences_tab") + if(href_list["tab"]) + preferences_tab = text2num(href_list["tab"]) + if(href_list["preference"] == "gear") if(href_list["clear_loadout"]) loadout_data["SAVE_[loadout_slot]"] = list() diff --git a/code/modules/mob/dead/new_player/preferences_setup.dm b/code/modules/mob/dead/new_player/preferences_setup.dm index dd3d5186de..a978e541bf 100644 --- a/code/modules/mob/dead/new_player/preferences_setup.dm +++ b/code/modules/mob/dead/new_player/preferences_setup.dm @@ -30,7 +30,6 @@ age = rand(AGE_MIN,AGE_MAX) /datum/preferences/proc/update_preview_icon(current_tab) - var/equip_job = (current_tab != APPEARANCE_TAB) // Determine what job is marked as 'High' priority, and dress them up as such. var/datum/job/previewJob = get_highest_job() @@ -49,14 +48,25 @@ mannequin.add_overlay(mutable_appearance('modular_citadel/icons/ui/backgrounds.dmi', bgstate, layer = SPACE_LAYER)) copy_to(mannequin, initial_spawn = TRUE) - if(current_tab == LOADOUT_TAB) - //give it its loadout if not on the appearance tab - SSjob.equip_loadout(parent.mob, mannequin, bypass_prereqs = TRUE, can_drop = FALSE) - SSjob.post_equip_loadout(parent.mob, mannequin, bypass_prereqs = TRUE, can_drop = FALSE) - else - if(previewJob && equip_job) - mannequin.job = previewJob.title - previewJob.equip(mannequin, TRUE, preference_source = parent) + switch(preview_pref) + if(PREVIEW_PREF_JOB) + if(previewJob) + mannequin.job = previewJob.title + previewJob.equip(mannequin, TRUE, preference_source = parent) + if(PREVIEW_PREF_LOADOUT) + SSjob.equip_loadout(parent.mob, mannequin, bypass_prereqs = TRUE, can_drop = FALSE) + SSjob.post_equip_loadout(parent.mob, mannequin, bypass_prereqs = TRUE, can_drop = FALSE) + if(PREVIEW_PREF_NAKED) + mannequin.hidden_underwear = TRUE + mannequin.hidden_undershirt = TRUE + mannequin.hidden_socks = TRUE + if(PREVIEW_PREF_NAKED_AROUSED) + mannequin.hidden_underwear = TRUE + mannequin.hidden_undershirt = TRUE + mannequin.hidden_socks = TRUE + for(var/obj/item/organ/genital/genital in mannequin.internal_organs) + if(genital.genital_flags & GENITAL_CAN_AROUSE) + genital.set_aroused_state(TRUE, null) mannequin.regenerate_icons()