diff --git a/code/_onclick/hud/screen/screen_setup.dm b/code/_onclick/hud/screen/screen_setup.dm index 62551d92fde..ebd2975ffba 100644 --- a/code/_onclick/hud/screen/screen_setup.dm +++ b/code/_onclick/hud/screen/screen_setup.dm @@ -20,5 +20,7 @@ /obj/screen/setup_preview/bg/Click(location, control, params) if(pref) pref.bgstate = next_in_list(pref.bgstate, pref.bgstate_options) - pref.update_preview_icon() + var/mob/living/carbon/human/dummy/mannequin/mannequin = get_mannequin(pref.client_ckey) + if(mannequin) + pref.update_character_previews(mannequin) return ..() diff --git a/code/modules/client/preference_setup/general/02_body.dm b/code/modules/client/preference_setup/general/02_body.dm index b8b913bda1d..70899b4f511 100644 --- a/code/modules/client/preference_setup/general/02_body.dm +++ b/code/modules/client/preference_setup/general/02_body.dm @@ -85,20 +85,25 @@ W.write("bgstate", pref.bgstate) /datum/category_item/player_setup_item/physical/body/sanitize_character() - - pref.skin_colour = pref.skin_colour || COLOR_BLACK - pref.eye_colour = pref.eye_colour || COLOR_BLACK + var/decl/species/mob_species = get_species_by_key(pref.species) + var/decl/bodytype/mob_bodytype = mob_species.get_bodytype_by_name(pref.bodytype) || mob_species.default_bodytype + if(mob_bodytype.appearance_flags & HAS_SKIN_COLOR) + pref.skin_colour = pref.skin_colour || mob_bodytype.base_color || COLOR_BLACK + else + pref.skin_colour = mob_bodytype.base_color || COLOR_BLACK + if(mob_bodytype.appearance_flags & HAS_EYE_COLOR) + pref.eye_colour = pref.eye_colour || mob_bodytype.base_eye_color || COLOR_BLACK + else + pref.eye_colour = mob_bodytype.base_eye_color || COLOR_BLACK pref.blood_type = sanitize_text(pref.blood_type, initial(pref.blood_type)) if(!pref.species || !(pref.species in get_playable_species())) pref.species = global.using_map.default_species - var/decl/species/mob_species = get_species_by_key(pref.species) if(!pref.blood_type || !(pref.blood_type in mob_species.blood_types)) pref.blood_type = pickweight(mob_species.blood_types) - var/decl/bodytype/mob_bodytype = mob_species.get_bodytype_by_name(pref.bodytype) || mob_species.default_bodytype var/low_skin_tone = mob_bodytype ? (35 - mob_bodytype.max_skin_tone()) : -185 sanitize_integer(pref.skin_tone, low_skin_tone, 34, initial(pref.skin_tone)) diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index e7a0ec50cce..5edf110a34c 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -401,7 +401,10 @@ var/global/list/time_prefs_fixed = list() character.backpack_setup = new(backpack, backpack_metadata["[backpack]"]) for(var/obj/item/organ/external/O in character.get_external_organs()) - O.clear_sprite_accessories(skip_update = TRUE) + for(var/decl/sprite_accessory_category/sprite_category in O.get_sprite_accessory_categories()) + if(!sprite_category.clear_in_pref_apply) + continue + O.clear_sprite_accessories_by_category(sprite_category.type, skip_update = TRUE) for(var/accessory_category in sprite_accessories) for(var/accessory in sprite_accessories[accessory_category]) diff --git a/code/modules/mob/living/carbon/human/human_appearance.dm b/code/modules/mob/living/carbon/human/human_appearance.dm index 728e531b698..c35f0b73bea 100644 --- a/code/modules/mob/living/carbon/human/human_appearance.dm +++ b/code/modules/mob/living/carbon/human/human_appearance.dm @@ -61,23 +61,28 @@ /mob/living/carbon/human/proc/reset_hair() var/decl/bodytype/root_bodytype = get_bodytype() + var/decl/sprite_accessory_category/hair/hair_category = GET_DECL(SAC_HAIR) var/list/valid_hairstyles = species?.get_available_accessories(root_bodytype, SAC_HAIR) if(length(valid_hairstyles)) - SET_HAIR_STYLE(src, pick(valid_hairstyles), TRUE) + var/body_default_hairstyles = LAZYACCESS(root_bodytype?.default_sprite_accessories, SAC_HAIR) + // Forgive us, but we need to set both hair color AND style at the same time... + set_organ_sprite_accessory_by_category(pick(valid_hairstyles), SAC_HAIR, GET_HAIR_COLOUR(src) || body_default_hairstyles?[body_default_hairstyles[1]] || hair_category.default_accessory_color, TRUE, TRUE, BP_HEAD, TRUE) else //this shouldn't happen var/new_hair = LAZYACCESS(root_bodytype?.default_sprite_accessories, SAC_HAIR) || /decl/sprite_accessory/hair/bald if(new_hair) - SET_HAIR_STYLE(src, new_hair, TRUE) + set_organ_sprite_accessory_by_category(new_hair[1], SAC_HAIR, new_hair[new_hair[1]] || hair_category.default_accessory_color, TRUE, TRUE, BP_HEAD, TRUE) + var/decl/sprite_accessory_category/facial_hair/facial_hair_category = GET_DECL(SAC_FACIAL_HAIR) var/list/valid_facial_hairstyles = species?.get_available_accessories(root_bodytype, SAC_FACIAL_HAIR) if(length(valid_facial_hairstyles)) - SET_FACIAL_HAIR_STYLE(src, pick(valid_facial_hairstyles), TRUE) + var/body_default_facial_hairstyles = LAZYACCESS(root_bodytype?.default_sprite_accessories, SAC_FACIAL_HAIR) + set_organ_sprite_accessory_by_category(pick(valid_facial_hairstyles), SAC_FACIAL_HAIR, GET_FACIAL_HAIR_COLOUR(src) || body_default_facial_hairstyles?[body_default_facial_hairstyles[1]] || facial_hair_category.default_accessory_color, TRUE, TRUE, BP_HEAD, TRUE) else //this shouldn't happen var/new_facial_hair = LAZYACCESS(root_bodytype?.default_sprite_accessories, SAC_FACIAL_HAIR) || /decl/sprite_accessory/facial_hair/shaved if(new_facial_hair) - SET_FACIAL_HAIR_STYLE(src, new_facial_hair, TRUE) + set_organ_sprite_accessory_by_category(new_facial_hair[1], SAC_FACIAL_HAIR, new_facial_hair[new_facial_hair[1]] || facial_hair_category.default_accessory_color, TRUE, TRUE, BP_HEAD, TRUE) update_hair() diff --git a/code/modules/modular_computers/file_system/programs/engineering/power_monitor.dm b/code/modules/modular_computers/file_system/programs/engineering/power_monitor.dm index 7a5ed3fee7a..3b5321fdf4b 100644 --- a/code/modules/modular_computers/file_system/programs/engineering/power_monitor.dm +++ b/code/modules/modular_computers/file_system/programs/engineering/power_monitor.dm @@ -65,7 +65,7 @@ // Build list of data from sensor readings. for(var/obj/machinery/power/sensor/S in grid_sensors) sensors.Add(list(list( - "name" = S.id_tag, + "name" = html_encode(S.id_tag), "alarm" = S.check_grid_warning() ))) if(S.id_tag == active_sensor) @@ -167,5 +167,5 @@ else if( href_list["setsensor"] ) - active_sensor = href_list["setsensor"] + active_sensor = html_decode(href_list["setsensor"]) . = 1 diff --git a/code/modules/organs/external/_external_icons.dm b/code/modules/organs/external/_external_icons.dm index 3ad0daef47d..76f373c0388 100644 --- a/code/modules/organs/external/_external_icons.dm +++ b/code/modules/organs/external/_external_icons.dm @@ -120,9 +120,22 @@ var/global/list/organ_icon_cache = list() owner.update_body() update_icon() +/obj/item/organ/external/proc/clear_sprite_accessories_by_category(var/accessory_category, var/skip_update = FALSE) + var/list/category_accessories = get_sprite_accessories_by_category(accessory_category) + category_accessories?.Cut() + _sprite_accessories?[accessory_category] = null + if(skip_update) + return + owner?.update_body(update_icons = TRUE) + /obj/item/organ/external/proc/get_sprite_accessories_by_category(var/accessory_category) return LAZYACCESS(_sprite_accessories, accessory_category) +/obj/item/organ/external/proc/get_sprite_accessory_categories() + . = list() + for(var/category_type in _sprite_accessories) + . += GET_DECL(category_type) + /obj/item/organ/external/proc/get_sprite_accessory_by_category(var/accessory_category) var/list/accessories = get_sprite_accessories_by_category(accessory_category) if(length(accessories)) @@ -178,7 +191,7 @@ var/global/list/organ_icon_cache = list() for(var/accessory in draw_accessories) var/decl/sprite_accessory/accessory_decl = GET_DECL(accessory) if(accessory_decl?.is_heritable) - LAZYADD(., accessory) + LAZYSET(., accessory, draw_accessories[accessory]) /obj/item/organ/external/proc/set_sprite_accessory_by_category(accessory_type, accessory_category, accessory_color, preserve_colour = TRUE, preserve_type = TRUE, skip_update) if(!accessory_category) @@ -198,7 +211,7 @@ var/global/list/organ_icon_cache = list() // We may only be setting colour, in which case we don't bother with a removal. if(preserve_type && !accessory_type) accessory_type = replacing_type - else + else if (accessory_type != replacing_type) remove_sprite_accessory(replacing_type, TRUE) // We have already done our removal above and have nothing further to set below. diff --git a/code/modules/power/sensors/powernet_sensor.dm b/code/modules/power/sensors/powernet_sensor.dm index f4266872ef0..8a02779ed2a 100644 --- a/code/modules/power/sensors/powernet_sensor.dm +++ b/code/modules/power/sensors/powernet_sensor.dm @@ -36,7 +36,10 @@ var/area/A = get_area(src) if(!A) return // in nullspace - id_tag = "[A.proper_name] #[sequential_id(A.name + "power/sensor")]" + var/suffix = uniqueness_repository.Generate(/datum/uniqueness_generator/id_sequential, "[A.proper_name]power/sensor", 1) // unlike sequential_id, starts at 1 instead of 100 + if(suffix == 1) + suffix = null + id_tag = "[A.proper_name][suffix ? " #[suffix]" : null]" name = "[id_tag] - powernet sensor" // Proc: check_grid_warning() diff --git a/code/modules/species/species.dm b/code/modules/species/species.dm index 4e5a5e2d3d3..2cafd661224 100644 --- a/code/modules/species/species.dm +++ b/code/modules/species/species.dm @@ -688,13 +688,14 @@ var/global/const/DEFAULT_SPECIES_HEALTH = 200 for(var/accessory in get_available_accessory_types(bodytype, accessory_category)) . += GET_DECL(accessory) -/decl/species/proc/get_available_accessory_types(bodytype, accessory_category) +/decl/species/proc/get_available_accessory_types(decl/bodytype/bodytype, accessory_category) if(!bodytype) bodytype = default_bodytype - var/list/available_accessories = LAZYACCESS(accessory_styles, accessory_category) + var/list/available_accessories = accessory_styles?[bodytype.type]?[accessory_category] if(!available_accessories) available_accessories = list() - LAZYSET(accessory_styles, accessory_category, available_accessories) + LAZYINITLIST(accessory_styles) + LAZYSET(accessory_styles[bodytype.type], accessory_category, available_accessories) var/decl/sprite_accessory_category/accessory_category_decl = GET_DECL(accessory_category) var/list/all_accessories = decls_repository.get_decls_of_subtype(accessory_category_decl.base_accessory_type) for(var/accessory_style in all_accessories) diff --git a/code/modules/sprite_accessories/_accessory_category.dm b/code/modules/sprite_accessories/_accessory_category.dm index ce41b362ad2..663699bf8f4 100644 --- a/code/modules/sprite_accessories/_accessory_category.dm +++ b/code/modules/sprite_accessories/_accessory_category.dm @@ -15,6 +15,8 @@ var/single_selection = TRUE /// Set to TRUE to apply these markings as defaults when bodytype is set. var/always_apply_defaults = FALSE + /// Whether the default accessories in this category are cleared when prefs are applied. + var/clear_in_pref_apply = FALSE /decl/sprite_accessory_category/validate() . = ..() diff --git a/code/modules/sprite_accessories/accessory_markings.dm b/code/modules/sprite_accessories/accessory_markings.dm index a55d64910b1..d37ab9e6acb 100644 --- a/code/modules/sprite_accessories/accessory_markings.dm +++ b/code/modules/sprite_accessories/accessory_markings.dm @@ -3,6 +3,7 @@ single_selection = FALSE base_accessory_type = /decl/sprite_accessory/marking uid = "acc_cat_markings" + clear_in_pref_apply = TRUE /decl/sprite_accessory/marking icon = 'icons/mob/human_races/species/default_markings.dmi' diff --git a/code/unit_tests/equipment_tests.dm b/code/unit_tests/equipment_tests.dm index e15fa9dbad6..6aefebbfbf8 100644 --- a/code/unit_tests/equipment_tests.dm +++ b/code/unit_tests/equipment_tests.dm @@ -146,7 +146,7 @@ failure_list += "[item] was equipped to [equipped_location] despite failing isEquipped (should not be equipped)." /datum/unit_test/equipment_slot_test/start_test() - var/mob/living/carbon/human/subject = new(get_safe_turf()) + var/mob/living/carbon/human/subject = new(get_safe_turf(), SPECIES_HUMAN) // force human so default map species doesn't mess with anything created_atoms |= subject var/list/failures = list()