mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-11 10:43:20 +00:00
TGUI Appearance Editor (Mirrors & Admin)
This commit is contained in:
@@ -15,7 +15,7 @@
|
|||||||
spawn(3)
|
spawn(3)
|
||||||
var/mob/living/carbon/human/H = player.current
|
var/mob/living/carbon/human/H = player.current
|
||||||
if(istype(H))
|
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
|
return player.current
|
||||||
|
|
||||||
/datum/antagonist/proc/update_access(var/mob/living/player)
|
/datum/antagonist/proc/update_access(var/mob/living/player)
|
||||||
|
|||||||
@@ -96,17 +96,16 @@
|
|||||||
w_class = ITEMSIZE_TINY
|
w_class = ITEMSIZE_TINY
|
||||||
icon = 'icons/obj/items.dmi'
|
icon = 'icons/obj/items.dmi'
|
||||||
icon_state = "trinketbox"
|
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)
|
/obj/item/weapon/makeover/attack_self(mob/living/carbon/user as mob)
|
||||||
if(ishuman(user))
|
if(ishuman(user))
|
||||||
to_chat(user, "<span class='notice'>You flip open \the [src] and begin to adjust your appearance.</span>")
|
to_chat(user, "<span class='notice'>You flip open \the [src] and begin to adjust your appearance.</span>")
|
||||||
var/datum/nano_module/appearance_changer/AC = ui_users[user]
|
M.tgui_interact(user)
|
||||||
if(!AC)
|
|
||||||
AC = new(src, user)
|
|
||||||
AC.name = "SalonPro Porta-Makeover Deluxe™"
|
|
||||||
ui_users[user] = AC
|
|
||||||
AC.ui_interact(user)
|
|
||||||
var/mob/living/carbon/human/H = user
|
var/mob/living/carbon/human/H = user
|
||||||
var/obj/item/organ/internal/eyes/E = H.internal_organs_by_name[O_EYES]
|
var/obj/item/organ/internal/eyes/E = H.internal_organs_by_name[O_EYES]
|
||||||
if(istype(E))
|
if(istype(E))
|
||||||
|
|||||||
@@ -121,7 +121,7 @@
|
|||||||
H.adjustBruteLoss(rand(1,20))
|
H.adjustBruteLoss(rand(1,20))
|
||||||
|
|
||||||
if(allow_appearance_change)
|
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("<span class='aliem'>\The [src] [pick("gurgles", "seizes", "clangs")] before releasing \the [H]!</span>")
|
visible_message("<span class='aliem'>\The [src] [pick("gurgles", "seizes", "clangs")] before releasing \the [H]!</span>")
|
||||||
|
|
||||||
@@ -241,6 +241,6 @@
|
|||||||
H.adjustBruteLoss(rand(1,20))
|
H.adjustBruteLoss(rand(1,20))
|
||||||
|
|
||||||
if(allow_appearance_change)
|
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("<span class='aliem'>\The [src] [pick("gurgles", "seizes", "clangs")] before releasing \the [H]!</span>")
|
visible_message("<span class='aliem'>\The [src] [pick("gurgles", "seizes", "clangs")] before releasing \the [H]!</span>")
|
||||||
|
|||||||
@@ -7,10 +7,11 @@
|
|||||||
density = 0
|
density = 0
|
||||||
anchored = 1
|
anchored = 1
|
||||||
var/shattered = 0
|
var/shattered = 0
|
||||||
var/list/ui_users = list()
|
|
||||||
var/glass = 1
|
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)
|
/obj/structure/mirror/New(var/loc, var/dir, var/building = 0, mob/user as mob)
|
||||||
|
M = new(src, null)
|
||||||
if(building)
|
if(building)
|
||||||
glass = 0
|
glass = 0
|
||||||
icon_state = "mirror_frame"
|
icon_state = "mirror_frame"
|
||||||
@@ -18,17 +19,16 @@
|
|||||||
pixel_y = (dir & 3)? (dir == 1 ? -30 : 30) : 0
|
pixel_y = (dir & 3)? (dir == 1 ? -30 : 30) : 0
|
||||||
return
|
return
|
||||||
|
|
||||||
|
/obj/structure/mirror/Destroy()
|
||||||
|
QDEL_NULL(M)
|
||||||
|
. = ..()
|
||||||
|
|
||||||
/obj/structure/mirror/attack_hand(mob/user as mob)
|
/obj/structure/mirror/attack_hand(mob/user as mob)
|
||||||
if(!glass) return
|
if(!glass) return
|
||||||
if(shattered) return
|
if(shattered) return
|
||||||
|
|
||||||
if(ishuman(user))
|
if(ishuman(user))
|
||||||
var/datum/nano_module/appearance_changer/AC = ui_users[user]
|
M.tgui_interact(user)
|
||||||
if(!AC)
|
|
||||||
AC = new(src, user)
|
|
||||||
AC.name = "SalonPro Nano-Mirror™"
|
|
||||||
ui_users[user] = AC
|
|
||||||
AC.ui_interact(user)
|
|
||||||
|
|
||||||
/obj/structure/mirror/proc/shatter()
|
/obj/structure/mirror/proc/shatter()
|
||||||
if(!glass) return
|
if(!glass) return
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
if(!H) return
|
if(!H) return
|
||||||
|
|
||||||
log_and_message_admins("is altering the appearance of [H].")
|
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!
|
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()
|
/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"))
|
switch(alert("Do you wish for [H] to be allowed to select non-whitelisted races?","Alter Mob Appearance","Yes","No","Cancel"))
|
||||||
if("Yes")
|
if("Yes")
|
||||||
log_and_message_admins("has allowed [H] to change [T.his] appearance, without whitelisting of races.")
|
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")
|
if("No")
|
||||||
log_and_message_admins("has allowed [H] to change [T.his] appearance, with whitelisting of races.")
|
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!
|
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()
|
/client/proc/editappear()
|
||||||
|
|||||||
@@ -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)
|
/mob/living/carbon/human/proc/change_appearance(var/flags = APPEARANCE_ALL_HAIR,
|
||||||
var/datum/nano_module/appearance_changer/AC = new(location, src, check_species_whitelist, species_whitelist, species_blacklist)
|
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.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)
|
/mob/living/carbon/human/proc/change_species(var/new_species)
|
||||||
if(!new_species)
|
if(!new_species)
|
||||||
|
|||||||
@@ -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
|
|
||||||
@@ -26,6 +26,9 @@ Code is pretty much ripped verbatim from nano modules, but with un-needed stuff
|
|||||||
if(host)
|
if(host)
|
||||||
host.tgui_close(user)
|
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)
|
/datum/tgui_module/proc/check_access(mob/user, access)
|
||||||
if(!access)
|
if(!access)
|
||||||
return 1
|
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)
|
ui = SStgui.try_update_ui(user, src, ui)
|
||||||
if(!ui)
|
if(!ui)
|
||||||
ui = new(user, src, tgui_id, name)
|
ui = new(user, src, tgui_id, name)
|
||||||
ui.open()
|
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!
|
||||||
358
code/modules/tgui/modules/appearance_changer.dm
Normal file
358
code/modules/tgui/modules/appearance_changer.dm
Normal file
@@ -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™"
|
||||||
@@ -37,37 +37,7 @@
|
|||||||
cam_screen.del_on_map_removal = FALSE
|
cam_screen.del_on_map_removal = FALSE
|
||||||
cam_screen.screen_loc = "[map_name]:1,1"
|
cam_screen.screen_loc = "[map_name]:1,1"
|
||||||
|
|
||||||
cam_plane_masters = list()
|
cam_plane_masters = get_plane_masters()
|
||||||
|
|
||||||
// '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!
|
|
||||||
|
|
||||||
for(var/plane in cam_plane_masters)
|
for(var/plane in cam_plane_masters)
|
||||||
var/obj/screen/instance = plane
|
var/obj/screen/instance = plane
|
||||||
|
|||||||
@@ -1,86 +0,0 @@
|
|||||||
{{if data.change_race}}
|
|
||||||
<div class="item">
|
|
||||||
<div class="itemLabelNarrow">
|
|
||||||
Species:
|
|
||||||
</div>
|
|
||||||
<div class="itemContentWide">
|
|
||||||
{{for data.species}}
|
|
||||||
{{:helper.link(value.specimen, null, { 'race' : value.specimen}, null, data.specimen == value.specimen ? 'selected' : null)}}
|
|
||||||
{{/for}}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{{/if}}
|
|
||||||
|
|
||||||
{{if data.change_gender}}
|
|
||||||
<div class="item">
|
|
||||||
<div class="itemLabelNarrow">
|
|
||||||
Biological Gender:
|
|
||||||
</div>
|
|
||||||
<div class="itemContentWide">
|
|
||||||
{{for data.genders}}
|
|
||||||
{{:helper.link(value.gender_name, null, { 'gender' : value.gender_key}, null, data.gender == value.gender_key ? 'selected' : null)}}
|
|
||||||
{{/for}}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="item">
|
|
||||||
<div class="itemLabelNarrow">
|
|
||||||
Gender Identity:
|
|
||||||
</div>
|
|
||||||
<div class="itemContentWide">
|
|
||||||
{{for data.id_genders}}
|
|
||||||
{{:helper.link(value.gender_name, null, { 'gender_id' : value.gender_key}, null, data.gender_id == value.gender_key ? 'selected' : null)}}
|
|
||||||
{{/for}}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{{/if}}
|
|
||||||
|
|
||||||
{{if data.change_eye_color || data.change_skin_tone || data.change_skin_color || data.change_hair_color || data.change_facial_hair_color}}
|
|
||||||
<div class="item">
|
|
||||||
<div class="itemLabelNarrow">
|
|
||||||
Colors:
|
|
||||||
</div>
|
|
||||||
<div class="itemContentWide">
|
|
||||||
{{if data.change_eye_color}}
|
|
||||||
{{:helper.link('Change eye color', null, { 'eye_color' : 1})}}
|
|
||||||
{{/if}}
|
|
||||||
{{if data.change_skin_tone}}
|
|
||||||
{{:helper.link('Change skin tone', null, { 'skin_tone' : 1})}}
|
|
||||||
{{/if}}
|
|
||||||
{{if data.change_skin_color}}
|
|
||||||
{{:helper.link('Change skin color', null, { 'skin_color' : 1})}}
|
|
||||||
{{/if}}
|
|
||||||
{{if data.change_hair_color}}
|
|
||||||
{{:helper.link('Change hair color', null, { 'hair_color' : 1})}}
|
|
||||||
{{/if}}
|
|
||||||
{{if data.change_facial_hair_color}}
|
|
||||||
{{:helper.link('Change facial hair color', null, { 'facial_hair_color' : 1})}}
|
|
||||||
{{/if}}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{{/if}}
|
|
||||||
|
|
||||||
{{if data.change_hair}}
|
|
||||||
<div class="item">
|
|
||||||
<div class="itemLabelNarrow">
|
|
||||||
Hair styles:
|
|
||||||
</div>
|
|
||||||
<div class="itemContentWide">
|
|
||||||
{{for data.hair_styles}}
|
|
||||||
{{:helper.link(value.hairstyle, null, { 'hair' : value.hairstyle}, null, data.hair_style == value.hairstyle ? 'selected' : null)}}
|
|
||||||
{{/for}}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{{/if}}
|
|
||||||
|
|
||||||
{{if data.change_facial_hair}}
|
|
||||||
<div class="item">
|
|
||||||
<div class="itemLabelNarrow">
|
|
||||||
Facial hair styles:
|
|
||||||
</div>
|
|
||||||
<div class="itemContentWide">
|
|
||||||
{{for data.facial_hair_styles}}
|
|
||||||
{{:helper.link(value.facialhairstyle, null, { 'facial_hair' : value.facialhairstyle}, null, data.facial_hair_style == value.facialhairstyle ? 'selected' : null)}}
|
|
||||||
{{/for}}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{{/if}}
|
|
||||||
@@ -120,7 +120,7 @@ export const decodeHtmlEntities = str => {
|
|||||||
if (!str) {
|
if (!str) {
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
const translate_re = /&(nbsp|amp|quot|lt|gt|apos);/g;
|
const translate_re = /&(nbsp|amp|quot|lt|gt|apos|trade);/g;
|
||||||
const translate = {
|
const translate = {
|
||||||
nbsp: ' ',
|
nbsp: ' ',
|
||||||
amp: '&',
|
amp: '&',
|
||||||
@@ -128,6 +128,7 @@ export const decodeHtmlEntities = str => {
|
|||||||
lt: '<',
|
lt: '<',
|
||||||
gt: '>',
|
gt: '>',
|
||||||
apos: '\'',
|
apos: '\'',
|
||||||
|
trade: '™',
|
||||||
};
|
};
|
||||||
return str
|
return str
|
||||||
// Newline tags
|
// Newline tags
|
||||||
|
|||||||
292
tgui/packages/tgui/interfaces/AppearanceChanger.js
Normal file
292
tgui/packages/tgui/interfaces/AppearanceChanger.js
Normal file
@@ -0,0 +1,292 @@
|
|||||||
|
import { filter, sortBy } from 'common/collections';
|
||||||
|
import { capitalize, decodeHtmlEntities } from 'common/string';
|
||||||
|
import { Fragment } from 'inferno';
|
||||||
|
import { useBackend, useLocalState } from "../backend";
|
||||||
|
import { Box, Button, ByondUi, Flex, Icon, LabeledList, ProgressBar, Section, Tabs, ColorBox } from "../components";
|
||||||
|
import { Window } from "../layouts";
|
||||||
|
|
||||||
|
export const AppearanceChanger = (props, context) => {
|
||||||
|
const { act, config, data } = useBackend(context);
|
||||||
|
|
||||||
|
const {
|
||||||
|
name,
|
||||||
|
specimen,
|
||||||
|
gender,
|
||||||
|
gender_id,
|
||||||
|
hair_style,
|
||||||
|
facial_hair_style,
|
||||||
|
change_race,
|
||||||
|
change_gender,
|
||||||
|
change_eye_color,
|
||||||
|
change_skin_tone,
|
||||||
|
change_skin_color,
|
||||||
|
change_hair_color,
|
||||||
|
change_facial_hair_color,
|
||||||
|
change_hair,
|
||||||
|
change_facial_hair,
|
||||||
|
mapRef,
|
||||||
|
} = data;
|
||||||
|
|
||||||
|
const {
|
||||||
|
title,
|
||||||
|
} = config;
|
||||||
|
|
||||||
|
const change_color = change_eye_color
|
||||||
|
|| change_skin_tone
|
||||||
|
|| change_skin_color
|
||||||
|
|| change_hair_color
|
||||||
|
|| change_facial_hair_color;
|
||||||
|
|
||||||
|
let firstAccesibleTab = -1;
|
||||||
|
if (change_race) {
|
||||||
|
firstAccesibleTab = 0;
|
||||||
|
} else if (change_gender) {
|
||||||
|
firstAccesibleTab = 1;
|
||||||
|
} else if (change_color) {
|
||||||
|
firstAccesibleTab = 2;
|
||||||
|
} else if (change_hair) {
|
||||||
|
firstAccesibleTab = 4;
|
||||||
|
} else if (change_facial_hair) {
|
||||||
|
firstAccesibleTab = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
const [tabIndex, setTabIndex] = useLocalState(context, 'tabIndex', firstAccesibleTab);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Window width={700} height={650} title={decodeHtmlEntities(title)}>
|
||||||
|
<Window.Content>
|
||||||
|
<Section title="Reflection">
|
||||||
|
<Flex>
|
||||||
|
<Flex.Item grow={1}>
|
||||||
|
<LabeledList>
|
||||||
|
<LabeledList.Item label="Name">
|
||||||
|
{name}
|
||||||
|
</LabeledList.Item>
|
||||||
|
<LabeledList.Item label="Species" color={!change_race ? "grey" : null}>
|
||||||
|
{specimen}
|
||||||
|
</LabeledList.Item>
|
||||||
|
<LabeledList.Item label="Biological Sex" color={!change_gender ? "grey" : null}>
|
||||||
|
{capitalize(gender)}
|
||||||
|
</LabeledList.Item>
|
||||||
|
<LabeledList.Item label="Gender Identity" color={!change_color ? "grey" : null}>
|
||||||
|
{capitalize(gender_id)}
|
||||||
|
</LabeledList.Item>
|
||||||
|
<LabeledList.Item label="Hair Style" color={!change_hair ? "grey" : null}>
|
||||||
|
{capitalize(hair_style)}
|
||||||
|
</LabeledList.Item>
|
||||||
|
<LabeledList.Item label="Facial Hair Style" color={!change_facial_hair ? "grey" : null}>
|
||||||
|
{capitalize(facial_hair_style)}
|
||||||
|
</LabeledList.Item>
|
||||||
|
</LabeledList>
|
||||||
|
</Flex.Item>
|
||||||
|
<Flex.Item>
|
||||||
|
<ByondUi
|
||||||
|
style={{
|
||||||
|
width: '256px',
|
||||||
|
height: '256px',
|
||||||
|
}}
|
||||||
|
params={{
|
||||||
|
id: mapRef,
|
||||||
|
type: 'map',
|
||||||
|
}} />
|
||||||
|
</Flex.Item>
|
||||||
|
</Flex>
|
||||||
|
</Section>
|
||||||
|
<Tabs>
|
||||||
|
{change_race ? (
|
||||||
|
<Tabs.Tab
|
||||||
|
selected={tabIndex === 0}
|
||||||
|
onClick={() => setTabIndex(0)}>
|
||||||
|
Race
|
||||||
|
</Tabs.Tab>
|
||||||
|
) : null}
|
||||||
|
{change_gender ? (
|
||||||
|
<Tabs.Tab
|
||||||
|
selected={tabIndex === 1}
|
||||||
|
onClick={() => setTabIndex(1)}>
|
||||||
|
Gender & Sex
|
||||||
|
</Tabs.Tab>
|
||||||
|
) : null}
|
||||||
|
{change_color ? (
|
||||||
|
<Tabs.Tab
|
||||||
|
selected={tabIndex === 2}
|
||||||
|
onClick={() => setTabIndex(2)}>
|
||||||
|
Colors
|
||||||
|
</Tabs.Tab>
|
||||||
|
) : null}
|
||||||
|
{change_hair ? (
|
||||||
|
<Tabs.Tab
|
||||||
|
selected={tabIndex === 3}
|
||||||
|
onClick={() => setTabIndex(3)}>
|
||||||
|
Hair
|
||||||
|
</Tabs.Tab>
|
||||||
|
) : null}
|
||||||
|
{change_facial_hair ? (
|
||||||
|
<Tabs.Tab
|
||||||
|
selected={tabIndex === 4}
|
||||||
|
onClick={() => setTabIndex(4)}>
|
||||||
|
Facial Hair
|
||||||
|
</Tabs.Tab>
|
||||||
|
) : null}
|
||||||
|
</Tabs>
|
||||||
|
<Box height="43%">
|
||||||
|
{(change_race && tabIndex === 0) ? <AppearanceChangerSpecies /> : null}
|
||||||
|
{(change_gender && tabIndex === 1) ? <AppearanceChangerGender /> : null}
|
||||||
|
{(change_color && tabIndex === 2) ? <AppearanceChangerColors /> : null}
|
||||||
|
{(change_hair && tabIndex === 3) ? <AppearanceChangerHair /> : null}
|
||||||
|
{(change_facial_hair && tabIndex === 4) ? <AppearanceChangerFacialHair /> : null}
|
||||||
|
</Box>
|
||||||
|
</Window.Content>
|
||||||
|
</Window>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const AppearanceChangerSpecies = (props, context) => {
|
||||||
|
const { act, data } = useBackend(context);
|
||||||
|
const {
|
||||||
|
species,
|
||||||
|
specimen,
|
||||||
|
} = data;
|
||||||
|
|
||||||
|
const sortedSpecies = sortBy(val => val.specimen)(species || []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Section title="Species" fill scrollable>
|
||||||
|
{sortedSpecies.map(spec => (
|
||||||
|
<Button
|
||||||
|
key={spec.specimen}
|
||||||
|
content={spec.specimen}
|
||||||
|
selected={specimen === spec.specimen}
|
||||||
|
onClick={() => act("race", { race: spec.specimen })} />
|
||||||
|
))}
|
||||||
|
</Section>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const AppearanceChangerGender = (props, context) => {
|
||||||
|
const { act, data } = useBackend(context);
|
||||||
|
|
||||||
|
const {
|
||||||
|
gender,
|
||||||
|
gender_id,
|
||||||
|
genders,
|
||||||
|
id_genders,
|
||||||
|
} = data;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Section title="Gender & Sex" fill scrollable>
|
||||||
|
<LabeledList>
|
||||||
|
<LabeledList.Item label="Biological Sex">
|
||||||
|
{genders.map(g => (
|
||||||
|
<Button
|
||||||
|
key={g.gender_key}
|
||||||
|
selected={g.gender_key === gender}
|
||||||
|
content={g.gender_name}
|
||||||
|
onClick={() => act("gender", { "gender": g.gender_key })} />
|
||||||
|
))}
|
||||||
|
</LabeledList.Item>
|
||||||
|
<LabeledList.Item label="Gender Identity">
|
||||||
|
{id_genders.map(g => (
|
||||||
|
<Button
|
||||||
|
key={g.gender_key}
|
||||||
|
selected={g.gender_key === gender_id}
|
||||||
|
content={g.gender_name}
|
||||||
|
onClick={() => act("gender_id", { "gender_id": g.gender_key })} />
|
||||||
|
))}
|
||||||
|
</LabeledList.Item>
|
||||||
|
</LabeledList>
|
||||||
|
</Section>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const AppearanceChangerColors = (props, context) => {
|
||||||
|
const { act, data } = useBackend(context);
|
||||||
|
|
||||||
|
const {
|
||||||
|
change_eye_color,
|
||||||
|
change_skin_tone,
|
||||||
|
change_skin_color,
|
||||||
|
change_hair_color,
|
||||||
|
change_facial_hair_color,
|
||||||
|
eye_color,
|
||||||
|
skin_color,
|
||||||
|
hair_color,
|
||||||
|
facial_hair_color,
|
||||||
|
} = data;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Section title="Colors" fill scrollable>
|
||||||
|
{change_eye_color ? (
|
||||||
|
<Box>
|
||||||
|
<ColorBox color={eye_color} mr={1} />
|
||||||
|
<Button content="Change Eye Color" onClick={() => act("eye_color")} />
|
||||||
|
</Box>
|
||||||
|
) : null}
|
||||||
|
{change_skin_tone ? (
|
||||||
|
<Box>
|
||||||
|
<Button content="Change Skin Tone" onClick={() => act("skin_tone")} />
|
||||||
|
</Box>
|
||||||
|
) : null}
|
||||||
|
{change_skin_color ? (
|
||||||
|
<Box>
|
||||||
|
<ColorBox color={skin_color} mr={1} />
|
||||||
|
<Button content="Change Skin Color" onClick={() => act("skin_color")} />
|
||||||
|
</Box>
|
||||||
|
) : null}
|
||||||
|
{change_hair_color ? (
|
||||||
|
<Box>
|
||||||
|
<ColorBox color={hair_color} mr={1} />
|
||||||
|
<Button content="Change Hair Color" onClick={() => act("hair_color")} />
|
||||||
|
</Box>
|
||||||
|
) : null}
|
||||||
|
{change_facial_hair_color ? (
|
||||||
|
<Box>
|
||||||
|
<ColorBox color={facial_hair_color} mr={1} />
|
||||||
|
<Button content="Change Facial Hair Color" onClick={() => act("facial_hair_color")} />
|
||||||
|
</Box>
|
||||||
|
) : null}
|
||||||
|
</Section>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const AppearanceChangerHair = (props, context) => {
|
||||||
|
const { act, data } = useBackend(context);
|
||||||
|
|
||||||
|
const {
|
||||||
|
hair_style,
|
||||||
|
hair_styles,
|
||||||
|
} = data;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Section title="Hair" fill scrollable>
|
||||||
|
{hair_styles.map(hair => (
|
||||||
|
<Button
|
||||||
|
key={hair.hairstyle}
|
||||||
|
onClick={() => act("hair", { hair: hair.hairstyle })}
|
||||||
|
selected={hair.hairstyle === hair_style}
|
||||||
|
content={hair.hairstyle} />
|
||||||
|
))}
|
||||||
|
</Section>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const AppearanceChangerFacialHair = (props, context) => {
|
||||||
|
const { act, data } = useBackend(context);
|
||||||
|
|
||||||
|
const {
|
||||||
|
facial_hair_style,
|
||||||
|
facial_hair_styles,
|
||||||
|
} = data;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Section title="Facial Hair" fill scrollable>
|
||||||
|
{facial_hair_styles.map(hair => (
|
||||||
|
<Button
|
||||||
|
key={hair.facialhairstyle}
|
||||||
|
onClick={() => act("facial_hair", { facial_hair: hair.facialhairstyle })}
|
||||||
|
selected={hair.facialhairstyle === facial_hair_style}
|
||||||
|
content={hair.facialhairstyle} />
|
||||||
|
))}
|
||||||
|
</Section>
|
||||||
|
);
|
||||||
|
};
|
||||||
File diff suppressed because one or more lines are too long
@@ -2945,7 +2945,6 @@
|
|||||||
#include "code\modules\nano\interaction\remote.dm"
|
#include "code\modules\nano\interaction\remote.dm"
|
||||||
#include "code\modules\nano\interaction\self.dm"
|
#include "code\modules\nano\interaction\self.dm"
|
||||||
#include "code\modules\nano\interaction\zlevel.dm"
|
#include "code\modules\nano\interaction\zlevel.dm"
|
||||||
#include "code\modules\nano\modules\human_appearance.dm"
|
|
||||||
#include "code\modules\nano\modules\law_manager.dm"
|
#include "code\modules\nano\modules\law_manager.dm"
|
||||||
#include "code\modules\nano\modules\nano_module.dm"
|
#include "code\modules\nano\modules\nano_module.dm"
|
||||||
#include "code\modules\nifsoft\nif.dm"
|
#include "code\modules\nifsoft\nif.dm"
|
||||||
@@ -3491,6 +3490,7 @@
|
|||||||
#include "code\modules\tgui\tgui.dm"
|
#include "code\modules\tgui\tgui.dm"
|
||||||
#include "code\modules\tgui\tgui_window.dm"
|
#include "code\modules\tgui\tgui_window.dm"
|
||||||
#include "code\modules\tgui\modules\_base.dm"
|
#include "code\modules\tgui\modules\_base.dm"
|
||||||
|
#include "code\modules\tgui\modules\appearance_changer.dm"
|
||||||
#include "code\modules\tgui\modules\camera.dm"
|
#include "code\modules\tgui\modules\camera.dm"
|
||||||
#include "code\modules\tgui\modules\crew_monitor.dm"
|
#include "code\modules\tgui\modules\crew_monitor.dm"
|
||||||
#include "code\modules\tgui\states\admin.dm"
|
#include "code\modules\tgui\states\admin.dm"
|
||||||
|
|||||||
Reference in New Issue
Block a user