diff --git a/San_Additions/BodyMarkings/body_markings_mod.dm b/San_Additions/BodyMarkings/body_markings_mod.dm new file mode 100644 index 0000000000000..fc9f42cecc938 --- /dev/null +++ b/San_Additions/BodyMarkings/body_markings_mod.dm @@ -0,0 +1,93 @@ +/* + Let's try to put as much as possible as a mod file +*/ + +// Initialization + +var/global/list/body_marking_styles_list = list() //stores /datum/sprite_accessory/marking indexed by name + +/hook/global_init/makeDatumRefLists() + ..() + var/list/paths = list() + //Body markings - Initialise all /datum/sprite_accessory/marking into an list indexed by marking name + paths = typesof(/datum/sprite_accessory/marking) - /datum/sprite_accessory/marking + for(var/path in paths) + var/datum/sprite_accessory/marking/M = new path() + body_marking_styles_list[M.name] = M + + return 1 + +// DNA + +/datum/dna + var/list/body_markings = list() + +/datum/dna/ResetUIFrom(var/mob/living/carbon/human/character) + ..() + body_markings.Cut() + for(var/obj/item/organ/external/E in character.organs) + if(E.markings.len) + body_markings[E.organ_tag] = E.markings.Copy() + UpdateUI() + +/mob/UpdateAppearance(var/list/UI=null) + if(..()) + //Body markings + var/mob/living/carbon/human/H = src + for(var/tag in dna.body_markings) + var/obj/item/organ/external/E = H.organs_by_name[tag] + if(E) + var/list/marklist = dna.body_markings[tag] + E.markings = marklist.Copy() + + H.force_update_limbs() + H.update_body() + H.update_eyes() + H.update_hair() + + return 1 + else + return 0 + +datum/preferences + var/list/body_markings = list() // "name" = "#rgbcolor" + +/obj/item/organ/external + var/list/markings = list() // Markings (body_markings) to apply to the icon + + +/obj/item/organ/external/head/get_icon() + ..() + //Body markings, does not include head, duplicated (sadly) above. + for(var/M in markings) + var/datum/sprite_accessory/marking/mark_style = markings[M]["datum"] + var/icon/mark_s = new/icon("icon" = mark_style.icon, "icon_state" = "[mark_style.icon_state]-[organ_tag]") + mark_s.Blend(markings[M]["color"], ICON_ADD) + overlays |= mark_s //So when it's not on your body, it has icons + mob_icon.Blend(mark_s, ICON_OVERLAY) //So when it's on your body, it has icons + icon_cache_key += "[M][markings[M]["color"]]" + return mob_icon + +/obj/item/organ/external/get_icon() + ..() + update_icon() + //Head markings, duplicated (sadly) below. + for(var/M in markings) + var/datum/sprite_accessory/marking/mark_style = markings[M]["datum"] + var/icon/mark_s = new/icon("icon" = mark_style.icon, "icon_state" = "[mark_style.icon_state]-[organ_tag]") + mark_s.Blend(markings[M]["color"], ICON_ADD) + overlays |= mark_s //So when it's not on your body, it has icons + mob_icon.Blend(mark_s, ICON_OVERLAY) //So when it's on your body, it has icons + icon_cache_key += "[M][markings[M]["color"]]" + return mob_icon + +/obj/item/organ/external/update_icon(var/regenerate = 0) + ..() + //Body markings, does not include head, duplicated (sadly) above. + for(var/M in markings) + var/datum/sprite_accessory/marking/mark_style = markings[M]["datum"] + var/icon/mark_s = new/icon("icon" = mark_style.icon, "icon_state" = "[mark_style.icon_state]-[organ_tag]") + mark_s.Blend(markings[M]["color"], ICON_ADD) + overlays |= mark_s //So when it's not on your body, it has icons + mob_icon.Blend(mark_s, ICON_OVERLAY) //So when it's on your body, it has icons + icon_cache_key += "[M][markings[M]["color"]]" \ No newline at end of file diff --git a/San_Additions/BodyMarkings/bodymarkings.dm b/San_Additions/BodyMarkings/bodymarkings.dm new file mode 100644 index 0000000000000..28310ccd1fe3b --- /dev/null +++ b/San_Additions/BodyMarkings/bodymarkings.dm @@ -0,0 +1,253 @@ + +/* +//////////////////////////// +/ =--------------------= / +/ == Body Markings == / +/ =--------------------= / +//////////////////////////// +*/ +/datum/sprite_accessory + // If only this ckey can get this body marking to show on their list of bodymarkings + // Don't init here + var/list/ckey_allowed + +/datum/sprite_accessory/marking + icon = 'bodymarkings.dmi' + do_colouration = 1 //Almost all of them have it, COLOR_ADD + + //Empty list is unrestricted. Should only restrict the ones that make NO SENSE on other species, + //like Tajara inner-ear coloring overlay stuff. + species_allowed = list() + + var/body_parts = list() //A list of bodyparts this covers, in organ_tag defines + //Reminder: BP_L_FOOT,BP_R_FOOT,BP_L_LEG,BP_R_LEG,BP_L_ARM,BP_R_ARM,BP_L_HAND,BP_R_HAND,BP_CHEST,BP_GROIN,BP_HEAD + + + // TATTOOS + // WORN BY HUMANS + tat_heart + name = "Tattoo (Heart, Torso)" + icon_state = "tat_heart" + body_parts = list(BP_CHEST) + species_allowed = list("Human") + + tat_heart + name = "Tattoo (Heart, Torso, Centered)" + icon_state = "tat_heart_center" + body_parts = list(BP_CHEST) + species_allowed = list("Human") + + tat_hive + name = "Tattoo (Hive, Back)" + icon_state = "tat_hive" + body_parts = list(BP_CHEST) + species_allowed = list("Human") + + tat_nightling + name = "Tattoo (Nightling, Back)" + icon_state = "tat_nightling" + body_parts = list(BP_CHEST) + species_allowed = list("Human") + + tat_campbell + name = "Tattoo (Campbell, R.Arm)" + icon_state = "tat_campbell" + body_parts = list(BP_R_ARM) + species_allowed = list("Human") + + tat_tiger + name = "Tattoo (Tiger Stripes, Body)" + icon_state = "tiger" + body_parts = list(BP_CHEST,BP_GROIN) + species_allowed = list("Human") + + tat_tiger_l_arm + name = "Tattoo (Tiger Stripes, left arm)" + icon_state = "tiger" + body_parts = list(BP_L_ARM) + species_allowed = list("Human") + + tat_tiger_r_arm + name = "Tattoo (Tiger Stripes, right arm)" + icon_state = "tiger" + body_parts = list(BP_R_ARM) + species_allowed = list("Human") + + tat_tiger_l_leg + name = "Tattoo (Tiger Stripes, left leg)" + icon_state = "tiger" + body_parts = list(BP_L_LEG, BP_L_FOOT) + species_allowed = list("Human") + + tat_tiger_r_leg + name = "Tattoo (Tiger Stripes, right leg)" + icon_state = "tiger" + body_parts = list(BP_R_LEG, BP_R_FOOT) + species_allowed = list("Human") + + tat_tiger_head + name = "Tattoo (Tiger Stripes Head, Minor)" + icon_state = "tigerhead" + body_parts = list(BP_HEAD) + species_allowed = list("Human") + + yakuza_tattoo + name = "Tattoo (Yakuza, Chest)" + icon_state = "yakuza" + body_parts = list(BP_CHEST) + species_allowed = list("Human") + + bands + name = "Color Bands" + icon_state = "bands" + body_parts = list(BP_L_FOOT,BP_R_FOOT,BP_L_LEG,BP_R_LEG,BP_L_ARM,BP_R_ARM,BP_L_HAND,BP_R_HAND,BP_CHEST,BP_GROIN) + species_allowed = list("Human") + + bandsface + name = "Color Bands (Face)" + icon_state = "bandsface" + body_parts = list(BP_HEAD) + species_allowed = list("Human") + + + + //Taj specific stuff + taj_belly + name = "Belly Fur (Taj)" + icon_state = "taj_belly" + body_parts = list(BP_CHEST) + species_allowed = list("Tajara") + + taj_bellyfull + name = "Belly Fur Wide (Taj)" + icon_state = "taj_bellyfull" + body_parts = list(BP_CHEST) + species_allowed = list("Tajara") + + taj_nose + name = "Nose Color (Taj)" + icon_state = "taj_nose" + body_parts = list(BP_HEAD) + species_allowed = list("Tajara") + + taj_crest + name = "Chest Fur Crest (Taj)" + icon_state = "taj_crest" + body_parts = list(BP_CHEST) + species_allowed = list("Tajara") + + taj_muzzle + name = "Muzzle Color (Taj)" + icon_state = "taj_muzzle" + body_parts = list(BP_HEAD) + species_allowed = list("Tajara") + + taj_face + name = "Cheeks Color (Taj)" + icon_state = "taj_face" + body_parts = list(BP_HEAD) + species_allowed = list("Tajara") + + taj_all + name = "All Taj Head (Taj)" + icon_state = "taj_all" + body_parts = list(BP_HEAD) + species_allowed = list("Tajara") + + shaggy_mane + name = "Shaggy mane" + icon_state = "shaggy" + body_parts = list(BP_CHEST) + species_allowed = list("Tajara") + + saber_teeth + name = "Saber teeth" + icon_state = "saber" + body_parts = list(BP_HEAD) + species_allowed = list("Tajara") + + fangs + name = "Fangs" + icon_state = "fangs" + body_parts = list(BP_HEAD) + species_allowed = list("Tajara") + + tiger_stripes + name = "Tiger Stripes" + icon_state = "tiger" + body_parts = list(BP_L_FOOT,BP_R_FOOT,BP_L_LEG,BP_R_LEG,BP_L_ARM,BP_R_ARM,BP_CHEST,BP_GROIN) + species_allowed = list("Tajara") //There's a tattoo for non-cats + + tigerface + name = "Tiger Stripes (Head, Major)" + icon_state = "tigerface" + body_parts = list(BP_HEAD) + species_allowed = list("Tajara") //There's a tattoo for non-cats + + taj_paw_socks + name = "Socks Coloration (Taj)" + icon_state = "taj_pawsocks" + body_parts = list(BP_L_FOOT,BP_R_FOOT,BP_L_LEG,BP_R_LEG,BP_L_ARM,BP_R_ARM,BP_L_HAND,BP_R_HAND) + species_allowed = list("Tajara") + + taj_paw_socks_arms + name = "Socks Coloration (Taj, arms)" + icon_state = "taj_pawsocks" + body_parts = list(BP_L_ARM,BP_R_ARM,BP_L_HAND,BP_R_HAND) + species_allowed = list("Tajara") + + taj_paw_socks_legs + name = "Socks Coloration (Taj, legs)" + icon_state = "taj_pawsocks" + body_parts = list(BP_L_FOOT,BP_R_FOOT,BP_L_LEG,BP_R_LEG) + species_allowed = list("Tajara") + + //Una specific stuff + una_face + name = "Face Color (Unathi)" + icon_state = "una_face" + body_parts = list(BP_HEAD) + species_allowed = list("Unathi") + + una_facelow + name = "Face Color Low (Unathi)" + icon_state = "una_facelow" + body_parts = list(BP_HEAD) + species_allowed = list("Unathi") + + una_scutes + name = "Scutes (Unathi)" + icon_state = "una_scutes" + body_parts = list(BP_CHEST) + species_allowed = list("Unathi") + + backstripe + name = "Back Stripe (Unathi)" + icon_state = "backstripe" + body_parts = list(BP_CHEST) + species_allowed = list("Unathi") + + una_paw_socks + name = "Socks Coloration (Una)" + icon_state = "una_pawsocks" + body_parts = list(BP_L_FOOT,BP_R_FOOT,BP_L_LEG,BP_R_LEG,BP_L_ARM,BP_R_ARM,BP_L_HAND,BP_R_HAND) + species_allowed = list("Unathi") + + una_paw_socks_arms + name = "Socks Coloration (Una)" + icon_state = "una_pawsocks" + body_parts = list(BP_L_ARM,BP_R_ARM,BP_L_HAND,BP_R_HAND) + species_allowed = list("Unathi") + + una_paw_socks_legs + name = "Socks Coloration (Una)" + icon_state = "una_pawsocks" + body_parts = list(BP_L_FOOT,BP_R_FOOT,BP_L_LEG,BP_R_LEG) + species_allowed = list("Unathi") + + // Snowflakey stuff + doubleeye + name = "Double eyes" + icon_state = "doubleeye" + body_parts = list(BP_HEAD) + ckey_allowed = list("jglitch") diff --git a/San_Additions/BodyMarkings/bodymarkings.dmi b/San_Additions/BodyMarkings/bodymarkings.dmi new file mode 100644 index 0000000000000..e42700989605d Binary files /dev/null and b/San_Additions/BodyMarkings/bodymarkings.dmi differ diff --git a/baystation12.dme b/baystation12.dme index c6479f4e94300..7df11b55205de 100644 --- a/baystation12.dme +++ b/baystation12.dme @@ -2433,6 +2433,10 @@ #include "San_Additions\barra_do.dm" #include "San_Additions\catwalk.dm" #include "San_Additions\cure_steps.dm" +#include "San_Additions\FrontFlip.dm" +#include "San_Additions\Tajaran_Necesidad_Dormir.dm" +#include "San_Additions\BodyMarkings\body_markings_mod.dm" +#include "San_Additions\BodyMarkings\bodymarkings.dm" #include "San_Additions\Field of View\FieldOfView.dm" #include "San_Additions\objectives_dreyfus\debugging.dm" #include "San_Additions\objectives_dreyfus\objectives.dm" diff --git a/code/_helpers/global_lists.dm b/code/_helpers/global_lists.dm index 12b903aee5eab..bccb9e17816f9 100644 --- a/code/_helpers/global_lists.dm +++ b/code/_helpers/global_lists.dm @@ -142,6 +142,7 @@ var/global/list/string_slot_flags = list( facial_hair_styles_male_list += H.name facial_hair_styles_female_list += H.name + //Surgery Steps - Initialize all /datum/surgery_step into a list paths = typesof(/datum/surgery_step)-/datum/surgery_step for(var/T in paths) diff --git a/code/datums/underwear/underwear.dm b/code/datums/underwear/underwear.dm index 0c93cc6e089d3..d39a04d9b1b1b 100644 --- a/code/datums/underwear/underwear.dm +++ b/code/datums/underwear/underwear.dm @@ -33,6 +33,7 @@ datum/category_group/underwear/dd_SortValue() sort_order = 4 // Undershirts currently have the highest sort order because they may cover both underwear and socks. category_item_type = /datum/category_item/underwear/undershirt + /******************* * Category entries * *******************/ diff --git a/code/game/dna/dna2.dm b/code/game/dna/dna2.dm index 2f1b55d4269df..230acb11cf85f 100644 --- a/code/game/dna/dna2.dm +++ b/code/game/dna/dna2.dm @@ -93,6 +93,7 @@ var/global/list/datum/dna/gene/dna_genes[0] new_dna.b_type=b_type new_dna.real_name=real_name new_dna.species=species + new_dna.body_markings=body_markings.Copy() for(var/b=1;b<=DNA_SE_LENGTH;b++) new_dna.SE[b]=SE[b] if(b<=DNA_UI_LENGTH) diff --git a/code/game/dna/dna2_helpers.dm b/code/game/dna/dna2_helpers.dm index f386421e9f5af..c4b784f6f0de4 100644 --- a/code/game/dna/dna2_helpers.dm +++ b/code/game/dna/dna2_helpers.dm @@ -174,6 +174,13 @@ if((0 < beard) && (beard <= facial_hair_styles_list.len)) H.f_style = facial_hair_styles_list[beard] + //Body markings + for(var/tag in dna.body_markings) + var/obj/item/organ/external/E = H.organs_by_name[tag] + if(E) + var/list/marklist = dna.body_markings[tag] + E.markings = marklist.Copy() + H.force_update_limbs() H.update_body() H.update_eyes() diff --git a/code/modules/client/preference_setup/general/03_body.dm b/code/modules/client/preference_setup/general/03_body.dm index 201d1fdb1bfda..8db75f7c59f3b 100644 --- a/code/modules/client/preference_setup/general/03_body.dm +++ b/code/modules/client/preference_setup/general/03_body.dm @@ -54,6 +54,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O S["organ_data"] >> pref.organ_data S["rlimb_data"] >> pref.rlimb_data S["has_cortical_stack"] >> pref.has_cortical_stack + S["body_markings"] >> pref.body_markings pref.preview_icon = null /datum/category_item/player_setup_item/general/body/save_character(var/savefile/S) @@ -78,6 +79,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O S["organ_data"] << pref.organ_data S["rlimb_data"] << pref.rlimb_data S["has_cortical_stack"] << pref.has_cortical_stack + S["body_markings"] << pref.body_markings /datum/category_item/player_setup_item/general/body/sanitize_character(var/savefile/S) if(!pref.species || !(pref.species in playable_species)) @@ -103,6 +105,8 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O pref.disabilities = sanitize_integer(pref.disabilities, 0, 65535, initial(pref.disabilities)) if(!istype(pref.organ_data)) pref.organ_data = list() if(!istype(pref.rlimb_data)) pref.rlimb_data = list() + if(!pref.body_markings) pref.body_markings = list() + else pref.body_markings &= body_marking_styles_list if(pref.organ_data[BP_CHEST] != "cyborg") pref.organ_data[BP_HEAD] = null @@ -134,6 +138,12 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O . += "Limbs: Adjust Reset
" . += "Internal Organs: Adjust
" + . += "
Body Markings +
" + for(var/M in pref.body_markings) + . += "[M] - Color" + . += "
__
" + . += "
" + //display limbs below var/ind = 0 for(var/name in pref.organ_data) @@ -327,6 +337,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O reset_limbs() // Safety for species with incompatible manufacturers; easier than trying to do it case by case. prune_occupation_prefs() + pref.body_markings.Cut() return TOPIC_REFRESH_UPDATE_PREVIEW else if(href_list["hair_color"]) @@ -572,6 +583,36 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O pref.equip_preview_mob ^= text2num(href_list["toggle_preview_value"]) return TOPIC_REFRESH_UPDATE_PREVIEW + else if(href_list["marking_style"]) + var/list/usable_markings = pref.body_markings.Copy() ^ body_marking_styles_list.Copy() + for(var/M in usable_markings) + var/datum/sprite_accessory/S = usable_markings[M] + if(S.ckey_allowed) + if(!(usr.ckey in S.ckey_allowed)) + usable_markings -= M + if(!S.species_allowed.len) + continue + else if(!(pref.species in S.species_allowed)) + usable_markings -= M + + + var/new_marking = input(user, "Choose a body marking:", "Character Preference") as null|anything in usable_markings + if(new_marking && CanUseTopic(user)) + pref.body_markings[new_marking] = "#000000" //New markings start black + return TOPIC_REFRESH_UPDATE_PREVIEW + + else if(href_list["marking_remove"]) + var/M = href_list["marking_remove"] + pref.body_markings -= M + return TOPIC_REFRESH_UPDATE_PREVIEW + + else if(href_list["marking_color"]) + var/M = href_list["marking_color"] + var/mark_color = input(user, "Choose the [M] color: ", "Character Preference", pref.body_markings[M]) as color|null + if(mark_color && CanUseTopic(user)) + pref.body_markings[M] = "[mark_color]" + return TOPIC_REFRESH_UPDATE_PREVIEW + return ..() /datum/category_item/player_setup_item/general/body/proc/reset_limbs() diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 249046cb90cbd..2c11076f7539f 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -177,6 +177,7 @@ datum/preferences ShowChoices(usr) return 1 + // WE need to leave the body marking things here /datum/preferences/proc/copy_to(mob/living/carbon/human/character, is_preview_copy = FALSE) // Sanitizing rather than saving as someone might still be editing when copy_to occurs. player_setup.sanitize_setup() @@ -229,7 +230,6 @@ datum/preferences if(!islist(organ_data)) continue var/limb_path = organ_data["path"] O = new limb_path(character) - // Destroy/cyborgize organs and limbs. The order is important for preserving low-level choices for robolimb sprites being overridden. for(var/name in BP_BY_DEPTH) var/status = organ_data[name] @@ -269,6 +269,20 @@ datum/preferences else if(status == "mechanical") I.robotize() + + for(var/N in character.organs_by_name) + var/obj/item/organ/external/O = character.organs_by_name[N] + O.markings.Cut() + + for(var/M in body_markings) + var/datum/sprite_accessory/marking/mark_datum = body_marking_styles_list[M] + var/mark_color = "[body_markings[M]]" + + for(var/BP in mark_datum.body_parts) + var/obj/item/organ/external/O = character.organs_by_name[BP] + if(O) + O.markings[M] = list("color" = mark_color, "datum" = mark_datum) + character.all_underwear.Cut() character.all_underwear_metadata.Cut() for(var/underwear_category_name in all_underwear) diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index ea4bf3254b770..a502345026792 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -291,6 +291,8 @@ var/global/list/damage_icon_parts = list() icon_key += "[rgb(part.h_col[1],part.h_col[2],part.h_col[3])]" else icon_key += "#000000" + for(var/M in part.markings) + icon_key += "[M][part.markings[M]["color"]]" if(part.robotic >= ORGAN_ROBOT) icon_key += "2[part.model ? "-[part.model]": ""]" else if(part.status & ORGAN_DEAD) diff --git a/code/modules/organs/external/_external.dm b/code/modules/organs/external/_external.dm index b1e4aff1455d6..694c3d2c0141c 100644 --- a/code/modules/organs/external/_external.dm +++ b/code/modules/organs/external/_external.dm @@ -9,7 +9,6 @@ dir = SOUTH organ_tag = "limb" appearance_flags = PIXEL_SCALE - // Strings var/broken_description // fracture string if any. var/damage_state = "00" // Modifier used for generating the on-mob damage overlay for this limb. diff --git a/code/modules/organs/external/_external_icons.dm b/code/modules/organs/external/_external_icons.dm index 8cb0c53d4d373..f2ea5b043f241 100644 --- a/code/modules/organs/external/_external_icons.dm +++ b/code/modules/organs/external/_external_icons.dm @@ -90,6 +90,27 @@ var/list/limb_icon_cache = list() dir = EAST icon = mob_icon + //Body markings, does not include head, duplicated (sadly) above. + for(var/M in markings) + var/datum/sprite_accessory/marking/mark_style = markings[M]["datum"] + var/icon/mark_s = new/icon("icon" = mark_style.icon, "icon_state" = "[mark_style.icon_state]-[organ_tag]") + mark_s.Blend(markings[M]["color"], ICON_ADD) + overlays |= mark_s //So when it's not on your body, it has icons + mob_icon.Blend(mark_s, ICON_OVERLAY) //So when it's on your body, it has icons + icon_cache_key += "[M][markings[M]["color"]]" + +/obj/item/organ/external/head/get_icon() + ..() + //Body markings, does not include head, duplicated (sadly) above. + for(var/M in markings) + var/datum/sprite_accessory/marking/mark_style = markings[M]["datum"] + var/icon/mark_s = new/icon("icon" = mark_style.icon, "icon_state" = "[mark_style.icon_state]-[organ_tag]") + mark_s.Blend(markings[M]["color"], ICON_ADD) + overlays |= mark_s //So when it's not on your body, it has icons + mob_icon.Blend(mark_s, ICON_OVERLAY) //So when it's on your body, it has icons + icon_cache_key += "[M][markings[M]["color"]]" + return mob_icon + /obj/item/organ/external/proc/get_icon() update_icon() return mob_icon