diff --git a/code/game/antagonist/antagonist_update.dm b/code/game/antagonist/antagonist_update.dm index 16c27f82c7..b118cb91db 100644 --- a/code/game/antagonist/antagonist_update.dm +++ b/code/game/antagonist/antagonist_update.dm @@ -15,7 +15,7 @@ spawn(3) var/mob/living/carbon/human/H = player.current if(istype(H)) - H.change_appearance(APPEARANCE_ALL, H.loc, H, species_whitelist = valid_species, state = z_state) + H.change_appearance(APPEARANCE_ALL, H, species_whitelist = valid_species, state = GLOB.tgui_self_state) return player.current /datum/antagonist/proc/update_access(var/mob/living/player) diff --git a/code/game/objects/items/weapons/cosmetics.dm b/code/game/objects/items/weapons/cosmetics.dm index 9435be7fb3..7150f7f556 100644 --- a/code/game/objects/items/weapons/cosmetics.dm +++ b/code/game/objects/items/weapons/cosmetics.dm @@ -96,17 +96,16 @@ w_class = ITEMSIZE_TINY icon = 'icons/obj/items.dmi' icon_state = "trinketbox" - var/list/ui_users = list() + var/datum/tgui_module/appearance_changer/mirror/coskit/M + +/obj/item/weapon/makeover/Initialize() + . = ..() + M = new(src, null) /obj/item/weapon/makeover/attack_self(mob/living/carbon/user as mob) if(ishuman(user)) to_chat(user, "You flip open \the [src] and begin to adjust your appearance.") - var/datum/nano_module/appearance_changer/AC = ui_users[user] - if(!AC) - AC = new(src, user) - AC.name = "SalonPro Porta-Makeover Deluxe™" - ui_users[user] = AC - AC.ui_interact(user) + M.tgui_interact(user) var/mob/living/carbon/human/H = user var/obj/item/organ/internal/eyes/E = H.internal_organs_by_name[O_EYES] if(istype(E)) diff --git a/code/game/objects/structures/ghost_pods/human.dm b/code/game/objects/structures/ghost_pods/human.dm index 2eda9b6c37..246c4b3e65 100644 --- a/code/game/objects/structures/ghost_pods/human.dm +++ b/code/game/objects/structures/ghost_pods/human.dm @@ -121,7 +121,7 @@ H.adjustBruteLoss(rand(1,20)) if(allow_appearance_change) - H.change_appearance(APPEARANCE_ALL, H.loc, check_species_whitelist = 1) + H.change_appearance(APPEARANCE_ALL, H, check_species_whitelist = 1) visible_message("\The [src] [pick("gurgles", "seizes", "clangs")] before releasing \the [H]!") @@ -241,6 +241,6 @@ H.adjustBruteLoss(rand(1,20)) if(allow_appearance_change) - H.change_appearance(APPEARANCE_ALL, H.loc, check_species_whitelist = 1) + H.change_appearance(APPEARANCE_ALL, H, check_species_whitelist = 1) visible_message("\The [src] [pick("gurgles", "seizes", "clangs")] before releasing \the [H]!") diff --git a/code/game/objects/structures/mirror.dm b/code/game/objects/structures/mirror.dm index 4705b39276..1473c8fe90 100644 --- a/code/game/objects/structures/mirror.dm +++ b/code/game/objects/structures/mirror.dm @@ -7,10 +7,11 @@ density = 0 anchored = 1 var/shattered = 0 - var/list/ui_users = list() var/glass = 1 + var/datum/tgui_module/appearance_changer/mirror/M /obj/structure/mirror/New(var/loc, var/dir, var/building = 0, mob/user as mob) + M = new(src, null) if(building) glass = 0 icon_state = "mirror_frame" @@ -18,17 +19,16 @@ pixel_y = (dir & 3)? (dir == 1 ? -30 : 30) : 0 return +/obj/structure/mirror/Destroy() + QDEL_NULL(M) + . = ..() + /obj/structure/mirror/attack_hand(mob/user as mob) if(!glass) return if(shattered) return if(ishuman(user)) - var/datum/nano_module/appearance_changer/AC = ui_users[user] - if(!AC) - AC = new(src, user) - AC.name = "SalonPro Nano-Mirror™" - ui_users[user] = AC - AC.ui_interact(user) + M.tgui_interact(user) /obj/structure/mirror/proc/shatter() if(!glass) return diff --git a/code/modules/admin/verbs/change_appearance.dm b/code/modules/admin/verbs/change_appearance.dm index e547d03f84..2f7166a2c0 100644 --- a/code/modules/admin/verbs/change_appearance.dm +++ b/code/modules/admin/verbs/change_appearance.dm @@ -9,7 +9,7 @@ if(!H) return log_and_message_admins("is altering the appearance of [H].") - H.change_appearance(APPEARANCE_ALL, usr, usr, check_species_whitelist = 0, state = admin_state) + H.change_appearance(APPEARANCE_ALL, usr, check_species_whitelist = 0, state = GLOB.tgui_admin_state) feedback_add_details("admin_verb","CHAA") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! /client/proc/change_human_appearance_self() @@ -29,10 +29,10 @@ switch(alert("Do you wish for [H] to be allowed to select non-whitelisted races?","Alter Mob Appearance","Yes","No","Cancel")) if("Yes") log_and_message_admins("has allowed [H] to change [T.his] appearance, without whitelisting of races.") - H.change_appearance(APPEARANCE_ALL, H.loc, check_species_whitelist = 0) + H.change_appearance(APPEARANCE_ALL, H, check_species_whitelist = 0) if("No") log_and_message_admins("has allowed [H] to change [T.his] appearance, with whitelisting of races.") - H.change_appearance(APPEARANCE_ALL, H.loc, check_species_whitelist = 1) + H.change_appearance(APPEARANCE_ALL, H, check_species_whitelist = 1) feedback_add_details("admin_verb","CMAS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! /client/proc/editappear() diff --git a/code/modules/mob/living/carbon/human/appearance.dm b/code/modules/mob/living/carbon/human/appearance.dm index eae3c47335..b1424ae5b0 100644 --- a/code/modules/mob/living/carbon/human/appearance.dm +++ b/code/modules/mob/living/carbon/human/appearance.dm @@ -1,7 +1,12 @@ -/mob/living/carbon/human/proc/change_appearance(var/flags = APPEARANCE_ALL_HAIR, var/location = src, var/mob/user = src, var/check_species_whitelist = 1, var/list/species_whitelist = list(), var/list/species_blacklist = list(), var/datum/topic_state/state = default_state) - var/datum/nano_module/appearance_changer/AC = new(location, src, check_species_whitelist, species_whitelist, species_blacklist) +/mob/living/carbon/human/proc/change_appearance(var/flags = APPEARANCE_ALL_HAIR, + var/mob/user = src, + var/check_species_whitelist = 1, + var/list/species_whitelist = list(), + var/list/species_blacklist = list(), + var/datum/tgui_state/state = GLOB.tgui_self_state) + var/datum/tgui_module/appearance_changer/AC = new(src, src, check_species_whitelist, species_whitelist, species_blacklist) AC.flags = flags - AC.ui_interact(user, state = state) + AC.tgui_interact(user, custom_state = state) /mob/living/carbon/human/proc/change_species(var/new_species) if(!new_species) diff --git a/code/modules/nano/modules/human_appearance.dm b/code/modules/nano/modules/human_appearance.dm deleted file mode 100644 index fd2ed900f2..0000000000 --- a/code/modules/nano/modules/human_appearance.dm +++ /dev/null @@ -1,191 +0,0 @@ -/datum/nano_module/appearance_changer - name = "Appearance Editor" - var/flags = APPEARANCE_ALL_HAIR - var/mob/living/carbon/human/owner = null - var/list/valid_species = list() - var/list/valid_hairstyles = list() - var/list/valid_facial_hairstyles = list() - - var/check_whitelist - var/list/whitelist - var/list/blacklist - -/datum/nano_module/appearance_changer/New(var/location, var/mob/living/carbon/human/H, var/check_species_whitelist = 1, var/list/species_whitelist = list(), var/list/species_blacklist = list()) - ..() - owner = H - src.check_whitelist = check_species_whitelist - src.whitelist = species_whitelist - src.blacklist = species_blacklist - -/datum/nano_module/appearance_changer/Topic(ref, href_list, var/datum/topic_state/state = default_state) - if(..()) - return 1 - - if(href_list["race"]) - if(can_change(APPEARANCE_RACE) && (href_list["race"] in valid_species)) - if(owner.change_species(href_list["race"])) - cut_and_generate_data() - return 1 - if(href_list["gender"]) - if(can_change(APPEARANCE_GENDER) && (href_list["gender"] in get_genders())) - if(owner.change_gender(href_list["gender"])) - cut_and_generate_data() - return 1 - if(href_list["gender_id"]) - if(can_change(APPEARANCE_GENDER) && (href_list["gender_id"] in all_genders_define_list)) - owner.identifying_gender = href_list["gender_id"] - return 1 - if(href_list["skin_tone"]) - if(can_change_skin_tone()) - var/new_s_tone = input(usr, "Choose your character's skin-tone:\n(Light 1 - 220 Dark)", "Skin Tone", -owner.s_tone + 35) as num|null - if(isnum(new_s_tone) && can_still_topic(state)) - new_s_tone = 35 - max(min( round(new_s_tone), 220),1) - return owner.change_skin_tone(new_s_tone) - if(href_list["skin_color"]) - if(can_change_skin_color()) - var/new_skin = input(usr, "Choose your character's skin colour: ", "Skin Color", rgb(owner.r_skin, owner.g_skin, owner.b_skin)) as color|null - if(new_skin && can_still_topic(state)) - var/r_skin = hex2num(copytext(new_skin, 2, 4)) - var/g_skin = hex2num(copytext(new_skin, 4, 6)) - var/b_skin = hex2num(copytext(new_skin, 6, 8)) - if(owner.change_skin_color(r_skin, g_skin, b_skin)) - update_dna() - return 1 - if(href_list["hair"]) - if(can_change(APPEARANCE_HAIR) && (href_list["hair"] in valid_hairstyles)) - if(owner.change_hair(href_list["hair"])) - update_dna() - return 1 - if(href_list["hair_color"]) - if(can_change(APPEARANCE_HAIR_COLOR)) - var/new_hair = input("Please select hair color.", "Hair Color", rgb(owner.r_hair, owner.g_hair, owner.b_hair)) as color|null - if(new_hair && can_still_topic(state)) - var/r_hair = hex2num(copytext(new_hair, 2, 4)) - var/g_hair = hex2num(copytext(new_hair, 4, 6)) - var/b_hair = hex2num(copytext(new_hair, 6, 8)) - if(owner.change_hair_color(r_hair, g_hair, b_hair)) - update_dna() - return 1 - if(href_list["facial_hair"]) - if(can_change(APPEARANCE_FACIAL_HAIR) && (href_list["facial_hair"] in valid_facial_hairstyles)) - if(owner.change_facial_hair(href_list["facial_hair"])) - update_dna() - return 1 - if(href_list["facial_hair_color"]) - if(can_change(APPEARANCE_FACIAL_HAIR_COLOR)) - var/new_facial = input("Please select facial hair color.", "Facial Hair Color", rgb(owner.r_facial, owner.g_facial, owner.b_facial)) as color|null - if(new_facial && can_still_topic(state)) - var/r_facial = hex2num(copytext(new_facial, 2, 4)) - var/g_facial = hex2num(copytext(new_facial, 4, 6)) - var/b_facial = hex2num(copytext(new_facial, 6, 8)) - if(owner.change_facial_hair_color(r_facial, g_facial, b_facial)) - update_dna() - return 1 - if(href_list["eye_color"]) - if(can_change(APPEARANCE_EYE_COLOR)) - var/new_eyes = input("Please select eye color.", "Eye Color", rgb(owner.r_eyes, owner.g_eyes, owner.b_eyes)) as color|null - if(new_eyes && can_still_topic(state)) - var/r_eyes = hex2num(copytext(new_eyes, 2, 4)) - var/g_eyes = hex2num(copytext(new_eyes, 4, 6)) - var/b_eyes = hex2num(copytext(new_eyes, 6, 8)) - if(owner.change_eye_color(r_eyes, g_eyes, b_eyes)) - update_dna() - return 1 - - return 0 - -/datum/nano_module/appearance_changer/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = default_state) - - if(!owner || !owner.species) - return - - generate_data(check_whitelist, whitelist, blacklist) - var/list/data = host.initial_data() - - data["specimen"] = owner.species.name - data["gender"] = owner.gender - data["gender_id"] = owner.identifying_gender - data["change_race"] = can_change(APPEARANCE_RACE) - if(data["change_race"]) - var/species[0] - for(var/specimen in valid_species) - species[++species.len] = list("specimen" = specimen) - data["species"] = species - - data["change_gender"] = can_change(APPEARANCE_GENDER) - if(data["change_gender"]) - var/genders[0] - for(var/gender in get_genders()) - genders[++genders.len] = list("gender_name" = gender2text(gender), "gender_key" = gender) - data["genders"] = genders - var/id_genders[0] - for(var/gender in all_genders_define_list) - id_genders[++id_genders.len] = list("gender_name" = gender2text(gender), "gender_key" = gender) - data["id_genders"] = id_genders - - - data["change_skin_tone"] = can_change_skin_tone() - data["change_skin_color"] = can_change_skin_color() - data["change_eye_color"] = can_change(APPEARANCE_EYE_COLOR) - data["change_hair"] = can_change(APPEARANCE_HAIR) - if(data["change_hair"]) - var/hair_styles[0] - for(var/hair_style in valid_hairstyles) - hair_styles[++hair_styles.len] = list("hairstyle" = hair_style) - data["hair_styles"] = hair_styles - data["hair_style"] = owner.h_style - - data["change_facial_hair"] = can_change(APPEARANCE_FACIAL_HAIR) - if(data["change_facial_hair"]) - var/facial_hair_styles[0] - for(var/facial_hair_style in valid_facial_hairstyles) - facial_hair_styles[++facial_hair_styles.len] = list("facialhairstyle" = facial_hair_style) - data["facial_hair_styles"] = facial_hair_styles - data["facial_hair_style"] = owner.f_style - - data["change_hair_color"] = can_change(APPEARANCE_HAIR_COLOR) - data["change_facial_hair_color"] = can_change(APPEARANCE_FACIAL_HAIR_COLOR) - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - if (!ui) - ui = new(user, src, ui_key, "appearance_changer.tmpl", "[src]", 800, 450, state = state) - ui.set_initial_data(data) - ui.open() - ui.set_auto_update(1) - -/datum/nano_module/appearance_changer/proc/update_dna() - if(owner && (flags & APPEARANCE_UPDATE_DNA)) - owner.update_dna() - -/datum/nano_module/appearance_changer/proc/can_change(var/flag) - return owner && (flags & flag) - -/datum/nano_module/appearance_changer/proc/can_change_skin_tone() - return owner && (flags & APPEARANCE_SKIN) && owner.species.appearance_flags & HAS_SKIN_TONE - -/datum/nano_module/appearance_changer/proc/can_change_skin_color() - return owner && (flags & APPEARANCE_SKIN) && owner.species.appearance_flags & HAS_SKIN_COLOR - -/datum/nano_module/appearance_changer/proc/cut_and_generate_data() - // Making the assumption that the available species remain constant - valid_facial_hairstyles.Cut() - valid_facial_hairstyles.Cut() - generate_data() - -/datum/nano_module/appearance_changer/proc/generate_data() - if(!owner) - return - if(!valid_species.len) - valid_species = owner.generate_valid_species(check_whitelist, whitelist, blacklist) - if(!valid_hairstyles.len || !valid_facial_hairstyles.len) - valid_hairstyles = owner.generate_valid_hairstyles(check_gender = 0) - valid_facial_hairstyles = owner.generate_valid_facial_hairstyles() - - -/datum/nano_module/appearance_changer/proc/get_genders() - var/datum/species/S = owner.species - var/list/possible_genders = S.genders - if(!owner.internal_organs_by_name["cell"]) - return possible_genders - possible_genders = possible_genders.Copy() - possible_genders |= NEUTER - return possible_genders \ No newline at end of file diff --git a/code/modules/tgui/modules/_base.dm b/code/modules/tgui/modules/_base.dm index 46dbc655ff..cefe49230f 100644 --- a/code/modules/tgui/modules/_base.dm +++ b/code/modules/tgui/modules/_base.dm @@ -26,6 +26,9 @@ Code is pretty much ripped verbatim from nano modules, but with un-needed stuff if(host) host.tgui_close(user) +/datum/tgui_module/proc/can_still_topic(mob/user, datum/tgui_state/state) + return (tgui_status(user, state) == STATUS_INTERACTIVE) + /datum/tgui_module/proc/check_access(mob/user, access) if(!access) return 1 @@ -76,4 +79,37 @@ Code is pretty much ripped verbatim from nano modules, but with un-needed stuff ui = SStgui.try_update_ui(user, src, ui) if(!ui) ui = new(user, src, tgui_id, name) - ui.open() \ No newline at end of file + ui.open() + +// This is a helper for anything that wants to render the map. +/datum/tgui_module/proc/get_plane_masters() + . = list() + // 'Utility' planes + . += new /obj/screen/plane_master/fullbright //Lighting system (lighting_overlay objects) + . += new /obj/screen/plane_master/lighting //Lighting system (but different!) + . += new /obj/screen/plane_master/ghosts //Ghosts! + . += new /obj/screen/plane_master{plane = PLANE_AI_EYE} //AI Eye! + + . += new /obj/screen/plane_master{plane = PLANE_CH_STATUS} //Status is the synth/human icon left side of medhuds + . += new /obj/screen/plane_master{plane = PLANE_CH_HEALTH} //Health bar + . += new /obj/screen/plane_master{plane = PLANE_CH_LIFE} //Alive-or-not icon + . += new /obj/screen/plane_master{plane = PLANE_CH_ID} //Job ID icon + . += new /obj/screen/plane_master{plane = PLANE_CH_WANTED} //Wanted status + . += new /obj/screen/plane_master{plane = PLANE_CH_IMPLOYAL} //Loyalty implants + . += new /obj/screen/plane_master{plane = PLANE_CH_IMPTRACK} //Tracking implants + . += new /obj/screen/plane_master{plane = PLANE_CH_IMPCHEM} //Chemical implants + . += new /obj/screen/plane_master{plane = PLANE_CH_SPECIAL} //"Special" role stuff + . += new /obj/screen/plane_master{plane = PLANE_CH_STATUS_OOC} //OOC status HUD + + . += new /obj/screen/plane_master{plane = PLANE_ADMIN1} //For admin use + . += new /obj/screen/plane_master{plane = PLANE_ADMIN2} //For admin use + . += new /obj/screen/plane_master{plane = PLANE_ADMIN3} //For admin use + + . += new /obj/screen/plane_master{plane = PLANE_MESONS} //Meson-specific things like open ceilings. + . += new /obj/screen/plane_master{plane = PLANE_BUILDMODE} //Things that only show up while in build mode + + // Real tangible stuff planes + . += new /obj/screen/plane_master/main{plane = TURF_PLANE} + . += new /obj/screen/plane_master/main{plane = OBJ_PLANE} + . += new /obj/screen/plane_master/main{plane = MOB_PLANE} + . += new /obj/screen/plane_master/cloaked //Cloaked atoms! \ No newline at end of file diff --git a/code/modules/tgui/modules/appearance_changer.dm b/code/modules/tgui/modules/appearance_changer.dm new file mode 100644 index 0000000000..667fe7e0a0 --- /dev/null +++ b/code/modules/tgui/modules/appearance_changer.dm @@ -0,0 +1,358 @@ +/datum/tgui_module/appearance_changer + name = "Appearance Editor" + tgui_id = "AppearanceChanger" + var/flags = APPEARANCE_ALL_HAIR + var/mob/living/carbon/human/owner = null + var/list/valid_species = list() + var/list/valid_hairstyles = list() + var/list/valid_facial_hairstyles = list() + + var/check_whitelist + var/list/whitelist + var/list/blacklist + + var/customize_usr = FALSE + + // Stuff needed to render the map + var/map_name + var/obj/screen/map_view/cam_screen + var/list/cam_plane_masters + var/obj/screen/background/cam_background + var/obj/screen/skybox/local_skybox + // Needed for moving camera support + var/camera_diff_x = -1 + var/camera_diff_y = -1 + var/camera_diff_z = -1 + +/datum/tgui_module/appearance_changer/New( + var/host, + mob/living/carbon/human/H, + check_species_whitelist = 1, + list/species_whitelist = list(), + list/species_blacklist = list()) + . = ..() + + map_name = "appearance_changer_[REF(src)]_map" + // Initialize map objects + cam_screen = new + cam_screen.name = "screen" + cam_screen.assigned_map = map_name + cam_screen.del_on_map_removal = FALSE + cam_screen.screen_loc = "[map_name]:1,1" + + cam_plane_masters = get_plane_masters() + + for(var/plane in cam_plane_masters) + var/obj/screen/instance = plane + instance.assigned_map = map_name + instance.del_on_map_removal = FALSE + instance.screen_loc = "[map_name]:CENTER" + + local_skybox = new() + local_skybox.assigned_map = map_name + local_skybox.del_on_map_removal = FALSE + local_skybox.screen_loc = "[map_name]:CENTER,CENTER" + cam_plane_masters += local_skybox + + cam_background = new + cam_background.assigned_map = map_name + cam_background.del_on_map_removal = FALSE + reload_cameraview() + + owner = H + check_whitelist = check_species_whitelist + whitelist = species_whitelist + blacklist = species_blacklist + +/datum/tgui_module/appearance_changer/Destroy() + qdel(cam_screen) + QDEL_LIST(cam_plane_masters) + qdel(cam_background) + return ..() + +/datum/tgui_module/appearance_changer/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state) + if(..()) + return TRUE + + var/mob/living/carbon/human/target = owner + if(customize_usr) + if(!ishuman(usr)) + return TRUE + target = usr + + switch(action) + if("race") + if(can_change(APPEARANCE_RACE) && (params["race"] in valid_species)) + if(target.change_species(params["race"])) + cut_and_generate_data() + return 1 + if("gender") + if(can_change(APPEARANCE_GENDER) && (params["gender"] in get_genders())) + if(target.change_gender(params["gender"])) + cut_and_generate_data() + return 1 + if("gender_id") + if(can_change(APPEARANCE_GENDER) && (params["gender_id"] in all_genders_define_list)) + target.identifying_gender = params["gender_id"] + return 1 + if("skin_tone") + if(can_change_skin_tone()) + var/new_s_tone = input(usr, "Choose your character's skin-tone:\n(Light 1 - 220 Dark)", "Skin Tone", -target.s_tone + 35) as num|null + if(isnum(new_s_tone) && can_still_topic(usr, state)) + new_s_tone = 35 - max(min( round(new_s_tone), 220),1) + return target.change_skin_tone(new_s_tone) + if("skin_color") + if(can_change_skin_color()) + var/new_skin = input(usr, "Choose your character's skin colour: ", "Skin Color", rgb(target.r_skin, target.g_skin, target.b_skin)) as color|null + if(new_skin && can_still_topic(usr, state)) + var/r_skin = hex2num(copytext(new_skin, 2, 4)) + var/g_skin = hex2num(copytext(new_skin, 4, 6)) + var/b_skin = hex2num(copytext(new_skin, 6, 8)) + if(target.change_skin_color(r_skin, g_skin, b_skin)) + update_dna() + return 1 + if("hair") + if(can_change(APPEARANCE_HAIR) && (params["hair"] in valid_hairstyles)) + if(target.change_hair(params["hair"])) + update_dna() + return 1 + if("hair_color") + if(can_change(APPEARANCE_HAIR_COLOR)) + var/new_hair = input("Please select hair color.", "Hair Color", rgb(target.r_hair, target.g_hair, target.b_hair)) as color|null + if(new_hair && can_still_topic(usr, state)) + var/r_hair = hex2num(copytext(new_hair, 2, 4)) + var/g_hair = hex2num(copytext(new_hair, 4, 6)) + var/b_hair = hex2num(copytext(new_hair, 6, 8)) + if(target.change_hair_color(r_hair, g_hair, b_hair)) + update_dna() + return 1 + if("facial_hair") + if(can_change(APPEARANCE_FACIAL_HAIR) && (params["facial_hair"] in valid_facial_hairstyles)) + if(target.change_facial_hair(params["facial_hair"])) + update_dna() + return 1 + if("facial_hair_color") + if(can_change(APPEARANCE_FACIAL_HAIR_COLOR)) + var/new_facial = input("Please select facial hair color.", "Facial Hair Color", rgb(target.r_facial, target.g_facial, target.b_facial)) as color|null + if(new_facial && can_still_topic(usr, state)) + var/r_facial = hex2num(copytext(new_facial, 2, 4)) + var/g_facial = hex2num(copytext(new_facial, 4, 6)) + var/b_facial = hex2num(copytext(new_facial, 6, 8)) + if(target.change_facial_hair_color(r_facial, g_facial, b_facial)) + update_dna() + return 1 + if("eye_color") + if(can_change(APPEARANCE_EYE_COLOR)) + var/new_eyes = input("Please select eye color.", "Eye Color", rgb(target.r_eyes, target.g_eyes, target.b_eyes)) as color|null + if(new_eyes && can_still_topic(usr, state)) + var/r_eyes = hex2num(copytext(new_eyes, 2, 4)) + var/g_eyes = hex2num(copytext(new_eyes, 4, 6)) + var/b_eyes = hex2num(copytext(new_eyes, 6, 8)) + if(target.change_eye_color(r_eyes, g_eyes, b_eyes)) + update_dna() + return 1 + return FALSE + +/datum/tgui_module/appearance_changer/tgui_interact(mob/user, datum/tgui/ui = null, datum/tgui/parent_ui = null, datum/tgui_state/custom_state = GLOB.tgui_default_state) + var/mob/living/carbon/human/target = owner + if(customize_usr) + if(!ishuman(user)) + return TRUE + target = user + + if(!target || !target.species) + return + + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + reload_cameraview() + // Register map objects + user.client.register_map_obj(cam_screen) + for(var/plane in cam_plane_masters) + user.client.register_map_obj(plane) + user.client.register_map_obj(cam_background) + // Open UI + ui = new(user, src, tgui_id, name) + ui.open() + if(custom_state) + ui.set_state(custom_state) + +/datum/tgui_module/appearance_changer/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state) + var/list/data = ..() + + generate_data(check_whitelist, whitelist, blacklist) + differential_check() + + var/mob/living/carbon/human/target = owner + if(customize_usr) + if(!ishuman(usr)) + return TRUE + target = usr + + data["name"] = target.name + data["specimen"] = target.species.name + data["gender"] = target.gender + data["gender_id"] = target.identifying_gender + data["change_race"] = can_change(APPEARANCE_RACE) + if(data["change_race"]) + var/species[0] + for(var/specimen in valid_species) + species[++species.len] = list("specimen" = specimen) + data["species"] = species + + data["change_gender"] = can_change(APPEARANCE_GENDER) + if(data["change_gender"]) + var/genders[0] + for(var/gender in get_genders()) + genders[++genders.len] = list("gender_name" = gender2text(gender), "gender_key" = gender) + data["genders"] = genders + var/id_genders[0] + for(var/gender in all_genders_define_list) + id_genders[++id_genders.len] = list("gender_name" = gender2text(gender), "gender_key" = gender) + data["id_genders"] = id_genders + + data["change_hair"] = can_change(APPEARANCE_HAIR) + if(data["change_hair"]) + var/hair_styles[0] + for(var/hair_style in valid_hairstyles) + hair_styles[++hair_styles.len] = list("hairstyle" = hair_style) + data["hair_styles"] = hair_styles + data["hair_style"] = target.h_style + + data["change_facial_hair"] = can_change(APPEARANCE_FACIAL_HAIR) + if(data["change_facial_hair"]) + var/facial_hair_styles[0] + for(var/facial_hair_style in valid_facial_hairstyles) + facial_hair_styles[++facial_hair_styles.len] = list("facialhairstyle" = facial_hair_style) + data["facial_hair_styles"] = facial_hair_styles + data["facial_hair_style"] = target.f_style + + data["change_skin_tone"] = can_change_skin_tone() + data["change_skin_color"] = can_change_skin_color() + if(data["change_skin_color"]) + data["skin_color"] = rgb(target.r_skin, target.g_skin, target.b_skin) + data["change_eye_color"] = can_change(APPEARANCE_EYE_COLOR) + if(data["change_eye_color"]) + data["eye_color"] = rgb(target.r_eyes, target.g_eyes, target.b_eyes) + data["change_hair_color"] = can_change(APPEARANCE_HAIR_COLOR) + if(data["change_hair_color"]) + data["hair_color"] = rgb(target.r_hair, target.g_hair, target.b_hair) + data["change_facial_hair_color"] = can_change(APPEARANCE_FACIAL_HAIR_COLOR) + if(data["change_facial_hair_color"]) + data["facial_hair_color"] = rgb(target.r_facial, target.g_facial, target.b_facial) + return data + +/datum/tgui_module/appearance_changer/tgui_static_data(mob/user) + var/list/data = ..() + data["mapRef"] = map_name + return data + +/datum/tgui_module/appearance_changer/proc/differential_check() + var/turf/T = get_turf(customize_usr ? tgui_host() : owner) + if(T) + var/new_x = T.x + var/new_y = T.y + var/new_z = T.z + if((new_x != camera_diff_x) || (new_y != camera_diff_y) || (new_z != camera_diff_z)) + reload_cameraview() + +/datum/tgui_module/appearance_changer/proc/reload_cameraview() + var/turf/camTurf = get_turf(customize_usr ? tgui_host() : owner) + if(!camTurf) + return + + camera_diff_x = camTurf.x + camera_diff_y = camTurf.y + camera_diff_z = camTurf.z + + var/list/visible_turfs = list() + for(var/turf/T in range(1, camTurf)) + visible_turfs += T + + cam_screen.vis_contents = visible_turfs + cam_background.icon_state = "clear" + cam_background.fill_rect(1, 1, 3, 3) + + local_skybox.cut_overlays() + local_skybox.add_overlay(SSskybox.get_skybox(get_z(camTurf))) + local_skybox.scale_to_view(3) + local_skybox.set_position("CENTER", "CENTER", (world.maxx>>1) - camTurf.x, (world.maxy>>1) - camTurf.y) + +/datum/tgui_module/appearance_changer/proc/update_dna() + var/mob/living/carbon/human/target = owner + if(customize_usr) + if(!ishuman(usr)) + return TRUE + target = usr + + if(target && (flags & APPEARANCE_UPDATE_DNA)) + target.update_dna() + +/datum/tgui_module/appearance_changer/proc/can_change(var/flag) + var/mob/living/carbon/human/target = owner + if(customize_usr) + if(!ishuman(usr)) + return TRUE + target = usr + + return target && (flags & flag) + +/datum/tgui_module/appearance_changer/proc/can_change_skin_tone() + var/mob/living/carbon/human/target = owner + if(customize_usr) + if(!ishuman(usr)) + return TRUE + target = usr + + return target && (flags & APPEARANCE_SKIN) && target.species.appearance_flags & HAS_SKIN_TONE + +/datum/tgui_module/appearance_changer/proc/can_change_skin_color() + var/mob/living/carbon/human/target = owner + if(customize_usr) + if(!ishuman(usr)) + return TRUE + target = usr + + return target && (flags & APPEARANCE_SKIN) && target.species.appearance_flags & HAS_SKIN_COLOR + +/datum/tgui_module/appearance_changer/proc/cut_and_generate_data() + // Making the assumption that the available species remain constant + valid_facial_hairstyles.Cut() + valid_facial_hairstyles.Cut() + generate_data() + +/datum/tgui_module/appearance_changer/proc/generate_data() + var/mob/living/carbon/human/target = owner + if(customize_usr) + if(!ishuman(usr)) + return TRUE + target = usr + if(!target) + return + if(!valid_species.len) + valid_species = target.generate_valid_species(check_whitelist, whitelist, blacklist) + if(!valid_hairstyles.len || !valid_facial_hairstyles.len) + valid_hairstyles = target.generate_valid_hairstyles(check_gender = 0) + valid_facial_hairstyles = target.generate_valid_facial_hairstyles() + +/datum/tgui_module/appearance_changer/proc/get_genders() + var/mob/living/carbon/human/target = owner + if(customize_usr) + if(!ishuman(usr)) + return TRUE + target = usr + var/datum/species/S = target.species + var/list/possible_genders = S.genders + if(!target.internal_organs_by_name["cell"]) + return possible_genders + possible_genders = possible_genders.Copy() + possible_genders |= NEUTER + return possible_genders + +/datum/tgui_module/appearance_changer/mirror + name = "SalonPro Nano-Mirror™" + flags = APPEARANCE_ALL_HAIR + customize_usr = TRUE + +/datum/tgui_module/appearance_changer/mirror/coskit + name = "SalonPro Porta-Makeover Deluxe™" \ No newline at end of file diff --git a/code/modules/tgui/modules/camera.dm b/code/modules/tgui/modules/camera.dm index e1223fad74..d9ac311ee3 100644 --- a/code/modules/tgui/modules/camera.dm +++ b/code/modules/tgui/modules/camera.dm @@ -37,37 +37,7 @@ cam_screen.del_on_map_removal = FALSE cam_screen.screen_loc = "[map_name]:1,1" - cam_plane_masters = list() - - // 'Utility' planes - cam_plane_masters += new /obj/screen/plane_master/fullbright //Lighting system (lighting_overlay objects) - cam_plane_masters += new /obj/screen/plane_master/lighting //Lighting system (but different!) - cam_plane_masters += new /obj/screen/plane_master/ghosts //Ghosts! - cam_plane_masters += new /obj/screen/plane_master{plane = PLANE_AI_EYE} //AI Eye! - - cam_plane_masters += new /obj/screen/plane_master{plane = PLANE_CH_STATUS} //Status is the synth/human icon left side of medhuds - cam_plane_masters += new /obj/screen/plane_master{plane = PLANE_CH_HEALTH} //Health bar - cam_plane_masters += new /obj/screen/plane_master{plane = PLANE_CH_LIFE} //Alive-or-not icon - cam_plane_masters += new /obj/screen/plane_master{plane = PLANE_CH_ID} //Job ID icon - cam_plane_masters += new /obj/screen/plane_master{plane = PLANE_CH_WANTED} //Wanted status - cam_plane_masters += new /obj/screen/plane_master{plane = PLANE_CH_IMPLOYAL} //Loyalty implants - cam_plane_masters += new /obj/screen/plane_master{plane = PLANE_CH_IMPTRACK} //Tracking implants - cam_plane_masters += new /obj/screen/plane_master{plane = PLANE_CH_IMPCHEM} //Chemical implants - cam_plane_masters += new /obj/screen/plane_master{plane = PLANE_CH_SPECIAL} //"Special" role stuff - cam_plane_masters += new /obj/screen/plane_master{plane = PLANE_CH_STATUS_OOC} //OOC status HUD - - cam_plane_masters += new /obj/screen/plane_master{plane = PLANE_ADMIN1} //For admin use - cam_plane_masters += new /obj/screen/plane_master{plane = PLANE_ADMIN2} //For admin use - cam_plane_masters += new /obj/screen/plane_master{plane = PLANE_ADMIN3} //For admin use - - cam_plane_masters += new /obj/screen/plane_master{plane = PLANE_MESONS} //Meson-specific things like open ceilings. - cam_plane_masters += new /obj/screen/plane_master{plane = PLANE_BUILDMODE} //Things that only show up while in build mode - - // Real tangible stuff planes - cam_plane_masters += new /obj/screen/plane_master/main{plane = TURF_PLANE} - cam_plane_masters += new /obj/screen/plane_master/main{plane = OBJ_PLANE} - cam_plane_masters += new /obj/screen/plane_master/main{plane = MOB_PLANE} - cam_plane_masters += new /obj/screen/plane_master/cloaked //Cloaked atoms! + cam_plane_masters = get_plane_masters() for(var/plane in cam_plane_masters) var/obj/screen/instance = plane diff --git a/nano/templates/appearance_changer.tmpl b/nano/templates/appearance_changer.tmpl deleted file mode 100644 index 1111add5c5..0000000000 --- a/nano/templates/appearance_changer.tmpl +++ /dev/null @@ -1,86 +0,0 @@ -{{if data.change_race}} -