diff --git a/code/modules/client/preferences/README.md b/code/modules/client/preferences/README.md index 9df77515e51..00899536398 100644 --- a/code/modules/client/preferences/README.md +++ b/code/modules/client/preferences/README.md @@ -135,14 +135,18 @@ Choiced preferences can generate icons. This is how the clothing/species prefere savefile_key = "favorite_drink" should_generate_icons = TRUE // NEW! This is necessary. -// Instead of returning a flat list, this now returns an assoc list -// of values to icons. /datum/preference/choiced/favorite_drink/init_possible_values() - return list( - "Milk" = icon('drinks.dmi', "milk"), - "Cola" = icon('drinks.dmi', "cola"), - "Water" = icon('drinks.dmi', "water"), - ) + return list("Milk", "Cola", "Water") + +// New! This proc will get called for every value. +/datum/preference/choiced/favorite_drink/icon_for(value) + switch (value) + if ("Milk") + return icon('drinks.dmi', "milk") + if ("Cola") + return icon('drinks.dmi', "cola") + if ("Water") + return icon('drinks.dmi', "water") ``` Then, change your `.tsx` file to look like: diff --git a/code/modules/client/preferences/_preference.dm b/code/modules/client/preferences/_preference.dm index e43f852a267..8d2d52ae0d1 100644 --- a/code/modules/client/preferences/_preference.dm +++ b/code/modules/client/preferences/_preference.dm @@ -347,9 +347,8 @@ GLOBAL_LIST_INIT(preference_entries_by_key, init_preference_entries_by_key()) /// A preference that is a choice of one option among a fixed set. /// Used for preferences such as clothing. /datum/preference/choiced - /// If this is TRUE, icons will be generated. - /// This is necessary for if your `init_possible_values()` override - /// returns an assoc list of names to atoms/icons. + /// If this is TRUE, an icon will be generated for every value. + /// If you implement this, you must implement `icon_for(value)` for every possible value. var/should_generate_icons = FALSE var/list/cached_values @@ -376,34 +375,31 @@ GLOBAL_LIST_INIT(preference_entries_by_key, init_preference_entries_by_key()) return cached_values /// Returns a list of every possible value, serialized. -/// Return value can be in the form of: -/// - A flat list of serialized values, such as list(MALE, FEMALE, PLURAL). -/// - An assoc list of serialized values to atoms/icons. /datum/preference/choiced/proc/get_choices_serialized() // Override `init_values()` instead. SHOULD_NOT_OVERRIDE(TRUE) var/list/serialized_choices = list() - var/choices = get_choices() - if (should_generate_icons) - for (var/choice in choices) - serialized_choices[serialize(choice)] = choices[choice] - else - for (var/choice in choices) - serialized_choices += serialize(choice) + for (var/choice in get_choices()) + serialized_choices += serialize(choice) return serialized_choices /// Returns a list of every possible value. /// This must be overriden by `/datum/preference/choiced` subtypes. -/// Return value can be in the form of: -/// - A flat list of raw values, such as list(MALE, FEMALE, PLURAL). -/// - An assoc list of raw values to atoms/icons, in which case -/// icons will be generated. +/// If `should_generate_icons` is TRUE, then you will also need to implement `icon_for(value)` +/// for every possible value. /datum/preference/choiced/proc/init_possible_values() CRASH("`init_possible_values()` was not implemented for [type]!") +/// When `should_generate_icons` is TRUE, this proc is called for every value. +/// It can return either an icon or a typepath to an atom to create. +/datum/preference/choiced/proc/icon_for(value) + SHOULD_CALL_PARENT(FALSE) + SHOULD_NOT_SLEEP(TRUE) + CRASH("`icon_for()` was not implemented for [type], even though should_generate_icons = TRUE!") + /datum/preference/choiced/is_valid(value) return value in get_choices() @@ -453,51 +449,6 @@ GLOBAL_LIST_INIT(preference_entries_by_key, init_preference_entries_by_key()) /datum/preference/color/is_valid(value) return findtext(value, GLOB.is_color) -/// Takes an assoc list of names to /datum/sprite_accessory and returns a value -/// fit for `/datum/preference/init_possible_values()` -/proc/possible_values_for_sprite_accessory_list(list/datum/sprite_accessory/sprite_accessories) - var/list/possible_values = list() - for (var/name in sprite_accessories) - var/datum/sprite_accessory/sprite_accessory = sprite_accessories[name] - if (istype(sprite_accessory)) - possible_values[name] = icon(sprite_accessory.icon, sprite_accessory.icon_state) - else - // This means it didn't have an icon state - possible_values[name] = icon('icons/mob/landmarks.dmi', "x") - return possible_values - -/// Takes an assoc list of names to /datum/sprite_accessory and returns a value -/// fit for `/datum/preference/init_possible_values()` -/// Different from `possible_values_for_sprite_accessory_list` in that it takes a list of layers -/// such as BEHIND, FRONT, and ADJ. -/// It also takes a "body part name", such as body_markings, moth_wings, etc -/// They are expected to be in order from lowest to top. -/proc/possible_values_for_sprite_accessory_list_for_body_part( - list/datum/sprite_accessory/sprite_accessories, - body_part, - list/layers, -) - var/list/possible_values = list() - - for (var/name in sprite_accessories) - var/datum/sprite_accessory/sprite_accessory = sprite_accessories[name] - if(sprite_accessory.locked) - continue - - var/icon/final_icon - - for (var/layer in layers) - var/icon/icon = icon(sprite_accessory.icon, "m_[body_part]_[sprite_accessory.icon_state]_[layer]") - - if (isnull(final_icon)) - final_icon = icon - else - final_icon.Blend(icon, ICON_OVERLAY) - - possible_values[name] = final_icon - - return possible_values - /// A numeric preference with a minimum and maximum value /datum/preference/numeric /// The minimum value diff --git a/code/modules/client/preferences/ai_core_display.dm b/code/modules/client/preferences/ai_core_display.dm index 1abbc586a1a..924b475961e 100644 --- a/code/modules/client/preferences/ai_core_display.dm +++ b/code/modules/client/preferences/ai_core_display.dm @@ -6,14 +6,13 @@ should_generate_icons = TRUE /datum/preference/choiced/ai_core_display/init_possible_values() - var/list/values = list() + return GLOB.ai_core_display_screens - "Portrait" - values["Random"] = icon('icons/mob/silicon/ai.dmi', "questionmark") - - for (var/screen in GLOB.ai_core_display_screens - "Portrait" - "Random") - values[screen] = icon('icons/mob/silicon/ai.dmi', resolve_ai_icon_sync(screen)) - - return values +/datum/preference/choiced/ai_core_display/icon_for(value) + if (value == "Random") + return icon('icons/mob/silicon/ai.dmi', "questionmark") + else + return icon('icons/mob/silicon/ai.dmi', resolve_ai_icon_sync(value)) /datum/preference/choiced/ai_core_display/is_accessible(datum/preferences/preferences) if (!..(preferences)) diff --git a/code/modules/client/preferences/ai_emote_display.dm b/code/modules/client/preferences/ai_emote_display.dm index 31e59433fec..eea059c8fe9 100644 --- a/code/modules/client/preferences/ai_emote_display.dm +++ b/code/modules/client/preferences/ai_emote_display.dm @@ -6,15 +6,13 @@ should_generate_icons = TRUE /datum/preference/choiced/ai_emote_display/init_possible_values() - var/list/values = list() + return assoc_to_keys(GLOB.ai_status_display_emotes) - values["Random"] = icon('icons/mob/silicon/ai.dmi', "questionmark") - - for(var/emote in GLOB.ai_status_display_emotes) - var/emote_icon = GLOB.ai_status_display_emotes[emote] - values[emote] = icon('icons/obj/machines/status_display.dmi', emote_icon) - - return values +/datum/preference/choiced/ai_emote_display/icon_for(value) + if (value == "Random") + return icon('icons/mob/silicon/ai.dmi', "questionmark") + else + return icon('icons/obj/machines/status_display.dmi', GLOB.ai_status_display_emotes[value]) /datum/preference/choiced/ai_emote_display/is_accessible(datum/preferences/preferences) if (!..(preferences)) diff --git a/code/modules/client/preferences/ai_hologram_display.dm b/code/modules/client/preferences/ai_hologram_display.dm index fdf49aecb2b..e71f806c3e4 100644 --- a/code/modules/client/preferences/ai_hologram_display.dm +++ b/code/modules/client/preferences/ai_hologram_display.dm @@ -6,14 +6,13 @@ should_generate_icons = TRUE /datum/preference/choiced/ai_hologram_display/init_possible_values() - var/list/values = list() + return assoc_to_keys(GLOB.ai_hologram_icons) + "Random" - values["Random"] = icon('icons/mob/silicon/ai.dmi', "questionmark") - - for(var/hologram in GLOB.ai_hologram_icons - "Random") - values[hologram] = icon(GLOB.ai_hologram_icons[hologram], GLOB.ai_hologram_icon_state[hologram]) - - return values +/datum/preference/choiced/ai_hologram_display/icon_for(value) + if (value == "Random") + return icon('icons/mob/silicon/ai.dmi', "questionmark") + else + return icon(GLOB.ai_hologram_icons[value], GLOB.ai_hologram_icon_state[value]) /datum/preference/choiced/ai_hologram_display/is_accessible(datum/preferences/preferences) if (!..(preferences)) diff --git a/code/modules/client/preferences/assets.dm b/code/modules/client/preferences/assets.dm index fbd4d0698ca..6fa29b9f90f 100644 --- a/code/modules/client/preferences/assets.dm +++ b/code/modules/client/preferences/assets.dm @@ -15,9 +15,8 @@ if (!preference.should_generate_icons) continue - var/list/choices = preference.get_choices_serialized() - for (var/preference_value in choices) - var/create_icon_of = choices[preference_value] + for (var/preference_value in preference.get_choices()) + var/create_icon_of = preference.icon_for(preference_value) var/icon/icon var/icon_state @@ -31,8 +30,8 @@ else CRASH("[create_icon_of] is an invalid preference value (from [preference_key]:[preference_value]).") - to_insert[preference.get_spritesheet_key(preference_value)] = list(icon, icon_state) - + to_insert[preference.get_spritesheet_key(preference.serialize(preference_value))] = list(icon, icon_state) + for (var/spritesheet_key in to_insert) var/list/inserting = to_insert[spritesheet_key] Insert(spritesheet_key, inserting[1], inserting[2]) diff --git a/code/modules/client/preferences/clothing.dm b/code/modules/client/preferences/clothing.dm index fae46b31be9..75b6a95be09 100644 --- a/code/modules/client/preferences/clothing.dm +++ b/code/modules/client/preferences/clothing.dm @@ -1,28 +1,16 @@ -/proc/generate_values_for_underwear(list/accessory_list, list/icons, color, icon_offset) //SKYRAT EDIT CHANGE - Colorable Undershirt/Socks - var/icon/lower_half = icon('icons/blanks/32x32.dmi', "nothing") +/proc/generate_underwear_icon(datum/sprite_accessory/accessory, icon/base_icon, color, icon_offset = 0) //SKYRAT EDIT CHANGE : adds icon_offset - Colorable Undershirt/Socks + var/icon/final_icon = new(base_icon) - for (var/icon in icons) - lower_half.Blend(icon('icons/mob/human/bodyparts_greyscale.dmi', icon), ICON_OVERLAY) + if (!isnull(accessory)) + var/icon/accessory_icon = icon(accessory.icon, accessory.icon_state) // SKYRAT EDIT CHANGE: ORIGINAL - var/icon/accessory_icon = icon('icons/mob/clothing/underwear.dmi', accessory.icon_state) + if (color && !accessory.use_static) + accessory_icon.Blend(color, ICON_MULTIPLY) + final_icon.Blend(accessory_icon, ICON_OVERLAY) - var/list/values = list() + final_icon.Crop(10, 1+icon_offset, 22, 13+icon_offset) //SKYRAT EDIT CHANGE : adds icon_offset - Colorable Undershirt/Socks + final_icon.Scale(32, 32) - for (var/accessory_name in accessory_list) - var/icon/icon_with_socks = new(lower_half) - var/datum/sprite_accessory/accessory = accessory_list[accessory_name] - //SKYRAT EDIT CHANGE - if (accessory_name != "Nude" && accessory) - var/icon/accessory_icon = icon(accessory.icon, accessory.icon_state) - //SKYRAT EDIT CHANGE END - if (color && !accessory.use_static) - accessory_icon.Blend(color, ICON_MULTIPLY) - icon_with_socks.Blend(accessory_icon, ICON_OVERLAY) - icon_with_socks.Crop(10, 1+icon_offset, 22, 13+icon_offset) //SKYRAT EDIT CHANGE - Colorable Undershirt/Socks - - icon_with_socks.Scale(32, 32) - - values[accessory_name] = icon_with_socks - - return values + return final_icon /// Backpack preference /datum/preference/choiced/backpack @@ -33,22 +21,37 @@ should_generate_icons = TRUE /datum/preference/choiced/backpack/init_possible_values() - var/list/values = list() + return list( + GBACKPACK, + GSATCHEL, + LSATCHEL, + GDUFFELBAG, + DBACKPACK, + DSATCHEL, + DDUFFELBAG, + ) - values[GBACKPACK] = /obj/item/storage/backpack - values[GSATCHEL] = /obj/item/storage/backpack/satchel - values[LSATCHEL] = /obj/item/storage/backpack/satchel/leather - values[GDUFFELBAG] = /obj/item/storage/backpack/duffelbag +/datum/preference/choiced/backpack/icon_for(value) + switch (value) + if (GBACKPACK) + return /obj/item/storage/backpack + if (GSATCHEL) + return /obj/item/storage/backpack/satchel + if (LSATCHEL) + return /obj/item/storage/backpack/satchel/leather + if (GDUFFELBAG) + return /obj/item/storage/backpack/duffelbag - // In a perfect world, these would be your department's backpack. - // However, this doesn't factor in assistants, or no high slot, and would - // also increase the spritesheet size a lot. - // I play medical doctor, and so medical doctor you get. - values[DBACKPACK] = /obj/item/storage/backpack/medic - values[DSATCHEL] = /obj/item/storage/backpack/satchel/med - values[DDUFFELBAG] = /obj/item/storage/backpack/duffelbag/med - - return values + // In a perfect world, these would be your department's backpack. + // However, this doesn't factor in assistants, or no high slot, and would + // also increase the spritesheet size a lot. + // I play medical doctor, and so medical doctor you get. + if (DBACKPACK) + return /obj/item/storage/backpack/medic + if (DSATCHEL) + return /obj/item/storage/backpack/satchel/med + if (DDUFFELBAG) + return /obj/item/storage/backpack/duffelbag/med /datum/preference/choiced/backpack/apply_to_human(mob/living/carbon/human/target, value) target.backpack = value @@ -62,12 +65,17 @@ should_generate_icons = TRUE /datum/preference/choiced/jumpsuit/init_possible_values() - var/list/values = list() + return list( + PREF_SUIT, + PREF_SKIRT, + ) - values[PREF_SUIT] = /obj/item/clothing/under/color/grey - values[PREF_SKIRT] = /obj/item/clothing/under/color/jumpskirt/grey - - return values +/datum/preference/choiced/jumpsuit/icon_for(value) + switch (value) + if (PREF_SUIT) + return /obj/item/clothing/under/color/grey + if (PREF_SKIRT) + return /obj/item/clothing/under/color/jumpskirt/grey /datum/preference/choiced/jumpsuit/apply_to_human(mob/living/carbon/human/target, value) target.jumpsuit_style = value @@ -81,7 +89,17 @@ should_generate_icons = TRUE /datum/preference/choiced/socks/init_possible_values() - return generate_values_for_underwear(GLOB.socks_list, list("human_r_leg", "human_l_leg")) + return assoc_to_keys_features(GLOB.socks_list) + +/datum/preference/choiced/socks/icon_for(value) + var/static/icon/lower_half + + if (isnull(lower_half)) + lower_half = icon('icons/blanks/32x32.dmi', "nothing") + lower_half.Blend(icon('icons/mob/human/bodyparts_greyscale.dmi', "human_r_leg"), ICON_OVERLAY) + lower_half.Blend(icon('icons/mob/human/bodyparts_greyscale.dmi', "human_l_leg"), ICON_OVERLAY) + + return generate_underwear_icon(GLOB.socks_list[value], lower_half) /datum/preference/choiced/socks/apply_to_human(mob/living/carbon/human/target, value) target.socks = value @@ -95,28 +113,28 @@ should_generate_icons = TRUE /datum/preference/choiced/undershirt/init_possible_values() - var/icon/body = icon('icons/mob/human/bodyparts_greyscale.dmi', "human_r_leg") - body.Blend(icon('icons/mob/human/bodyparts_greyscale.dmi', "human_l_leg"), ICON_OVERLAY) - body.Blend(icon('icons/mob/human/bodyparts_greyscale.dmi', "human_r_arm"), ICON_OVERLAY) - body.Blend(icon('icons/mob/human/bodyparts_greyscale.dmi', "human_l_arm"), ICON_OVERLAY) - body.Blend(icon('icons/mob/human/bodyparts_greyscale.dmi', "human_r_hand"), ICON_OVERLAY) - body.Blend(icon('icons/mob/human/bodyparts_greyscale.dmi', "human_l_hand"), ICON_OVERLAY) - body.Blend(icon('icons/mob/human/bodyparts_greyscale.dmi', "human_chest_m"), ICON_OVERLAY) + return assoc_to_keys_features(GLOB.undershirt_list) - var/list/values = list() +/datum/preference/choiced/undershirt/icon_for(value) + var/static/icon/body + if (isnull(body)) + body = icon('icons/mob/human/bodyparts_greyscale.dmi', "human_r_leg") + body.Blend(icon('icons/mob/human/bodyparts_greyscale.dmi', "human_l_leg"), ICON_OVERLAY) + body.Blend(icon('icons/mob/human/bodyparts_greyscale.dmi', "human_r_arm"), ICON_OVERLAY) + body.Blend(icon('icons/mob/human/bodyparts_greyscale.dmi', "human_l_arm"), ICON_OVERLAY) + body.Blend(icon('icons/mob/human/bodyparts_greyscale.dmi', "human_r_hand"), ICON_OVERLAY) + body.Blend(icon('icons/mob/human/bodyparts_greyscale.dmi', "human_l_hand"), ICON_OVERLAY) + body.Blend(icon('icons/mob/human/bodyparts_greyscale.dmi', "human_chest_m"), ICON_OVERLAY) - for (var/accessory_name in GLOB.undershirt_list) - var/icon/icon_with_undershirt = icon(body) + var/icon/icon_with_undershirt = icon(body) - if (accessory_name != "Nude") - var/datum/sprite_accessory/accessory = GLOB.undershirt_list[accessory_name] - icon_with_undershirt.Blend(icon('icons/mob/clothing/underwear.dmi', accessory.icon_state), ICON_OVERLAY) + if (value != "Nude") + var/datum/sprite_accessory/accessory = GLOB.undershirt_list[value] + icon_with_undershirt.Blend(icon(accessory.icon, accessory.icon_state), ICON_OVERLAY) // SKYRAT EDIT CHANGE: ORIGINAL - icon_with_undershirt.Blend(icon('icons/mob/clothing/underwear.dmi', accessory.icon_state), ICON_OVERLAY) - icon_with_undershirt.Crop(9, 9, 23, 23) - icon_with_undershirt.Scale(32, 32) - values[accessory_name] = icon_with_undershirt - - return values + icon_with_undershirt.Crop(10, 11, 22, 23) // SKYRAT EDIT CHANGE : ORIGINAL - icon_with_undershirt.Crop(9, 9, 23, 23) + icon_with_undershirt.Scale(32, 32) + return icon_with_undershirt /datum/preference/choiced/undershirt/apply_to_human(mob/living/carbon/human/target, value) target.undershirt = value @@ -130,7 +148,18 @@ should_generate_icons = TRUE /datum/preference/choiced/underwear/init_possible_values() - return generate_values_for_underwear(GLOB.underwear_list, list("human_chest_m", "human_r_leg", "human_l_leg"), COLOR_ALMOST_BLACK) + return assoc_to_keys_features(GLOB.underwear_list) + +/datum/preference/choiced/underwear/icon_for(value) + var/static/icon/lower_half + + if (isnull(lower_half)) + lower_half = icon('icons/blanks/32x32.dmi', "nothing") + lower_half.Blend(icon('icons/mob/human/bodyparts_greyscale.dmi', "human_chest_m"), ICON_OVERLAY) + lower_half.Blend(icon('icons/mob/human/bodyparts_greyscale.dmi', "human_r_leg"), ICON_OVERLAY) + lower_half.Blend(icon('icons/mob/human/bodyparts_greyscale.dmi', "human_l_leg"), ICON_OVERLAY) + + return generate_underwear_icon(GLOB.underwear_list[value], lower_half, COLOR_ALMOST_BLACK, icon_offset = 5) // SKYRAT EDIT CHANGE : ICON_OFFSET /datum/preference/choiced/underwear/apply_to_human(mob/living/carbon/human/target, value) target.underwear = value diff --git a/code/modules/client/preferences/ghost.dm b/code/modules/client/preferences/ghost.dm index ae84249507d..e3d7fbf6328 100644 --- a/code/modules/client/preferences/ghost.dm +++ b/code/modules/client/preferences/ghost.dm @@ -71,12 +71,10 @@ ) /datum/preference/choiced/ghost_form/init_possible_values() - var/list/values = list() + return assoc_to_keys(ghost_forms) - for (var/ghost_form in ghost_forms) - values[ghost_form] = icon('icons/mob/simple/mob.dmi', ghost_form) - - return values +/datum/preference/choiced/ghost_form/icon_for(value) + return icon('icons/mob/simple/mob.dmi', value) /datum/preference/choiced/ghost_form/create_default_value() return "ghost" diff --git a/code/modules/client/preferences/glasses.dm b/code/modules/client/preferences/glasses.dm index 6e93c98fd37..e34cdd0e090 100644 --- a/code/modules/client/preferences/glasses.dm +++ b/code/modules/client/preferences/glasses.dm @@ -5,14 +5,13 @@ should_generate_icons = TRUE /datum/preference/choiced/glasses/init_possible_values() - var/list/values = list() + return assoc_to_keys(GLOB.nearsighted_glasses) + "Random" - values["Random"] = icon('icons/effects/random_spawners.dmi', "questionmark") - - for(var/glass_design in GLOB.nearsighted_glasses - "Random") - values[glass_design] = icon('icons/obj/clothing/glasses.dmi', "glasses_[lowertext(glass_design)]") - - return values +/datum/preference/choiced/glasses/icon_for(value) + if (value == "Random") + return icon('icons/effects/random_spawners.dmi', "questionmark") + else + return icon('icons/obj/clothing/glasses.dmi', "glasses_[lowertext(value)]") /datum/preference/choiced/glasses/is_accessible(datum/preferences/preferences) if (!..(preferences)) diff --git a/code/modules/client/preferences/species_features/basic.dm b/code/modules/client/preferences/species_features/basic.dm index 5cf0fc5905f..faa86cc07e2 100644 --- a/code/modules/client/preferences/species_features/basic.dm +++ b/code/modules/client/preferences/species_features/basic.dm @@ -1,26 +1,24 @@ -/proc/generate_possible_values_for_sprite_accessories_on_head(accessories) - var/list/values = possible_values_for_sprite_accessory_list(accessories) +/proc/generate_icon_with_head_accessory(datum/sprite_accessory/sprite_accessory) + var/static/icon/head_icon + if (isnull(head_icon)) + head_icon = icon('icons/mob/human/bodyparts_greyscale.dmi', "human_head_m") + head_icon.Blend(skintone2hex("caucasian1"), ICON_MULTIPLY) - var/icon/head_icon = icon('icons/mob/human/bodyparts_greyscale.dmi', "human_head_m") - head_icon.Blend(skintone2hex("caucasian1"), ICON_MULTIPLY) + if (isnull(sprite_accessory)) + return head_icon - for (var/name in values) - var/datum/sprite_accessory/accessory = accessories[name] - if (accessory == null || accessory.icon_state == null) - continue + ASSERT(istype(sprite_accessory)) - var/icon/final_icon = new(head_icon) + var/icon/final_icon = new(head_icon) - var/icon/beard_icon = values[name] - beard_icon.Blend(COLOR_DARK_BROWN, ICON_MULTIPLY) - final_icon.Blend(beard_icon, ICON_OVERLAY) + var/icon/head_accessory_icon = icon(sprite_accessory.icon, sprite_accessory.icon_state) + head_accessory_icon.Blend(COLOR_DARK_BROWN, ICON_MULTIPLY) + final_icon.Blend(head_accessory_icon, ICON_OVERLAY) - final_icon.Crop(10, 19, 22, 31) - final_icon.Scale(32, 32) + final_icon.Crop(10, 19, 22, 31) + final_icon.Scale(32, 32) - values[name] = final_icon - - return values + return final_icon /datum/preference/color/eye_color priority = PREFERENCE_PRIORITY_BODYPARTS @@ -64,7 +62,10 @@ relevant_head_flag = HEAD_FACIAL_HAIR /datum/preference/choiced/facial_hairstyle/init_possible_values() - return generate_possible_values_for_sprite_accessories_on_head(GLOB.facial_hairstyles_list) + return assoc_to_keys_features(GLOB.facial_hairstyles_list) + +/datum/preference/choiced/facial_hairstyle/icon_for(value) + return generate_icon_with_head_accessory(GLOB.facial_hairstyles_list[value]) /datum/preference/choiced/facial_hairstyle/apply_to_human(mob/living/carbon/human/target, value) target.set_facial_hairstyle(value, update = FALSE) @@ -137,7 +138,10 @@ relevant_head_flag = HEAD_HAIR /datum/preference/choiced/hairstyle/init_possible_values() - return generate_possible_values_for_sprite_accessories_on_head(GLOB.hairstyles_list) + return assoc_to_keys_features(GLOB.hairstyles_list) + +/datum/preference/choiced/hairstyle/icon_for(value) + return generate_icon_with_head_accessory(GLOB.hairstyles_list[value]) /datum/preference/choiced/hairstyle/apply_to_human(mob/living/carbon/human/target, value) target.set_hairstyle(value, update = FALSE) diff --git a/code/modules/client/preferences/species_features/ethereal.dm b/code/modules/client/preferences/species_features/ethereal.dm index ba0f3d3a202..19c2fd650e1 100644 --- a/code/modules/client/preferences/species_features/ethereal.dm +++ b/code/modules/client/preferences/species_features/ethereal.dm @@ -6,28 +6,26 @@ should_generate_icons = TRUE /datum/preference/choiced/ethereal_color/init_possible_values() - var/list/values = list() + return assoc_to_keys(GLOB.color_list_ethereal) - var/icon/ethereal_base = icon('icons/mob/human/species/ethereal/bodyparts.dmi', "ethereal_head") - ethereal_base.Blend(icon('icons/mob/human/species/ethereal/bodyparts.dmi', "ethereal_chest"), ICON_OVERLAY) - ethereal_base.Blend(icon('icons/mob/human/species/ethereal/bodyparts.dmi', "ethereal_l_arm"), ICON_OVERLAY) - ethereal_base.Blend(icon('icons/mob/human/species/ethereal/bodyparts.dmi', "ethereal_r_arm"), ICON_OVERLAY) +/datum/preference/choiced/ethereal_color/icon_for(value) + var/static/icon/ethereal_base + if (isnull(ethereal_base)) + ethereal_base = icon('icons/mob/human/species/ethereal/bodyparts.dmi', "ethereal_head") + ethereal_base.Blend(icon('icons/mob/human/species/ethereal/bodyparts.dmi', "ethereal_chest"), ICON_OVERLAY) + ethereal_base.Blend(icon('icons/mob/human/species/ethereal/bodyparts.dmi', "ethereal_l_arm"), ICON_OVERLAY) + ethereal_base.Blend(icon('icons/mob/human/species/ethereal/bodyparts.dmi', "ethereal_r_arm"), ICON_OVERLAY) - var/icon/eyes = icon('icons/mob/human/human_face.dmi', "eyes") - eyes.Blend(COLOR_BLACK, ICON_MULTIPLY) - ethereal_base.Blend(eyes, ICON_OVERLAY) + var/icon/eyes = icon('icons/mob/human/human_face.dmi', "eyes") + eyes.Blend(COLOR_BLACK, ICON_MULTIPLY) + ethereal_base.Blend(eyes, ICON_OVERLAY) - ethereal_base.Scale(64, 64) - ethereal_base.Crop(15, 64, 15 + 31, 64 - 31) + ethereal_base.Scale(64, 64) + ethereal_base.Crop(15, 64, 15 + 31, 64 - 31) - for (var/name in GLOB.color_list_ethereal) - var/color = GLOB.color_list_ethereal[name] - - var/icon/icon = new(ethereal_base) - icon.Blend(color, ICON_MULTIPLY) - values[name] = icon - - return values + var/icon/icon = new(ethereal_base) + icon.Blend(GLOB.color_list_ethereal[value], ICON_MULTIPLY) + return icon /datum/preference/choiced/ethereal_color/apply_to_human(mob/living/carbon/human/target, value) target.dna.features["ethcolor"] = GLOB.color_list_ethereal[value] diff --git a/code/modules/client/preferences/species_features/lizard.dm b/code/modules/client/preferences/species_features/lizard.dm index 9c0b6e36519..2e0b3f3e513 100644 --- a/code/modules/client/preferences/species_features/lizard.dm +++ b/code/modules/client/preferences/species_features/lizard.dm @@ -1,31 +1,28 @@ /* SKYRAT EDIT REMOVAL -/proc/generate_lizard_side_shots(list/sprite_accessories, key, include_snout = TRUE) - var/list/values = list() +/proc/generate_lizard_side_shot(datum/sprite_accessory/sprite_accessory, key, include_snout = TRUE) + var/static/icon/lizard + var/static/icon/lizard_with_snout - var/icon/lizard = icon('icons/mob/human/species/lizard/bodyparts.dmi', "lizard_head", EAST) - var/icon/eyes = icon('icons/mob/human/human_face.dmi', "eyes", EAST) - eyes.Blend(COLOR_GRAY, ICON_MULTIPLY) - lizard.Blend(eyes, ICON_OVERLAY) + if (isnull(lizard)) + lizard = icon('icons/mob/human/species/lizard/bodyparts.dmi', "lizard_head", EAST) + var/icon/eyes = icon('icons/mob/human/human_face.dmi', "eyes", EAST) + eyes.Blend(COLOR_GRAY, ICON_MULTIPLY) + lizard.Blend(eyes, ICON_OVERLAY) - if (include_snout) - lizard.Blend(icon('icons/mob/human/species/lizard/lizard_misc.dmi', "m_snout_round_ADJ", EAST), ICON_OVERLAY) + lizard_with_snout = icon(lizard) + lizard_with_snout.Blend(icon('icons/mob/human/species/lizard/lizard_misc.dmi', "m_snout_round_ADJ", EAST), ICON_OVERLAY) - for (var/name in sprite_accessories) - var/datum/sprite_accessory/sprite_accessory = sprite_accessories[name] + var/icon/final_icon = include_snout ? icon(lizard_with_snout) : icon(lizard) - var/icon/final_icon = icon(lizard) + if (!isnull(sprite_accessory)) + var/icon/accessory_icon = icon(sprite_accessory.icon, "m_[key]_[sprite_accessory.icon_state]_ADJ", EAST) + final_icon.Blend(accessory_icon, ICON_OVERLAY) - if (sprite_accessory.icon_state != "none") - var/icon/accessory_icon = icon(sprite_accessory.icon, "m_[key]_[sprite_accessory.icon_state]_ADJ", EAST) - final_icon.Blend(accessory_icon, ICON_OVERLAY) + final_icon.Crop(11, 20, 23, 32) + final_icon.Scale(32, 32) + final_icon.Blend(COLOR_VIBRANT_LIME, ICON_MULTIPLY) - final_icon.Crop(11, 20, 23, 32) - final_icon.Scale(32, 32) - final_icon.Blend(COLOR_VIBRANT_LIME, ICON_MULTIPLY) - - values[name] = final_icon - - return values + return final_icon /datum/preference/choiced/lizard_body_markings savefile_key = "feature_lizard_body_markings" @@ -36,31 +33,27 @@ relevant_mutant_bodypart = "body_markings" /datum/preference/choiced/lizard_body_markings/init_possible_values() - var/list/values = list() + return assoc_to_keys_features(GLOB.body_markings_list) - var/icon/lizard = icon('icons/mob/human/species/lizard/bodyparts.dmi', "lizard_chest_m") +/datum/preference/choiced/lizard_body_markings/icon_for(value) + var/datum/sprite_accessory/sprite_accessory = GLOB.body_markings_list[value] - for (var/name in GLOB.body_markings_list) - var/datum/sprite_accessory/sprite_accessory = GLOB.body_markings_list[name] + var/icon/final_icon = icon('icons/mob/human/species/lizard/bodyparts.dmi', "lizard_chest_m") - var/icon/final_icon = icon(lizard) + if (sprite_accessory.icon_state != "none") + var/icon/body_markings_icon = icon( + 'icons/mob/human/species/lizard/lizard_misc.dmi', + "m_body_markings_[sprite_accessory.icon_state]_ADJ", + ) - if (sprite_accessory.icon_state != "none") - var/icon/body_markings_icon = icon( - 'icons/mob/human/species/lizard/lizard_misc.dmi', - "m_body_markings_[sprite_accessory.icon_state]_ADJ", - ) + final_icon.Blend(body_markings_icon, ICON_OVERLAY) - final_icon.Blend(body_markings_icon, ICON_OVERLAY) + final_icon.Blend(COLOR_VIBRANT_LIME, ICON_MULTIPLY) + final_icon.Crop(10, 8, 22, 23) + final_icon.Scale(26, 32) + final_icon.Crop(-2, 1, 29, 32) - final_icon.Blend(COLOR_VIBRANT_LIME, ICON_MULTIPLY) - final_icon.Crop(10, 8, 22, 23) - final_icon.Scale(26, 32) - final_icon.Crop(-2, 1, 29, 32) - - values[name] = final_icon - - return values + return final_icon /datum/preference/choiced/lizard_body_markings/apply_to_human(mob/living/carbon/human/target, value) target.dna.features["body_markings"] = value @@ -73,7 +66,10 @@ should_generate_icons = TRUE /datum/preference/choiced/lizard_frills/init_possible_values() - return generate_lizard_side_shots(GLOB.frills_list, "frills") + return assoc_to_keys_features(GLOB.frills_list) + +/datum/preference/choiced/lizard_frills/icon_for(value) + return generate_lizard_side_shot(GLOB.frills_list[value], "frills") /datum/preference/choiced/lizard_frills/apply_to_human(mob/living/carbon/human/target, value) target.dna.features["frills"] = value @@ -86,7 +82,10 @@ should_generate_icons = TRUE /datum/preference/choiced/lizard_horns/init_possible_values() - return generate_lizard_side_shots(GLOB.horns_list, "horns") + return assoc_to_keys_features(GLOB.horns_list) + +/datum/preference/choiced/lizard_horns/icon_for(value) + return generate_lizard_side_shot(GLOB.horns_list[value], "horns") /datum/preference/choiced/lizard_horns/apply_to_human(mob/living/carbon/human/target, value) target.dna.features["horns"] = value @@ -111,7 +110,10 @@ should_generate_icons = TRUE /datum/preference/choiced/lizard_snout/init_possible_values() - return generate_lizard_side_shots(GLOB.snouts_list, "snout", include_snout = FALSE) + return assoc_to_keys_features(GLOB.snouts_list) + +/datum/preference/choiced/lizard_snout/icon_for(value) + return generate_lizard_side_shot(GLOB.snouts_list[value], "snout", include_snout = FALSE) /datum/preference/choiced/lizard_snout/apply_to_human(mob/living/carbon/human/target, value) target.dna.features["snout"] = value diff --git a/code/modules/client/preferences/species_features/moth.dm b/code/modules/client/preferences/species_features/moth.dm index ba80ad56b1d..2879cfb8788 100644 --- a/code/modules/client/preferences/species_features/moth.dm +++ b/code/modules/client/preferences/species_features/moth.dm @@ -7,24 +7,24 @@ should_generate_icons = TRUE /datum/preference/choiced/moth_antennae/init_possible_values() - var/list/values = list() + return assoc_to_keys_features(GLOB.moth_antennae_list) - var/icon/moth_head = icon('icons/mob/human/species/moth/bodyparts.dmi', "moth_head") - moth_head.Blend(icon('icons/mob/human/human_face.dmi', "motheyes"), ICON_OVERLAY) +/datum/preference/choiced/moth_antennae/icon_for(value) + var/static/icon/moth_head - for (var/antennae_name in GLOB.moth_antennae_list) - var/datum/sprite_accessory/antennae = GLOB.moth_antennae_list[antennae_name] - if(antennae.locked) - continue + if (isnull(moth_head)) + moth_head = icon('icons/mob/human/species/moth/bodyparts.dmi', "moth_head") + moth_head.Blend(icon('icons/mob/human/human_face.dmi', "motheyes_l"), ICON_OVERLAY) + moth_head.Blend(icon('icons/mob/human/human_face.dmi', "motheyes_r"), ICON_OVERLAY) - var/icon/icon_with_antennae = new(moth_head) - icon_with_antennae.Blend(icon(antennae.icon, "m_moth_antennae_[antennae.icon_state]_FRONT"), ICON_OVERLAY) - icon_with_antennae.Scale(64, 64) - icon_with_antennae.Crop(15, 64, 15 + 31, 64 - 31) + var/datum/sprite_accessory/antennae = GLOB.moth_antennae_list[value] - values[antennae.name] = icon_with_antennae + var/icon/icon_with_antennae = new(moth_head) + icon_with_antennae.Blend(icon(antennae.icon, "m_moth_antennae_[antennae.icon_state]_FRONT"), ICON_OVERLAY) + icon_with_antennae.Scale(64, 64) + icon_with_antennae.Crop(15, 64, 15 + 31, 64 - 31) - return values + return icon_with_antennae /datum/preference/choiced/moth_antennae/apply_to_human(mob/living/carbon/human/target, value) target.dna.features["moth_antennae"] = value @@ -38,47 +38,45 @@ relevant_mutant_bodypart = "moth_markings" /datum/preference/choiced/moth_markings/init_possible_values() - var/list/values = list() + return assoc_to_keys_features(GLOB.moth_markings_list) - var/icon/moth_body = icon('icons/blanks/32x32.dmi', "nothing") - - moth_body.Blend(icon('icons/mob/human/species/moth/moth_wings.dmi', "m_moth_wings_plain_BEHIND"), ICON_OVERLAY) - - var/list/body_parts = list( +/datum/preference/choiced/moth_markings/icon_for(value) + var/static/list/body_parts = list( /obj/item/bodypart/head/moth, /obj/item/bodypart/chest/moth, /obj/item/bodypart/arm/left/moth, /obj/item/bodypart/arm/right/moth, ) - for (var/obj/item/bodypart/body_part in body_parts) - var/gender = (initial(body_part.is_dimorphic)) ? "_m" : "" - moth_body.Blend(icon('icons/mob/human/species/moth/bodyparts.dmi', "moth_[body_part][gender]"), ICON_OVERLAY) + var/static/icon/moth_body + if (isnull(moth_body)) + moth_body = icon('icons/blanks/32x32.dmi', "nothing") - moth_body.Blend(icon('icons/mob/human/human_face.dmi', "motheyes"), ICON_OVERLAY) + moth_body.Blend(icon('icons/mob/human/species/moth/moth_wings.dmi', "m_moth_wings_plain_BEHIND"), ICON_OVERLAY) - for (var/markings_name in GLOB.moth_markings_list) - var/datum/sprite_accessory/markings = GLOB.moth_markings_list[markings_name] - if(markings.locked) - continue - var/icon/icon_with_markings = new(moth_body) + for (var/obj/item/bodypart/body_part as anything in body_parts) + moth_body.Blend(icon('icons/mob/human/species/moth/bodyparts.dmi', initial(body_part.icon_state)), ICON_OVERLAY) - if (markings_name != "None") - for (var/body_part in body_parts) - var/icon/body_part_icon = icon(markings.icon, "[markings.icon_state]_[body_part]") - body_part_icon.Crop(1, 1, 32, 32) - icon_with_markings.Blend(body_part_icon, ICON_OVERLAY) + moth_body.Blend(icon('icons/mob/human/human_face.dmi', "motheyes_l"), ICON_OVERLAY) + moth_body.Blend(icon('icons/mob/human/human_face.dmi', "motheyes_r"), ICON_OVERLAY) - icon_with_markings.Blend(icon('icons/mob/human/species/moth/moth_wings.dmi', "m_moth_wings_plain_FRONT"), ICON_OVERLAY) - icon_with_markings.Blend(icon('icons/mob/human/species/moth/moth_antennae.dmi', "m_moth_antennae_plain_FRONT"), ICON_OVERLAY) + var/datum/sprite_accessory/markings = GLOB.moth_markings_list[value] + var/icon/icon_with_markings = new(moth_body) - // Zoom in on the top of the head and the chest - icon_with_markings.Scale(64, 64) - icon_with_markings.Crop(15, 64, 15 + 31, 64 - 31) + if (value != "None") + for (var/obj/item/bodypart/body_part as anything in body_parts) + var/icon/body_part_icon = icon(markings.icon, "[markings.icon_state]_[initial(body_part.body_zone)]") + body_part_icon.Crop(1, 1, 32, 32) + icon_with_markings.Blend(body_part_icon, ICON_OVERLAY) - values[markings.name] = icon_with_markings + icon_with_markings.Blend(icon('icons/mob/human/species/moth/moth_wings.dmi', "m_moth_wings_plain_FRONT"), ICON_OVERLAY) + icon_with_markings.Blend(icon('icons/mob/human/species/moth/moth_antennae.dmi', "m_moth_antennae_plain_FRONT"), ICON_OVERLAY) - return values + // Zoom in on the top of the head and the chest + icon_with_markings.Scale(64, 64) + icon_with_markings.Crop(15, 64, 15 + 31, 64 - 31) + + return icon_with_markings /datum/preference/choiced/moth_markings/apply_to_human(mob/living/carbon/human/target, value) target.dna.features["moth_markings"] = value @@ -91,11 +89,13 @@ should_generate_icons = TRUE /datum/preference/choiced/moth_wings/init_possible_values() - return possible_values_for_sprite_accessory_list_for_body_part( - GLOB.moth_wings_list, - "moth_wings", - list("BEHIND", "FRONT"), - ) + return assoc_to_keys_features(GLOB.moth_wings_list) + +/datum/preference/choiced/moth_wings/icon_for(value) + var/datum/sprite_accessory/moth_wings = GLOB.moth_wings_list[value] + var/icon/final_icon = icon(moth_wings.icon, "m_moth_wings_[moth_wings.icon_state]_BEHIND") + final_icon.Blend(icon(moth_wings.icon, "m_moth_wings_[moth_wings.icon_state]_FRONT"), ICON_OVERLAY) + return final_icon /datum/preference/choiced/moth_wings/apply_to_human(mob/living/carbon/human/target, value) target.dna.features["moth_wings"] = value diff --git a/code/modules/client/preferences/species_features/pod.dm b/code/modules/client/preferences/species_features/pod.dm index c5315d95380..7f7746ea41d 100644 --- a/code/modules/client/preferences/species_features/pod.dm +++ b/code/modules/client/preferences/species_features/pod.dm @@ -8,27 +8,22 @@ should_generate_icons = TRUE /datum/preference/choiced/pod_hair/init_possible_values() - var/list/values = list() + return assoc_to_keys_features(GLOB.pod_hair_list) - var/icon/pod_head = icon('icons/mob/human/bodyparts_greyscale.dmi', "pod_head_m") +/datum/preference/choiced/pod_hair/icon_for(value) + var/datum/sprite_accessory/pod_hair = GLOB.pod_hair_list[value] - for (var/pod_name in GLOB.pod_hair_list) - var/datum/sprite_accessory/pod_hair = GLOB.pod_hair_list[pod_name] - if(pod_hair.locked) - continue + var/icon/icon_with_hair = icon('icons/mob/human/bodyparts_greyscale.dmi', "pod_head_m") - var/icon/icon_with_hair = new(pod_head) - var/icon/icon_adj = icon(pod_hair.icon, "m_pod_hair_[pod_hair.icon_state]_ADJ") - var/icon/icon_front = icon(pod_hair.icon, "m_pod_hair_[pod_hair.icon_state]_FRONT") - icon_adj.Blend(icon_front, ICON_OVERLAY) - icon_with_hair.Blend(icon_adj, ICON_OVERLAY) - icon_with_hair.Scale(64, 64) - icon_with_hair.Crop(15, 64, 15 + 31, 64 - 31) - icon_with_hair.Blend(COLOR_GREEN, ICON_MULTIPLY) + var/icon/icon_adj = icon(pod_hair.icon, "m_pod_hair_[pod_hair.icon_state]_ADJ") + var/icon/icon_front = icon(pod_hair.icon, "m_pod_hair_[pod_hair.icon_state]_FRONT") + icon_adj.Blend(icon_front, ICON_OVERLAY) + icon_with_hair.Blend(icon_adj, ICON_OVERLAY) + icon_with_hair.Scale(64, 64) + icon_with_hair.Crop(15, 64, 15 + 31, 64 - 31) + icon_with_hair.Blend(COLOR_GREEN, ICON_MULTIPLY) - values[pod_hair.name] = icon_with_hair - - return values + return icon_with_hair /datum/preference/choiced/pod_hair/create_default_value() return pick(assoc_to_keys_features(GLOB.pod_hair_list)) diff --git a/code/modules/client/preferences/species_features/vampire.dm b/code/modules/client/preferences/species_features/vampire.dm index 710dd37a1f2..5ecdae7b1bf 100644 --- a/code/modules/client/preferences/species_features/vampire.dm +++ b/code/modules/client/preferences/species_features/vampire.dm @@ -11,12 +11,14 @@ return "Inoculated" //eh, have em try out the mechanic first /datum/preference/choiced/vampire_status/init_possible_values() - var/list/values = list() + return list("Inoculated", "Outcast") - values["Inoculated"] = icon('icons/obj/drinks/drinks.dmi', "bloodglass") - values["Outcast"] = icon('icons/obj/medical/bloodpack.dmi', "generic_bloodpack") - - return values +/datum/preference/choiced/vampire_status/icon_for(value) + switch (value) + if ("Inoculated") + return icon('icons/obj/drinks/drinks.dmi', "bloodglass") + if ("Outcast") + return icon('icons/obj/medical/bloodpack.dmi', "generic_bloodpack") ///list that stores a vampire house name for each department GLOBAL_LIST_EMPTY(vampire_houses) diff --git a/code/modules/client/preferences/ui_style.dm b/code/modules/client/preferences/ui_style.dm index 08f1af6c7dd..64a82b592c6 100644 --- a/code/modules/client/preferences/ui_style.dm +++ b/code/modules/client/preferences/ui_style.dm @@ -6,18 +6,16 @@ should_generate_icons = TRUE /datum/preference/choiced/ui_style/init_possible_values() - var/list/values = list() + return assoc_to_keys(GLOB.available_ui_styles) - for (var/style in GLOB.available_ui_styles) - var/icon/icons = GLOB.available_ui_styles[style] +/datum/preference/choiced/ui_style/icon_for(value) + var/icon/icons = GLOB.available_ui_styles[value] - var/icon/icon = icon(icons, "hand_r") - icon.Crop(1, 1, world.icon_size * 2, world.icon_size) - icon.Blend(icon(icons, "hand_l"), ICON_OVERLAY, world.icon_size) + var/icon/icon = icon(icons, "hand_r") + icon.Crop(1, 1, world.icon_size * 2, world.icon_size) + icon.Blend(icon(icons, "hand_l"), ICON_OVERLAY, world.icon_size) - values[style] = icon - - return values + return icon /datum/preference/choiced/ui_style/create_default_value() return GLOB.available_ui_styles[1] diff --git a/code/modules/modular_computers/computers/item/role_tablet_presets.dm b/code/modules/modular_computers/computers/item/role_tablet_presets.dm index 7cbde66267f..506be4a772a 100644 --- a/code/modules/modular_computers/computers/item/role_tablet_presets.dm +++ b/code/modules/modular_computers/computers/item/role_tablet_presets.dm @@ -258,7 +258,7 @@ /obj/item/modular_computer/pda/shaftminer name = "shaft miner PDA" greyscale_config = /datum/greyscale_config/tablet/stripe_thick - greyscale_colors = "#927444#D6B328#6C3BA1" + greyscale_colors = "#927444#8b4c31#4c202d" starting_programs = list( /datum/computer_file/program/skill_tracker, ) diff --git a/code/modules/unit_tests/preferences.dm b/code/modules/unit_tests/preferences.dm index 950b1dc281c..626d5b48466 100644 --- a/code/modules/unit_tests/preferences.dm +++ b/code/modules/unit_tests/preferences.dm @@ -49,3 +49,29 @@ continue TEST_ASSERT(!isnull(preference.main_feature_name), "Preference [preference_type] does not have a main_feature_name set!") + +/// Validates that every choiced preference with should_generate_icons implements icon_for, +/// and that every one that doesn't, doesn't. +/datum/unit_test/preferences_should_generate_icons_sanity + +/datum/unit_test/preferences_should_generate_icons_sanity/Run() + for (var/preference_type in GLOB.preference_entries) + var/datum/preference/choiced/choiced_preference = GLOB.preference_entries[preference_type] + if (!istype(choiced_preference) || choiced_preference.abstract_type == preference_type) + continue + + var/list/values = choiced_preference.get_choices() + + if (choiced_preference.should_generate_icons) + for (var/value in values) + var/icon = choiced_preference.icon_for(value) + TEST_ASSERT(istype(icon, /icon) || ispath(icon), "[preference_type] gave [icon] as an icon for [value], which is not a valid value") + else + var/errored = FALSE + + try + choiced_preference.icon_for(values[1]) + catch + errored = TRUE + + TEST_ASSERT(errored, "[preference_type] implemented icon_for, but does not have should_generate_icons = TRUE") diff --git a/modular_skyrat/master_files/code/modules/client/preferences/_preference.dm b/modular_skyrat/master_files/code/modules/client/preferences/_preference.dm index a5ccd16e543..19cec000446 100644 --- a/modular_skyrat/master_files/code/modules/client/preferences/_preference.dm +++ b/modular_skyrat/master_files/code/modules/client/preferences/_preference.dm @@ -108,7 +108,7 @@ savefile_identifier = PREFERENCE_CHARACTER /// Path to the default sprite accessory - var/datum/sprite_accessory/default_accessory_type + var/datum/sprite_accessory/default_accessory_type = /datum/sprite_accessory/blank /// Path to the corresponding /datum/preference/toggle to check if part is enabled. var/datum/preference/toggle/type_to_check /// Generates icons from the provided mutant bodypart for use in icon-enabled selection boxes in the prefs window. @@ -124,6 +124,15 @@ var/part_enabled = is_part_enabled(preferences) return (passed_initial_check || overriding) && part_enabled +// icons are cached +/datum/preference/choiced/mutant_choice/icon_for(value) + if(!should_generate_icons) + // because of the way the unit tests are set up, we need this to crash here + CRASH("`icon_for()` was not implemented for [type], even though should_generate_icons = TRUE!") + + var/list/cached_icons = get_choices() + return cached_icons[value] + /// Allows for dynamic assigning of icon states. /datum/preference/choiced/mutant_choice/proc/generate_icon_state(datum/sprite_accessory/sprite_accessory, original_icon_state) return original_icon_state @@ -160,7 +169,7 @@ return list_of_accessories /datum/preference/choiced/mutant_choice/create_default_value() - return initial(default_accessory_type?.name) || "None" + return initial(default_accessory_type.name) /** * Is this part enabled by the player? @@ -204,6 +213,9 @@ if(!bodypart_is_visible) value = create_default_value() + if(value == "None") + return bodypart_is_visible + if(!target.dna.mutant_bodyparts[relevant_mutant_bodypart]) target.dna.mutant_bodyparts[relevant_mutant_bodypart] = list(MUTANT_INDEX_NAME = value, MUTANT_INDEX_COLOR_LIST = list("#FFFFFF", "#FFFFFF", "#FFFFFF"), MUTANT_INDEX_EMISSIVE_LIST = list(FALSE, FALSE, FALSE)) return bodypart_is_visible diff --git a/modular_skyrat/master_files/code/modules/client/preferences/clothing.dm b/modular_skyrat/master_files/code/modules/client/preferences/clothing.dm index 48f9df3be3c..8041e751783 100644 --- a/modular_skyrat/master_files/code/modules/client/preferences/clothing.dm +++ b/modular_skyrat/master_files/code/modules/client/preferences/clothing.dm @@ -1,6 +1,3 @@ -/datum/preference/choiced/socks/init_possible_values() - return generate_values_for_underwear(GLOB.socks_list, list("human_r_leg", "human_l_leg"), COLOR_ALMOST_BLACK, 0) - /datum/preference/choiced/socks/compile_constant_data() var/list/data = ..() @@ -16,9 +13,6 @@ var/datum/species/species = new species_type return !(TRAIT_NO_UNDERWEAR in species.inherent_traits) -/datum/preference/choiced/undershirt/init_possible_values() - return generate_values_for_underwear(GLOB.undershirt_list, list("human_chest_m", "human_r_arm", "human_l_arm", "human_r_leg", "human_l_leg", "human_r_hand", "human_l_hand"), COLOR_ALMOST_BLACK, 10) - /datum/preference/choiced/undershirt/compile_constant_data() var/list/data = ..() @@ -34,9 +28,6 @@ var/datum/species/species = new species_type return !(TRAIT_NO_UNDERWEAR in species.inherent_traits) -/datum/preference/choiced/underwear/init_possible_values() - return generate_values_for_underwear(GLOB.underwear_list, list("human_chest_m", "human_r_leg", "human_l_leg"), COLOR_ALMOST_BLACK, 5) - /datum/preference/choiced/underwear/is_accessible(datum/preferences/preferences) if (!..(preferences)) return FALSE diff --git a/modular_skyrat/master_files/code/modules/client/preferences/genitals.dm b/modular_skyrat/master_files/code/modules/client/preferences/genitals.dm index a2be968a8d1..3612f27243c 100644 --- a/modular_skyrat/master_files/code/modules/client/preferences/genitals.dm +++ b/modular_skyrat/master_files/code/modules/client/preferences/genitals.dm @@ -68,7 +68,7 @@ return (savefile_key in species.get_features()) /datum/preference/choiced/genital/create_default_value() - return initial(default_accessory_type?.name) || "None" + return initial(default_accessory_type.name) /datum/preference/choiced/genital/init_possible_values() return assoc_to_keys_features(GLOB.sprite_accessories[relevant_mutant_bodypart]) diff --git a/modular_skyrat/master_files/code/modules/client/preferences/mutant_parts.dm b/modular_skyrat/master_files/code/modules/client/preferences/mutant_parts.dm index cffc4ab6d5f..fd11a6bd3b5 100644 --- a/modular_skyrat/master_files/code/modules/client/preferences/mutant_parts.dm +++ b/modular_skyrat/master_files/code/modules/client/preferences/mutant_parts.dm @@ -81,7 +81,6 @@ /datum/preference/toggle/mutant_toggle/body_markings/apply_to_human(mob/living/carbon/human/target, value, datum/preferences/preferences) return FALSE - /datum/preference/choiced/mutant_choice/body_markings savefile_key = "feature_body_markings" relevant_mutant_bodypart = "body_markings" @@ -95,7 +94,6 @@ /datum/preference/choiced/mutant_choice/body_markings/apply_to_human(mob/living/carbon/human/target, value, datum/preferences/preferences) return FALSE - /datum/preference/tri_color/body_markings category = PREFERENCE_CATEGORY_SECONDARY_FEATURES savefile_identifier = PREFERENCE_CHARACTER @@ -124,7 +122,6 @@ /datum/preference/tri_bool/body_markings/apply_to_human(mob/living/carbon/human/target, value, datum/preferences/preferences) return FALSE - /// Tails /datum/preference/toggle/mutant_toggle/tail