diff --git a/code/modules/client/preference_setup/general/03_body.dm b/code/modules/client/preference_setup/general/03_body.dm index 2e1066dc0b..a084e29ffa 100644 --- a/code/modules/client/preference_setup/general/03_body.dm +++ b/code/modules/client/preference_setup/general/03_body.dm @@ -372,14 +372,17 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O var/obj/item/organ/external/O = character.organs_by_name[N] O.markings.Cut() + var/priority = 0 for(var/M in pref.body_markings) + priority += 1 var/datum/sprite_accessory/marking/mark_datum = body_marking_styles_list[M] var/mark_color = "[pref.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) + O.markings[M] = list("color" = mark_color, "datum" = mark_datum, "priority" = priority) + character.markings_len = priority var/list/last_descriptors = list() if(islist(pref.body_descriptors)) diff --git a/code/modules/mob/living/carbon/human/human_defines_vr.dm b/code/modules/mob/living/carbon/human/human_defines_vr.dm index 69a008029c..39c4f11cbc 100644 --- a/code/modules/mob/living/carbon/human/human_defines_vr.dm +++ b/code/modules/mob/living/carbon/human/human_defines_vr.dm @@ -9,6 +9,7 @@ var/sensorpref = 5 //Suit sensor loadout pref var/wings_hidden = FALSE var/tail_hidden = FALSE + var/markings_len = 0 //mostly an arbitrary number /mob/living/carbon/human/proc/shadekin_get_energy() var/datum/species/shadekin/SK = species diff --git a/code/modules/mob/living/carbon/human/human_helpers_vr.dm b/code/modules/mob/living/carbon/human/human_helpers_vr.dm index b8e9d75b30..14ed52bd8c 100644 --- a/code/modules/mob/living/carbon/human/human_helpers_vr.dm +++ b/code/modules/mob/living/carbon/human/human_helpers_vr.dm @@ -7,3 +7,116 @@ var/static/icon/ingame_hud_med_vr = icon('icons/mob/hud_med_vr.dmi') hud_list[STATUS_R_HUD] = gen_hud_image(ingame_hud_vr, src, plane = PLANE_CH_STATUS_R) hud_list[BACKUP_HUD] = gen_hud_image(ingame_hud_vr, src, plane = PLANE_CH_BACKUP) hud_list[VANTAG_HUD] = gen_hud_image(ingame_hud_vr, src, plane = PLANE_CH_VANTAG) + +/mob/living/carbon/human/proc/remove_marking(var/datum/sprite_accessory/marking/mark_datum) + if (!mark_datum) + return FALSE + var/successful = FALSE + for(var/BP in mark_datum.body_parts) + var/obj/item/organ/external/O = organs_by_name[BP] + if(O) + successful = O.markings.Remove(mark_datum.name) || successful + if (successful) + markings_len -= 1 + update_dna() + update_icons_body() + return TRUE + return FALSE + +/mob/living/carbon/human/proc/add_marking(var/datum/sprite_accessory/marking/mark_datum, var/mark_color = "#000000") + if (!mark_datum) + return FALSE + var/success = FALSE + for(var/BP in mark_datum.body_parts) + var/obj/item/organ/external/O = organs_by_name[BP] + if(O) + success = TRUE + O.markings[mark_datum.name] = list("color" = mark_color, "datum" = mark_datum, "priority" = markings_len + 1) + if (success) + markings_len += 1 + update_dna() + update_icons_body() + return success + +/mob/living/carbon/human/proc/change_priority_of_marking(var/datum/sprite_accessory/marking/mark_datum, var/move_down, var/swap = TRUE) //move_down should be true/false + if (!mark_datum) + return FALSE + var/change = move_down ? 1 : -1 + var/success = FALSE + for(var/BP in mark_datum.body_parts) + var/obj/item/organ/external/O = organs_by_name[BP] + if(O) + var/index = O.markings.Find(mark_datum.name) + if (!index) + continue + var/change_from = O.markings[mark_datum.name]["priority"] + if (change_from == clamp(change_from + change, 1, markings_len)) + continue + if (!success) + success = TRUE + change_priority_marking_to_priority(change_from + change, change_from) + O.markings[mark_datum.name]["priority"] = clamp(change_from + change, 1, markings_len) + if ((move_down && index == O.markings.len) || (!move_down && index == 1)) + continue + if (O.markings[O.markings[index + change]]["priority"] == change_from) + moveElement(O.markings, index, index+(move_down ? 2 : -1)) + if (success) + update_dna() + update_icons_body() + return TRUE + +/mob/living/carbon/human/proc/change_priority_marking_to_priority(var/priority, var/to_priority) + for (var/obj/item/organ/external/O in organs) + for (var/marking in O.markings) + if (O.markings[marking]["priority"] == priority) + O.markings[marking]["priority"] = to_priority + +/mob/living/carbon/human/proc/change_marking_color(var/datum/sprite_accessory/marking/mark_datum, var/mark_color = "#000000") + if (!mark_datum) + return FALSE + var/success = FALSE + for(var/BP in mark_datum.body_parts) + var/obj/item/organ/external/O = organs_by_name[BP] + if(O && O.markings[mark_datum.name] && O.markings[mark_datum.name]["color"] != mark_color) + success = TRUE + O.markings[mark_datum.name]["color"] = mark_color + if (success) + update_dna() + update_icons_body() + return success + +/mob/living/carbon/human/proc/get_prioritised_markings() + var/list/markings = list() + var/list/priorities = list() + for(var/obj/item/organ/external/O in organs) + if(O.markings?.len) + for (var/marking in O.markings) + var/priority = num2text(O.markings[marking]["priority"]) + if (markings[priority]) + markings[priority] |= list("[marking]" = O.markings[marking]["color"]) //yes I know technically you could have a limb that was attached that has the same marking as another limb with a different color but I'm too tired + else + priorities |= O.markings[marking]["priority"] + markings[priority] = list("[marking]" = O.markings[marking]["color"]) + var/list/sorted = list() + while (priorities.len > 0) + var/priority = min(priorities) + priorities.Remove(priority) + priority = num2text(priority) + for (var/marking in markings[priority]) + if (!(marking in sorted)) + sorted[marking] = markings[priority][marking] + del(markings) + del(priorities) + markings_len = sorted.len + //todo - add an autofixing thing for having markings with the same priorities as another, and for having markings that should have the same priorities across bodyparts, but don't + //does not really need to happen, that kinda thing will only happen when putting another person's limb onto your own body + return sorted + + + + + + + + + diff --git a/code/modules/tgui/modules/appearance_changer.dm b/code/modules/tgui/modules/appearance_changer.dm index d6d7e5f386..a90d69689b 100644 --- a/code/modules/tgui/modules/appearance_changer.dm +++ b/code/modules/tgui/modules/appearance_changer.dm @@ -26,6 +26,7 @@ var/list/valid_earstyles = list() var/list/valid_tailstyles = list() var/list/valid_wingstyles = list() + var/list/markings = null /datum/tgui_module/appearance_changer/New( var/host, @@ -174,7 +175,7 @@ update_dna() changed_hook(APPEARANCECHANGER_CHANGED_EYES) return 1 - // VOREStation Add - Ears/Tails/Wings + // VOREStation Add - Ears/Tails/Wings/Markings if("ear") if(can_change(APPEARANCE_ALL_HAIR)) var/datum/sprite_accessory/ears/instance = locate(params["ref"]) @@ -277,6 +278,40 @@ owner.update_wing_showing() changed_hook(APPEARANCECHANGER_CHANGED_HAIRCOLOR) return 1 + if("marking") + if(can_change(APPEARANCE_ALL_HAIR)) + var/todo = params["todo"] + var/name_marking = params["name"] + switch (todo) + if (0) //delete + if (name_marking) + var/datum/sprite_accessory/marking/mark_datum = body_marking_styles_list[name_marking] + if (target.remove_marking(mark_datum)) + changed_hook(APPEARANCECHANGER_CHANGED_HAIRSTYLE) + return TRUE + if (1) //add + var/list/usable_markings = markings.Copy() ^ body_marking_styles_list.Copy() + var/new_marking = tgui_input_list(usr, "Choose a body marking:", "New Body Marking", usable_markings) + if(new_marking && can_still_topic(usr, state)) + var/datum/sprite_accessory/marking/mark_datum = body_marking_styles_list[new_marking] + if (target.add_marking(mark_datum)) + changed_hook(APPEARANCECHANGER_CHANGED_HAIRSTYLE) + return TRUE + if (2) //move up + var/datum/sprite_accessory/marking/mark_datum = body_marking_styles_list[name_marking] + if (target.change_priority_of_marking(mark_datum, FALSE)) + return TRUE + if (3) //move down + var/datum/sprite_accessory/marking/mark_datum = body_marking_styles_list[name_marking] + if (target.change_priority_of_marking(mark_datum, TRUE)) + return TRUE + if (4) //color + var/current = markings[name_marking] ? markings[name_marking] : "#000000" + var/marking_color = input(usr, "Please select marking color", "Marking color", current) as color|null + if(marking_color && can_still_topic(usr, state)) + var/datum/sprite_accessory/marking/mark_datum = body_marking_styles_list[name_marking] + if (target.change_marking_color(mark_datum, marking_color)) + return TRUE // VOREStation Add End return FALSE @@ -370,6 +405,11 @@ data["ear_style"] = target.ear_style data["tail_style"] = target.tail_style data["wing_style"] = target.wing_style + var/list/markings_data[0] + markings = target.get_prioritised_markings() + for (var/marking in markings) + markings_data[++markings_data.len] = list("marking_name" = marking, "marking_color" = markings[marking]) + data["markings"] = markings_data // VOREStation Add End data["change_facial_hair"] = can_change(APPEARANCE_FACIAL_HAIR) diff --git a/tgui/packages/tgui/interfaces/AppearanceChanger.js b/tgui/packages/tgui/interfaces/AppearanceChanger.js index 088306b969..23fd8d8ebb 100644 --- a/tgui/packages/tgui/interfaces/AppearanceChanger.js +++ b/tgui/packages/tgui/interfaces/AppearanceChanger.js @@ -18,6 +18,7 @@ export const AppearanceChanger = (props, context) => { ear_style, tail_style, wing_style, + markings, change_race, change_gender, change_eye_color, @@ -128,6 +129,9 @@ export const AppearanceChanger = (props, context) => { setTabIndex(7)}> Wing + setTabIndex(8)}> + Markings + ) : null} {change_facial_hair ? ( @@ -145,6 +149,7 @@ export const AppearanceChanger = (props, context) => { {change_hair && tabIndex === 5 ? : null} {change_hair && tabIndex === 6 ? : null} {change_hair && tabIndex === 7 ? : null} + {change_hair && tabIndex === 8 ? : null} @@ -383,3 +388,28 @@ const AppearanceChangerWings = (props, context) => { ); }; + +const AppearanceChangerMarkings = (props, context) => { + const { act, data } = useBackend(context); + + const { markings } = data; + + return ( +
+ +
+ ); +};