diff --git a/code/__HELPERS/_hyper_helpers.dm b/code/__HELPERS/_hyper_helpers.dm new file mode 100644 index 000000000..be7a9e423 --- /dev/null +++ b/code/__HELPERS/_hyper_helpers.dm @@ -0,0 +1,10 @@ +GLOBAL_LIST_EMPTY(cosmetic_head) +GLOBAL_LIST_EMPTY(cosmetic_chest) +GLOBAL_LIST_EMPTY(cosmetic_arms) +GLOBAL_LIST_EMPTY(cosmetic_legs) + +/proc/init_cosmetic_parts(datum/cosmetic_part/type, global_list) + global_list = list("default") + for(var/subtype in subtypesof(type)) + var/datum/cosmetic_part/part = new subtype() + global_list[part.name] = part \ No newline at end of file diff --git a/code/__HELPERS/global_lists.dm b/code/__HELPERS/global_lists.dm index 9b5ac9395..32f6df4db 100644 --- a/code/__HELPERS/global_lists.dm +++ b/code/__HELPERS/global_lists.dm @@ -54,6 +54,14 @@ init_sprite_accessory_subtypes(/datum/sprite_accessory/vagina, GLOB.vagina_shapes_list) init_sprite_accessory_subtypes(/datum/sprite_accessory/breasts, GLOB.breasts_shapes_list) + + // hyper: cosmetic parts + init_cosmetic_parts(/datum/cosmetic_part/head, GLOB.cosmetic_head) + init_cosmetic_parts(/datum/cosmetic_part/chest, GLOB.cosmetic_chest) + init_cosmetic_parts(/datum/cosmetic_part/arms, GLOB.cosmetic_arms) + init_cosmetic_parts(/datum/cosmetic_part/legs, GLOB.cosmetic_legs) + // end cosmetic parts + GLOB.breasts_size_list = list ("a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o") //We need the list to choose from initialized, but it's no longer a sprite_accessory thing. GLOB.genital_fluids_list = list ("Milk", "Water", "Semen", "Femcum", "Honey") GLOB.gentlemans_organ_names = list("phallus", "willy", "dick", "prick", "member", "tool", "gentleman's organ", "cock", "wang", "knob", "dong", "joystick", "pecker", "johnson", "weenie", "tadger", "schlong", "thirsty ferret", "baloney pony", "schlanger") diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm index ed0434f2f..a00ef1b61 100644 --- a/code/__HELPERS/mobs.dm +++ b/code/__HELPERS/mobs.dm @@ -237,7 +237,13 @@ "ipc_antenna" = "None", "flavor_text" = "", "silicon_flavor_text" = "", - "ooc_text" = "")) + "ooc_text" = "", + "cosmetic_head" = "default", + "cosmetic_chest" = "default", + "cosmetic_l_arm" = "default", + "cosmetic_r_arm" = "default", + "cosmetic_l_leg" = "default", + "cosmetic_r_leg" = "default")) /proc/random_hair_style(gender) switch(gender) diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index d0abb7d46..c949954bf 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -102,6 +102,9 @@ GLOBAL_LIST_EMPTY(preferences_datums) //HS13 var/body_size = 100 //Body Size in percent var/can_get_preg = 0 //if they can get preggers + var/list/cosmetic_parts = list( + BODY_ZONE_L_ARM + ) //HS13 jobs var/sillyroles = FALSE //for clown and mime @@ -196,7 +199,13 @@ GLOBAL_LIST_EMPTY(preferences_datums) "flavor_text" = "", "silicon_flavor_text" = "", "ooc_text" = "", - "front_genitals_over_hair" = FALSE + "front_genitals_over_hair" = FALSE, + "cosmetic_head" = "default", + "cosmetic_chest" = "default", + "cosmetic_l_arm" = "default", + "cosmetic_r_arm" = "default", + "cosmetic_l_leg" = "default", + "cosmetic_r_leg" = "default" ) /// Security record note section diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm index 80fab69e6..a77f504f8 100644 --- a/code/modules/client/preferences_savefile.dm +++ b/code/modules/client/preferences_savefile.dm @@ -576,6 +576,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car all_quirks -= V cit_character_pref_load(S) + hyper_character_pref_load(S) return 1 @@ -671,6 +672,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car WRITE_FILE(S["all_quirks"] , all_quirks) cit_character_pref_save(S) + hyper_character_pref_save(S) return 1 diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 92ad4fa08..1765e6873 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -5,30 +5,24 @@ icon_state = "caucasian_m" appearance_flags = KEEP_TOGETHER|TILE_BOUND|PIXEL_SCALE|LONG_GLIDE + /mob/living/carbon/human/Initialize() add_verb(src, /mob/living/proc/mob_sleep) add_verb(src, /mob/living/proc/lay_down) time_initialized = world.time - //initialize limbs first create_bodyparts() - //initialize dna. for spawned humans; overwritten by other code create_dna(src) randomize_human(src) dna.initialize_dna() - if(dna.species) set_species(dna.species.type) - //initialise organs create_internal_organs() //most of it is done in set_species now, this is only for parent call physiology = new() - AddComponent(/datum/component/personal_crafting) - . = ..() - RegisterSignal(src, COMSIG_COMPONENT_CLEAN_ACT, /mob/living/carbon/human/clean_blood) diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm index fc87bd816..8b7c3cd5f 100644 --- a/code/modules/mob/living/carbon/human/species.dm +++ b/code/modules/mob/living/carbon/human/species.dm @@ -503,6 +503,9 @@ GLOBAL_LIST_EMPTY(roundstart_races) var/obj/item/bodypart/head/HD = H.get_bodypart(BODY_ZONE_HEAD) + // hyper edit: updates cosmetic part graphics + H.handle_cosmetic_parts() + if(HD && !(HAS_TRAIT(H, TRAIT_HUSK))) // lipstick if(H.lip_style && (LIPS in species_traits)) @@ -678,21 +681,17 @@ GLOBAL_LIST_EMPTY(roundstart_races) if("mam_tail" in mutant_bodyparts) if(H.wear_suit && (H.wear_suit.flags_inv & HIDETAUR) || (!H.dna.features["taur"] == "None")) bodyparts_to_add -= "mam_tail" - if("mam_waggingtail" in mutant_bodyparts) if(H.wear_suit && (H.wear_suit.flags_inv & HIDETAUR) || (!H.dna.features["taur"] == "None")) bodyparts_to_add -= "mam_waggingtail" else if ("mam_tail" in mutant_bodyparts) bodyparts_to_add -= "mam_waggingtail" - if("mam_ears" in mutant_bodyparts) if(!H.dna.features["mam_ears"] || H.dna.features["mam_ears"] == "None" || H.head && (H.head.flags_inv & HIDEEARS) || (H.wear_mask && (H.wear_mask.flags_inv & HIDEEARS)) || !HD || HD.status == BODYPART_ROBOTIC) bodyparts_to_add -= "mam_ears" - if("mam_snouts" in mutant_bodyparts) //Take a closer look at that snout! if((H.wear_mask && (H.wear_mask.flags_inv & HIDESNOUT)) || (H.head && (H.head.flags_inv & HIDESNOUT)) || !HD || HD.status == BODYPART_ROBOTIC) bodyparts_to_add -= "mam_snouts" - if("taur" in mutant_bodyparts) if(!H.dna.features["taur"] || H.dna.features["taur"] == "None" || (H.wear_suit && (H.wear_suit.flags_inv & HIDETAUR))) bodyparts_to_add -= "taur" diff --git a/code/modules/surgery/bodyparts/bodyparts.dm b/code/modules/surgery/bodyparts/bodyparts.dm index 4a1bc2113..d9f140759 100644 --- a/code/modules/surgery/bodyparts/bodyparts.dm +++ b/code/modules/surgery/bodyparts/bodyparts.dm @@ -44,6 +44,13 @@ var/skin_tone = "" var/body_gender = "" var/species_id = "" + /** + * HYPER: when getting the appearance of a limb, the game will check + * for `cosmetic_icon` first. if there is none, it will default back + * to `species_id`. this allows us to use custom body part types for + * each limb in character customization. + */ + var/cosmetic_icon var/color_src var/base_bp_icon //Overrides the icon being used for this limb. This is mainly for downstreams, implemented and maintained as a favor in return for implementing synths. And also because should_draw_* for icon overrides was pretty messy. You're welcome. var/should_draw_gender = FALSE @@ -436,6 +443,7 @@ var/image_dir = 0 var/icon_gender = (body_gender == FEMALE) ? "f" : "m" //gender of the icon, if applicable + var/is_husk = species_id == "husk" if(dropped) image_dir = SOUTH @@ -464,7 +472,7 @@ if(animal_origin) if(is_organic_limb()) limb.icon = 'icons/mob/animal_parts.dmi' - if(species_id == "husk") + if(is_husk) limb.icon_state = "[animal_origin]_husk_[body_zone]" else limb.icon_state = "[animal_origin]_[body_zone]" @@ -476,24 +484,27 @@ if((body_zone != BODY_ZONE_HEAD && body_zone != BODY_ZONE_CHEST)) should_draw_gender = FALSE + /// HYPER: allow for custom limb icons in character customization + var/limb_style = !isnull(cosmetic_icon) ? cosmetic_icon : species_id + if(is_organic_limb()) limb.icon = base_bp_icon || 'icons/mob/human_parts.dmi' if(should_draw_gender) - limb.icon_state = "[species_id]_[body_zone]_[icon_gender]" + limb.icon_state = "[limb_style]_[body_zone]_[icon_gender]" else if (use_digitigrade) if(base_bp_icon == DEFAULT_BODYPART_ICON_ORGANIC) //Compatibility hack for the current iconset. limb.icon_state = "digitigrade_[use_digitigrade]_[body_zone]" else - limb.icon_state = "[species_id]_digitigrade_[use_digitigrade]_[body_zone]" + limb.icon_state = "[limb_style]_digitigrade_[use_digitigrade]_[body_zone]" else - limb.icon_state = "[species_id]_[body_zone]" + limb.icon_state = "[limb_style]_[body_zone]" // Body markings if(body_markings) - if(species_id == "husk") + if(is_husk) marking = image('modular_citadel/icons/mob/markings_notmammals.dmi', "husk_[body_zone]", -MARKING_LAYER, image_dir) - else if(species_id == "husk" && use_digitigrade) + else if(is_husk && use_digitigrade) marking = image('modular_citadel/icons/mob/markings_notmammals.dmi', "husk_digitigrade_[use_digitigrade]_[body_zone]", -MARKING_LAYER, image_dir) else if(!use_digitigrade) @@ -508,10 +519,10 @@ // Citadel End if(aux_zone) - aux = image(limb.icon, "[species_id]_[aux_zone]", -aux_layer, image_dir) + aux = image(limb.icon, "[limb_style]_[aux_zone]", -aux_layer, image_dir) . += aux if(body_markings) - if(species_id == "husk") + if(is_husk) auxmarking = image('modular_citadel/icons/mob/markings_notmammals.dmi', "husk_[aux_zone]", -aux_layer, image_dir) else auxmarking = image(body_markings_icon, "[body_markings]_[aux_zone]", -aux_layer, image_dir) @@ -528,16 +539,16 @@ aux = image(limb.icon, "[aux_zone]", -aux_layer, image_dir) . += aux if(!isnull(auxmarking)) - if(species_id == "husk") + if(is_husk) auxmarking = image('modular_citadel/icons/mob/markings_notmammals.dmi', "husk_[aux_zone]", -aux_layer, image_dir) else auxmarking = image(body_markings_icon, "[body_markings]_[aux_zone]", -aux_layer, image_dir) . += auxmarking if(!isnull(body_markings)) - if(species_id == "husk") + if(is_husk) marking = image('modular_citadel/icons/mob/markings_notmammals.dmi', "husk_[body_zone]", -MARKING_LAYER, image_dir) - else if(species_id == "husk" && use_digitigrade) + else if(is_husk && use_digitigrade) marking = image('modular_citadel/icons/mob/markings_notmammals.dmi', "husk_digitigrade_[use_digitigrade]_[body_zone]", -MARKING_LAYER, image_dir) else if(!use_digitigrade) @@ -560,7 +571,7 @@ auxmarking.color = list(markings_color) if(!isnull(body_markings)) - if(species_id == "husk") + if(is_husk) marking.color = "#141414" else marking.color = list(markings_color) diff --git a/hyperstation/code/modules/client/hyper_pref_savefile.dm b/hyperstation/code/modules/client/hyper_pref_savefile.dm new file mode 100644 index 000000000..769e3b122 --- /dev/null +++ b/hyperstation/code/modules/client/hyper_pref_savefile.dm @@ -0,0 +1,22 @@ +/datum/preferences/proc/hyper_character_pref_load(savefile/S) + S["feature_cosmetic_head"] >> features["cosmetic_head"] + S["feature_cosmetic_chest"] >> features["cosmetic_chest"] + S["feature_cosmetic_l_arm"] >> features["cosmetic_l_arm"] + S["feature_cosmetic_r_arm"] >> features["cosmetic_r_arm"] + S["feature_cosmetic_l_leg"] >> features["cosmetic_l_leg"] + S["feature_cosmetic_r_leg"] >> features["cosmetic_r_leg"] + features["cosmetic_head"] = sanitize_inlist(features["cosmetic_head"], GLOB.cosmetic_head, "default") + features["cosmetic_chest"] = sanitize_inlist(features["cosmetic_chest"], GLOB.cosmetic_chest, "default") + features["cosmetic_l_arm"] = sanitize_inlist(features["cosmetic_l_arm"], GLOB.cosmetic_arms, "default") + features["cosmetic_r_arm"] = sanitize_inlist(features["cosmetic_r_arm"], GLOB.cosmetic_arms, "default") + features["cosmetic_l_leg"] = sanitize_inlist(features["cosmetic_l_leg"], GLOB.cosmetic_legs, "default") + features["cosmetic_r_leg"] = sanitize_inlist(features["cosmetic_r_leg"], GLOB.cosmetic_legs, "default") + + +/datum/preferences/proc/hyper_character_pref_save(savefile/S) + WRITE_FILE(S["feature_cosmetic_head"], features["cosmetic_head"]) + WRITE_FILE(S["feature_cosmetic_chest"], features["cosmetic_chest"]) + WRITE_FILE(S["feature_cosmetic_l_arm"], features["cosmetic_l_arm"]) + WRITE_FILE(S["feature_cosmetic_r_arm"], features["cosmetic_r_arm"]) + WRITE_FILE(S["feature_cosmetic_l_leg"], features["cosmetic_l_leg"]) + WRITE_FILE(S["feature_cosmetic_r_leg"], features["cosmetic_r_leg"]) \ No newline at end of file diff --git a/hyperstation/code/modules/mob/dead/new_player/cosmetic_parts.dm b/hyperstation/code/modules/mob/dead/new_player/cosmetic_parts.dm new file mode 100644 index 000000000..f5d11656c --- /dev/null +++ b/hyperstation/code/modules/mob/dead/new_player/cosmetic_parts.dm @@ -0,0 +1,29 @@ +/* +COSMETIC PARTS + +this system allows you to change the _base_ appearance of a limb independent +of species or markings. this, for example, allows us to create "hybrids" like a +mammal with avian legs. + +keep in mind that this does not change the species of a leg! in the above example, +the mammal's bird-legs are still mammal legs. this matters in some places, like +body part transplants; mis-matched species will cause extra damage if the surgery +fails and the part is rejected. so you can't attach mammal-bird legs to avians +safely. +*/ + +/datum/cosmetic_part + var/name + var/icon = 'hyperstation/icons/mob/char_parts.dmi' + var/icon_state + var/support_digitigrade = TRUE + +/datum/cosmetic_part/head +/datum/cosmetic_part/chest +/datum/cosmetic_part/arms +/datum/cosmetic_part/legs + +/datum/cosmetic_part/legs/avian + name = "avian" + icon = 'modular_citadel/icons/mob/mutant_bodyparts.dmi' + icon_state = "avian" \ No newline at end of file diff --git a/hyperstation/code/modules/mob/living/carbon/human/cosmetic_part_handler.dm b/hyperstation/code/modules/mob/living/carbon/human/cosmetic_part_handler.dm new file mode 100644 index 000000000..f33cb1e7a --- /dev/null +++ b/hyperstation/code/modules/mob/living/carbon/human/cosmetic_part_handler.dm @@ -0,0 +1,18 @@ +/obj/item/bodypart/proc/apply_cosmetic(datum/cosmetic_part/part) + if(!is_organic_limb() || animal_origin || !part) + return + cosmetic_icon = part.icon_state + icon = part.icon + +/mob/living/carbon/human/proc/handle_cosmetic_parts() + var/features = src.dna.features + var/list/body_zones = list(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG) + for(var/I in body_zones) + var/zone = body_zones[I] + var/cosmetic_pref = features["cosmetic_" + zone] + if(!istype(cosmetic_pref, /datum/cosmetic_part)) + continue + var/datum/cosmetic_part/part = cosmetic_pref + var/obj/item/bodypart/body_part = get_bodypart(zone) + if(body_part && part) + body_part.apply_cosmetic(part) \ No newline at end of file diff --git a/hyperstation/icons/mob/char_parts.dmi b/hyperstation/icons/mob/char_parts.dmi new file mode 100644 index 000000000..f082396ac Binary files /dev/null and b/hyperstation/icons/mob/char_parts.dmi differ diff --git a/modular_citadel/code/modules/client/preferences_savefile.dm b/modular_citadel/code/modules/client/preferences_savefile.dm index fae7e9e0d..3067e680a 100644 --- a/modular_citadel/code/modules/client/preferences_savefile.dm +++ b/modular_citadel/code/modules/client/preferences_savefile.dm @@ -2,9 +2,9 @@ //ipcs S["feature_ipc_screen"] >> features["ipc_screen"] S["feature_ipc_antenna"] >> features["ipc_antenna"] - features["ipc_screen"] = sanitize_inlist(features["ipc_screen"], GLOB.ipc_screens_list) features["ipc_antenna"] = sanitize_inlist(features["ipc_antenna"], GLOB.ipc_antennas_list) + //Citadel features["flavor_text"] = sanitize_text(features["flavor_text"], initial(features["flavor_text"])) features["ooc_text"] = sanitize_text(features["ooc_text"], initial(features["ooc_text"])) @@ -35,6 +35,7 @@ LAZYADD(chosen_gear, path) gear_points -= initial(path.cost) + /datum/preferences/proc/cit_character_pref_save(savefile/S) //ipcs WRITE_FILE(S["feature_ipc_screen"], features["ipc_screen"]) diff --git a/tgstation.dme b/tgstation.dme index b6c7c761e..749acf8a4 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -119,6 +119,7 @@ #include "code\__DEFINES\wires.dm" #include "code\__DEFINES\dcs\signals.dm" #include "code\__HELPERS\_cit_helpers.dm" +#include "code\__HELPERS\_hyper_helpers.dm" #include "code\__HELPERS\_lists.dm" #include "code\__HELPERS\_logging.dm" #include "code\__HELPERS\_string_lists.dm" @@ -3156,6 +3157,7 @@ #include "hyperstation\code\modules\cargo\sweatshop\metal.dm" #include "hyperstation\code\modules\cargo\sweatshop\sweatshop.dm" #include "hyperstation\code\modules\cargo\sweatshop\wooden.dm" +#include "hyperstation\code\modules\client\hyper_pref_savefile.dm" #include "hyperstation\code\modules\client\loadout\glasses.dm" #include "hyperstation\code\modules\client\loadout\gloves.dm" #include "hyperstation\code\modules\client\loadout\neck.dm" @@ -3178,9 +3180,11 @@ #include "hyperstation\code\modules\mining\shelters.dm" #include "hyperstation\code\modules\mining\equipment\survival_pod.dm" #include "hyperstation\code\modules\mob\mob_helpers.dm" +#include "hyperstation\code\modules\mob\dead\new_player\cosmetic_parts.dm" #include "hyperstation\code\modules\mob\dead\new_player\sprite_accessories.dm" #include "hyperstation\code\modules\mob\living\status_indicators.dm" #include "hyperstation\code\modules\mob\living\carbon\carbon.dm" +#include "hyperstation\code\modules\mob\living\carbon\human\cosmetic_part_handler.dm" #include "hyperstation\code\modules\mob\living\silicon\robot\robot.dm" #include "hyperstation\code\modules\mob\living\silicon\robot\robot_modules.dm" #include "hyperstation\code\modules\mob\living\simple_animal\friendly\chicken_types.dm"